This use case demonstrates the usage of the proposed introspection capability
to convert a complex data structure (nested records and arrays) to a user defined
string. The string obeys to the data format rules of JSON (
JavaScript Object Notation)
Sources:
- RFC 4627 - The application/json Media Type for JavaScript Object Notation (JSON)
- ECMA-262 - ECMAScript 2015 Language Specification
- ECMA-404 - The JSON Data interchange Format
JSON Overview
Here is a simple JSON example:
[
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]
JSON supports the following data types and literals:
- boolean values:
- empty value:
- string literals enclosed in double quotes
- integer consecutive decimal digits with an optional minus sign as prefix
- floating point numbers in common float formatting <sign><integer part>"."<fractional part>"e"<exp sign><exponent>
- list enclosed in brackets and seperated by comas
- "[" elem1 "," elem2 "," ... "]"
- associative array (dictionary, hash table) key-value-pais enclosed in braces and seperated by comas
- key-value-pairs (allowed only in dictionaries) are string keys seperated by a colon from a value
Element's data types in lists and dictionaries can be mixed.
The Use Case
I'll use an example from the non-public part of the
PoC-Library, so it's a real-life example. Our
Serial-ATA controller follows the layered architecture defined by the standard. Each layer has four
FIFO based streaming ports (TX in/out and RX in/out) and instantiates several data processing modules
in the data flow and one FSM to control and monitor the layer and/or implement the protocol state
machine defined in the standard. An upper layer controls and monitors a lower layer using a so called
Command-Status-Error interface (CSE). The CSE interface uses 3 enumerated type.
type T_Command is (
CMD_NONE,
CMD_WRITE_DMA,
CMD_READ_DMA
-- ...
);
type T_Status is (
STATUS_RESETING,
STATUS_IDLE,
STATUS_WRITING,
STATUS_WRITE_COMPLETE,
-- ...
STATUS_ERROR
);
type T_Error is (
ERROR_NONE,
ERROR_PROTOCOL,
ERROR_FIFO_OVERFLOW,
ERROR_CRC
-- ...
);
If a Status signal is set to STATUS_ERROR, then the Error signal is valid.
Let's look into the 4 main layers:
-
StreamingLayer
-> generated ATA commands
-
TransportLayer
-> pack ATA register for a transfers
-
LinkLayer
-> frame based data transfer incl. flow control
-
PhysicalLayer
-> serialization, line encoding, ...
The CSE signals of all layers are made available through a
DebugPort to the testbench. So a testbench can
monitor all Status or Error signals of every layer and all exchanged commands between the layers. In addition
the FIFO interfaces (to the upper layer) are added too, for monitoring in a on-chip logic analyzer. The FIFO
interface to the lower layer is not monitored, because it's available through the lower layer.
So let's define records to combine all signals:
type T_FIFO_In is record
Put : std_logic;
Data : std_logic_vector(31 downto 0);
Full : std_logic;
end record;
type T_FIFO_Out is record
got : std_logic;
Data : std_logic_vector(31 downto 0);
Valid : std_logic;
end record;
type T_StreamLayer is record
Command : T_Stream_Command;
Status : T_Stream_Status;
Error : T_Stream_Error;
TX : T_FIFO_In;
RX : T_FIFO_Out;
end record;
type T_TransLayer is record
Command : T_Trans_Command;
Status : T_Trans_Status;
Error : T_Trans_Error;
TX : T_FIFO_In;
RX : T_FIFO_Out;
end record;
type T_LinkLayer is record
Command : T_Link_Command;
Status : T_Link_Status;
Error : T_Link_Error;
TX : T_FIFO_In;
RX : T_FIFO_Out;
end record;
type T_PhyLayer is record
Command : T_Phy_Command;
Status : T_Phy_Status;
Error : T_Phy_Error;
TX : T_FIFO_In;
RX : T_FIFO_Out;
end record;
type T_DebugPort is record
StreamingLayer : T_StreamLayer;
TransportLayer : T_TransLayer;
LinkLayer : T_LinkLayer;
PhysicalLayer : T_PhyLayer;
end record;
Let's assume a testbench, which wants to report the overall state of all signals in the
DebugPortwhen an error occurred.
ErrorIndicator <= '1' when ((DebugPort.StreamingLayer.Status = STATUS_ERROR) or
(DebugPort.TransportLayer.Status = STATUS_ERROR) or
(DebugPort.LinkLayer.Status = STATUS_ERROR) or
(DebugPort.PhysicalLayer.Status = STATUS_ERROR)) else
'0';
process(DebugPort, ErrorIndicator)
-- under construction
begin
-- under construction
end process;
--
Patrick Lehmann - 2016-03-09
Comments