External Control of a ModelSim Simulation Via Unix Named Pipes
Abstract: In this thesis, we present a method of controlling a
ModelSim simulation via an external program. Communication between
ModelSim and the external program is accomplished by using Named Pipes
("FIFOs"), which appear as normal files to each application. The main
difference between using FIFOs versus normal files for Inter-Process
Communication (IPC) is that an application attempting to write to a
FIFO is paused until another application attempts to read from the
FIFO and vice-versa. This improves reliability of the IPC. The major
advantages of this method are 1) Since only generic file operations
are used, the external application can be written in nearly any
programming language; 2) It gives the verification engineer the
ability to reuse standards-validation software packages with minimal
rewriting; 3) By having multiple Devices Under Test (DUT) communicate
with each other, a more accurate simulation of the final system can be
created; and 4) Performance of the overall simulation can be increased
easily on a Single-System Image (SSI) cluster or multiprocessor
computer even though ModelSim's simulation engine is not multi-
threaded. Due to its implementation of file input/output (I/O) for
behavioral VHDL, ModelSim cannot read or write these FIFOs directly. A
workaround for this limitation is demonstrated using ModelSim's
Foreign Language Interface (FLI). This paper also shows a working
example of this method being used in the verification of the next
generation of floating point routines in VHDL. Specifically, the
open-source IEEE Compliance Checker software package, which is written
in C++, is modified to communicate with a VHDL testbench running on
ModelSim to verify functionality of the add, multiply, divide, and
square root operations with various widths of floating point numbers.
And the issue with FIFOs requiring a Foreign programming interface is that VHDL file I/O can't deal gracefully with blocking until data is available.
Unfortunately the thesis isn't available on the web.
Model Sim ® Foreign Language Interface Version 5.6d, PDF 3.4 MB.
Using ModelSim Foreign Language Interface for c – VHDL Co- Simulation and for Simulator Control on Linux x86 Platform Andre Pool - fli@andrepool.com - Version 1.5 - created November 2012, last update September 2013, PDF, 320KB (And never mentions FIFOs).
Using ModelSim Foreign Language Interface for c – VHDL Co-Simulation and for Simulator Control on Linux x86 Platform (The matching github code repository).
There's a bit more open source, using the VHPI Foreign function calls in ghdl:
vhdl/src/sim/ghdlex_mein at master · texane/vhdl · GitHub.
And what looks like an update from Martin Strubel on the GHDL_discuss list:
http://www.section5.ch/downloads/ghdlex-0.051.tgz showing a date for fifo.c of April 14, 2014.
FLI would by definition lock you in to Modelsim, not sure of the state of their VHPI support (which is part of IEEE Std 1076-2008, the VHDL LRM).
Using a socket or file FIFO allows the software and hardware process to run at different rates, by providing rate buffering. It isn't always necessary if you're software system is orders of magnitude faster than the hardware simulation (and it generally is).
There's an effort to provide UNIX (POSIX) functionality to VHDL, See Public Domain VHDL packages, which contains a pointer to an earlier paper SNUG San Jose 2002 1 C/UNIX Functions for VHDL Testbenches C/UNIX Functions for VHDL Testbenches along with a slide set with additional notes on Unix pipes & rsh. This shows how to keep named pipes opened. All the VHDL code can be downloaded as well. I'm of the opinion this would lead to the easiest way of achieving your goal.
So is there something native to Modelsim that allows you to hook up to a pipe? Likely not, the more so under Windows. Can it be done? Yes, but the way isn't for the fainthearted. You can deadlock one end or the other or possibly both waiting on data availability.
A Foreign programming interface theoretically allows you to spawn a child process for one or the other end of the 'pipe' which also means you could use a shared memory model to communicate between the two ends.
If your VHDL description exhibits combinatorial dependency cycles, then the synthesizers will generate the exact same circuit. If you want it, you get it. However, warnings will be emitted, because it is difficult (but not impossible) to tell whether the circuit will oscillate or not (that is : will behave as pure combinatorial circuit circuits or sequential circuit). So the synthesis algorithms prefer to inform you about this danger. Such cyclic circuits also cause several difficulties in mainstream SoC design flows : for instance during timing analysis...
Please note that your question is indeed a research topic. For instance, you can read about this in several known articles :
To sum up, this resort to cyclic combinatorial circuit can be interesting when they can stabilize, because their performance (area and speed) will be better than a sequential counterpart. However, as mentioned earlier, this is not mainstream and as such still not recommended in classical (industrial) design flows.
Concerning VHDL simulation, the simulation algorithm is event-driven : an evaluation of a concurrent assignment (ou process) can lead to new evaluation of other parts or of itself. This is not a problem for the simulator. Again, depending of the circuit described, this behavior will stop (sequential behavior) or not (infinite loop).
Best Answer
If you only have one 'sink,' then you have to arbitrate. You'll have to apply backpressure to any source that has yet to receive a grant. If you can't apply backpressure to whatever is generating the requests directly, then the only option is to put in a 'large enough' FIFO on each source and apply backpressure to those FIFOs. The trick is figuring out how big those FIFOs need to be to eliminate drops - maybe some sources can accept backpressure, maybe some send more often and therefore require deeper FIFOs, etc. You can usually make FIFOs of depth 16-128 or so using distributed RAM with 1 LUT per bit.
AXI stream is super simple, it's just a ready and a valid signal that go along with the data. Valid is high when the data is valid, ready indicates that the sink is ready to receive the data, and data is transferred when both valid and ready are high. When you connect a FIFO with a 'traditional' FIFO interface, you can map input_ready, input_valid, output_ready, and output_valid onto read, write, full and empty like so: