-
Notifications
You must be signed in to change notification settings - Fork 31
Workflow Overview
This page describes the following aspects of the P4->NetFPGA workflow:
- SimpleSumeSwitch Architecture
- Xilinx P4-SDNet
- Workflow Steps
- Writing P4 Programs
- Testing P4 Programs
- Debugging P4 Programs
- P4->NetFPGA Extern Library
- API / CLI
- Limitations
- FAQ
- SUME Event Switch Architecture
The SimpleSumeSwitch is the P4 architecture that is currently defined for the NetFPGA SUME. See here for a description of the SimpleSumeSwitch architecture for releases 1.2.1 and earlier. See the release notes for a description of the key changes made to the architecture. The architecture definition can be found in /opt/Xilinx/SDNet/<version_number>/data/p4include/sume_switch.p4
or wherever you have installed Xilinx SDNet. The architecture consists of a single parser, single match-action pipeline, and single deparser. As shown below:
- sume_metadata: corresponds to the tuser bus in the SUME reference_switch design, it is defined as follows:
struct sume_metadata_t {
bit<16> dma_q_size; // measured in 32-byte words
bit<16> nf3_q_size; // measured in 32-byte words
bit<16> nf2_q_size; // measured in 32-byte words
bit<16> nf1_q_size; // measured in 32-byte words
bit<16> nf0_q_size; // measured in 32-byte words
bit<8> send_dig_to_cpu; // send digest_data to CPU
bit<8> drop; // * DEPRECATED *
port_t dst_port; // one-hot encoded (see below)
port_t src_port; // one-hot encoded (see below)
bit<16> pkt_len; // (bytes) unsigned int
}
The format of the dst_port and src_port fields is as follows:
bit-7 bit-6 bit-5 bit-4 bit-3 bit-2 bit-1 bit-0
(nf3_dma)-(nf3_phy)-(nf2_dma)-(nf2_phy)-(nf1_dma)-(nf1_phy)-(nf0_dma)-(nf0_phy)
-
pkt_len
- the size of the packet (not including the Ethernet preamble or FCS) in bytes. -
src_port
- the port on which the packet arrived. For example, if the packet arrived on port nf1 this field would be set to 0b00000100. -
dst_port
- should be set by the user's P4 program to indicate which port or ports (if any) the packet should be sent out of. For example, to send a copy the packet out of both ports nf0 and nf2 this field should be set to 0b00010001. -
drop
- this field is now deprecated and will be remove in a future version. To drop a packet setdst_port
= 0. -
send_dig_to_cpu
- set the least significant bit of this field to send thedigest_data
to the CPU. If this bit is set and a packet is to be forwarded to the CPU then thedigest_data
will be prepended to the packet. Otherwise, only thedigest_data
will be sent over DMA. -
_q_size
- the size of each output queue, measured in terms of 32-byte words (rounded up). This is the size of the output queues when the packet starts being processed by the P4 program. -
digest_data: the format of this bus is defined by the P4 programmer. The only constraint is that it must be defined to be 256 bits wide. This data can optionally be prepended to the packet when it is sent over DMA to the CPU by setting the
send_dig_to_cpu
bit. -
user_metadata: the format of this bus is also defined by the P4 programmer. It can be used to pass additional information between the parser, the M/A pipeline, and the deparser.
-
in/out control: these signals are used to add/remove entries from tables and read/write control registers.
The Xilinx P4-SDNet toolchain creates an HDL module, which is then wrapped in a small wrapper and inserted into the NetFPGA SUME reference switch architecture, as indicated by the image below.
The Xilinx P4-SDNet compiler is the centerpiece of the P4->NetFPGA workflow. It compiles P4 programs that target the SimpleSumeSwitch architecture into a single HDL module that has standard AXI-Stream packet interfaces and an AXI-Lite control interface. The SDNet output is engineered for 100G rates so is able to easily handle the aggregate 40G rate in the SUME reference switch design. See here for more information about the Xilinx SDNet tools.
-
Modify
$SUME_FOLDER/tools/settings.sh
to ensure that theP4_PROJECT_NAME
environment variable is set to the name of the project you would like to work on. Run$ source settings.sh
-
Write your P4 program and commands.txt - the
commands.txt
file allows you to add entries to tables you have defined in your P4 program. -
Write gen_testdata.py
-
Run the P4-SDNet compiler to generate the resulting HDL and an initial simulation framework:
$ cd $P4_PROJECT_DIR && make
-
Run the SDNet simulation:
$ cd $P4_PROJECT_DIR/nf_sume_sdnet_ip/SimpleSumeSwitch
$ ./vivado_sim.bash
.Note: you may also run
vivado_sim_waveform.bash
if you would like to fire up the Vivado GUI and see the HDL waveforms (this is a very useful debugging tool).If this simulation passes great! If it does not you will need to modify either your P4 program or your
gen_testdata.py
script. -
Generate the scripts that can be used in the NetFPGA SUME simulations to configure the table entries.
$ cd $P4_PROJECT_DIR
$ make config_writes
-
Wrap SDNet output in wrapper module and install as a SUME library core:
$ cd $P4_PROJECT_DIR
$ make uninstall_sdnet && make install_sdnet
-
Set up the SUME simulation. The
$NF_DESIGN_DIR/test/sim_switch_default
directory contains therun.py
script which is responsible for running a SUME simulation, check it out. You can find more information on writing theserun.py
scripts here. You will see that it reads the test packets generated by thegen_testdata.py
script in step 3 and applies the packets to SUME interfaces. All we need to do here is copy theconfig_writes.py
script generated in step 6 into this directory.$ cd $NF_DESIGN_DIR/test/sim_switch_default && make
-
Run the SUME simulation:
$ cd $SUME_FOLDER
$ ./tools/scripts/nf_test.py sim --major switch --minor default
Note: you may also run the above command with the
--gui
option to fire up the Vivado GUI and see the HDL waveforms. Again, a very useful debugging tool. -
Compile the bitstream:
$ cd $NF_DESIGN_DIR && make
-
Check to make sure the design meets the timing requirements. See this FAQ to see how to do this.
-
Program the FPGA. Copy the
config_writes.sh
script into the$NF_DESIGN_DIR/bitfiles
directory.$ cd $NF_DESIGN_DIR/bitfiles
$ mv simple_sume_switch.bit ${P4_PROJECT_NAME}.bit
$ cp $P4_PROJECT_DIR/testdata/config_writes.sh ./
$ sudo bash
# bash program_switch.sh
Note: Make sure that the configuration writes all succeed. If this is the first time programming the FPGA since the machine was last powered off it may need to be rebooted.
-
Test the design on real hardware! Go to the
$ P4_PROJECT_DIR/sw/CLI
directory and run theP4_SWITCH_CLI.py
script. This initiates an interactive command line interface that you can use to interact with your switch (i.e. read/write registers, add/remove table entries, etc.). Typehelp
to see the list of available commands. The tutorial assignments include hardware testing tools located at$P4_PROJECT_DIR/sw/hw_test_tool
. Refer to the tutorials page for a description of usage.
This repository currently supports the Xilinx P4_16 frontend compiler. See here for a link to the current standard for the P4_16 language. Also go to P4.org for more information about the open source P4 language consortium.
Xilinx P4-SDNet specifies a few additional annotations that can be used in P4 programs:
-
@Xilinx_MaxPacketRegion()
- for parser/deparser; declares the largest packet size (in bits) the parser/deparser needs to support. -
@Xilinx_MaxLatency()
- for externs; the maximum number of clock cycles an extern function needs to complete. -
@Xilinx_ControlWidth()
- for externs; the size in bits of the address space to allocate to an extern function. -
@Xilinx_ExternallyConnected()
- for tables; pulls the table's request and response tuples to the top level of the design
See the section "P4->NetFPGA Extern Library" for more information about using and writing extern functions.
Table Types: There are 3 types of tables that can be used in P4 programs:
-
exact
- match exactly on the specified header or metadata field then perform the desired action. Can specify multiple keys to match on. -
ternary
- match exactly on some desired subset of the specified keys. -
lpm
- match on the entry in the table that shares the longest prefix match with the specified key. Can only specify one key.
Commands.txt: This is the file in the $P4_PROJECT_DIR/src/ directory that contains commands used to populate table entries. Below is the format of the commands used to populate table entries in each type of table:
Table Type | Command |
---|---|
exact |
table_cam_add_entry <table_name> <action_name> <keys (space separated)> => <action_data (space separated)> |
ternary |
table_tcam_add_entry <table_name> <entry_address> <action_name> <key1/mask1 ... keyN/maskN> => <action_data (space separated)> |
lpm |
table_lpm_add_entry <table_name> <action_name> <key>/<prefix_length> => <action_data (space separated)> |
The commands listed above are currently the only ones supported by the commands.txt file.
NOTE: when working with lpm
tables the SDNet compiler will generate a bash script (i.e. create_ip_forward.bash
) which must be run before launching the SDNet simulation.
Test your P4 program by writing a gen_testdata.py
script in the $P4_PROJECT_DIR/testdata directory. The gen_testdata.py
script makes heavy use of the python scapy module. Scapy is a very convenient and easy to use packet manipulation library. It allows you to define arbitrary packets and even define your own header types (see switch_calc_headers.py
for an example). The gen_testdata.py
script must generate:
-
src.pcap
- the packets to feed through the P4 switch -
dst.pcap
- the packets to expect at the output of the P4 switch -
Tuples_in.txt
- the metadata associated with each packet insrc.pcap
-
Tuples_expect.txt
- the metadata associated with each packet indst.pcap
The files listed above are used in the initial SDNet simulation. The file $P4_PROJECT_DIR/testdata/sss_sdnet_tuples.py
can be used to facilitate creation of the Tuples_in.txt
and Tuples_expect.txt
files for projects that target the SimpleSumeSwitch architecture. For each packet, update sume_tuple_in
, dig_tuple_in
, sume_tuple_expect
, and dig_tuple_expect
and subsequently call write_tuples()
to add a line to the Tuples_*.txt
files.
It is recommended that the gen_testdata.py
script also generate:
-
nf0_applied.pcap
...nf3_applied.pcap
-
nf0_expected.pcap
...nf3_expected.pcap
These are files that can be used in the SUME simulations. The script should also set the time field for each applied packet so that they can be applied in the correct order for the SUME simulation.
The ${NF_DESIGN_DIR}/test/sim_switch_default/run.py
script runs a SUME simulation. It may make use of the packet traces generated by the gen_tesdata.py
script or it may create new packets and use those. See here for more details about writing the run.py
script.
If you do enough P4 development, chances are you will need to do debugging at some point. This section is meant to provide you with some debugging tips.
SDNet produces two implementations of your P4 program: an HDL implementation and a C++ model. Running the C++ model is useful for a couple of reasons: (1) it produces very verbose information about how packets are being processed, and (2) it produces a PCAP file that contains the expected output packets of the simulation Packets_expected.pcap
. To generate and run the C++ model do the following:
$ cd $P4_PROJECT_DIR && make cpp_test
$ cd nf_sume_sdnet_ip/SimpleSumeSwitch/SimpleSumeSwitch.TB/
$ ./compile.bash
$ ./SimpleSumeSwitch
The resulting PCAP file is called Packet_expect.pcap
and can be compared to the dst.pcap
file produced by your gen_testdata.py
script. Running The C++ model produces very verbose output that describes how the packets are processed. For example, you can see how metadata fields are modified throughout the design as well as whether of not there are hits or misses in the tables you've defined.
Once you are sure that the Packet_expect.pcap
file matches the dst.pcap
file you can run the SDNet simulation comparing the HDL implementation output to the packets in dst.pcap
and the expected metadata in Tuple_expect.txt
:
$ cd $P4_PROJECT_DIR && make
$ cd nf_sume_sdnet_ip/SimpleSumeSwitch/
$ ./vivado_sim.bash
If running this simulation results in a metadata error (i.e. a mismatch between expected and actual tuples) you can easily check which fields do not match:
$ ./vivado_sim.bash
...
expected < tuple_out_sume_metadata > = < 00000000000000000000000100040041 >
actual < tuple_out_sume_metadata > = < 00000000000000000000000100040040 >
...
$ $P4_PROJECT_DIR/testdata/sss_sdnet_tuples.py --parse 00000000000000000000000100040041 sume
Parsed Tuple:
-----------------------
dma_q_size = 0
nf3_q_size = 0
nf2_q_size = 0
nf1_q_size = 0
nf0_q_size = 0
send_dig_to_cpu = 0
drop = 1
dst_port = 00000000
src_port = 00000100
pkt_len = 65
What to do if SDNet simulation passes but SUME simulation fails?
If you run into this issue I would suggest checking a few things:
- Make sure that you have run:
$ cd $P4_PROJECT_DIR && make config_writes
$ cd $NF_DESIGN_DIR/test/sim_<major>_<minor> && make
$ cd $P4_PROJECT_DIR && make install_sdnet
- Note that the order in which packets are received matters. If the packets in your
nf_*_expected.pcap
files contain packets that in a different order than the actual received packets this will result in a failed simulation. - Run SUME simulation for longer - This may be the problem if you see all of the expected packets have not arrived.
- Make sure all configuration writes have completed before applying the test packets.
- To check the actual and expected packets for the SUME simulation check
$NF_DESIGN_DIR/test/nf_*_expected.axi
and$NF_DESIGN_DIR/test/nf_*_logged.axi
. - Add signals to simulation waveform by adding to bottom of
$NF_DESIGN_DIR/hw/tcl/simple_sume_switch_sim.tcl
and running the SUME simulation with the--gui
option.
Extern functions are designed to allow P4 programers to utilize custom logic in their P4 programs. For the NetFPGA platform, these extern functions must be implemented in HDL (or perhaps some high-level language that generates HDL). In an effort to abstract away the HDL details from the P4 developer, the P4->NetFPGA workflow provides a library of extern functions that can be used in P4 programs. The stateful atomic externs are inspired by the Domino atoms. The following tables describes the currently supported extern functions:
Stateful Atomic Extern Functions
Name | Description |
---|---|
RW | Read or write state |
RAW | Read, add to, or overwrite state |
PRAW | Either perform RAW or don't perform RAW based on predicate |
ifElseRAW | Two RAWs, one each for when a predicate is true or false |
Sub | IfElseRAW with stateful subtraction capability |
Bloom | Bloom filter |
IMPORTANT: each stateful atom (i.e. register) can only be accessed one time in the P4 code. Multiple calls to the extern function will generate multiple instances of the atom and you will likely get unexpected results.
NOTE: If you try to define a stateful atom that requires more than 32Kbit of state (one BRAM tile on the FPGA) then you will likely run into timing issues using the provided implementations.
Stateless Extern Functions
Name | Description |
---|---|
IP Checksum | Given an IP header, compute the IP checksum |
LRC | longitudinal redundancy check, simple hash function |
timestamp | generate timestamp (measure in clock cycles, granularity of 5ns) |
Adding new extern functions:
It is very easy to add new extern functions to the workflow. Implement the extern function and simply add an entry to the ${SUME_SDNET}/bin/extern_data.py file. Each entry is a python dictionary with two keys:
- "template_file" - specifies the path to the extern function template relative to the ${SUME_SDNET}/templates directory.
- "replacements" - a python dictionary that specifies patterns to replace in template file and what to replace the patterns with. The supported commands are:
Command | Description |
---|---|
"module_name" | The name of the module. This is determined by the P4-SDNet compiler and so must be replaced in the template file. |
"extern_name" | The full name of the extern function. This is also determined by the P4-SDNet compiler and so must be replaced in the template file. |
"prefix_name" | The name given to the extern function by the P4 programmer. For example, for an extern function called pktCnt_reg_raw the "prefix_name" would be called pktCnt . |
"addr_width" | The size (in bits) of the address space allocated to the extern function. Specified by the P4 programmer using the @Xilinx_ControlWidth annotation. |
"input_width(field)" | The width (in bits) of a particular input field. |
"output_width(field)" | The width (in bits) of a particular output field. |
If a P4 program instantiates an extern function with a control width greater than 0 the P4->NetFPGA tools will automatically generate a <prefix_name>_cpu_regs
module that can be used in the extern module. It is designed to make it easy to expose control registers using the AXI-Lite interface.
Externs must be pipelined: P4 may input data in any cycle, not only after the previous computation has finished. In addition to the reset, clock, input, and output signals, there is also an extra input bit valid_in
and an extra output bit valid_out
. The valid_in
bit will be high when we have valid data to compute with (i.e. if it is not set, we can ignore that input). The valid_out
bit should be set whenever the result of a valid input (i.e. of data that was input when valid_in
was set) is ready -- this bit signals to P4 that it can take the data and resume execution of the caller pipeline.
Users that implement new extern functions are highly encouraged to contribute them to the P4->NetFPGA project so others can use them as well.
Both a python and C API are generated by the workflow and and can be used to manipulate the registers and tables instantiated in the P4 program. The C API is generated directly by P4-SDNet and the files are copied into the ${P4_PROJECT_DIR}/sw/API
directory. The python API is simply a wrapper around these C API functions to make it easy for developers to write python programs to control their switch designs. The python API files are called p4_tables_api.py
and p4_regs_api.py
and reside inside the ${P4_PROJECT_DIR}/sw/CLI
directory.
The tools generate an interactive command line environment that can be used to query compile time information about the generated P4 design, as well as interact with the physical switch when it is loaded onto the FPGA. Run: $ ./P4_SWITCH_CLI.py
to enter the environment, type help
to see a list of commands and their documentation.
-
lpm
tables are not well supported in SDNet. We recommend you useternary
tables instead. -
Registers that are accessed from the control plane must be limited to 32-bits wide. As this is the width of the SUME control data bus.
-
All P4 designs must have at least one table or extern function with a control interface. This is because the HDL wrapper module currently assumes the SimpleSumeSwitch module will have an AXI-Lite control interface.
-
See the github repo issues page for more issues.
Language Feature | Notes |
---|---|
error type |
Unsupported, use custom metadata fields instead |
varbit<n> |
Unsupported, for variable length bit strings |
Language Feature | Notes |
---|---|
tuple type |
Partial support, syntax: tuple<bit<>, bit<>>
|
extern objects |
Only packet_in , packet_out , packet_mod ; extern functions are supported |
Language Feature | Notes |
---|---|
On error types |
Because error type is not supported |
On varibit types |
Because varbit type is not supported |
tuples of sets | Unsupported |
Language Feature | Notes |
---|---|
division |
/ operator, only allowed if it evaluates to a constant at compile time |
modulo |
% operator, only allowed if it evaluates to a constant at compile time |
Language Feature | Notes |
---|---|
multiplication |
* operator, at least one operand must be constant power of 2 |
Language Feature | Notes |
---|---|
Shift right |
>> operator, only for unsigned on LHS |
Language Feature | Notes |
---|---|
return |
Unsupported, exit statement is supported |
Language Feature | Notes |
---|---|
Extern method invocation | Unsupported, expect for packet_in extern methods |
verify |
Unsupported, used for errors |
packet_in.extract(header, size) |
Unsupported, used for varbit
|
packet_in.length |
Unsupported, use sume_metadata.pkt_len
|
Language Feature | Notes |
---|---|
Mixed table match types | All table match types must be the same |
Static table entries | Unsupported, entries must be populated by control-plane |
Extern function invocations | Not allowed in parser or deparser, can only be invoked directly in control block apply{} statement |
Language Feature | Notes |
---|---|
@name |
Unsupported, used for control API to enforce user names |
@atomic |
Unsupported |
See this page for a set of frequently asked questions.
As part of an on-going research project, we've developed a new P4 programmable architecture for the NetFPGA SUME: the "SUME Event Switch". The SUME Event Switch is similar to the SimpleSumeSwitch is many ways. In particular, you still describe the functionality of a parser, match-action pipeline, and deparser by writing a single P4 program. The key difference lies in the events that trigger the pipeline to execute. In the SimpleSumeSwitch, the only event that could trigger the pipeline to execute was an ingress packet arrival. In the SUME Event Switch, your P4 program will now be executed on all of the following data-plane events:
- Ingress Packet Arrival
- Generated Packet Arrival
- Packet Enqueued into an output queue
- Packet Dropped from an output queue (buffer overflow)
- Packet Dequeued from an output queue
- Configurable timer expires
- Link status changes
Below is a block diagram of the SUME Event Switch Architecture:
Recall that the SDNet Pipeline is the HDL implementation of your P4 program. The Event Merger module is responsible for aggregating all simultaneous events into a single "packet" and forwarding the result to the SDNet pipeline. I say "packet" because if there are no ingress packet events then the Event Merger module will generate "ghost packets" with the metadata fields listed below. Ghost packets cannot be forwarded out of the ports, they will always be dropped at the output queues. That being said, a ghost packet can tell the Packet Generator module to generate a packet, which can be forwarded out of the switch.
Every packet that enters the SDNet pipeline comes with the following metadata fields that you can access in your P4 program:
struct sume_metadata_t {
// request a packet to be generated
bit<1> gen_packet;
// *_trigger fields indicate when a particular event has fired
bit<1> link_trigger;
bit<1> timer_trigger;
bit<1> drop_trigger;
bit<1> deq_trigger;
bit<1> enq_trigger;
bit<1> pkt_trigger;
// Current link status (one-hot)
bit<4> link_status;
// time when timer event fired (20ns resolution)
bit<48> timer_now;
// period at which timer events are configured to fire (20ns resolution)
bit<32> timer_period;
// ports and user metadata for enq/deq/drop events
port_t drop_port;
port_t deq_port;
port_t enq_port;
bit<32> drop_data;
bit<32> deq_data;
bit<32> enq_data;
// standard metadata fields
port_t dst_port;
port_t src_port;
bit<16> pkt_len;
}
Here is a more detailed description of the above metadata fields:
-
gen_packet
- if this bit is set by the P4 program then the Packet Generator module will generate one 64B packet with an etherType field value of0x2121
, all other fields have a value of 0. -
link_trigger
- this bit will be set when one or more links have changed their status (e.g. cable has been unplugged). -
timer_trigger
- this bit will be set if the timer has expired. -
drop_trigger
- this bit will be set whenever a packet is dropped at an output queue as a result of of overflow. -
deq_trigger
- this bit will be set whenever a packet is dequeued from an output queue. -
enq_trigger
- this bit will be set whenever a packet is enqueued into and output queue. -
pkt_trigger
- this bit will be set whenever there is a legitimate packet attached to this thread of execution. -
link_status
- the current link status, one-hot encoded where 1 indicates the link is up and 0 indicates the link is down. The most significant bit corresponds to nf3 and the least significant bit corresponds to nf0. -
timer_now
- the time when the timer event last fired, measured in increments of 20ns. -
timer_period
- the period at which the timer events should fire, measured in increments of 20ns. Initialized to 0 by default, meaning that the timer events should never fire. This can be changed by the P4 program. -
drop_port
- if thedrop_trigger
field is set then this field indicates the output port(s) that dropped the packet, uses the same format as thedst_port
field. -
deq_port
- if thedeq_trigger
field is set then this field indicates the port that just dequeued a packet for transmission, uses the same format as thedst_port
field. -
enq_port
- if theenq_trigger
field is set then this field indicates the port that just enqueued a packet, uses the same format as thedst_port
field. -
drop_data
,deq_data
, andenq_data
- these are intended to be user defined metadata fields. They serve a dual purpose: (1) whenever a dequeue, drop, or enqueue event fires, the corresponding field will contain the metadata that correponds to the packet that was just dequeued, dropped, or enqueued; (2) the P4 program should overwrite these fields at the end of the pipeline to prepare the current packet for enqueue, drop, and dequeue. -
pkt_len
,src_port
,dst_port
- the fields have the same functionality as they do in the SimpleSumeSwitch architecture.
We've also added support for a new extern called reg_multi_raws
that allows P4 programs to perform up to 3 read-modify-write (RMW) operations on a single BRAM-based register array. Only one of the RMW operations is guaranteed to be performed immediately (because that's all that fits in a single 64B packet time @ 40Gbps), the other two RMW requests are queued and will be performed by the extern whenever it finds spare cycles. If the min size packet is 150B then all 3 RMW operations will be performed atomically for each packet.
The general process of setting up and running smiulations for P4 programs that are written for the SUME Event Switch architecture is the same as it is for the SimpleSumeSwitch architecture, with a few minor differences.
The gen_testdata.py
script can only be used to test the functionality of the SDNet pipeline within the architecture. This makes it challenging to use it to test programs that use the various events generated by other blocks in the architecture. Here are some recommendations for testing SUME Event Switch programs:
- The Workflow Steps are still exactly the same, but now your effort will shift from step 3 (writing
gen_testdata.py
) to step 8 (setting up the SUME simulation). - You do still need to write a
gen_testdata.py
script that generates at least one applied/expected packet/metadata, but these tests do not need to be comprehensive. The reason for this is because the SDNet simulation generates the configuration writes to populate table entries, which are reused in the SUME simulation. - Once you reach step 8 in the workflow steps, you'll want to write your own
run.py
script(s). Yourrun.py
script should generate the set of packets you want to send through the switch and configure their injection timestamps andtuser_sport
fields. Therun.py
script can also read/write registers within your P4 program. See the sim_switch_2flows example within the fred_basic project. Here is some more information about writing theserun.py
scripts. - After running the SUME simulation as indicated in step 9 of the workflow steps, you'll see that the
$NF_DESIGN_DIR/test
directory has been populated with files that contain the expected and logged packets on each port (in AXI grammar format). These are very useful files for debugging purposes. For example, thenf_interface_1_log.axi
might look like:
*3082
000a0100000ac966004000000100320000450008010000000008020000000008, ffffffff, 00000000000000000000000004010040, # 12576 ns
0000000000000000000000000000000000000000000000000000000000000200, ffffffff, 00000000000000000000000004010040. # 12580 ns
*84
000a0100000ac966004000000100320000450008010000000008020000000008, ffffffff, 00000000000000000000000004010040, # 12920 ns
0000000000000000000000000000000000000000000000000000000000000200, ffffffff, 00000000000000000000000004010040. # 12924 ns
- You can also run the SUME simulations using the
--gui
option to view the simulation waveforms within a Vivado GUI, which can also be a useful way of debugging. For example,$ cd $SUME_FOLDER && ./tools/scripts/nf_test.py sim --major switch --minor 2flows --gui