Home

Awesome

This project is deprecated and replaced by https://github.com/olofk/vidbo

This repository will be removed once the relevant information has been migrated

verilatio

A protocol for communicating with HDL simulations over websockets

Background

All chip designs inevitably have some kind of inputs and outputs to the world outside of the device under test. This I/O can be modeled in different ways for different purposes. For regression tests this often takes the form of predefined stimuli sent into the device and outputs being monitored to make sure the device did the expected thing. In other cases however, there is a need to communicate interactively with the simulated design. As an example this can be a simulation of a SoC running a user program, where the user wants to send commands over a simulated UART connection and see that the program behaves as expected by observing changes in the device's output. This adds more requirements to the simulated design, especially when there are multiple types of inputs and outputs. Many solutions exist already for various cases, such as outputting the UART output on the screen, creating a window to show graphics and communicating over sockets and FIFOs. One common problem with these solutions however is that they decrease the portability by depending on external libraries which can be hard to compile on some platforms. They are also not standardized which makes reuse harder

This is a proposal for a protocol to be used over websockets to handle input, output and run control of chip designs running in simulations. Websockets was chosen since it's a a light-weight extension over standard sockets and allows the client side to be implemented in a web browser or any program that implements websockets.

Some use cases for the protocol are

Note: No attempt to emulate communication on bus-level like SPI. Focus on higher-level use cases like memories and sensors. Let simulator figure out the lower-level details.

Basics

Messages are JSON-encoded. All messages from simulator carries a timestamp of current simulator time. This time can not be decreasing. Simulator can send messages only containing the timestamp to inform the client of the current simulation time.

/* Turn on LED 0 */
{
"time" : 12345,
"led" : {"0" : true}
}

Messages from client to simulator does not contain timestamps.

/* Turn off switch 3. Turn on VCD capturing */
{
"switch" : {"3" : false},
"vcd" : true
}

Main websocket channel is text. Binary high-bandwidth data (e.g. ethernet and video) are sent over separate sockets as binary data. Client can ask simulator which additional sockets are used.

If several commands of the same type is sent in the same message, the result is undefined since we can't guarantee ordering in the json struct. Example

/* VCD on and off at the same time. Undefined outcome */
{
"time" : 12345,
"vcd" : false,
"vcd" : true
}

TODO : This covers several classes of devices. Would be good to mimic a strcuture here (like the Linux kernel) to avoid having to come up with a device classification from scratch.

TODO: Figure out corner cases and error handling

TODO: Is it necessary to have different sockets for high-bandwidth data. No clue how this works in practice

TODO: PWM for LEDs. Do we send each I/O change (lots of messages) or calculate a PWM value as a float in the sim (how do we decide when to send a new value? First case does not need special protocol handling so lets start with that

TODO: How do we handle 7-segment displays? Just a series of gpio to begin with to make it easy

TODO: Several use cases slot in somewhat with VirtIO. Maybe develop VirtIO<->verilatio bridges for e.g. ethernet, block devices, console

TODO: How to handle non-buffered data streams like UART? One messages for each character? Do some clever queueing? Treat as binary data or text?

TODO: Transfering large chunks of data such as ihex file for programming or maybe a frame from a graphics output might be split across several messages (frames?) Need to investigate if this is a problem

TODO: Should simulator send message with all GPIO state upon connecting? That would both help discover available I/O and sync up both sides

Protocol

gpio

Turn GPIOs on and off. GPIO can be switches, LEDs (RGB LEDs would have three pins associated with them), buttons, 7-segment displays (each segment gets its own gpio pin)

Argument : dict of name/value (string/bool) pairs

dir: both

Example:

/* To simulator */
{
   "gpio":{
      "SW0":true,
      "BTN4":false
   }
}

/* From simulator */
{
   "gpio":{
      "LED2":true,
   }
}

vcd

Turn waveform capturing on and off

Argument : bool

dir: to sim

line

A line of text for line-buffered communication

Argument : string

dir : both

run

Run/pause simulation

Argument : bool

dir: to sim

memwrite

Write an Intel Hex file to memory.

Argument : dict of name/value (string/string) pairs where name refers to the identifier of the memory to be programmed (in case there are multiple) and the value is the ihex data

dir: to sim

/* Write a ihex file (containing a RISC-V LED blinker) to RAM */
{"memwrite" :
  {"ram" : ":1000000037050040130505003703010023005500A4\n:1000100093C21200B373000093831300E31E73FEB8\n:040020006FF0DFFEA0\n:00000001FF"}
}