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 |
- 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
- tested with QuestaSim 2024.3
- EMULATION
- define
MULTISIM_EMULATIONin SV and C/C++ compilation - tested with Veloce v23.0.1
- 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
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

