Skip to content

Software Firmware simulation with VCS and Rogue

Benjamin Reese edited this page Nov 14, 2019 · 10 revisions

Here are instructions for setting up and running a software-firmware co-simulation with VCS and Rogue.

Note: These instructions assume surf @ v1.10.0 (or later) and rogue @ v4.0.0 (or later)

Instantiate RogueTcpStreamWrap in Firmware

The firmware will need an instance of RogueTcpStreamWrap per Virtual Channel / TDEST.

For cases where a PGP2b (or PGP3) interface is being emulated, you can use RoguePgp2bSim (or RoguePgp3Sim) instead. This will instantiate 4 RogueTcpStreamWrap instances, one per VC. It will also instantiate a 5th instance specifically for OpCodes.

The PORT_NUM_G generic constitute the TCP port forwarding. You will use these same numbers when instantiating the streams on the software side.

Example:

SIM_GEN : if (SIMULATION_G) generate
   DESTS : for i in 1 downto 0 generate
      U_RogueTcpStreamWrap_1 : entity work.RogueTcpStreamWrap
         generic map (
            TPD_G         => TPD_G,
            PORT_NUM_G    => (9000 + i*2), -- 2 TCP ports per RogueTcpStreamWrap connection
            SSI_EN_G      => true,
            CHAN_COUNT_G  => 1,
            AXIS_CONFIG_G => AXIS_CONFIG_C)
         port map (
            axisClk     => pgpClk,              -- [in]
            axisRst     => pgpRst,              -- [in]
            sAxisMaster => pgpTxMasters(i),     -- [in]
            sAxisSlave  => pgpTxSlaves(i),      -- [out]
            mAxisMaster => pgpRxMasters(i),     -- [out]
            mAxisSlave  => pgpRxSlaves(i));     -- [in]   
   end generate DESTS;
end generate SIM_GEN;
HW_GEN : if (not SIMULATION_G) generate
  -- Instantiate normal PGP or Ethernet/UDP blocks here
end generate HW_GEN;

Warning

RogueTcpStreamWrap uses normal AxiStream flow control with AxiStreamSlave. PGP blocks use PAUSE based flow control with AxiStreamCtrl for RX streams

This means you'll probably have to do something like this:

U_SRPv3 : entity work.SrpV3AxiLite
   generic map (
      TPD_G               => TPD_G,
      SLAVE_READY_EN_G    => SIMULATION_G, -- Use READY when in SIMULATION mode
      GEN_SYNC_FIFO_G     => false,
      AXI_STREAM_CONFIG_G => AXIS_CONFIG_C)
   port map (
      -- Streaming Slave (Rx) Interface (sAxisClk domain) 
      sAxisClk         => pgpClk,
      sAxisRst         => pgpRst,
      sAxisMaster      => rxMasters(0),
      sAxisSlave       => rxSlaves(0),
      sAxisCtrl        => rxCtrl(0),
      -- Streaming Master (Tx) Data Interface (mAxisClk domain)
      mAxisClk         => pgpClk,
      mAxisRst         => pgpRst,
      mAxisMaster      => txMasters(0),
      mAxisSlave       => txSlaves(0),
      -- AXI Lite Bus (axilClk domain)
      axilClk          => axilClk,
      axilRst          => axilRst,
      mAxilReadMaster  => mAxilReadMaster,
      mAxilReadSlave   => mAxilReadSlave,
      mAxilWriteMaster => mAxilWriteMaster,
      mAxilWriteSlave  => mAxilWriteSlave);

Note that SLAVE_READY_EN_G must be set to True when compiling for simulation.

Instantiate StreamSim in Software

The class pyrogue.interfaces.simulation.StreamSim is a Rogue Stream Master+Slave. You can instantiate and use it in place of pyrogue.protocols.UdpRssiPack or rogue.hardware.pgp.PgpCard.

Example:

 if mode == "SIM":
     dest0 = rogue.interfaces.stream.TcpClient('localhost',9000)
     dest1 = rogue.interfaces.stream.TcpClient('localhost',9002)
 
 elif mode == "HW":
     udp = pyrogue.protocols.UdpRssiPack( host='192.168.1.10', port=8192, packVer=2 )                
     dest0 = udp.application(dest=0)
     dest1 = udp.application(dest=1)

Note that each RogueTcpStream connection takes 2 TCP ports: PORT_NUM_G & PORT_NUM_G + 1

Build and run your firmware with VCS

First, you'll need to setup the Vivado and VCS environment if you haven't already:

> source /afs/slac/g/reseng/xilinx/vivado_2018.3/Vivado/2018.3/settings64.sh
> source /afs/slac/g/reseng/synopsys/vcs-mx/M-2017.03-1/settings.sh
> source /afs/slac/g/reseng/zeromq/4.2.0/settings.sh

Your firmware target will need to specify the top level testbench module in your design. This is done in the targets/TargetName/vivado/sources.tcl file:

set_property top "TopLevelTestbenchModuleName" [get_filesets sim_1]

Then make your firmware with VCS

> cd firmware/targets/TargetName
> make vcs

What make vcs does is build VCS project **makefiles **based on your Vivado project hierarchy. When make vcs is done it will give you instructions on how to proceed:

********************************************************
The VCS simulation script has been generated.
To compile and run the simulation:
	$ cd /path/to/build/target/$TargetName_project.sim/sim_1/behav/
	$ ./sim_vcs_mx.sh
	$ source setup_env.sh
	$ ./simv -gui&
********************************************************

Now source the environment file and run vcs:

> source setup_env.sh
> ./simv -gui&

This will launch the GUI. You can drag whatever you want to see into the waveform viewer then start the simulation running.

Run the software

In a separate terminal, launch your Rogue GUI or script that uses rogue.interfaces.stream.TcpClient. It should act on the running VCS sim.

Contact

Ben Reese

[email protected]