jtag_dpi icon indicating copy to clipboard operation
jtag_dpi copied to clipboard

JTAG DPI module for OpenRISC simulation with Verilator

This is the source file from which the README file is generated.

This file is written in Perl's Plain Old Documentation (POD) format. Run the following Perl commands to convert it to text or to HTML for easy reading:

podchecker README.pod # Optional, check syntax. pod2text README.pod >README.txt

pod2html seems buggy, at least in perl v5.10.1, therefore

I'm using this long one-liner instead (with bash):

perl -MPod::Simple::HTML -e "$p = Pod::Simple::HTML->new; $p->index( 1 ); $p->output_fh( *STDOUT{IO} ); $p->force_title('JTAG DPI'); $p->parse_file('README.pod');" >README.html

This file is best edited with emacs module pod-mode, available in CPAN. However, the POD syntax is quite simple and can be edited with a standard text editor.

=pod

=head1 JTAG DPI module for OpenRISC simulation with Verilator

Version 1.04, September 2012

If you are simulating an OpenRISC-based System-on-a-Chip (SoC) with L<< Icarus Verilog|http://iverilog.icarus.com/ >>, you have probably come across the L<< MinSoC|http://www.minsoc.com/ >> project. MinSoC includes a copy of Nathan Yawn's L<< Advanced Debug System|http://opencores.org/project,adv_debug_sys >>, which among other things allows you to create a virtual JTAG interface, so that you can start GDB (the GNU debugger) on your PC and connect to the simulated system as if it were real hardware and you were using a real JTAG cable.

The virtual JTAG cable implemented in the Advanced Debug Interface is a VPI module which only works with Icarus Verilog and the like. This JTAG DPI module is a replacement written in SystemVerilog's Direct Programming Interface (DPI) that allows simulating the SoC with Verilator (and probably other simulators that support DPI). Similarly to its VPI counterpart, the JTAG DPI module connects the JTAG TAP, written in Verilog, with a DPI module, written in C++. The C++ part creates a listening TCP socket so that adv_jtag_bridge (which is part of the Advanced Debug System) can connect to it over TCP/IP. The network connection between the JTAG DPI module and the adv_jtag_bridge is effectively a virtual JTAG cable.

Note that, if the socket connection is lost for some reason, you can start another instance of adv_jtag_bridge and connect to the simulation again. This is equivalent to disconnecting and reconnecting a physical JTAG cable on real hardware.

You should be aware that there are no security checks at all, any user logged on to the local computer can connect to the TCP socket.

The JTAG DPI module is loosely based on its VPI counterpart in the Advanced Debug System (as of october 2011, version 2.5), as the (very simple) protocol over the TCP socket has to remain compatible with the adv_jtag_bridge side. There is nothing specific to OpenRISC in the JTAG DPI module. However, if you wish to reuse it for another processor arquitecture, you will need to modify the adv_jtag_bridge counterpart accordingly.

As an alternative to this DPI module, take a look at L<< Embecosm|http://www.embecosm.com/ >>'s project "Cycle Accurate SystemC JTAG Interface: Reference Implementation" (among other software they publish), as they have a similar type of virtual JTAG interface for Verilator written in SystemC.

=head2 Installation instructions

I hacked together a MinSoC version on my PC which seems to work with Verilator. I can connect to the simulation with the Advanced Debugging System, set breakpoints with GDB and step through the C sources. I was very happy to see the Verilator simulation fly compared to Icarus Verilog. I have done very limited testing, so I would love to hear your experiences with this module. This section describes how I have done it.

Note that the current implementation of the JTAG DPI module has been developed and tested only on Linux.

You need to be familiar with Verilator or your simulator of choice, as you need to add file I<< jtag_dpi.cpp >> to the generated C++ code. There are a few ways to do that:

Alternative 1) Add the jtag_dpi.cpp to the Verilator command line. Alternative 2) Include jtag_dpi.cpp from your main .cpp file (with #include). Alternative 3) Edit the makefile you are using.

Your main routine should ignore or properly handle signal SIGPIPE. Otherwise, the simulation may get killed by this signal if the remote end (the JTAG TCP client, normally adv_jtag_bridge) closes the connection unexpectedly.

You also need to add file I<< jtag_dpi.v >> to the Verilog sources and connect its Verilog module to the JTAG TAP module, you need something like this:

jtag_dpi jtag_dpi_instance ( .system_clk( clock ), .jtag_tms_o( dbg_tms_i ), .jtag_tck_o( dbg_tck_i ), .jtag_trst_o(), // Leave unconnected or use it in your design as you wish. .jtag_tdi_o( dbg_tdi_i ), .jtag_tdo_i( dbg_tdo_o ) );

See the following files included in this package for an example on how to generate and run the Verilator simulation in MinSoC:

verilator_main.cpp generate_verilator_bench run_verilator_bench

The top-level test bench module needs to declare the clock and reset signals as input arguments, as the C++ side will be generating them. You will probably have to make other small amendments to those files in order to make it work with your MinSoC version.

At the time of writing these instructions, Verilator printed many lint warnings for many of the Verilog modules included with MinSoC. In my opinion, it would be worth fixing those warnings, in order to uncover potential problems or to improve the simulation performance.

Please note that there is a bug in adv_jtag_bridge (as of october 2011, version 2.5), so that the TCP port number has the wrong format on little-endian processors (which includes all Intel-compatible PCs). Until this bug is fixed you must specify on one side the familiar port number 4567 (which is 11D7 in hex), and on the other side port number 55057 (which is D711 in hex, note how the bytes are reversed). For the DPI side, look at constant LISTENING_TCP_PORT in file I<< jtag_dpi.v >>, and for the adv_jtag_bridge side, look at command-line parameter -p .

=head2 How you can help

MinSoC's UART and Ethernet test benches do not work under Verilator. The only way to interact with the Verilator simulation is the GDB connection over JTAG and the occasional $display() message on the debug console. At the very minimum I would love to get the UART test bench running, as the "Hello World" message at the end is very reassuring.

Ideally, you could help by rewriting the UART test bench and UART monitor in pure synthesisable Verilog (things like $display() do also work). That means mainly no fork/join and no waiting for a signal to change with a statement like this:

@(posedge new_char);

The UART test bench is small and should be no real challenge for an experience Verilog developer. Rewriting the Ethernet test model in the same way would be a good bonus.

About writing those test modules in Verilog, I have avoided SystemC until now for these reasons:

  1. It's slower than Verilator's native C++.
  2. I don't have the time now to learn it (as of Nov 2011).
  3. I don't want to burden the users with the installation of the extra SystemC and SystemPerl libraries needed by Verilator
  4. Test models in pure synthesisable Verilog are more complicated but should work on all simulators, whether cycle-based or not.

A separate SystemC test bench is certainly still an option if somebody is willing to take this up. Note that Embecosm has already released a SystemC test bench for OpenRISC (but not for MinSoC), see the link above.

I don't have access to other commercial simulators to test the JTAG DPI module on, maybe you can help here too. Cygwin and BSD maintainers are also welcome.

=head2 License

Copyright (C) R. Diez 2011, rdiezmail-openrisc at yahoo.de

The JTAG DPI source code is released under the LGPL 3 license.

This document is released under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) license.

=cut