Code Monkey home page Code Monkey logo

pyxsi's Introduction

C/RTL Cosimulation with Vivado and Python

tags:Vivado, xsim, XSI
category:Vivado
slug:vivado-cosimulation-with-xsi
summary:A method to cosimulate C and RTL code under Python control

Xilinx's xsim simulator (UG900) includes the Xilinx Simulator Interface (XSI), a way to embed a RTL simulation kernel inside a C/C++ program. This page further embeds XSI kernels within a Python session, creating a layered simulation environment where Python, C/C++, and RTL coexist. Testbenches can be coded in a mixture of the three languages, removing the hard boundaries that surround an RTL-only testbench environment.

RTL testbenches are a good way to verify low-level design elements, but RTL testbenches alone are not good enough.

First, I want to verify a combination of C and RTL code, where the interface between C and RTL is complex and malleable. Driving a wedge between C code and RTL code so I can extract test vectors via file I/O feels like a monumental distraction.

Second, I need to post-process test data in Python. For signal-processing analysis, my go-to environment is Python/Scipy/Matplotlib. For data analysis, there is nothing in C or RTL that offer the same broad reach and high productivity.

Finally, I want my test environment to resemble my deployment environment. My design is an amalgam of C and RTL when it's deployed; why should the testing environment be different? (Here, ASIC designers will be tearing out their hair. It's OK, I understand.) Combining C and RTL reduces the amount of hassle associated with testing, which allows me to focus on solving problems and not fighting tools.

Compounding the issue further: many excellent test environments (cocotb, VUnit, UVVM) do not work with Xilinx's simulator. As a result, my options for higher-level testing constructs focused on an RTL world dwindle from "frustrating" to "squalid". This is largely Xilinx's fault: although it is slowly improving, xsim's support for SystemVerilog and VHDL-2008 constructs lags other simulators [1].

The following sections show a start-to-finish build, from checking out the source code to completing a test.

Source code is available at https://github.com/gsmecher/pyxsi.

$ git clone https://github.com/gsmecher/pyxsi.git
Cloning into 'pyxsi'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 14 (delta 0), reused 14 (delta 0), pack-reused 0
Receiving objects: 100% (14/14), 6.72 KiB | 6.72 MiB/s, done.

You should modify the top-level Makefile (setting XILINX_BASE) to match your Vivado installation. The example here uses Vivado 2023.2, though it is reasonably portable.

Next, prepare your Docker environment:

$ cd pyxsi
pyxsi$ make dockerenv

This step prepares a portable build environment using Docker. You only need to run this step once.

Now set up Xilinx's environment variables and build the RTL into a simulation library.

There is a Docker wrapper in this command (and subsequent commands). You may need to modify the top-level Makefile to point to the right Vivado installation path.

pyxsi$ make rtl
Moving inside Docker...
make: Entering directory '/root'
. /opt/xilinx/Vivado/2023.2/settings64.sh && \
     xelab work.widget -prj rtl/widget.prj -debug all -dll -s widget && \
     xelab work.counter_verilog -prj rtl/counter.prj -debug all -dll -s counter_verilog  && \
     xelab work.counter_wide_verilog -prj rtl/counter.prj -debug all -dll -s counter_wide_verilog
Vivado Simulator v2023.2
Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
Copyright 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved.
Running: /opt/xilinx/Vivado/2023.2/bin/unwrapped/lnx64.o/xelab work.widget -prj rtl/widget.prj -debug all -dll -s widget
Multi-threading is on. Using 14 slave threads.
Determining compilation order of HDL files.
INFO: [VRFC 10-163] Analyzing VHDL file "/root/rtl/widget.vhd" into library work
INFO: [VRFC 10-3107] analyzing entity 'widget'
Starting static elaboration
Completed static elaboration
Starting simulation data flow analysis
Completed simulation data flow analysis
Time Resolution for simulation is 1ps
Compiling package std.standard
Compiling package std.textio
Compiling package ieee.std_logic_1164
Compiling package ieee.numeric_std
Compiling architecture behav of entity work.widget
Built XSI simulation shared library xsim.dir/widget/xsimk.so
Vivado Simulator v2023.2
Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
Copyright 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved.
Running: /opt/xilinx/Vivado/2023.2/bin/unwrapped/lnx64.o/xelab work.counter_verilog -prj rtl/counter.prj -debug all -dll -s counter_verilog
Multi-threading is on. Using 14 slave threads.
INFO: [VRFC 10-2263] Analyzing Verilog file "/root/rtl/counter.v" into library work
INFO: [VRFC 10-311] analyzing module counter_verilog
INFO: [VRFC 10-311] analyzing module counter_wide_verilog
Starting static elaboration
Pass Through NonSizing Optimizer
Completed static elaboration
Starting simulation data flow analysis
Completed simulation data flow analysis
Time Resolution for simulation is 1ps
Compiling module work.counter_verilog
Built XSI simulation shared library xsim.dir/counter_verilog/xsimk.so
Vivado Simulator v2023.2
Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
Copyright 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved.
Running: /opt/xilinx/Vivado/2023.2/bin/unwrapped/lnx64.o/xelab work.counter_wide_verilog -prj rtl/counter.prj -debug all -dll -s counter_wide_verilog
Multi-threading is on. Using 14 slave threads.
INFO: [VRFC 10-2263] Analyzing Verilog file "/root/rtl/counter.v" into library work
INFO: [VRFC 10-311] analyzing module counter_verilog
INFO: [VRFC 10-311] analyzing module counter_wide_verilog
Starting static elaboration
Pass Through NonSizing Optimizer
Completed static elaboration
Starting simulation data flow analysis
Completed simulation data flow analysis
Time Resolution for simulation is 1ps
Compiling module work.counter_wide_verilog
Built XSI simulation shared library xsim.dir/counter_wide_verilog/xsimk.so
make: Leaving directory '/root'

Now build the C++ code:

pyxsi$ make
make: Entering directory '/root'
g++-10 -Wall -Werror -g -fPIC -std=c++20 -I/usr/include/python3.9 -I/opt/xilinx/Vivado/2021.2/data/xsim/include -Isrc -c -o pybind.o src/pybind.cpp
g++-10 -Wall -Werror -g -fPIC -std=c++20 -I/usr/include/python3.9 -I/opt/xilinx/Vivado/2021.2/data/xsim/include -Isrc -c -o xsi_loader.o src/xsi_loader.cpp
g++-10 -Wall -Werror -g -fPIC -std=c++20 -I/usr/include/python3.9 -I/opt/xilinx/Vivado/2021.2/data/xsim/include -Isrc -shared -o pyxsi.so pybind.o xsi_loader.o -lfmt -ldl -static-libstdc++
make: Leaving directory '/root'

Finally, tests are discovered and executed using Python's pytest environment.

pyxsi$ make test
Moving inside Docker...
make: Entering directory '/root'
LD_LIBRARY_PATH=/opt/xilinx/Vivado/2023.2/lib/lnx64.o \
     python3.10 -m pytest py/test.py -v
============================= test session starts ==============================
platform linux -- Python 3.10.12, pytest-8.3.2, pluggy-1.5.0 -- /usr/bin/python3.10
cachedir: .pytest_cache
metadata: {'Python': '3.10.12', 'Platform': 'Linux-6.7.12-amd64-x86_64-with-glibc2.35', 'Packages': {'pytest': '8.3.2', 'pluggy': '1.5.0'}, 'Plugins': {'html': '4.1.1', 'check': '2.4.1', 'metadata': '3.1.1', 'xdist': '2.5.0', 'forked': '1.4.0'}}
rootdir: /root
plugins: html-4.1.1, check-2.4.1, metadata-3.1.1, xdist-2.5.0, forked-1.4.0
collecting ... collected 4 items

py/test.py::test_counting[VHDL] PASSED                                   [ 25%]
py/test.py::test_counting[VERILOG] PASSED                                [ 50%]
py/test.py::test_counting_wide_verilog PASSED                            [ 75%]
py/test.py::test_random PASSED                                           [100%]

============================== 4 passed in 5.09s ===============================
make: Leaving directory '/root'

This is only a skeletal example, with just enough scaffolding to build on.

[1]I use xsim because none of the open-source simulators can combine VHDL and Verilog, or simulate encrypted IP. Commercial simulators don't make sense for a small instrumentation consultancy (mine, anyway).

pyxsi's People

Contributors

gsmecher avatar maltanar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pyxsi's Issues

License Project

Would you consider licensing this source code under MIT, BSD, etc? Currently there is no OSS license specified that I could fine.

(XSI runtime issue) Vivado 2021.2 crashes when more than one distinct simulator snapshot is used.

This issue is a bug in the underlying XSI implementation (in at least Vivado 2021.2). It's being tracked here to inform pyxsi users.

A testbench that instantiates multiple simulator snapshots with different RTL:

int main(int argc, char **argv)
{
	s_xsi_setup_info info;
	memset(&info, 0, sizeof(info));

	/* First simulator kernel - no problem */
	auto xsi1 = Xsi::Loader("xsim.dir/counter/xsimk.so", "librdi_simulator_kernel.so");
	xsi1.open(&info);
	xsi1.close();

	/* Second simulator kernel - also no problem. Note that we're using the
	 * same xsimk.so, so any relocation may follow a degenerate code path. */
	auto xsi2 = Xsi::Loader("xsim.dir/counter/xsimk.so", "librdi_simulator_kernel.so");
	xsi2.open(&info);
	xsi2.close();

	/* Third simulator kernel - note that the RTL design we're using here
	 * is different. The simulator segfaults. */
	auto xsi3 = Xsi::Loader("xsim.dir/widget/xsimk.so", "librdi_simulator_kernel.so");
	xsi3.open(&info);
	xsi3.close();
}

...will crash as follows:

./sim
munmap_chunk(): invalid pointer
./run.sh: line 19: 3269298 Aborted                 ./sim

There appears to be a problem in the underlying relocation code. The stack trace looks as follows:

$ gdb ./sim 
	Reading symbols from ./sim...
	(gdb) run
	Starting program: /home/gsmecher/xsi/sim 
	munmap_chunk(): invalid pointer
	
	Program received signal SIGABRT, Aborted.
	__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
	49	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
	(gdb) backtrace
	#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
	#1  0x00007ffff7bb5546 in __GI_abort () at abort.c:79
	#2  0x00007ffff7c0ceb8 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7d2aa78 "%s\n")
	    at ../sysdeps/posix/libc_fatal.c:155
	#3  0x00007ffff7c1491a in malloc_printerr (str=str@entry=0x7ffff7d2ca20 "munmap_chunk(): invalid pointer") at malloc.c:5628
	#4  0x00007ffff7c14d6c in munmap_chunk (p=<optimized out>) at malloc.c:2995
	#5  0x00007ffff7c199e3 in __GI___libc_free (mem=<optimized out>) at malloc.c:3302
	#6  0x00007ffff753a160 in iki_vhdl_file_close () from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#7  0x00007ffff753a1cc in iki_vhdl_file_open () from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#8  0x00007ffff75563fc in iki_vhdl_file_variable_register ()
	   from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#9  0x00007ffff7fc0b17 in relocate () from xsim.dir/counter/xsimk.so
	#10 0x00007ffff75c2acc in ISIMK::Kernel::initialize() ()
	   from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#11 0x00007ffff75c2d58 in ISIMK::Kernel::Kernel(char const*, char const*, void (*)(char*), void (*)(char*), void (*)(char*), unsigned int, ISIMK::Host*) () from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#12 0x00007ffff75f1025 in ISIMK::XSIHost::XSIHost(char const*, char const*, void*, void*, void*, void*, unsigned int, void*, int, char const**) () from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#13 0x00007ffff7467d73 in iki_create_ccp_design () from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#14 0x00007ffff7467ee3 in iki_create_design () from /opt/xilinx/Vivado/2021.2/lib/lnx64.o/librdi_simulator_kernel.so
	#15 0x00007ffff7045335 in xsi_open () from xsim.dir/widget/xsimk.so
	#16 0x0000555555556b2d in Xsi::Loader::open (this=this@entry=0x5555555a2410, setup_info=setup_info@entry=0x7fffffffdcc0)
	    at xsi_loader.cpp:42
	#17 0x000055555555650b in main (argc=<optimized out>, argv=<optimized out>) at testbench.cpp:30

Xilinx IP support?

Hi there!

This project is pretty great!
Have played around with the example a bit.

I was wondering if it's possible to support code with Xilinx IP cores? I should, right?
In that case, do you have any example?

Cheers, William

Verilog/SystemVerilog support

As documented here and here XSI uses different data structures to represent logic values (0, 1, X, Z) depending on whether the top-level module is Verilog or VHDL. The current pyxsi implementation handles the VHDL-style interfaces well, but fails (misinterprets) Verilog which is expected since it uses a completely different data structure. This is worth documenting in the README that Verilog top modules aren't yet supported.

I've started working on adding support for this in my fork. I've yet to test it with >32-bit vectors, but would be happy to open a PR to the mainline if this is of interest.

Thank you for making pyxsi and sharing it with the community :-)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.