Simulation questions



When a simulation is run with “reco sim run”, what is actually happening under the hood?

Is the Go code translated to the exact same Verilog that would be obtained if I run a build, or is the simulation RTL different in some way^
Is this a functional simulation run on the Vivado simulator?


Hi Mark,

The simulations are run on the same Verilog as used in a build. It is actually an intermediate netlist rather than RTL, so takes longer to run than an RTL simulation but is closer to the final hardware. This is currently run in the context of the Xilinx SDAccel hardware simulation framework, so uses the appropriate Xilinx simulation models for the wrapper components and external memory.



To continue on ‘what is going on under the hood’: what happens to code that terminates go-routines.

We have build an extensive architecture functional simulator in Go of our hardware. There are two patterns that we use that I would like to understand how they would be processed.

The first pattern is the use of passing pointers to data structures that are sometimes pooled so that the simulation doesn’t pay the overhead of memory allocations of each and every transaction/package that gets communicated in the CSP model.

The second pattern is the use of special paths to terminate the go-routines. We have two patterns, a non-blocking pattern that uses an interrupt channel, and a blocking pattern that can process a STOP command as part of the regular packet data structure that is communicated across the channel that feeds the go-routine.

How would these two patterns be processed?


The first pattern you mention is problematic for our current tooling since we don’t support the full Go memory model. Access to shared memory is via a low level interface (AXI or SMI) that just treats it as a contiguous block of RAM. Depending on the size of the data items involved it would make sense to either use pass by value or implement an application specific memory pool for managing the shared state.

In terms of goroutine termination, any goroutine which invokes other goroutines that can terminate will always wait for all those goroutines to exit before terminating itself. Any goroutines which do not terminate will run until the main function exits, at which point a hard reset is automatically applied to the entire design. In the scenario you describe, this will mean that the main function will wait until all the appropriate goroutines have been halted on interrupt events or STOP commands before exiting.