SCP protocol
This section describes the chosen and implemented SCP protocol for the frames sent and received to/from the Verisocks server TCP socket by any client that wishes to connect to it.
Note
A reference Python client implementation can be found in the Verisocks github repository.
A plethora of tools and languages on many platforms support socket programming with convenient built-in libraries and methods (C, Ruby, Perl, Tcl, Labview, Matlab, Java, etc.). Any could be used to implement a client that could connect to the Verisocks server.
Frames format
Note
The SCP message format follows the proposal for a message format in the RealPython’s guide on sockets programming. It allows to deal easily with variable-length messages while making sure that it is possible to verify that the full message has been received and that it is not overlapping with the next message. Moreover, while it is not really foreseen at this time to be used in this project, it also allows to cope with the transmission of binary data.
The chosen frame format contains in order:
Fixed-length pre-header: Indicates the length in bytes of the following variable-length header.
Type: Integer value
Encoding: Big endian byte ordering (most significant byte sent first)
Length: 2 bytes – This limits the size of the following variable-length header to a maximum of 65535 bytes. This is more than enough…
Variable-length header: Gives information on the message payload’s content.
Type: Unicode text, JSON format
Encoding: UTF-8
Length: As specified by the pre-header integer value
Content: Follows partially RFC 9110 (HTTP semantics); only the following fields are being used:
content-type: Type of content for the variable-length payload. For Verisocks current implementation, only application/json is currently supported.
content-encoding: Encoding for the variable-length payload. OnlyUTF-8currently supported (supporting encodings other than system’s default is a nightmare with the GNU standard C library).
content-length: Length in bytes of the variable-length payload.
uuid(optional): Unique identifier for the transaction, following RFC 4122 (UUID). This field can be used by clients to match requests and responses. This field shall be a field formatted with the RFC’s specified URN format (see example below).For example, the following constitutes a valid Verisocks header (assuming that the following payload is indeed 110-byte long):
{ "content-type": "application/json", "content-encoding": "UTF-8", "content-length": 110, "uuid": "8aca5d03-3120-410c-8909-080bed5e9c2f" }
Variable-length payload
Type: As specified in the header’s
content-typefield.Encoding: As specified in the header’s
content-encodingfield.Length: As specified in the header’s
content-lengthfield.Content: At the moment, the only supported content correspond to a
request (or command) from the client to the Verisocks server, respectively a response (or return message) from the Verisocks server to the client, formatted as a JSON object.
Full message example
As an example of a valid Verisocks full message, you can consider the following (taken from the SPI master example provided in the verisocks github repository):
Pre-header: value 88, first byte =
0x00, second byte =0x58Header:
{ "content-type": "application/json", "content-encoding": "utf-8", "content-length": 110 }
Payload:
{ "command": "set", "path": "spi_master_tb.i_spi_master.tx_buffer", "value": [132, 201, 31, 71, 178, 192, 137] }
Commands
Commands are messages sent from a client to the Verisocks server intending to trigger specific actions for the simulator or the server. The supported commands are exhaustively listed below.
Information frame (info)
Provides an arbitary information text from the client to the server. This arbitrary text is then printed out to the VPI standard output.
JSON payload fields:
"command": "info""value":Arbitrary text content to be printed out to VPI stdout
Returned frame (normal case):
"type": "ack"(acknowledgement)"value": "command info received"
With the provided Python client reference implementation, the method
Verisocks.info()
corresponds to this command.
Finish simulation (finish)
Finishes the simulation (equivalent to a verilog $finish()
statement). This will also result in the simulator process being terminated as
well as the Verisocks server. The socket used will also be closed. After this
command, the execution focus goes to
Verisocks.
JSON payload fields:
"command": "finish"
Returned frame (normal case):
"type": "ack"(acknowledgement)"value": "Processing finish command - Terminating simulation."
With the provided Python client reference implementation, the method
Verisocks.finish()
corresponds to this command.
Stop simulation (stop)
Stops the simulation (equivalent to the verilog $stop() statement).
Contrary to the finish command, the socket is not
closed. After this command, the execution focus
goes to Verisocks.
JSON payload fields:
"command": "stop"
Returned frame (normal case):
"type": "ack"(acknowledgement)"value": "Processing stop command - Stopping simulation."
With the provided Python client reference implementation, the method
Verisocks.stop()
corresponds to this command.
Exit (exit)
Exits Verisocks and closes the socket. After this command, the execution focus goes to the simulator and the simulation continues its course until it ends.
JSON payload fields:
"command": "exit"
Returned frame (normal case):
"type": "ack"(acknowledgement)"value": "Processing exit command - Quitting Verisocks."
With the provided Python client reference implementation, the method
Verisocks.exit()
corresponds to this command.
Run simulation (run)
Transfers the execution focus to the simulator and runs it until a callback event which is specified by the command arguments (see description below). After the callback is reached, the focus gets back to Verisocks.
JSON payload fields:
"command": "run"Command nameA callback needs to be defined in order to specify when the run command has to yield the execution focus back to Verisocks. The different available possibilities are:
"cb": "for_time"- The simulation shall run for a certain amount of time,"cb": "until_time"- The simulation shall run until a certain (simulator) time,"cb": "until_change"- The simulation shall run until a certain simulator variable changes to any new value or to a specific value,"cb": "to_next"- The simulation shall run until the next simulation time step.
If the
"cb"field is"for_time"or"until_time", the following fields are further expected in the command frame:"time":(number): Time value (either as a time difference or as an absolute simulation time). For example"time": 3.2"time_unit":(text): Time unit ("s","ms","us","ns","ps"or"fs") which applies to the"time"field value. Be aware that depending on the simulator time resolution, the provided time value can be truncated.
If the
"cb"field is"until_change", the following fields are further expected in the command frame:"path":(text): Path to the simulation variable used for the callback"value":(number): Condition on the simulation variable’s value for the callback to be executed. If this argument is missing, the callback shall be executed as soon as the value of the object changes to any newer value. This argument is also not required if the path corresponds to a named event."sim_timeout":(number, optional): Time duration defining a timeout. If the timeout duration expires before the defined condition is met, the simulation pauses and a timeout message is returned."time_unit":(text): Time unit which applies to the"sim_timeout"field value. See the possible values above.
If the
"cb"field is"to_next", no further fields are required.Returned frame (normal case):
"type": "ack"(acknowledgement)"value": "Reached callback - Getting back to Verisocks main loop"
With the provided Python client reference implementation, the method
Verisocks.run()
corresponds to this command.
Get information from simulation (get)
This command can be used to get pieces of information from the simulator.
JSON payload fields:
"command": "get"Command nameIt is possible to select which shall be the returned information, using the following possibilities:
"sel": "sim_info"- The simulator information (name and version) is returned,"sel": "sim_time"- The simulator (absolute) time is returned,"sel": "value"- The value of a simulator variable is returned,"sel": "type"- The VPI type of a simulator variable is returned."sel": "variables"- The list of registered variables is returned (Verilator integration only)"sel": "clocks"- The list of registered clocks is returned (Verilator integration only)
If the
"sel"field is"value"or"type", the following field is required in the command frame:"path":(text): Path to the simulation variable
For the
"path":field, selecting only a specific index of an array is also possible by using the[]operator, e.g."<path_to_array>[4]". The Verilator integration API even supports sub-ranges, such as e.g."<path_to_array>[6:3]"or"<path_to_array>[3:6]".Returned frame (for
"sel": "sim_info"):"type": "result""product":(text): Simulator product name"version":(text): Simulator version"verisocks_version":(text): Verisocks version"time_unit":(text): Simulator time unit"time_precision":(text): Simulator time precision
The Verilator integration API version of Verisocks further includes the following fields:
"model_name":(text): Model name"model_hier_name":(text): Model top instance name"user_info":(text): Free user-defined text
Returned frame (for
"sel": "sim_time"):"type": "result""time":(number): Simulator absolute time, in seconds
Returned frame (for
"sel": "value"):"type": "result""value":(number or array): Value for the queried variable.
Returned frame (for
"sel": "type"):"type": "result""vpi_type":(number): Value for the queried variable’s VPI type (see VPI objects types definitions in IEEE 1364-2001)
Note that this selection value is currently not supported by the Verilator integration API version of Verisocks. A warning message will be returned.
Returned frame (for
"sel": "variables"):"type": "result""value":(array): List of publicly available variables (Verilator integration only)
Returned frame (for
"sel": "clocks"):"type": "result""value":(array): List of regitstered, available clocks, including period, duty cycle and enabled flag status (Verilator integration only)
With the provided Python client reference implementation, the method
Verisocks.get()
corresponds to this command.
Set variables in simulation (set)
This command can be used to forcefully set the value of a simulator variable.
JSON payload fields:
"command": "set"Command name"sel":(text): Sub-command selector. This field is optional to ensure back-compatibility with previous versions of the protocol. If it is not provided, the command set will behave as"sel": "value". The following values are possible:"sel": "value"(default) - A signal value is set,"sel": "clk_en"- A clock signal is enabled or disabled (only supported with Verilator integration API),"sel": "clk_cfg"- A clock signal is configured (only supported with Verilator integration API) by specifying its period duration and duty cycle.
Independently of the value for the field
"sel", the"path"field has to be provided as follows:"path":(text): Path to the simulator variable to be setSelecting only a specific index of an array is also possible by using the
[]operator, e.g."<path_to_array>[4]". The Verilator integration API even supports sub-ranges, such as e.g."<path_to_array>[6:3]"or"<path_to_array>[3:6]".
For
"sel": "value", the field"value"shall be defined as follows:"value":(number or array): Value to be set. If the path corresponds to a verilog named event, this argument is not required. If the path corresponds to a memory array, this argument needs to be provided as an array of the same length.
For
"sel": "clk_en", the field"value"shall also be defined as follows:"value":(number): The value of this number defines if the concerned clock signal is enabled (if > 0) or disabled (otherwise).
For
"sel": "clk_cfg", the fields"period","unit"and"dc"shall be defined as follows:"period":(number): Period duration,"unit":(text): Time unit ("s","ms","us","ns","ps"or"fs") which applies to the"period"field value,"dc":(number): Duty cycle (shall be strictly larger than 0.0 and strictly smaller than 1.0).
Returned frame (normal case):
"type": "ack"(acknowledgement)"value": "Processed command set"
With the provided Python client reference implementation, the method
Verisocks.set()
corresponds to this command.
Returned messages
As documented in the section Commands, each command shall have its own return message with a specific, expected content in case of normal execution of the command. All return messages are expected to contain at least the following field:
"type":(text): Specifies which is the type of the returned message. It can be either:
"ack"(the returned message is an acknowledgement), which confirms the good execution of a command that is not expected to return a specific result
"result"(the returned message provides a result)
"error"(the returned message signals an error)
"timeout"(the returned message signals a timeout)
Other fields in return messages are dependent of the initating command for the given transaction and are documented for each commands in the previous section Commands.
From version 1.6.0, the following fields shall also be available for each
and every return messages, such as to timestamp each return message:
"sim_time":(number): Current simulation time
"sim_time_unit":(text): Current simulation time unit
Note
The addition of a timestamp in simlation time unit to each return message
makes the command {"command": "get", "sel": "sim_time"} obviously
obsolete… It shall thus be considered as deprecated from version 1.6.0.