simulate your RTL with real multi-threaded speed
interface different simulators, chiplets and platforms together
multisim is a systemverilog/DPI library allowing multiple simulations/platforms to run in parallel and communicate to simulate your DUT.
Typically, you can have:
- 1 server simulation with your DUT skeleton (NOC, fabric, etc)
- N client simulations with 1 big instance each (computing core, chip, etc)
Assuming your original simulation has N CPUs that take a lot of simulation time.
Into this one, running on N+1 simulation instances:

Reusing this example where we have:
- 1 server simulation with 1 NOC
CPU numberclient simulations with 1cpu(slow module) each
Tested platform combinations:
| client \ server | sim | emu | sw |
|---|---|---|---|
| sim | ✅ examples | ✅ examples | untested |
| emu | untested | untested | untested |
| sw | ✅ examples | ✅ examples | ✅ examples |
./run_regression.sh # all the tools: sw,verilator,vcs,zebu
./run_regression.sh -t sw,vcs # some of them
./run_regression.sh -z # also build the ZeBu database if needed (about 1 hour)
./run_regression.sh -a # also run the long sim_server and emu_server example suitesShort versions of the tests, a summary at the end (PASS/FAIL/SKIP per tool and test), exit code 1
if a test fails. Tools that are not installed are skipped. Logs and the summary (summary.txt) are
in output_regression/.
sw(g++ only, about 1 min): example/sw_server/sw_client/run_all.sh, the read_write example and the unit regression tests of the libraryverilator: sim_server examples, 2 CPUs for the multi onesvcs: sim_server/sw_client/read_write and sim_server/sim_client/axi_4state/multi (2 CPUs)zebu: emu_server/sw_client/read_write, reusing its database unless the SV sources changed (then skipped,-zbuilds it); the host code is rebuilt alone when the C sources changed
example/sw_server/sw_client/bench/run measures the client/server library (SW, about 15 s): latency of a round trip, throughput of a stream, cost of a pull with no data.
- core library (ready/valid protocol)
client->server: multisim_client_push and multisim_server_pullserver->client: multisim_server_push and multisim_client_pull
- other protocols:
- axi
- apb
- quasi static signals (useful for signals without control signals like IRQ)
- SIMULATION
- tested with Verilator 5.040 (
./runin sim_server examples) - tested with QuestaSim 2024.3 (
./run_questain the sim_server examples) - tested with VCS X-2025.06 (
./run_vcsin sim_server examples)
- tested with Verilator 5.040 (
- EMULATION
- define
MULTISIM_EMULATIONin SV and C/C++ compilation - tested with Veloce v23.0.1 (
./compilein emu_server examples) - ZeBu: define
MULTISIM_ZEBUinstead, see ZeBu- tested with ZeBu W-2025.06-4 (
./compile -e zebuin emu_server examples)
- tested with ZeBu W-2025.06-4 (
- define
- SW
- define
MULTISIM_SWin C/C++ compilation - client API / server API
- tested with GCC 15.2.1
- define
Look at those files to have more info about those platforms:
- server simulation and client simulations communicate through channels
- channels direction can be
client->serverorserver->client - each simulation can use multiple channels
multisimmodules need a uniqueserver_nameto link a client/server channel together- client modules need to set
server_runtime_directoryto know the port/ip address of each channel - a client on the host of the server connects through a Unix socket (in
.multisim/), a client on another host through TCP - the pull modules call their DPI at every cycle while no data comes: their
DPI_DELAY_CYCLES_INACTIVE/DPI_DELAY_CYCLES_ACTIVEparameters space the calls (faster idle simulation, more latency), e.g. 1000 cycles cuts the idle cost of a VCS client by 75%
# optional site settings
export MULTISIM_ZEBU_SETTINGS=site.utf # UTF sourced by the zCui project (grid_cmd, clock_config...)
export MULTISIM_ZEBU_LAUNCHER="srun --emu-work-dir ./zcui.work/zebu.work" # zRci prefix, books an emulator
cd example/emu_server/sw_client/core
./compile -e zebu
./output/run
# or all the examples
cd example/emu_server && ./run_all.sh -e zebu- define
MULTISIM_ZEBUinstead ofMULTISIM_EMULATIONin SV and C/C++ compilation server_namemust be a string literal of at most 512 characters- the server modules are ZEMI3 transactors, see example/emu_server/zebu for the zCui project and the zRci script
By default, multisim uses 2-state logic (0 and 1).
However 4-state logic (0, 1, X and Z) can be used by using the parameter DATA_IS_4STATE.
See the axi_4state example
4-state logic:
- is currently not supported in EMULATION
- doubles the amount of bytes exchanges over TCP/IP sockets
- source env.sh
- pass the right files to your simulator:
If your platform requires a shared object (.so file), it can be compiled like so:
# SW client example
g++ -o multisim_sw_client.so -g -shared -fPIC \
-DMULTISIM_SW \
$MULTISIM_SRC/core/multisim_client.cpp \
$MULTISIM_SRC/core/socket_server/client.cppLook in the example directory for more examples.
You can either:
- use the helper function
$MULTISIM_SRC/bin/kill_all_clientsto kill clients running in the backgroud - use an "exit" channel to send exit instructions to the clients/servers you want to kill
- write a custom kill script
Find more info about PIDs/IPs of your clients in the server runtime directory in .multisim/client*.txt
Pros:
- speed: split your big DUT in as many smaller parts as you want
- interoperability: can use different simulators/platforms combinations (Verilator, VCS, Questa, Xcelium, Veloce, Palladium, Zebu, Qemu etc)
- scalability: as long as you have enough CPUs on your server
Cons:
⚠️ no cycle accuracy⚠️ : transactionally accurate, but not cycle accurate- harder debug: waveforms split on N+1 simulation, no time coherency in between them
- simple transaction logging to help debug

