From 4c003c25e03ed27edd8d218959bf4608e99c9049 Mon Sep 17 00:00:00 2001 From: Yuta Date: Wed, 18 Aug 2021 23:22:41 +0900 Subject: [PATCH] move from initial repo to here --- .gitignore | 51 + .gitmodules | 6 + APACHE-LICENSE-2.0.txt | 202 ++++ Makefile | 188 ++++ NetFPGA-CIC-LICENSE.md | 6 + README | 39 + hw/contrib-projects/.keep | 0 hw/lib/common/constraints/Makefile | 50 + hw/lib/common/constraints/au200_general.xdc | 166 +++ .../constraints/au200_vcu1525_timing.tcl | 32 + hw/lib/common/constraints/au250_general.xdc | 166 +++ hw/lib/common/constraints/au280_general.xdc | 108 ++ hw/lib/common/constraints/nf_timing.tcl | 29 + hw/lib/common/constraints/vcu1525_general.xdc | 163 +++ hw/lib/common/hdl/nf_attachment.sv | 651 ++++++++++++ hw/lib/common/hdl/top.v | 514 ++++++++++ hw/lib/common/hdl/top_wrapper.sv | 486 +++++++++ .../nf_endianess_manager_v1_0_0/Makefile | 32 + .../nf_endianess_manager_v1_0_0/hdl/bridge.v | 105 ++ .../hdl/nf_endianess_manager.v | 132 +++ .../nf_endianess_manager.tcl | 111 ++ hw/lib/std/axi_sim_transactor_v1_0_0/Makefile | 33 + .../axi_sim_transactor.tcl | 87 ++ .../hdl/axi_sim_transactor.vhd | 555 ++++++++++ .../hdl/transactor_fifos.vhd | 276 +++++ hw/lib/std/axis_fifo_v1_0_0/Makefile | 32 + hw/lib/std/axis_fifo_v1_0_0/axis_fifo.tcl | 93 ++ hw/lib/std/axis_fifo_v1_0_0/hdl/axis_fifo.v | 253 +++++ hw/lib/std/axis_sim_pkg_v1_0_0/Makefile | 34 + .../std/axis_sim_pkg_v1_0_0/axis_sim_pkg.tcl | 70 ++ .../axis_sim_pkg_v1_0_0/hdl/axis_sim_pkg.vhd | 196 ++++ hw/lib/std/axis_sim_record_v1_0_0/Makefile | 33 + .../axis_sim_record.tcl | 73 ++ .../hdl/axis_sim_record.v | 116 +++ hw/lib/std/axis_sim_stim_v1_0_0/Makefile | 33 + .../axis_sim_stim_v1_0_0/axis_sim_stim.tcl | 70 ++ .../hdl/axis_sim_stim.vhd | 274 +++++ hw/lib/std/barrier_v1_0_0/Makefile | 33 + hw/lib/std/barrier_v1_0_0/barrier.tcl | 65 ++ hw/lib/std/barrier_v1_0_0/hdl/barrier.v | 140 +++ .../fallthrough_small_fifo_v1_0_0/Makefile | 32 + .../fallthrough_small_fifo.tcl | 95 ++ .../hdl/fallthrough_small_fifo.v | 128 +++ .../hdl/small_fifo.v | 124 +++ hw/lib/std/input_arbiter_v1_0_0/Makefile | 33 + .../data/input_arbiter_regs_defines.h | 59 ++ .../data/input_arbiter_regs_defines.tcl | 56 + .../data/input_arbiter_regs_defines.txt | 56 + .../data/module_generation_Input_arbiter.xlsm | Bin 0 -> 39747 bytes .../input_arbiter_v1_0_0/hdl/input_arbiter.v | 385 +++++++ .../hdl/input_arbiter_cpu_regs.v | 440 ++++++++ .../hdl/input_arbiter_cpu_regs_defines.v | 72 ++ .../input_arbiter_v1_0_0/input_arbiter.tcl | 133 +++ hw/lib/std/nf_axis_converter_v1_0_0/Makefile | 32 + .../hdl/nf_axis_converter.v | 159 +++ .../hdl/nf_axis_converter_main.v | 681 +++++++++++++ .../nf_axis_converter.tcl | 155 +++ hw/lib/std/nf_mac_attachment_v1_0_0/Makefile | 30 + .../nf_mac_attachment_v1_0_0/hdl/data_synch.v | 50 + .../hdl/nf_mac_attachment.v | 496 +++++++++ .../hdl/nf_mac_attachment_cpu_regs.v | 518 ++++++++++ .../hdl/nf_mac_attachment_cpu_regs_defines.v | 85 ++ .../nf_mac_attachment_v1_0_0/hdl/rx_queue.v | 190 ++++ .../nf_mac_attachment_v1_0_0/hdl/tx_queue.v | 269 +++++ .../nf_mac_attachment_tcl.tcl | 238 +++++ .../nic_output_port_lookup_v1_0_0/Makefile | 32 + .../data/module_generation_nic_opl.xlsm | Bin 0 -> 39697 bytes .../data/output_port_lookup_regs_defines.h | 59 ++ .../data/output_port_lookup_regs_defines.tcl | 56 + .../data/output_port_lookup_regs_defines.txt | 56 + .../hdl/nic_output_port_lookup.v | 308 ++++++ .../hdl/output_port_lookup_cpu_regs.v | 438 ++++++++ .../hdl/output_port_lookup_cpu_regs_defines.v | 73 ++ .../nic_output_port_lookup.tcl | 141 +++ hw/lib/std/output_queues_v1_0_0/Makefile | 33 + .../data/module_generation_output_queues.xlsm | Bin 0 -> 46069 bytes .../data/output_queues_regs_defines.h | 143 +++ .../data/output_queues_regs_defines.tcl | 119 +++ .../data/output_queues_regs_defines.txt | 119 +++ .../output_queues_v1_0_0/hdl/output_queues.v | 656 ++++++++++++ .../hdl/output_queues_cpu_regs.v | 824 +++++++++++++++ .../hdl/output_queues_cpu_regs_defines.v | 248 +++++ .../output_queues_v1_0_0/output_queues.tcl | 146 +++ .../router_output_port_lookup_v1_0_0/Makefile | 32 + .../data/output_port_lookup_regs_defines.h | 148 +++ .../data/output_port_lookup_regs_defines.tcl | 145 +++ .../data/output_port_lookup_regs_defines.txt | 145 +++ .../hdl/dest_ip_filter.v | 361 +++++++ .../hdl/eth_parser.v | 312 ++++++ .../hdl/ip_arp.v | 246 +++++ .../hdl/ip_checksum_ttl.v | 376 +++++++ .../hdl/ip_lpm.v | 338 +++++++ .../hdl/op_lut_hdr_parser.v | 198 ++++ .../hdl/op_lut_process_sm.v | 338 +++++++ .../hdl/output_port_lookup.v | 555 ++++++++++ .../hdl/output_port_lookup_cpu_regs.v | 956 ++++++++++++++++++ .../hdl/output_port_lookup_cpu_regs_defines.v | 225 +++++ .../hdl/preprocess_control.v | 161 +++ .../hdl/router_output_port_lookup.v | 562 ++++++++++ .../hdl/unencoded_cam_lut_sm.v | 225 +++++ .../router_output_port_lookup.tcl | 166 +++ .../Makefile | 33 + .../data/module_generation_switch_opl.xlsm | Bin 0 -> 39968 bytes .../data/output_port_lookup_regs_defines.h | 65 ++ .../data/output_port_lookup_regs_defines.tcl | 62 ++ .../data/output_port_lookup_regs_defines.txt | 62 ++ .../hdl/eth_parser.v | 144 +++ .../hdl/mac_cam_lut.v | 178 ++++ .../hdl/output_port_lookup_cpu_regs.v | 460 +++++++++ .../hdl/output_port_lookup_cpu_regs_defines.v | 83 ++ .../hdl/switch_lite_output_port_lookup.v | 404 ++++++++ .../switch_lite_output_port_lookup.tcl | 161 +++ .../switch_output_port_lookup_v1_0_1/Makefile | 32 + .../data/module_generation_switch_opl.xlsm | Bin 0 -> 39968 bytes .../data/output_port_lookup_regs_defines.h | 65 ++ .../data/output_port_lookup_regs_defines.tcl | 62 ++ .../data/output_port_lookup_regs_defines.txt | 62 ++ .../hdl/eth_parser.v | 144 +++ .../hdl/mac_cam_lut.v | 355 +++++++ .../hdl/output_port_lookup_cpu_regs.v | 461 +++++++++ .../hdl/output_port_lookup_cpu_regs_defines.v | 83 ++ .../hdl/switch_output_port_lookup.v | 407 ++++++++ .../switch_output_port_lookup.tcl | 153 +++ hw/lib/xilinx/cam_v1_1_0/Makefile | 44 + hw/lib/xilinx/cam_v1_1_0/README | 43 + hw/lib/xilinx/cam_v1_1_0/cam.tcl | 113 +++ hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam.v | 70 ++ .../cam_v1_1_0/hdl/verilog/cam_wrapper.v | 85 ++ hw/lib/xilinx/cam_v1_1_0/hdl/vhdl/cam/.keep | 0 .../cam_v1_1_0/scripts/run_update_lib.sh | 42 + hw/lib/xilinx/tcam_v1_1_0/Makefile | 43 + hw/lib/xilinx/tcam_v1_1_0/README | 43 + hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam.v | 73 ++ .../tcam_v1_1_0/hdl/verilog/tcam_wrapper.v | 87 ++ hw/lib/xilinx/tcam_v1_1_0/hdl/vhdl/tcam/.keep | 0 .../tcam_v1_1_0/scripts/run_update_lib.sh | 41 + hw/lib/xilinx/tcam_v1_1_0/sim/run_sim.tcl | 31 + hw/lib/xilinx/tcam_v1_1_0/sim/run_tcam_sim.sh | 62 ++ hw/lib/xilinx/tcam_v1_1_0/sim/testbench.v | 243 +++++ hw/lib/xilinx/tcam_v1_1_0/tcam.tcl | 92 ++ hw/lib/xilinx/xilinx_shell_v1_0_0/Makefile | 35 + .../xilinx_shell_v1_0_0/hdl/open_nic_shell.sv | 755 ++++++++++++++ .../xilinx/xilinx_shell_v1_0_0/open-nic-shell | 1 + hw/lib/xilinx/xilinx_shell_v1_0_0/update.sh | 69 ++ .../xilinx_shell_v1_0_0/vivado_ip/.keep | 0 .../xilinx_shell_v1_0_0/xilinx_shell.tcl | 225 +++++ hw/projects/reference_nic/bitfiles/README | 42 + hw/projects/reference_nic/hw/Makefile | 90 ++ .../constraints/au200_vcu1525_user_timing.tcl | 29 + .../reference_nic/hw/hdl/nf_datapath.v | 332 ++++++ hw/projects/reference_nic/hw/hdl/top_sim.v | 677 +++++++++++++ hw/projects/reference_nic/hw/hdl/top_tb.v | 180 ++++ .../reference_nic/hw/tcl/export_registers.tcl | 160 +++ .../reference_nic/hw/tcl/reference_nic.tcl | 365 +++++++ .../hw/tcl/reference_nic_defines.tcl | 79 ++ .../hw/tcl/reference_nic_sim.tcl | 248 +++++ .../reference_nic/test/both_inc_size/run.py | 116 +++ .../test/both_loopback_maxsize/run.py | 116 +++ .../test/both_loopback_minsize/run.py | 120 +++ .../test/both_loopback_random/run.py | 119 +++ .../reference_nic/test/connections/conn | 30 + hw/projects/reference_nic/test/global/setup | 35 + hw/projects/reference_router/bitfiles/README | 42 + hw/projects/reference_router/hw/Makefile | 104 ++ .../constraints/au200_vcu1525_user_timing.tcl | 29 + .../reference_router/hw/hdl/nf_datapath.v | 378 +++++++ hw/projects/reference_router/hw/hdl/top_sim.v | 677 +++++++++++++ hw/projects/reference_router/hw/hdl/top_tb.v | 180 ++++ .../hw/tcl/export_registers.tcl | 156 +++ .../hw/tcl/reference_router.tcl | 382 +++++++ .../hw/tcl/reference_router_defines.tcl | 82 ++ .../hw/tcl/reference_router_sim.tcl | 264 +++++ .../lib/Python/RegressRouterLib.py | 290 ++++++ .../reference_router/lib/Python/RouterLib.py | 292 ++++++ .../test/both_arp_misses/run.py | 115 +++ .../test/both_badipchksum_packet/run.py | 107 ++ .../test/both_invalidttl_packet/run.py | 108 ++ .../test/both_ipdestfilter_hit/run.py | 120 +++ .../test/both_lpm_generic/run.py | 102 ++ .../test/both_lpm_misses/run.py | 104 ++ .../test/both_lpm_nexthop/run.py | 106 ++ .../test/both_nonip_packet/run.py | 109 ++ .../test/both_nonipv4_packet/run.py | 110 ++ .../test/both_packet_forwarding/run.py | 139 +++ .../test/both_router_table/run.py | 180 ++++ .../test/both_wrong_destMAC/run.py | 109 ++ .../reference_router/test/connections/conn | 30 + .../reference_router/test/global/setup | 35 + hw/projects/reference_switch/bitfiles/README | 42 + hw/projects/reference_switch/hw/Makefile | 91 ++ .../au250_au200_vcu1525_user_timing.tcl | 29 + .../reference_switch/hw/hdl/nf_datapath.v | 332 ++++++ hw/projects/reference_switch/hw/hdl/top_sim.v | 677 +++++++++++++ hw/projects/reference_switch/hw/hdl/top_tb.v | 180 ++++ .../hw/tcl/export_registers.tcl | 160 +++ .../hw/tcl/reference_switch.tcl | 417 ++++++++ .../hw/tcl/reference_switch_defines.tcl | 81 ++ .../hw/tcl/reference_switch_sim.tcl | 253 +++++ .../test/both_learning_sw/run.py | 116 +++ .../test/both_simple_broadcast/run.py | 96 ++ .../reference_switch/test/connections/conn | 30 + .../reference_switch/test/global/setup | 35 + .../reference_switch_lite/bitfiles/README | 42 + hw/projects/reference_switch_lite/hw/Makefile | 91 ++ .../constraints/au200_vcu1525_user_timing.tcl | 29 + .../hw/hdl/nf_datapath.v | 339 +++++++ .../reference_switch_lite/hw/hdl/top_sim.v | 677 +++++++++++++ .../reference_switch_lite/hw/hdl/top_tb.v | 180 ++++ .../hw/tcl/export_registers.tcl | 160 +++ .../hw/tcl/reference_switch_lite.tcl | 379 +++++++ .../hw/tcl/reference_switch_lite_defines.tcl | 99 ++ .../hw/tcl/reference_switch_lite_sim.tcl | 253 +++++ .../test/both_learning_sw/run.py | 116 +++ .../test/both_simple_broadcast/run.py | 96 ++ .../test/connections/conn | 30 + .../reference_switch_lite/test/global/setup | 35 + sw/app/Makefile | 34 + sw/app/main.c | 161 +++ sw/driver/Makefile | 47 + sw/driver/open-nic-driver | 1 + sw/driver/opennic-driver.patch | 298 ++++++ sw/hwtestlib/Makefile | 41 + sw/hwtestlib/sume_reg.c | 178 ++++ tools/scripts/NFTest/NFTest/Makefile | 45 + tools/scripts/NFTest/NFTest/NFTestHeader.py | 44 + tools/scripts/NFTest/NFTest/NFTestLib.py | 474 +++++++++ tools/scripts/NFTest/NFTest/PacketLib.py | 230 +++++ tools/scripts/NFTest/NFTest/__init__.py | 34 + tools/scripts/NFTest/NFTest/hwPkt.py | 320 ++++++ tools/scripts/NFTest/NFTest/hwPktLib.py | 346 +++++++ tools/scripts/NFTest/NFTest/hwReg.py | 51 + tools/scripts/NFTest/NFTest/hwRegLib.py | 142 +++ .../NFTest/NFTest/scapy_sniff_patch.py | 109 ++ tools/scripts/NFTest/NFTest/simLib.py | 184 ++++ tools/scripts/NFTest/NFTest/simPkt.py | 169 ++++ tools/scripts/NFTest/NFTest/simReg.py | 125 +++ tools/scripts/NFTest/testcheck.py | 68 ++ tools/scripts/axitools.py | 237 +++++ tools/scripts/nf_sim_reconcile_axi_logs.py | 76 ++ tools/scripts/nf_sim_registers_axi_logs.py | 115 +++ tools/scripts/nf_test.py | 642 ++++++++++++ tools/scripts/pci_rescan_run.sh | 66 ++ tools/scripts/python_parser.py | 57 ++ tools/scripts/xparam2regdefines.py | 97 ++ tools/settings.sh | 98 ++ 245 files changed, 41474 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 APACHE-LICENSE-2.0.txt create mode 100644 Makefile create mode 100644 NetFPGA-CIC-LICENSE.md create mode 100644 README create mode 100644 hw/contrib-projects/.keep create mode 100644 hw/lib/common/constraints/Makefile create mode 100644 hw/lib/common/constraints/au200_general.xdc create mode 100644 hw/lib/common/constraints/au200_vcu1525_timing.tcl create mode 100644 hw/lib/common/constraints/au250_general.xdc create mode 100644 hw/lib/common/constraints/au280_general.xdc create mode 100644 hw/lib/common/constraints/nf_timing.tcl create mode 100644 hw/lib/common/constraints/vcu1525_general.xdc create mode 100644 hw/lib/common/hdl/nf_attachment.sv create mode 100644 hw/lib/common/hdl/top.v create mode 100644 hw/lib/common/hdl/top_wrapper.sv create mode 100755 hw/lib/contrib/nf_endianess_manager_v1_0_0/Makefile create mode 100644 hw/lib/contrib/nf_endianess_manager_v1_0_0/hdl/bridge.v create mode 100644 hw/lib/contrib/nf_endianess_manager_v1_0_0/hdl/nf_endianess_manager.v create mode 100755 hw/lib/contrib/nf_endianess_manager_v1_0_0/nf_endianess_manager.tcl create mode 100644 hw/lib/std/axi_sim_transactor_v1_0_0/Makefile create mode 100644 hw/lib/std/axi_sim_transactor_v1_0_0/axi_sim_transactor.tcl create mode 100755 hw/lib/std/axi_sim_transactor_v1_0_0/hdl/axi_sim_transactor.vhd create mode 100755 hw/lib/std/axi_sim_transactor_v1_0_0/hdl/transactor_fifos.vhd create mode 100644 hw/lib/std/axis_fifo_v1_0_0/Makefile create mode 100644 hw/lib/std/axis_fifo_v1_0_0/axis_fifo.tcl create mode 100644 hw/lib/std/axis_fifo_v1_0_0/hdl/axis_fifo.v create mode 100644 hw/lib/std/axis_sim_pkg_v1_0_0/Makefile create mode 100644 hw/lib/std/axis_sim_pkg_v1_0_0/axis_sim_pkg.tcl create mode 100644 hw/lib/std/axis_sim_pkg_v1_0_0/hdl/axis_sim_pkg.vhd create mode 100644 hw/lib/std/axis_sim_record_v1_0_0/Makefile create mode 100644 hw/lib/std/axis_sim_record_v1_0_0/axis_sim_record.tcl create mode 100644 hw/lib/std/axis_sim_record_v1_0_0/hdl/axis_sim_record.v create mode 100644 hw/lib/std/axis_sim_stim_v1_0_0/Makefile create mode 100644 hw/lib/std/axis_sim_stim_v1_0_0/axis_sim_stim.tcl create mode 100755 hw/lib/std/axis_sim_stim_v1_0_0/hdl/axis_sim_stim.vhd create mode 100644 hw/lib/std/barrier_v1_0_0/Makefile create mode 100644 hw/lib/std/barrier_v1_0_0/barrier.tcl create mode 100755 hw/lib/std/barrier_v1_0_0/hdl/barrier.v create mode 100644 hw/lib/std/fallthrough_small_fifo_v1_0_0/Makefile create mode 100644 hw/lib/std/fallthrough_small_fifo_v1_0_0/fallthrough_small_fifo.tcl create mode 100644 hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/fallthrough_small_fifo.v create mode 100644 hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/small_fifo.v create mode 100644 hw/lib/std/input_arbiter_v1_0_0/Makefile create mode 100644 hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.h create mode 100644 hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.tcl create mode 100644 hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt create mode 100644 hw/lib/std/input_arbiter_v1_0_0/data/module_generation_Input_arbiter.xlsm create mode 100644 hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter.v create mode 100644 hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs.v create mode 100644 hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs_defines.v create mode 100644 hw/lib/std/input_arbiter_v1_0_0/input_arbiter.tcl create mode 100644 hw/lib/std/nf_axis_converter_v1_0_0/Makefile create mode 100644 hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter.v create mode 100644 hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter_main.v create mode 100644 hw/lib/std/nf_axis_converter_v1_0_0/nf_axis_converter.tcl create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/Makefile create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/hdl/data_synch.v create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment.v create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs.v create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs_defines.v create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/hdl/rx_queue.v create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/hdl/tx_queue.v create mode 100644 hw/lib/std/nf_mac_attachment_v1_0_0/nf_mac_attachment_tcl.tcl create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/Makefile create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/data/module_generation_nic_opl.xlsm create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/nic_output_port_lookup.v create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs.v create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs_defines.v create mode 100644 hw/lib/std/nic_output_port_lookup_v1_0_0/nic_output_port_lookup.tcl create mode 100644 hw/lib/std/output_queues_v1_0_0/Makefile create mode 100644 hw/lib/std/output_queues_v1_0_0/data/module_generation_output_queues.xlsm create mode 100644 hw/lib/std/output_queues_v1_0_0/data/output_queues_regs_defines.h create mode 100644 hw/lib/std/output_queues_v1_0_0/data/output_queues_regs_defines.tcl create mode 100644 hw/lib/std/output_queues_v1_0_0/data/output_queues_regs_defines.txt create mode 100644 hw/lib/std/output_queues_v1_0_0/hdl/output_queues.v create mode 100644 hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs.v create mode 100644 hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs_defines.v create mode 100644 hw/lib/std/output_queues_v1_0_0/output_queues.tcl create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/Makefile create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/dest_ip_filter.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/eth_parser.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/ip_arp.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/ip_checksum_ttl.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/ip_lpm.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/op_lut_hdr_parser.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/op_lut_process_sm.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/output_port_lookup.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs_defines.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/preprocess_control.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/router_output_port_lookup.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/hdl/unencoded_cam_lut_sm.v create mode 100755 hw/lib/std/router_output_port_lookup_v1_0_0/router_output_port_lookup.tcl create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/Makefile create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/module_generation_switch_opl.xlsm create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/eth_parser.v create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/mac_cam_lut.v create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs.v create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs_defines.v create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/switch_lite_output_port_lookup.v create mode 100644 hw/lib/std/switch_lite_output_port_lookup_v1_0_0/switch_lite_output_port_lookup.tcl create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/Makefile create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/data/module_generation_switch_opl.xlsm create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.h create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.tcl create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.txt create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/eth_parser.v create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/mac_cam_lut.v create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/output_port_lookup_cpu_regs.v create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/output_port_lookup_cpu_regs_defines.v create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/switch_output_port_lookup.v create mode 100644 hw/lib/std/switch_output_port_lookup_v1_0_1/switch_output_port_lookup.tcl create mode 100644 hw/lib/xilinx/cam_v1_1_0/Makefile create mode 100644 hw/lib/xilinx/cam_v1_1_0/README create mode 100644 hw/lib/xilinx/cam_v1_1_0/cam.tcl create mode 100644 hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam.v create mode 100644 hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam_wrapper.v create mode 100644 hw/lib/xilinx/cam_v1_1_0/hdl/vhdl/cam/.keep create mode 100644 hw/lib/xilinx/cam_v1_1_0/scripts/run_update_lib.sh create mode 100644 hw/lib/xilinx/tcam_v1_1_0/Makefile create mode 100644 hw/lib/xilinx/tcam_v1_1_0/README create mode 100644 hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam.v create mode 100644 hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam_wrapper.v create mode 100644 hw/lib/xilinx/tcam_v1_1_0/hdl/vhdl/tcam/.keep create mode 100644 hw/lib/xilinx/tcam_v1_1_0/scripts/run_update_lib.sh create mode 100644 hw/lib/xilinx/tcam_v1_1_0/sim/run_sim.tcl create mode 100644 hw/lib/xilinx/tcam_v1_1_0/sim/run_tcam_sim.sh create mode 100644 hw/lib/xilinx/tcam_v1_1_0/sim/testbench.v create mode 100644 hw/lib/xilinx/tcam_v1_1_0/tcam.tcl create mode 100644 hw/lib/xilinx/xilinx_shell_v1_0_0/Makefile create mode 100644 hw/lib/xilinx/xilinx_shell_v1_0_0/hdl/open_nic_shell.sv create mode 160000 hw/lib/xilinx/xilinx_shell_v1_0_0/open-nic-shell create mode 100755 hw/lib/xilinx/xilinx_shell_v1_0_0/update.sh create mode 100644 hw/lib/xilinx/xilinx_shell_v1_0_0/vivado_ip/.keep create mode 100644 hw/lib/xilinx/xilinx_shell_v1_0_0/xilinx_shell.tcl create mode 100644 hw/projects/reference_nic/bitfiles/README create mode 100644 hw/projects/reference_nic/hw/Makefile create mode 100644 hw/projects/reference_nic/hw/constraints/au200_vcu1525_user_timing.tcl create mode 100644 hw/projects/reference_nic/hw/hdl/nf_datapath.v create mode 100644 hw/projects/reference_nic/hw/hdl/top_sim.v create mode 100644 hw/projects/reference_nic/hw/hdl/top_tb.v create mode 100644 hw/projects/reference_nic/hw/tcl/export_registers.tcl create mode 100644 hw/projects/reference_nic/hw/tcl/reference_nic.tcl create mode 100644 hw/projects/reference_nic/hw/tcl/reference_nic_defines.tcl create mode 100644 hw/projects/reference_nic/hw/tcl/reference_nic_sim.tcl create mode 100755 hw/projects/reference_nic/test/both_inc_size/run.py create mode 100755 hw/projects/reference_nic/test/both_loopback_maxsize/run.py create mode 100755 hw/projects/reference_nic/test/both_loopback_minsize/run.py create mode 100755 hw/projects/reference_nic/test/both_loopback_random/run.py create mode 100644 hw/projects/reference_nic/test/connections/conn create mode 100644 hw/projects/reference_nic/test/global/setup create mode 100644 hw/projects/reference_router/bitfiles/README create mode 100644 hw/projects/reference_router/hw/Makefile create mode 100644 hw/projects/reference_router/hw/constraints/au200_vcu1525_user_timing.tcl create mode 100644 hw/projects/reference_router/hw/hdl/nf_datapath.v create mode 100644 hw/projects/reference_router/hw/hdl/top_sim.v create mode 100644 hw/projects/reference_router/hw/hdl/top_tb.v create mode 100644 hw/projects/reference_router/hw/tcl/export_registers.tcl create mode 100644 hw/projects/reference_router/hw/tcl/reference_router.tcl create mode 100644 hw/projects/reference_router/hw/tcl/reference_router_defines.tcl create mode 100644 hw/projects/reference_router/hw/tcl/reference_router_sim.tcl create mode 100755 hw/projects/reference_router/lib/Python/RegressRouterLib.py create mode 100755 hw/projects/reference_router/lib/Python/RouterLib.py create mode 100755 hw/projects/reference_router/test/both_arp_misses/run.py create mode 100755 hw/projects/reference_router/test/both_badipchksum_packet/run.py create mode 100755 hw/projects/reference_router/test/both_invalidttl_packet/run.py create mode 100755 hw/projects/reference_router/test/both_ipdestfilter_hit/run.py create mode 100755 hw/projects/reference_router/test/both_lpm_generic/run.py create mode 100755 hw/projects/reference_router/test/both_lpm_misses/run.py create mode 100755 hw/projects/reference_router/test/both_lpm_nexthop/run.py create mode 100755 hw/projects/reference_router/test/both_nonip_packet/run.py create mode 100755 hw/projects/reference_router/test/both_nonipv4_packet/run.py create mode 100755 hw/projects/reference_router/test/both_packet_forwarding/run.py create mode 100755 hw/projects/reference_router/test/both_router_table/run.py create mode 100755 hw/projects/reference_router/test/both_wrong_destMAC/run.py create mode 100755 hw/projects/reference_router/test/connections/conn create mode 100755 hw/projects/reference_router/test/global/setup create mode 100644 hw/projects/reference_switch/bitfiles/README create mode 100644 hw/projects/reference_switch/hw/Makefile create mode 100644 hw/projects/reference_switch/hw/constraints/au250_au200_vcu1525_user_timing.tcl create mode 100644 hw/projects/reference_switch/hw/hdl/nf_datapath.v create mode 100644 hw/projects/reference_switch/hw/hdl/top_sim.v create mode 100644 hw/projects/reference_switch/hw/hdl/top_tb.v create mode 100644 hw/projects/reference_switch/hw/tcl/export_registers.tcl create mode 100644 hw/projects/reference_switch/hw/tcl/reference_switch.tcl create mode 100644 hw/projects/reference_switch/hw/tcl/reference_switch_defines.tcl create mode 100644 hw/projects/reference_switch/hw/tcl/reference_switch_sim.tcl create mode 100755 hw/projects/reference_switch/test/both_learning_sw/run.py create mode 100755 hw/projects/reference_switch/test/both_simple_broadcast/run.py create mode 100644 hw/projects/reference_switch/test/connections/conn create mode 100644 hw/projects/reference_switch/test/global/setup create mode 100644 hw/projects/reference_switch_lite/bitfiles/README create mode 100644 hw/projects/reference_switch_lite/hw/Makefile create mode 100644 hw/projects/reference_switch_lite/hw/constraints/au200_vcu1525_user_timing.tcl create mode 100644 hw/projects/reference_switch_lite/hw/hdl/nf_datapath.v create mode 100644 hw/projects/reference_switch_lite/hw/hdl/top_sim.v create mode 100644 hw/projects/reference_switch_lite/hw/hdl/top_tb.v create mode 100644 hw/projects/reference_switch_lite/hw/tcl/export_registers.tcl create mode 100644 hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite.tcl create mode 100644 hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_defines.tcl create mode 100644 hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_sim.tcl create mode 100755 hw/projects/reference_switch_lite/test/both_learning_sw/run.py create mode 100755 hw/projects/reference_switch_lite/test/both_simple_broadcast/run.py create mode 100644 hw/projects/reference_switch_lite/test/connections/conn create mode 100644 hw/projects/reference_switch_lite/test/global/setup create mode 100644 sw/app/Makefile create mode 100644 sw/app/main.c create mode 100644 sw/driver/Makefile create mode 160000 sw/driver/open-nic-driver create mode 100644 sw/driver/opennic-driver.patch create mode 100644 sw/hwtestlib/Makefile create mode 100644 sw/hwtestlib/sume_reg.c create mode 100644 tools/scripts/NFTest/NFTest/Makefile create mode 100644 tools/scripts/NFTest/NFTest/NFTestHeader.py create mode 100755 tools/scripts/NFTest/NFTest/NFTestLib.py create mode 100644 tools/scripts/NFTest/NFTest/PacketLib.py create mode 100644 tools/scripts/NFTest/NFTest/__init__.py create mode 100644 tools/scripts/NFTest/NFTest/hwPkt.py create mode 100644 tools/scripts/NFTest/NFTest/hwPktLib.py create mode 100755 tools/scripts/NFTest/NFTest/hwReg.py create mode 100644 tools/scripts/NFTest/NFTest/hwRegLib.py create mode 100644 tools/scripts/NFTest/NFTest/scapy_sniff_patch.py create mode 100644 tools/scripts/NFTest/NFTest/simLib.py create mode 100644 tools/scripts/NFTest/NFTest/simPkt.py create mode 100644 tools/scripts/NFTest/NFTest/simReg.py create mode 100644 tools/scripts/NFTest/testcheck.py create mode 100755 tools/scripts/axitools.py create mode 100755 tools/scripts/nf_sim_reconcile_axi_logs.py create mode 100755 tools/scripts/nf_sim_registers_axi_logs.py create mode 100755 tools/scripts/nf_test.py create mode 100755 tools/scripts/pci_rescan_run.sh create mode 100755 tools/scripts/python_parser.py create mode 100755 tools/scripts/xparam2regdefines.py create mode 100644 tools/settings.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..14d5117 --- /dev/null +++ b/.gitignore @@ -0,0 +1,51 @@ +*.bit +*.ltx +*.zip +*.log +*.o +*.ko +*.cmd +*.mod +*.mod.c +*.axi +*.so +*.sim +*.d +*.a +*.backup.jou +vivado.log +vivado.jou +xvlog.pb +xvlog.log +xsim.dir +seed +__pycache__ +usage_statistics_webtalk.html +usage_statistics_webtalk.xml +nf_register_defines.h +reg_defines.h +lib_pkg_v1_0_rfs.vhd +lib_srl_fifo_v1_0_rfs.vhd +rwaxi +scone +cli +rkd +xgui +ip_repo +ip_proj +proj +project +component.xml +Module.symvers +modules.order +xapp1151_cam_v1_1 +sw/driver/.updated.txt +hw/lib/std/axi_sim_transactor_v1_0_0/hdl/axis_sim_pkg/ +hw/lib/xilinx/cam_v1_1_0/hdl/vhdl/cam/*.vhd +hw/lib/xilinx/tcam_v1_1_0/hdl/vhdl/tcam/*.vhd +hw/projects/*/test/Makefile +reg_defines_*.py +hw/projects/reference_nic/sw/ +hw/projects/reference_switch/sw/ +hw/projects/reference_switch_lite/sw/ +tools/scripts/NFTest/testcheck.pyc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..09abe1b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "sw/driver/open-nic-driver"] + path = sw/driver/open-nic-driver + url = https://github.com/Xilinx/open-nic-driver.git +[submodule "hw/lib/xilinx/xilinx_shell_v1_0_0/open-nic-shell"] + path = hw/lib/xilinx/xilinx_shell_v1_0_0/open-nic-shell + url = https://github.com/Xilinx/open-nic-shell.git diff --git a/APACHE-LICENSE-2.0.txt b/APACHE-LICENSE-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/APACHE-LICENSE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ead9ca4 --- /dev/null +++ b/Makefile @@ -0,0 +1,188 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +################################################################################ +# File: +# Makefile +# +# Project: +# Makes all the cores of NetFPGA library +# +# Description: +# This makefile is used to generate and compile SDK project for NetFPGA reference projects. +# The first argument is target + +SCRIPTS_DIR = tools/ +LIB_REPO = hw/lib/ip_repo +LIB_HW_DIR = hw/lib +LIB_SW_DIR = sw +LIB_HW_DIR_INSTANCES := $(shell cd $(LIB_HW_DIR) && find . -maxdepth 4 -type d) +LIB_HW_DIR_INSTANCES := $(basename $(patsubst ./%,%,$(LIB_HW_DIR_INSTANCES))) +LIB_SW_DIR_INSTANCES := $(shell cd $(LIB_SW_DIR) && find . -maxdepth 4 -type d) +LIB_SW_DIR_INSTANCES := $(basename $(patsubst ./%,%,$(LIB_SW_DIR_INSTANCES))) + +TOOLS_DIR = tools +TOOLS_DIR_INSTANCES := $(shell cd $(TOOLS_DIR) && find . -maxdepth 3 -type d) +TOOLS_DIR_INSTANCES := $(basename $(patsubst ./%,%,$(TOOLS_DIR_INSTANCES))) + +PROJECTS_DIR = hw/projects +PROJECTS_DIR_INSTANCES := $(shell cd $(PROJECTS_DIR) && find . -maxdepth 1 -type d) +PROJECTS_DIR_INSTANCES := $(basename $(patsubst ./%,%,$(PROJECTS_DIR_INSTANCES))) + +CONTRIBPROJECTS_DIR = hw/contrib-projects +CONTRIBPROJECTS_DIR_INSTANCES := $(shell cd $(CONTRIBPROJECTS_DIR) && find . -maxdepth 1 -type d) +CONTRIBPROJECTS_DIR_INSTANCES := $(basename $(patsubst ./%,%,$(CONTRIBPROJECTS_DIR_INSTANCES))) + +RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +$(eval $(RUN_ARGS):;@:) + + +all: clean cores hwtestlib constraints + +clean: libclean toolsclean projectsclean swclean constraintsclean + @rm -rfv *.*~ + @rm -rfv ip_proj + @rm -rfv ip_user_files + @find . -type f -name '*.pyc' -delete + @find . -type f -name '*.jou' -delete + @find . -type f -name '*.log' -delete + @find . -type f -name '*.coe' -delete + @find . -type f -name '*.mif' -delete + +cores: + make -C $(LIB_HW_DIR)/xilinx/cam_v1_1_0/ + make -C $(LIB_HW_DIR)/xilinx/tcam_v1_1_0/ + make -C $(LIB_HW_DIR)/xilinx/xilinx_shell_v1_0_0/ + make -C $(LIB_HW_DIR)/std/fallthrough_small_fifo_v1_0_0/ + make -C $(LIB_HW_DIR)/contrib/nf_endianess_manager_v1_0_0/ + make -C $(LIB_HW_DIR)/std/axis_fifo_v1_0_0/ + make -C $(LIB_HW_DIR)/std/nf_axis_converter_v1_0_0/ + make -C $(LIB_HW_DIR)/std/nf_mac_attachment_v1_0_0/ + make -C $(LIB_HW_DIR)/std/input_arbiter_v1_0_0/ + make -C $(LIB_HW_DIR)/std/output_queues_v1_0_0/ + make -C $(LIB_HW_DIR)/std/switch_output_port_lookup_v1_0_1/ + make -C $(LIB_HW_DIR)/std/nic_output_port_lookup_v1_0_0/ + make -C $(LIB_HW_DIR)/std/switch_lite_output_port_lookup_v1_0_0/ + make -C $(LIB_HW_DIR)/std/router_output_port_lookup_v1_0_0/ + make -C $(LIB_HW_DIR)/std/barrier_v1_0_0/ + make -C $(LIB_HW_DIR)/std/axi_sim_transactor_v1_0_0/ + make -C $(LIB_HW_DIR)/std/axis_sim_record_v1_0_0/ + make -C $(LIB_HW_DIR)/std/axis_sim_stim_v1_0_0/ + @echo "/////////////////////////////////////////"; + @echo "//\tLibrary cores created."; + @echo "/////////////////////////////////////////"; + + +libclean: + @rm -rf $(LIB_REPO) + @for lib in $(LIB_HW_DIR_INSTANCES) ; do \ + if test -f $(LIB_HW_DIR)/$$lib/Makefile; then \ + $(MAKE) -C $(LIB_HW_DIR)/$$lib clean; \ + fi; \ + done; + @echo "/////////////////////////////////////////"; + @echo "//\tLibrary cores cleaned."; + @echo "/////////////////////////////////////////"; + + +toolsclean: + @if test -f $(TOOLS_DIR)/Makefile; then \ + $(MAKE) -C $(TOOLS_DIR) clean; \ + fi; + @echo "/////////////////////////////////////////"; + @echo "//\tTools cleaned."; + @echo "/////////////////////////////////////////"; + + +projectsclean: + @for lib in $(PROJECTS_DIR_INSTANCES) ; do \ + if test -f $(PROJECTS_DIR)/$$lib/Makefile; then \ + $(MAKE) -C $(PROJECTS_DIR)/$$lib/ clean; \ + fi; \ + done; + @echo "/////////////////////////////////////////"; + @echo "//\tProjects cleaned."; + @echo "/////////////////////////////////////////"; + + +contribprojectsclean: + @for lib in $(CONTRIBPROJECTS_DIR_INSTANCES) ; do \ + if test -f $(CONTRIBPROJECTS_DIR)/$$lib/Makefile; then \ + $(MAKE) -C $(CONTRIBPROJECTS_DIR)/$$lib/ clean; \ + fi; \ + done; + @echo "/////////////////////////////////////////"; + @echo "//\tContrib-projects cleaned."; + @echo "/////////////////////////////////////////"; + +constraints: + $(MAKE) -C hw/lib/common/constraints + @echo "/////////////////////////////////////////"; + @echo "//\tConstraints files are updated"; + @echo "/////////////////////////////////////////"; + +constraintsclean: + $(MAKE) -C hw/lib/common/constraints clean + @echo "/////////////////////////////////////////"; + @echo "//\tConstraints files are cleaned"; + @echo "/////////////////////////////////////////"; + +contribprojects: + @for lib in $(CONTRIBPROJECTS_DIR_INSTANCES) ; do \ + if test -f $(CONTRIBPROJECTS_DIR)/$$lib/Makefile; then \ + $(MAKE) -C $(CONTRIBPROJECTS_DIR)/$$lib/; \ + fi; \ + done; + @echo "/////////////////////////////////////////"; + @echo "//\tContrib-projects created."; + @echo "/////////////////////////////////////////"; + + +hwtestlib: + $(MAKE) -C sw/hwtestlib + @echo "/////////////////////////////////////////"; + @echo "//\tHW test Library created."; + @echo "/////////////////////////////////////////"; + + +hwtestlibclean: + $(MAKE) -C sw/hwtestlib clean + @echo "/////////////////////////////////////////"; + @echo "//\tHW test Library cleaned."; + @echo "/////////////////////////////////////////"; + +swclean: + @for swlib in $(LIB_SW_DIR_INSTANCES) ; do \ + if test -f $(LIB_SW_DIR)/$$swlib/Makefile; then \ + $(MAKE) -C $(LIB_SW_DIR)/$$swlib clean; \ + fi; \ + done; + @echo "/////////////////////////////////////////"; + @echo "//\tSW Library cleaned."; + @echo "/////////////////////////////////////////"; + diff --git a/NetFPGA-CIC-LICENSE.md b/NetFPGA-CIC-LICENSE.md new file mode 100644 index 0000000..ff2ac74 --- /dev/null +++ b/NetFPGA-CIC-LICENSE.md @@ -0,0 +1,6 @@ +[![](https://github.com/NetFPGA/NetFPGA-public/blob/master/netfpga.png)](http://www.netfpga.org) + + + + +[NetFPGA license and agreements](http://netfpga-cic.org/) diff --git a/README b/README new file mode 100644 index 0000000..d357ecd --- /dev/null +++ b/README @@ -0,0 +1,39 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +Welcome to the NetFPGA-PLUS base package. + +For documentation on its content and use, as well as general +information on the NetFPGA-SUME platform, please visit the +documentation wiki: + +https://github.com/NetFPGA/NetFPGA-PLUS/wiki + +The wiki additionally contains a useful "Getting Started Guide" +for new users, which can be found here: + +https://github.com/NetFPGA/NetFPGA-PLUS/wiki/Getting-Started-Guide + +Have fun! diff --git a/hw/contrib-projects/.keep b/hw/contrib-projects/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/lib/common/constraints/Makefile b/hw/lib/common/constraints/Makefile new file mode 100644 index 0000000..cb0668d --- /dev/null +++ b/hw/lib/common/constraints/Makefile @@ -0,0 +1,50 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +OUTFILE := au280_timing.tcl au250_timing.tcl + +all: $(OUTFILE) + +au250_timing.tcl: + sed -e 's/pcie_refclk_p/pci_clk_p/g' -e 's/pcie_rstn/pci_rst_n/g' \ + -e 's/\[get_nets cmac_clk/\[get_nets u_top_wrapper\/cmac_clk/g' \ + -e 's/create_pbloc/#create_pbloc/g' \ + -e 's/add_cells_to_pblock/#add_cells_to_pblock/g' \ + -e 's/resize_pblock/#resize_pblock/g' \ + ../../xilinx/xilinx_shell_v1_0_0/open-nic-shell/constr/au250/timing.xdc > au250_timing.tcl + +au280_timing.tcl: + sed -e 's/pcie_refclk_p/pci_clk_p/g' -e 's/pcie_rstn/pci_rst_n/g' \ + -e 's/\[get_nets cmac_clk/\[get_nets u_top_wrapper\/cmac_clk/g' \ + -e 's/cmac_port/u_top_wrapper\/xilinx_nic_shell\/inst\/cmac_port/g' \ + -e 's/qdma_subsystem_inst/u_top_wrapper\/xilinx_nic_shell\/inst\/qdma_subsystem_inst/g' \ + -e 's/create_pblock pblock_packet_adapter/#create_pblock pblock_packet_adapter/g' \ + -e 's/add_cells_to_pblock \[get_pblocks pblock_packet/#add_cells_to_pblock \[get_pblocks pblock_packet/g' \ + -e 's/resize_pblock \[get_pblocks pblock_packe/#resize_pblock \[get_pblocks pblock_packe/g' \ + -e '/box/d' \ + ../../xilinx/xilinx_shell_v1_0_0/open-nic-shell/constr/au280/timing.xdc > au280_timing.tcl + cat nf_timing.tcl >> au280_timing.tcl + +clean: + rm -rf $(OUTFILE) diff --git a/hw/lib/common/constraints/au200_general.xdc b/hw/lib/common/constraints/au200_general.xdc new file mode 100644 index 0000000..fda565c --- /dev/null +++ b/hw/lib/common/constraints/au200_general.xdc @@ -0,0 +1,166 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +########################################################################### +# This file is based on the origin file downloaded from +# https://www.xilinx.com/products/boards-and-kits/alveo/u200.html#vivado +########################################################################### +# +####################################################################### +# General Clock +####################################################################### +set_property PACKAGE_PIN AY38 [get_ports sysclk_n]; +set_property IOSTANDARD DIFF_SSTL12 [get_ports sysclk_n]; +set_property PACKAGE_PIN AY37 [get_ports sysclk_p]; +set_property IOSTANDARD DIFF_SSTL12 [get_ports sysclk_p]; +create_clock -period 3.333 -name SYSCLK0_300 [get_ports sysclk_p] + +set_clock_groups -asynchronous -group [get_clocks SYSCLK0_300 -include_generated_clocks] +####################################################################### +# PCIe +####################################################################### +set_property PACKAGE_PIN AM10 [get_ports pci_clk_n] +set_property PACKAGE_PIN AM11 [get_ports pci_clk_p] +create_clock -name sys_clk -period 10 [get_ports pci_clk_p] + +set_property PULLUP true [get_ports pci_rst_n] +set_property IOSTANDARD LVCMOS12 [get_ports pci_rst_n] +set_property PACKAGE_PIN BD21 [get_ports pci_rst_n] + +set_false_path -from [get_ports pci_rst_n] +####################################################################### +# CMAC +####################################################################### +# QSFP0_CLOCK +set_property PACKAGE_PIN K10 [get_ports QSFP0_CLOCK_N]; +set_property PACKAGE_PIN K11 [get_ports QSFP0_CLOCK_P]; +# QSFP0_PORT +set_property PACKAGE_PIN AT20 [get_ports QSFP0_FS[0]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_FS[0]]; +set_property PACKAGE_PIN AU22 [get_ports QSFP0_FS[1]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_FS[1]]; +set_property PACKAGE_PIN AT22 [get_ports QSFP0_RESET]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_RESET]; + +set_property PACKAGE_PIN BE21 [get_ports QSFP0_INTL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_INTL]; +set_property PACKAGE_PIN BD18 [get_ports QSFP0_LPMODE]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_LPMODE]; +set_property PACKAGE_PIN BE20 [get_ports QSFP0_MODPRSL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_MODPRSL]; +set_property PACKAGE_PIN BE16 [get_ports QSFP0_MODSELL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_MODSELL]; +set_property PACKAGE_PIN BE17 [get_ports QSFP0_RESETL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_RESETL]; + +# QSFP0_TX +set_property -dict { LOC K7 } [get_ports QSFP0_TX_P[3]] +set_property -dict { LOC K6 } [get_ports QSFP0_TX_N[3]] +set_property -dict { LOC L9 } [get_ports QSFP0_TX_P[2]] +set_property -dict { LOC L8 } [get_ports QSFP0_TX_N[2]] +set_property -dict { LOC M7 } [get_ports QSFP0_TX_P[1]] +set_property -dict { LOC M6 } [get_ports QSFP0_TX_N[1]] +set_property -dict { LOC N9 } [get_ports QSFP0_TX_P[0]] +set_property -dict { LOC N8 } [get_ports QSFP0_TX_N[0]] + +# QSFP0_RX +set_property -dict { LOC K2 } [get_ports QSFP0_RX_P[3]] +set_property -dict { LOC K1 } [get_ports QSFP0_RX_N[3]] +set_property -dict { LOC L4 } [get_ports QSFP0_RX_P[2]] +set_property -dict { LOC L3 } [get_ports QSFP0_RX_N[2]] +set_property -dict { LOC M2 } [get_ports QSFP0_RX_P[1]] +set_property -dict { LOC M1 } [get_ports QSFP0_RX_N[1]] +set_property -dict { LOC N4 } [get_ports QSFP0_RX_P[0]] +set_property -dict { LOC N3 } [get_ports QSFP0_RX_N[0]] + +# QSFP1 +set_property PACKAGE_PIN P10 [get_ports QSFP1_CLOCK_N]; +set_property PACKAGE_PIN P11 [get_ports QSFP1_CLOCK_P]; + +# QSFP1 +set_property PACKAGE_PIN AR22 [get_ports QSFP1_FS[0]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_FS[0]]; +set_property PACKAGE_PIN AU20 [get_ports QSFP1_FS[1]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_FS[1]]; +set_property PACKAGE_PIN AR21 [get_ports QSFP1_RESET]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_RESET]; +set_property PACKAGE_PIN AV21 [get_ports QSFP1_INTL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_INTL]; +set_property PACKAGE_PIN AV22 [get_ports QSFP1_LPMODE]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_LPMODE]; +set_property PACKAGE_PIN BC19 [get_ports QSFP1_MODPRSL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_MODPRSL]; +set_property PACKAGE_PIN AY20 [get_ports QSFP1_MODSELL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_MODSELL]; +set_property PACKAGE_PIN BC18 [get_ports QSFP1_RESETL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_RESETL]; + + +# QSFP1_TX +set_property -dict { LOC P7 } [get_ports QSFP1_TX_P[3]] +set_property -dict { LOC P6 } [get_ports QSFP1_TX_N[3]] +set_property -dict { LOC R9 } [get_ports QSFP1_TX_P[2]] +set_property -dict { LOC R8 } [get_ports QSFP1_TX_N[2]] +set_property -dict { LOC T7 } [get_ports QSFP1_TX_P[1]] +set_property -dict { LOC T6 } [get_ports QSFP1_TX_N[1]] +set_property -dict { LOC U9 } [get_ports QSFP1_TX_P[0]] +set_property -dict { LOC U8 } [get_ports QSFP1_TX_N[0]] + +# QSFP1_RX +set_property -dict { LOC P2 } [get_ports QSFP1_RX_P[3]] +set_property -dict { LOC P1 } [get_ports QSFP1_RX_N[3]] +set_property -dict { LOC R4 } [get_ports QSFP1_RX_P[2]] +set_property -dict { LOC R3 } [get_ports QSFP1_RX_N[2]] +set_property -dict { LOC T2 } [get_ports QSFP1_RX_P[1]] +set_property -dict { LOC T1 } [get_ports QSFP1_RX_N[1]] +set_property -dict { LOC U4 } [get_ports QSFP1_RX_P[0]] +set_property -dict { LOC U3 } [get_ports QSFP1_RX_N[0]] +########################################################################## +# Timing +########################################################################## +# CMAC user clock +create_clock -period 3.103 -name cmac_clk_0 [get_pins -hier -filter name=~*cmac_port[0]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] +create_clock -period 3.103 -name cmac_clk_1 [get_pins -hier -filter name=~*cmac_port[1]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] + +# Registers Clock +create_clock -period 8.000 -name reg_clk [get_pins -hier -filter name=~*u_top_wrapper/xilinx_nic_shell/inst/qdma_subsystem_inst/qdma_wrapper_inst/clk_div_inst/clk_out1] + +# Datapath Clock - 340MHz +create_clock -period 2.941 -name dp_clk [get_pins -hier -filter name=~*u_clk_wiz_1/clk_out1] + +set_false_path -from [get_clocks axis_aclk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_0] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks axis_aclk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_0] diff --git a/hw/lib/common/constraints/au200_vcu1525_timing.tcl b/hw/lib/common/constraints/au200_vcu1525_timing.tcl new file mode 100644 index 0000000..0d10d8d --- /dev/null +++ b/hw/lib/common/constraints/au200_vcu1525_timing.tcl @@ -0,0 +1,32 @@ +# ************************************************************************* +# +# Copyright 2020 Xilinx, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ************************************************************************* +create_clock -period 10.000 -name pcie_refclk [get_ports pci_clk_p] + +set_false_path -through [get_ports pci_rst_n] + +set axis_aclk [get_clocks -of_object [get_nets axis_aclk]] +foreach cmac_clk [get_clocks -of_object [get_nets u_top_wrapper/cmac_clk*]] { + set_max_delay -datapath_only -from $axis_aclk -to $cmac_clk 4.000 + set_max_delay -datapath_only -from $cmac_clk -to $axis_aclk 3.103 +} + +create_pblock pblock_nf_datapath +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list nf_datapath_0]] +#add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list u_top_wrapper/u_nf_attachment]] +resize_pblock [get_pblocks pblock_nf_datapath] -add {SLR2} + diff --git a/hw/lib/common/constraints/au250_general.xdc b/hw/lib/common/constraints/au250_general.xdc new file mode 100644 index 0000000..a97fc87 --- /dev/null +++ b/hw/lib/common/constraints/au250_general.xdc @@ -0,0 +1,166 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +########################################################################### +# This file is based on the origin file downloaded from +# https://www.xilinx.com/products/boards-and-kits/alveo/u250.html#vivado +########################################################################### +# +####################################################################### +# General Clock +####################################################################### +set_property PACKAGE_PIN AY38 [get_ports sysclk_n]; +set_property IOSTANDARD DIFF_SSTL12 [get_ports sysclk_n]; +set_property PACKAGE_PIN AY37 [get_ports sysclk_p]; +set_property IOSTANDARD DIFF_SSTL12 [get_ports sysclk_p]; +create_clock -period 3.333 -name SYSCLK0_300 [get_ports sysclk_p] + +set_clock_groups -asynchronous -group [get_clocks SYSCLK0_300 -include_generated_clocks] +####################################################################### +# PCIe +####################################################################### +set_property PACKAGE_PIN AM10 [get_ports pci_clk_n] +set_property PACKAGE_PIN AM11 [get_ports pci_clk_p] +create_clock -name sys_clk -period 10 [get_ports pci_clk_p] + +set_property PULLUP true [get_ports pci_rst_n] +set_property IOSTANDARD LVCMOS12 [get_ports pci_rst_n] +set_property PACKAGE_PIN BD21 [get_ports pci_rst_n] + +set_false_path -from [get_ports pci_rst_n] +####################################################################### +# CMAC +####################################################################### +# QSFP0_CLOCK +set_property PACKAGE_PIN K10 [get_ports QSFP0_CLOCK_N]; +set_property PACKAGE_PIN K11 [get_ports QSFP0_CLOCK_P]; +# QSFP0_PORT +set_property PACKAGE_PIN AT20 [get_ports QSFP0_FS[0]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_FS[0]]; +set_property PACKAGE_PIN AU22 [get_ports QSFP0_FS[1]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_FS[1]]; +set_property PACKAGE_PIN AT22 [get_ports QSFP0_RESET]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_RESET]; + +set_property PACKAGE_PIN BE21 [get_ports QSFP0_INTL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_INTL]; +set_property PACKAGE_PIN BD18 [get_ports QSFP0_LPMODE]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_LPMODE]; +set_property PACKAGE_PIN BE20 [get_ports QSFP0_MODPRSL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_MODPRSL]; +set_property PACKAGE_PIN BE16 [get_ports QSFP0_MODSELL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_MODSELL]; +set_property PACKAGE_PIN BE17 [get_ports QSFP0_RESETL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_RESETL]; + +# QSFP0_TX +set_property -dict { LOC K7 } [get_ports QSFP0_TX_P[3]] +set_property -dict { LOC K6 } [get_ports QSFP0_TX_N[3]] +set_property -dict { LOC L9 } [get_ports QSFP0_TX_P[2]] +set_property -dict { LOC L8 } [get_ports QSFP0_TX_N[2]] +set_property -dict { LOC M7 } [get_ports QSFP0_TX_P[1]] +set_property -dict { LOC M6 } [get_ports QSFP0_TX_N[1]] +set_property -dict { LOC N9 } [get_ports QSFP0_TX_P[0]] +set_property -dict { LOC N8 } [get_ports QSFP0_TX_N[0]] + +# QSFP0_RX +set_property -dict { LOC K2 } [get_ports QSFP0_RX_P[3]] +set_property -dict { LOC K1 } [get_ports QSFP0_RX_N[3]] +set_property -dict { LOC L4 } [get_ports QSFP0_RX_P[2]] +set_property -dict { LOC L3 } [get_ports QSFP0_RX_N[2]] +set_property -dict { LOC M2 } [get_ports QSFP0_RX_P[1]] +set_property -dict { LOC M1 } [get_ports QSFP0_RX_N[1]] +set_property -dict { LOC N4 } [get_ports QSFP0_RX_P[0]] +set_property -dict { LOC N3 } [get_ports QSFP0_RX_N[0]] + +# QSFP1 +set_property PACKAGE_PIN P10 [get_ports QSFP1_CLOCK_N]; +set_property PACKAGE_PIN P11 [get_ports QSFP1_CLOCK_P]; + +# QSFP1 +set_property PACKAGE_PIN AR22 [get_ports QSFP1_FS[0]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_FS[0]]; +set_property PACKAGE_PIN AU20 [get_ports QSFP1_FS[1]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_FS[1]]; +set_property PACKAGE_PIN AR21 [get_ports QSFP1_RESET]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_RESET]; +set_property PACKAGE_PIN AV21 [get_ports QSFP1_INTL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_INTL]; +set_property PACKAGE_PIN AV22 [get_ports QSFP1_LPMODE]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_LPMODE]; +set_property PACKAGE_PIN BC19 [get_ports QSFP1_MODPRSL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_MODPRSL]; +set_property PACKAGE_PIN AY20 [get_ports QSFP1_MODSELL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_MODSELL]; +set_property PACKAGE_PIN BC18 [get_ports QSFP1_RESETL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_RESETL]; + + +# QSFP1_TX +set_property -dict { LOC P7 } [get_ports QSFP1_TX_P[3]] +set_property -dict { LOC P6 } [get_ports QSFP1_TX_N[3]] +set_property -dict { LOC R9 } [get_ports QSFP1_TX_P[2]] +set_property -dict { LOC R8 } [get_ports QSFP1_TX_N[2]] +set_property -dict { LOC T7 } [get_ports QSFP1_TX_P[1]] +set_property -dict { LOC T6 } [get_ports QSFP1_TX_N[1]] +set_property -dict { LOC U9 } [get_ports QSFP1_TX_P[0]] +set_property -dict { LOC U8 } [get_ports QSFP1_TX_N[0]] + +# QSFP1_RX +set_property -dict { LOC P2 } [get_ports QSFP1_RX_P[3]] +set_property -dict { LOC P1 } [get_ports QSFP1_RX_N[3]] +set_property -dict { LOC R4 } [get_ports QSFP1_RX_P[2]] +set_property -dict { LOC R3 } [get_ports QSFP1_RX_N[2]] +set_property -dict { LOC T2 } [get_ports QSFP1_RX_P[1]] +set_property -dict { LOC T1 } [get_ports QSFP1_RX_N[1]] +set_property -dict { LOC U4 } [get_ports QSFP1_RX_P[0]] +set_property -dict { LOC U3 } [get_ports QSFP1_RX_N[0]] +########################################################################## +# Timing +########################################################################## +# CMAC user clock +create_clock -period 3.103 -name cmac_clk_0 [get_pins -hier -filter name=~*cmac_port[0]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] +create_clock -period 3.103 -name cmac_clk_1 [get_pins -hier -filter name=~*cmac_port[1]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] + +# Registers Clock +create_clock -period 8.000 -name reg_clk [get_pins -hier -filter name=~*u_top_wrapper/xilinx_nic_shell/inst/qdma_subsystem_inst/qdma_wrapper_inst/clk_div_inst/clk_out1] + +# Datapath Clock - 340MHz +create_clock -period 2.941 -name dp_clk [get_pins -hier -filter name=~*u_clk_wiz_1/clk_out1] + +set_false_path -from [get_clocks axis_aclk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_0] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks axis_aclk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_0] diff --git a/hw/lib/common/constraints/au280_general.xdc b/hw/lib/common/constraints/au280_general.xdc new file mode 100644 index 0000000..95905f2 --- /dev/null +++ b/hw/lib/common/constraints/au280_general.xdc @@ -0,0 +1,108 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +########################################################################### +# This file is based on the origin file downloaded from +# https://www.xilinx.com/products/boards-and-kits/alveo/u280.html#vivado +########################################################################### +# +####################################################################### +# General Clock +####################################################################### +set_property PACKAGE_PIN BJ44 [get_ports sysclk_n]; +set_property IOSTANDARD LVDS [get_ports sysclk_n]; +set_property PACKAGE_PIN BJ43 [get_ports sysclk_p]; +set_property IOSTANDARD LVDS [get_ports sysclk_p]; +#create_clock -period 10.000 -name sysclk0 [get_ports sysclk0_p] +#set_clock_groups -asynchronous -group [get_clocks sysclk0 -include_generated_clocks] + +#set_clock_groups -asynchronous -group [get_clocks SYSCLK0_300 -include_generated_clocks] +####################################################################### +# PCIe +####################################################################### +set_property PACKAGE_PIN AR14 [get_ports pci_clk_n] +set_property PACKAGE_PIN AR15 [get_ports pci_clk_p] +#create_clock -name sys_clk -period 10 [get_ports pci_clk_p] +create_clock -period 10.000 -name pcie_refclk [get_ports pci_clk_p] + + + +set_property PULLUP true [get_ports pci_rst_n] +set_property IOSTANDARD LVCMOS18 [get_ports pci_rst_n] +set_property PACKAGE_PIN BH26 [get_ports pci_rst_n] + +set_false_path -through [get_ports pci_rst_n] +####################################################################### +# CMAC +####################################################################### +# QSFP0_CLOCK +set_property PACKAGE_PIN R41 [get_ports QSFP0_CLOCK_N]; +set_property PACKAGE_PIN R40 [get_ports QSFP0_CLOCK_P]; +# QSFP0_PORT +set_property PACKAGE_PIN G32 [get_ports QSFP0_FS]; +set_property IOSTANDARD LVCMOS18 [get_ports QSFP0_FS]; +set_property PACKAGE_PIN H32 [get_ports QSFP0_RESET] +set_property IOSTANDARD LVCMOS18 [get_ports QSFP0_RESET] + +# QSFP1 +set_property PACKAGE_PIN M43 [get_ports QSFP1_CLOCK_N]; +set_property PACKAGE_PIN M42 [get_ports QSFP1_CLOCK_P]; + +# QSFP1 +set_property PACKAGE_PIN G33 [get_ports QSFP1_FS]; +set_property IOSTANDARD LVCMOS18 [get_ports QSFP1_FS]; +set_property PACKAGE_PIN H30 [get_ports QSFP1_RESET] +set_property IOSTANDARD LVCMOS18 [get_ports QSFP1_RESET] + +# HBM +set_property PACKAGE_PIN D32 [get_ports STAT_CATTRIP] +set_property IOSTANDARD LVCMOS18 [get_ports STAT_CATTRIP] +########################################################################## +# Timing +########################################################################## +# CMAC user clock +create_clock -period 3.103 -name cmac_clk_0 [get_pins -hier -filter name=~*cmac_port[0]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] +create_clock -period 3.103 -name cmac_clk_1 [get_pins -hier -filter name=~*cmac_port[1]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] + +# Registers Clock +create_clock -period 8.000 -name reg_clk [get_pins -hier -filter name=~*u_top_wrapper/xilinx_nic_shell/inst/qdma_subsystem_inst/qdma_wrapper_inst/clk_div_inst/clk_out1] + +# Datapath Clock - 340MHz +create_clock -period 2.941 -name dp_clk [get_pins -hier -filter name=~*u_clk_wiz_1/clk_out1] + +set_false_path -from [get_clocks axis_aclk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_0] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks axis_aclk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_0] diff --git a/hw/lib/common/constraints/nf_timing.tcl b/hw/lib/common/constraints/nf_timing.tcl new file mode 100644 index 0000000..42f05c6 --- /dev/null +++ b/hw/lib/common/constraints/nf_timing.tcl @@ -0,0 +1,29 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +create_pblock pblock_nf_datapath +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list nf_datapath_0]] +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list u_top_wrapper/u_nf_attachment]] +resize_pblock [get_pblocks pblock_nf_datapath] -add {SLR1} diff --git a/hw/lib/common/constraints/vcu1525_general.xdc b/hw/lib/common/constraints/vcu1525_general.xdc new file mode 100644 index 0000000..cfc682a --- /dev/null +++ b/hw/lib/common/constraints/vcu1525_general.xdc @@ -0,0 +1,163 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed to NetFPGA C.I.C. (NetFPGA) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. NetFPGA licenses this +# file to you under the NetFPGA Hardware-Software License, Version 1.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at: +# +# http://www.netfpga-cic.org +# +# Unless required by applicable law or agreed to in writing, Work distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +####################################################################### +# General Clock +####################################################################### +set_property PACKAGE_PIN AY38 [get_ports sysclk_n]; +set_property IOSTANDARD DIFF_SSTL12 [get_ports sysclk_n]; +set_property PACKAGE_PIN AY37 [get_ports sysclk_p]; +set_property IOSTANDARD DIFF_SSTL12 [get_ports sysclk_p]; +create_clock -period 3.333 -name SYSCLK0_300 [get_ports sysclk_p] + +set_clock_groups -asynchronous -group [get_clocks SYSCLK0_300 -include_generated_clocks] +####################################################################### +# PCIe +####################################################################### +set_property PACKAGE_PIN AM10 [get_ports pci_clk_n] +set_property PACKAGE_PIN AM11 [get_ports pci_clk_p] +create_clock -name sys_clk -period 10 [get_ports pci_clk_p] + +set_property PULLUP true [get_ports pci_rst_n] +set_property IOSTANDARD LVCMOS12 [get_ports pci_rst_n] +set_property PACKAGE_PIN BD21 [get_ports pci_rst_n] + +set_false_path -from [get_ports pci_rst_n] +####################################################################### +# CMAC +####################################################################### +# QSFP0_CLOCK +set_property PACKAGE_PIN K10 [get_ports QSFP0_CLOCK_N]; +set_property PACKAGE_PIN K11 [get_ports QSFP0_CLOCK_P]; +# QSFP0_PORT +set_property PACKAGE_PIN AT20 [get_ports QSFP0_FS[0]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_FS[0]]; +set_property PACKAGE_PIN AU22 [get_ports QSFP0_FS[1]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_FS[1]]; +set_property PACKAGE_PIN AT22 [get_ports QSFP0_RESET]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_RESET]; + +set_property PACKAGE_PIN BE21 [get_ports QSFP0_INTL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_INTL]; +set_property PACKAGE_PIN BD18 [get_ports QSFP0_LPMODE]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_LPMODE]; +set_property PACKAGE_PIN BE20 [get_ports QSFP0_MODPRSL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_MODPRSL]; +set_property PACKAGE_PIN BE16 [get_ports QSFP0_MODSELL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_MODSELL]; +set_property PACKAGE_PIN BE17 [get_ports QSFP0_RESETL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP0_RESETL]; + +# QSFP0_TX +set_property -dict { LOC K7 } [get_ports QSFP0_TX_P[3]] +set_property -dict { LOC K6 } [get_ports QSFP0_TX_N[3]] +set_property -dict { LOC L9 } [get_ports QSFP0_TX_P[2]] +set_property -dict { LOC L8 } [get_ports QSFP0_TX_N[2]] +set_property -dict { LOC M7 } [get_ports QSFP0_TX_P[1]] +set_property -dict { LOC M6 } [get_ports QSFP0_TX_N[1]] +set_property -dict { LOC N9 } [get_ports QSFP0_TX_P[0]] +set_property -dict { LOC N8 } [get_ports QSFP0_TX_N[0]] + +# QSFP0_RX +set_property -dict { LOC K2 } [get_ports QSFP0_RX_P[3]] +set_property -dict { LOC K1 } [get_ports QSFP0_RX_N[3]] +set_property -dict { LOC L4 } [get_ports QSFP0_RX_P[2]] +set_property -dict { LOC L3 } [get_ports QSFP0_RX_N[2]] +set_property -dict { LOC M2 } [get_ports QSFP0_RX_P[1]] +set_property -dict { LOC M1 } [get_ports QSFP0_RX_N[1]] +set_property -dict { LOC N4 } [get_ports QSFP0_RX_P[0]] +set_property -dict { LOC N3 } [get_ports QSFP0_RX_N[0]] + +# QSFP1 +set_property PACKAGE_PIN P10 [get_ports QSFP1_CLOCK_N]; +set_property PACKAGE_PIN P11 [get_ports QSFP1_CLOCK_P]; + +# QSFP1 +set_property PACKAGE_PIN AR22 [get_ports QSFP1_FS[0]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_FS[0]]; +set_property PACKAGE_PIN AU20 [get_ports QSFP1_FS[1]]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_FS[1]]; +set_property PACKAGE_PIN AR21 [get_ports QSFP1_RESET]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_RESET]; +set_property PACKAGE_PIN AV21 [get_ports QSFP1_INTL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_INTL]; +set_property PACKAGE_PIN AV22 [get_ports QSFP1_LPMODE]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_LPMODE]; +set_property PACKAGE_PIN BC19 [get_ports QSFP1_MODPRSL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_MODPRSL]; +set_property PACKAGE_PIN AY20 [get_ports QSFP1_MODSELL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_MODSELL]; +set_property PACKAGE_PIN BC18 [get_ports QSFP1_RESETL]; +set_property IOSTANDARD LVCMOS12 [get_ports QSFP1_RESETL]; + + +# QSFP1_TX +set_property -dict { LOC P7 } [get_ports QSFP1_TX_P[3]] +set_property -dict { LOC P6 } [get_ports QSFP1_TX_N[3]] +set_property -dict { LOC R9 } [get_ports QSFP1_TX_P[2]] +set_property -dict { LOC R8 } [get_ports QSFP1_TX_N[2]] +set_property -dict { LOC T7 } [get_ports QSFP1_TX_P[1]] +set_property -dict { LOC T6 } [get_ports QSFP1_TX_N[1]] +set_property -dict { LOC U9 } [get_ports QSFP1_TX_P[0]] +set_property -dict { LOC U8 } [get_ports QSFP1_TX_N[0]] + +# QSFP1_RX +set_property -dict { LOC P2 } [get_ports QSFP1_RX_P[3]] +set_property -dict { LOC P1 } [get_ports QSFP1_RX_N[3]] +set_property -dict { LOC R4 } [get_ports QSFP1_RX_P[2]] +set_property -dict { LOC R3 } [get_ports QSFP1_RX_N[2]] +set_property -dict { LOC T2 } [get_ports QSFP1_RX_P[1]] +set_property -dict { LOC T1 } [get_ports QSFP1_RX_N[1]] +set_property -dict { LOC U4 } [get_ports QSFP1_RX_P[0]] +set_property -dict { LOC U3 } [get_ports QSFP1_RX_N[0]] +########################################################################## +# Timing +########################################################################## +# CMAC user clock +create_clock -period 3.103 -name cmac_clk_0 [get_pins -hier -filter name=~*cmac_port[0]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] +create_clock -period 3.103 -name cmac_clk_1 [get_pins -hier -filter name=~*cmac_port[1]*cmac_gtwiz_userclk_tx_inst/txoutclk_out[0]] + +# Registers Clock +create_clock -period 8.000 -name reg_clk [get_pins -hier -filter name=~*u_top_wrapper/xilinx_nic_shell/inst/qdma_subsystem_inst/qdma_wrapper_inst/clk_div_inst/clk_out1] + +# Datapath Clock - 340MHz +create_clock -period 2.941 -name dp_clk [get_pins -hier -filter name=~*u_clk_wiz_1/clk_out1] + +set_false_path -from [get_clocks axis_aclk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_0] +set_false_path -from [get_clocks reg_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks axis_aclk] +set_false_path -from [get_clocks axis_aclk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks reg_clk] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks reg_clk] +set_false_path -from [get_clocks cmac_clk_1] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_1] +set_false_path -from [get_clocks cmac_clk_0] -to [get_clocks dp_clk] +set_false_path -from [get_clocks dp_clk] -to [get_clocks cmac_clk_0] diff --git a/hw/lib/common/hdl/nf_attachment.sv b/hw/lib/common/hdl/nf_attachment.sv new file mode 100644 index 0000000..4548b82 --- /dev/null +++ b/hw/lib/common/hdl/nf_attachment.sv @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2021 Yuta Tokusashi + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory under EPSRC EARL Project EP/P025374/1 alongside support + * from Xilinx Inc. + * + * @NETFPGA_LICENSE_HEADER_START@ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @NETFPGA_LICENSE_HEADER_END@ + * + */ +`timescale 1ps/1ps +module nf_attachment #( + parameter C_NF_TDATA_WIDTH = 512, + parameter C_NF_TUSER_WIDTH = 128, + parameter C_TDATA_WIDTH = 512, + parameter C_TUSER_WIDTH = 128 +)( + // Slave Stream Ports + input [C_NF_TDATA_WIDTH-1:0] axis_dma_o_tdata, + input [(C_NF_TDATA_WIDTH/8)-1:0] axis_dma_o_tkeep, + input [C_NF_TUSER_WIDTH-1:0] axis_dma_o_tuser, + input axis_dma_o_tvalid, + output axis_dma_o_tready, + input axis_dma_o_tlast, + + // Master Stream Ports + output [C_NF_TDATA_WIDTH-1:0] axis_dma_i_tdata, + output [(C_NF_TDATA_WIDTH/8)-1:0]axis_dma_i_tkeep, + output [C_NF_TUSER_WIDTH-1:0] axis_dma_i_tuser, + output axis_dma_i_tvalid, + input axis_dma_i_tready, + output axis_dma_i_tlast, + + // Slave Stream Ports + input [C_NF_TDATA_WIDTH-1:0] axis_o_0_tdata, + input [(C_NF_TDATA_WIDTH/8)-1:0] axis_o_0_tkeep, + input [C_NF_TUSER_WIDTH-1:0] axis_o_0_tuser, + input axis_o_0_tvalid, + output axis_o_0_tready, + input axis_o_0_tlast, + // Slave Stream Ports + input [C_NF_TDATA_WIDTH-1:0] axis_o_1_tdata, + input [(C_NF_TDATA_WIDTH/8)-1:0] axis_o_1_tkeep, + input [C_NF_TUSER_WIDTH-1:0] axis_o_1_tuser, + input axis_o_1_tvalid, + output axis_o_1_tready, + input axis_o_1_tlast, + // Master Stream Ports + output [C_NF_TDATA_WIDTH-1:0] axis_i_0_tdata, + output [(C_NF_TDATA_WIDTH/8)-1:0]axis_i_0_tkeep, + output [C_NF_TUSER_WIDTH-1:0] axis_i_0_tuser, + output axis_i_0_tvalid, + input axis_i_0_tready, + output axis_i_0_tlast, + // Master Stream Ports + output [C_NF_TDATA_WIDTH-1:0] axis_i_1_tdata, + output [(C_NF_TDATA_WIDTH/8)-1:0]axis_i_1_tkeep, + output [C_NF_TUSER_WIDTH-1:0] axis_i_1_tuser, + output axis_i_1_tvalid, + input axis_i_1_tready, + output axis_i_1_tlast, + + input axis_cmac_0_rx_tvalid, + input [C_TDATA_WIDTH-1:0] axis_cmac_0_rx_tdata , + input [(C_TDATA_WIDTH/8)-1:0] axis_cmac_0_rx_tkeep , + input axis_cmac_0_rx_tuser_err, + input axis_cmac_0_rx_tlast , + + input axis_cmac_1_rx_tvalid, + input [C_TDATA_WIDTH-1:0] axis_cmac_1_rx_tdata , + input [(C_TDATA_WIDTH/8)-1:0] axis_cmac_1_rx_tkeep , + input axis_cmac_1_rx_tuser_err , + input axis_cmac_1_rx_tlast , + + output axis_cmac_0_tx_tvalid, + output [C_TDATA_WIDTH-1:0] axis_cmac_0_tx_tdata , + output [(C_TDATA_WIDTH/8)-1:0] axis_cmac_0_tx_tkeep , + output axis_cmac_0_tx_tuser_err , + output axis_cmac_0_tx_tlast , + input axis_cmac_0_tx_tready, + + output axis_cmac_1_tx_tvalid, + output [C_TDATA_WIDTH-1:0] axis_cmac_1_tx_tdata , + output [(C_TDATA_WIDTH/8)-1:0] axis_cmac_1_tx_tkeep , + output axis_cmac_1_tx_tuser_err , + output axis_cmac_1_tx_tlast , + input axis_cmac_1_tx_tready, + + + output s_axis_qdma_c2h_0_tvalid, + output [511:0] s_axis_qdma_c2h_0_tdata , + output [63:0] s_axis_qdma_c2h_0_tkeep , + output s_axis_qdma_c2h_0_tlast , + output [15:0] s_axis_qdma_c2h_0_tuser_size, + output [15:0] s_axis_qdma_c2h_0_tuser_src, + output [15:0] s_axis_qdma_c2h_0_tuser_dst, + input s_axis_qdma_c2h_0_tready, + + output s_axis_qdma_c2h_1_tvalid, + output [511:0] s_axis_qdma_c2h_1_tdata , + output [63:0] s_axis_qdma_c2h_1_tkeep , + output s_axis_qdma_c2h_1_tlast , + output [15:0] s_axis_qdma_c2h_1_tuser_size, + output [15:0] s_axis_qdma_c2h_1_tuser_src, + output [15:0] s_axis_qdma_c2h_1_tuser_dst, + input s_axis_qdma_c2h_1_tready, + + input m_axis_qdma_h2c_0_tvalid, + input [511:0] m_axis_qdma_h2c_0_tdata , + input [63:0] m_axis_qdma_h2c_0_tkeep , + input m_axis_qdma_h2c_0_tlast , + input [15:0] m_axis_qdma_h2c_0_tuser_size, + input [15:0] m_axis_qdma_h2c_0_tuser_src, + input [15:0] m_axis_qdma_h2c_0_tuser_dst, + output m_axis_qdma_h2c_0_tready, + + input m_axis_qdma_h2c_1_tvalid, + input [511:0] m_axis_qdma_h2c_1_tdata , + input [63:0] m_axis_qdma_h2c_1_tkeep , + input m_axis_qdma_h2c_1_tlast , + input [15:0] m_axis_qdma_h2c_1_tuser_size, + input [15:0] m_axis_qdma_h2c_1_tuser_src, + input [15:0] m_axis_qdma_h2c_1_tuser_dst, + output m_axis_qdma_h2c_1_tready, + + input m0_axil_awvalid, + input [31:0] m0_axil_awaddr, + output m0_axil_awready, + input m0_axil_wvalid, + input [31:0] m0_axil_wdata, + output m0_axil_wready, + output m0_axil_bvalid, + output [1:0] m0_axil_bresp, + input m0_axil_bready, + input m0_axil_arvalid, + input [31:0] m0_axil_araddr, + output m0_axil_arready, + output m0_axil_rvalid, + output [31:0] m0_axil_rdata, + output [1:0] m0_axil_rresp, + input m0_axil_rready, + + input [1:0] cmac_clk, + input core_clk, + input axis_aclk, + input axil_aclk, + output axis_rst, + output axil_rst +); + + // Parameters + localparam CMAC0_IFNUM = 8'b0000_0001; + localparam CMAC1_IFNUM = 8'b0000_0100; + localparam QDMA0_IFNUM = 8'b0000_0010; + localparam QDMA1_IFNUM = 8'b0000_1000; + + localparam QDMA0_TDEST = 16'h0; + localparam QDMA1_TDEST = 16'h1; + + localparam NF_TUSER_SRCPORT_START = 16; + localparam NF_TUSER_SRCPORT_WIDTH = 8; + localparam NF_TUSER_DSTPORT_START = 24; + localparam NF_TUSER_DSTPORT_WIDTH = 8; + + localparam NF_TUSER_SRCPORT_CMAC0 = NF_TUSER_SRCPORT_START; + localparam NF_TUSER_SRCPORT_CMAC1 = NF_TUSER_SRCPORT_START + 2; + localparam NF_TUSER_SRCPORT_QDMA0 = NF_TUSER_SRCPORT_START + 1; + localparam NF_TUSER_SRCPORT_QDMA1 = NF_TUSER_SRCPORT_START + 3; + + localparam NF_TUSER_DSTPORT_CMAC0 = NF_TUSER_DSTPORT_START; + localparam NF_TUSER_DSTPORT_CMAC1 = NF_TUSER_DSTPORT_START + 2; + localparam NF_TUSER_DSTPORT_QDMA0 = NF_TUSER_DSTPORT_START + 1; + localparam NF_TUSER_DSTPORT_QDMA1 = NF_TUSER_DSTPORT_START + 3; + + // Reset + reg [9:0] axis_rst_cnt = 10'd0; + reg [9:0] axil_rst_cnt = 10'd0; + reg [9:0] cmac0_rst_cnt = 10'd0; + reg [9:0] cmac1_rst_cnt = 10'd0; + reg [9:0] core_rst_cnt = 10'd0; + reg axis_rst_reg, axil_rst_reg, cmac0_rst_reg, cmac1_rst_reg; + reg core_rst_reg; + assign axis_rst = axis_rst_reg; + assign axil_rst = axil_rst_reg; + wire cmac0_rst = cmac0_rst_reg; + wire cmac1_rst = cmac1_rst_reg; + wire core_rst = core_rst_reg; + + always @ (posedge cmac_clk[0]) begin + if (cmac0_rst_cnt != 10'h3ff) begin + cmac0_rst_cnt <= cmac0_rst_cnt + 10'd1; + cmac0_rst_reg <= 1'b1; + end + else begin + cmac0_rst_reg <= 1'b0; + end + end + + always @ (posedge cmac_clk[1]) begin + if (cmac1_rst_cnt != 10'h3ff) begin + cmac1_rst_cnt <= cmac1_rst_cnt + 10'd1; + cmac1_rst_reg <= 1'b1; + end + else begin + cmac1_rst_reg <= 1'b0; + end + end + + always @ (posedge axis_aclk) begin + if (axis_rst_cnt != 10'h3ff) begin + axis_rst_cnt <= axis_rst_cnt + 10'd1; + axis_rst_reg <= 1'b1; + end + else begin + axis_rst_reg <= 1'b0; + end + end + + always @ (posedge axil_aclk) begin + if (axil_rst_cnt != 10'h3ff) begin + axil_rst_cnt <= axil_rst_cnt + 10'd1; + axil_rst_reg <= 1'b1; + end + else begin + axil_rst_reg <= 1'b0; + end + end + + always @ (posedge core_clk) begin + if (core_rst_cnt != 10'h3ff) begin + core_rst_cnt <= core_rst_cnt + 10'd1; + core_rst_reg <= 1'b1; + end + else begin + core_rst_reg <= 1'b0; + end + end + + wire S2_AXI_ACLK, S1_AXI_ACLK, S0_AXI_ACLK; + wire S2_AXI_ARESETN, S1_AXI_ARESETN, S0_AXI_ARESETN; + wire[31 : 0] S2_AXI_AWADDR, S1_AXI_AWADDR, S0_AXI_AWADDR; + wire S2_AXI_AWVALID, S1_AXI_AWVALID, S0_AXI_AWVALID; + wire[31 : 0] S2_AXI_WDATA, S1_AXI_WDATA, S0_AXI_WDATA; + wire[3 : 0] S2_AXI_WSTRB, S1_AXI_WSTRB, S0_AXI_WSTRB; + wire S2_AXI_WVALID, S1_AXI_WVALID, S0_AXI_WVALID; + wire S2_AXI_BREADY, S1_AXI_BREADY, S0_AXI_BREADY; + wire[31 : 0] S2_AXI_ARADDR, S1_AXI_ARADDR, S0_AXI_ARADDR; + wire S2_AXI_ARVALID, S1_AXI_ARVALID, S0_AXI_ARVALID; + wire S2_AXI_RREADY, S1_AXI_RREADY, S0_AXI_RREADY; + wire S2_AXI_ARREADY, S1_AXI_ARREADY, S0_AXI_ARREADY; + wire[31 : 0] S2_AXI_RDATA, S1_AXI_RDATA, S0_AXI_RDATA; + wire[1 : 0] S2_AXI_RRESP, S1_AXI_RRESP, S0_AXI_RRESP; + wire S2_AXI_RVALID, S1_AXI_RVALID, S0_AXI_RVALID; + wire S2_AXI_WREADY, S1_AXI_WREADY, S0_AXI_WREADY; + wire[1 :0] S2_AXI_BRESP, S1_AXI_BRESP, S0_AXI_BRESP; + wire S2_AXI_BVALID, S1_AXI_BVALID, S0_AXI_BVALID; + wire S2_AXI_AWREADY, S1_AXI_AWREADY, S0_AXI_AWREADY; + + axi_crossbar_0 u_crossbar_m0 ( + .aclk (axil_aclk), + .aresetn (!axil_rst), + .s_axi_awaddr (m0_axil_awaddr ), + .s_axi_awprot (), + .s_axi_awvalid (m0_axil_awvalid), + .s_axi_awready (m0_axil_awready), + .s_axi_wdata (m0_axil_wdata ), + .s_axi_wstrb (4'b1111), + .s_axi_wvalid (m0_axil_wvalid ), + .s_axi_wready (m0_axil_wready ), + .s_axi_bresp (m0_axil_bresp ), + .s_axi_bvalid (m0_axil_bvalid ), + .s_axi_bready (m0_axil_bready ), + .s_axi_araddr (m0_axil_araddr), + .s_axi_arprot (), + .s_axi_arvalid (m0_axil_arvalid ), + .s_axi_arready (m0_axil_arready ), + .s_axi_rdata (m0_axil_rdata ), + .s_axi_rresp (m0_axil_rresp ), + .s_axi_rvalid (m0_axil_rvalid ), + .s_axi_rready (m0_axil_rready ), + .m_axi_awaddr ({S2_AXI_AWADDR ,S1_AXI_AWADDR ,S0_AXI_AWADDR }), + .m_axi_awprot (), + .m_axi_awvalid ({S2_AXI_AWVALID,S1_AXI_AWVALID,S0_AXI_AWVALID}), + .m_axi_awready ({S2_AXI_AWREADY,S1_AXI_AWREADY,S0_AXI_AWREADY}), + .m_axi_wdata ({S2_AXI_WDATA ,S1_AXI_WDATA ,S0_AXI_WDATA }), + .m_axi_wstrb ({S2_AXI_WSTRB ,S1_AXI_WSTRB ,S0_AXI_WSTRB }), + .m_axi_wvalid ({S2_AXI_WVALID ,S1_AXI_WVALID ,S0_AXI_WVALID }), + .m_axi_wready ({S2_AXI_WREADY ,S1_AXI_WREADY ,S0_AXI_WREADY }), + .m_axi_bresp ({S2_AXI_BRESP ,S1_AXI_BRESP ,S0_AXI_BRESP }), + .m_axi_bvalid ({S2_AXI_BVALID ,S1_AXI_BVALID ,S0_AXI_BVALID }), + .m_axi_bready ({S2_AXI_BREADY ,S1_AXI_BREADY ,S0_AXI_BREADY }), + .m_axi_araddr ({S2_AXI_ARADDR ,S1_AXI_ARADDR ,S0_AXI_ARADDR }), + .m_axi_arprot (), + .m_axi_arvalid ({S2_AXI_ARVALID,S1_AXI_ARVALID,S0_AXI_ARVALID}), + .m_axi_arready ({S2_AXI_ARREADY,S1_AXI_ARREADY,S0_AXI_ARREADY}), + .m_axi_rdata ({S2_AXI_RDATA ,S1_AXI_RDATA ,S0_AXI_RDATA }), + .m_axi_rresp ({S2_AXI_RRESP ,S1_AXI_RRESP ,S0_AXI_RRESP }), + .m_axi_rvalid ({S2_AXI_RVALID ,S1_AXI_RVALID ,S0_AXI_RVALID }), + .m_axi_rready ({S2_AXI_RREADY ,S1_AXI_RREADY ,S0_AXI_RREADY }) + ); + wire [C_TDATA_WIDTH-1:0] axis_dma_conv_o_tdata , axis_dma_conv_i_tdata ; + wire [C_TDATA_WIDTH/8-1:0] axis_dma_conv_o_tkeep , axis_dma_conv_i_tkeep ; + wire axis_dma_conv_o_tlast , axis_dma_conv_i_tlast ; + wire axis_dma_conv_o_tready, axis_dma_conv_i_tready; + wire [C_TUSER_WIDTH-1:0] axis_dma_conv_o_tuser , axis_dma_conv_i_tuser ; + wire axis_dma_conv_o_tvalid, axis_dma_conv_i_tvalid; + wire [15:0] axis_dma_conv_o_tuser_size, axis_dma_conv_i_tuser_size; + wire [15:0] axis_dma_conv_o_tuser_src , axis_dma_conv_i_tuser_src ; + wire [15:0] axis_dma_conv_o_tuser_dst , axis_dma_conv_i_tuser_dst ; + + nf_mac_attachment_dma_ip u_nf_attachment_dma ( + .S_AXI_ACLK (axil_aclk), + .S_AXI_ARESETN (!axil_rst), + .S_AXI_AWADDR (S2_AXI_AWADDR), + .S_AXI_AWVALID (S2_AXI_AWVALID), + .S_AXI_WDATA (S2_AXI_WDATA), + .S_AXI_WSTRB (S2_AXI_WSTRB), + .S_AXI_WVALID (S2_AXI_WVALID), + .S_AXI_BREADY (S2_AXI_BREADY), + .S_AXI_ARADDR (S2_AXI_ARADDR), + .S_AXI_ARVALID (S2_AXI_ARVALID), + .S_AXI_RREADY (S2_AXI_RREADY), + .S_AXI_ARREADY (S2_AXI_ARREADY), + .S_AXI_RDATA (S2_AXI_RDATA), + .S_AXI_RRESP (S2_AXI_RRESP), + .S_AXI_RVALID (S2_AXI_RVALID), + .S_AXI_WREADY (S2_AXI_WREADY), + .S_AXI_BRESP (S2_AXI_BRESP), + .S_AXI_BVALID (S2_AXI_BVALID), + .S_AXI_AWREADY (S2_AXI_AWREADY), + // 10GE block clk & rst + .clk156 (axis_aclk), + .areset_clk156 (axis_rst), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (axis_dma_conv_i_tdata), + .m_axis_mac_tkeep (axis_dma_conv_i_tkeep), + .m_axis_mac_tvalid (axis_dma_conv_i_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (axis_dma_conv_i_tuser), + .m_axis_mac_tlast (axis_dma_conv_i_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (axis_dma_conv_o_tdata), + .s_axis_mac_tkeep (axis_dma_conv_o_tkeep), + .s_axis_mac_tvalid (axis_dma_conv_o_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (axis_dma_conv_o_tuser), + .s_axis_mac_tlast (axis_dma_conv_o_tlast), + .s_axis_mac_tready (axis_dma_conv_o_tready), + + // TX/RX DATA channels + .interface_number (8'd0), + + // NFPLUS pipeline clk & rst + .axis_aclk (core_clk), + .axis_aresetn (!core_rst), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_dma_o_tdata), + .s_axis_pipe_tkeep (axis_dma_o_tkeep), + .s_axis_pipe_tlast (axis_dma_o_tlast), + .s_axis_pipe_tuser (axis_dma_o_tuser), + .s_axis_pipe_tvalid (axis_dma_o_tvalid), + .s_axis_pipe_tready (axis_dma_o_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_dma_i_tdata), + .m_axis_pipe_tkeep (axis_dma_i_tkeep), + .m_axis_pipe_tlast (axis_dma_i_tlast), + .m_axis_pipe_tuser (axis_dma_i_tuser), + .m_axis_pipe_tvalid (axis_dma_i_tvalid), + .m_axis_pipe_tready (axis_dma_i_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_0 ( + .S_AXI_ACLK (axil_aclk), + .S_AXI_ARESETN (!axil_rst), + .S_AXI_AWADDR (S0_AXI_AWADDR), + .S_AXI_AWVALID (S0_AXI_AWVALID), + .S_AXI_WDATA (S0_AXI_WDATA), + .S_AXI_WSTRB (S0_AXI_WSTRB), + .S_AXI_WVALID (S0_AXI_WVALID), + .S_AXI_BREADY (S0_AXI_BREADY), + .S_AXI_ARADDR (S0_AXI_ARADDR), + .S_AXI_ARVALID (S0_AXI_ARVALID), + .S_AXI_RREADY (S0_AXI_RREADY), + .S_AXI_ARREADY (S0_AXI_ARREADY), + .S_AXI_RDATA (S0_AXI_RDATA), + .S_AXI_RRESP (S0_AXI_RRESP), + .S_AXI_RVALID (S0_AXI_RVALID), + .S_AXI_WREADY (S0_AXI_WREADY), + .S_AXI_BRESP (S0_AXI_BRESP), + .S_AXI_BVALID (S0_AXI_BVALID), + .S_AXI_AWREADY (S0_AXI_AWREADY), + // 10GE block clk & rst + .clk156 (cmac_clk[0]), + .areset_clk156 (cmac0_rst), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (axis_cmac_0_rx_tdata), + .m_axis_mac_tkeep (axis_cmac_0_rx_tkeep), + .m_axis_mac_tvalid (axis_cmac_0_rx_tvalid), + .m_axis_mac_tuser_err (!axis_cmac_0_rx_tuser_err), // valid frame + .m_axis_mac_tuser (), + .m_axis_mac_tlast (axis_cmac_0_rx_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (axis_cmac_0_tx_tdata), + .s_axis_mac_tkeep (axis_cmac_0_tx_tkeep), + .s_axis_mac_tvalid (axis_cmac_0_tx_tvalid), + .s_axis_mac_tuser_err (axis_cmac_0_tx_tuser_err), //underrun + .s_axis_mac_tuser (), //underrun + .s_axis_mac_tlast (axis_cmac_0_tx_tlast), + .s_axis_mac_tready (axis_cmac_0_tx_tready), + + // TX/RX DATA channels + .interface_number (CMAC0_IFNUM), + + // NFPLUS pipeline clk & rst + .axis_aclk (core_clk), + .axis_aresetn (!core_rst), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_0_tdata), + .s_axis_pipe_tkeep (axis_o_0_tkeep), + .s_axis_pipe_tlast (axis_o_0_tlast), + .s_axis_pipe_tuser (axis_o_0_tuser), + .s_axis_pipe_tvalid (axis_o_0_tvalid), + .s_axis_pipe_tready (axis_o_0_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_0_tdata), + .m_axis_pipe_tkeep (axis_i_0_tkeep), + .m_axis_pipe_tlast (axis_i_0_tlast), + .m_axis_pipe_tuser (axis_i_0_tuser), + .m_axis_pipe_tvalid (axis_i_0_tvalid), + .m_axis_pipe_tready (axis_i_0_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_1 ( + .S_AXI_ACLK (axil_aclk), + .S_AXI_ARESETN (!axil_rst), + .S_AXI_AWADDR (S1_AXI_AWADDR), + .S_AXI_AWVALID (S1_AXI_AWVALID), + .S_AXI_WDATA (S1_AXI_WDATA), + .S_AXI_WSTRB (S1_AXI_WSTRB), + .S_AXI_WVALID (S1_AXI_WVALID), + .S_AXI_BREADY (S1_AXI_BREADY), + .S_AXI_ARADDR (S1_AXI_ARADDR), + .S_AXI_ARVALID (S1_AXI_ARVALID), + .S_AXI_RREADY (S1_AXI_RREADY), + .S_AXI_ARREADY (S1_AXI_ARREADY), + .S_AXI_RDATA (S1_AXI_RDATA), + .S_AXI_RRESP (S1_AXI_RRESP), + .S_AXI_RVALID (S1_AXI_RVALID), + .S_AXI_WREADY (S1_AXI_WREADY), + .S_AXI_BRESP (S1_AXI_BRESP), + .S_AXI_BVALID (S1_AXI_BVALID), + .S_AXI_AWREADY (S1_AXI_AWREADY), + // 10GE block clk & rst + .clk156 (cmac_clk[1]), + .areset_clk156 (cmac1_rst), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (axis_cmac_1_rx_tdata), + .m_axis_mac_tkeep (axis_cmac_1_rx_tkeep), + .m_axis_mac_tvalid (axis_cmac_1_rx_tvalid), + .m_axis_mac_tuser_err (!axis_cmac_1_rx_tuser_err), // valid frame + .m_axis_mac_tuser (), + .m_axis_mac_tlast (axis_cmac_1_rx_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (axis_cmac_1_tx_tdata), + .s_axis_mac_tkeep (axis_cmac_1_tx_tkeep), + .s_axis_mac_tvalid (axis_cmac_1_tx_tvalid), + .s_axis_mac_tuser_err (axis_cmac_1_tx_tuser_err), //underrun + .s_axis_mac_tuser (), //underrun + .s_axis_mac_tlast (axis_cmac_1_tx_tlast), + .s_axis_mac_tready (axis_cmac_1_tx_tready), + + // TX/RX DATA channels + .interface_number (CMAC1_IFNUM), + + // NFPLUS pipeline clk & rst + .axis_aclk (core_clk), + .axis_aresetn (!core_rst), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_1_tdata), + .s_axis_pipe_tkeep (axis_o_1_tkeep), + .s_axis_pipe_tlast (axis_o_1_tlast), + .s_axis_pipe_tuser (axis_o_1_tuser), + .s_axis_pipe_tvalid (axis_o_1_tvalid), + .s_axis_pipe_tready (axis_o_1_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_1_tdata), + .m_axis_pipe_tkeep (axis_i_1_tkeep), + .m_axis_pipe_tlast (axis_i_1_tlast), + .m_axis_pipe_tuser (axis_i_1_tuser), + .m_axis_pipe_tvalid (axis_i_1_tvalid), + .m_axis_pipe_tready (axis_i_1_tready) + ); + + reg arb_0, arb_1; + reg arb_0_reg, arb_1_reg; + + assign axis_dma_conv_i_tvalid = (arb_0) ? m_axis_qdma_h2c_0_tvalid : m_axis_qdma_h2c_1_tvalid; + assign axis_dma_conv_i_tdata = (arb_0) ? m_axis_qdma_h2c_0_tdata : m_axis_qdma_h2c_1_tdata; + assign axis_dma_conv_i_tkeep = (arb_0) ? m_axis_qdma_h2c_0_tkeep : m_axis_qdma_h2c_1_tkeep; + assign axis_dma_conv_i_tlast = (arb_0) ? m_axis_qdma_h2c_0_tlast : m_axis_qdma_h2c_1_tlast; + + assign axis_dma_conv_i_tuser[15:0] = (arb_0) ? m_axis_qdma_h2c_0_tuser_size : m_axis_qdma_h2c_1_tuser_size; + assign axis_dma_conv_i_tuser[23:16] = (arb_0) ? QDMA0_IFNUM /*m_axis_qdma_h2c_0_tuser_src[7:0]*/ : QDMA1_IFNUM/*m_axis_qdma_h2c_1_tuser_src[7:0]*/; + assign axis_dma_conv_i_tuser[31:24] = 0;//(arb_0) ? m_axis_qdma_h2c_0_tuser_dst[7:0] : m_axis_qdma_h2c_1_tuser_dst[7:0]; + assign axis_dma_conv_i_tuser[127:32] = 0; + + reg last_flip0, last_flip1; + + always @(*) begin + arb_0 = arb_0_reg; + arb_1 = arb_1_reg; + + if (last_flip0) begin + arb_0 = 0; + end + if (m_axis_qdma_h2c_0_tvalid && arb_1 == 0) begin + arb_0 = 1; + end + + if (last_flip1) begin + arb_1 = 0; + end + if (m_axis_qdma_h2c_1_tvalid && arb_0 == 0) begin + arb_1 = 1; + end + end + + always @(posedge axis_aclk) begin + if (axis_rst) begin + arb_0_reg <= 0; + arb_1_reg <= 0; + last_flip0 <= 0; + last_flip1 <= 0; + end + else begin + arb_0_reg <= arb_0; + arb_1_reg <= arb_1; + last_flip0 <= m_axis_qdma_h2c_0_tvalid && m_axis_qdma_h2c_0_tlast; + last_flip1 <= m_axis_qdma_h2c_1_tvalid && m_axis_qdma_h2c_1_tlast; + end + end + + reg [15:0] s_axis_qdma_c2h_0_tuser_size_r, s_axis_qdma_c2h_0_tuser_size_d; + reg [15:0] s_axis_qdma_c2h_1_tuser_size_r, s_axis_qdma_c2h_1_tuser_size_d; + reg [15:0] s_axis_qdma_c2h_0_tuser_dst_r , s_axis_qdma_c2h_0_tuser_dst_d; + reg [15:0] s_axis_qdma_c2h_1_tuser_dst_r , s_axis_qdma_c2h_1_tuser_dst_d; + localparam IDLE = 0; + localparam PKT = 1; + reg state, state_next; + + always @(*) begin + s_axis_qdma_c2h_0_tuser_size_r = s_axis_qdma_c2h_0_tuser_size_d; + s_axis_qdma_c2h_1_tuser_size_r = s_axis_qdma_c2h_1_tuser_size_d; + s_axis_qdma_c2h_0_tuser_dst_r = s_axis_qdma_c2h_0_tuser_dst_d; + s_axis_qdma_c2h_1_tuser_dst_r = s_axis_qdma_c2h_1_tuser_dst_d; + state_next = state; + + case(state) + IDLE: begin + if (axis_dma_conv_o_tvalid && axis_dma_conv_o_tready) begin + if (axis_dma_conv_o_tuser_dst[1]) begin + s_axis_qdma_c2h_0_tuser_size_r = axis_dma_conv_o_tuser_size; + s_axis_qdma_c2h_0_tuser_dst_r = 16'b0000_0000_0000_0001; + end + if (axis_dma_conv_o_tuser_dst[3]) begin + s_axis_qdma_c2h_1_tuser_size_r = axis_dma_conv_o_tuser_size; + s_axis_qdma_c2h_1_tuser_dst_r = 16'b0000_0000_0000_0010; + end + if (axis_dma_conv_o_tlast) + state_next = IDLE; + else + state_next = PKT; + end + end + PKT: begin + if (axis_dma_conv_o_tvalid && axis_dma_conv_o_tready) begin + if (axis_dma_conv_o_tlast) + state_next = IDLE; + else + state_next = PKT; + end + end + default:; + endcase + end + + always @(posedge axis_aclk) begin + if (axis_rst) begin + state <= 0; + s_axis_qdma_c2h_0_tuser_size_d <= 0; + s_axis_qdma_c2h_1_tuser_size_d <= 0; + s_axis_qdma_c2h_0_tuser_dst_d <= 0; + s_axis_qdma_c2h_1_tuser_dst_d <= 0; + end + else begin + state <= state_next; + s_axis_qdma_c2h_0_tuser_size_d <= s_axis_qdma_c2h_0_tuser_size_r; + s_axis_qdma_c2h_1_tuser_size_d <= s_axis_qdma_c2h_1_tuser_size_r; + s_axis_qdma_c2h_0_tuser_dst_d <= s_axis_qdma_c2h_0_tuser_dst_r; + s_axis_qdma_c2h_1_tuser_dst_d <= s_axis_qdma_c2h_1_tuser_dst_r; + end + end + + assign s_axis_qdma_c2h_0_tvalid = (axis_dma_conv_o_tuser_dst[1]) ? axis_dma_conv_o_tvalid : 1'b0; + assign s_axis_qdma_c2h_0_tlast = axis_dma_conv_o_tlast; + assign s_axis_qdma_c2h_0_tdata = axis_dma_conv_o_tdata; + assign s_axis_qdma_c2h_0_tkeep = axis_dma_conv_o_tkeep; + //assign s_axis_qdma_c2h_0_tuser_size = axis_dma_conv_o_tuser_size; + assign s_axis_qdma_c2h_0_tuser_size = s_axis_qdma_c2h_0_tuser_size_r; + assign s_axis_qdma_c2h_0_tuser_src = axis_dma_conv_o_tuser_src; + assign s_axis_qdma_c2h_0_tuser_dst = s_axis_qdma_c2h_0_tuser_dst_r; + //assign s_axis_qdma_c2h_0_tuser_dst = (axis_dma_conv_o_tuser_dst == {8'd0, QDMA0_IFNUM}) ? 16'b01 : + // (axis_dma_conv_o_tuser_dst == {8'd0, QDMA1_IFNUM}) ? 16'b10 : 16'd0; + + assign s_axis_qdma_c2h_1_tvalid = (axis_dma_conv_o_tuser_dst[3]) ? axis_dma_conv_o_tvalid : 1'b0; + assign s_axis_qdma_c2h_1_tlast = axis_dma_conv_o_tlast; + assign s_axis_qdma_c2h_1_tkeep = axis_dma_conv_o_tkeep; + assign s_axis_qdma_c2h_1_tdata = axis_dma_conv_o_tdata; + //assign s_axis_qdma_c2h_1_tuser_size = axis_dma_conv_o_tuser_size; + assign s_axis_qdma_c2h_1_tuser_size = s_axis_qdma_c2h_1_tuser_size_r; + assign s_axis_qdma_c2h_1_tuser_src = axis_dma_conv_o_tuser_src; + assign s_axis_qdma_c2h_1_tuser_dst = s_axis_qdma_c2h_1_tuser_dst_r; + //assign s_axis_qdma_c2h_1_tuser_dst = (axis_dma_conv_o_tuser_dst == {8'd0, QDMA0_IFNUM}) ? 16'b01 : + // (axis_dma_conv_o_tuser_dst == {8'd0, QDMA1_IFNUM}) ? 16'b10 : 16'd0; + assign axis_dma_conv_o_tready = s_axis_qdma_c2h_0_tready && s_axis_qdma_c2h_1_tready; + + // todo + assign m_axis_qdma_h2c_0_tready = 1'b1; + assign m_axis_qdma_h2c_1_tready = 1'b1; + + // ToDo : broadcast to DMA ? or fixed direction? + assign axis_dma_conv_o_tuser_size = axis_dma_conv_o_tuser[15:0]; + assign axis_dma_conv_o_tuser_src = {8'h0, axis_dma_conv_o_tuser[23:16]}; + assign axis_dma_conv_o_tuser_dst = {8'h0, axis_dma_conv_o_tuser[31:24]}; + +endmodule diff --git a/hw/lib/common/hdl/top.v b/hw/lib/common/hdl/top.v new file mode 100644 index 0000000..b7f6197 --- /dev/null +++ b/hw/lib/common/hdl/top.v @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2021 University of Cambridge + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory under EPSRC EARL Project EP/P025374/1 alongside support + * from Xilinx Inc. + * + * @NETFPGA_LICENSE_HEADER_START@ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @NETFPGA_LICENSE_HEADER_END@ + * + */ +`default_nettype none +`timescale 1ns/1ns + +module top #( + parameter SIMULATIOM = "FALSE", + parameter BOARD = "AU280", + parameter C_NF_DATA_WIDTH = 512 , + parameter C_NF_TUSER_WIDTH = 128, + parameter C_IF_DATA_WIDTH = 512, + parameter C_IF_TUSER_WIDTH = 128, + parameter NF_C_S_AXI_DATA_WIDTH = 32, + parameter NF_C_S_AXI_ADDR_WIDTH = 32 +)( +`ifdef BOARD_AU280 + output wire STAT_CATTRIP, +`endif + input wire QSFP0_CLOCK_P, + input wire QSFP0_CLOCK_N, + input wire QSFP1_CLOCK_P, + input wire QSFP1_CLOCK_N, + + /* QSFP port 0 */ +`ifndef BOARD_AU280 + output wire [1:0] QSFP0_FS, + + input wire QSFP0_INTL, + output wire QSFP0_LPMODE, + input wire QSFP0_MODPRSL, + output wire QSFP0_MODSELL, + output wire QSFP0_RESETL, +`else + output wire QSFP0_FS, +`endif /* BOARD_AU280 */ + output wire QSFP0_RESET, + + output wire [3:0] QSFP0_TX_P, + output wire [3:0] QSFP0_TX_N, + input wire [3:0] QSFP0_RX_P, + input wire [3:0] QSFP0_RX_N, + + /* QSFP port 1 */ +`ifndef BOARD_AU280 + output wire [1:0] QSFP1_FS, + + input wire QSFP1_INTL, + output wire QSFP1_LPMODE, + input wire QSFP1_MODPRSL, + output wire QSFP1_MODSELL, + output wire QSFP1_RESETL, +`else + output wire QSFP1_FS, +`endif /* BOARD_AU280 */ + output wire QSFP1_RESET, + + output wire [3:0] QSFP1_TX_P, + output wire [3:0] QSFP1_TX_N, + input wire [3:0] QSFP1_RX_P, + input wire [3:0] QSFP1_RX_N, + + input wire sysclk_p, + input wire sysclk_n, + + input wire pci_clk_p, + input wire pci_clk_n, + input wire pci_rst_n, + + output wire [15:0] pcie_txp, + output wire [15:0] pcie_txn, + input wire [15:0] pcie_rxp, + input wire [15:0] pcie_rxn +); + +`ifdef BOARD_AU280 + assign STAT_CATTRIP = 1'b0; +`endif + +`ifndef BOARD_AU280 + // QSFP Clock for 156.25MHz (2'b01) + // QSFP Clock for 161MHz (2'b1X) + assign QSFP0_FS = 2'b11; + assign QSFP0_RESET = 1'b0; + assign QSFP0_LPMODE = 1'b0; + assign QSFP0_MODSELL = 1'b0; + assign QSFP0_RESETL = 1'b1; + + // QSFP Clock for 156.25MHz (2'b01) + // QSFP Clock for 161MHz (2'b1X) + assign QSFP1_FS = 2'b11; + assign QSFP1_RESET = 1'b0; + assign QSFP1_LPMODE = 1'b0; + assign QSFP1_MODSELL = 1'b0; + assign QSFP1_RESETL = 1'b1; +`else + // QSFP Clock for 156.25MHz + assign QSFP0_FS = 1'b0; + assign QSFP0_RESET = 1'b0; + // QSFP Clock for 156.25MHz + assign QSFP1_FS = 1'b0; + assign QSFP1_RESET = 1'b0; +`endif /*BOARD_AU280*/ + + /* clock infrastracture */ + wire sysclk_ibufds; + IBUFDS IBUFDS_sysclk ( + .I(sysclk_p), + .IB(sysclk_n), + .O(sysclk_ibufds) + ); + + wire sys_clk; + reg clk_div = 1'b0; + always @ (posedge sysclk_ibufds) + clk_div <= ~clk_div; + BUFG bufg_clk ( + .I (clk_div), + .O (sys_clk) + ); + + reg [13:0] cold_counter = 14'd0; + reg sys_rst; + always @ (posedge sys_clk) begin + if (cold_counter != 14'h10) begin + cold_counter <= cold_counter + 14'd1; + sys_rst <= 1'b1; + end + else begin + sys_rst <= 1'b0; + end + end + + wire axis_aclk, axil_aclk; + wire axis_rst, axil_rst; + + wire core_clk; + wire locked; + wire core_rst = ~locked; + + clk_wiz_1 u_clk_wiz_1 ( + .clk_out1(core_clk), + .reset (axis_rst), + .locked (locked), + .clk_in1 (axis_aclk) // DMA clock (250MHz) + ); + + //-- AXI Master Write Address Channel + wire [31:0] m_axil_awaddr; + wire [2:0] m_axil_awprot; + wire m_axil_awvalid; + wire m_axil_awready; + + //-- AXI Master Write Data Channel + wire [31:0] m_axil_wdata; + wire [3:0] m_axil_wstrb = 4'hf; + wire m_axil_wvalid; + wire m_axil_wready; + + //-- AXI Master Write Response Channel + wire m_axil_bvalid; + wire m_axil_bready; + + //-- AXI Master Read Address Channel + wire [31:0] m_axil_araddr; + wire [2:0] m_axil_arprot; + wire m_axil_arvalid; + wire m_axil_arready; + + //-- AXI Master Read Data Channel + wire [31:0] m_axil_rdata; + wire [1:0] m_axil_rresp; + wire m_axil_rvalid; + wire m_axil_rready; + wire [1:0] m_axil_bresp; + + wire [NF_C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_AWADDR , S1_AXI_AWADDR , S0_AXI_AWADDR; + wire S2_AXI_AWVALID, S1_AXI_AWVALID, S0_AXI_AWVALID; + wire [NF_C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_WDATA , S1_AXI_WDATA , S0_AXI_WDATA; + wire [NF_C_S_AXI_DATA_WIDTH/8-1 : 0] S2_AXI_WSTRB , S1_AXI_WSTRB , S0_AXI_WSTRB; + wire S2_AXI_WVALID , S1_AXI_WVALID , S0_AXI_WVALID; + wire S2_AXI_BREADY , S1_AXI_BREADY , S0_AXI_BREADY; + wire [NF_C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_ARADDR , S1_AXI_ARADDR , S0_AXI_ARADDR; + wire S2_AXI_ARVALID, S1_AXI_ARVALID, S0_AXI_ARVALID; + wire S2_AXI_RREADY , S1_AXI_RREADY , S0_AXI_RREADY; + wire S2_AXI_ARREADY, S1_AXI_ARREADY, S0_AXI_ARREADY; + wire [NF_C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_RDATA , S1_AXI_RDATA , S0_AXI_RDATA; + wire [1 : 0] S2_AXI_RRESP , S1_AXI_RRESP , S0_AXI_RRESP; + wire S2_AXI_RVALID , S1_AXI_RVALID , S0_AXI_RVALID; + wire S2_AXI_WREADY , S1_AXI_WREADY , S0_AXI_WREADY; + wire [1 :0] S2_AXI_BRESP , S1_AXI_BRESP , S0_AXI_BRESP; + wire S2_AXI_BVALID , S1_AXI_BVALID , S0_AXI_BVALID; + wire S2_AXI_AWREADY, S1_AXI_AWREADY, S0_AXI_AWREADY; + + wire [C_NF_DATA_WIDTH-1:0] axis_i_0_tdata, axis_o_0_tdata; + wire axis_i_0_tvalid, axis_o_0_tvalid; + wire axis_i_0_tlast, axis_o_0_tlast; + wire [C_NF_TUSER_WIDTH-1:0] axis_i_0_tuser, axis_o_0_tuser; + wire [(C_NF_DATA_WIDTH/8)-1:0] axis_i_0_tkeep, axis_o_0_tkeep; + wire axis_i_0_tready, axis_o_0_tready; + + wire [C_NF_DATA_WIDTH-1:0] axis_i_1_tdata, axis_o_1_tdata; + wire axis_i_1_tvalid, axis_o_1_tvalid; + wire axis_i_1_tlast, axis_o_1_tlast; + wire [C_NF_TUSER_WIDTH-1:0] axis_i_1_tuser, axis_o_1_tuser; + wire [(C_NF_DATA_WIDTH/8)-1:0] axis_i_1_tkeep, axis_o_1_tkeep; + wire axis_i_1_tready, axis_o_1_tready; + + wire [C_NF_DATA_WIDTH-1:0] axis_dma_i_tdata , axis_dma_o_tdata ; + wire [(C_NF_DATA_WIDTH/8)-1:0] axis_dma_i_tkeep , axis_dma_o_tkeep ; + wire axis_dma_i_tlast , axis_dma_o_tlast ; + wire axis_dma_i_tready, axis_dma_o_tready; + wire [C_NF_TUSER_WIDTH-1:0] axis_dma_i_tuser , axis_dma_o_tuser ; + wire axis_dma_i_tvalid, axis_dma_o_tvalid; + // ---------------------------------------------------------- + // nf_datapath + // ---------------------------------------------------------- + nf_datapath #( + //Slave AXI parameters + .C_S_AXI_DATA_WIDTH ( 32 ), + .C_S_AXI_ADDR_WIDTH ( 32 ), + .C_BASEADDR ( 32'h00000000), + // Master AXI Stream Data Width + .C_M_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_S_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_M_AXIS_TUSER_WIDTH(C_NF_TUSER_WIDTH), + .C_S_AXIS_TUSER_WIDTH(C_NF_TUSER_WIDTH), + .NUM_QUEUES(5) + ) nf_datapath_0 ( + //Datapath clock + .axis_aclk (core_clk), + .axis_resetn (!core_rst), + //Registers clock + .axi_aclk (axil_aclk), + .axi_resetn (!axil_rst), + + // Slave AXI Ports + .S0_AXI_AWADDR (S0_AXI_AWADDR ), + .S0_AXI_AWVALID (S0_AXI_AWVALID), + .S0_AXI_WDATA (S0_AXI_WDATA ), + .S0_AXI_WSTRB (S0_AXI_WSTRB ), + .S0_AXI_WVALID (S0_AXI_WVALID ), + .S0_AXI_BREADY (S0_AXI_BREADY ), + .S0_AXI_ARADDR (S0_AXI_ARADDR ), + .S0_AXI_ARVALID (S0_AXI_ARVALID), + .S0_AXI_RREADY (S0_AXI_RREADY ), + .S0_AXI_ARREADY (S0_AXI_ARREADY), + .S0_AXI_RDATA (S0_AXI_RDATA ), + .S0_AXI_RRESP (S0_AXI_RRESP ), + .S0_AXI_RVALID (S0_AXI_RVALID ), + .S0_AXI_WREADY (S0_AXI_WREADY ), + .S0_AXI_BRESP (S0_AXI_BRESP ), + .S0_AXI_BVALID (S0_AXI_BVALID ), + .S0_AXI_AWREADY (S0_AXI_AWREADY), + + .S1_AXI_AWADDR (S1_AXI_AWADDR ), + .S1_AXI_AWVALID (S1_AXI_AWVALID), + .S1_AXI_WDATA (S1_AXI_WDATA ), + .S1_AXI_WSTRB (S1_AXI_WSTRB ), + .S1_AXI_WVALID (S1_AXI_WVALID ), + .S1_AXI_BREADY (S1_AXI_BREADY ), + .S1_AXI_ARADDR (S1_AXI_ARADDR ), + .S1_AXI_ARVALID (S1_AXI_ARVALID), + .S1_AXI_RREADY (S1_AXI_RREADY ), + .S1_AXI_ARREADY (S1_AXI_ARREADY), + .S1_AXI_RDATA (S1_AXI_RDATA ), + .S1_AXI_RRESP (S1_AXI_RRESP ), + .S1_AXI_RVALID (S1_AXI_RVALID ), + .S1_AXI_WREADY (S1_AXI_WREADY ), + .S1_AXI_BRESP (S1_AXI_BRESP ), + .S1_AXI_BVALID (S1_AXI_BVALID ), + .S1_AXI_AWREADY (S1_AXI_AWREADY), + + .S2_AXI_AWADDR (S2_AXI_AWADDR ), + .S2_AXI_AWVALID (S2_AXI_AWVALID), + .S2_AXI_WDATA (S2_AXI_WDATA ), + .S2_AXI_WSTRB (S2_AXI_WSTRB ), + .S2_AXI_WVALID (S2_AXI_WVALID ), + .S2_AXI_BREADY (S2_AXI_BREADY ), + .S2_AXI_ARADDR (S2_AXI_ARADDR ), + .S2_AXI_ARVALID (S2_AXI_ARVALID), + .S2_AXI_RREADY (S2_AXI_RREADY ), + .S2_AXI_ARREADY (S2_AXI_ARREADY), + .S2_AXI_RDATA (S2_AXI_RDATA ), + .S2_AXI_RRESP (S2_AXI_RRESP ), + .S2_AXI_RVALID (S2_AXI_RVALID ), + .S2_AXI_WREADY (S2_AXI_WREADY ), + .S2_AXI_BRESP (S2_AXI_BRESP ), + .S2_AXI_BVALID (S2_AXI_BVALID ), + .S2_AXI_AWREADY (S2_AXI_AWREADY), + + // Slave Stream Ports (interface from Rx queues) + .s_axis_0_tdata (axis_i_0_tdata ), + .s_axis_0_tkeep (axis_i_0_tkeep ), + .s_axis_0_tuser (axis_i_0_tuser ), + .s_axis_0_tvalid (axis_i_0_tvalid), + .s_axis_0_tready (axis_i_0_tready), + .s_axis_0_tlast (axis_i_0_tlast ), +`ifdef __BOARD_AU50__ + .s_axis_1_tdata (axis_dma_i_tdata ), + .s_axis_1_tkeep (axis_dma_i_tkeep ), + .s_axis_1_tuser (axis_dma_i_tuser ), + .s_axis_1_tvalid (axis_dma_i_tvalid), + .s_axis_1_tready (axis_dma_i_tready), + .s_axis_1_tlast (axis_dma_i_tlast ), +`else + .s_axis_1_tdata (axis_i_1_tdata ), + .s_axis_1_tkeep (axis_i_1_tkeep ), + .s_axis_1_tuser (axis_i_1_tuser ), + .s_axis_1_tvalid (axis_i_1_tvalid), + .s_axis_1_tready (axis_i_1_tready), + .s_axis_1_tlast (axis_i_1_tlast ), + .s_axis_2_tdata (axis_dma_i_tdata ), + .s_axis_2_tkeep (axis_dma_i_tkeep ), + .s_axis_2_tuser (axis_dma_i_tuser ), + .s_axis_2_tvalid (axis_dma_i_tvalid), + .s_axis_2_tready (axis_dma_i_tready), + .s_axis_2_tlast (axis_dma_i_tlast ), +`endif /* __BOARD_AU50__ */ + // Master Stream Ports (interface to TX queues) + .m_axis_0_tdata (axis_o_0_tdata ), + .m_axis_0_tkeep (axis_o_0_tkeep ), + .m_axis_0_tuser (axis_o_0_tuser ), + .m_axis_0_tvalid (axis_o_0_tvalid), + .m_axis_0_tready (axis_o_0_tready), + .m_axis_0_tlast (axis_o_0_tlast ), +`ifdef __BOARD_AU50__ + .m_axis_1_tdata (axis_dma_o_tdata ), + .m_axis_1_tkeep (axis_dma_o_tkeep ), + .m_axis_1_tuser (axis_dma_o_tuser ), + .m_axis_1_tvalid (axis_dma_o_tvalid), + .m_axis_1_tready (axis_dma_o_tready), + .m_axis_1_tlast (axis_dma_o_tlast ) +`else + .m_axis_1_tdata (axis_o_1_tdata ), + .m_axis_1_tkeep (axis_o_1_tkeep ), + .m_axis_1_tuser (axis_o_1_tuser ), + .m_axis_1_tvalid (axis_o_1_tvalid), + .m_axis_1_tready (axis_o_1_tready), + .m_axis_1_tlast (axis_o_1_tlast ), + .m_axis_2_tdata (axis_dma_o_tdata ), + .m_axis_2_tkeep (axis_dma_o_tkeep ), + .m_axis_2_tuser (axis_dma_o_tuser ), + .m_axis_2_tvalid (axis_dma_o_tvalid), + .m_axis_2_tready (axis_dma_o_tready), + .m_axis_2_tlast (axis_dma_o_tlast ) +`endif /* __BOARD_AU50__ */ + ); + + axi_crossbar_0 u_interconnect ( + .aclk (axil_aclk), + .aresetn (!axil_rst), + .s_axi_awaddr (m_axil_awaddr ), + .s_axi_awprot (), + .s_axi_awvalid (m_axil_awvalid), + .s_axi_awready (m_axil_awready), + .s_axi_wdata (m_axil_wdata ), + .s_axi_wstrb (4'b1111), + .s_axi_wvalid (m_axil_wvalid ), + .s_axi_wready (m_axil_wready ), + .s_axi_bresp (m_axil_bresp ), + .s_axi_bvalid (m_axil_bvalid ), + .s_axi_bready (m_axil_bready ), + .s_axi_araddr (m_axil_araddr), + .s_axi_arprot (), + .s_axi_arvalid (m_axil_arvalid ), + .s_axi_arready (m_axil_arready ), + .s_axi_rdata (m_axil_rdata ), + .s_axi_rresp (m_axil_rresp ), + .s_axi_rvalid (m_axil_rvalid ), + .s_axi_rready (m_axil_rready ), + .m_axi_awaddr ({S2_AXI_AWADDR ,S1_AXI_AWADDR ,S0_AXI_AWADDR }), + .m_axi_awprot (), + .m_axi_awvalid ({S2_AXI_AWVALID,S1_AXI_AWVALID,S0_AXI_AWVALID}), + .m_axi_awready ({S2_AXI_AWREADY,S1_AXI_AWREADY,S0_AXI_AWREADY}), + .m_axi_wdata ({S2_AXI_WDATA ,S1_AXI_WDATA ,S0_AXI_WDATA }), + .m_axi_wstrb ({S2_AXI_WSTRB ,S1_AXI_WSTRB ,S0_AXI_WSTRB }), + .m_axi_wvalid ({S2_AXI_WVALID ,S1_AXI_WVALID ,S0_AXI_WVALID }), + .m_axi_wready ({S2_AXI_WREADY ,S1_AXI_WREADY ,S0_AXI_WREADY }), + .m_axi_bresp ({S2_AXI_BRESP ,S1_AXI_BRESP ,S0_AXI_BRESP }), + .m_axi_bvalid ({S2_AXI_BVALID ,S1_AXI_BVALID ,S0_AXI_BVALID }), + .m_axi_bready ({S2_AXI_BREADY ,S1_AXI_BREADY ,S0_AXI_BREADY }), + .m_axi_araddr ({S2_AXI_ARADDR ,S1_AXI_ARADDR ,S0_AXI_ARADDR }), + .m_axi_arprot (), + .m_axi_arvalid ({S2_AXI_ARVALID,S1_AXI_ARVALID,S0_AXI_ARVALID}), + .m_axi_arready ({S2_AXI_ARREADY,S1_AXI_ARREADY,S0_AXI_ARREADY}), + .m_axi_rdata ({S2_AXI_RDATA ,S1_AXI_RDATA ,S0_AXI_RDATA }), + .m_axi_rresp ({S2_AXI_RRESP ,S1_AXI_RRESP ,S0_AXI_RRESP }), + .m_axi_rvalid ({S2_AXI_RVALID ,S1_AXI_RVALID ,S0_AXI_RVALID }), + .m_axi_rready ({S2_AXI_RREADY ,S1_AXI_RREADY ,S0_AXI_RREADY }) + ); + + top_wrapper #( + .C_NF_TDATA_WIDTH (C_NF_DATA_WIDTH), + .C_NF_TUSER_WIDTH (C_NF_TUSER_WIDTH), + .C_TDATA_WIDTH (C_IF_DATA_WIDTH), + .C_TUSER_WIDTH (C_IF_TUSER_WIDTH) + ) u_top_wrapper ( + // QSFP port0 + .qsfp0_rxp (QSFP0_RX_P), + .qsfp0_rxn (QSFP0_RX_N), + .qsfp0_txp (QSFP0_TX_P), + .qsfp0_txn (QSFP0_TX_N), + // QSFP port1 + .qsfp1_rxp (QSFP1_RX_P), + .qsfp1_rxn (QSFP1_RX_N), + .qsfp1_txp (QSFP1_TX_P), + .qsfp1_txn (QSFP1_TX_N), + // QSFP CLK0 + .qsfp0_clk_p (QSFP0_CLOCK_P), + .qsfp0_clk_n (QSFP0_CLOCK_N), + // QSFP CLK1 + .qsfp1_clk_p (QSFP1_CLOCK_P), + .qsfp1_clk_n (QSFP1_CLOCK_N), + + .pcie_txp (pcie_txp), + .pcie_txn (pcie_txn), + .pcie_rxp (pcie_rxp), + .pcie_rxn (pcie_rxn), + // PCIe CLK + .pcie_clk_p (pci_clk_p), + .pcie_clk_n (pci_clk_n), + .pcie_rst_n (pci_rst_n), + + .m_axil_awvalid (m_axil_awvalid), + .m_axil_awaddr (m_axil_awaddr ), + .m_axil_awready (m_axil_awready), + .m_axil_wvalid (m_axil_wvalid ), + .m_axil_wdata (m_axil_wdata ), + .m_axil_wready (m_axil_wready ), + .m_axil_bvalid (m_axil_bvalid ), + .m_axil_bresp (m_axil_bresp ), + .m_axil_bready (m_axil_bready ), + .m_axil_arvalid (m_axil_arvalid), + .m_axil_araddr (m_axil_araddr ), + .m_axil_arready (m_axil_arready), + .m_axil_rvalid (m_axil_rvalid ), + .m_axil_rdata (m_axil_rdata ), + .m_axil_rresp (m_axil_rresp ), + .m_axil_rready (m_axil_rready ), + // Slave Stream Ports + .axis_dma_o_tdata (axis_dma_o_tdata ), + .axis_dma_o_tkeep (axis_dma_o_tkeep ), + .axis_dma_o_tuser (axis_dma_o_tuser ), + .axis_dma_o_tvalid (axis_dma_o_tvalid), + .axis_dma_o_tready (axis_dma_o_tready), + .axis_dma_o_tlast (axis_dma_o_tlast ), + // Master Stream Ports + .axis_dma_i_tdata (axis_dma_i_tdata ), + .axis_dma_i_tkeep (axis_dma_i_tkeep ), + .axis_dma_i_tuser (axis_dma_i_tuser ), + .axis_dma_i_tvalid (axis_dma_i_tvalid), + .axis_dma_i_tready (axis_dma_i_tready), + .axis_dma_i_tlast (axis_dma_i_tlast ), + // Slave Stream Ports + .axis_o_0_tdata (axis_o_0_tdata ), + .axis_o_0_tkeep (axis_o_0_tkeep ), + .axis_o_0_tuser (axis_o_0_tuser ), + .axis_o_0_tvalid (axis_o_0_tvalid), + .axis_o_0_tready (axis_o_0_tready), + .axis_o_0_tlast (axis_o_0_tlast ), + // Slave Stream Ports + .axis_o_1_tdata (axis_o_1_tdata ), + .axis_o_1_tkeep (axis_o_1_tkeep ), + .axis_o_1_tuser (axis_o_1_tuser ), + .axis_o_1_tvalid (axis_o_1_tvalid), + .axis_o_1_tready (axis_o_1_tready), + .axis_o_1_tlast (axis_o_1_tlast ), + // Master Stream Ports + .axis_i_0_tdata (axis_i_0_tdata ), + .axis_i_0_tkeep (axis_i_0_tkeep ), + .axis_i_0_tuser (axis_i_0_tuser ), + .axis_i_0_tvalid (axis_i_0_tvalid), + .axis_i_0_tready (axis_i_0_tready), + .axis_i_0_tlast (axis_i_0_tlast ), + // Master Stream Ports + .axis_i_1_tdata (axis_i_1_tdata ), + .axis_i_1_tkeep (axis_i_1_tkeep ), + .axis_i_1_tuser (axis_i_1_tuser ), + .axis_i_1_tvalid (axis_i_1_tvalid), + .axis_i_1_tready (axis_i_1_tready), + .axis_i_1_tlast (axis_i_1_tlast ), + + .core_clk (core_clk), + .axis_aclk (axis_aclk), + .axil_aclk (axil_aclk), + .axis_rst (axis_rst), + .axil_rst (axil_rst) + ); + +endmodule +`default_nettype wire diff --git a/hw/lib/common/hdl/top_wrapper.sv b/hw/lib/common/hdl/top_wrapper.sv new file mode 100644 index 0000000..30e8ee8 --- /dev/null +++ b/hw/lib/common/hdl/top_wrapper.sv @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2021 Yuta Tokusashi + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory under EPSRC EARL Project EP/P025374/1 alongside support + * from Xilinx Inc. + * + * @NETFPGA_LICENSE_HEADER_START@ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @NETFPGA_LICENSE_HEADER_END@ + * + */ +module top_wrapper #( + parameter C_NF_TDATA_WIDTH = 512, + parameter C_NF_TUSER_WIDTH = 128, + parameter C_TDATA_WIDTH = 512, + parameter C_TUSER_WIDTH = 128 +)( + // QSFP port0 + input [3:0] qsfp0_rxp, + input [3:0] qsfp0_rxn, + output [3:0] qsfp0_txp, + output [3:0] qsfp0_txn, + // QSFP port1 + input [3:0] qsfp1_rxp, + input [3:0] qsfp1_rxn, + output [3:0] qsfp1_txp, + output [3:0] qsfp1_txn, + // QSFP CLK0 + input qsfp0_clk_p, + input qsfp0_clk_n, + // QSFP CLK1 + input qsfp1_clk_p, + input qsfp1_clk_n, + + output [15:0] pcie_txp, + output [15:0] pcie_txn, + input [15:0] pcie_rxp, + input [15:0] pcie_rxn, + // PCIe CLK + input pcie_clk_p, + input pcie_clk_n, + input pcie_rst_n, + + output m_axil_awvalid, + output [31:0] m_axil_awaddr, + input m_axil_awready, + output m_axil_wvalid, + output [31:0] m_axil_wdata, + input m_axil_wready, + input m_axil_bvalid, + input [1:0] m_axil_bresp, + output m_axil_bready, + output m_axil_arvalid, + output [31:0] m_axil_araddr, + input m_axil_arready, + input m_axil_rvalid, + input [31:0] m_axil_rdata, + input [1:0] m_axil_rresp, + output m_axil_rready, + // Slave Stream Ports + input [C_NF_TDATA_WIDTH-1:0] axis_dma_o_tdata, + input [(C_NF_TDATA_WIDTH/8)-1:0] axis_dma_o_tkeep, + input [C_NF_TUSER_WIDTH-1:0] axis_dma_o_tuser, + input axis_dma_o_tvalid, + output axis_dma_o_tready, + input axis_dma_o_tlast, + + // Master Stream Ports + output [C_NF_TDATA_WIDTH-1:0] axis_dma_i_tdata, + output [(C_NF_TDATA_WIDTH/8)-1:0]axis_dma_i_tkeep, + output [C_NF_TUSER_WIDTH-1:0] axis_dma_i_tuser, + output axis_dma_i_tvalid, + input axis_dma_i_tready, + output axis_dma_i_tlast, + + // Slave Stream Ports + input [C_NF_TDATA_WIDTH-1:0] axis_o_0_tdata, + input [(C_NF_TDATA_WIDTH/8)-1:0] axis_o_0_tkeep, + input [C_NF_TUSER_WIDTH-1:0] axis_o_0_tuser, + input axis_o_0_tvalid, + output axis_o_0_tready, + input axis_o_0_tlast, + // Slave Stream Ports + input [C_NF_TDATA_WIDTH-1:0] axis_o_1_tdata, + input [(C_NF_TDATA_WIDTH/8)-1:0] axis_o_1_tkeep, + input [C_NF_TUSER_WIDTH-1:0] axis_o_1_tuser, + input axis_o_1_tvalid, + output axis_o_1_tready, + input axis_o_1_tlast, + // Master Stream Ports + output [C_NF_TDATA_WIDTH-1:0] axis_i_0_tdata, + output [(C_NF_TDATA_WIDTH/8)-1:0]axis_i_0_tkeep, + output [C_NF_TUSER_WIDTH-1:0] axis_i_0_tuser, + output axis_i_0_tvalid, + input axis_i_0_tready, + output axis_i_0_tlast, + // Master Stream Ports + output [C_NF_TDATA_WIDTH-1:0] axis_i_1_tdata, + output [(C_NF_TDATA_WIDTH/8)-1:0]axis_i_1_tkeep, + output [C_NF_TUSER_WIDTH-1:0] axis_i_1_tuser, + output axis_i_1_tvalid, + input axis_i_1_tready, + output axis_i_1_tlast, + + input core_clk, + output axis_aclk, + output axil_aclk, + output axis_rst, + output axil_rst +); + + wire [1:0] cmac_clk; + + wire axis_cmac_0_rx_tvalid, axis_cmac_1_rx_tvalid; + wire [C_TDATA_WIDTH-1:0] axis_cmac_0_rx_tdata , axis_cmac_1_rx_tdata ; + wire [(C_TDATA_WIDTH/8)-1:0] axis_cmac_0_rx_tkeep , axis_cmac_1_rx_tkeep ; + wire axis_cmac_0_rx_tuser_err , axis_cmac_1_rx_tuser_err ; + wire axis_cmac_0_rx_tlast , axis_cmac_1_rx_tlast ; + + wire axis_cmac_0_tx_tvalid, axis_cmac_1_tx_tvalid; + wire [C_TDATA_WIDTH-1:0] axis_cmac_0_tx_tdata , axis_cmac_1_tx_tdata ; + wire [(C_TDATA_WIDTH/8)-1:0] axis_cmac_0_tx_tkeep , axis_cmac_1_tx_tkeep ; + wire axis_cmac_0_tx_tuser_err , axis_cmac_1_tx_tuser_err ; + wire axis_cmac_0_tx_tlast , axis_cmac_1_tx_tlast ; + wire axis_cmac_0_tx_tready , axis_cmac_1_tx_tready ; + + wire s_axis_qdma_c2h_0_tvalid, s_axis_qdma_c2h_1_tvalid; + wire [511:0] s_axis_qdma_c2h_0_tdata , s_axis_qdma_c2h_1_tdata ; + wire [63:0] s_axis_qdma_c2h_0_tkeep , s_axis_qdma_c2h_1_tkeep ; + wire s_axis_qdma_c2h_0_tlast , s_axis_qdma_c2h_1_tlast ; + wire [15:0] s_axis_qdma_c2h_0_tuser_size, s_axis_qdma_c2h_1_tuser_size; + wire [15:0] s_axis_qdma_c2h_0_tuser_src, s_axis_qdma_c2h_1_tuser_src; + wire [15:0] s_axis_qdma_c2h_0_tuser_dst, s_axis_qdma_c2h_1_tuser_dst; + wire s_axis_qdma_c2h_0_tready, s_axis_qdma_c2h_1_tready; + + wire m_axis_qdma_h2c_0_tvalid, m_axis_qdma_h2c_1_tvalid; + wire [511:0] m_axis_qdma_h2c_0_tdata , m_axis_qdma_h2c_1_tdata ; + wire [63:0] m_axis_qdma_h2c_0_tkeep , m_axis_qdma_h2c_1_tkeep ; + wire m_axis_qdma_h2c_0_tlast , m_axis_qdma_h2c_1_tlast ; + wire [15:0] m_axis_qdma_h2c_0_tuser_size, m_axis_qdma_h2c_1_tuser_size; + wire [15:0] m_axis_qdma_h2c_0_tuser_src, m_axis_qdma_h2c_1_tuser_src; + wire [15:0] m_axis_qdma_h2c_0_tuser_dst, m_axis_qdma_h2c_1_tuser_dst; + wire m_axis_qdma_h2c_0_tready, m_axis_qdma_h2c_1_tready; + + wire m0_axil_awvalid; + wire [31:0] m0_axil_awaddr; + wire m0_axil_awready; + wire m0_axil_wvalid; + wire [31:0] m0_axil_wdata; + wire m0_axil_wready; + wire m0_axil_bvalid; + wire [1:0] m0_axil_bresp; + wire m0_axil_bready; + wire m0_axil_arvalid; + wire [31:0] m0_axil_araddr; + wire m0_axil_arready; + wire m0_axil_rvalid; + wire [31:0] m0_axil_rdata; + wire [1:0] m0_axil_rresp; + wire m0_axil_rready; + + wire [31:0] user_rst_done = 32'hffff_fffe; + + nf_attachment #( + .C_NF_TDATA_WIDTH (C_NF_TDATA_WIDTH), + .C_NF_TUSER_WIDTH (C_NF_TUSER_WIDTH), + .C_TDATA_WIDTH (C_TDATA_WIDTH ), + .C_TUSER_WIDTH (C_TUSER_WIDTH ) + ) u_nf_attachment ( + // Slave Stream Ports + .axis_dma_o_tdata (axis_dma_o_tdata ), + .axis_dma_o_tkeep (axis_dma_o_tkeep ), + .axis_dma_o_tuser (axis_dma_o_tuser ), + .axis_dma_o_tvalid (axis_dma_o_tvalid), + .axis_dma_o_tready (axis_dma_o_tready), + .axis_dma_o_tlast (axis_dma_o_tlast ), + // Master Stream Ports + .axis_dma_i_tdata (axis_dma_i_tdata ), + .axis_dma_i_tkeep (axis_dma_i_tkeep ), + .axis_dma_i_tuser (axis_dma_i_tuser ), + .axis_dma_i_tvalid (axis_dma_i_tvalid), + .axis_dma_i_tready (axis_dma_i_tready), + .axis_dma_i_tlast (axis_dma_i_tlast ), + // Slave Stream Ports + .axis_o_0_tdata (axis_o_0_tdata ), + .axis_o_0_tkeep (axis_o_0_tkeep ), + .axis_o_0_tuser (axis_o_0_tuser ), + .axis_o_0_tvalid (axis_o_0_tvalid), + .axis_o_0_tready (axis_o_0_tready), + .axis_o_0_tlast (axis_o_0_tlast ), + // Slave Stream Ports + .axis_o_1_tdata (axis_o_1_tdata ), + .axis_o_1_tkeep (axis_o_1_tkeep ), + .axis_o_1_tuser (axis_o_1_tuser ), + .axis_o_1_tvalid (axis_o_1_tvalid), + .axis_o_1_tready (axis_o_1_tready), + .axis_o_1_tlast (axis_o_1_tlast ), + // Master Stream Ports + .axis_i_0_tdata (axis_i_0_tdata ), + .axis_i_0_tkeep (axis_i_0_tkeep ), + .axis_i_0_tuser (axis_i_0_tuser ), + .axis_i_0_tvalid (axis_i_0_tvalid), + .axis_i_0_tready (axis_i_0_tready), + .axis_i_0_tlast (axis_i_0_tlast ), + // Master Stream Ports + .axis_i_1_tdata (axis_i_1_tdata ), + .axis_i_1_tkeep (axis_i_1_tkeep ), + .axis_i_1_tuser (axis_i_1_tuser ), + .axis_i_1_tvalid (axis_i_1_tvalid), + .axis_i_1_tready (axis_i_1_tready), + .axis_i_1_tlast (axis_i_1_tlast ), + + .axis_cmac_0_rx_tvalid(axis_cmac_0_rx_tvalid), + .axis_cmac_0_rx_tdata (axis_cmac_0_rx_tdata ), + .axis_cmac_0_rx_tkeep (axis_cmac_0_rx_tkeep ), + .axis_cmac_0_rx_tuser_err (axis_cmac_0_rx_tuser_err), + .axis_cmac_0_rx_tlast (axis_cmac_0_rx_tlast ), + + .axis_cmac_1_rx_tvalid(axis_cmac_1_rx_tvalid), + .axis_cmac_1_rx_tdata (axis_cmac_1_rx_tdata ), + .axis_cmac_1_rx_tkeep (axis_cmac_1_rx_tkeep ), + .axis_cmac_1_rx_tuser_err (axis_cmac_1_rx_tuser_err ), + .axis_cmac_1_rx_tlast (axis_cmac_1_rx_tlast ), + + .axis_cmac_0_tx_tvalid(axis_cmac_0_tx_tvalid), + .axis_cmac_0_tx_tdata (axis_cmac_0_tx_tdata ), + .axis_cmac_0_tx_tkeep (axis_cmac_0_tx_tkeep ), + .axis_cmac_0_tx_tuser_err (axis_cmac_0_tx_tuser_err ), + .axis_cmac_0_tx_tlast (axis_cmac_0_tx_tlast ), + .axis_cmac_0_tx_tready(axis_cmac_0_tx_tready), + + .axis_cmac_1_tx_tvalid(axis_cmac_1_tx_tvalid), + .axis_cmac_1_tx_tdata (axis_cmac_1_tx_tdata ), + .axis_cmac_1_tx_tkeep (axis_cmac_1_tx_tkeep ), + .axis_cmac_1_tx_tuser_err (axis_cmac_1_tx_tuser_err ), + .axis_cmac_1_tx_tlast (axis_cmac_1_tx_tlast ), + .axis_cmac_1_tx_tready(axis_cmac_1_tx_tready), + + .s_axis_qdma_c2h_0_tvalid (s_axis_qdma_c2h_0_tvalid), + .s_axis_qdma_c2h_0_tdata (s_axis_qdma_c2h_0_tdata ), + .s_axis_qdma_c2h_0_tkeep (s_axis_qdma_c2h_0_tkeep ), + .s_axis_qdma_c2h_0_tlast (s_axis_qdma_c2h_0_tlast ), + .s_axis_qdma_c2h_0_tuser_size(s_axis_qdma_c2h_0_tuser_size), + .s_axis_qdma_c2h_0_tuser_src (s_axis_qdma_c2h_0_tuser_src), + .s_axis_qdma_c2h_0_tuser_dst (s_axis_qdma_c2h_0_tuser_dst), + //.s_axis_qdma_c2h_0_tid (s_axis_qdma_c2h_0_tid ), + //.s_axis_qdma_c2h_0_tdest (s_axis_qdma_c2h_0_tdest ), + .s_axis_qdma_c2h_0_tready (s_axis_qdma_c2h_0_tready), + + .s_axis_qdma_c2h_1_tvalid (s_axis_qdma_c2h_1_tvalid), + .s_axis_qdma_c2h_1_tdata (s_axis_qdma_c2h_1_tdata ), + .s_axis_qdma_c2h_1_tkeep (s_axis_qdma_c2h_1_tkeep ), + .s_axis_qdma_c2h_1_tlast (s_axis_qdma_c2h_1_tlast ), + .s_axis_qdma_c2h_1_tuser_size(s_axis_qdma_c2h_1_tuser_size), + .s_axis_qdma_c2h_1_tuser_src (s_axis_qdma_c2h_1_tuser_src), + .s_axis_qdma_c2h_1_tuser_dst (s_axis_qdma_c2h_1_tuser_dst), + //.s_axis_qdma_c2h_1_tid (s_axis_qdma_c2h_1_tid ), + //.s_axis_qdma_c2h_1_tdest (s_axis_qdma_c2h_1_tdest ), + .s_axis_qdma_c2h_1_tready (s_axis_qdma_c2h_1_tready), + + .m_axis_qdma_h2c_0_tvalid (m_axis_qdma_h2c_0_tvalid), + .m_axis_qdma_h2c_0_tdata (m_axis_qdma_h2c_0_tdata ), + .m_axis_qdma_h2c_0_tkeep (m_axis_qdma_h2c_0_tkeep ), + .m_axis_qdma_h2c_0_tlast (m_axis_qdma_h2c_0_tlast ), + .m_axis_qdma_h2c_0_tuser_size(m_axis_qdma_h2c_0_tuser_size), + .m_axis_qdma_h2c_0_tuser_src (m_axis_qdma_h2c_0_tuser_src), + .m_axis_qdma_h2c_0_tuser_dst (m_axis_qdma_h2c_0_tuser_dst), + //.m_axis_qdma_h2c_0_tid (m_axis_qdma_h2c_0_tid ), + //.m_axis_qdma_h2c_0_tdest (m_axis_qdma_h2c_0_tdest ), + .m_axis_qdma_h2c_0_tready (m_axis_qdma_h2c_0_tready), + + .m_axis_qdma_h2c_1_tvalid (m_axis_qdma_h2c_1_tvalid), + .m_axis_qdma_h2c_1_tdata (m_axis_qdma_h2c_1_tdata ), + .m_axis_qdma_h2c_1_tkeep (m_axis_qdma_h2c_1_tkeep ), + .m_axis_qdma_h2c_1_tlast (m_axis_qdma_h2c_1_tlast ), + .m_axis_qdma_h2c_1_tuser_size(m_axis_qdma_h2c_1_tuser_size), + .m_axis_qdma_h2c_1_tuser_src (m_axis_qdma_h2c_1_tuser_src), + .m_axis_qdma_h2c_1_tuser_dst (m_axis_qdma_h2c_1_tuser_dst), + //.m_axis_qdma_h2c_1_tid (m_axis_qdma_h2c_1_tid ), + //.m_axis_qdma_h2c_1_tdest (m_axis_qdma_h2c_1_tdest ), + .m_axis_qdma_h2c_1_tready (m_axis_qdma_h2c_1_tready), + + .m0_axil_awvalid (m0_axil_awvalid), + .m0_axil_awaddr (m0_axil_awaddr ), + .m0_axil_awready (m0_axil_awready), + .m0_axil_wvalid (m0_axil_wvalid ), + .m0_axil_wdata (m0_axil_wdata ), + .m0_axil_wready (m0_axil_wready ), + .m0_axil_bvalid (m0_axil_bvalid ), + .m0_axil_bresp (m0_axil_bresp ), + .m0_axil_bready (m0_axil_bready ), + .m0_axil_arvalid (m0_axil_arvalid), + .m0_axil_araddr (m0_axil_araddr ), + .m0_axil_arready (m0_axil_arready), + .m0_axil_rvalid (m0_axil_rvalid ), + .m0_axil_rdata (m0_axil_rdata ), + .m0_axil_rresp (m0_axil_rresp ), + .m0_axil_rready (m0_axil_rready ), + + .cmac_clk (cmac_clk), + .core_clk (core_clk ), + .axis_aclk (axis_aclk), + .axil_aclk (axil_aclk), + .axis_rst (axis_rst ), + .axil_rst (axil_rst ) + ); + + xilinx_shell_ip xilinx_nic_shell ( +`ifndef sim + .pcie_txp (pcie_txp), + .pcie_txn (pcie_txn), + .pcie_rxp (pcie_rxp), + .pcie_rxn (pcie_rxn), + .pcie_refclk_p (pcie_clk_p), + .pcie_refclk_n (pcie_clk_n), + .pcie_rstn (pcie_rst_n), + + .qsfp_rxp ({qsfp1_rxp, qsfp0_rxp}), + .qsfp_rxn ({qsfp1_rxn, qsfp0_rxn}), + .qsfp_txp ({qsfp1_txp, qsfp0_txp}), + .qsfp_txn ({qsfp1_txn, qsfp0_txn}), + .qsfp_refclk_p ({qsfp1_clk_p, qsfp0_clk_p}), + .qsfp_refclk_n ({qsfp1_clk_n, qsfp0_clk_n}), +`else // !`ifdef __synthesis__ + .s_axil_awvalid (), + .s_axil_awaddr (), + .s_axil_awready (), + .s_axil_wvalid (), + .s_axil_wdata (), + .s_axil_wready (), + .s_axil_bvalid (), + .s_axil_bresp (), + .s_axil_bready (), + .s_axil_arvalid (), + .s_axil_araddr (), + .s_axil_arready (), + .s_axil_rvalid (), + .s_axil_rdata (), + .s_axil_rresp (), + .s_axil_rready (), + + .s_axis_qdma_h2c_tvalid (), + .s_axis_qdma_h2c_tlast (), + .s_axis_qdma_h2c_tdata (), + .s_axis_qdma_h2c_dpar (), + .s_axis_qdma_h2c_tuser_qid (), + .s_axis_qdma_h2c_tuser_port_id(), + .s_axis_qdma_h2c_tuser_err (), + .s_axis_qdma_h2c_tuser_mdata (), + .s_axis_qdma_h2c_tuser_mty (), + .s_axis_qdma_h2c_tuser_zero_byte(), + .s_axis_qdma_h2c_tready (), + + .m_axis_qdma_c2h_tvalid (), + .m_axis_qdma_c2h_tlast (), + .m_axis_qdma_c2h_tdata (), + .m_axis_qdma_c2h_dpar (), + .m_axis_qdma_c2h_ctrl_marker (), + .m_axis_qdma_c2h_ctrl_port_id (), + .m_axis_qdma_c2h_ctrl_len (), + .m_axis_qdma_c2h_ctrl_qid (), + .m_axis_qdma_c2h_ctrl_has_cmpt(), + .m_axis_qdma_c2h_mty (), + .m_axis_qdma_c2h_tready (), + + .m_axis_qdma_cpl_tvalid (), + .m_axis_qdma_cpl_tdata (), + .m_axis_qdma_cpl_size (), + .m_axis_qdma_cpl_dpar (), + .m_axis_qdma_cpl_ctrl_qid (), + .m_axis_qdma_cpl_ctrl_cmpt_type (), + .m_axis_qdma_cpl_ctrl_wait_pld_pkt_id(), + .m_axis_qdma_cpl_ctrl_port_id (), + .m_axis_qdma_cpl_ctrl_marker (), + .m_axis_qdma_cpl_ctrl_user_trig (), + .m_axis_qdma_cpl_ctrl_col_idx (), + .m_axis_qdma_cpl_ctrl_err_idx (), + .m_axis_qdma_cpl_tready (), + + .m_axis_cmac_tx_tvalid (), + .m_axis_cmac_tx_tdata (), + .m_axis_cmac_tx_tkeep (), + .m_axis_cmac_tx_tlast (), + .m_axis_cmac_tx_tuser (), + .m_axis_cmac_tx_tready (), + + .s_axis_cmac_rx_tvalid (), + .s_axis_cmac_rx_tdata (), + .s_axis_cmac_rx_tkeep (), + .s_axis_cmac_rx_tlast (), + .s_axis_cmac_rx_tuser (), + + .powerup_rstn (), +`endif + + .m_axil_box0_awvalid (m0_axil_awvalid), + .m_axil_box0_awaddr (m0_axil_awaddr ), + .m_axil_box0_awready (m0_axil_awready), + .m_axil_box0_wvalid (m0_axil_wvalid ), + .m_axil_box0_wdata (m0_axil_wdata ), + .m_axil_box0_wready (m0_axil_wready ), + .m_axil_box0_bvalid (m0_axil_bvalid ), + .m_axil_box0_bresp (m0_axil_bresp ), + .m_axil_box0_bready (m0_axil_bready ), + .m_axil_box0_arvalid (m0_axil_arvalid), + .m_axil_box0_araddr (m0_axil_araddr ), + .m_axil_box0_arready (m0_axil_arready), + .m_axil_box0_rvalid (m0_axil_rvalid ), + .m_axil_box0_rdata (m0_axil_rdata ), + .m_axil_box0_rresp (m0_axil_rresp ), + .m_axil_box0_rready (m0_axil_rready ), + + .m_axil_box1_awvalid (m_axil_awvalid), + .m_axil_box1_awaddr (m_axil_awaddr ), + .m_axil_box1_awready (m_axil_awready), + .m_axil_box1_wvalid (m_axil_wvalid ), + .m_axil_box1_wdata (m_axil_wdata ), + .m_axil_box1_wready (m_axil_wready ), + .m_axil_box1_bvalid (m_axil_bvalid ), + .m_axil_box1_bresp (m_axil_bresp ), + .m_axil_box1_bready (m_axil_bready ), + .m_axil_box1_arvalid (m_axil_arvalid), + .m_axil_box1_araddr (m_axil_araddr ), + .m_axil_box1_arready (m_axil_arready), + .m_axil_box1_rvalid (m_axil_rvalid ), + .m_axil_box1_rdata (m_axil_rdata ), + .m_axil_box1_rresp (m_axil_rresp ), + .m_axil_box1_rready (m_axil_rready ), + + // QDMA subsystem interfaces to the box running at 250MHz + .m_axis_qdma_h2c_tvalid ({m_axis_qdma_h2c_1_tvalid, m_axis_qdma_h2c_0_tvalid }), + .m_axis_qdma_h2c_tdata ({m_axis_qdma_h2c_1_tdata , m_axis_qdma_h2c_0_tdata }), + .m_axis_qdma_h2c_tkeep ({m_axis_qdma_h2c_1_tkeep , m_axis_qdma_h2c_0_tkeep }), + .m_axis_qdma_h2c_tlast ({m_axis_qdma_h2c_1_tlast , m_axis_qdma_h2c_0_tlast }), + .m_axis_qdma_h2c_tuser_size({m_axis_qdma_h2c_1_tuser_size, m_axis_qdma_h2c_0_tuser_size}), + .m_axis_qdma_h2c_tuser_src ({m_axis_qdma_h2c_1_tuser_src, m_axis_qdma_h2c_0_tuser_src}), + .m_axis_qdma_h2c_tuser_dst ({m_axis_qdma_h2c_1_tuser_dst, m_axis_qdma_h2c_0_tuser_dst}), + .m_axis_qdma_h2c_tready ({m_axis_qdma_h2c_1_tready, m_axis_qdma_h2c_0_tready}), + + .s_axis_qdma_c2h_tvalid ({s_axis_qdma_c2h_1_tvalid, s_axis_qdma_c2h_0_tvalid }), + .s_axis_qdma_c2h_tdata ({s_axis_qdma_c2h_1_tdata , s_axis_qdma_c2h_0_tdata }), + .s_axis_qdma_c2h_tkeep ({s_axis_qdma_c2h_1_tkeep , s_axis_qdma_c2h_0_tkeep }), + .s_axis_qdma_c2h_tlast ({s_axis_qdma_c2h_1_tlast , s_axis_qdma_c2h_0_tlast }), + .s_axis_qdma_c2h_tuser_size({s_axis_qdma_c2h_1_tuser_size, s_axis_qdma_c2h_0_tuser_size}), + .s_axis_qdma_c2h_tuser_src ({s_axis_qdma_c2h_1_tuser_src, s_axis_qdma_c2h_0_tuser_src}), + .s_axis_qdma_c2h_tuser_dst ({s_axis_qdma_c2h_1_tuser_dst, s_axis_qdma_c2h_0_tuser_dst}), + .s_axis_qdma_c2h_tready ({s_axis_qdma_c2h_1_tready, s_axis_qdma_c2h_0_tready}), + + // CMAC subsystem CMAC-side interfaces to the box running at 322MHz + .s_axis_cmac_tx_tvalid ({axis_cmac_1_tx_tvalid, axis_cmac_0_tx_tvalid}), + .s_axis_cmac_tx_tdata ({axis_cmac_1_tx_tdata , axis_cmac_0_tx_tdata }), + .s_axis_cmac_tx_tkeep ({axis_cmac_1_tx_tkeep , axis_cmac_0_tx_tkeep }), + .s_axis_cmac_tx_tlast ({axis_cmac_1_tx_tlast , axis_cmac_0_tx_tlast }), + .s_axis_cmac_tx_tuser_err({axis_cmac_1_tx_tuser_err, axis_cmac_0_tx_tuser_err}), + .s_axis_cmac_tx_tready ({axis_cmac_1_tx_tready, axis_cmac_0_tx_tready}), + + .m_axis_cmac_rx_tvalid ({axis_cmac_1_rx_tvalid, axis_cmac_0_rx_tvalid}), + .m_axis_cmac_rx_tdata ({axis_cmac_1_rx_tdata , axis_cmac_0_rx_tdata }), + .m_axis_cmac_rx_tkeep ({axis_cmac_1_rx_tkeep , axis_cmac_0_rx_tkeep }), + .m_axis_cmac_rx_tlast ({axis_cmac_1_rx_tlast , axis_cmac_0_rx_tlast }), + .m_axis_cmac_rx_tuser_err({axis_cmac_1_rx_tuser_err, axis_cmac_0_rx_tuser_err}), + + .user_rstn (), + .user_rst_done (user_rst_done), + + .axil_aclk (axil_aclk), + .axis_aclk (axis_aclk), + + .cmac_clk (cmac_clk) + ); + +endmodule diff --git a/hw/lib/contrib/nf_endianess_manager_v1_0_0/Makefile b/hw/lib/contrib/nf_endianess_manager_v1_0_0/Makefile new file mode 100755 index 0000000..bb0500c --- /dev/null +++ b/hw/lib/contrib/nf_endianess_manager_v1_0_0/Makefile @@ -0,0 +1,32 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source nf_endianess_manager.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/contrib/nf_endianess_manager_v1_0_0/hdl/bridge.v b/hw/lib/contrib/nf_endianess_manager_v1_0_0/hdl/bridge.v new file mode 100644 index 0000000..f872f16 --- /dev/null +++ b/hw/lib/contrib/nf_endianess_manager_v1_0_0/hdl/bridge.v @@ -0,0 +1,105 @@ +// +// Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +// Junior University +// Copyright (C) 2015 Gianni Antichi +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +module bridge +#( + parameter C_AXIS_DATA_WIDTH = 256, + parameter C_AXIS_TUSER_WIDTH = 128, + parameter NUM_QUEUES = 8, + parameter NUM_QUEUES_WIDTH = log2(NUM_QUEUES) +) +( + // Global Ports + input clk, + input reset, + + // little endian signals + input [C_AXIS_DATA_WIDTH-1:0] s_axis_tdata, + input [(C_AXIS_DATA_WIDTH/8)-1:0] s_axis_tkeep, + input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser, + input s_axis_tvalid, + output reg s_axis_tready, + input s_axis_tlast, + + // big endian signals + output reg [C_AXIS_DATA_WIDTH-1:0] m_axis_tdata, + output reg[(C_AXIS_DATA_WIDTH/8)-1:0] m_axis_tkeep, + output reg [C_AXIS_TUSER_WIDTH-1:0] m_axis_tuser, + output reg m_axis_tvalid, + input m_axis_tready, + output reg m_axis_tlast + +); + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 big endian + * ----------------------------------------- */ + + bridge + #( + .C_AXIS_DATA_WIDTH (C_M_AXIS_TDATA_WIDTH), + .C_AXIS_TUSER_WIDTH (C_M_AXIS_TUSER_WIDTH) + ) le_be_bridge + ( + // Global Ports + .clk(ACLK), + .reset(~ARESETN), + // little endian signals + .s_axis_tready(S_AXIS_TREADY), + .s_axis_tdata(S_AXIS_TDATA), + .s_axis_tlast(S_AXIS_TLAST), + .s_axis_tvalid(S_AXIS_TVALID), + .s_axis_tuser(S_AXIS_TUSER), + .s_axis_tkeep(S_AXIS_TKEEP), + // big endian signals + .m_axis_tready(M_AXIS_INT_TREADY), + .m_axis_tdata(M_AXIS_INT_TDATA), + .m_axis_tlast(M_AXIS_INT_TLAST), + .m_axis_tvalid(M_AXIS_INT_TVALID), + .m_axis_tuser(M_AXIS_INT_TUSER), + .m_axis_tkeep(M_AXIS_INT_TKEEP) + ); + + + /* ------------------------------------------ + * big endian ---> little endian + * ----------------------------------------- */ + + bridge + #( + .C_AXIS_DATA_WIDTH (C_S_AXIS_TDATA_WIDTH), + .C_AXIS_TUSER_WIDTH (C_S_AXIS_TUSER_WIDTH) + ) be_le_bridge + ( + // Global Ports + .clk(ACLK), + .reset(~ARESETN), + // big endian signals + .s_axis_tready(S_AXIS_INT_TREADY), + .s_axis_tdata(S_AXIS_INT_TDATA), + .s_axis_tlast(S_AXIS_INT_TLAST), + .s_axis_tvalid(S_AXIS_INT_TVALID), + .s_axis_tuser(S_AXIS_INT_TUSER), + .s_axis_tkeep(S_AXIS_INT_TKEEP), + // little endian signals + .m_axis_tready(M_AXIS_TREADY), + .m_axis_tdata(M_AXIS_TDATA), + .m_axis_tlast(M_AXIS_TLAST), + .m_axis_tvalid(M_AXIS_TVALID), + .m_axis_tuser(M_AXIS_TUSER), + .m_axis_tkeep(M_AXIS_TKEEP) + ); + +endmodule diff --git a/hw/lib/contrib/nf_endianess_manager_v1_0_0/nf_endianess_manager.tcl b/hw/lib/contrib/nf_endianess_manager_v1_0_0/nf_endianess_manager.tcl new file mode 100755 index 0000000..3ca5943 --- /dev/null +++ b/hw/lib/contrib/nf_endianess_manager_v1_0_0/nf_endianess_manager.tcl @@ -0,0 +1,111 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design nf_endianess_manager +set top nf_endianess_manager +set device $::env(DEVICE) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# set IP paths +##################################### + +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +update_ip_catalog +puts "nf_endianess_manager" +# Project Constraints +##################################### +# Project Structure & IP Build +##################################### + +read_verilog "./hdl/bridge.v" +read_verilog "./hdl/nf_endianess_manager.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + + +ipx::add_user_parameter {C_M_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property display_name {C_M_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property display_name {C_S_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property display_name {C_M_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property display_name {C_S_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] + + +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces S_AXIS -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces M_AXIS -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces S_AXIS_INT -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces M_AXIS_INT -of_objects [ipx::current_core]] + +update_ip_catalog -rebuild +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + diff --git a/hw/lib/std/axi_sim_transactor_v1_0_0/Makefile b/hw/lib/std/axi_sim_transactor_v1_0_0/Makefile new file mode 100644 index 0000000..98fd1d8 --- /dev/null +++ b/hw/lib/std/axi_sim_transactor_v1_0_0/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (c) 2015 Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +all: clean + vivado -mode batch -source axi_sim_transactor.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* ip_pro* *.*~ *.zip hdl/axis_sim_pkg/ hdl/lib_srl_fifo hdl/lib_srl_fifo_v1_0 hdl/lib_pkg hdl/lib_pkg_v1_0 diff --git a/hw/lib/std/axi_sim_transactor_v1_0_0/axi_sim_transactor.tcl b/hw/lib/std/axi_sim_transactor_v1_0_0/axi_sim_transactor.tcl new file mode 100644 index 0000000..14d8e4d --- /dev/null +++ b/hw/lib/std/axi_sim_transactor_v1_0_0/axi_sim_transactor.tcl @@ -0,0 +1,87 @@ +# +# Copyright (c) 2015 Georgina Kalogeridou +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Set variables. +set design axi_sim_transactor +set device $::env(DEVICE) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name NetFPGA + +set axis_sim_pkg_path ../axis_sim_pkg_v1_0_0/hdl/ +set lib_srl_fifo_path $::env(XILINX_VIVADO)/data/ip/xilinx/lib_srl_fifo_v1_0/hdl +set lib_pkg_path $::env(XILINX_VIVADO)/data/ip/xilinx/lib_pkg_v1_0/hdl + +# Project setting. +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${design} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] + +# IP build. +file copy -force ${lib_srl_fifo_path}/lib_srl_fifo_v1_0_rfs.vhd "./hdl/lib_srl_fifo_v1_0_rfs.vhd" +read_vhdl "./hdl/lib_srl_fifo_v1_0_rfs.vhd" +set_property is_global_include true [get_files ./hdl/lib_srl_fifo_v1_0_rfs.vhd] +update_ip_catalog + +file copy -force ${lib_pkg_path}/lib_pkg_v1_0_rfs.vhd "./hdl/lib_pkg_v1_0_rfs.vhd" +read_vhdl "./hdl/lib_pkg_v1_0_rfs.vhd" +set_property is_global_include true [get_files ./hdl/lib_pkg_v1_0_rfs.vhd] +update_ip_catalog + +file copy -force ${axis_sim_pkg_path}/ "./hdl/axis_sim_pkg/" +read_vhdl "./hdl/axis_sim_pkg/axis_sim_pkg.vhd" +update_ip_catalog + +read_vhdl "./hdl/transactor_fifos.vhd" +read_vhdl "./hdl/axi_sim_transactor.vhd" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +update_ip_catalog -rebuild + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + diff --git a/hw/lib/std/axi_sim_transactor_v1_0_0/hdl/axi_sim_transactor.vhd b/hw/lib/std/axi_sim_transactor_v1_0_0/hdl/axi_sim_transactor.vhd new file mode 100755 index 0000000..1c46c8f --- /dev/null +++ b/hw/lib/std/axi_sim_transactor_v1_0_0/hdl/axi_sim_transactor.vhd @@ -0,0 +1,555 @@ +--- +-- Copyright (c) 2015 David J. Miller, Georgina Kalogeridou +-- All rights reserved. +-- +-- This software was developed by +-- Stanford University and the University of Cambridge Computer Laboratory +-- under National Science Foundation under Grant No. CNS-0855268, +-- the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +-- by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +-- as part of the DARPA MRC research programme. +-- +-- @NETFPGA_LICENSE_HEADER_START@ +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- @NETFPGA_LICENSE_HEADER_END@ +-- +------------------------------------------------------------------------------ +-- File: +-- axi_sim_transactor.vhd +-- +-- Library: +-- hw/std/cores/axi_sim_transactor_v1_0_0 +-- +-- Module: +-- axi_sim_transactor +-- +-- Author: +-- David J. Miller, Georgina Kalogeridou +-- +-- Description: +-- Drives an AXI Stream slave using stimuli from an AXI grammar +-- formatted text file. +-- + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use ieee.numeric_std.all; +use ieee.std_logic_textio.all; + +use std.textio.all; + +library xil_defaultlib; +use xil_defaultlib.axis_sim_pkg.all; + +entity axi_sim_transactor is + generic ( + STIM_FILE : string := "../../reg_stim.axi"; + EXPECT_FILE : string := "../../reg_expect.axi"; + LOG_FILE : string := "../../reg_stim.log" + ); + port ( + axi_aclk : in std_logic; + axi_resetn : in std_logic; + -- AXI Lite interface + -- + -- AXI Write address channel + M_AXI_AWADDR : out std_logic_vector(31 downto 0); + M_AXI_AWVALID : out std_logic; + M_AXI_AWREADY : in std_logic; + -- AXI Write data channel + M_AXI_WDATA : out std_logic_vector(31 downto 0); + M_AXI_WSTRB : out std_logic_vector( 3 downto 0); + M_AXI_WVALID : out std_logic; + M_AXI_WREADY : in std_logic; + -- AXI Write response channel + M_AXI_BRESP : in std_logic_vector( 1 downto 0); + M_AXI_BVALID : in std_logic; + M_AXI_BREADY : out std_logic; + -- AXI Read address channel + M_AXI_ARADDR : out std_logic_vector(31 downto 0); + M_AXI_ARVALID : out std_logic; + M_AXI_ARREADY : in std_logic; + -- AXI Read data & response channel + M_AXI_RDATA : in std_logic_vector(31 downto 0); + M_AXI_RRESP : in std_logic_vector( 1 downto 0); + M_AXI_RVALID : in std_logic; + M_AXI_RREADY : out std_logic; + + activity_trans_sim : out std_logic; + activity_trans_log : out std_logic; + barrier_req_trans : out std_logic; + barrier_proceed : in std_logic + ); +end; + + +architecture rtl of axi_sim_transactor is + + signal reset, rst : std_logic; + + file stim: text open read_mode is STIM_FILE; + file expect: text open read_mode is EXPECT_FILE; + file log : text open write_mode is LOG_FILE; + + signal w_req_addr : std_logic_vector(31 downto 0); + signal w_req_data : std_logic_vector(31 downto 0); + signal w_req_strb : std_logic_vector( 3 downto 0); + signal w_req_valid : std_logic; + signal w_req_ready : std_logic; + + signal w_rsp_addr : std_logic_vector(31 downto 0); + signal w_rsp_data : std_logic_vector(31 downto 0); + signal w_rsp_rsp : std_logic_vector( 1 downto 0); + signal w_rsp_valid : std_logic; + + signal r_req_addr : std_logic_vector(31 downto 0); + signal r_req_valid : std_logic; + signal r_req_ready : std_logic; + + signal r_rsp_addr : std_logic_vector(31 downto 0); + signal r_rsp_data : std_logic_vector(31 downto 0); + signal r_rsp_rsp : std_logic_vector( 1 downto 0); + signal r_rsp_valid : std_logic; + signal addr_r : std_logic_vector(31 downto 0); + signal data_r : std_logic_vector(31 downto 0); + shared variable f, o, v, j, k: integer range 0 to 31; + + +begin + + rst <= not axi_resetn; + reset <= rst; + + stimulation: process + + ----------------------------------------------------------------------- + -- quiescent() + -- + -- Quiesce outputs. + procedure quiescent is + begin + w_req_addr <= (others => '0'); + w_req_data <= (others => '0'); + w_req_strb <= (others => '0'); + w_req_valid <= '0'; + + r_req_addr <= (others => '0'); + r_req_valid <= '0'; + end procedure; + + ----------------------------------------------------------------------- + -- wait_cycle() + -- + -- Wait for N cycles (1 by default). + procedure wait_cycle( n: natural := 1 ) is + variable lp: natural := n; + begin + while lp /= 0 loop + wait until rising_edge(axi_aclk); + lp := lp - 1; + end loop; + end procedure; + + ----------------------------------------------------------------------- + variable l: line; + variable i: integer; + variable c: character; + variable ok, dontcare: boolean; + variable w_pending, r_pending: std_logic; + begin + quiescent; -- sane initial outputs + + -- Wait for a couple cycles in case reset is not asserted straight + -- away. + -- + -- NB: Reset is ignored except at the beginning of simulation. + wait_cycle( 10 ); + while reset = '1' loop -- wait until reset goes away + wait_cycle; + end loop; + + activity_trans_sim <= '0'; + barrier_req_trans <= '0'; + + -- begin reading stimuli + while not endfile( stim ) loop + -- Main dispatch: Get and parse input + readline( stim, l ); + lookahead_char( l, c, ok ); + next when not ok; + + if c = 'B' then + read_char( l, c ); + parse_int( l, i ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + write(l, integer'image(now / 1 ns) & string'(" ns.") & string'(" Info: barrier request transactor")); + writeline( output, l ); + wait for (1 ns); + barrier_req_trans <= '1'; + while (barrier_proceed = '0') loop + wait until (barrier_proceed = '1'); + end loop; + wait for (1 ns); + barrier_req_trans <= '0'; + wait until (barrier_proceed = '0'); + write(l, integer'image(now / 1 ns) & string'(" ns.") & string'("Info: barrier complete transactor")); + writeline( output, l ); + + elsif c = 'N' then + read_char( l, c ); + parse_int( l, v ); + quiescent; + wait for ( v * 1 ns); + wait_cycle; + + elsif c = 'S' then -- wait for relative time (ns) + read_char( l, c ); -- discard operator + parse_int( l, i ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + -- operator @(N): wait until absolute time N ns + elsif c = '@' then -- wait until absolute time (ns) + read_char( l, c ); -- discard operator + parse_int( l, i ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + elsif c = 'R' then + read_char( l, c ); + parse_int( l, i ); + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Read Register!")); + writeline( output, l ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + elsif c = 'W' then + read_char( l, c ); + parse_int( l, i ); + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Write Register!")); + writeline( output, l ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + elsif c = 'D' then + read_char( l, c ); + parse_int( l, i ); + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Info: delaying ") & integer'image(i) & string'(" ns")); + writeline( output, l ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + else + activity_trans_sim <= '1'; + -- parse out each component of the stimulus + parse_slv( l, w_req_addr, dontcare ); + w_pending := sl( not dontcare ); + w_req_valid <= w_pending; + read_char( l, c ); -- discard ',' + parse_slv( l, w_req_data, dontcare ); + if w_pending = '1' then + assert not dontcare + report STIM_FILE & ": malformed write request: missing data" + severity warning; + end if; + read_char( l, c ); -- discard ',' + + parse_slv( l, w_req_strb, dontcare ); + if w_pending = '1' then + assert not dontcare + report STIM_FILE & ": malformed write request: missing byte lane strobe" + severity warning; + end if; + read_char( l, c ); -- discard ',' + parse_slv( l, r_req_addr, dontcare ); + r_pending := sl( not dontcare ); + r_req_valid <= r_pending; + wait_cycle; + -- block until accepted + while ((w_pending and not w_req_ready) or (r_pending and not r_req_ready)) = '1' loop + wait_cycle; + end loop; + w_req_valid <= '0'; + r_req_valid <= '0'; + -- wait for transactions to return, as required + read_char( l, c ); -- read terminal wait flag + if c = '.' then -- '.' == wait for result + while (w_pending or r_pending) = '1' loop + wait_cycle; + if w_rsp_valid = '1' and w_rsp_addr = w_req_addr then + w_pending := '0'; + end if; + if r_rsp_valid = '1' and r_rsp_addr = r_req_addr then + r_pending := '0'; + end if; + end loop; + elsif c = ',' then -- continue immediately + else + assert false + report STIM_FILE & ": bad input: expected terminal ',' or '.'" + severity failure; + end if; + activity_trans_sim <= '0'; + end if; + deallocate(l); -- finished with input line + end loop; + + -- End of stimuli. + quiescent; + write( l, string'("") ); + writeline( output, l ); + write( l, STIM_FILE & string'(": end of stimuli @ ") & integer'image(now / 1 ns) & string'(" ns.") ); + writeline( output, l ); + wait; + end process; + + expected: process + + ----------------------------------------------------------------------- + -- wait_cycle() + -- + -- Wait for N cycles (1 by default). + procedure wait_cycle( n: natural := 1 ) is + variable lp: natural := n; + begin + while lp /= 0 loop + wait until rising_edge(axi_aclk); + lp := lp - 1; + end loop; + end procedure; + ----------------------------------------------------------------------- + + variable l: line; + variable i: integer; + variable t, p: integer :=0; + variable c: character; + variable ok, dontcare: boolean; + variable write_pending, read_pending: std_logic; + + begin + + -- NB: Reset is ignored except at the beginning of simulation. + wait_cycle( 10 ); + while reset = '1' loop -- wait until reset goes away + wait_cycle; + end loop; + + -- begin reading stimuli + while not endfile( expect ) loop + -- Main dispatch: Get and parse input + readline( expect, l ); + lookahead_char( l, c, ok ); + next when not ok; + + if c = 'B' then + read_char( l, c ); + parse_int( l, i ); + wait for ( i * 1 ns); + wait_cycle; + + elsif c = 'R' then + read_char( l, c ); + parse_int( l, i ); + v := v + 1; + wait for ( i * 1 ns); + wait_cycle; + + elsif c = 'W' then -- wait until absolute time (ns) + read_char( l, c ); -- discard operator + parse_int( l, i ); + wait for ( i * 1 ns); + wait_cycle; + + -- operator @(N): wait until absolute time N ns + elsif c = '@' then -- wait until absolute time (ns) + read_char( l, c ); -- discard operator + parse_int( l, i ); + wait for ( i * 1 ns); + wait_cycle; + + elsif c = '+' then -- wait for relative time (ns) + read_char( l, c ); -- discard operator + parse_int( l, i ); + wait for ( i * 1 ns); + wait_cycle; + + else + parse_slv( l, addr_r, dontcare ); + read_pending := sl( not dontcare ); + read_char( l, c ); -- discard ',' + parse_slv( l, data_r, dontcare ); + if read_pending = '1' then + assert not dontcare + report EXPECT_FILE & ": malformed read request: missing data" + severity warning; + end if; + wait_cycle; + -- block until accepted + while (read_pending and not r_req_ready) = '1' loop + wait_cycle; + end loop; + -- wait for transactions to return, as required + read_char( l, c ); -- read terminal wait flag + if c = '.' then -- '.' == wait for result + while (read_pending) = '1' loop + wait_cycle; + if r_rsp_valid = '1' and addr_r = r_rsp_addr then + read_pending := '0'; + end if; + end loop; + elsif c = ',' then -- continue immediately + else + assert false + report STIM_FILE & ": bad input: expected terminal ',' or '.'" + severity failure; + end if; + end if; + deallocate(l); -- finished with input line + end loop; + + -- End of stimuli. + write( l, string'("") ); + writeline( output, l ); + write( l, EXPECT_FILE & string'(": end of stimuli @ ") & integer'image(now / 1 ns) & string'(" ns.") ); + writeline( output, l ); + wait; + end process; +-------------------------------------------------------------------------------------------------- + + + logging: process( axi_aclk ) + + function result_str( res: std_logic_vector(1 downto 0) ) return string is + begin + case res is + when "00" => return "OKAY"; + when "01" => return "EXOKAY"; + when "10" => return "SLVERR"; + when "11" => return "DECERR"; + when others => return "INVALID_RESP"; + end case; + end function; + + variable l: line; + variable g: integer; + variable b: integer := 0; + + begin + activity_trans_log <= '0'; + + if rising_edge( axi_aclk ) then + if w_rsp_valid = '1' then + activity_trans_log <= '1'; + hwrite( l, w_rsp_addr, RIGHT, w_rsp_addr'length/4 ); + write( l, string'(" <- ") ); + hwrite( l, w_rsp_data, RIGHT, w_rsp_data'length/4 ); + write( l, string'(" (" & result_str( w_rsp_rsp ) & ")") & + ht & ht & string'("# ") & integer'image(now / 1 ns) & string'(" ns") ); + writeline( log, l ); + end if; + if r_rsp_valid = '1' then + activity_trans_log <= '1'; + hwrite( l, r_rsp_addr, RIGHT, r_rsp_addr'length/4 ); + write( l, string'(" -> ") ); + if addr_r = r_rsp_addr then + + for g in 0 to 31 loop + if (data_r(g) = '0') and (r_rsp_data(g) = 'X') then + b := 1; + end if; + end loop; + + if data_r = r_rsp_data then + hwrite( l, r_rsp_data, RIGHT, r_rsp_data'length/4 ); + write( l, string'(" (" & result_str( r_rsp_rsp ) & ")") & ht & ht & string'("# ") & integer'image(now / 1 ns) & string'(" ns") ); + elsif b = 1 then + hwrite( l, r_rsp_data, RIGHT, r_rsp_data'length/4 ); + write( l, string'(" (" & result_str( r_rsp_rsp ) & ")") & ht & ht & string'("# ") & integer'image(now / 1 ns) & string'(" ns") & string'(" ## ") & string'("WARNING! Undefined bits -- check waveforms!!!!") ); + elsif data_r /= r_rsp_data and b = 0 then + activity_trans_log <= '0'; + write( l, string'("Data Error: register error!!!! ")); + write( l, string'("Seen from user: ")); + hwrite( l, data_r); + write( l, string'(" but expected from system: ")); + hwrite( l, r_rsp_data, RIGHT, r_rsp_data'length/4 ); + end if; + else + activity_trans_log <= '0'; + write( l, string'("Address Error: register error!!!! ")); + write( l, string'("Seen from user: ")); + hwrite( l, addr_r); + write( l, string'(" but expected from system: ")); + hwrite( l, r_rsp_addr, RIGHT, r_rsp_addr'length/4 ); + end if; + writeline( log, l ); + end if; + end if; + + end process; + + fifos: entity xil_defaultlib.transactor_fifos + port map ( + clk => axi_aclk, + reset => reset, + -- + w_req_addr => w_req_addr, + w_req_data => w_req_data, + w_req_strb => w_req_strb, + w_req_valid => w_req_valid, + w_req_ready => w_req_ready, + + w_rsp_addr => w_rsp_addr, + w_rsp_data => w_rsp_data, + w_rsp_rsp => w_rsp_rsp, + w_rsp_valid => w_rsp_valid, + -- + r_req_addr => r_req_addr, + r_req_valid => r_req_valid, + r_req_ready => r_req_ready, + + r_rsp_addr => r_rsp_addr, + r_rsp_data => r_rsp_data, + r_rsp_rsp => r_rsp_rsp, + r_rsp_valid => r_rsp_valid, + -- + M_AXI_AWADDR => M_AXI_AWADDR, + M_AXI_AWVALID => M_AXI_AWVALID, + M_AXI_AWREADY => M_AXI_AWREADY, + M_AXI_WDATA => M_AXI_WDATA, + M_AXI_WSTRB => M_AXI_WSTRB, + M_AXI_WVALID => M_AXI_WVALID, + M_AXI_WREADY => M_AXI_WREADY, + M_AXI_BRESP => M_AXI_BRESP, + M_AXI_BVALID => M_AXI_BVALID, + M_AXI_BREADY => M_AXI_BREADY, + M_AXI_ARADDR => M_AXI_ARADDR, + M_AXI_ARVALID => M_AXI_ARVALID, + M_AXI_ARREADY => M_AXI_ARREADY, + M_AXI_RDATA => M_AXI_RDATA, + M_AXI_RRESP => M_AXI_RRESP, + M_AXI_RVALID => M_AXI_RVALID, + M_AXI_RREADY => M_AXI_RREADY); + +end; diff --git a/hw/lib/std/axi_sim_transactor_v1_0_0/hdl/transactor_fifos.vhd b/hw/lib/std/axi_sim_transactor_v1_0_0/hdl/transactor_fifos.vhd new file mode 100755 index 0000000..2849502 --- /dev/null +++ b/hw/lib/std/axi_sim_transactor_v1_0_0/hdl/transactor_fifos.vhd @@ -0,0 +1,276 @@ +--- +-- Copyright (c) 2015 David J. Miller +-- All rights reserved. +-- +-- This software was developed by +-- Stanford University and the University of Cambridge Computer Laboratory +-- under National Science Foundation under Grant No. CNS-0855268, +-- the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +-- by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +-- as part of the DARPA MRC research programme. +-- +-- @NETFPGA_LICENSE_HEADER_START@ +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- @NETFPGA_LICENSE_HEADER_END@ +-- +------------------------------------------------------------------------------ +-- File: +-- transactor_fifos.vhd +-- +-- Library: +-- hw/std/cores/axi_sim_transactor_v1_0_0 +-- +-- Module: +-- axi_sim_transactor +-- +-- Author: +-- David J. Miller +-- +-- Description: +-- AXI4 Lite I/O FIFOs +-- + +library IEEE; +use IEEE.STD_LOGIC_1164.all; + +use std.textio.all; + +library xil_defaultlib; +library lib_srl_fifo_v1_0_2; +use lib_srl_fifo_v1_0_2.all; + +entity transactor_fifos is + port ( + clk : in std_logic; + reset : in std_logic; + + -- + -- Transactor interface + -- + w_req_addr : in std_logic_vector(31 downto 0); + w_req_data : in std_logic_vector(31 downto 0); + w_req_strb : in std_logic_vector( 3 downto 0); + w_req_valid : in std_logic; + w_req_ready : out std_logic; + + w_rsp_addr : out std_logic_vector(31 downto 0); + w_rsp_data : out std_logic_vector(31 downto 0); + w_rsp_rsp : out std_logic_vector( 1 downto 0); + w_rsp_valid : out std_logic; + -- + r_req_addr : in std_logic_vector(31 downto 0); + r_req_valid : in std_logic; + r_req_ready : out std_logic; + + r_rsp_addr : out std_logic_vector(31 downto 0); + r_rsp_data : out std_logic_vector(31 downto 0); + r_rsp_rsp : out std_logic_vector( 1 downto 0); + r_rsp_valid : out std_logic; + + -- + -- AXI Lite interface + -- + -- AXI Write address channel + M_AXI_AWADDR : out std_logic_vector(31 downto 0); + M_AXI_AWVALID : out std_logic; + M_AXI_AWREADY : in std_logic; + -- AXI Write data channel + M_AXI_WDATA : out std_logic_vector(31 downto 0); + M_AXI_WSTRB : out std_logic_vector( 3 downto 0); + M_AXI_WVALID : out std_logic; + M_AXI_WREADY : in std_logic; + -- AXI Write response channel + M_AXI_BRESP : in std_logic_vector( 1 downto 0); + M_AXI_BVALID : in std_logic; + M_AXI_BREADY : out std_logic; + -- AXI Read address channel + M_AXI_ARADDR : out std_logic_vector(31 downto 0); + M_AXI_ARVALID : out std_logic; + M_AXI_ARREADY : in std_logic; + -- AXI Read data & response channel + M_AXI_RDATA : in std_logic_vector(31 downto 0); + M_AXI_RRESP : in std_logic_vector( 1 downto 0); + M_AXI_RVALID : in std_logic; + M_AXI_RREADY : out std_logic + ); +end; + + +architecture rtl of transactor_fifos is + signal w_req_we : std_logic; + signal int_w_addr_full : std_logic; + signal int_w_addr_empty : std_logic; + signal w_req_addr_data : std_logic_vector(w_rsp_addr'length+w_req_data'length-1 downto 0); + signal w_rsp_addr_data : std_logic_vector(w_rsp_addr'length+w_req_data'length-1 downto 0); + + signal axi_w_addr_full : std_logic; + signal axi_w_addr_empty : std_logic; + + signal w_req_data_strb_full : std_logic; + signal w_req_data_strb_empty : std_logic; + signal w_req_data_strb : std_logic_vector(w_req_strb'length+w_req_data'length-1 downto 0); + signal w_axi_data_strb : std_logic_vector(w_req_strb'length+w_req_data'length-1 downto 0); + + signal r_req_we : std_logic; + signal int_r_addr_full : std_logic; + signal int_r_addr_empty : std_logic; + signal r_rsp_addr_i : std_logic_vector(r_rsp_addr'range); + signal r_req_addr_fifo : std_logic_vector(r_req_addr'range); + signal r_req_re : std_logic; + signal int_r_re : std_logic; + + signal axi_r_addr_full : std_logic; + signal axi_r_addr_empty : std_logic; + + + signal int_w_req_re : std_logic; + signal w_req_re : std_logic; + signal w_data_re : std_logic; + +begin + --------------------------------------------------------------------------- + -- AXI Write + --------------------------------------------------------------------------- + + w_req_ready <= not int_w_addr_full and not axi_w_addr_full and not w_req_data_strb_full; + w_req_we <= not int_w_addr_full and not axi_w_addr_full and not w_req_data_strb_full and w_req_valid; + + w_req_addr_data <= w_req_addr & w_req_data; + w_req_data_strb <= w_req_strb & w_req_data; + + int_w_req_re <= M_AXI_BVALID and not int_w_addr_empty; + w_req_re <= M_AXI_AWREADY and not axi_w_addr_empty; + w_data_re <= M_AXI_WREADY and not w_req_data_strb_empty; + + + + int_w_addr: entity lib_srl_fifo_v1_0_2.srl_fifo_f + generic map ( + C_DWIDTH => w_req_addr_data'length, + C_DEPTH => 16) + port map ( + Clk => clk, + Reset => reset, + + FIFO_Write => w_req_we, + Data_In => w_req_addr_data, + FIFO_Full => int_w_addr_full, + + FIFO_Read => int_w_req_re, + Data_Out => w_rsp_addr_data, + FIFO_Empty => int_w_addr_empty, + Addr => open); + + axi_w_addr: entity lib_srl_fifo_v1_0_2.srl_fifo_f + generic map ( + C_DWIDTH => w_req_addr'length, + C_DEPTH => 16) + port map ( + Clk => clk, + Reset => reset, + + FIFO_Write => w_req_we, + Data_In => w_req_addr, + FIFO_Full => axi_w_addr_full, + + FIFO_Read => w_req_re, + Data_Out => M_AXI_AWADDR, + FIFO_Empty => axi_w_addr_empty, + Addr => open); + + axi_w_data: entity lib_srl_fifo_v1_0_2.srl_fifo_f + generic map ( + C_DWIDTH => w_req_data_strb'length, + C_DEPTH => 16) + port map ( + Clk => clk, + Reset => reset, + + FIFO_Write => w_req_we, + Data_In => w_req_data_strb, + FIFO_Full => w_req_data_strb_full, + + FIFO_Read => w_data_re, + Data_Out => w_axi_data_strb, + FIFO_Empty => w_req_data_strb_empty, + Addr => open); + + M_AXI_AWVALID <= not axi_w_addr_empty; + + M_AXI_WDATA <= w_axi_data_strb(M_AXI_WDATA'range); + M_AXI_WSTRB <= w_axi_data_strb(w_axi_data_strb'high downto w_axi_data_strb'high-M_AXI_WSTRB'length+1); + M_AXI_WVALID <= not w_req_data_strb_empty; + + w_rsp_addr <= w_rsp_addr_data(w_rsp_addr_data'high downto w_rsp_addr_data'high-w_req_addr'length+1) + when int_w_addr_empty = '0' else (others => '-'); + w_rsp_data <= w_rsp_addr_data(w_req_data'length - 1 downto 0) + when int_w_addr_empty = '0' else (others => '-'); + w_rsp_rsp <= M_AXI_BRESP when M_AXI_BVALID = '1' else (others => '-'); + w_rsp_valid <= M_AXI_BVALID; + M_AXI_BREADY <= '1'; + + --------------------------------------------------------------------------- + -- AXI Read + --------------------------------------------------------------------------- + + r_req_ready <= not int_r_addr_full and not axi_r_addr_full; + r_req_we <= not int_r_addr_full and not axi_r_addr_full and r_req_valid; + r_req_re <= M_AXI_ARREADY and not axi_r_addr_empty; + + int_r_re <= M_AXI_RVALID and not int_r_addr_empty; + + int_r_addr: entity lib_srl_fifo_v1_0_2.srl_fifo_f + generic map ( + C_DWIDTH => r_req_addr'length, + C_DEPTH => 16) + port map ( + Clk => clk, + Reset => reset, + + FIFO_Write => r_req_we, + Data_In => r_req_addr, + FIFO_Full => int_r_addr_full, + + FIFO_Read => int_r_re, + Data_Out => r_rsp_addr_i, + FIFO_Empty => int_r_addr_empty, + Addr => open); + + axi_r_addr: entity lib_srl_fifo_v1_0_2.srl_fifo_f + generic map ( + C_DWIDTH => r_req_addr'length, + C_DEPTH => 16) + port map ( + Clk => clk, + Reset => reset, + + FIFO_Write => r_req_we, + Data_In => r_req_addr, + FIFO_Full => axi_r_addr_full, + + FIFO_Read => r_req_re, + Data_Out => r_req_addr_fifo , + FIFO_Empty => axi_r_addr_empty, + Addr => open); + + M_AXI_ARVALID <= not axi_r_addr_empty; + M_AXI_ARADDR <= r_req_addr_fifo; + + r_rsp_addr <= r_rsp_addr_i when int_r_addr_empty = '0' else (others => '-'); + r_rsp_data <= M_AXI_RDATA when M_AXI_RVALID = '1' else (others => '-'); + r_rsp_rsp <= M_AXI_RRESP when M_AXI_RVALID = '1' else (others => '-'); + r_rsp_valid <= M_AXI_RVALID; + M_AXI_RREADY <= '1'; +end; diff --git a/hw/lib/std/axis_fifo_v1_0_0/Makefile b/hw/lib/std/axis_fifo_v1_0_0/Makefile new file mode 100644 index 0000000..93e8bf9 --- /dev/null +++ b/hw/lib/std/axis_fifo_v1_0_0/Makefile @@ -0,0 +1,32 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source axis_fifo.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/std/axis_fifo_v1_0_0/axis_fifo.tcl b/hw/lib/std/axis_fifo_v1_0_0/axis_fifo.tcl new file mode 100644 index 0000000..e3cf55e --- /dev/null +++ b/hw/lib/std/axis_fifo_v1_0_0/axis_fifo.tcl @@ -0,0 +1,93 @@ +# +# Copyright (c) 2015 Noa Zilberman +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Vivado Launch Script +#### Change design settings here ####### +set design axis_fifo +set top axis_fifo +set device $::env(DEVICE) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# set IP paths +##################################### + +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +puts "Creating AXIS FIFO IP" +# Project Constraints +##################################### +# Project Structure & IP Build +##################################### + +update_ip_catalog + +read_verilog "./hdl/axis_fifo.v" +update_compile_order -fileset sources_1 + +update_compile_order -fileset sim_1 +ipx::package_project +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] +ipx::infer_user_parameters [ipx::current_core] + +ipx::add_user_parameter {C_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameter C_AXIS_DATA_WIDTH [ipx::current_core]] +set_property display_name {C_AXIS_DATA_WIDTH} [ipx::get_user_parameter C_AXIS_DATA_WIDTH [ipx::current_core]] +set_property value {64} [ipx::get_user_parameter C_AXIS_DATA_WIDTH [ipx::current_core]] +set_property value_format {long} [ipx::get_user_parameter C_AXIS_DATA_WIDTH [ipx::current_core]] + +ipx::add_user_parameter {C_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameter C_AXIS_TUSER_WIDTH [ipx::current_core]] +set_property display_name {C_AXIS_TUSER_WIDTH} [ipx::get_user_parameter C_AXIS_TUSER_WIDTH [ipx::current_core]] +set_property value {128} [ipx::get_user_parameter C_AXIS_TUSER_WIDTH [ipx::current_core]] +set_property value_format {long} [ipx::get_user_parameter C_AXIS_TUSER_WIDTH [ipx::current_core]] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + +file delete -force ${proj_dir} + diff --git a/hw/lib/std/axis_fifo_v1_0_0/hdl/axis_fifo.v b/hw/lib/std/axis_fifo_v1_0_0/hdl/axis_fifo.v new file mode 100644 index 0000000..2a6b270 --- /dev/null +++ b/hw/lib/std/axis_fifo_v1_0_0/hdl/axis_fifo.v @@ -0,0 +1,253 @@ +//- +// Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +// Junior University +// Copyright (C) 2018 Stephen Ibanez +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +/******************************************************************************* + * File: + * axis_fifo.v + * + * Library: + * + * Module: + * axis_fifo + * + * Author: + * Stephen Ibanez + * + * Description: + * Simple AXI4 Stream wrapper around fallthrough_small_fifo + * + */ + +module axis_fifo +#( + // Pkt AXI Stream Data Width + parameter C_AXIS_DATA_WIDTH = 64, + parameter C_AXIS_TUSER_WIDTH = 128 +) +( + // Global Ports + input axis_aclk, + input axis_resetn, + + // Master Pkt Stream Ports (outgoing pkts) + output [C_AXIS_DATA_WIDTH - 1:0] m_axis_tdata, + output [((C_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_tkeep, + output [C_AXIS_TUSER_WIDTH-1:0] m_axis_tuser, + output reg m_axis_tvalid, + input m_axis_tready, + output m_axis_tlast, + + // Slave Pkt Stream Ports (incomming pkts) + input [C_AXIS_DATA_WIDTH - 1:0] s_axis_tdata, + input [((C_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_tkeep, + input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser, + input s_axis_tvalid, + output reg s_axis_tready, + input s_axis_tlast + +); + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 '0'); + M_AXIS_TKEEP <= (others => '0'); + M_AXIS_TUSER <= (others => '0'); + M_AXIS_TLAST <= '0'; + M_AXIS_TVALID <= '0'; + end procedure; + ----------------------------------------------------------------------- + -- wait_cycle() + -- + -- Wait for N cycles (1 by default). + procedure wait_cycle( n: natural := 1 ) is + variable lp: natural := n; + begin + while lp /= 0 loop + wait until rising_edge(ACLK); + lp := lp - 1; + end loop; + end procedure; + ----------------------------------------------------------------------- + variable l: line; + variable i, x: integer := 0; + variable c: character; + variable ok, dontcare: boolean; + variable barrier_count : integer := 0; + variable exp_pkts: integer :=0; + + begin + + quiescent; -- sane initial outputs + + -- Wait for a couple cycles in case reset is not asserted straight + -- away. + -- + -- NB: Reset is ignored except at the beginning of simulation. + wait_cycle( 10 ); + while ARESETN = '0' loop -- wait until reset goes away + wait_cycle; + end loop; + + activity_stim <= '0'; + barrier_req <= '0'; + + -- begin reading stimuli + while not endfile( f ) loop + -- Main dispatch: Get and parse input + readline( f, l ); + lookahead_char( l, c, ok ); + next when not ok; + + if c = 'B' then + barrier_count := barrier_count + 1; + read_char( l, c ); + parse_int( l, x ); + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Info: Input file contains:")); + writeline( output, l ); + write(l, string'("Info: ") & integer'image(barrier_count) & string'(" barriers")); + writeline( output, l ); + quiescent; + wait for ( x * 1 ns); + wait_cycle; + + elsif c = 'N' then + read_char( l, c ); + parse_int( l, i ); + exp_pkts := exp_pkts + i; + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + elsif c = 'S' then + read_char( l, c ); + parse_int( l, i ); + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Info: ") & integer'image(i) & string'(" ingress packets")); + writeline( output, l ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Info: barrier request: expecting ") & integer'image(exp_pkts) & string'(" pkts")); + writeline( output, l ); + wait for 1 ns; + + while (to_integer(UNSIGNED(counter)) /= exp_pkts) loop + wait until (to_integer(UNSIGNED(counter)) >= exp_pkts); + end loop; + + barrier_req <= '1'; + while (barrier_proceed = '0') loop + wait until (barrier_proceed = '1'); + end loop; + wait for 1 ns; + barrier_req <= '0'; + wait until (barrier_proceed = '0'); + + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Info: barrier complete")); + writeline( output, l ); + + -- operator *(N): wait for N cycles + elsif c = '*' then -- wait n cycles + read_char( l, c ); -- discard operator + parse_int( l, i ); + quiescent; + wait_cycle( i ); + + -- operator @(N): wait until absolute time N ns + elsif c = '@' then -- wait until absolute time (ns) + read_char( l, c ); -- discard operator + parse_int( l, i ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + -- operator +(N): wait for N ns + elsif c = '+' then -- wait for relative time (ns) + read_char( l, c ); -- discard operator + parse_int( l, i ); + quiescent; + wait for ( i * 1 ns); + wait_cycle; + + -- data transfer: a cycle containing active data + else + wait for 0.5ns; + M_AXIS_TVALID <= '1'; + activity_stim <= '1'; + -- parse out each component of the stimulus + parse_slv( l, M_AXIS_TDATA, dontcare ); + assert not dontcare + report input_file & ": bad input: nf_axis_sim_stim doesn't accept 'don't-cares'" + severity failure; + read_char( l, c ); -- discard ',' + parse_slv( l, M_AXIS_TKEEP, dontcare ); + assert not dontcare + report input_file & ": bad input: nf_axis_sim_stim doesn't accept 'don't-cares'" + severity failure; + read_char( l, c ); -- discard ',' + parse_slv( l, M_AXIS_TUSER, dontcare ); + assert not dontcare + report input_file & ": bad input: nf_axis_sim_stim doesn't accept 'don't-cares'" + severity failure; + read_char( l, c ); -- read terminal flag for TLAST... + if c = '.' then -- '.' == end of packet + M_AXIS_TLAST <= '1'; + report "Time is " & integer'image(now / 1 ns) & string'(" ns."); + write(l, string'("Sending next ingress packet")); + writeline( output, l ); + elsif c = ',' then -- ',' == more pkt data to follow + M_AXIS_TLAST <= '0'; + else + assert false + report input_file & ": bad input: expected terminal ',' or '.'" + severity failure; + end if; + wait_cycle; + + -- block until target ready + while M_AXIS_TREADY /= '1' loop + wait_cycle; + end loop; + activity_stim <= '0'; + end if; + + deallocate(l); -- finished with input line + end loop; + + -- End of stimuli. + quiescent; + write( l, string'("") ); + writeline( output, l ); + write( l, input_file & string'(": end of stimuli @ ") & + integer'image(now / 1 ns) & string'(" ns.") ); + writeline( output, l ); + wait; + end process; +end; diff --git a/hw/lib/std/barrier_v1_0_0/Makefile b/hw/lib/std/barrier_v1_0_0/Makefile new file mode 100644 index 0000000..7ea74e4 --- /dev/null +++ b/hw/lib/std/barrier_v1_0_0/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (c) 2015 Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +all: clean + vivado -mode batch -source barrier.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* ip_pro* *.*~ *.zip diff --git a/hw/lib/std/barrier_v1_0_0/barrier.tcl b/hw/lib/std/barrier_v1_0_0/barrier.tcl new file mode 100644 index 0000000..3608b24 --- /dev/null +++ b/hw/lib/std/barrier_v1_0_0/barrier.tcl @@ -0,0 +1,65 @@ +# +# Copyright (c) 2015 Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Set variables. +set design barrier +set device $::env(DEVICE) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name NetFPGA + +# Project setting. +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${design} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +update_ip_catalog +# IP build. +read_verilog "./hdl/barrier.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +update_ip_catalog -rebuild +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project diff --git a/hw/lib/std/barrier_v1_0_0/hdl/barrier.v b/hw/lib/std/barrier_v1_0_0/hdl/barrier.v new file mode 100755 index 0000000..bb9eddf --- /dev/null +++ b/hw/lib/std/barrier_v1_0_0/hdl/barrier.v @@ -0,0 +1,140 @@ +//- +// Copyright (c) 2015 University of Cambridge +// Copyright (c) 2015 Georgina Kalogeridou +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +/******************************************************************************* + * File: + * barrier.v + * + * Library: + * hw/std/cores/barrier_v1_0_0 + * + * Module: + * barrier + * + * Author: + * Modified by Georgina Kalogeridou + * Modified by Yuta Tokusashi + * + * Description: + * Barrier control module. Aggregates barrier good notifications + * from individual modules and pushes out a global barrier good notification + * when all modules are ready. + * + * + */ + +`timescale 1ns/1ps + +module barrier #( + parameter NUM_PORTS = 2, +// Time to wait before declaring the system "stuck" when we have a barrier +// and not all modules are ready to proceed. + parameter INACTIVITY_TIMEOUT = 4000 +) +( + input [NUM_PORTS-1:0] activity_stim, + input [NUM_PORTS-1:0] activity_rec, + input activity_trans_sim, + input activity_trans_log, + input [NUM_PORTS-1:0] barrier_req, + input barrier_req_trans, + output reg barrier_proceed +); + +time req_time; +reg timeout; +wire [NUM_PORTS:0] activity; +wire activity_trans; + +assign activity = {activity_stim[2] || activity_rec[2],activity_stim[1] || activity_rec[1],activity_stim[0] || activity_rec[0]}; + +assign activity_trans = {activity_trans_sim || activity_trans_log}; + +initial +begin + barrier_proceed = 0; + timeout = 0; + + forever begin + wait ({barrier_req, barrier_req_trans} != 'h0); + + req_time = $time; + timeout = 0; + #1; + + // Wait until either all ports are asserting a barrier request, + // none of the ports are asserting a barrier request, or a timeout + // occurs waiting for the barrier + wait (({barrier_req, barrier_req_trans} === {(NUM_PORTS+1){1'b1}}) || + ({barrier_req, barrier_req_trans} === 'h0) || timeout); + + if (timeout == 1) begin + $display($time," %m Error: timeout exceeded waiting for barrier"); + $finish; + end + else if ({barrier_req, barrier_req_trans} === {(NUM_PORTS+1){1'b1}}) begin + // Barrier request from all modules + + barrier_proceed = 1; + + wait ({barrier_req, barrier_req_trans} === 'h0); + + barrier_proceed = 0; + end + end +end + +initial +begin + forever begin + wait ({barrier_req, barrier_req_trans} != 'h0 && {activity, activity_trans} != 'h0); + + req_time = $time; + #1; + end +end + +initial +begin + forever begin + + if ({barrier_req, barrier_req_trans} != 'h0) begin + while ({barrier_req, barrier_req_trans} != 'h0) begin + #1; + #(req_time + INACTIVITY_TIMEOUT - $time); + if ({barrier_req, barrier_req_trans} != 'h0 && req_time + INACTIVITY_TIMEOUT <= $time) + timeout = 1; + end + end + else begin + wait ({barrier_req, barrier_req_trans} != 'h0); + end + end +end + +endmodule // barrier_ctrl diff --git a/hw/lib/std/fallthrough_small_fifo_v1_0_0/Makefile b/hw/lib/std/fallthrough_small_fifo_v1_0_0/Makefile new file mode 100644 index 0000000..5b01fbc --- /dev/null +++ b/hw/lib/std/fallthrough_small_fifo_v1_0_0/Makefile @@ -0,0 +1,32 @@ + +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source fallthrough_small_fifo.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/std/fallthrough_small_fifo_v1_0_0/fallthrough_small_fifo.tcl b/hw/lib/std/fallthrough_small_fifo_v1_0_0/fallthrough_small_fifo.tcl new file mode 100644 index 0000000..ee2cdf7 --- /dev/null +++ b/hw/lib/std/fallthrough_small_fifo_v1_0_0/fallthrough_small_fifo.tcl @@ -0,0 +1,95 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design fallthrough_small_fifo +set top fallthrough_small_fifo +set device $::env(DEVICE) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# set IP paths +##################################### + +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib [current_fileset] +puts "Creating Fallthrough Small FIFO IP" +##################################### +# Project Structure & IP Build +##################################### + +read_verilog "./hdl/fallthrough_small_fifo.v" +read_verilog "./hdl/small_fifo.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::add_user_parameter {WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters WIDTH] +set_property display_name {WIDTH} [ipx::get_user_parameters WIDTH] +set_property value {72} [ipx::get_user_parameters WIDTH] +set_property value_format {long} [ipx::get_user_parameters WIDTH] + +ipx::add_user_parameter {MAX_DEPTH_BITS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters MAX_DEPTH_BITS] +set_property display_name {MAX_DEPTH_BITS} [ipx::get_user_parameters MAX_DEPTH_BITS] +set_property value {3} [ipx::get_user_parameters MAX_DEPTH_BITS] +set_property value_format {long} [ipx::get_user_parameters MAX_DEPTH_BITS] + +ipx::add_user_parameter {PROG_FULL_THRESHOLD} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters PROG_FULL_THRESHOLD] +set_property display_name {PROG_FULL_THRESHOLD} [ipx::get_user_parameters PROG_FULL_THRESHOLD] +set_property value {2} [ipx::get_user_parameters PROG_FULL_THRESHOLD] +set_property value_format {long} [ipx::get_user_parameters PROG_FULL_THRESHOLD] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + +file delete -force ${proj_dir} diff --git a/hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/fallthrough_small_fifo.v b/hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/fallthrough_small_fifo.v new file mode 100644 index 0000000..188e032 --- /dev/null +++ b/hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/fallthrough_small_fifo.v @@ -0,0 +1,128 @@ +//- +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +///////////////////////////////////////////////////////////////////////////////// +// $Id: small_fifo.v 1998 2007-07-21 01:22:57Z grg $ +// +// Module: fallthrough_small_fifo.v +// Project: utils +// Description: small fifo with fallthrough i.e. data valid when rd is high +// +// Change history: +// 7/20/07 -- Set nearly full to 2^MAX_DEPTH_BITS - 1 by default so that it +// goes high a clock cycle early. +// 2/11/09 -- jnaous: Rewrote to make much more efficient. +// 5/11/11 -- hyzeng: Rewrote based on http://www.billauer.co.il/reg_fifo.html +// to improve timing by adding output register +/////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns/1ps + +module fallthrough_small_fifo + #(parameter WIDTH = 72, + parameter MAX_DEPTH_BITS = 3, + parameter PROG_FULL_THRESHOLD = 2**MAX_DEPTH_BITS - 1) + ( + + input [WIDTH-1:0] din, // Data in + input wr_en, // Write enable + + input rd_en, // Read the next word + + output reg [WIDTH-1:0] dout, // Data out + output full, + output nearly_full, + output prog_full, + output empty, + + input reset, + input clk + ); + + reg fifo_valid, middle_valid, dout_valid; + reg [(WIDTH-1):0] middle_dout; + + wire [(WIDTH-1):0] fifo_dout; + wire fifo_empty, fifo_rd_en; + wire will_update_middle, will_update_dout; + + // orig_fifo is just a normal (non-FWFT) synchronous or asynchronous FIFO + small_fifo + #(.WIDTH (WIDTH), + .MAX_DEPTH_BITS (MAX_DEPTH_BITS), + .PROG_FULL_THRESHOLD (PROG_FULL_THRESHOLD)) + fifo + (.din (din), + .wr_en (wr_en), + .rd_en (fifo_rd_en), + .dout (fifo_dout), + .full (full), + .nearly_full (nearly_full), + .prog_full (prog_full), + .empty (fifo_empty), + .reset (reset), + .clk (clk) + ); + + assign will_update_middle = fifo_valid && (middle_valid == will_update_dout); + assign will_update_dout = (middle_valid || fifo_valid) && (rd_en || !dout_valid); + assign fifo_rd_en = (!fifo_empty) && !(middle_valid && dout_valid && fifo_valid); + assign empty = !dout_valid; + + always @(posedge clk) begin + if (reset) + begin + fifo_valid <= 0; + middle_valid <= 0; + dout_valid <= 0; + dout <= 0; + middle_dout <= 0; + end + else + begin + if (will_update_middle) + middle_dout <= fifo_dout; + + if (will_update_dout) + dout <= middle_valid ? middle_dout : fifo_dout; + + if (fifo_rd_en) + fifo_valid <= 1; + else if (will_update_middle || will_update_dout) + fifo_valid <= 0; + + if (will_update_middle) + middle_valid <= 1; + else if (will_update_dout) + middle_valid <= 0; + + if (will_update_dout) + dout_valid <= 1; + else if (rd_en) + dout_valid <= 0; + end + end +endmodule diff --git a/hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/small_fifo.v b/hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/small_fifo.v new file mode 100644 index 0000000..e04f438 --- /dev/null +++ b/hw/lib/std/fallthrough_small_fifo_v1_0_0/hdl/small_fifo.v @@ -0,0 +1,124 @@ +//- +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +/////////////////////////////////////////////////////////////////////////////// +// $Id: small_fifo.v 4761 2008-12-27 01:11:00Z jnaous $ +// +// Module: small_fifo.v +// Project: UNET +// Description: small fifo with no fallthrough i.e. data valid after rd is high +// +// Change history: +// 7/20/07 -- Set nearly full to 2^MAX_DEPTH_BITS - 1 by default so that it +// goes high a clock cycle early. +// 11/2/09 -- Modified to have both prog threshold and almost full +/////////////////////////////////////////////////////////////////////////////// +`timescale 1ns/1ps + + module small_fifo + #(parameter WIDTH = 72, + parameter MAX_DEPTH_BITS = 3, + parameter PROG_FULL_THRESHOLD = 2**MAX_DEPTH_BITS - 1 + ) + ( + + input [WIDTH-1:0] din, // Data in + input wr_en, // Write enable + + input rd_en, // Read the next word + + output reg [WIDTH-1:0] dout, // Data out + output full, + output nearly_full, + output prog_full, + output empty, + + input reset, + input clk + ); + + +parameter MAX_DEPTH = 2 ** MAX_DEPTH_BITS; + +reg [WIDTH-1:0] queue [MAX_DEPTH - 1 : 0]; +reg [MAX_DEPTH_BITS - 1 : 0] rd_ptr; +reg [MAX_DEPTH_BITS - 1 : 0] wr_ptr; +reg [MAX_DEPTH_BITS : 0] depth; + +// Sample the data +always @(posedge clk) +begin + if (wr_en) + queue[wr_ptr] <= din; + if (rd_en) + dout <= + // synthesis translate_off + #1 + // synthesis translate_on + queue[rd_ptr]; +end + +always @(posedge clk) +begin + if (reset) begin + rd_ptr <= 'h0; + wr_ptr <= 'h0; + depth <= 'h0; + end + else begin + if (wr_en) wr_ptr <= wr_ptr + 'h1; + if (rd_en) rd_ptr <= rd_ptr + 'h1; + if (wr_en & ~rd_en) depth <= + // synthesis translate_off + #1 + // synthesis translate_on + depth + 'h1; + else if (~wr_en & rd_en) depth <= + // synthesis translate_off + #1 + // synthesis translate_on + depth - 'h1; + end +end + +assign full = depth == MAX_DEPTH; +assign prog_full = (depth >= PROG_FULL_THRESHOLD); +assign nearly_full = depth >= MAX_DEPTH-1; +assign empty = depth == 'h0; + +// synthesis translate_off +always @(posedge clk) +begin + if (wr_en && depth == MAX_DEPTH && !rd_en) + $display($time, " ERROR: Attempt to write to full FIFO: %m"); + if (rd_en && depth == 'h0) + $display($time, " ERROR: Attempt to read an empty FIFO: %m"); +end +// synthesis translate_on + +endmodule // small_fifo + diff --git a/hw/lib/std/input_arbiter_v1_0_0/Makefile b/hw/lib/std/input_arbiter_v1_0_0/Makefile new file mode 100644 index 0000000..205ad0c --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (c) 2015 University of Cambridge +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source input_arbiter.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.h b/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.h new file mode 100644 index 0000000..751ee8d --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// input_arbiter_regs_defines.h +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +##########This text should be copied to the head file ############# + #Registers offset definitions + +#define NFPLUS_INPUT_ARBITER_ID_0_OFFSET 0x0 +#define NFPLUS_INPUT_ARBITER_ID_0_DEFAULT 0x0000DA01 +#define NFPLUS_INPUT_ARBITER_ID_0_WIDTH 32 +#define NFPLUS_INPUT_ARBITER_VERSION_0_OFFSET 0x4 +#define NFPLUS_INPUT_ARBITER_VERSION_0_DEFAULT 0x1 +#define NFPLUS_INPUT_ARBITER_VERSION_0_WIDTH 32 +#define NFPLUS_INPUT_ARBITER_RESET_0_OFFSET 0x8 +#define NFPLUS_INPUT_ARBITER_RESET_0_DEFAULT 0x0 +#define NFPLUS_INPUT_ARBITER_RESET_0_WIDTH 16 +#define NFPLUS_INPUT_ARBITER_FLIP_0_OFFSET 0xC +#define NFPLUS_INPUT_ARBITER_FLIP_0_DEFAULT 0x0 +#define NFPLUS_INPUT_ARBITER_FLIP_0_WIDTH 32 +#define NFPLUS_INPUT_ARBITER_DEBUG_0_OFFSET 0x10 +#define NFPLUS_INPUT_ARBITER_DEBUG_0_DEFAULT 0x0 +#define NFPLUS_INPUT_ARBITER_DEBUG_0_WIDTH 32 +#define NFPLUS_INPUT_ARBITER_PKTIN_0_OFFSET 0x14 +#define NFPLUS_INPUT_ARBITER_PKTIN_0_DEFAULT 0x0 +#define NFPLUS_INPUT_ARBITER_PKTIN_0_WIDTH 32 +#define NFPLUS_INPUT_ARBITER_PKTOUT_0_OFFSET 0x18 +#define NFPLUS_INPUT_ARBITER_PKTOUT_0_DEFAULT 0x0 +#define NFPLUS_INPUT_ARBITER_PKTOUT_0_WIDTH 32 diff --git a/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.tcl b/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.tcl new file mode 100644 index 0000000..a8b9a2b --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.tcl @@ -0,0 +1,56 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# +# File: +# input_arbiter_regs_defines.tcl +# +# Description: +# This file is automatically generated with tcl defines for the software +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +set INPUT_ARBITER_REGS_ID_0_OFFSET 0x0 +set INPUT_ARBITER_REGS_ID_0_DEFAULT 0x0000DA01 +set INPUT_ARBITER_REGS_ID_0_WIDTH 32 +set INPUT_ARBITER_REGS_VERSION_0_OFFSET 0x4 +set INPUT_ARBITER_REGS_VERSION_0_DEFAULT 0x1 +set INPUT_ARBITER_REGS_VERSION_0_WIDTH 32 +set INPUT_ARBITER_REGS_RESET_0_OFFSET 0x8 +set INPUT_ARBITER_REGS_RESET_0_DEFAULT 0x0 +set INPUT_ARBITER_REGS_RESET_0_WIDTH 16 +set INPUT_ARBITER_REGS_FLIP_0_OFFSET 0xC +set INPUT_ARBITER_REGS_FLIP_0_DEFAULT 0x0 +set INPUT_ARBITER_REGS_FLIP_0_WIDTH 32 +set INPUT_ARBITER_REGS_DEBUG_0_OFFSET 0x10 +set INPUT_ARBITER_REGS_DEBUG_0_DEFAULT 0x0 +set INPUT_ARBITER_REGS_DEBUG_0_WIDTH 32 +set INPUT_ARBITER_REGS_PKTIN_0_OFFSET 0x14 +set INPUT_ARBITER_REGS_PKTIN_0_DEFAULT 0x0 +set INPUT_ARBITER_REGS_PKTIN_0_WIDTH 32 +set INPUT_ARBITER_REGS_PKTOUT_0_OFFSET 0x18 +set INPUT_ARBITER_REGS_PKTOUT_0_DEFAULT 0x0 +set INPUT_ARBITER_REGS_PKTOUT_0_WIDTH 32 diff --git a/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt b/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt new file mode 100644 index 0000000..224df27 --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt @@ -0,0 +1,56 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// input_arbiter_regs_defines.txt +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +#define NFPLUS INPUT_ARBITER ID OFFSET 0x0 +#define NFPLUS INPUT_ARBITER ID DEFAULT 0x0000DA01 +#define NFPLUS INPUT_ARBITER ID WIDTH 32 +#define NFPLUS INPUT_ARBITER VERSION OFFSET 0x4 +#define NFPLUS INPUT_ARBITER VERSION DEFAULT 0x1 +#define NFPLUS INPUT_ARBITER VERSION WIDTH 32 +#define NFPLUS INPUT_ARBITER RESET OFFSET 0x8 +#define NFPLUS INPUT_ARBITER RESET DEFAULT 0x0 +#define NFPLUS INPUT_ARBITER RESET WIDTH 16 +#define NFPLUS INPUT_ARBITER FLIP OFFSET 0xC +#define NFPLUS INPUT_ARBITER FLIP DEFAULT 0x0 +#define NFPLUS INPUT_ARBITER FLIP WIDTH 32 +#define NFPLUS INPUT_ARBITER DEBUG OFFSET 0x10 +#define NFPLUS INPUT_ARBITER DEBUG DEFAULT 0x0 +#define NFPLUS INPUT_ARBITER DEBUG WIDTH 32 +#define NFPLUS INPUT_ARBITER PKTIN OFFSET 0x14 +#define NFPLUS INPUT_ARBITER PKTIN DEFAULT 0x0 +#define NFPLUS INPUT_ARBITER PKTIN WIDTH 32 +#define NFPLUS INPUT_ARBITER PKTOUT OFFSET 0x18 +#define NFPLUS INPUT_ARBITER PKTOUT DEFAULT 0x0 +#define NFPLUS INPUT_ARBITER PKTOUT WIDTH 32 diff --git a/hw/lib/std/input_arbiter_v1_0_0/data/module_generation_Input_arbiter.xlsm b/hw/lib/std/input_arbiter_v1_0_0/data/module_generation_Input_arbiter.xlsm new file mode 100644 index 0000000000000000000000000000000000000000..ad82ce2a957280771c538de4bc6de4cb578d37a0 GIT binary patch literal 39747 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 literal 0 HcmV?d00001 diff --git a/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter.v b/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter.v new file mode 100644 index 0000000..bc979ba --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter.v @@ -0,0 +1,385 @@ +//- +// Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +// Junior University +// Copyright (C) 2010, 2011 Adam Covington +// Copyright (C) 2015 Noa Zilberman +// Copyright (C) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +/******************************************************************************* + * File: + * input_arbiter.v + * + * Library: + * hw/std/cores/input_arbiter + * + * Module: + * input_arbiter + * + * Author: + * Adam Covington + * Modified by Noa Zilberman + * + * Description: + * Round Robin arbiter (N inputs to 1 output) + * Inputs have a parameterizable width + * + */ + +`timescale 1ns/1ns +`include "input_arbiter_cpu_regs_defines.v" + +module input_arbiter +#( + // Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH=512, + parameter C_S_AXIS_DATA_WIDTH=512, + parameter C_M_AXIS_TUSER_WIDTH=128, + parameter C_S_AXIS_TUSER_WIDTH=128, + parameter NUM_QUEUES=3, + + // AXI Registers Data Width + parameter C_S_AXI_DATA_WIDTH = 32, + parameter C_S_AXI_ADDR_WIDTH = 12, + parameter C_BASEADDR = 32'h00000000 + +) +( + // Part 1: System side signals + // Global Ports + input axis_aclk, + input axis_resetn, + + // Master Stream Ports (interface to data path) + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_tuser, + output m_axis_tvalid, + input m_axis_tready, + output m_axis_tlast, + + // Slave Stream Ports (interface to RX queues) + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_0_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_0_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_0_tuser, + input s_axis_0_tvalid, + output s_axis_0_tready, + input s_axis_0_tlast, + + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_1_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_1_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_1_tuser, + input s_axis_1_tvalid, + output s_axis_1_tready, + input s_axis_1_tlast, + + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_2_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_2_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_2_tuser, + input s_axis_2_tvalid, + output s_axis_2_tready, + input s_axis_2_tlast, + + // Slave AXI Ports + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 :0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY + +); + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 NUM_QUEUES-1) ? extended_next_queue - NUM_QUEUES : extended_next_queue; + + assign m_axis_tuser = fifo_out_tuser[cur_queue]; + assign m_axis_tdata = fifo_out_tdata[cur_queue]; + assign m_axis_tlast = fifo_out_tlast[cur_queue]; + assign m_axis_tkeep = fifo_out_tkeep[cur_queue]; + assign m_axis_tvalid = ~empty[cur_queue]; + + + always @(*) begin + state_next = state; + cur_queue_next = cur_queue; + rd_en = 0; + + case(state) + + /* cycle between input queues until one is not empty */ + IDLE: begin + if(!empty[cur_queue]) begin + if(m_axis_tready && m_axis_tlast) begin + state_next = IDLE; + rd_en[cur_queue] = 1; + cur_queue_next = next_queue; + end + else if(m_axis_tready) begin + state_next = WR_PKT; + rd_en[cur_queue] = 1; + end + end + else begin + cur_queue_next = next_queue; + end + end + + /* wait until eop */ + WR_PKT: begin + /* if this is the last word then write it and get out */ + if(m_axis_tready & m_axis_tlast) begin + state_next = IDLE; + rd_en[cur_queue] = 1; + cur_queue_next = next_queue; //next non-empty queue + end + /* otherwise read and write as usual */ + else if (m_axis_tready & !empty[cur_queue]) begin + rd_en[cur_queue] = 1; + end + end // case: WR_PKT + + endcase // case(state) + end // always @ (*) + + always @(posedge axis_aclk) begin + if(~axis_resetn) begin + state <= IDLE; + cur_queue <= 0; + end + else begin + state <= state_next; + cur_queue <= cur_queue_next; + end + end + + + //Registers section + input_arbiter_cpu_regs + #( + .C_S_AXI_DATA_WIDTH (C_S_AXI_DATA_WIDTH), + .C_S_AXI_ADDR_WIDTH (C_S_AXI_ADDR_WIDTH), + .C_BASE_ADDRESS (C_BASEADDR) + ) arbiter_cpu_regs_inst + ( + // General ports + .clk (axis_aclk), + .resetn (axis_resetn), + // AXI Lite ports + .S_AXI_ACLK (S_AXI_ACLK), + .S_AXI_ARESETN (S_AXI_ARESETN), + .S_AXI_AWADDR (S_AXI_AWADDR), + .S_AXI_AWVALID (S_AXI_AWVALID), + .S_AXI_WDATA (S_AXI_WDATA), + .S_AXI_WSTRB (S_AXI_WSTRB), + .S_AXI_WVALID (S_AXI_WVALID), + .S_AXI_BREADY (S_AXI_BREADY), + .S_AXI_ARADDR (S_AXI_ARADDR), + .S_AXI_ARVALID (S_AXI_ARVALID), + .S_AXI_RREADY (S_AXI_RREADY), + .S_AXI_ARREADY (S_AXI_ARREADY), + .S_AXI_RDATA (S_AXI_RDATA), + .S_AXI_RRESP (S_AXI_RRESP), + .S_AXI_RVALID (S_AXI_RVALID), + .S_AXI_WREADY (S_AXI_WREADY), + .S_AXI_BRESP (S_AXI_BRESP), + .S_AXI_BVALID (S_AXI_BVALID), + .S_AXI_AWREADY (S_AXI_AWREADY), + + // Register ports + .id_reg (id_reg), + .version_reg (version_reg), + .reset_reg (reset_reg), + .ip2cpu_flip_reg (ip2cpu_flip_reg), + .cpu2ip_flip_reg (cpu2ip_flip_reg), + .pktin_reg (pktin_reg), + .pktin_reg_clear (pktin_reg_clear), + .pktout_reg (pktout_reg), + .pktout_reg_clear (pktout_reg_clear), + .ip2cpu_debug_reg (ip2cpu_debug_reg), + .cpu2ip_debug_reg (cpu2ip_debug_reg), + // Global Registers - user can select if to use + .cpu_resetn_soft(),//software reset, after cpu module + .resetn_soft (),//software reset to cpu module (from central reset management) + .resetn_sync (resetn_sync)//synchronized reset, use for better timing + ); + + assign clear_counters = reset_reg[0]; + assign reset_registers = reset_reg[4]; + + always @(posedge axis_aclk) + if (~resetn_sync | reset_registers) begin + id_reg <= #1 `REG_ID_DEFAULT; + version_reg <= #1 `REG_VERSION_DEFAULT; + ip2cpu_flip_reg <= #1 `REG_FLIP_DEFAULT; + pktin_reg <= #1 `REG_PKTIN_DEFAULT; + pktout_reg <= #1 `REG_PKTOUT_DEFAULT; + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT; + end + else begin + id_reg <= #1 `REG_ID_DEFAULT; + version_reg <= #1 `REG_VERSION_DEFAULT; + ip2cpu_flip_reg <= #1 ~cpu2ip_flip_reg; + pktin_reg[`REG_PKTIN_WIDTH -2: 0] <= #1 clear_counters | pktin_reg_clear ? 'h0 : pktin_reg[`REG_PKTIN_WIDTH-2:0] + (s_axis_0_tlast && s_axis_0_tvalid && s_axis_0_tready ) + (s_axis_1_tlast && s_axis_1_tvalid && s_axis_1_tready) + (s_axis_2_tlast && s_axis_2_tvalid && s_axis_2_tready); + pktin_reg[`REG_PKTIN_WIDTH-1] <= #1 clear_counters | pktin_reg_clear ? 1'h0 : pktin_reg_clear ? 'h0 : pktin_reg[`REG_PKTIN_WIDTH-2:0] + pktin_reg[`REG_PKTIN_WIDTH-2:0] + (s_axis_0_tlast && s_axis_0_tvalid && s_axis_0_tready ) + (s_axis_1_tlast && s_axis_1_tvalid && s_axis_1_tready) + (s_axis_2_tlast && s_axis_2_tvalid && s_axis_2_tready) > {(`REG_PKTIN_WIDTH-1){1'b1}} ? 1'b1 : pktin_reg[`REG_PKTIN_WIDTH-1]; + + pktout_reg [`REG_PKTOUT_WIDTH-2:0]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tvalid && m_axis_tlast && m_axis_tready ) ; + pktout_reg [`REG_PKTOUT_WIDTH-1]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tvalid && m_axis_tlast && m_axis_tready) > {(`REG_PKTOUT_WIDTH-1){1'b1}} ? 1'b1 : pktout_reg [`REG_PKTOUT_WIDTH-1]; + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT+cpu2ip_debug_reg; + end + + + +endmodule diff --git a/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs.v b/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs.v new file mode 100644 index 0000000..e406063 --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs.v @@ -0,0 +1,440 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// input_arbiter_cpu_regs.v +// +// Module: +// input_arbiter_cpu_regs +// +// Description: +// This file is automatically generated with the registers towards the CPU/Software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ns/1ns +`include "input_arbiter_cpu_regs_defines.v" +module input_arbiter_cpu_regs # +( +parameter C_BASE_ADDRESS = 32'h00000000, +parameter C_S_AXI_DATA_WIDTH = 32, +parameter C_S_AXI_ADDR_WIDTH = 32 +) +( + // General ports + input clk, + input resetn, + // Global Registers + input cpu_resetn_soft, + output reg resetn_soft, + output reg resetn_sync, + + // Register ports + input [`REG_ID_BITS] id_reg, + input [`REG_VERSION_BITS] version_reg, + output reg [`REG_RESET_BITS] reset_reg, + input [`REG_FLIP_BITS] ip2cpu_flip_reg, + output reg [`REG_FLIP_BITS] cpu2ip_flip_reg, + input [`REG_DEBUG_BITS] ip2cpu_debug_reg, + output reg [`REG_DEBUG_BITS] cpu2ip_debug_reg, + input [`REG_PKTIN_BITS] pktin_reg, + output reg pktin_reg_clear, + input [`REG_PKTOUT_BITS] pktout_reg, + output reg pktout_reg_clear, + + // AXI Lite ports + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 :0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY + +); + + // AXI4LITE signals + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; + reg axi_awready; + reg axi_wready; + reg [1 : 0] axi_bresp; + reg axi_bvalid; + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; + reg axi_arready; + reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; + reg [1 : 0] axi_rresp; + reg axi_rvalid; + + reg resetn_sync_d; + wire reg_rden; + wire reg_wren; + reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; + integer byte_index; + reg pktin_reg_clear_d; + reg pktout_reg_clear_d; + + // I/O Connections assignments + assign S_AXI_AWREADY = axi_awready; + assign S_AXI_WREADY = axi_wready; + assign S_AXI_BRESP = axi_bresp; + assign S_AXI_BVALID = axi_bvalid; + assign S_AXI_ARREADY = axi_arready; + assign S_AXI_RDATA = axi_rdata; + assign S_AXI_RRESP = axi_rresp; + assign S_AXI_RVALID = axi_rvalid; + + + //Sample reset (not mandatory, but good practice) + always @ (posedge clk) begin + if (~resetn) begin + resetn_sync_d <= 1'b0; + resetn_sync <= 1'b0; + end + else begin + resetn_sync_d <= resetn; + resetn_sync <= resetn_sync_d; + end + end + + + //global registers, sampling + always @(posedge clk) resetn_soft <= #1 cpu_resetn_soft; + + // Implement axi_awready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awready <= 1'b0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // slave is ready to accept write address when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_awready <= 1'b1; + end + else + begin + axi_awready <= 1'b0; + end + end + end + + // Implement axi_awaddr latching + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awaddr <= 0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // Write Address latching + axi_awaddr <= S_AXI_AWADDR ^ C_BASE_ADDRESS; + end + end + end + + // Implement axi_wready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_wready <= 1'b0; + end + else + begin + if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID) + begin + // slave is ready to accept write data when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_wready <= 1'b1; + end + else + begin + axi_wready <= 1'b0; + end + end + end + + // Implement write response logic generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_bvalid <= 0; + axi_bresp <= 2'b0; + end + else + begin + if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) + begin + // indicates a valid write response is available + axi_bvalid <= 1'b1; + axi_bresp <= 2'b0; // OKAY response + end // work error responses in future + else + begin + if (S_AXI_BREADY && axi_bvalid) + //check if bready is asserted while bvalid is high) + //(there is a possibility that bready is always asserted high) + begin + axi_bvalid <= 1'b0; + end + end + end + end + + // Implement axi_arready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_arready <= 1'b0; + axi_araddr <= 32'b0; + end + else + begin + if (~axi_arready && S_AXI_ARVALID) + begin + // indicates that the slave has acceped the valid read address + // Read address latching + axi_arready <= 1'b1; + axi_araddr <= S_AXI_ARADDR ^ C_BASE_ADDRESS; + end + else + begin + axi_arready <= 1'b0; + end + end + end + + + // Implement axi_rvalid generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rvalid <= 0; + axi_rresp <= 0; + end + else + begin + if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) + begin + // Valid read data is available at the read data bus + axi_rvalid <= 1'b1; + axi_rresp <= 2'b0; // OKAY response + end + else if (axi_rvalid && S_AXI_RREADY) + begin + // Read data is accepted by the master + axi_rvalid <= 1'b0; + end + end + end + + + // Implement memory mapped register select and write logic generation + + assign reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; + +////////////////////////////////////////////////////////////// +// write registers +////////////////////////////////////////////////////////////// + + +//Write only register, clear on write (i.e. event) + always @(posedge clk) begin + if (!resetn_sync) begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + else begin + if (reg_wren) begin + case (axi_awaddr) + //Reset Register + `REG_RESET_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_RESET_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + reset_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; + end + end + endcase + end + else begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + end + end + +//R/W register, not cleared + always @(posedge clk) begin + if (!resetn_sync) begin + + cpu2ip_flip_reg <= #1 `REG_FLIP_DEFAULT; + cpu2ip_debug_reg <= #1 `REG_DEBUG_DEFAULT; + end + else begin + if (reg_wren) //write event + case (axi_awaddr) + //Flip Register + `REG_FLIP_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_FLIP_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_flip_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + //Debug Register + `REG_DEBUG_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_DEBUG_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_debug_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + default: begin + end + + endcase + end + end + + + +///////////////////////// +//// end of write +///////////////////////// + + // Implement memory mapped register select and read logic generation + // Slave register read enable is asserted when valid address is available + // and the slave is ready to accept the read address. + + // reg_rden control logic + // temperary no extra logic here + assign reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; + + always @(*) + begin + + case ( axi_araddr /*S_AXI_ARADDR ^ C_BASE_ADDRESS*/) + //Id Register + `REG_ID_ADDR : begin + reg_data_out [`REG_ID_BITS] = id_reg; + end + //Version Register + `REG_VERSION_ADDR : begin + reg_data_out [`REG_VERSION_BITS] = version_reg; + end + //Flip Register + `REG_FLIP_ADDR : begin + reg_data_out [`REG_FLIP_BITS] = ip2cpu_flip_reg; + end + //Debug Register + `REG_DEBUG_ADDR : begin + reg_data_out [`REG_DEBUG_BITS] = ip2cpu_debug_reg; + end + //Pktin Register + `REG_PKTIN_ADDR : begin + reg_data_out [`REG_PKTIN_BITS] = pktin_reg; + end + //Pktout Register + `REG_PKTOUT_ADDR : begin + reg_data_out [`REG_PKTOUT_BITS] = pktout_reg; + end + //Default return value + default: begin + reg_data_out [31:0] = 32'hDEADBEEF; + end + + endcase + + + end//end of assigning data to IP2Bus_Data bus + + //Read only registers, not cleared + //Nothing to do here.... + +//Read only registers, cleared on read (e.g. counters) + always @(posedge clk) + if (!resetn_sync) begin + pktin_reg_clear <= #1 1'b0; + pktin_reg_clear_d <= #1 1'b0; + pktout_reg_clear <= #1 1'b0; + pktout_reg_clear_d <= #1 1'b0; + end + else begin + pktin_reg_clear <= #1 pktin_reg_clear_d; + pktin_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTIN_ADDR)) ? 1'b1 : 1'b0; + pktout_reg_clear <= #1 pktout_reg_clear_d; + pktout_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTOUT_ADDR)) ? 1'b1 : 1'b0; + end + + +// Output register or memory read data + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rdata <= 0; + end + else + begin + // When there is a valid read address (S_AXI_ARVALID) with + // acceptance of read address by the slave (axi_arready), + // output the read dada + if (reg_rden) + begin + axi_rdata <= reg_data_out/*ip2bus_data*/; // register read data /* some new changes here */ + end + end + end +endmodule diff --git a/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs_defines.v b/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs_defines.v new file mode 100644 index 0000000..7ceb8a6 --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/hdl/input_arbiter_cpu_regs_defines.v @@ -0,0 +1,72 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// input_arbiter_cpu_regs_defines.v +// +// Module: +// input_arbiter_cpu_regs_defines +// +// Description: +// This file is automatically generated with the registers defintions towards the CPU/Software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + `define REG_ID_BITS 31:0 + `define REG_ID_WIDTH 32 + `define REG_ID_DEFAULT 32'h0000DA01 + `define REG_ID_ADDR 32'h0 + + `define REG_VERSION_BITS 31:0 + `define REG_VERSION_WIDTH 32 + `define REG_VERSION_DEFAULT 32'h1 + `define REG_VERSION_ADDR 32'h4 + + `define REG_RESET_BITS 15:0 + `define REG_RESET_WIDTH 16 + `define REG_RESET_DEFAULT 16'h0 + `define REG_RESET_ADDR 32'h8 + + `define REG_FLIP_BITS 31:0 + `define REG_FLIP_WIDTH 32 + `define REG_FLIP_DEFAULT 32'h0 + `define REG_FLIP_ADDR 32'hC + + `define REG_DEBUG_BITS 31:0 + `define REG_DEBUG_WIDTH 32 + `define REG_DEBUG_DEFAULT 32'h0 + `define REG_DEBUG_ADDR 32'h10 + + `define REG_PKTIN_BITS 31:0 + `define REG_PKTIN_WIDTH 32 + `define REG_PKTIN_DEFAULT 32'h0 + `define REG_PKTIN_ADDR 32'h14 + + `define REG_PKTOUT_BITS 31:0 + `define REG_PKTOUT_WIDTH 32 + `define REG_PKTOUT_DEFAULT 32'h0 + `define REG_PKTOUT_ADDR 32'h18 diff --git a/hw/lib/std/input_arbiter_v1_0_0/input_arbiter.tcl b/hw/lib/std/input_arbiter_v1_0_0/input_arbiter.tcl new file mode 100644 index 0000000..70a6f12 --- /dev/null +++ b/hw/lib/std/input_arbiter_v1_0_0/input_arbiter.tcl @@ -0,0 +1,133 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design input_arbiter +set top input_arbiter +set device $::env(DEVICE) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +puts "Creating Input Arbiter IP" +##################################### +# Project Structure & IP Build +##################################### +read_verilog "./hdl/input_arbiter_cpu_regs_defines.v" +read_verilog "./hdl/input_arbiter_cpu_regs.v" +read_verilog "./hdl/input_arbiter.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +update_ip_catalog -rebuild +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] +ipx::infer_user_parameters [ipx::current_core] + +ipx::add_user_parameter {C_M_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property display_name {C_M_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property display_name {C_S_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property display_name {C_M_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property display_name {C_S_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {NUM_QUEUES} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters NUM_QUEUES] +set_property display_name {NUM_QUEUES} [ipx::get_user_parameters NUM_QUEUES] +set_property value {3} [ipx::get_user_parameters NUM_QUEUES] +set_property value_format {long} [ipx::get_user_parameters NUM_QUEUES] + +ipx::add_user_parameter {C_S_AXI_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property display_name {C_S_AXI_DATA_WIDTH} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXI_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property display_name {C_S_AXI_ADDR_WIDTH} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] + +ipx::add_user_parameter {C_BASEADDR} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_BASEADDR] +set_property display_name {C_BASEADDR} [ipx::get_user_parameters C_BASEADDR] +set_property value {0x00000000} [ipx::get_user_parameters C_BASEADDR] +set_property value_format {bitstring} [ipx::get_user_parameters C_BASEADDR] + +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis_0 -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis_1 -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis_2 -of_objects [ipx::current_core]] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + diff --git a/hw/lib/std/nf_axis_converter_v1_0_0/Makefile b/hw/lib/std/nf_axis_converter_v1_0_0/Makefile new file mode 100644 index 0000000..181e492 --- /dev/null +++ b/hw/lib/std/nf_axis_converter_v1_0_0/Makefile @@ -0,0 +1,32 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source nf_axis_converter.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter.v b/hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter.v new file mode 100644 index 0000000..f504c00 --- /dev/null +++ b/hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter.v @@ -0,0 +1,159 @@ +//- +// Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +// Junior University +// Copyright (C) 2018 Noa Zilberman +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +/******************************************************************************* + * + * File: + * nf_axis_converter.v + * + * Module: + * nf_axis_converter + * + * Author: + * Stephen Ibanez + * + * Description: + * Convert AXI4-Streams to different data width + * Add LEN subchannel. + * NOTE: This is just a wrapper module to add a pipeline stage after the + * main conversion logic to help with timing. + * + */ + +//Need to add support for err bit (1 bit tuser) +module nf_axis_converter +#( + // Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH=512, + parameter C_S_AXIS_DATA_WIDTH=512, + + parameter C_M_AXIS_TUSER_WIDTH=128, + parameter C_S_AXIS_TUSER_WIDTH=128, + + parameter C_LEN_WIDTH=16, + parameter C_SPT_WIDTH=8, + parameter C_DPT_WIDTH=8, + + parameter C_DEFAULT_VALUE_ENABLE=0, + parameter C_DEFAULT_SRC_PORT=0, + parameter C_DEFAULT_DST_PORT=0 +) +( + // Part 1: System side signals + // Global Ports + input axi_aclk, + input axi_resetn, + + input [7:0] interface_number, + input interface_number_en, + + // Master Stream Ports + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_tuser, + output m_axis_tvalid, + input m_axis_tready, + output m_axis_tlast, + + // Slave Stream Ports + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser, + input s_axis_tvalid, + output s_axis_tready, + input s_axis_tlast +); + + wire [C_M_AXIS_DATA_WIDTH-1:0] m_axis_nfconv_tdata; + wire [(C_M_AXIS_DATA_WIDTH/8)-1:0] m_axis_nfconv_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_nfconv_tuser; + wire m_axis_nfconv_tvalid; + wire m_axis_nfconv_tready; + wire m_axis_nfconv_tlast; + + nf_axis_converter_main + #( + .C_M_AXIS_DATA_WIDTH (C_M_AXIS_DATA_WIDTH), + .C_S_AXIS_DATA_WIDTH (C_S_AXIS_DATA_WIDTH), + .C_M_AXIS_TUSER_WIDTH (C_M_AXIS_TUSER_WIDTH), + .C_S_AXIS_TUSER_WIDTH (C_S_AXIS_TUSER_WIDTH), + .C_LEN_WIDTH (C_LEN_WIDTH), + .C_SPT_WIDTH (C_SPT_WIDTH), + .C_DPT_WIDTH (C_DPT_WIDTH), + .C_DEFAULT_VALUE_ENABLE (C_DEFAULT_VALUE_ENABLE), + .C_DEFAULT_SRC_PORT (C_DEFAULT_SRC_PORT), + .C_DEFAULT_DST_PORT (C_DEFAULT_DST_PORT) + ) nf_converter ( + .axi_aclk (axi_aclk), + .axi_resetn (axi_resetn), + .interface_number (interface_number), + .interface_number_en (interface_number_en), + // Slave Ports + .s_axis_tdata (s_axis_tdata), + .s_axis_tkeep (s_axis_tkeep), + .s_axis_tvalid (s_axis_tvalid), + .s_axis_tready (s_axis_tready), + .s_axis_tlast (s_axis_tlast), + .s_axis_tuser (s_axis_tuser), + // Master Ports + .m_axis_tdata (m_axis_nfconv_tdata), + .m_axis_tkeep (m_axis_nfconv_tkeep), + .m_axis_tvalid (m_axis_nfconv_tvalid), + .m_axis_tready (m_axis_nfconv_tready), + .m_axis_tlast (m_axis_nfconv_tlast), + .m_axis_tuser (m_axis_nfconv_tuser) + ); + + /* Output FIFO for nf_axis_converter to help with timing */ + axis_fifo + #( + .C_AXIS_DATA_WIDTH (C_M_AXIS_DATA_WIDTH), + .C_AXIS_TUSER_WIDTH (C_M_AXIS_TUSER_WIDTH) + ) + axis_fifo_inst + ( + .axis_aclk (axi_aclk), + .axis_resetn (axi_resetn), + // master ports + .m_axis_tdata (m_axis_tdata), + .m_axis_tkeep (m_axis_tkeep), + .m_axis_tuser (m_axis_tuser), + .m_axis_tvalid (m_axis_tvalid), + .m_axis_tready (m_axis_tready), + .m_axis_tlast (m_axis_tlast), + // slave ports + .s_axis_tdata (m_axis_nfconv_tdata), + .s_axis_tkeep (m_axis_nfconv_tkeep), + .s_axis_tuser (m_axis_nfconv_tuser), + .s_axis_tvalid (m_axis_nfconv_tvalid), + .s_axis_tready (m_axis_nfconv_tready), + .s_axis_tlast (m_axis_nfconv_tlast) + ); + +endmodule diff --git a/hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter_main.v b/hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter_main.v new file mode 100644 index 0000000..81cc471 --- /dev/null +++ b/hw/lib/std/nf_axis_converter_v1_0_0/hdl/nf_axis_converter_main.v @@ -0,0 +1,681 @@ +//- +// Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +// Junior University +// Copyright (C) 2010, 2011 James Hongyi Zeng +// Copyright (C) 2015 Noa Zilberman +// Copyright (C) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +/******************************************************************************* + * + * File: + * nf_axis_converter.v + * + * Module: + * nf_axis_converter + * + * Author: + * James Hongyi Zeng + * modified by Noa Zilberman + * modified by Stephen Ibanez + * modified by Chris Neely + * + * Description: + * Convert AXI4-Streams to different data width + * Add LEN subchannel + * + */ + +//Need to add support for err bit (1 bit tuser) +module nf_axis_converter_main +#( + // Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH=512, + parameter C_S_AXIS_DATA_WIDTH=512, + + parameter C_M_AXIS_TUSER_WIDTH=128, + parameter C_S_AXIS_TUSER_WIDTH=128, + + parameter C_LEN_WIDTH=16, + parameter C_SPT_WIDTH=8, + parameter C_DPT_WIDTH=8, + + parameter C_DEFAULT_VALUE_ENABLE=0, + parameter C_DEFAULT_SRC_PORT=0, + parameter C_DEFAULT_DST_PORT=0 +) +( + // Part 1: System side signals + // Global Ports + input axi_aclk, + input axi_resetn, + + input [7:0] interface_number, + input interface_number_en, + + // Master Stream Ports + output reg [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_tdata, + output reg [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_tuser, + output reg m_axis_tvalid, + input m_axis_tready, + output reg m_axis_tlast, + + // Slave Stream Ports + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser, + input s_axis_tvalid, + output reg s_axis_tready, + input s_axis_tlast +); + + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 C_S_AXIS_DATA_WIDTH) begin: MASTER_WIDER + + reg [log2(M_S_RATIO_COUNT)-1:0] counter, counter_next; + wire [log2(M_S_RATIO_COUNT)-1:0] counter_plus_1 = counter + 1'b1; + + always @(*) begin + in_fifo_rd_en = 1'b0; + info_fifo_rd_en = 1'b0; + + m_axis_tdata = m_axis_tdata_prev; + m_axis_tkeep = m_axis_tkeep_prev; + m_axis_tlast = 1'b0; + + m_axis_tdata_prev_next = m_axis_tdata_prev; + m_axis_tkeep_prev_next = m_axis_tkeep_prev; + + counter_next = counter; + first_time_next = first_time; + m_axis_tvalid = 1'b0; + + for(j=0;j rx_queue 64b@axis_clk + input [511:0] m_axis_mac_tdata, + input [63:0] m_axis_mac_tkeep, + input m_axis_mac_tvalid, + input m_axis_mac_tuser_err, // valid frame + input [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_mac_tuser, + input m_axis_mac_tlast, + + // tx_queue 64b@axis_clk -> mac 64b@clk156 + output [511:0] s_axis_mac_tdata, + output [63:0] s_axis_mac_tkeep, + output s_axis_mac_tvalid, + output s_axis_mac_tuser_err, //underrun + output [C_M_AXIS_TUSER_WIDTH-1:0] s_axis_mac_tuser, + output s_axis_mac_tlast, + input s_axis_mac_tready, + + // TX/RX DATA channels + input [7:0] interface_number, + + // NFPLUS pipeline clk & rst + input axis_aclk, + input axis_aresetn, + + // input from ref pipeline 256b -> MAC + input [C_S_AXIS_DATA_WIDTH-1:0] s_axis_pipe_tdata, + input [(C_S_AXIS_DATA_WIDTH/8)-1:0] s_axis_pipe_tkeep, + input s_axis_pipe_tlast, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_pipe_tuser, + input s_axis_pipe_tvalid, + output s_axis_pipe_tready, + + // output to ref pipeline 256b -> DMA + output [C_M_AXIS_DATA_WIDTH-1:0] m_axis_pipe_tdata, + output [(C_M_AXIS_DATA_WIDTH/8)-1:0] m_axis_pipe_tkeep, + output m_axis_pipe_tlast, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_pipe_tuser, + output m_axis_pipe_tvalid, + input m_axis_pipe_tready, + + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 :0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY + + ); + + + ///////////////////////////////////////////////////////////////////// + // localparam + ///////////////////////////////////////////////////////////////////// + localparam C_M_AXIS_DATA_WIDTH_INTERNAL = 512; + localparam C_S_AXIS_DATA_WIDTH_INTERNAL = 512; + + localparam NUM_RW_REGS = 1; + localparam NUM_RO_REGS = 17; + + // localparam for now, should be params + localparam C_USE_WSTRB = 0; + + ///////////////////////////////////////////////////////////////////// + // signals + ///////////////////////////////////////////////////////////////////// + + // rx_queue -> AXIS_converter + wire [C_M_AXIS_DATA_WIDTH_INTERNAL-1:0] m_axis_fifo_tdata; + wire [(C_M_AXIS_DATA_WIDTH_INTERNAL/8)-1:0] m_axis_fifo_tkeep; + wire [C_S_AXIS_TUSER_WIDTH-1:0] m_axis_fifo_tuser; + wire m_axis_fifo_tvalid; + wire m_axis_fifo_tready; + wire m_axis_fifo_tlast; + + // AXIS_converter 64b@axis_clk -> tx_queue@axis_clk + wire [C_S_AXIS_DATA_WIDTH_INTERNAL-1:0] s_axis_fifo_tdata; + wire [(C_S_AXIS_DATA_WIDTH_INTERNAL/8)-1:0] s_axis_fifo_tkeep; + wire [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_fifo_tuser; + wire s_axis_fifo_tvalid; + wire s_axis_fifo_tready; + wire s_axis_fifo_tlast; + + //////////////////////////////////////////////////////////////// + // 10g interface statistics + // TODO: Send through AXI-Lite interface + //////////////////////////////////////////////////////////////// + wire interface_number_en; + // tx_queues + wire tx_dequeued_pkt; // + wire tx_pkts_enqueued_signal;// + wire [15:0] tx_bytes_enqueued;// + wire be; // + + ///////////////////////////////////////////////////////////////////////////// + /////////////// DATA WIDTH conversion logic ///////////////// + ///////////////////////////////////////////////////////////////////////////// + assign interface_number_en = (C_DEFAULT_VALUE_ENABLE) ? 1'b1 : 1'b0; + ///////////////////////////////////////////////////////////////////////////// + /////////////// RX SIDE MAC -> DMA: FIFO + AXIS_CONV ///////////////// + ///////////////////////////////////////////////////////////////////////////// + // Internal FIFO resets for clk domain crossing + wire areset_rx_fifo_extended; + wire areset_tx_fifo_extended; + + // FIFO36_72 primitive rst extension rx + data_sync_block #( + .C_NUM_SYNC_REGS (6) + ) rx_fifo_rst ( + .clk (axis_aclk), + .data_in (~axis_aresetn), + .data_out (areset_rx_fifo_extended) + ); + + // FIFO36_72 primitive rst extension tx + data_sync_block #( + .C_NUM_SYNC_REGS (6) + ) tx_fifo_rst ( + .clk (axis_aclk), + .data_in (~axis_aresetn), + .data_out (areset_tx_fifo_extended) + ); + + + //------------------------------------------------------------------------- + // RX queue: 64b@clk ->64b@axis_clk conversion. + // Creates a backpressure to the interface (axi ethernet block doesn't have tready signal). + // IMPORTANT: FIFO36_72 requires rst to be asserted for at least 5 clks. RDEN and WREN + // should be ONLY 1'b0 at that time. + //------------------------------------------------------------------------- + rx_queue #( + .AXI_DATA_WIDTH (C_M_AXIS_DATA_WIDTH_INTERNAL) + ) rx_fifo_intf ( + // MAC input 64b@clk156 + .clk156 (clk156), + .areset_clk156 (areset_clk156), + + .i_tdata (m_axis_mac_tdata), + .i_tkeep (m_axis_mac_tkeep), + .i_tuser_err (m_axis_mac_tuser_err), + .i_tuser (m_axis_mac_tuser), + .i_tvalid (m_axis_mac_tvalid), + .i_tlast (m_axis_mac_tlast), + + // FIFO output 64b@axi_aclk + .clk (axis_aclk), + .reset (areset_rx_fifo_extended), + + .o_tdata (m_axis_fifo_tdata), + .o_tkeep (m_axis_fifo_tkeep), + .o_tuser (m_axis_fifo_tuser), + .o_tvalid (m_axis_fifo_tvalid), + .o_tlast (m_axis_fifo_tlast), + .o_tready (m_axis_fifo_tready), + + // interface statistics + .fifo_wr_en (fifo_wr_en), + .rx_pkt_drop (rx_pkt_drop), + .rx_bad_frame (rx_bad_frame), + .rx_good_frame (rx_good_frame) + ); + + //-------------------------------------------------------------------------- + // 64b to 256b axis converter RX SIDE (rx_queue FIFO -> DMA): + // (AXIS mac_64b@axis_clk -> AXIS conv_256b@axis_clk with TUSER) + //-------------------------------------------------------------------------- + nf_axis_converter + #( + .C_M_AXIS_DATA_WIDTH (C_M_AXIS_DATA_WIDTH), + .C_S_AXIS_DATA_WIDTH (C_M_AXIS_DATA_WIDTH_INTERNAL), + .C_M_AXIS_TUSER_WIDTH (C_M_AXIS_TUSER_WIDTH), + .C_S_AXIS_TUSER_WIDTH (C_S_AXIS_TUSER_WIDTH), + + .C_DEFAULT_VALUE_ENABLE (C_DEFAULT_VALUE_ENABLE), // USE C_DEFAULT_VALUE_ENABLE = 1 + .C_DEFAULT_SRC_PORT (C_DEFAULT_SRC_PORT), + .C_DEFAULT_DST_PORT (C_DEFAULT_DST_PORT) + ) + converter_rx ( + .axi_aclk (axis_aclk), + .axi_resetn (~areset_rx_fifo_extended), + + .interface_number (interface_number), + .interface_number_en (interface_number_en), + + // Slave Ports (Input 64b from AXIS_FIFO) + .s_axis_tdata (m_axis_fifo_tdata), + .s_axis_tkeep (m_axis_fifo_tkeep), + .s_axis_tvalid (m_axis_fifo_tvalid), + .s_axis_tready (m_axis_fifo_tready), + .s_axis_tlast (m_axis_fifo_tlast), + .s_axis_tuser (m_axis_fifo_tuser), + + // Master Ports (Output 256b to outside) + .m_axis_tdata (m_axis_pipe_tdata), + .m_axis_tkeep (m_axis_pipe_tkeep), + .m_axis_tvalid (m_axis_pipe_tvalid), + .m_axis_tready (m_axis_pipe_tready), + .m_axis_tlast (m_axis_pipe_tlast), + .m_axis_tuser (m_axis_pipe_tuser) // sideband tuser 128b + ); + + ///////////////////////////////////////////////////////////////////////////// + /////////////// TX SIDE DMA -> MAC: AXIS_CONV + FIFO ///////////////// + ///////////////////////////////////////////////////////////////////////////// + + //-------------------------------------------------------------------------- + // 256b to 64b axis converter TX SIDE (Outside -> AXIS_CONV): + // (AXIS 256b@axi_aclk -> AXIS 64b@axis_aclk) + // C_DEFAULT_VALUE_ENABLE = 0 -- bypass tuser field logic + //-------------------------------------------------------------------------- + nf_axis_converter + #( + .C_M_AXIS_DATA_WIDTH (C_S_AXIS_DATA_WIDTH_INTERNAL), + .C_S_AXIS_DATA_WIDTH (C_S_AXIS_DATA_WIDTH), + .C_DEFAULT_VALUE_ENABLE (1'b0) + ) + converter_tx ( + .axi_aclk (axis_aclk), + .axi_resetn (~areset_tx_fifo_extended), + + .interface_number (interface_number), + .interface_number_en (interface_number_en), + + // Slave Ports (Input 256b from DMA) + .s_axis_tdata (s_axis_pipe_tdata), + .s_axis_tkeep (s_axis_pipe_tkeep), + .s_axis_tvalid (s_axis_pipe_tvalid), + .s_axis_tready (s_axis_pipe_tready), + .s_axis_tlast (s_axis_pipe_tlast), + .s_axis_tuser (s_axis_pipe_tuser), + + // Master Ports (Output 64b to AXIS_FIFO) + .m_axis_tdata (s_axis_fifo_tdata), + .m_axis_tkeep (s_axis_fifo_tkeep), + .m_axis_tvalid (s_axis_fifo_tvalid), + .m_axis_tready (s_axis_fifo_tready), + .m_axis_tlast (s_axis_fifo_tlast), + .m_axis_tuser (s_axis_fifo_tuser) + ); + + //------------------------------------------------------------------------- + // TX queue: 64b@axis_clk -> 64b@clk conversion. + // TODO : add FSM from the original block for AXI-Lite interfaces + // IMPORTANT: FIFO36_72 requires rst to be asserted for at least 5 clks. + // RDEN and WREN should be ONLY 1'b0 at that time. + //------------------------------------------------------------------------- + tx_queue #( + .AXI_DATA_WIDTH (C_S_AXIS_DATA_WIDTH_INTERNAL), + .C_S_AXIS_TUSER_WIDTH (C_S_AXIS_TUSER_WIDTH) + ) tx_fifo_intf ( + // AXIS input 64b @axis_clk + .clk (axis_aclk), + .reset (areset_tx_fifo_extended), + + .i_tuser (s_axis_fifo_tuser), + .i_tdata (s_axis_fifo_tdata), + .i_tkeep (s_axis_fifo_tkeep), + .i_tvalid (s_axis_fifo_tvalid), + .i_tlast (s_axis_fifo_tlast), + .i_tready (s_axis_fifo_tready), + + // AXIS MAC output 64b @156MHz + .clk156 (clk156), + .areset_clk156 (areset_clk156), + + .o_tdata (s_axis_mac_tdata), + .o_tkeep (s_axis_mac_tkeep), + .o_tvalid (s_axis_mac_tvalid), + .o_tlast (s_axis_mac_tlast), + .o_tuser_err (s_axis_mac_tuser_err), + .o_tuser (s_axis_mac_tuser), + .o_tready (s_axis_mac_tready), + + // sideband data + .tx_dequeued_pkt (tx_dequeued_pkt), + .be (be), + .tx_pkts_enqueued_signal (tx_pkts_enqueued_signal), + .tx_bytes_enqueued (tx_bytes_enqueued) + ); + + //------------------------------------------------------------------------- + // AXI-Lite registers + // TODO : AXI-lite slave interface (not ipif) + //------------------------------------------------------------------------- + reg [`REG_ID_BITS] id_reg; + reg [`REG_VERSION_BITS] version_reg; + wire [`REG_RESET_BITS] reset_reg; + wire [`REG_RESET_BITS] mac_reset_reg; + reg [`REG_FLIP_BITS] ip2cpu_flip_reg; + wire [`REG_FLIP_BITS] cpu2ip_flip_reg; + reg [`REG_DEBUG_BITS] ip2cpu_debug_reg; + wire [`REG_DEBUG_BITS] cpu2ip_debug_reg; + reg [`REG_RXMACPKT_BITS] rx_mac_pktin_reg, rx_queue_pktin_reg, rx_conv_pktin_reg; + reg [`REG_TXMACPKT_BITS] tx_mac_pktin_reg, tx_queue_pktin_reg, tx_conv_pktin_reg; + wire rx_mac_pktin_reg_clear, rx_queue_pktin_reg_clear, rx_conv_pktin_reg_clear; + wire tx_mac_pktin_reg_clear, tx_queue_pktin_reg_clear, tx_conv_pktin_reg_clear; + + wire resetn_soft, resetn_sync, mac_resetn_sync, cpu_resetn_soft; + wire clear_counters; + wire reset_registers; + wire reset_tables; + wire mac_clear_counters; + wire mac_reset_registers; + wire mac_reset_tables; + nf_mac_attachment_cpu_regs #( + .C_BASE_ADDRESS (C_BASEADDR), + .C_S_AXI_DATA_WIDTH (C_S_AXI_DATA_WIDTH), + .C_S_AXI_ADDR_WIDTH (C_S_AXI_ADDR_WIDTH) + ) u_nf_mac_attachment_cpu_reg ( + // General ports + .mac_clk (clk156), + .mac_resetn (!areset_clk156), + .clk (axis_aclk), + .resetn (axis_aresetn), + // Global Registers + .cpu_resetn_soft (cpu_resetn_soft ), + .resetn_soft (resetn_soft ), + .resetn_sync (resetn_sync ), + .mac_resetn_sync (mac_resetn_sync ), + // Register ports + .id_reg (id_reg), + .version_reg (version_reg), + .reset_reg (reset_reg), + .mac_reset_reg (mac_reset_reg), + .ip2cpu_flip_reg (ip2cpu_flip_reg ), + .cpu2ip_flip_reg (cpu2ip_flip_reg ), + .ip2cpu_debug_reg(ip2cpu_debug_reg), + .cpu2ip_debug_reg(cpu2ip_debug_reg), + .rx_mac_pktin_reg (rx_mac_pktin_reg ), + .rx_mac_pktin_reg_clear (rx_mac_pktin_reg_clear ), + .rx_queue_pktin_reg (rx_queue_pktin_reg ), + .rx_queue_pktin_reg_clear (rx_queue_pktin_reg_clear), + .rx_conv_pktin_reg (rx_conv_pktin_reg ), + .rx_conv_pktin_reg_clear (rx_conv_pktin_reg_clear ), + .tx_mac_pktin_reg (tx_mac_pktin_reg ), + .tx_mac_pktin_reg_clear (tx_mac_pktin_reg_clear ), + .tx_queue_pktin_reg (tx_queue_pktin_reg ), + .tx_queue_pktin_reg_clear (tx_queue_pktin_reg_clear), + .tx_conv_pktin_reg (tx_conv_pktin_reg ), + .tx_conv_pktin_reg_clear (tx_conv_pktin_reg_clear ), + // AXI Lite ports + .S_AXI_ACLK (S_AXI_ACLK ), + .S_AXI_ARESETN (S_AXI_ARESETN), + .S_AXI_AWADDR (S_AXI_AWADDR & 32'h0000ffff), + .S_AXI_AWVALID (S_AXI_AWVALID), + .S_AXI_WDATA (S_AXI_WDATA ), + .S_AXI_WSTRB (S_AXI_WSTRB ), + .S_AXI_WVALID (S_AXI_WVALID ), + .S_AXI_BREADY (S_AXI_BREADY ), + .S_AXI_ARADDR (S_AXI_ARADDR & 32'h0000ffff), + .S_AXI_ARVALID (S_AXI_ARVALID), + .S_AXI_RREADY (S_AXI_RREADY ), + .S_AXI_ARREADY (S_AXI_ARREADY), + .S_AXI_RDATA (S_AXI_RDATA ), + .S_AXI_RRESP (S_AXI_RRESP ), + .S_AXI_RVALID (S_AXI_RVALID ), + .S_AXI_WREADY (S_AXI_WREADY ), + .S_AXI_BRESP (S_AXI_BRESP ), + .S_AXI_BVALID (S_AXI_BVALID ), + .S_AXI_AWREADY (S_AXI_AWREADY) + ); + + assign clear_counters = reset_reg[0]; + assign reset_registers = reset_reg[4]; + assign reset_tables = reset_reg[8]; + assign mac_clear_counters = mac_reset_reg[0]; + assign mac_reset_registers = mac_reset_reg[4]; + assign mac_reset_tables = mac_reset_reg[8]; + //------------------------------------------------------------ + // MAC interface statistics + //------------------------------------------------------------ + always @ (posedge clk156) begin + if (~mac_resetn_sync | mac_reset_registers) begin + rx_mac_pktin_reg <= #1 `REG_RXMACPKT_DEFAULT; + tx_mac_pktin_reg <= #1 `REG_TXMACPKT_DEFAULT; + end + else begin + rx_mac_pktin_reg[`REG_RXMACPKT_WIDTH-2:0] <= #1 clear_counters | rx_mac_pktin_reg_clear ? 'h0 : + rx_mac_pktin_reg[`REG_RXMACPKT_WIDTH-2:0] + (m_axis_mac_tvalid && m_axis_mac_tlast); + rx_mac_pktin_reg[`REG_RXMACPKT_WIDTH-1] <= #1 clear_counters | rx_mac_pktin_reg_clear ? 1'h0 : + rx_mac_pktin_reg[`REG_RXMACPKT_WIDTH-2:0] + (m_axis_mac_tvalid && m_axis_mac_tlast) + > {(`REG_RXMACPKT_WIDTH-1){1'b1}} ? 1'b1 : rx_mac_pktin_reg[`REG_RXMACPKT_WIDTH-1]; + tx_mac_pktin_reg[`REG_TXMACPKT_WIDTH-2:0] <= #1 clear_counters | tx_mac_pktin_reg_clear ? 'h0 : + tx_mac_pktin_reg[`REG_TXMACPKT_WIDTH-2:0] + (s_axis_mac_tvalid && s_axis_mac_tready && s_axis_mac_tlast); + tx_mac_pktin_reg[`REG_RXMACPKT_WIDTH-1] <= #1 clear_counters | tx_mac_pktin_reg_clear ? 1'h0 : + tx_mac_pktin_reg[`REG_TXMACPKT_WIDTH-2:0] + (s_axis_mac_tvalid && s_axis_mac_tready && s_axis_mac_tlast) + > {(`REG_TXMACPKT_WIDTH-1){1'b1}} ? 1'b1 : tx_mac_pktin_reg[`REG_TXMACPKT_WIDTH-1]; + end + end + + always @ (posedge axis_aclk) begin + if (~resetn_sync | reset_registers) begin + id_reg <= #1 `REG_ID_DEFAULT; + version_reg <= #1 `REG_VERSION_DEFAULT; + ip2cpu_flip_reg <= #1 `REG_FLIP_DEFAULT; + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT; + rx_queue_pktin_reg <= #1 `REG_RXQPKT_DEFAULT; + rx_conv_pktin_reg <= #1 `REG_RXCONVPKT_DEFAULT; + tx_queue_pktin_reg <= #1 `REG_TXQPKT_DEFAULT; + tx_conv_pktin_reg <= #1 `REG_TXCONVPKT_DEFAULT; + end + else begin + rx_queue_pktin_reg[`REG_RXQPKT_WIDTH-2:0] <= #1 clear_counters | rx_queue_pktin_reg_clear ? 'h0 : + rx_queue_pktin_reg[`REG_RXQPKT_WIDTH-2:0] + (m_axis_fifo_tvalid && m_axis_fifo_tready && m_axis_fifo_tlast); + rx_queue_pktin_reg[`REG_RXQPKT_WIDTH-1] <= #1 clear_counters | rx_queue_pktin_reg_clear ? 1'h0 : + rx_queue_pktin_reg[`REG_RXQPKT_WIDTH-2:0] + (m_axis_fifo_tvalid && m_axis_fifo_tready && m_axis_fifo_tlast) + > {(`REG_RXQPKT_WIDTH-1){1'b1}} ? 1'b1 : rx_queue_pktin_reg[`REG_RXQPKT_WIDTH-1]; + tx_queue_pktin_reg[`REG_TXQPKT_WIDTH-2:0] <= #1 clear_counters | tx_queue_pktin_reg_clear ? 'h0 : + tx_queue_pktin_reg[`REG_TXQPKT_WIDTH-2:0] + (s_axis_fifo_tvalid && s_axis_fifo_tready && s_axis_fifo_tlast); + tx_queue_pktin_reg[`REG_TXQPKT_WIDTH-1] <= #1 clear_counters | tx_queue_pktin_reg_clear ? 1'h0 : + tx_queue_pktin_reg[`REG_TXQPKT_WIDTH-2:0] + (s_axis_fifo_tvalid && s_axis_fifo_tready && s_axis_fifo_tlast) + > {(`REG_TXQPKT_WIDTH-1){1'b1}} ? 1'b1 : tx_queue_pktin_reg[`REG_TXQPKT_WIDTH-1]; + + rx_conv_pktin_reg[`REG_RXCONVPKT_WIDTH-2:0] <= #1 clear_counters | rx_conv_pktin_reg_clear ? 'h0 : + rx_conv_pktin_reg[`REG_RXCONVPKT_WIDTH-2:0] + (m_axis_pipe_tvalid && m_axis_pipe_tready && m_axis_pipe_tlast); + rx_conv_pktin_reg[`REG_RXCONVPKT_WIDTH-1] <= #1 clear_counters | rx_conv_pktin_reg_clear ? 1'h0 : + rx_conv_pktin_reg[`REG_RXCONVPKT_WIDTH-2:0] + (m_axis_pipe_tvalid && m_axis_pipe_tready && m_axis_pipe_tlast) + > {(`REG_RXCONVPKT_WIDTH-1){1'b1}} ? 1'b1 : rx_conv_pktin_reg[`REG_RXCONVPKT_WIDTH-1]; + tx_conv_pktin_reg[`REG_TXCONVPKT_WIDTH-2:0] <= #1 clear_counters | tx_conv_pktin_reg_clear ? 'h0 : + tx_conv_pktin_reg[`REG_TXCONVPKT_WIDTH-2:0] + (s_axis_pipe_tvalid && s_axis_pipe_tready && s_axis_pipe_tlast); + tx_conv_pktin_reg[`REG_TXCONVPKT_WIDTH-1] <= #1 clear_counters | tx_conv_pktin_reg_clear ? 1'h0 : + tx_conv_pktin_reg[`REG_TXCONVPKT_WIDTH-2:0] + (s_axis_pipe_tvalid && s_axis_pipe_tready && s_axis_pipe_tlast) + > {(`REG_TXCONVPKT_WIDTH-1){1'b1}} ? 1'b1 : tx_conv_pktin_reg[`REG_TXCONVPKT_WIDTH-1]; + + id_reg <= #1 `REG_ID_DEFAULT; + version_reg <= #1 `REG_VERSION_DEFAULT; + ip2cpu_flip_reg <= #1 ~cpu2ip_flip_reg; + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT+cpu2ip_debug_reg; + end + end + +endmodule diff --git a/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs.v b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs.v new file mode 100644 index 0000000..cddef84 --- /dev/null +++ b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs.v @@ -0,0 +1,518 @@ +// +// Copyright (c) 2015 University of Cambridge +// Copyright (C) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ns/1ns +`include "nf_mac_attachment_cpu_regs_defines.v" +module nf_mac_attachment_cpu_regs # +( +parameter C_BASE_ADDRESS = 32'h00000000, +parameter C_S_AXI_DATA_WIDTH = 32, +parameter C_S_AXI_ADDR_WIDTH = 32 +) +( + // General ports + input mac_clk, + input mac_resetn, + input clk, + input resetn, + // Global Registers + input cpu_resetn_soft, + output reg resetn_soft, + output reg resetn_sync, + output reg mac_resetn_sync, + + // Register ports + input [`REG_ID_BITS] id_reg, + input [`REG_VERSION_BITS] version_reg, + output reg [`REG_RESET_BITS] reset_reg, + output reg [`REG_RESET_BITS] mac_reset_reg, + input [`REG_FLIP_BITS] ip2cpu_flip_reg, + output reg [`REG_FLIP_BITS] cpu2ip_flip_reg, + input [`REG_DEBUG_BITS] ip2cpu_debug_reg, + output reg [`REG_DEBUG_BITS] cpu2ip_debug_reg, + input [`REG_RXMACPKT_BITS] rx_mac_pktin_reg, + output reg rx_mac_pktin_reg_clear, + input [`REG_RXQPKT_BITS] rx_queue_pktin_reg, + output reg rx_queue_pktin_reg_clear, + input [`REG_RXCONVPKT_BITS] rx_conv_pktin_reg, + output reg rx_conv_pktin_reg_clear, + input [`REG_TXMACPKT_BITS] tx_mac_pktin_reg, + output reg tx_mac_pktin_reg_clear, + input [`REG_TXQPKT_BITS] tx_queue_pktin_reg, + output reg tx_queue_pktin_reg_clear, + input [`REG_RXCONVPKT_BITS] tx_conv_pktin_reg, + output reg tx_conv_pktin_reg_clear, + + // AXI Lite ports + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 :0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY + +); + + // AXI4LITE signals + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; + reg axi_awready; + reg axi_wready; + reg [1 : 0] axi_bresp; + reg axi_bvalid; + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; + reg axi_arready; + reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; + reg [1 : 0] axi_rresp; + reg axi_rvalid; + + reg resetn_sync_d; + reg mac_resetn_sync_d; + wire reg_rden; + wire reg_wren; + reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; + integer byte_index; + reg rx_mac_pktin_reg_clear_d; + reg rx_queue_pktin_reg_clear_d; + reg rx_conv_pktin_reg_clear_d; + reg tx_mac_pktin_reg_clear_d; + reg tx_queue_pktin_reg_clear_d; + reg tx_conv_pktin_reg_clear_d; + + // I/O Connections assignments + assign S_AXI_AWREADY = axi_awready; + assign S_AXI_WREADY = axi_wready; + assign S_AXI_BRESP = axi_bresp; + assign S_AXI_BVALID = axi_bvalid; + assign S_AXI_ARREADY = axi_arready; + assign S_AXI_RDATA = axi_rdata; + assign S_AXI_RRESP = axi_rresp; + assign S_AXI_RVALID = axi_rvalid; + + + //Sample reset (not mandatory, but good practice) + always @ (posedge clk) begin + if (~resetn) begin + resetn_sync_d <= 1'b0; + resetn_sync <= 1'b0; + end + else begin + resetn_sync_d <= resetn; + resetn_sync <= resetn_sync_d; + end + end + + always @ (posedge mac_clk) begin + if (~mac_resetn) begin + mac_resetn_sync_d <= 1'b0; + mac_resetn_sync <= 1'b0; + end + else begin + mac_resetn_sync_d <= resetn; + mac_resetn_sync <= resetn_sync_d; + end + end + + //global registers, sampling + always @(posedge clk) resetn_soft <= #1 cpu_resetn_soft; + + // Implement axi_awready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awready <= 1'b0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // slave is ready to accept write address when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_awready <= 1'b1; + end + else + begin + axi_awready <= 1'b0; + end + end + end + + // Implement axi_awaddr latching + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awaddr <= 0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // Write Address latching + axi_awaddr <= S_AXI_AWADDR ^ C_BASE_ADDRESS; + end + end + end + + // Implement axi_wready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_wready <= 1'b0; + end + else + begin + if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID) + begin + // slave is ready to accept write data when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_wready <= 1'b1; + end + else + begin + axi_wready <= 1'b0; + end + end + end + + // Implement write response logic generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_bvalid <= 0; + axi_bresp <= 2'b0; + end + else + begin + if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) + begin + // indicates a valid write response is available + axi_bvalid <= 1'b1; + axi_bresp <= 2'b0; // OKAY response + end // work error responses in future + else + begin + if (S_AXI_BREADY && axi_bvalid) + //check if bready is asserted while bvalid is high) + //(there is a possibility that bready is always asserted high) + begin + axi_bvalid <= 1'b0; + end + end + end + end + + // Implement axi_arready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_arready <= 1'b0; + axi_araddr <= 32'b0; + end + else + begin + if (~axi_arready && S_AXI_ARVALID) + begin + // indicates that the slave has acceped the valid read address + // Read address latching + axi_arready <= 1'b1; + axi_araddr <= S_AXI_ARADDR ^ C_BASE_ADDRESS; + end + else + begin + axi_arready <= 1'b0; + end + end + end + + + // Implement axi_rvalid generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rvalid <= 0; + axi_rresp <= 0; + end + else + begin + if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) + begin + // Valid read data is available at the read data bus + axi_rvalid <= 1'b1; + axi_rresp <= 2'b0; // OKAY response + end + else if (axi_rvalid && S_AXI_RREADY) + begin + // Read data is accepted by the master + axi_rvalid <= 1'b0; + end + end + end + + + // Implement memory mapped register select and write logic generation + + assign reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; + +////////////////////////////////////////////////////////////// +// write registers +////////////////////////////////////////////////////////////// + + +//Write only register, clear on write (i.e. event) + always @(posedge clk) begin + if (!resetn_sync) begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + else begin + if (reg_wren) begin + case (axi_awaddr) + //Reset Register + `REG_RESET_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_RESET_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + reset_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; + end + end + endcase + end + else begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + end + end + always @(posedge mac_clk) begin + if (!mac_resetn_sync) begin + mac_reset_reg <= #1 `REG_RESET_DEFAULT; + end + else begin + if (reg_wren) begin + case (axi_awaddr) + //Reset Register + `REG_RESET_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_RESET_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + mac_reset_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; + end + end + endcase + end + else begin + mac_reset_reg <= #1 `REG_RESET_DEFAULT; + end + end + end + +//R/W register, not cleared + always @(posedge clk) begin + if (!resetn_sync) begin + + cpu2ip_flip_reg <= #1 `REG_FLIP_DEFAULT; + cpu2ip_debug_reg <= #1 `REG_DEBUG_DEFAULT; + end + else begin + if (reg_wren) //write event + case (axi_awaddr) + //Flip Register + `REG_FLIP_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_FLIP_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_flip_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + //Debug Register + `REG_DEBUG_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_DEBUG_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_debug_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + default: begin + end + + endcase + end + end + + + +///////////////////////// +//// end of write +///////////////////////// + + // Implement memory mapped register select and read logic generation + // Slave register read enable is asserted when valid address is available + // and the slave is ready to accept the read address. + + // reg_rden control logic + // temperary no extra logic here + assign reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; + + always @(*) + begin + + case ( axi_araddr /*S_AXI_ARADDR ^ C_BASE_ADDRESS*/) + //Id Register + `REG_ID_ADDR : begin + reg_data_out [`REG_ID_BITS] = id_reg; + end + //Version Register + `REG_VERSION_ADDR : begin + reg_data_out [`REG_VERSION_BITS] = version_reg; + end + //Flip Register + `REG_FLIP_ADDR : begin + reg_data_out [`REG_FLIP_BITS] = ip2cpu_flip_reg; + end + //Debug Register + `REG_DEBUG_ADDR : begin + reg_data_out [`REG_DEBUG_BITS] = ip2cpu_debug_reg; + end + // RX MAC PKT Register + `REG_RXMACPKT_ADDR : begin + reg_data_out [`REG_RXMACPKT_BITS] = rx_mac_pktin_reg; + end + // RX QUEUE PKT Register + `REG_RXQPKT_ADDR : begin + reg_data_out [`REG_RXQPKT_BITS] = rx_queue_pktin_reg; + end + // RX CONV PKT Register + `REG_RXCONVPKT_ADDR : begin + reg_data_out [`REG_RXCONVPKT_BITS] = rx_conv_pktin_reg; + end + // TX MAC PKT Register + `REG_TXMACPKT_ADDR : begin + reg_data_out [`REG_TXMACPKT_BITS] = tx_mac_pktin_reg; + end + // TX QUEUE PKT Register + `REG_TXQPKT_ADDR : begin + reg_data_out [`REG_TXQPKT_BITS] = tx_queue_pktin_reg; + end + // TX CONV PKT Register + `REG_TXCONVPKT_ADDR : begin + reg_data_out [`REG_TXCONVPKT_BITS] = tx_conv_pktin_reg; + end + //Default return value + default: begin + reg_data_out [31:0] = 32'hDEADBEEF; + end + + endcase + + + end//end of assigning data to IP2Bus_Data bus + + //Read only registers, not cleared + //Nothing to do here.... + +//Read only registers, cleared on read (e.g. counters) + always @(posedge clk) + if (!resetn_sync) begin + rx_queue_pktin_reg_clear <= #1 1'b0; + rx_queue_pktin_reg_clear_d <= #1 1'b0; + tx_queue_pktin_reg_clear <= #1 1'b0; + tx_queue_pktin_reg_clear_d <= #1 1'b0; + rx_conv_pktin_reg_clear <= #1 1'b0; + rx_conv_pktin_reg_clear_d <= #1 1'b0; + tx_conv_pktin_reg_clear <= #1 1'b0; + tx_conv_pktin_reg_clear_d <= #1 1'b0; + end + else begin + rx_queue_pktin_reg_clear <= #1 rx_queue_pktin_reg_clear_d; + rx_queue_pktin_reg_clear_d <= #1 (reg_rden && (axi_araddr==`REG_RXQPKT_ADDR)) ? 1'b1 : 1'b0; + tx_queue_pktin_reg_clear <= #1 tx_queue_pktin_reg_clear_d; + tx_queue_pktin_reg_clear_d <= #1 (reg_rden && (axi_araddr==`REG_TXQPKT_ADDR)) ? 1'b1 : 1'b0; + rx_conv_pktin_reg_clear <= #1 rx_conv_pktin_reg_clear_d; + rx_conv_pktin_reg_clear_d <= #1 (reg_rden && (axi_araddr==`REG_RXCONVPKT_ADDR)) ? 1'b1 : 1'b0; + tx_conv_pktin_reg_clear <= #1 tx_conv_pktin_reg_clear_d; + tx_conv_pktin_reg_clear_d <= #1 (reg_rden && (axi_araddr==`REG_TXCONVPKT_ADDR)) ? 1'b1 : 1'b0; + end + + always @(posedge mac_clk) + if (!mac_resetn_sync) begin + rx_mac_pktin_reg_clear <= #1 1'b0; + rx_mac_pktin_reg_clear_d <= #1 1'b0; + tx_mac_pktin_reg_clear <= #1 1'b0; + tx_mac_pktin_reg_clear_d <= #1 1'b0; + end + else begin + rx_mac_pktin_reg_clear <= #1 rx_mac_pktin_reg_clear_d; + rx_mac_pktin_reg_clear_d <= #1 (reg_rden && (axi_araddr==`REG_RXMACPKT_ADDR)) ? 1'b1 : 1'b0; + tx_mac_pktin_reg_clear <= #1 tx_mac_pktin_reg_clear_d; + tx_mac_pktin_reg_clear_d <= #1 (reg_rden && (axi_araddr==`REG_TXMACPKT_ADDR)) ? 1'b1 : 1'b0; + end + +// Output register or memory read data + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rdata <= 0; + end + else + begin + // When there is a valid read address (S_AXI_ARVALID) with + // acceptance of read address by the slave (axi_arready), + // output the read dada + if (reg_rden) + begin + axi_rdata <= reg_data_out/*ip2bus_data*/; // register read data /* some new changes here */ + end + end + end +endmodule diff --git a/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs_defines.v b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs_defines.v new file mode 100644 index 0000000..591baf8 --- /dev/null +++ b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/nf_mac_attachment_cpu_regs_defines.v @@ -0,0 +1,85 @@ +// +// Copyright (c) 2015 University of Cambridge +// Copyright (C) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + `define REG_ID_BITS 31:0 + `define REG_ID_WIDTH 32 + `define REG_ID_DEFAULT 32'h0000DA04 + `define REG_ID_ADDR 32'h0 + + `define REG_VERSION_BITS 31:0 + `define REG_VERSION_WIDTH 32 + `define REG_VERSION_DEFAULT 32'h1 + `define REG_VERSION_ADDR 32'h4 + + `define REG_RESET_BITS 15:0 + `define REG_RESET_WIDTH 16 + `define REG_RESET_DEFAULT 16'h0 + `define REG_RESET_ADDR 32'h8 + + `define REG_FLIP_BITS 31:0 + `define REG_FLIP_WIDTH 32 + `define REG_FLIP_DEFAULT 32'h0 + `define REG_FLIP_ADDR 32'hC + + `define REG_DEBUG_BITS 31:0 + `define REG_DEBUG_WIDTH 32 + `define REG_DEBUG_DEFAULT 32'h0 + `define REG_DEBUG_ADDR 32'h10 + + `define REG_RXMACPKT_BITS 31:0 + `define REG_RXMACPKT_WIDTH 32 + `define REG_RXMACPKT_DEFAULT 32'h0 + `define REG_RXMACPKT_ADDR 32'h14 + + `define REG_TXMACPKT_BITS 31:0 + `define REG_TXMACPKT_WIDTH 32 + `define REG_TXMACPKT_DEFAULT 32'h0 + `define REG_TXMACPKT_ADDR 32'h18 + + `define REG_RXQPKT_BITS 31:0 + `define REG_RXQPKT_WIDTH 32 + `define REG_RXQPKT_DEFAULT 32'h0 + `define REG_RXQPKT_ADDR 32'h1C + + `define REG_TXQPKT_BITS 31:0 + `define REG_TXQPKT_WIDTH 32 + `define REG_TXQPKT_DEFAULT 32'h0 + `define REG_TXQPKT_ADDR 32'h20 + + `define REG_RXCONVPKT_BITS 31:0 + `define REG_RXCONVPKT_WIDTH 32 + `define REG_RXCONVPKT_DEFAULT 32'h0 + `define REG_RXCONVPKT_ADDR 32'h24 + + `define REG_TXCONVPKT_BITS 31:0 + `define REG_TXCONVPKT_WIDTH 32 + `define REG_TXCONVPKT_DEFAULT 32'h0 + `define REG_TXCONVPKT_ADDR 32'h28 diff --git a/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/rx_queue.v b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/rx_queue.v new file mode 100644 index 0000000..7abd595 --- /dev/null +++ b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/rx_queue.v @@ -0,0 +1,190 @@ +// +// Copyright (c) 2015 James Hongyi Zeng, Yury Audzevich, Gianni Antichi, Neelakandan Manihatty Bojan +// Copyright (c) 2016 Jong Hun Han +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// Description: +// 100g ethernet rx queue with backpressure. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ + +module rx_queue +#( + parameter AXI_DATA_WIDTH = 512, + parameter AXI_USER_WIDTH = 128, + parameter RXQUEUE_DEPTH = 128 +) +( + // AXI side output + input clk, + input reset, + + output [AXI_DATA_WIDTH-1:0] o_tdata, + output [AXI_USER_WIDTH-1:0] o_tuser, + output [AXI_DATA_WIDTH/8-1:0] o_tkeep, + output o_tvalid, + output o_tlast, + input o_tready, + + // MAC side input + input clk156, + input areset_clk156, + + input [AXI_DATA_WIDTH-1:0] i_tdata, + input [AXI_DATA_WIDTH/8-1:0] i_tkeep, + input [AXI_USER_WIDTH-1:0] i_tuser, + input i_tuser_err, + input i_tvalid, + input i_tlast, + + // statistics + output wire fifo_wr_en, + output wire rx_pkt_drop, + output rx_bad_frame, + output rx_good_frame +); + + localparam IDLE = 0; + localparam PKT = 1; + + wire fifo_almost_full; + wire fifo_empty, fifo_full; + wire fifo_rd_en; + + wire [AXI_DATA_WIDTH-1:0] tdata_rx_fifo, tdata_delay; + wire [AXI_USER_WIDTH-1:0] tuser_rx_fifo, tuser_delay; + wire [AXI_DATA_WIDTH/8-1:0] tkeep_rx_fifo, tkeep_delay; + wire tlast_rx_fifo, tlast_delay; + + reg rx_pkt_drop_reg; + wire rx_pkt_drop_frame; + reg [0:0] state; + + /* ************************************************** + * FIFO: rx_queue + * **************************************************/ + xpm_fifo_async # ( + // Common module parameters + .FIFO_MEMORY_TYPE ("auto"), + .ECC_MODE ("no_ecc"), + .FIFO_WRITE_DEPTH (RXQUEUE_DEPTH), + .WRITE_DATA_WIDTH (AXI_USER_WIDTH+AXI_DATA_WIDTH+(AXI_DATA_WIDTH/8)+1), + .WR_DATA_COUNT_WIDTH (1), + .PROG_FULL_THRESH (RXQUEUE_DEPTH-10), + .FULL_RESET_VALUE (0), + .USE_ADV_FEATURES ("0707"), + .READ_MODE ("fwft") + ) u_rxqueue ( + // Common module ports + .sleep (1'b0), + .rst (areset_clk156), + // Write Domain ports + .wr_clk (clk156), + .wr_en (fifo_wr_en), + .din ({tlast_rx_fifo, tkeep_rx_fifo, tdata_rx_fifo, tuser_rx_fifo}), + .full (fifo_full), + .prog_full (fifo_almost_full), + .wr_data_count(), + .overflow (), + .wr_rst_busy (), + .almost_full (), + .wr_ack (), + // Read Domain ports + .rd_clk (clk), + .rd_en (fifo_rd_en), + .dout ({tlast_delay, tkeep_delay, tdata_delay, tuser_delay}), + .empty (fifo_empty), + .prog_empty (), + .rd_data_count(), + .underflow (), + .rd_rst_busy (), + .almost_empty (), + .data_valid (), + // ECC Related ports + .injectsbiterr(), + .injectdbiterr(), + .sbiterr (), + .dbiterr () + ); + + assign rx_good_frame = (i_tuser_err == 1'b1); + assign rx_bad_frame = (i_tvalid && i_tlast && !rx_good_frame); + + /* ************************************************** + * Enqueue: rx_queue + * **************************************************/ + assign rx_pkt_drop = (i_tvalid && state == IDLE && fifo_almost_full) || + (i_tvalid && state == IDLE && !rx_good_frame); + assign rx_pkt_drop_frame = rx_pkt_drop || rx_pkt_drop_reg; + assign fifo_wr_en = i_tvalid && !rx_pkt_drop_frame; + assign tdata_rx_fifo = i_tdata; + assign tkeep_rx_fifo = i_tkeep; + assign tlast_rx_fifo = i_tlast; + assign tuser_rx_fifo = i_tuser; + + always @ (posedge clk156) + if (areset_clk156) begin + state <= IDLE; + rx_pkt_drop_reg <= 1'b0; + end + else begin + case(state) + IDLE:begin + if (i_tvalid && i_tlast && rx_pkt_drop_frame) begin + state <= IDLE; + rx_pkt_drop_reg <= 1'b0; + end + else if (i_tvalid && rx_pkt_drop_frame) begin + state <= IDLE; + rx_pkt_drop_reg <= 1'b1; + end + else if (i_tvalid && i_tlast && !rx_pkt_drop_frame) begin + state <= IDLE; + end + else if (i_tvalid && !rx_pkt_drop_frame) begin + state <= PKT; + end + end + PKT:begin + if (i_tvalid && i_tlast && ~fifo_full) begin + state <= IDLE; + end + end + default: ; + endcase + end + + /* ************************************************** + * Dequeue: rx_queue + * **************************************************/ + assign fifo_rd_en = ~fifo_empty && o_tready; + assign o_tvalid = ~fifo_empty; + assign o_tlast = tlast_delay; + assign o_tdata = tdata_delay; + assign o_tkeep = tkeep_delay; + assign o_tuser = tuser_delay; +endmodule diff --git a/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/tx_queue.v b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/tx_queue.v new file mode 100644 index 0000000..b97437d --- /dev/null +++ b/hw/lib/std/nf_mac_attachment_v1_0_0/hdl/tx_queue.v @@ -0,0 +1,269 @@ +// +// Copyright (c) 2015 James Hongyi Zeng, Yury Audzevich +// Copyright (c) 2016 Jong Hun Han +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// Description: +// 10g ethernet tx queue with backpressure. +// ported from nf10 (Virtex-5 based) interface. +// +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ + +module tx_queue + #( + parameter AXI_DATA_WIDTH = 512, //Only 64 is supported right now. + parameter C_S_AXIS_TUSER_WIDTH = 512 + + ) + ( + // AXI side + input clk, + input reset, + + input [C_S_AXIS_TUSER_WIDTH-1:0] i_tuser, + input [AXI_DATA_WIDTH-1:0] i_tdata, + input [(AXI_DATA_WIDTH/8)-1:0] i_tkeep, + input i_tvalid, + input i_tlast, + output i_tready, + + // other + output tx_dequeued_pkt, + output reg be, + output reg tx_pkts_enqueued_signal, + output reg [15:0] tx_bytes_enqueued, + + // MAC side + input clk156, + input areset_clk156, + + // AXI side output + output [AXI_DATA_WIDTH-1:0] o_tdata, + output [C_S_AXIS_TUSER_WIDTH-1:0] o_tuser, + output [(AXI_DATA_WIDTH/8)-1:0] o_tkeep, + output reg o_tvalid, + output reg o_tlast, + output reg o_tuser_err, + input o_tready + ); + + localparam IDLE = 2'd0; + localparam SEND_PKT = 2'd1; + + localparam METADATA = 1'b0; + localparam EOP = 1'b1; + + wire tlast_axi_i; + wire tlast_axi_o; + + wire fifo_almost_full, info_fifo_full; + wire fifo_empty, info_fifo_empty; + reg fifo_rd_en, info_fifo_rd_en; + wire info_fifo_wr_en; + wire fifo_wr_en; + + reg tx_dequeued_pkt_next; + + reg [2:0] state, state_next; + reg state1, state1_next; + + wire [2:0] zero_padding; + + //////////////////////////////////////////////// + //////////////////////////////////////////////// + assign fifo_wr_en = (i_tvalid & i_tready); + assign info_fifo_wr_en = i_tlast & i_tvalid & i_tready; + assign i_tready = ~fifo_almost_full & ~info_fifo_full; + assign tlast_axi_i = i_tlast; + + xpm_fifo_async # ( + // Common module parameters + .FIFO_MEMORY_TYPE ("auto"), + .ECC_MODE ("no_ecc"), + .FIFO_WRITE_DEPTH (128), + .WRITE_DATA_WIDTH (AXI_DATA_WIDTH+(AXI_DATA_WIDTH/8)+1+AXI_DATA_WIDTH), + .WR_DATA_COUNT_WIDTH (1), + .PROG_FULL_THRESH (128-10), + .FULL_RESET_VALUE (0), + .USE_ADV_FEATURES ("0707"), + .READ_MODE ("fwft") + ) u_tx_fifo ( + // Common module ports + .sleep (1'b0), + .rst (areset_clk156), + // Write Domain ports + .wr_clk (clk), + .wr_en (fifo_wr_en), + .din ({tlast_axi_i , i_tkeep, i_tdata, i_tuser}), + .full (), + .prog_full (fifo_almost_full), + .wr_data_count(), + .overflow (), + .wr_rst_busy (), + .almost_full (), + .wr_ack (), + // Read Domain ports + .rd_clk (clk156), + .rd_en (fifo_rd_en), + .dout ({tlast_axi_o, o_tkeep, o_tdata, o_tuser}), + .empty (fifo_empty), + .prog_empty (), + .rd_data_count(), + .underflow (), + .rd_rst_busy (), + .almost_empty (), + .data_valid (), + // ECC Related ports + .injectsbiterr(), + .injectdbiterr(), + .sbiterr (), + .dbiterr () + ); + + fifo_generator_1_9 tx_info_fifo ( + .din (1'b0), + .wr_en (info_fifo_wr_en), //Only 1 cycle per packet! + .wr_clk (clk), + + .dout (), + .rd_en (info_fifo_rd_en), + .rd_clk (clk156), + + .full (info_fifo_full), + .empty (info_fifo_empty), + .rst (areset_clk156) + ); + + // Sideband INFO + // pkt enq FSM comb + always @(*) begin + state1_next = METADATA; + + tx_pkts_enqueued_signal = 0; + tx_bytes_enqueued = 0; + + case(state1) + METADATA: begin + if(i_tvalid & i_tlast & i_tready) begin + state1_next = METADATA; + tx_pkts_enqueued_signal = 1; + tx_bytes_enqueued = i_tuser[15:0]; + end else if(i_tvalid & i_tready) begin + tx_pkts_enqueued_signal = 1; + tx_bytes_enqueued = i_tuser[15:0]; + state1_next = EOP; + end + end + + EOP: begin + state1_next = EOP; + if(i_tvalid & i_tlast & i_tready) begin + state1_next = METADATA; + end + end + + default: begin + state1_next = METADATA; + end + endcase + end + + // pkt enq FSM seq + always @(posedge clk) begin + if (reset) state1 <= METADATA; + else state1 <= state1_next; + end + + ////////////////////////////////////////////////////////// + + // FIFO draining FSM comb + assign tx_dequeued_pkt = tx_dequeued_pkt_next; + + always @(*) begin + state_next = IDLE; + + // axi + o_tuser_err = 1'b0; // no underrun + o_tvalid = 1'b0; + o_tlast = 1'b0; + + // fifos + fifo_rd_en = 1'b0; + info_fifo_rd_en = 1'b0; + + //sideband + tx_dequeued_pkt_next = 'b0; + be = 'b0; + + case(state) + IDLE: begin + if( ~info_fifo_empty & ~fifo_empty) begin + // pkt is stored already + info_fifo_rd_en = 1'b1; + be = 'b0; + state_next = SEND_PKT; + o_tvalid = 1'b1; + if (o_tready) begin + fifo_rd_en = 1'b1; + be = 1'b1; + tx_dequeued_pkt_next = 1'b1; + + if (tlast_axi_o) begin + o_tlast = 1'b1; + be = 1'b1; + state_next = IDLE; + end + end + end + end + + SEND_PKT: begin + // very important: + // tvalid to go first: pg157, v3.0, pp. 109. + o_tvalid = 1'b1; + state_next = SEND_PKT; + if (o_tready & ~fifo_empty) begin + fifo_rd_en = 1'b1; + be = 1'b1; + tx_dequeued_pkt_next = 1'b1; + + if (tlast_axi_o) begin + o_tlast = 1'b1; + be = 1'b1; + state_next = IDLE; + end + end + end + endcase + end + + always @(posedge clk156) begin + if(areset_clk156) state <= IDLE; + else state <= state_next; + end + endmodule diff --git a/hw/lib/std/nf_mac_attachment_v1_0_0/nf_mac_attachment_tcl.tcl b/hw/lib/std/nf_mac_attachment_v1_0_0/nf_mac_attachment_tcl.tcl new file mode 100644 index 0000000..f6f4bcc --- /dev/null +++ b/hw/lib/std/nf_mac_attachment_v1_0_0/nf_mac_attachment_tcl.tcl @@ -0,0 +1,238 @@ +# +# Copyright (c) 2015 Yury Audzevich +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +set device $::env(DEVICE) +set ip_name {nf_mac_attachment} +set lib_name {NetFPGA} +set vendor_name {NetFPGA} +set ip_display_name {nf_mac_attachment} +set ip_description {10G Ethernet attachment for NetFPGA NFPLUS} +set vendor_display_name {NetFPGA} +set vendor_company_url {http://www.netfpga.org} +set ip_version {1.0} + + +## Other +set proj_dir ./ip_proj + + +## # of added files +set_param project.singleFileAddWarning.Threshold 500 + + +### SubCore Reference +set subcore_names {\ + nf_axis_converter\ + fallthrough_small_fifo\ +} + +### Source Files List +# Here for all directory +set source_dir { \ + hdl\ +} + +## quick way, there is a cleaner way +set VerilogFiles [list] +set VerilogFiles [concat \ + [glob -nocomplain hdl]] + +set rtl_dirs [list] +set rtl_dirs [concat \ + hdl] + + +# Top Module Name +set top_module_name {nf_mac_attachment} +set top_module_file ./hdl/$top_module_name.v + +puts "top_file: $top_module_file \n" + +# Inferred Bus Interface +set bus_interfaces {\ + xilinx.com:signal:clock:1.0\ + xilinx.com:signal:reset:1.0\ + xilinx.com:interface:axis_rtl:1.0\ +} + +############################################# +# Create Project +############################################# +create_project -name ${ip_name} -force -dir "./${proj_dir}" -part ${device} +set_property source_mgmt_mode All [current_project] +set_property top $top_module_name [current_fileset] + +# local IP repo +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib [current_fileset] +update_ip_catalog + +# include dirs +foreach rtl_dir $rtl_dirs { + set_property include_dirs $rtl_dirs [current_fileset] +} + + +# Add verilog sources here +# Add Verilog Files to The IP Core +foreach verilog_file $VerilogFiles { + add_files -norecurse ${verilog_file} +} +#read_verilog $VerilogFiles + +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 + +create_ip -name fifo_generator -vendor xilinx.com -library ip -version 13.2 -module_name fifo_generator_1_9 -dir ./${proj_dir} +set_property -dict [list \ + CONFIG.Component_Name {fifo_generator_1_9} \ + CONFIG.Fifo_Implementation {Independent_Clocks_Block_RAM} \ + CONFIG.Performance_Options {First_Word_Fall_Through} \ + CONFIG.Input_Data_Width {1} \ + CONFIG.Input_Depth {16} \ + CONFIG.Output_Data_Width {1} \ + CONFIG.Output_Depth {16} \ + CONFIG.Reset_Type {Asynchronous_Reset} \ + CONFIG.Full_Flags_Reset_Value {1} \ + CONFIG.Data_Count_Width {4} \ + CONFIG.Write_Data_Count_Width {4} \ + CONFIG.Read_Data_Count_Width {4} \ + CONFIG.Full_Threshold_Assert_Value {15} \ + CONFIG.Full_Threshold_Negate_Value {14} \ + CONFIG.Empty_Threshold_Assert_Value {4} \ + CONFIG.Empty_Threshold_Negate_Value {5} \ + CONFIG.Enable_Safety_Circuit {true}] [get_ips fifo_generator_1_9] +generate_target {instantiation_template} [get_files ./${proj_dir}/fifo_generator_1_9/fifo_generator_1_9.xci] +generate_target all [get_files ./${proj_dir}/fifo_generator_1_9/fifo_generator_1_9.xci] +ipx::package_project -force -import_files ./${proj_dir}/fifo_generator_1_9/fifo_generator_1_9.xci + +## without fifo +ipx::package_project + +# Create IP Information +set_property name ${ip_name} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name ${vendor_display_name} [ipx::current_core] +set_property company_url ${vendor_company_url} [ipx::current_core] +set_property vendor ${vendor_name} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${ip_display_name} [ipx::current_core] +set_property description ${ip_description} [ipx::current_core] + +# Add SubCore Reference +#foreach subcore ${subcore_names} { +# puts $subcore +# set subcore_regex NAME=~*$subcore* +# set subcore_ipdef [get_ipdefs -filter ${subcore_regex}] +# +# ipx::add_subcore ${subcore_ipdef} [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +# ipx::add_subcore ${subcore_ipdef} [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] +# puts "Adding the following subcore: $subcore_ipdef \n" +# +#} +ipx::add_subcore NetFPGA:NetFPGA:nf_axis_converter:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:nf_axis_converter:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] +ipx::infer_user_parameters [ipx::current_core] + + +# Auto Generate Parameters +ipx::remove_all_hdl_parameter [ipx::current_core] +ipx::add_model_parameters_from_hdl [ipx::current_core] -top_level_hdl_file $top_module_file -top_module_name $top_module_name +ipx::infer_user_parameters [ipx::current_core] + +## manual +set_property value_validation_type list [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_list {1024 512 256 64} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_type list [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_list {1024 512 256 64} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_type list [ipx::get_user_parameters C_DEFAULT_VALUE_ENABLE -of_objects [ipx::current_core]] +set_property value_validation_list {0 1} [ipx::get_user_parameters C_DEFAULT_VALUE_ENABLE -of_objects [ipx::current_core]] +set_property value_validation_type list [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_list 128 [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_type list [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_list 128 [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH -of_objects [ipx::current_core]] +set_property value_validation_type list [ipx::get_user_parameters C_DEFAULT_VALUE_ENABLE -of_objects [ipx::current_core]] +set_property value_validation_list {0 1} [ipx::get_user_parameters C_DEFAULT_VALUE_ENABLE -of_objects [ipx::current_core]] + +# Add Ports +ipx::remove_all_port [ipx::current_core] +ipx::add_ports_from_hdl [ipx::current_core] -top_level_hdl_file $top_module_file -top_module_name $top_module_name + +# Auto Infer Bus Interfaces +foreach bus_standard ${bus_interfaces} { + ipx::infer_bus_interfaces ${bus_standard} [ipx::current_core] +} + +# manually infer the rest +# 156MHz clk +ipx::add_bus_interface clk156 [ipx::current_core] +set_property abstraction_type_vlnv xilinx.com:signal:clock_rtl:1.0 [ipx::get_bus_interfaces clk156 -of_objects [ipx::current_core]] +set_property bus_type_vlnv xilinx.com:signal:clock:1.0 [ipx::get_bus_interfaces clk156 -of_objects [ipx::current_core]] +set_property interface_mode slave [ipx::get_bus_interfaces clk156 -of_objects [ipx::current_core]] +ipx::add_port_map CLK [ipx::get_bus_interfaces clk156 -of_objects [ipx::current_core]] +set_property physical_name clk156 [ipx::get_port_maps CLK -of_objects [ipx::get_bus_interfaces clk156 -of_objects [ipx::current_core]]] +ipx::add_bus_parameter ASSOCIATED_BUSIF [ipx::get_bus_interfaces clk156 -of_objects [ipx::current_core]] +set_property value m_axis_mac:s_axis_mac [ipx::get_bus_parameters ASSOCIATED_BUSIF -of_objects [ipx::get_bus_interfaces clk156 -of_objects [ipx::current_core]]] + +# rst associated with 156MHz +ipx::add_bus_interface areset_clk156 [ipx::current_core] +set_property abstraction_type_vlnv xilinx.com:signal:reset_rtl:1.0 [ipx::get_bus_interfaces areset_clk156 -of_objects [ipx::current_core]] +set_property bus_type_vlnv xilinx.com:signal:reset:1.0 [ipx::get_bus_interfaces areset_clk156 -of_objects [ipx::current_core]] +set_property interface_mode slave [ipx::get_bus_interfaces areset_clk156 -of_objects [ipx::current_core]] +ipx::add_port_map RST [ipx::get_bus_interfaces areset_clk156 -of_objects [ipx::current_core]] +set_property physical_name areset_clk156 [ipx::get_port_maps RST -of_objects [ipx::get_bus_interfaces areset_clk156 -of_objects [ipx::current_core]]] +ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces areset_clk156 -of_objects [ipx::current_core]] +set_property value ACTIVE_HIGH [ipx::get_bus_parameters POLARITY -of_objects [ipx::get_bus_interfaces areset_clk156 -of_objects [ipx::current_core]]] + +# axis clk - auto inferred as axis_signal_aclk -- bug of 2014.4 +ipx::add_bus_parameter ASSOCIATED_BUSIF [ipx::get_bus_interfaces axis_aclk -of_objects [ipx::current_core]] +set_property value m_axis_pipe:s_axis_pipe [ipx::get_bus_parameters ASSOCIATED_BUSIF -of_objects [ipx::get_bus_interfaces axis_aclk -of_objects [ipx::current_core]]] + +# rst associated with axis clk - auto inferred + +# BUS parameters +ipx::add_bus_parameter TDATA_NUM_BYTES [ipx::get_bus_interfaces m_axis_pipe -of_objects [ipx::current_core]] +set_property description {TDATA Width (bytes)} [ipx::get_bus_parameters TDATA_NUM_BYTES -of_objects [ipx::get_bus_interfaces m_axis_pipe -of_objects [ipx::current_core]]] +set_property value 32 [ipx::get_bus_parameters TDATA_NUM_BYTES -of_objects [ipx::get_bus_interfaces m_axis_pipe -of_objects [ipx::current_core]]] + +# Write IP Core xml to File system +ipx::check_integrity [ipx::current_core] +write_peripheral [ipx::current_core] + +# Generate GUI Configuration Files +ipx::create_xgui_files [ipx::current_core] +ipx::update_checksums [ipx::current_core] +ipx::save_core [ipx::current_core] + +close_project +exit diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/Makefile b/hw/lib/std/nic_output_port_lookup_v1_0_0/Makefile new file mode 100644 index 0000000..292a8b4 --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/Makefile @@ -0,0 +1,32 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source nic_output_port_lookup.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip hdl/axi_lite_ipif/ diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/data/module_generation_nic_opl.xlsm b/hw/lib/std/nic_output_port_lookup_v1_0_0/data/module_generation_nic_opl.xlsm new file mode 100644 index 0000000000000000000000000000000000000000..5855b2f5efaa52e18342eb92a032a5175ce43fcc GIT binary patch literal 39697 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 z zKBX2+QJsCwNa73pMYy4OMY95RAqH=*3W|2-aN@)6> z&a#ZC907K{Qbn*v%LOYNq34Ko;5@_zzOWUNjDt3yS0z5d(qGyk4QgjyVUci!5x^Fl2zBqrXy!&Z@Qd-QC_BuGT=+om9lWX}!(geXU2H^y zKq&=QpaEK)Cp`<{;LG5}vbjApm$2wcBDjP<329UPrMp>_{R*Q7ZJV#X&9UWLRl-m( zmjp$G59={U6+?t2bJW0Nhmi2C{dOjNu|?4#o|D{!Hb4r&HI?KAOgk7^pcibpSTe-nFx(bK&m*5& z!#ii6qu(V}eS(kBtk)>Nm4~jUdy2355)WqwmHw${e&|alR(|MBWlWd9(vNs+sFK!! zK6=23(sN}B5AjUb27rf-8qJ3Z$5TN- zgTfgUo@)SwAM6z(_j=rzFPXLk|TnA#r zhU5>v4^jIrOmf5F?ti~)QuWaWkLdL?n8x~Ub*vQ+~YefkP9dp^2Rq103HMW~6 zo#)Gs-f_tct21Y~jU-84^(wX)wMxRY4*B+ZZSzAQroPvCM%#|_P8+E6OD_mdW4qal zV%ucs=2iN)?hDyOsQ7=rCBZ@d{RNf()-34llFI*}SDjmeO(KE zVG~_bt3M&bB1!_LgApn4*4G)Ty56){DJEYNjmHO{FjpV7FNaj{>c&VnOeg6Q{^vbFy>$wQ`^&TT(D+ft2@Y^HVTIs+Y_$YKDND9*bupwid-M3gJF@RTHo%Of?82D; z(&{Z>(AqjW6OF89xqX4wlb9IVXR3Y%TK}(}qdA1mOab&Q8n_4j-}4-%Kb~V}@I|-J z_>0~bLs=at9UEO6eL{G~D#nUs-MJ3zr&gbs7@s&@jCyEM7*G;W{!R!Ca>5p$0IV-u zOv%wE^nBalvSLWXU|o!SjTzqvM;R%=sny_E#X%%t3;hT|L7{|yLj+J;1m zu#s9of421mn2Gv!LihJ9)!Ne1(8|I7&6T_47R^9DB6(sy1reQMC&>LgDhpPmMWfZ4 z+jVeuz_gnuA2(}jjXO~@3mXkUG8##1AT|DRE+)qD!!d9C9^UJ+(g_u8Q!&M zJ>BWX&iEkyYK>82v)+9^jwlV5&CKx%8k6N!+~)i$dUf)(V8!RA_{;k5{^kBsxPKy4 zNjcY3{?`xXO(|Pj_||ynMr2jyZ4W#B(w||OP;2h?OAg+-FE>71ditg)(`Mzj98Z_O zR-1qQ%XQ;5mmB>5J?Iw6xI61ZNvZ64r(}a!A>x%M<}Wknc%P_q>+)=_m@O-|zkIaw z3Dz|TM5RBIA&~wUnRJ1RDA*V{fCZu=gTvIM2i(90?jA14p~OHzBoOVK4{Yn^mBfcs z7Ni!(f_xX?jcUNwPy^*JKrKE%Lx4-FkbnztCI_;80=%RjUE`J@nB*6&M(J5jugaD?DJ$#U+(Fso(`B=vwdme=P74m~VFieGM8bMt~e(X8~w0eBoGG zZjMV)VmYw4U<4XDMmGrkT6u&)ePUpPP%oKB*N%RyG(!7XE3kI-L#ELUKtIzHVZcO3 zumM<4_(V4aeH#tJl$0cNQ?PETK{pV6*9gMEW65|7MC>6!HxPZt1j0b+RCEIo8-CDD zL0=(=Fr_dLYzjQuk=F~Nn}WWg31JF*5!e)r^-bs|pwE>eOn6_3)g9mp1>F?%2@ixR z1$C&VAQCZn`UBk{^x_d=kW~}dARMEw=;ojfaUx6s=Iv$%2J`_>bls@KNyxe%wj$|< z4KAT;NAK+;3~1~CdjhSmk3JRv?)#$~iaTT+x^aXI)~G`7_8=T5+5<5Mxf6u$3iM6| zLibmQZUSBdcQMcn#qG7kJ{(>Hx21_U$E+WRIpAzgygA$xaF_#bF`}D;-Yi1|)&rm literal 0 HcmV?d00001 diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h b/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h new file mode 100644 index 0000000..1235e92 --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.h +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +##########This text should be copied to the head file ############# + #Registers offset definitions + +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_OFFSET 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_DEFAULT 0x0000DA02 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_OFFSET 0x4 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_DEFAULT 0x1 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_OFFSET 0x8 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_WIDTH 16 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_OFFSET 0xC +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_OFFSET 0x10 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_OFFSET 0x14 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_OFFSET 0x18 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_WIDTH 32 diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl b/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl new file mode 100644 index 0000000..ac05517 --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl @@ -0,0 +1,56 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# +# File: +# output_port_lookup_regs_defines.tcl +# +# Description: +# This file is automatically generated with tcl defines for the software +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +set OUTPUT_PORT_LOOKUP_REGS_ID_0_OFFSET 0x0 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_DEFAULT 0x0000DA02 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_OFFSET 0x4 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_DEFAULT 0x1 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_OFFSET 0x8 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_WIDTH 16 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_OFFSET 0xC +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_OFFSET 0x10 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_OFFSET 0x14 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_OFFSET 0x18 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_WIDTH 32 diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt b/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt new file mode 100644 index 0000000..fe7361e --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt @@ -0,0 +1,56 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.txt +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +#define NFPLUS OUTPUT_PORT_LOOKUP ID OFFSET 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP ID DEFAULT 0x0000DA02 +#define NFPLUS OUTPUT_PORT_LOOKUP ID WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION OFFSET 0x4 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION DEFAULT 0x1 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET OFFSET 0x8 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET WIDTH 16 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP OFFSET 0xC +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG OFFSET 0x10 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN OFFSET 0x14 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT OFFSET 0x18 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT WIDTH 32 diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/nic_output_port_lookup.v b/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/nic_output_port_lookup.v new file mode 100644 index 0000000..1193aae --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/nic_output_port_lookup.v @@ -0,0 +1,308 @@ +//- +// Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +// Junior University +// Copyright (C) 2010, 2011 Adam Covington +// Copyright (C) 2015 Noa Zilberman +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +/******************************************************************************* + * File: + * nic_output_port_lookup.v + * + * Library: + * hw/std/cores/nic_output_port_lookup + * + * Module: + * nic_output_port_lookup + * + * Author: + * Adam Covington + * Modified by Noa Zilberman + * + * Description: + * Output port lookup for the reference NIC project + * + */ + + +`include "output_port_lookup_cpu_regs_defines.v" + +module nic_output_port_lookup +#( + //Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH=512, + parameter C_S_AXIS_DATA_WIDTH=512, + parameter C_M_AXIS_TUSER_WIDTH=128, + parameter C_S_AXIS_TUSER_WIDTH=128, + parameter SRC_PORT_POS=16, + parameter DST_PORT_POS=24, + + // AXI Registers Data Width + parameter C_S_AXI_DATA_WIDTH = 32, + parameter C_S_AXI_ADDR_WIDTH = 12, + parameter C_BASEADDR = 32'h00000000 + + +) +( + // Global Ports + input axis_aclk, + input axis_resetn, + + // Master Stream Ports (interface to data path) + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_tkeep, + output reg [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_tuser, + output m_axis_tvalid, + input m_axis_tready, + output m_axis_tlast, + + // Slave Stream Ports (interface to RX queues) + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser, + input s_axis_tvalid, + output s_axis_tready, + input s_axis_tlast, + +// Slave AXI Ports + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 :0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY +); + + reg [`REG_ID_BITS] id_reg; + reg [`REG_VERSION_BITS] version_reg; + wire [`REG_RESET_BITS] reset_reg; + reg [`REG_FLIP_BITS] ip2cpu_flip_reg; + wire [`REG_FLIP_BITS] cpu2ip_flip_reg; + reg [`REG_PKTIN_BITS] pktin_reg; + wire pktin_reg_clear; + reg [`REG_PKTOUT_BITS] pktout_reg; + wire pktout_reg_clear; + reg [`REG_DEBUG_BITS] ip2cpu_debug_reg; + wire [`REG_DEBUG_BITS] cpu2ip_debug_reg; + + wire clear_counters; + wire reset_registers; + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 {(`REG_PKTIN_WIDTH-1){1'b1}} ? 1'b1 : pktin_reg[`REG_PKTIN_WIDTH-1]; + + pktout_reg [`REG_PKTOUT_WIDTH-2:0]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tlast && m_axis_tvalid && m_axis_tready) ; + pktout_reg [`REG_PKTOUT_WIDTH-1]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tlast && m_axis_tvalid && m_axis_tready) > {(`REG_PKTOUT_WIDTH-1){1'b1}} ? + 1'b1 : pktout_reg [`REG_PKTOUT_WIDTH-1]; + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT+cpu2ip_debug_reg; + end + + + + + +endmodule // output_port_lookup diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs.v b/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs.v new file mode 100644 index 0000000..46ad36d --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs.v @@ -0,0 +1,438 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_cpu_regs.v +// +// Module: +// output_port_lookup_cpu_regs +// +// Description: +// This file is automatically generated with the registers towards the CPU/Software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`include "output_port_lookup_cpu_regs_defines.v" +module output_port_lookup_cpu_regs # +( +parameter C_BASE_ADDRESS = 32'h00000000, +parameter C_S_AXI_DATA_WIDTH = 32, +parameter C_S_AXI_ADDR_WIDTH = 32 +) +( + // General ports + input clk, + input resetn, + // Global Registers + input cpu_resetn_soft, + output reg resetn_soft, + output reg resetn_sync, + + // Register ports + input [`REG_ID_BITS] id_reg, + input [`REG_VERSION_BITS] version_reg, + output reg [`REG_RESET_BITS] reset_reg, + input [`REG_FLIP_BITS] ip2cpu_flip_reg, + output reg [`REG_FLIP_BITS] cpu2ip_flip_reg, + input [`REG_DEBUG_BITS] ip2cpu_debug_reg, + output reg [`REG_DEBUG_BITS] cpu2ip_debug_reg, + input [`REG_PKTIN_BITS] pktin_reg, + output reg pktin_reg_clear, + input [`REG_PKTOUT_BITS] pktout_reg, + output reg pktout_reg_clear, + + // AXI Lite ports + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 :0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY + +); + + // AXI4LITE signals + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; + reg axi_awready; + reg axi_wready; + reg [1 : 0] axi_bresp; + reg axi_bvalid; + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; + reg axi_arready; + reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; + reg [1 : 0] axi_rresp; + reg axi_rvalid; + + reg resetn_sync_d; + wire reg_rden; + wire reg_wren; + reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; + integer byte_index; + reg pktin_reg_clear_d; + reg pktout_reg_clear_d; + + // I/O Connections assignments + assign S_AXI_AWREADY = axi_awready; + assign S_AXI_WREADY = axi_wready; + assign S_AXI_BRESP = axi_bresp; + assign S_AXI_BVALID = axi_bvalid; + assign S_AXI_ARREADY = axi_arready; + assign S_AXI_RDATA = axi_rdata; + assign S_AXI_RRESP = axi_rresp; + assign S_AXI_RVALID = axi_rvalid; + + + //Sample reset (not mandatory, but good practice) + always @ (posedge clk) begin + if (~resetn) begin + resetn_sync_d <= 1'b0; + resetn_sync <= 1'b0; + end + else begin + resetn_sync_d <= resetn; + resetn_sync <= resetn_sync_d; + end + end + + + //global registers, sampling + always @(posedge clk) resetn_soft <= #1 cpu_resetn_soft; + + // Implement axi_awready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awready <= 1'b0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // slave is ready to accept write address when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_awready <= 1'b1; + end + else + begin + axi_awready <= 1'b0; + end + end + end + + // Implement axi_awaddr latching + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awaddr <= 0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // Write Address latching + axi_awaddr <= S_AXI_AWADDR ^ C_BASE_ADDRESS; + end + end + end + + // Implement axi_wready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_wready <= 1'b0; + end + else + begin + if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID) + begin + // slave is ready to accept write data when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_wready <= 1'b1; + end + else + begin + axi_wready <= 1'b0; + end + end + end + + // Implement write response logic generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_bvalid <= 0; + axi_bresp <= 2'b0; + end + else + begin + if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) + begin + // indicates a valid write response is available + axi_bvalid <= 1'b1; + axi_bresp <= 2'b0; // OKAY response + end // work error responses in future + else + begin + if (S_AXI_BREADY && axi_bvalid) + //check if bready is asserted while bvalid is high) + //(there is a possibility that bready is always asserted high) + begin + axi_bvalid <= 1'b0; + end + end + end + end + + // Implement axi_arready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_arready <= 1'b0; + axi_araddr <= 32'b0; + end + else + begin + if (~axi_arready && S_AXI_ARVALID) + begin + // indicates that the slave has acceped the valid read address + // Read address latching + axi_arready <= 1'b1; + axi_araddr <= S_AXI_ARADDR ^ C_BASE_ADDRESS; + end + else + begin + axi_arready <= 1'b0; + end + end + end + + + // Implement axi_rvalid generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rvalid <= 0; + axi_rresp <= 0; + end + else + begin + if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) + begin + // Valid read data is available at the read data bus + axi_rvalid <= 1'b1; + axi_rresp <= 2'b0; // OKAY response + end + else if (axi_rvalid && S_AXI_RREADY) + begin + // Read data is accepted by the master + axi_rvalid <= 1'b0; + end + end + end + + + // Implement memory mapped register select and write logic generation + + assign reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; + +////////////////////////////////////////////////////////////// +// write registers +////////////////////////////////////////////////////////////// + + +//Write only register, clear on write (i.e. event) + always @(posedge clk) begin + if (!resetn_sync) begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + else begin + if (reg_wren) begin + case (axi_awaddr) + //Reset Register + `REG_RESET_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_RESET_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + reset_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; + end + end + endcase + end + else begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + end + end + +//R/W register, not cleared + always @(posedge clk) begin + if (!resetn_sync) begin + + cpu2ip_flip_reg <= #1 `REG_FLIP_DEFAULT; + cpu2ip_debug_reg <= #1 `REG_DEBUG_DEFAULT; + end + else begin + if (reg_wren) //write event + case (axi_awaddr) + //Flip Register + `REG_FLIP_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_FLIP_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_flip_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + //Debug Register + `REG_DEBUG_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_DEBUG_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_debug_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + default: begin + end + + endcase + end + end + + + +///////////////////////// +//// end of write +///////////////////////// + + // Implement memory mapped register select and read logic generation + // Slave register read enable is asserted when valid address is available + // and the slave is ready to accept the read address. + + // reg_rden control logic + // temperary no extra logic here + assign reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; + + always @(*) + begin + + case ( axi_araddr /*S_AXI_ARADDR ^ C_BASE_ADDRESS*/) + //Id Register + `REG_ID_ADDR : begin + reg_data_out [`REG_ID_BITS] = id_reg; + end + //Version Register + `REG_VERSION_ADDR : begin + reg_data_out [`REG_VERSION_BITS] = version_reg; + end + //Flip Register + `REG_FLIP_ADDR : begin + reg_data_out [`REG_FLIP_BITS] = ip2cpu_flip_reg; + end + //Debug Register + `REG_DEBUG_ADDR : begin + reg_data_out [`REG_DEBUG_BITS] = ip2cpu_debug_reg; + end + //Pktin Register + `REG_PKTIN_ADDR : begin + reg_data_out [`REG_PKTIN_BITS] = pktin_reg; + end + //Pktout Register + `REG_PKTOUT_ADDR : begin + reg_data_out [`REG_PKTOUT_BITS] = pktout_reg; + end + //Default return value + default: begin + reg_data_out [31:0] = 32'hDEADBEEF; + end + + endcase + + end//end of assigning data to IP2Bus_Data bus + + //Read only registers, not cleared + //Nothing to do here.... + +//Read only registers, cleared on read (e.g. counters) + always @(posedge clk) + if (!resetn_sync) begin + pktin_reg_clear <= #1 1'b0; + pktin_reg_clear_d <= #1 1'b0; + pktout_reg_clear <= #1 1'b0; + pktout_reg_clear_d <= #1 1'b0; + end + else begin + pktin_reg_clear <= #1 pktin_reg_clear_d; + pktin_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTIN_ADDR)) ? 1'b1 : 1'b0; + pktout_reg_clear <= #1 pktout_reg_clear_d; + pktout_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTOUT_ADDR)) ? 1'b1 : 1'b0; + end + + +// Output register or memory read data + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rdata <= 0; + end + else + begin + // When there is a valid read address (S_AXI_ARVALID) with + // acceptance of read address by the slave (axi_arready), + // output the read dada + if (reg_rden) + begin + axi_rdata <= reg_data_out/*ip2bus_data*/; // register read data /* some new changes here */ + end + end + end +endmodule diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs_defines.v b/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs_defines.v new file mode 100644 index 0000000..e564f14 --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/hdl/output_port_lookup_cpu_regs_defines.v @@ -0,0 +1,73 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_cpu_regs_defines.v +// +// Module: +// output_port_lookup_cpu_regs_defines +// +// Description: +// This file is automatically generated with the registers defintions towards the CPU/Software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + + `define REG_ID_BITS 31:0 + `define REG_ID_WIDTH 32 + `define REG_ID_DEFAULT 32'h0000DA02 + `define REG_ID_ADDR 32'h0 + + `define REG_VERSION_BITS 31:0 + `define REG_VERSION_WIDTH 32 + `define REG_VERSION_DEFAULT 32'h1 + `define REG_VERSION_ADDR 32'h4 + + `define REG_RESET_BITS 15:0 + `define REG_RESET_WIDTH 16 + `define REG_RESET_DEFAULT 16'h0 + `define REG_RESET_ADDR 32'h8 + + `define REG_FLIP_BITS 31:0 + `define REG_FLIP_WIDTH 32 + `define REG_FLIP_DEFAULT 32'h0 + `define REG_FLIP_ADDR 32'hC + + `define REG_DEBUG_BITS 31:0 + `define REG_DEBUG_WIDTH 32 + `define REG_DEBUG_DEFAULT 32'h0 + `define REG_DEBUG_ADDR 32'h10 + + `define REG_PKTIN_BITS 31:0 + `define REG_PKTIN_WIDTH 32 + `define REG_PKTIN_DEFAULT 32'h0 + `define REG_PKTIN_ADDR 32'h14 + + `define REG_PKTOUT_BITS 31:0 + `define REG_PKTOUT_WIDTH 32 + `define REG_PKTOUT_DEFAULT 32'h0 + `define REG_PKTOUT_ADDR 32'h18 diff --git a/hw/lib/std/nic_output_port_lookup_v1_0_0/nic_output_port_lookup.tcl b/hw/lib/std/nic_output_port_lookup_v1_0_0/nic_output_port_lookup.tcl new file mode 100644 index 0000000..a407597 --- /dev/null +++ b/hw/lib/std/nic_output_port_lookup_v1_0_0/nic_output_port_lookup.tcl @@ -0,0 +1,141 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design nic_output_port_lookup +set top nic_output_port_lookup +set device $::env(DEVICE) +set proj_dir ./synth +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# set IP paths +##################################### + +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +puts "Creating Output Port Lookup IP" +# Project Constraints +##################################### +# Project Structure & IP Build +##################################### +read_verilog "./hdl/output_port_lookup_cpu_regs_defines.v" +read_verilog "./hdl/output_port_lookup_cpu_regs.v" +read_verilog "./hdl/nic_output_port_lookup.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::add_user_parameter {C_S_AXI_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property display_name {C_S_AXI_DATA_WIDTH} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXI_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property display_name {C_S_AXI_ADDR_WIDTH} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property display_name {C_M_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property display_name {C_S_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property display_name {C_M_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property display_name {C_S_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {SRC_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters SRC_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters SRC_PORT_POS] +set_property value {16} [ipx::get_user_parameters SRC_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters SRC_PORT_POS] + +ipx::add_user_parameter {DST_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters DST_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters DST_PORT_POS] +set_property value {24} [ipx::get_user_parameters DST_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters DST_PORT_POS] + +ipx::add_user_parameter {C_BASEADDR} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_BASEADDR] +set_property display_name {C_BASEADDR} [ipx::get_user_parameters C_BASEADDR] +set_property value {0x00000000} [ipx::get_user_parameters C_BASEADDR] +set_property value_format {bitstring} [ipx::get_user_parameters C_BASEADDR] + +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] + +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis -of_objects [ipx::current_core]] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + +file delete -force ${proj_dir} diff --git a/hw/lib/std/output_queues_v1_0_0/Makefile b/hw/lib/std/output_queues_v1_0_0/Makefile new file mode 100644 index 0000000..54fc49a --- /dev/null +++ b/hw/lib/std/output_queues_v1_0_0/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (c) 2015 University of Cambridge +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source output_queues.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/std/output_queues_v1_0_0/data/module_generation_output_queues.xlsm b/hw/lib/std/output_queues_v1_0_0/data/module_generation_output_queues.xlsm new file mode 100644 index 0000000000000000000000000000000000000000..01970e19a29eca9d44d2b6ac42dd65d5bdaf0d33 GIT binary patch literal 46069 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%0AhclM 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%0A@{uD8&-hmvz4RE|%U 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 {(`REG_PKTIN_WIDTH-1){1'b1}} ? 1'b1 : pktin_reg[`REG_PKTIN_WIDTH-1]; + + pktout_reg [`REG_PKTOUT_WIDTH-2:0]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_0_tlast && m_axis_0_tvalid && m_axis_0_tready) + (m_axis_1_tlast && m_axis_1_tvalid && m_axis_1_tready)+ (m_axis_2_tlast && m_axis_2_tvalid && m_axis_2_tready); + pktout_reg [`REG_PKTOUT_WIDTH-1]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_0_tlast && m_axis_0_tvalid && m_axis_0_tready) + (m_axis_1_tlast && m_axis_1_tvalid && m_axis_1_tready)+ (m_axis_2_tlast && m_axis_2_tvalid && m_axis_2_tready) > {(`REG_PKTOUT_WIDTH-1){1'b1}} ? 1'b1 : pktout_reg [`REG_PKTOUT_WIDTH-1]; + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT+cpu2ip_debug_reg; + //Port 0 Counters + pktstoredport0_reg[`REG_PKTSTOREDPORT0_WIDTH-2:0] <= #1 clear_counters | pktstoredport0_reg_clear ? 'h0 : pktstoredport0_reg[`REG_PKTSTOREDPORT0_WIDTH-2:0] + pkt_stored[0]; + pktstoredport0_reg[`REG_PKTSTOREDPORT0_WIDTH-1] <= #1 clear_counters | pktstoredport0_reg_clear ? 'h0 : pktstoredport0_reg [`REG_PKTSTOREDPORT0_WIDTH-2:0] + pkt_stored[0] > {(`REG_PKTSTOREDPORT0_WIDTH-1){1'b1}} ? 1'b1 : pktstoredport0_reg[`REG_PKTSTOREDPORT0_WIDTH-1]; + bytesstoredport0_reg[`REG_BYTESSTOREDPORT0_WIDTH-2:0] <= #1 clear_counters | bytesstoredport0_reg_clear ? 'h0 : bytesstoredport0_reg[`REG_BYTESSTOREDPORT0_WIDTH-2:0] + (pkt_stored[0] ? bytes_stored : 0); + bytesstoredport0_reg[`REG_BYTESSTOREDPORT0_WIDTH-1] <= #1 clear_counters | bytesstoredport0_reg_clear ? 'h0 : bytesstoredport0_reg [`REG_BYTESSTOREDPORT0_WIDTH-2:0] + (pkt_stored[0] ? bytes_stored : 0) > {(`REG_BYTESSTOREDPORT0_WIDTH-1){1'b1}} ? 1'b1 : bytesstoredport0_reg[`REG_BYTESSTOREDPORT0_WIDTH-1]; + pktremovedport0_reg[`REG_PKTREMOVEDPORT0_WIDTH-2:0] <= #1 clear_counters | pktremovedport0_reg_clear ? 'h0 : pktremovedport0_reg[`REG_PKTREMOVEDPORT0_WIDTH-2:0] + pkt_removed[0]; + pktremovedport0_reg[`REG_PKTREMOVEDPORT0_WIDTH-1] <= #1 clear_counters | pktremovedport0_reg_clear ? 'h0 : pktremovedport0_reg [`REG_PKTREMOVEDPORT0_WIDTH-2:0] + pkt_removed[0] > {(`REG_PKTREMOVEDPORT0_WIDTH-1){1'b1}} ? 1'b1 : pktremovedport0_reg[`REG_PKTREMOVEDPORT0_WIDTH-1]; + bytesremovedport0_reg[`REG_BYTESREMOVEDPORT0_WIDTH-2:0] <= #1 clear_counters | bytesremovedport0_reg_clear ? 'h0 : bytesremovedport0_reg[`REG_BYTESREMOVEDPORT0_WIDTH-2:0] + bytes_removed_0; + bytesremovedport0_reg[`REG_BYTESREMOVEDPORT0_WIDTH-1] <= #1 clear_counters | bytesremovedport0_reg_clear ? 'h0 : bytesremovedport0_reg [`REG_BYTESREMOVEDPORT0_WIDTH-2:0] + bytes_removed_0 > {(`REG_BYTESREMOVEDPORT0_WIDTH-1){1'b1}} ? 1'b1 : bytesremovedport0_reg[`REG_BYTESREMOVEDPORT0_WIDTH-1]; + pktdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-2:0] <= #1 clear_counters | pktdroppedport0_reg_clear ? 'h0 : pktdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-2:0] + pkt_dropped[0]; + pktdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-1] <= #1 clear_counters | pktdroppedport0_reg_clear ? 'h0 : pktdroppedport0_reg [`REG_PKTDROPPEDPORT0_WIDTH-2:0] + pkt_dropped[0] > {(`REG_PKTDROPPEDPORT0_WIDTH-1){1'b1}} ? 1'b1 : pktdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-1]; + bytesdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-2:0] <= #1 clear_counters | bytesdroppedport0_reg_clear ? 'h0 : bytesdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-2:0] + bytes_dropped[0]; + bytesdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-1] <= #1 clear_counters | bytesdroppedport0_reg_clear ? 'h0 : bytesdroppedport0_reg [`REG_PKTDROPPEDPORT0_WIDTH-2:0] + bytes_dropped[0] > {(`REG_PKTDROPPEDPORT0_WIDTH-1){1'b1}} ? 1'b1 : bytesdroppedport0_reg[`REG_PKTDROPPEDPORT0_WIDTH-1]; + pktinqueueport0_reg[`REG_PKTINQUEUEPORT0_WIDTH-2:0] <= #1 clear_counters | pktinqueueport0_reg_clear ? 'h0 : pktinqueueport0_reg[`REG_PKTINQUEUEPORT0_WIDTH-2:0] + pkt_stored[0]-pkt_removed[0]; + pktinqueueport0_reg[`REG_PKTINQUEUEPORT0_WIDTH-1] <= #1 clear_counters | pktinqueueport0_reg_clear ? 'h0 : pktinqueueport0_reg [`REG_PKTINQUEUEPORT0_WIDTH-2:0] + pkt_stored[0]-pkt_removed[0] > {(`REG_PKTINQUEUEPORT0_WIDTH-1){1'b1}} ? 1'b1 : pktinqueueport0_reg[`REG_PKTINQUEUEPORT0_WIDTH-1]; + //Port 1 Counters + pktstoredport1_reg[`REG_PKTSTOREDPORT1_WIDTH-2:0] <= #1 clear_counters | pktstoredport1_reg_clear ? 'h0 : pktstoredport1_reg[`REG_PKTSTOREDPORT1_WIDTH-2:0] + pkt_stored[1]; + pktstoredport1_reg[`REG_PKTSTOREDPORT1_WIDTH-1] <= #1 clear_counters | pktstoredport1_reg_clear ? 'h0 : pktstoredport1_reg [`REG_PKTSTOREDPORT1_WIDTH-2:0] + pkt_stored[1] > {(`REG_PKTSTOREDPORT1_WIDTH-1){1'b1}} ? 1'b1 : pktstoredport1_reg[`REG_PKTSTOREDPORT1_WIDTH-1]; + bytesstoredport1_reg[`REG_BYTESSTOREDPORT1_WIDTH-2:0] <= #1 clear_counters | bytesstoredport1_reg_clear ? 'h0 : bytesstoredport1_reg[`REG_BYTESSTOREDPORT1_WIDTH-2:0] + (pkt_stored[1] ? bytes_stored : 0); + bytesstoredport1_reg[`REG_BYTESSTOREDPORT1_WIDTH-1] <= #1 clear_counters | bytesstoredport1_reg_clear ? 'h0 : bytesstoredport1_reg [`REG_BYTESSTOREDPORT1_WIDTH-2:0] + (pkt_stored[1] ? bytes_stored : 0) > {(`REG_BYTESSTOREDPORT1_WIDTH-1){1'b1}} ? 1'b1 : bytesstoredport1_reg[`REG_BYTESSTOREDPORT1_WIDTH-1]; + pktremovedport1_reg[`REG_PKTREMOVEDPORT1_WIDTH-2:0] <= #1 clear_counters | pktremovedport1_reg_clear ? 'h0 : pktremovedport1_reg[`REG_PKTREMOVEDPORT1_WIDTH-2:0] + pkt_removed[1]; + pktremovedport1_reg[`REG_PKTREMOVEDPORT1_WIDTH-1] <= #1 clear_counters | pktremovedport1_reg_clear ? 'h0 : pktremovedport1_reg [`REG_PKTREMOVEDPORT1_WIDTH-2:0] + pkt_removed[1] > {(`REG_PKTREMOVEDPORT1_WIDTH-1){1'b1}} ? 1'b1 : pktremovedport1_reg[`REG_PKTREMOVEDPORT1_WIDTH-1]; + bytesremovedport1_reg[`REG_BYTESREMOVEDPORT1_WIDTH-2:0] <= #1 clear_counters | bytesremovedport1_reg_clear ? 'h0 : bytesremovedport1_reg[`REG_BYTESREMOVEDPORT1_WIDTH-2:0] + bytes_removed_1; + bytesremovedport1_reg[`REG_BYTESREMOVEDPORT1_WIDTH-1] <= #1 clear_counters | bytesremovedport1_reg_clear ? 'h0 : bytesremovedport1_reg [`REG_BYTESREMOVEDPORT1_WIDTH-2:0] + bytes_removed_1 > {(`REG_BYTESREMOVEDPORT1_WIDTH-1){1'b1}} ? 1'b1 : bytesremovedport1_reg[`REG_BYTESREMOVEDPORT1_WIDTH-1]; + pktdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-2:0] <= #1 clear_counters | pktdroppedport1_reg_clear ? 'h0 : pktdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-2:0] + pkt_dropped[1]; + pktdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-1] <= #1 clear_counters | pktdroppedport1_reg_clear ? 'h0 : pktdroppedport1_reg [`REG_PKTDROPPEDPORT1_WIDTH-2:0] + pkt_dropped[1] > {(`REG_PKTDROPPEDPORT1_WIDTH-1){1'b1}} ? 1'b1 : pktdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-1]; + bytesdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-2:0] <= #1 clear_counters | bytesdroppedport1_reg_clear ? 'h0 : bytesdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-2:0] + bytes_dropped[1]; + bytesdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-1] <= #1 clear_counters | bytesdroppedport1_reg_clear ? 'h0 : bytesdroppedport1_reg [`REG_PKTDROPPEDPORT1_WIDTH-2:0] + bytes_dropped[1] > {(`REG_PKTDROPPEDPORT1_WIDTH-1){1'b1}} ? 1'b1 : bytesdroppedport1_reg[`REG_PKTDROPPEDPORT1_WIDTH-1]; + pktinqueueport1_reg[`REG_PKTINQUEUEPORT1_WIDTH-2:0] <= #1 clear_counters | pktinqueueport1_reg_clear ? 'h0 : pktinqueueport1_reg[`REG_PKTINQUEUEPORT1_WIDTH-2:0] + pkt_stored[1]-pkt_removed[1]; + pktinqueueport1_reg[`REG_PKTINQUEUEPORT1_WIDTH-1] <= #1 clear_counters | pktinqueueport1_reg_clear ? 'h0 : pktinqueueport1_reg [`REG_PKTINQUEUEPORT1_WIDTH-2:0] + pkt_stored[1]-pkt_removed[1] > {(`REG_PKTINQUEUEPORT1_WIDTH-1){1'b1}} ? 1'b1 : pktinqueueport1_reg[`REG_PKTINQUEUEPORT1_WIDTH-1]; + //Port 2 Counters + pktstoredport2_reg[`REG_PKTSTOREDPORT2_WIDTH-2:0] <= #1 clear_counters | pktstoredport2_reg_clear ? 'h0 : pktstoredport2_reg[`REG_PKTSTOREDPORT2_WIDTH-2:0] + pkt_stored[2]; + pktstoredport2_reg[`REG_PKTSTOREDPORT2_WIDTH-1] <= #1 clear_counters | pktstoredport2_reg_clear ? 'h0 : pktstoredport2_reg [`REG_PKTSTOREDPORT2_WIDTH-2:0] + pkt_stored[2] > {(`REG_PKTSTOREDPORT2_WIDTH-1){1'b1}} ? 1'b1 : pktstoredport2_reg[`REG_PKTSTOREDPORT2_WIDTH-1]; + bytesstoredport2_reg[`REG_BYTESSTOREDPORT2_WIDTH-2:0] <= #1 clear_counters | bytesstoredport2_reg_clear ? 'h0 : bytesstoredport2_reg[`REG_BYTESSTOREDPORT2_WIDTH-2:0] + (pkt_stored[2] ? bytes_stored : 0); + bytesstoredport2_reg[`REG_BYTESSTOREDPORT2_WIDTH-1] <= #1 clear_counters | bytesstoredport2_reg_clear ? 'h0 : bytesstoredport2_reg [`REG_BYTESSTOREDPORT2_WIDTH-2:0] + (pkt_stored[2] ? bytes_stored : 0) > {(`REG_BYTESSTOREDPORT2_WIDTH-1){1'b1}} ? 1'b1 : bytesstoredport2_reg[`REG_BYTESSTOREDPORT2_WIDTH-1]; + pktremovedport2_reg[`REG_PKTREMOVEDPORT2_WIDTH-2:0] <= #1 clear_counters | pktremovedport2_reg_clear ? 'h0 : pktremovedport2_reg[`REG_PKTREMOVEDPORT2_WIDTH-2:0] + pkt_removed[2]; + pktremovedport2_reg[`REG_PKTREMOVEDPORT2_WIDTH-1] <= #1 clear_counters | pktremovedport2_reg_clear ? 'h0 : pktremovedport2_reg [`REG_PKTREMOVEDPORT2_WIDTH-2:0] + pkt_removed[2] > {(`REG_PKTREMOVEDPORT2_WIDTH-1){1'b1}} ? 1'b1 : pktremovedport2_reg[`REG_PKTREMOVEDPORT2_WIDTH-1]; + bytesremovedport2_reg[`REG_BYTESREMOVEDPORT2_WIDTH-2:0] <= #1 clear_counters | bytesremovedport2_reg_clear ? 'h0 : bytesremovedport2_reg[`REG_BYTESREMOVEDPORT2_WIDTH-2:0] + bytes_removed_2; + bytesremovedport2_reg[`REG_BYTESREMOVEDPORT2_WIDTH-1] <= #1 clear_counters | bytesremovedport2_reg_clear ? 'h0 : bytesremovedport2_reg [`REG_BYTESREMOVEDPORT2_WIDTH-2:0] + bytes_removed_2 > {(`REG_BYTESREMOVEDPORT2_WIDTH-1){1'b1}} ? 1'b1 : bytesremovedport2_reg[`REG_BYTESREMOVEDPORT2_WIDTH-1]; + pktdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-2:0] <= #1 clear_counters | pktdroppedport2_reg_clear ? 'h0 : pktdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-2:0] + pkt_dropped[2]; + pktdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-1] <= #1 clear_counters | pktdroppedport2_reg_clear ? 'h0 : pktdroppedport2_reg [`REG_PKTDROPPEDPORT2_WIDTH-2:0] + pkt_dropped[2] > {(`REG_PKTDROPPEDPORT2_WIDTH-1){1'b1}} ? 1'b1 : pktdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-1]; + bytesdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-2:0] <= #1 clear_counters | bytesdroppedport2_reg_clear ? 'h0 : bytesdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-2:0] + bytes_dropped[2]; + bytesdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-1] <= #1 clear_counters | bytesdroppedport2_reg_clear ? 'h0 : bytesdroppedport2_reg [`REG_PKTDROPPEDPORT2_WIDTH-2:0] + bytes_dropped[2] > {(`REG_PKTDROPPEDPORT2_WIDTH-1){1'b1}} ? 1'b1 : bytesdroppedport2_reg[`REG_PKTDROPPEDPORT2_WIDTH-1]; + pktinqueueport2_reg[`REG_PKTINQUEUEPORT2_WIDTH-2:0] <= #1 clear_counters | pktinqueueport2_reg_clear ? 'h0 : pktinqueueport2_reg[`REG_PKTINQUEUEPORT2_WIDTH-2:0] + pkt_stored[2]-pkt_removed[2]; + pktinqueueport2_reg[`REG_PKTINQUEUEPORT2_WIDTH-1] <= #1 clear_counters | pktinqueueport2_reg_clear ? 'h0 : pktinqueueport2_reg [`REG_PKTINQUEUEPORT2_WIDTH-2:0] + pkt_stored[2]-pkt_removed[2] > {(`REG_PKTINQUEUEPORT2_WIDTH-1){1'b1}} ? 1'b1 : pktinqueueport2_reg[`REG_PKTINQUEUEPORT2_WIDTH-1]; + + end + + + + + +endmodule diff --git a/hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs.v b/hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs.v new file mode 100644 index 0000000..4f8b0a1 --- /dev/null +++ b/hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs.v @@ -0,0 +1,824 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_queues_cpu_regs.v +// +// Module: +// output_queues_cpu_regs +// +// Description: +// This file is automatically generated with the registers towards the CPU/Software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ns/1ns +`include "output_queues_cpu_regs_defines.v" +module output_queues_cpu_regs # +( +parameter C_BASE_ADDRESS = 32'h00000000, +parameter C_S_AXI_DATA_WIDTH = 32, +parameter C_S_AXI_ADDR_WIDTH = 32 +) +( + // General ports + input clk, + input resetn, + // Global Registers + input cpu_resetn_soft, + output reg resetn_soft, + output reg resetn_sync, + + // Register ports + input [`REG_ID_BITS] id_reg, + input [`REG_VERSION_BITS] version_reg, + output reg [`REG_RESET_BITS] reset_reg, + input [`REG_FLIP_BITS] ip2cpu_flip_reg, + output reg [`REG_FLIP_BITS] cpu2ip_flip_reg, + input [`REG_DEBUG_BITS] ip2cpu_debug_reg, + output reg [`REG_DEBUG_BITS] cpu2ip_debug_reg, + input [`REG_PKTIN_BITS] pktin_reg, + output reg pktin_reg_clear, + input [`REG_PKTOUT_BITS] pktout_reg, + output reg pktout_reg_clear, + input [`REG_PKTSTOREDPORT0_BITS] pktstoredport0_reg, + output reg pktstoredport0_reg_clear, + input [`REG_BYTESSTOREDPORT0_BITS] bytesstoredport0_reg, + output reg bytesstoredport0_reg_clear, + input [`REG_PKTREMOVEDPORT0_BITS] pktremovedport0_reg, + output reg pktremovedport0_reg_clear, + input [`REG_BYTESREMOVEDPORT0_BITS] bytesremovedport0_reg, + output reg bytesremovedport0_reg_clear, + input [`REG_PKTDROPPEDPORT0_BITS] pktdroppedport0_reg, + output reg pktdroppedport0_reg_clear, + input [`REG_BYTESDROPPEDPORT0_BITS] bytesdroppedport0_reg, + output reg bytesdroppedport0_reg_clear, + input [`REG_PKTINQUEUEPORT0_BITS] pktinqueueport0_reg, + output reg pktinqueueport0_reg_clear, + input [`REG_PKTSTOREDPORT1_BITS] pktstoredport1_reg, + output reg pktstoredport1_reg_clear, + input [`REG_BYTESSTOREDPORT1_BITS] bytesstoredport1_reg, + output reg bytesstoredport1_reg_clear, + input [`REG_PKTREMOVEDPORT1_BITS] pktremovedport1_reg, + output reg pktremovedport1_reg_clear, + input [`REG_BYTESREMOVEDPORT1_BITS] bytesremovedport1_reg, + output reg bytesremovedport1_reg_clear, + input [`REG_PKTDROPPEDPORT1_BITS] pktdroppedport1_reg, + output reg pktdroppedport1_reg_clear, + input [`REG_BYTESDROPPEDPORT1_BITS] bytesdroppedport1_reg, + output reg bytesdroppedport1_reg_clear, + input [`REG_PKTINQUEUEPORT1_BITS] pktinqueueport1_reg, + output reg pktinqueueport1_reg_clear, + input [`REG_PKTSTOREDPORT2_BITS] pktstoredport2_reg, + output reg pktstoredport2_reg_clear, + input [`REG_BYTESSTOREDPORT2_BITS] bytesstoredport2_reg, + output reg bytesstoredport2_reg_clear, + input [`REG_PKTREMOVEDPORT2_BITS] pktremovedport2_reg, + output reg pktremovedport2_reg_clear, + input [`REG_BYTESREMOVEDPORT2_BITS] bytesremovedport2_reg, + output reg bytesremovedport2_reg_clear, + input [`REG_PKTDROPPEDPORT2_BITS] pktdroppedport2_reg, + output reg pktdroppedport2_reg_clear, + input [`REG_BYTESDROPPEDPORT2_BITS] bytesdroppedport2_reg, + output reg bytesdroppedport2_reg_clear, + input [`REG_PKTINQUEUEPORT2_BITS] pktinqueueport2_reg, + output reg pktinqueueport2_reg_clear, + input [`REG_PKTSTOREDPORT3_BITS] pktstoredport3_reg, + output reg pktstoredport3_reg_clear, + input [`REG_BYTESSTOREDPORT3_BITS] bytesstoredport3_reg, + output reg bytesstoredport3_reg_clear, + input [`REG_PKTREMOVEDPORT3_BITS] pktremovedport3_reg, + output reg pktremovedport3_reg_clear, + input [`REG_BYTESREMOVEDPORT3_BITS] bytesremovedport3_reg, + output reg bytesremovedport3_reg_clear, + input [`REG_PKTDROPPEDPORT3_BITS] pktdroppedport3_reg, + output reg pktdroppedport3_reg_clear, + input [`REG_BYTESDROPPEDPORT3_BITS] bytesdroppedport3_reg, + output reg bytesdroppedport3_reg_clear, + input [`REG_PKTINQUEUEPORT3_BITS] pktinqueueport3_reg, + output reg pktinqueueport3_reg_clear, + input [`REG_PKTSTOREDPORT4_BITS] pktstoredport4_reg, + output reg pktstoredport4_reg_clear, + input [`REG_BYTESSTOREDPORT4_BITS] bytesstoredport4_reg, + output reg bytesstoredport4_reg_clear, + input [`REG_PKTREMOVEDPORT4_BITS] pktremovedport4_reg, + output reg pktremovedport4_reg_clear, + input [`REG_BYTESREMOVEDPORT4_BITS] bytesremovedport4_reg, + output reg bytesremovedport4_reg_clear, + input [`REG_PKTDROPPEDPORT4_BITS] pktdroppedport4_reg, + output reg pktdroppedport4_reg_clear, + input [`REG_BYTESDROPPEDPORT4_BITS] bytesdroppedport4_reg, + output reg bytesdroppedport4_reg_clear, + input [`REG_PKTINQUEUEPORT4_BITS] pktinqueueport4_reg, + output reg pktinqueueport4_reg_clear, + + // AXI Lite ports + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 :0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY + +); + + // AXI4LITE signals + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; + reg axi_awready; + reg axi_wready; + reg [1 : 0] axi_bresp; + reg axi_bvalid; + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; + reg axi_arready; + reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; + reg [1 : 0] axi_rresp; + reg axi_rvalid; + + reg resetn_sync_d; + wire reg_rden; + wire reg_wren; + reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; + integer byte_index; + reg pktin_reg_clear_d; + reg pktout_reg_clear_d; + reg pktstoredport0_reg_clear_d; + reg bytesstoredport0_reg_clear_d; + reg pktremovedport0_reg_clear_d; + reg bytesremovedport0_reg_clear_d; + reg pktdroppedport0_reg_clear_d; + reg bytesdroppedport0_reg_clear_d; + reg pktinqueueport0_reg_clear_d; + reg pktstoredport1_reg_clear_d; + reg bytesstoredport1_reg_clear_d; + reg pktremovedport1_reg_clear_d; + reg bytesremovedport1_reg_clear_d; + reg pktdroppedport1_reg_clear_d; + reg bytesdroppedport1_reg_clear_d; + reg pktinqueueport1_reg_clear_d; + reg pktstoredport2_reg_clear_d; + reg bytesstoredport2_reg_clear_d; + reg pktremovedport2_reg_clear_d; + reg bytesremovedport2_reg_clear_d; + reg pktdroppedport2_reg_clear_d; + reg bytesdroppedport2_reg_clear_d; + reg pktinqueueport2_reg_clear_d; + reg pktstoredport3_reg_clear_d; + reg bytesstoredport3_reg_clear_d; + reg pktremovedport3_reg_clear_d; + reg bytesremovedport3_reg_clear_d; + reg pktdroppedport3_reg_clear_d; + reg bytesdroppedport3_reg_clear_d; + reg pktinqueueport3_reg_clear_d; + reg pktstoredport4_reg_clear_d; + reg bytesstoredport4_reg_clear_d; + reg pktremovedport4_reg_clear_d; + reg bytesremovedport4_reg_clear_d; + reg pktdroppedport4_reg_clear_d; + reg bytesdroppedport4_reg_clear_d; + reg pktinqueueport4_reg_clear_d; + + // I/O Connections assignments + assign S_AXI_AWREADY = axi_awready; + assign S_AXI_WREADY = axi_wready; + assign S_AXI_BRESP = axi_bresp; + assign S_AXI_BVALID = axi_bvalid; + assign S_AXI_ARREADY = axi_arready; + assign S_AXI_RDATA = axi_rdata; + assign S_AXI_RRESP = axi_rresp; + assign S_AXI_RVALID = axi_rvalid; + + + //Sample reset (not mandatory, but good practice) + always @ (posedge clk) begin + if (~resetn) begin + resetn_sync_d <= 1'b0; + resetn_sync <= 1'b0; + end + else begin + resetn_sync_d <= resetn; + resetn_sync <= resetn_sync_d; + end + end + + + //global registers, sampling + always @(posedge clk) resetn_soft <= #1 cpu_resetn_soft; + + // Implement axi_awready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awready <= 1'b0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // slave is ready to accept write address when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_awready <= 1'b1; + end + else + begin + axi_awready <= 1'b0; + end + end + end + + // Implement axi_awaddr latching + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awaddr <= 0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) + begin + // Write Address latching + axi_awaddr <= S_AXI_AWADDR ^ C_BASE_ADDRESS; + end + end + end + + // Implement axi_wready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_wready <= 1'b0; + end + else + begin + if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID) + begin + // slave is ready to accept write data when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_wready <= 1'b1; + end + else + begin + axi_wready <= 1'b0; + end + end + end + + // Implement write response logic generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_bvalid <= 0; + axi_bresp <= 2'b0; + end + else + begin + if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) + begin + // indicates a valid write response is available + axi_bvalid <= 1'b1; + axi_bresp <= 2'b0; // OKAY response + end // work error responses in future + else + begin + if (S_AXI_BREADY && axi_bvalid) + //check if bready is asserted while bvalid is high) + //(there is a possibility that bready is always asserted high) + begin + axi_bvalid <= 1'b0; + end + end + end + end + + // Implement axi_arready generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_arready <= 1'b0; + axi_araddr <= 32'b0; + end + else + begin + if (~axi_arready && S_AXI_ARVALID) + begin + // indicates that the slave has acceped the valid read address + // Read address latching + axi_arready <= 1'b1; + axi_araddr <= S_AXI_ARADDR ^ C_BASE_ADDRESS; + end + else + begin + axi_arready <= 1'b0; + end + end + end + + + // Implement axi_rvalid generation + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rvalid <= 0; + axi_rresp <= 0; + end + else + begin + if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) + begin + // Valid read data is available at the read data bus + axi_rvalid <= 1'b1; + axi_rresp <= 2'b0; // OKAY response + end + else if (axi_rvalid && S_AXI_RREADY) + begin + // Read data is accepted by the master + axi_rvalid <= 1'b0; + end + end + end + + + // Implement memory mapped register select and write logic generation + + assign reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; + +////////////////////////////////////////////////////////////// +// write registers +////////////////////////////////////////////////////////////// + + +//Write only register, clear on write (i.e. event) + always @(posedge clk) begin + if (!resetn_sync) begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + else begin + if (reg_wren) begin + case (axi_awaddr) + //Reset Register + `REG_RESET_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_RESET_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + reset_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; + end + end + endcase + end + else begin + reset_reg <= #1 `REG_RESET_DEFAULT; + end + end + end + +//R/W register, not cleared + always @(posedge clk) begin + if (!resetn_sync) begin + + cpu2ip_flip_reg <= #1 `REG_FLIP_DEFAULT; + cpu2ip_debug_reg <= #1 `REG_DEBUG_DEFAULT; + end + else begin + if (reg_wren) //write event + case (axi_awaddr) + //Flip Register + `REG_FLIP_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_FLIP_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_flip_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + //Debug Register + `REG_DEBUG_ADDR : begin + for ( byte_index = 0; byte_index <= (`REG_DEBUG_WIDTH/8-1); byte_index = byte_index +1) + if (S_AXI_WSTRB[byte_index] == 1) begin + cpu2ip_debug_reg[byte_index*8 +: 8] <= S_AXI_WDATA[byte_index*8 +: 8]; //dynamic register; + end + end + default: begin + end + + endcase + end + end + + + +///////////////////////// +//// end of write +///////////////////////// + + // Implement memory mapped register select and read logic generation + // Slave register read enable is asserted when valid address is available + // and the slave is ready to accept the read address. + + // reg_rden control logic + // temperary no extra logic here + assign reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; + + always @(*) + begin + + case ( axi_araddr /*S_AXI_ARADDR ^ C_BASE_ADDRESS*/) + //Id Register + `REG_ID_ADDR : begin + reg_data_out [`REG_ID_BITS] = id_reg; + end + //Version Register + `REG_VERSION_ADDR : begin + reg_data_out [`REG_VERSION_BITS] = version_reg; + end + //Flip Register + `REG_FLIP_ADDR : begin + reg_data_out [`REG_FLIP_BITS] = ip2cpu_flip_reg; + end + //Debug Register + `REG_DEBUG_ADDR : begin + reg_data_out [`REG_DEBUG_BITS] = ip2cpu_debug_reg; + end + //Pktin Register + `REG_PKTIN_ADDR : begin + reg_data_out [`REG_PKTIN_BITS] = pktin_reg; + end + //Pktout Register + `REG_PKTOUT_ADDR : begin + reg_data_out [`REG_PKTOUT_BITS] = pktout_reg; + end + //Pktstoredport0 Register + `REG_PKTSTOREDPORT0_ADDR : begin + reg_data_out [`REG_PKTSTOREDPORT0_BITS] = pktstoredport0_reg; + end + //Bytesstoredport0 Register + `REG_BYTESSTOREDPORT0_ADDR : begin + reg_data_out [`REG_BYTESSTOREDPORT0_BITS] = bytesstoredport0_reg; + end + //Pktremovedport0 Register + `REG_PKTREMOVEDPORT0_ADDR : begin + reg_data_out [`REG_PKTREMOVEDPORT0_BITS] = pktremovedport0_reg; + end + //Bytesremovedport0 Register + `REG_BYTESREMOVEDPORT0_ADDR : begin + reg_data_out [`REG_BYTESREMOVEDPORT0_BITS] = bytesremovedport0_reg; + end + //Pktdroppedport0 Register + `REG_PKTDROPPEDPORT0_ADDR : begin + reg_data_out [`REG_PKTDROPPEDPORT0_BITS] = pktdroppedport0_reg; + end + //Bytesdroppedport0 Register + `REG_BYTESDROPPEDPORT0_ADDR : begin + reg_data_out [`REG_BYTESDROPPEDPORT0_BITS] = bytesdroppedport0_reg; + end + //Pktinqueueport0 Register + `REG_PKTINQUEUEPORT0_ADDR : begin + reg_data_out [`REG_PKTINQUEUEPORT0_BITS] = pktinqueueport0_reg; + end + //Pktstoredport1 Register + `REG_PKTSTOREDPORT1_ADDR : begin + reg_data_out [`REG_PKTSTOREDPORT1_BITS] = pktstoredport1_reg; + end + //Bytesstoredport1 Register + `REG_BYTESSTOREDPORT1_ADDR : begin + reg_data_out [`REG_BYTESSTOREDPORT1_BITS] = bytesstoredport1_reg; + end + //Pktremovedport1 Register + `REG_PKTREMOVEDPORT1_ADDR : begin + reg_data_out [`REG_PKTREMOVEDPORT1_BITS] = pktremovedport1_reg; + end + //Bytesremovedport1 Register + `REG_BYTESREMOVEDPORT1_ADDR : begin + reg_data_out [`REG_BYTESREMOVEDPORT1_BITS] = bytesremovedport1_reg; + end + //Pktdroppedport1 Register + `REG_PKTDROPPEDPORT1_ADDR : begin + reg_data_out [`REG_PKTDROPPEDPORT1_BITS] = pktdroppedport1_reg; + end + //Bytesdroppedport1 Register + `REG_BYTESDROPPEDPORT1_ADDR : begin + reg_data_out [`REG_BYTESDROPPEDPORT1_BITS] = bytesdroppedport1_reg; + end + //Pktinqueueport1 Register + `REG_PKTINQUEUEPORT1_ADDR : begin + reg_data_out [`REG_PKTINQUEUEPORT1_BITS] = pktinqueueport1_reg; + end + //Pktstoredport2 Register + `REG_PKTSTOREDPORT2_ADDR : begin + reg_data_out [`REG_PKTSTOREDPORT2_BITS] = pktstoredport2_reg; + end + //Bytesstoredport2 Register + `REG_BYTESSTOREDPORT2_ADDR : begin + reg_data_out [`REG_BYTESSTOREDPORT2_BITS] = bytesstoredport2_reg; + end + //Pktremovedport2 Register + `REG_PKTREMOVEDPORT2_ADDR : begin + reg_data_out [`REG_PKTREMOVEDPORT2_BITS] = pktremovedport2_reg; + end + //Bytesremovedport2 Register + `REG_BYTESREMOVEDPORT2_ADDR : begin + reg_data_out [`REG_BYTESREMOVEDPORT2_BITS] = bytesremovedport2_reg; + end + //Pktdroppedport2 Register + `REG_PKTDROPPEDPORT2_ADDR : begin + reg_data_out [`REG_PKTDROPPEDPORT2_BITS] = pktdroppedport2_reg; + end + //Bytesdroppedport2 Register + `REG_BYTESDROPPEDPORT2_ADDR : begin + reg_data_out [`REG_BYTESDROPPEDPORT2_BITS] = bytesdroppedport2_reg; + end + //Pktinqueueport2 Register + `REG_PKTINQUEUEPORT2_ADDR : begin + reg_data_out [`REG_PKTINQUEUEPORT2_BITS] = pktinqueueport2_reg; + end + //Pktstoredport3 Register + `REG_PKTSTOREDPORT3_ADDR : begin + reg_data_out [`REG_PKTSTOREDPORT3_BITS] = pktstoredport3_reg; + end + //Bytesstoredport3 Register + `REG_BYTESSTOREDPORT3_ADDR : begin + reg_data_out [`REG_BYTESSTOREDPORT3_BITS] = bytesstoredport3_reg; + end + //Pktremovedport3 Register + `REG_PKTREMOVEDPORT3_ADDR : begin + reg_data_out [`REG_PKTREMOVEDPORT3_BITS] = pktremovedport3_reg; + end + //Bytesremovedport3 Register + `REG_BYTESREMOVEDPORT3_ADDR : begin + reg_data_out [`REG_BYTESREMOVEDPORT3_BITS] = bytesremovedport3_reg; + end + //Pktdroppedport3 Register + `REG_PKTDROPPEDPORT3_ADDR : begin + reg_data_out [`REG_PKTDROPPEDPORT3_BITS] = pktdroppedport3_reg; + end + //Bytesdroppedport3 Register + `REG_BYTESDROPPEDPORT3_ADDR : begin + reg_data_out [`REG_BYTESDROPPEDPORT3_BITS] = bytesdroppedport3_reg; + end + //Pktinqueueport3 Register + `REG_PKTINQUEUEPORT3_ADDR : begin + reg_data_out [`REG_PKTINQUEUEPORT3_BITS] = pktinqueueport3_reg; + end + //Pktstoredport4 Register + `REG_PKTSTOREDPORT4_ADDR : begin + reg_data_out [`REG_PKTSTOREDPORT4_BITS] = pktstoredport4_reg; + end + //Bytesstoredport4 Register + `REG_BYTESSTOREDPORT4_ADDR : begin + reg_data_out [`REG_BYTESSTOREDPORT4_BITS] = bytesstoredport4_reg; + end + //Pktremovedport4 Register + `REG_PKTREMOVEDPORT4_ADDR : begin + reg_data_out [`REG_PKTREMOVEDPORT4_BITS] = pktremovedport4_reg; + end + //Bytesremovedport4 Register + `REG_BYTESREMOVEDPORT4_ADDR : begin + reg_data_out [`REG_BYTESREMOVEDPORT4_BITS] = bytesremovedport4_reg; + end + //Pktdroppedport4 Register + `REG_PKTDROPPEDPORT4_ADDR : begin + reg_data_out [`REG_PKTDROPPEDPORT4_BITS] = pktdroppedport4_reg; + end + //Bytesdroppedport4 Register + `REG_BYTESDROPPEDPORT4_ADDR : begin + reg_data_out [`REG_BYTESDROPPEDPORT4_BITS] = bytesdroppedport4_reg; + end + //Pktinqueueport4 Register + `REG_PKTINQUEUEPORT4_ADDR : begin + reg_data_out [`REG_PKTINQUEUEPORT4_BITS] = pktinqueueport4_reg; + end + //Default return value + default: begin + reg_data_out [31:0] = 32'hDEADBEEF; + end + + endcase + + end//end of assigning data to IP2Bus_Data bus + + //Read only registers, not cleared + //Nothing to do here.... + +//Read only registers, cleared on read (e.g. counters) + always @(posedge clk) + if (!resetn_sync) begin + pktin_reg_clear <= #1 1'b0; + pktin_reg_clear_d <= #1 1'b0; + pktout_reg_clear <= #1 1'b0; + pktout_reg_clear_d <= #1 1'b0; + pktstoredport0_reg_clear <= #1 1'b0; + pktstoredport0_reg_clear_d <= #1 1'b0; + bytesstoredport0_reg_clear <= #1 1'b0; + bytesstoredport0_reg_clear_d <= #1 1'b0; + pktremovedport0_reg_clear <= #1 1'b0; + pktremovedport0_reg_clear_d <= #1 1'b0; + bytesremovedport0_reg_clear <= #1 1'b0; + bytesremovedport0_reg_clear_d <= #1 1'b0; + pktdroppedport0_reg_clear <= #1 1'b0; + pktdroppedport0_reg_clear_d <= #1 1'b0; + bytesdroppedport0_reg_clear <= #1 1'b0; + bytesdroppedport0_reg_clear_d <= #1 1'b0; + pktinqueueport0_reg_clear <= #1 1'b0; + pktinqueueport0_reg_clear_d <= #1 1'b0; + pktstoredport1_reg_clear <= #1 1'b0; + pktstoredport1_reg_clear_d <= #1 1'b0; + bytesstoredport1_reg_clear <= #1 1'b0; + bytesstoredport1_reg_clear_d <= #1 1'b0; + pktremovedport1_reg_clear <= #1 1'b0; + pktremovedport1_reg_clear_d <= #1 1'b0; + bytesremovedport1_reg_clear <= #1 1'b0; + bytesremovedport1_reg_clear_d <= #1 1'b0; + pktdroppedport1_reg_clear <= #1 1'b0; + pktdroppedport1_reg_clear_d <= #1 1'b0; + bytesdroppedport1_reg_clear <= #1 1'b0; + bytesdroppedport1_reg_clear_d <= #1 1'b0; + pktinqueueport1_reg_clear <= #1 1'b0; + pktinqueueport1_reg_clear_d <= #1 1'b0; + pktstoredport2_reg_clear <= #1 1'b0; + pktstoredport2_reg_clear_d <= #1 1'b0; + bytesstoredport2_reg_clear <= #1 1'b0; + bytesstoredport2_reg_clear_d <= #1 1'b0; + pktremovedport2_reg_clear <= #1 1'b0; + pktremovedport2_reg_clear_d <= #1 1'b0; + bytesremovedport2_reg_clear <= #1 1'b0; + bytesremovedport2_reg_clear_d <= #1 1'b0; + pktdroppedport2_reg_clear <= #1 1'b0; + pktdroppedport2_reg_clear_d <= #1 1'b0; + bytesdroppedport2_reg_clear <= #1 1'b0; + bytesdroppedport2_reg_clear_d <= #1 1'b0; + pktinqueueport2_reg_clear <= #1 1'b0; + pktinqueueport2_reg_clear_d <= #1 1'b0; + pktstoredport3_reg_clear <= #1 1'b0; + pktstoredport3_reg_clear_d <= #1 1'b0; + bytesstoredport3_reg_clear <= #1 1'b0; + bytesstoredport3_reg_clear_d <= #1 1'b0; + pktremovedport3_reg_clear <= #1 1'b0; + pktremovedport3_reg_clear_d <= #1 1'b0; + bytesremovedport3_reg_clear <= #1 1'b0; + bytesremovedport3_reg_clear_d <= #1 1'b0; + pktdroppedport3_reg_clear <= #1 1'b0; + pktdroppedport3_reg_clear_d <= #1 1'b0; + bytesdroppedport3_reg_clear <= #1 1'b0; + bytesdroppedport3_reg_clear_d <= #1 1'b0; + pktinqueueport3_reg_clear <= #1 1'b0; + pktinqueueport3_reg_clear_d <= #1 1'b0; + pktstoredport4_reg_clear <= #1 1'b0; + pktstoredport4_reg_clear_d <= #1 1'b0; + bytesstoredport4_reg_clear <= #1 1'b0; + bytesstoredport4_reg_clear_d <= #1 1'b0; + pktremovedport4_reg_clear <= #1 1'b0; + pktremovedport4_reg_clear_d <= #1 1'b0; + bytesremovedport4_reg_clear <= #1 1'b0; + bytesremovedport4_reg_clear_d <= #1 1'b0; + pktdroppedport4_reg_clear <= #1 1'b0; + pktdroppedport4_reg_clear_d <= #1 1'b0; + bytesdroppedport4_reg_clear <= #1 1'b0; + bytesdroppedport4_reg_clear_d <= #1 1'b0; + pktinqueueport4_reg_clear <= #1 1'b0; + pktinqueueport4_reg_clear_d <= #1 1'b0; + end + else begin + pktin_reg_clear <= #1 pktin_reg_clear_d; + pktin_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTIN_ADDR)) ? 1'b1 : 1'b0; + pktout_reg_clear <= #1 pktout_reg_clear_d; + pktout_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTOUT_ADDR)) ? 1'b1 : 1'b0; + pktstoredport0_reg_clear <= #1 pktstoredport0_reg_clear_d; + pktstoredport0_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTSTOREDPORT0_ADDR)) ? 1'b1 : 1'b0; + bytesstoredport0_reg_clear <= #1 bytesstoredport0_reg_clear_d; + bytesstoredport0_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESSTOREDPORT0_ADDR)) ? 1'b1 : 1'b0; + pktremovedport0_reg_clear <= #1 pktremovedport0_reg_clear_d; + pktremovedport0_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTREMOVEDPORT0_ADDR)) ? 1'b1 : 1'b0; + bytesremovedport0_reg_clear <= #1 bytesremovedport0_reg_clear_d; + bytesremovedport0_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESREMOVEDPORT0_ADDR)) ? 1'b1 : 1'b0; + pktdroppedport0_reg_clear <= #1 pktdroppedport0_reg_clear_d; + pktdroppedport0_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTDROPPEDPORT0_ADDR)) ? 1'b1 : 1'b0; + bytesdroppedport0_reg_clear <= #1 bytesdroppedport0_reg_clear_d; + bytesdroppedport0_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESDROPPEDPORT0_ADDR)) ? 1'b1 : 1'b0; + pktinqueueport0_reg_clear <= #1 pktinqueueport0_reg_clear_d; + pktinqueueport0_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTINQUEUEPORT0_ADDR)) ? 1'b1 : 1'b0; + pktstoredport1_reg_clear <= #1 pktstoredport1_reg_clear_d; + pktstoredport1_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTSTOREDPORT1_ADDR)) ? 1'b1 : 1'b0; + bytesstoredport1_reg_clear <= #1 bytesstoredport1_reg_clear_d; + bytesstoredport1_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESSTOREDPORT1_ADDR)) ? 1'b1 : 1'b0; + pktremovedport1_reg_clear <= #1 pktremovedport1_reg_clear_d; + pktremovedport1_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTREMOVEDPORT1_ADDR)) ? 1'b1 : 1'b0; + bytesremovedport1_reg_clear <= #1 bytesremovedport1_reg_clear_d; + bytesremovedport1_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESREMOVEDPORT1_ADDR)) ? 1'b1 : 1'b0; + pktdroppedport1_reg_clear <= #1 pktdroppedport1_reg_clear_d; + pktdroppedport1_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTDROPPEDPORT1_ADDR)) ? 1'b1 : 1'b0; + bytesdroppedport1_reg_clear <= #1 bytesdroppedport1_reg_clear_d; + bytesdroppedport1_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESDROPPEDPORT1_ADDR)) ? 1'b1 : 1'b0; + pktinqueueport1_reg_clear <= #1 pktinqueueport1_reg_clear_d; + pktinqueueport1_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTINQUEUEPORT1_ADDR)) ? 1'b1 : 1'b0; + pktstoredport2_reg_clear <= #1 pktstoredport2_reg_clear_d; + pktstoredport2_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTSTOREDPORT2_ADDR)) ? 1'b1 : 1'b0; + bytesstoredport2_reg_clear <= #1 bytesstoredport2_reg_clear_d; + bytesstoredport2_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESSTOREDPORT2_ADDR)) ? 1'b1 : 1'b0; + pktremovedport2_reg_clear <= #1 pktremovedport2_reg_clear_d; + pktremovedport2_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTREMOVEDPORT2_ADDR)) ? 1'b1 : 1'b0; + bytesremovedport2_reg_clear <= #1 bytesremovedport2_reg_clear_d; + bytesremovedport2_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESREMOVEDPORT2_ADDR)) ? 1'b1 : 1'b0; + pktdroppedport2_reg_clear <= #1 pktdroppedport2_reg_clear_d; + pktdroppedport2_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTDROPPEDPORT2_ADDR)) ? 1'b1 : 1'b0; + bytesdroppedport2_reg_clear <= #1 bytesdroppedport2_reg_clear_d; + bytesdroppedport2_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESDROPPEDPORT2_ADDR)) ? 1'b1 : 1'b0; + pktinqueueport2_reg_clear <= #1 pktinqueueport2_reg_clear_d; + pktinqueueport2_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTINQUEUEPORT2_ADDR)) ? 1'b1 : 1'b0; + pktstoredport3_reg_clear <= #1 pktstoredport3_reg_clear_d; + pktstoredport3_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTSTOREDPORT3_ADDR)) ? 1'b1 : 1'b0; + bytesstoredport3_reg_clear <= #1 bytesstoredport3_reg_clear_d; + bytesstoredport3_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESSTOREDPORT3_ADDR)) ? 1'b1 : 1'b0; + pktremovedport3_reg_clear <= #1 pktremovedport3_reg_clear_d; + pktremovedport3_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTREMOVEDPORT3_ADDR)) ? 1'b1 : 1'b0; + bytesremovedport3_reg_clear <= #1 bytesremovedport3_reg_clear_d; + bytesremovedport3_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESREMOVEDPORT3_ADDR)) ? 1'b1 : 1'b0; + pktdroppedport3_reg_clear <= #1 pktdroppedport3_reg_clear_d; + pktdroppedport3_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTDROPPEDPORT3_ADDR)) ? 1'b1 : 1'b0; + bytesdroppedport3_reg_clear <= #1 bytesdroppedport3_reg_clear_d; + bytesdroppedport3_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESDROPPEDPORT3_ADDR)) ? 1'b1 : 1'b0; + pktinqueueport3_reg_clear <= #1 pktinqueueport3_reg_clear_d; + pktinqueueport3_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTINQUEUEPORT3_ADDR)) ? 1'b1 : 1'b0; + pktstoredport4_reg_clear <= #1 pktstoredport4_reg_clear_d; + pktstoredport4_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTSTOREDPORT4_ADDR)) ? 1'b1 : 1'b0; + bytesstoredport4_reg_clear <= #1 bytesstoredport4_reg_clear_d; + bytesstoredport4_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESSTOREDPORT4_ADDR)) ? 1'b1 : 1'b0; + pktremovedport4_reg_clear <= #1 pktremovedport4_reg_clear_d; + pktremovedport4_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTREMOVEDPORT4_ADDR)) ? 1'b1 : 1'b0; + bytesremovedport4_reg_clear <= #1 bytesremovedport4_reg_clear_d; + bytesremovedport4_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESREMOVEDPORT4_ADDR)) ? 1'b1 : 1'b0; + pktdroppedport4_reg_clear <= #1 pktdroppedport4_reg_clear_d; + pktdroppedport4_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTDROPPEDPORT4_ADDR)) ? 1'b1 : 1'b0; + bytesdroppedport4_reg_clear <= #1 bytesdroppedport4_reg_clear_d; + bytesdroppedport4_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_BYTESDROPPEDPORT4_ADDR)) ? 1'b1 : 1'b0; + pktinqueueport4_reg_clear <= #1 pktinqueueport4_reg_clear_d; + pktinqueueport4_reg_clear_d <= #1(reg_rden && (axi_araddr==`REG_PKTINQUEUEPORT4_ADDR)) ? 1'b1 : 1'b0; + end + + +// Output register or memory read data + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rdata <= 0; + end + else + begin + // When there is a valid read address (S_AXI_ARVALID) with + // acceptance of read address by the slave (axi_arready), + // output the read dada + if (reg_rden) + begin + axi_rdata <= reg_data_out/*ip2bus_data*/; // register read data /* some new changes here */ + end + end + end +endmodule diff --git a/hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs_defines.v b/hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs_defines.v new file mode 100644 index 0000000..22c77eb --- /dev/null +++ b/hw/lib/std/output_queues_v1_0_0/hdl/output_queues_cpu_regs_defines.v @@ -0,0 +1,248 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_queues_cpu_regs_defines.v +// +// Module: +// output_queues_cpu_regs_defines +// +// Description: +// This file is automatically generated with the registers defintions towards the CPU/Software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + + `define REG_ID_BITS 31:0 + `define REG_ID_WIDTH 32 + `define REG_ID_DEFAULT 32'h0000DA03 + `define REG_ID_ADDR 32'h0 + + `define REG_VERSION_BITS 31:0 + `define REG_VERSION_WIDTH 32 + `define REG_VERSION_DEFAULT 32'h1 + `define REG_VERSION_ADDR 32'h4 + + `define REG_RESET_BITS 15:0 + `define REG_RESET_WIDTH 16 + `define REG_RESET_DEFAULT 16'h0 + `define REG_RESET_ADDR 32'h8 + + `define REG_FLIP_BITS 31:0 + `define REG_FLIP_WIDTH 32 + `define REG_FLIP_DEFAULT 32'h0 + `define REG_FLIP_ADDR 32'hC + + `define REG_DEBUG_BITS 31:0 + `define REG_DEBUG_WIDTH 32 + `define REG_DEBUG_DEFAULT 32'h0 + `define REG_DEBUG_ADDR 32'h10 + + `define REG_PKTIN_BITS 31:0 + `define REG_PKTIN_WIDTH 32 + `define REG_PKTIN_DEFAULT 32'h0 + `define REG_PKTIN_ADDR 32'h14 + + `define REG_PKTOUT_BITS 31:0 + `define REG_PKTOUT_WIDTH 32 + `define REG_PKTOUT_DEFAULT 32'h0 + `define REG_PKTOUT_ADDR 32'h18 + + `define REG_PKTSTOREDPORT0_BITS 31:0 + `define REG_PKTSTOREDPORT0_WIDTH 32 + `define REG_PKTSTOREDPORT0_DEFAULT 32'h0 + `define REG_PKTSTOREDPORT0_ADDR 32'h1C + + `define REG_BYTESSTOREDPORT0_BITS 31:0 + `define REG_BYTESSTOREDPORT0_WIDTH 32 + `define REG_BYTESSTOREDPORT0_DEFAULT 32'h0 + `define REG_BYTESSTOREDPORT0_ADDR 32'h20 + + `define REG_PKTREMOVEDPORT0_BITS 31:0 + `define REG_PKTREMOVEDPORT0_WIDTH 32 + `define REG_PKTREMOVEDPORT0_DEFAULT 32'h0 + `define REG_PKTREMOVEDPORT0_ADDR 32'h24 + + `define REG_BYTESREMOVEDPORT0_BITS 31:0 + `define REG_BYTESREMOVEDPORT0_WIDTH 32 + `define REG_BYTESREMOVEDPORT0_DEFAULT 32'h0 + `define REG_BYTESREMOVEDPORT0_ADDR 32'h28 + + `define REG_PKTDROPPEDPORT0_BITS 31:0 + `define REG_PKTDROPPEDPORT0_WIDTH 32 + `define REG_PKTDROPPEDPORT0_DEFAULT 32'h0 + `define REG_PKTDROPPEDPORT0_ADDR 32'h2C + + `define REG_BYTESDROPPEDPORT0_BITS 31:0 + `define REG_BYTESDROPPEDPORT0_WIDTH 32 + `define REG_BYTESDROPPEDPORT0_DEFAULT 32'h0 + `define REG_BYTESDROPPEDPORT0_ADDR 32'h30 + + `define REG_PKTINQUEUEPORT0_BITS 31:0 + `define REG_PKTINQUEUEPORT0_WIDTH 32 + `define REG_PKTINQUEUEPORT0_DEFAULT 32'h0 + `define REG_PKTINQUEUEPORT0_ADDR 32'h34 + + `define REG_PKTSTOREDPORT1_BITS 31:0 + `define REG_PKTSTOREDPORT1_WIDTH 32 + `define REG_PKTSTOREDPORT1_DEFAULT 32'h0 + `define REG_PKTSTOREDPORT1_ADDR 32'h38 + + `define REG_BYTESSTOREDPORT1_BITS 31:0 + `define REG_BYTESSTOREDPORT1_WIDTH 32 + `define REG_BYTESSTOREDPORT1_DEFAULT 32'h0 + `define REG_BYTESSTOREDPORT1_ADDR 32'h3C + + `define REG_PKTREMOVEDPORT1_BITS 31:0 + `define REG_PKTREMOVEDPORT1_WIDTH 32 + `define REG_PKTREMOVEDPORT1_DEFAULT 32'h0 + `define REG_PKTREMOVEDPORT1_ADDR 32'h40 + + `define REG_BYTESREMOVEDPORT1_BITS 31:0 + `define REG_BYTESREMOVEDPORT1_WIDTH 32 + `define REG_BYTESREMOVEDPORT1_DEFAULT 32'h0 + `define REG_BYTESREMOVEDPORT1_ADDR 32'h44 + + `define REG_PKTDROPPEDPORT1_BITS 31:0 + `define REG_PKTDROPPEDPORT1_WIDTH 32 + `define REG_PKTDROPPEDPORT1_DEFAULT 32'h0 + `define REG_PKTDROPPEDPORT1_ADDR 32'h48 + + `define REG_BYTESDROPPEDPORT1_BITS 31:0 + `define REG_BYTESDROPPEDPORT1_WIDTH 32 + `define REG_BYTESDROPPEDPORT1_DEFAULT 32'h0 + `define REG_BYTESDROPPEDPORT1_ADDR 32'h4C + + `define REG_PKTINQUEUEPORT1_BITS 31:0 + `define REG_PKTINQUEUEPORT1_WIDTH 32 + `define REG_PKTINQUEUEPORT1_DEFAULT 32'h0 + `define REG_PKTINQUEUEPORT1_ADDR 32'h50 + + `define REG_PKTSTOREDPORT2_BITS 31:0 + `define REG_PKTSTOREDPORT2_WIDTH 32 + `define REG_PKTSTOREDPORT2_DEFAULT 32'h0 + `define REG_PKTSTOREDPORT2_ADDR 32'h54 + + `define REG_BYTESSTOREDPORT2_BITS 31:0 + `define REG_BYTESSTOREDPORT2_WIDTH 32 + `define REG_BYTESSTOREDPORT2_DEFAULT 32'h0 + `define REG_BYTESSTOREDPORT2_ADDR 32'h58 + + `define REG_PKTREMOVEDPORT2_BITS 31:0 + `define REG_PKTREMOVEDPORT2_WIDTH 32 + `define REG_PKTREMOVEDPORT2_DEFAULT 32'h0 + `define REG_PKTREMOVEDPORT2_ADDR 32'h5C + + `define REG_BYTESREMOVEDPORT2_BITS 31:0 + `define REG_BYTESREMOVEDPORT2_WIDTH 32 + `define REG_BYTESREMOVEDPORT2_DEFAULT 32'h0 + `define REG_BYTESREMOVEDPORT2_ADDR 32'h60 + + `define REG_PKTDROPPEDPORT2_BITS 31:0 + `define REG_PKTDROPPEDPORT2_WIDTH 32 + `define REG_PKTDROPPEDPORT2_DEFAULT 32'h0 + `define REG_PKTDROPPEDPORT2_ADDR 32'h64 + + `define REG_BYTESDROPPEDPORT2_BITS 31:0 + `define REG_BYTESDROPPEDPORT2_WIDTH 32 + `define REG_BYTESDROPPEDPORT2_DEFAULT 32'h0 + `define REG_BYTESDROPPEDPORT2_ADDR 32'h68 + + `define REG_PKTINQUEUEPORT2_BITS 31:0 + `define REG_PKTINQUEUEPORT2_WIDTH 32 + `define REG_PKTINQUEUEPORT2_DEFAULT 32'h0 + `define REG_PKTINQUEUEPORT2_ADDR 32'h6C + + `define REG_PKTSTOREDPORT3_BITS 31:0 + `define REG_PKTSTOREDPORT3_WIDTH 32 + `define REG_PKTSTOREDPORT3_DEFAULT 32'h0 + `define REG_PKTSTOREDPORT3_ADDR 32'h70 + + `define REG_BYTESSTOREDPORT3_BITS 31:0 + `define REG_BYTESSTOREDPORT3_WIDTH 32 + `define REG_BYTESSTOREDPORT3_DEFAULT 32'h0 + `define REG_BYTESSTOREDPORT3_ADDR 32'h74 + + `define REG_PKTREMOVEDPORT3_BITS 31:0 + `define REG_PKTREMOVEDPORT3_WIDTH 32 + `define REG_PKTREMOVEDPORT3_DEFAULT 32'h0 + `define REG_PKTREMOVEDPORT3_ADDR 32'h78 + + `define REG_BYTESREMOVEDPORT3_BITS 31:0 + `define REG_BYTESREMOVEDPORT3_WIDTH 32 + `define REG_BYTESREMOVEDPORT3_DEFAULT 32'h0 + `define REG_BYTESREMOVEDPORT3_ADDR 32'h7C + + `define REG_PKTDROPPEDPORT3_BITS 31:0 + `define REG_PKTDROPPEDPORT3_WIDTH 32 + `define REG_PKTDROPPEDPORT3_DEFAULT 32'h0 + `define REG_PKTDROPPEDPORT3_ADDR 32'h80 + + `define REG_BYTESDROPPEDPORT3_BITS 31:0 + `define REG_BYTESDROPPEDPORT3_WIDTH 32 + `define REG_BYTESDROPPEDPORT3_DEFAULT 32'h0 + `define REG_BYTESDROPPEDPORT3_ADDR 32'h84 + + `define REG_PKTINQUEUEPORT3_BITS 31:0 + `define REG_PKTINQUEUEPORT3_WIDTH 32 + `define REG_PKTINQUEUEPORT3_DEFAULT 32'h0 + `define REG_PKTINQUEUEPORT3_ADDR 32'h88 + + `define REG_PKTSTOREDPORT4_BITS 31:0 + `define REG_PKTSTOREDPORT4_WIDTH 32 + `define REG_PKTSTOREDPORT4_DEFAULT 32'h0 + `define REG_PKTSTOREDPORT4_ADDR 32'h8C + + `define REG_BYTESSTOREDPORT4_BITS 31:0 + `define REG_BYTESSTOREDPORT4_WIDTH 32 + `define REG_BYTESSTOREDPORT4_DEFAULT 32'h0 + `define REG_BYTESSTOREDPORT4_ADDR 32'h90 + + `define REG_PKTREMOVEDPORT4_BITS 31:0 + `define REG_PKTREMOVEDPORT4_WIDTH 32 + `define REG_PKTREMOVEDPORT4_DEFAULT 32'h0 + `define REG_PKTREMOVEDPORT4_ADDR 32'h94 + + `define REG_BYTESREMOVEDPORT4_BITS 31:0 + `define REG_BYTESREMOVEDPORT4_WIDTH 32 + `define REG_BYTESREMOVEDPORT4_DEFAULT 32'h0 + `define REG_BYTESREMOVEDPORT4_ADDR 32'h98 + + `define REG_PKTDROPPEDPORT4_BITS 31:0 + `define REG_PKTDROPPEDPORT4_WIDTH 32 + `define REG_PKTDROPPEDPORT4_DEFAULT 32'h0 + `define REG_PKTDROPPEDPORT4_ADDR 32'h9C + + `define REG_BYTESDROPPEDPORT4_BITS 31:0 + `define REG_BYTESDROPPEDPORT4_WIDTH 32 + `define REG_BYTESDROPPEDPORT4_DEFAULT 32'h0 + `define REG_BYTESDROPPEDPORT4_ADDR 32'hA0 + + `define REG_PKTINQUEUEPORT4_BITS 31:0 + `define REG_PKTINQUEUEPORT4_WIDTH 32 + `define REG_PKTINQUEUEPORT4_DEFAULT 32'h0 + `define REG_PKTINQUEUEPORT4_ADDR 32'hA4 diff --git a/hw/lib/std/output_queues_v1_0_0/output_queues.tcl b/hw/lib/std/output_queues_v1_0_0/output_queues.tcl new file mode 100644 index 0000000..9ed102c --- /dev/null +++ b/hw/lib/std/output_queues_v1_0_0/output_queues.tcl @@ -0,0 +1,146 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design output_queues +set top output_queues +set device $::env(DEVICE) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +puts "Creating Output Queues IP" +##################################### +# Project Structure & IP Build +##################################### +read_verilog "./hdl/output_queues_cpu_regs_defines.v" +read_verilog "./hdl/output_queues_cpu_regs.v" +read_verilog "./hdl/output_queues.v" + +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::add_user_parameter {C_M_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property display_name {C_M_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property display_name {C_S_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property display_name {C_M_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property display_name {C_S_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {NUM_QUEUES} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters NUM_QUEUES] +set_property display_name {NUM_QUEUES} [ipx::get_user_parameters NUM_QUEUES] +set_property value {3} [ipx::get_user_parameters NUM_QUEUES] +set_property value_format {long} [ipx::get_user_parameters NUM_QUEUES] + +ipx::add_user_parameter {C_S_AXI_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property display_name {C_S_AXI_DATA_WIDTH} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXI_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property display_name {C_S_AXI_ADDR_WIDTH} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] + +ipx::add_user_parameter {C_BASEADDR} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_BASEADDR] +set_property display_name {C_BASEADDR} [ipx::get_user_parameters C_BASEADDR] +set_property value {0x00000000} [ipx::get_user_parameters C_BASEADDR] +set_property value_format {bitstring} [ipx::get_user_parameters C_BASEADDR] + +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] + +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis_0 -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis_1 -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis_2 -of_objects [ipx::current_core]] +#ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis_3 -of_objects [ipx::current_core]] +#ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis_4 -of_objects [ipx::current_core]] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + +file delete -force ${proj_dir} + + + + + + + + + + + diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/Makefile b/hw/lib/std/router_output_port_lookup_v1_0_0/Makefile new file mode 100755 index 0000000..e97871e --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/Makefile @@ -0,0 +1,32 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source router_output_port_lookup.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip hdl/axi_lite_ipif/ diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h b/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h new file mode 100755 index 0000000..3b5b9af --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h @@ -0,0 +1,148 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.h +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +##########This text should be copied to the head file ############# + #Registers offset definitions + +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_OFFSET 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_DEFAULT 0x0000DA01 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_OFFSET 0x4 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_DEFAULT 0x1 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_OFFSET 0x8 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_WIDTH 16 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_OFFSET 0xC +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_OFFSET 0x10 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_FROM_CPU_CNTR_0_OFFSET 0x14 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_FROM_CPU_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_FROM_CPU_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_0_OFFSET 0x18 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_BAD_TTL_CNTR_0_OFFSET 0x1C +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_BAD_TTL_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_BAD_TTL_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_0_OFFSET 0x20 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_FORWARDED_CNTR_0_OFFSET 0x24 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_FORWARDED_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_FORWARDED_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_DROPPED_CHECKSUM_CNTR_0_OFFSET 0x28 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_DROPPED_CHECKSUM_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_DROPPED_CHECKSUM_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_NON_IP_CNTR_0_OFFSET 0x2C +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_NON_IP_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_NON_IP_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_ARP_MISS_CNTR_0_OFFSET 0x30 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_ARP_MISS_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_ARP_MISS_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_LPM_MISS_CNTR_0_OFFSET 0x34 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_LPM_MISS_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_SENT_TO_CPU_LPM_MISS_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_DROPPED_WRONG_DST_MAC_CNTR_0_OFFSET 0x38 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_DROPPED_WRONG_DST_MAC_CNTR_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKT_DROPPED_WRONG_DST_MAC_CNTR_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_0_HI_0_OFFSET 0x3C +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_0_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_0_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_0_LOW_0_OFFSET 0x40 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_0_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_0_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_1_HI_0_OFFSET 0x44 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_1_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_1_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_1_LOW_0_OFFSET 0x48 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_1_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_1_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_2_HI_0_OFFSET 0x4C +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_2_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_2_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_2_LOW_0_OFFSET 0x50 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_2_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_2_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_3_HI_0_OFFSET 0x54 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_3_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_3_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_3_LOW_0_OFFSET 0x58 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_3_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MAC_3_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTADDRESS_0_OFFSET 0x5C +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTADDRESS_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTADDRESS_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_A_HI_0_OFFSET 0x60 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_A_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_A_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_A_LOW_0_OFFSET 0x64 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_A_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_A_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_B_HI_0_OFFSET 0x68 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_B_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_B_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_B_LOW_0_OFFSET 0x6C +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_B_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTWRDATA_B_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_A_HI_0_OFFSET 0x70 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_A_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_A_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_A_LOW_0_OFFSET 0x74 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_A_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_A_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_B_HI_0_OFFSET 0x78 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_B_HI_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_B_HI_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_B_LOW_0_OFFSET 0x7C +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_B_LOW_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTREPLY_B_LOW_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTCOMMAND_0_OFFSET 0x80 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTCOMMAND_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTCOMMAND_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTCONFIG_0_OFFSET 0x84 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTCONFIG_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_INDIRECTCONFIG_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_IP_LPM_TCAM_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_IP_LPM_TCAM_0_DEPTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_IP_LPM_TCAM_0_ADDRESS 0x00000000 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_IP_ARP_CAM_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_IP_ARP_CAM_0_DEPTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_IP_ARP_CAM_0_ADDRESS 0x10000000 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_DEST_IP_CAM_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_DEST_IP_CAM_0_DEPTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_MEM_DEST_IP_CAM_0_ADDRESS 0x20000000 diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl b/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl new file mode 100755 index 0000000..29dfec6 --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl @@ -0,0 +1,145 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# +# File: +# output_port_lookup_regs_defines.tcl +# +# Description: +# This file is automatically generated with tcl defines for the software +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +set OUTPUT_PORT_LOOKUP_REGS_ID_0_OFFSET 0x0 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_DEFAULT 0x0000DA01 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_OFFSET 0x4 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_DEFAULT 0x1 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_OFFSET 0x8 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_WIDTH 16 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_OFFSET 0xC +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_OFFSET 0x10 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_FROM_CPU_CNTR_0_OFFSET 0x14 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_FROM_CPU_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_FROM_CPU_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_0_OFFSET 0x18 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_BAD_TTL_CNTR_0_OFFSET 0x1C +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_BAD_TTL_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_BAD_TTL_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_0_OFFSET 0x20 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_FORWARDED_CNTR_0_OFFSET 0x24 +set OUTPUT_PORT_LOOKUP_REGS_PKT_FORWARDED_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_FORWARDED_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_DROPPED_CHECKSUM_CNTR_0_OFFSET 0x28 +set OUTPUT_PORT_LOOKUP_REGS_PKT_DROPPED_CHECKSUM_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_DROPPED_CHECKSUM_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_NON_IP_CNTR_0_OFFSET 0x2C +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_NON_IP_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_NON_IP_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_ARP_MISS_CNTR_0_OFFSET 0x30 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_ARP_MISS_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_ARP_MISS_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_LPM_MISS_CNTR_0_OFFSET 0x34 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_LPM_MISS_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_SENT_TO_CPU_LPM_MISS_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKT_DROPPED_WRONG_DST_MAC_CNTR_0_OFFSET 0x38 +set OUTPUT_PORT_LOOKUP_REGS_PKT_DROPPED_WRONG_DST_MAC_CNTR_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKT_DROPPED_WRONG_DST_MAC_CNTR_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_0_HI_0_OFFSET 0x3C +set OUTPUT_PORT_LOOKUP_REGS_MAC_0_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_0_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_0_LOW_0_OFFSET 0x40 +set OUTPUT_PORT_LOOKUP_REGS_MAC_0_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_0_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_1_HI_0_OFFSET 0x44 +set OUTPUT_PORT_LOOKUP_REGS_MAC_1_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_1_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_1_LOW_0_OFFSET 0x48 +set OUTPUT_PORT_LOOKUP_REGS_MAC_1_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_1_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_2_HI_0_OFFSET 0x4C +set OUTPUT_PORT_LOOKUP_REGS_MAC_2_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_2_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_2_LOW_0_OFFSET 0x50 +set OUTPUT_PORT_LOOKUP_REGS_MAC_2_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_2_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_3_HI_0_OFFSET 0x54 +set OUTPUT_PORT_LOOKUP_REGS_MAC_3_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_3_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_MAC_3_LOW_0_OFFSET 0x58 +set OUTPUT_PORT_LOOKUP_REGS_MAC_3_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_MAC_3_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTADDRESS_0_OFFSET 0x5C +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTADDRESS_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTADDRESS_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_A_HI_0_OFFSET 0x60 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_A_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_A_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_A_LOW_0_OFFSET 0x64 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_A_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_A_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_B_HI_0_OFFSET 0x68 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_B_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_B_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_B_LOW_0_OFFSET 0x6C +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_B_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTWRDATA_B_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_A_HI_0_OFFSET 0x70 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_A_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_A_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_A_LOW_0_OFFSET 0x74 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_A_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_A_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_B_HI_0_OFFSET 0x78 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_B_HI_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_B_HI_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_B_LOW_0_OFFSET 0x7C +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_B_LOW_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTREPLY_B_LOW_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTCOMMAND_0_OFFSET 0x80 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTCOMMAND_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTCOMMAND_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTCONFIG_0_OFFSET 0x84 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTCONFIG_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_INDIRECTCONFIG_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_MEM_IP_LPM_TCAM_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_MEM_IP_LPM_TCAM_0_DEPTH 32 +set OUTPUT_PORT_LOOKUP_MEM_IP_LPM_TCAM_0_ADDRESS 0x00000000 +set OUTPUT_PORT_LOOKUP_MEM_IP_ARP_CAM_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_MEM_IP_ARP_CAM_0_DEPTH 32 +set OUTPUT_PORT_LOOKUP_MEM_IP_ARP_CAM_0_ADDRESS 0x10000000 +set OUTPUT_PORT_LOOKUP_MEM_DEST_IP_CAM_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_MEM_DEST_IP_CAM_0_DEPTH 32 +set OUTPUT_PORT_LOOKUP_MEM_DEST_IP_CAM_0_ADDRESS 0x20000000 diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt b/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt new file mode 100755 index 0000000..291c4a7 --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt @@ -0,0 +1,145 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.txt +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +#define NFPLUS OUTPUT_PORT_LOOKUP ID OFFSET 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP ID DEFAULT 0x0000DA01 +#define NFPLUS OUTPUT_PORT_LOOKUP ID WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION OFFSET 0x4 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION DEFAULT 0x1 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET OFFSET 0x8 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET WIDTH 16 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP OFFSET 0xC +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG OFFSET 0x10 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_FROM_CPU_CNTR OFFSET 0x14 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_FROM_CPU_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_FROM_CPU_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_OPTIONS_VER_CNTR OFFSET 0x18 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_OPTIONS_VER_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_OPTIONS_VER_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_BAD_TTL_CNTR OFFSET 0x1C +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_BAD_TTL_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_BAD_TTL_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR OFFSET 0x20 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_FORWARDED_CNTR OFFSET 0x24 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_FORWARDED_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_FORWARDED_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_DROPPED_CHECKSUM_CNTR OFFSET 0x28 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_DROPPED_CHECKSUM_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_DROPPED_CHECKSUM_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_NON_IP_CNTR OFFSET 0x2C +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_NON_IP_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_NON_IP_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_ARP_MISS_CNTR OFFSET 0x30 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_ARP_MISS_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_ARP_MISS_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_LPM_MISS_CNTR OFFSET 0x34 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_LPM_MISS_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_SENT_TO_CPU_LPM_MISS_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_DROPPED_WRONG_DST_MAC_CNTR OFFSET 0x38 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_DROPPED_WRONG_DST_MAC_CNTR DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKT_DROPPED_WRONG_DST_MAC_CNTR WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_0_HI OFFSET 0x3C +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_0_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_0_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_0_LOW OFFSET 0x40 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_0_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_0_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_1_HI OFFSET 0x44 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_1_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_1_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_1_LOW OFFSET 0x48 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_1_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_1_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_2_HI OFFSET 0x4C +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_2_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_2_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_2_LOW OFFSET 0x50 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_2_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_2_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_3_HI OFFSET 0x54 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_3_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_3_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_3_LOW OFFSET 0x58 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_3_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP MAC_3_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTADDRESS OFFSET 0x5C +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTADDRESS DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTADDRESS WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_A_HI OFFSET 0x60 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_A_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_A_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_A_LOW OFFSET 0x64 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_A_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_A_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_B_HI OFFSET 0x68 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_B_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_B_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_B_LOW OFFSET 0x6C +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_B_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTWRDATA_B_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_A_HI OFFSET 0x70 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_A_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_A_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_A_LOW OFFSET 0x74 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_A_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_A_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_B_HI OFFSET 0x78 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_B_HI DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_B_HI WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_B_LOW OFFSET 0x7C +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_B_LOW DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTREPLY_B_LOW WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTCOMMAND OFFSET 0x80 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTCOMMAND DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTCOMMAND WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTCONFIG OFFSET 0x84 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTCONFIG DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP INDIRECTCONFIG WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_IP_LPM_TCAM WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_IP_LPM_TCAM DEPTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_IP_LPM_TCAM ADDRESS 0x00000000 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_IP_ARP_CAM WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_IP_ARP_CAM DEPTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_IP_ARP_CAM ADDRESS 0x10000000 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_DEST_IP_CAM WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_DEST_IP_CAM DEPTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP MEM_DEST_IP_CAM ADDRESS 0x20000000 diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/dest_ip_filter.v b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/dest_ip_filter.v new file mode 100755 index 0000000..78c26eb --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/dest_ip_filter.v @@ -0,0 +1,361 @@ +/******************************************************************************* +* +* Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +* Junior University +* Copyright (C) grg, Gianni Antichi +* Copyright (C) 2021 Yuta Tokusashi +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme, +* and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +* EP/P025374/1 alongside support from Xilinx Inc. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +* +*******************************************************************************/ + + + module dest_ip_filter + #(parameter C_S_AXIS_DATA_WIDTH = 512, + parameter LUT_DEPTH = 32, + parameter LUT_DEPTH_BITS = log2(LUT_DEPTH) + ) + (// --- Interface to the previous stage + input [C_S_AXIS_DATA_WIDTH-1:0] tdata, + + // --- Interface to process block + output dest_ip_hit, + output dest_ip_filter_vld, + input rd_dest_ip_filter_result, + + // --- Interface to preprocess block + input word_IP_DST_HI, + input word_IP_DST_LO, + + // --- Interface to registers + // --- Read port + input [LUT_DEPTH_BITS-1:0] dest_ip_filter_rd_addr, // address in table to read + input dest_ip_filter_rd_req, // request a read + output [31:0] dest_ip_filter_rd_ip, // ip to match in the CAM + output dest_ip_filter_rd_ack, // pulses high + + // --- Write port + input [LUT_DEPTH_BITS-1:0] dest_ip_filter_wr_addr, + input dest_ip_filter_wr_req, + input [31:0] dest_ip_filter_wr_ip, // data to match in the CAM + output dest_ip_filter_wr_ack, + + // --- Misc + input reset, + input clk + ); + + + localparam DEST_IP_POS = C_S_AXIS_DATA_WIDTH - 240; + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2= 512) begin + always @(posedge clk) begin + if(reset) begin + dst_ip <= 0; + dst_ip_vld <= 0; + end else begin + if(word_IP_DST_HI) begin + dst_ip[31:0] <= tdata[DEST_IP_POS-1:DEST_IP_POS-32]; // Big endian + dst_ip_vld <= 1; + end else begin + dst_ip_vld <= 0; + end + end // else: !if(reset) + end // always @ (posedge clk) + end + endgenerate + +endmodule // dest_ip_filter + + + diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/eth_parser.v b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/eth_parser.v new file mode 100755 index 0000000..cdb4e26 --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/eth_parser.v @@ -0,0 +1,312 @@ +/******************************************************************************* +* +* Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +* Junior University +* Copyright (C) 2010, 2011 Muhammad Shahbaz +* Copyright (C) 2015 Gianni Antichi +* Copyright (C) 2021 Yuta Tokusashi +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme, +* and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +* EP/P025374/1 alongside support from Xilinx Inc. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +* +********************************************************************************/ + + + module eth_parser + #(parameter C_S_AXIS_DATA_WIDTH = 512, + parameter NUM_QUEUES = 8, + parameter NUM_QUEUES_WIDTH = log2(NUM_QUEUES) + ) + (// --- Interface to the previous stage + input [C_S_AXIS_DATA_WIDTH-1:0] tdata, + + // --- Interface to process block + output is_arp_pkt, + output is_ip_pkt, + output is_for_us, + output is_broadcast, + output [NUM_QUEUES_WIDTH-1:0] mac_dst_port_num, + input eth_parser_rd_info, + output eth_parser_info_vld, + + // --- Interface to preprocess block + input word_IP_DST_HI, + + // --- Interface to registers + input [47:0] mac_0, // address of rx queue 0 + input [47:0] mac_1, // address of rx queue 1 + input [47:0] mac_2, // address of rx queue 2 + input [47:0] mac_3, // address of rx queue 3 + + // --- Misc + + input reset, + input clk + ); + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2= 512) begin + assign cksm_temp = cksm_sum_0 + cksm_sum_1; + assign cksm_temp2 = cksm_sum_2 + cksm_sum_3; + + always @(*) begin + checksum_next = checksum; + cksm_sum_0_next = cksm_sum_0; + cksm_sum_1_next = cksm_sum_1; + cksm_sum_2_next = cksm_sum_2; + cksm_sum_3_next = cksm_sum_3; + if(word_IP_DST_HI) begin + cksm_sum_0_next = tdata[C_S_AXIS_DATA_WIDTH-112-1:C_S_AXIS_DATA_WIDTH-128]+tdata[C_S_AXIS_DATA_WIDTH-128-1:C_S_AXIS_DATA_WIDTH-144]+tdata[C_S_AXIS_DATA_WIDTH-144-1:C_S_AXIS_DATA_WIDTH-160]; + cksm_sum_1_next = tdata[C_S_AXIS_DATA_WIDTH-160-1:C_S_AXIS_DATA_WIDTH-176]+tdata[C_S_AXIS_DATA_WIDTH-176-1:C_S_AXIS_DATA_WIDTH-192]; + cksm_sum_2_next = tdata[C_S_AXIS_DATA_WIDTH-192-1:C_S_AXIS_DATA_WIDTH-208]+tdata[C_S_AXIS_DATA_WIDTH-208-1:C_S_AXIS_DATA_WIDTH-224]; + cksm_sum_3_next = tdata[C_S_AXIS_DATA_WIDTH-224-1:C_S_AXIS_DATA_WIDTH-240]+tdata[C_S_AXIS_DATA_WIDTH-240-1:C_S_AXIS_DATA_WIDTH-256] + tdata[C_S_AXIS_DATA_WIDTH-256-1:C_S_AXIS_DATA_WIDTH-272]; + end + if (add_carry_d0) begin + checksum_next = cksm_temp + cksm_temp2; + end + if(add_carry) begin + checksum_next = checksum[19:16] + checksum[15:0]; + end + end // always @ (*) + end // generate: C_S_AXIS_DATA_WIDTH >= 512 + endgenerate + + // checksum logic. 16bit 1's complement over the IP header. + // --- see RFC1936 for guidance. + // If checksum is good then it should be 0xffff + generate + if (C_S_AXIS_DATA_WIDTH == 256) begin + always @(posedge clk) begin + if(reset) begin + adjusted_checksum <= 17'h0; // calculates the new chksum + checksum_done <= 0; + ttl_new <= 0; + ttl_good <= 0; + hdr_has_options <= 0; + info_ready <= 0; + checksum <= 20'h0; + add_carry <= 0; + add_carry_d1 <= 0; + + cksm_sum_0 <= 0; + cksm_sum_1 <= 0; + cksm_sum_2 <= 0; + cksm_sum_3 <= 0; + end + else begin + checksum <= checksum_next; + cksm_sum_0 <= cksm_sum_0_next; + cksm_sum_1 <= cksm_sum_1_next; + cksm_sum_2 <= cksm_sum_2_next; + cksm_sum_3 <= cksm_sum_3_next; + + /* make sure the version is correct and there are no options */ + if(word_IP_DST_HI) begin + hdr_has_options <= (tdata[143:136]!=8'h45); + ttl_new <= (tdata[79:72]==8'h0) ? 8'h0 : tdata[79:72] - 1'b1; + ttl_good <= (tdata[79:72] > 8'h1); + adjusted_checksum <= {1'h0, tdata[63:48]} + 17'h0100; // adjust for the decrement in TTL (BIG Endian) + end + + if(word_IP_DST_LO) begin + adjusted_checksum <= {1'h0, adjusted_checksum[15:0]} + adjusted_checksum[16]; + info_ready <= 1; + add_carry <= 1; + end + else begin + info_ready <= 0; + add_carry <= 0; + end + + if(add_carry) + add_carry_d1 <= 1; + else + add_carry_d1 <= 0; + + + if(add_carry_d1) begin + checksum_done <= 1; + add_carry <= 0; + end + + else begin + checksum_done <= 0; + end + + // synthesis translate_off + // If we have any carry left in top 4 bits then algorithm is wrong + if (checksum_done && checksum[19:16] != 4'h0) begin + $display("%t %m ERROR: top 4 bits of checksum_word_0 not zero - algo wrong???", + $time); + #100 $stop; + end + // synthesis translate_on + + end // else: !if(reset) + end // always @ (posedge clk) + end // generate: C_S_AXIS_DATA_WIDTH == 256 + else if (C_S_AXIS_DATA_WIDTH >= 512) begin + always @(posedge clk) begin + if(reset) begin + adjusted_checksum <= 17'h0; // calculates the new chksum + checksum_done <= 0; + ttl_new <= 0; + ttl_good <= 0; + hdr_has_options <= 0; + info_ready <= 0; + checksum <= 20'h0; + add_carry <= 0; + add_carry_d1 <= 0; + add_carry_d0 <= 0; + + cksm_sum_0 <= 0; + cksm_sum_1 <= 0; + cksm_sum_2 <= 0; + cksm_sum_3 <= 0; + end + else begin + checksum <= checksum_next; + cksm_sum_0 <= cksm_sum_0_next; + cksm_sum_1 <= cksm_sum_1_next; + cksm_sum_2 <= cksm_sum_2_next; + cksm_sum_3 <= cksm_sum_3_next; + + /* make sure the version is correct and there are no options */ + if(word_IP_DST_HI) begin + hdr_has_options <= (tdata[C_S_AXIS_DATA_WIDTH-112-1:C_S_AXIS_DATA_WIDTH-120]!=8'h45); + ttl_new <= (tdata[C_S_AXIS_DATA_WIDTH-176-1:C_S_AXIS_DATA_WIDTH-184]==8'h0) ? 8'h0 : tdata[C_S_AXIS_DATA_WIDTH-176-1:C_S_AXIS_DATA_WIDTH-184] - 1'b1; + ttl_good <= (tdata[C_S_AXIS_DATA_WIDTH-176-1:C_S_AXIS_DATA_WIDTH-184] > 8'h1); + adjusted_checksum <= {1'h0, tdata[C_S_AXIS_DATA_WIDTH-192-1:C_S_AXIS_DATA_WIDTH-208]} + 17'h0100; // adjust for the decrement in TTL (BIG Endian) + add_carry_d0 <= 1; + end else begin + add_carry_d0 <= 0; + end + + if(add_carry_d0) begin + add_carry <= 1'b1; + end else begin + add_carry <= 1'b0; + end + + if(add_carry) begin + add_carry_d1 <= 1; + adjusted_checksum <= {1'h0, adjusted_checksum[15:0]} + adjusted_checksum[16]; + info_ready <= 1; + end else begin + add_carry_d1 <= 0; + info_ready <= 0; + end + + + if(add_carry_d1) begin + checksum_done <= 1; + add_carry <= 0; + end else begin + checksum_done <= 0; + end + + // synthesis translate_off + // If we have any carry left in top 4 bits then algorithm is wrong + if (checksum_done && checksum[19:16] != 4'h0) begin + $display("%t %m ERROR: top 4 bits of checksum_word_0 not zero - algo wrong???", + $time); + #100 $stop; + end + // synthesis translate_on + + end // else: !if(reset) + end // always @ (posedge clk) + end + endgenerate + +endmodule // IP_checksum diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/ip_lpm.v b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/ip_lpm.v new file mode 100755 index 0000000..3cef494 --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/ip_lpm.v @@ -0,0 +1,338 @@ +/******************************************************************************* +* +* Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +* Junior University +* Copyright (C) grg, Gianni Antichi +* Copyright (C) 2021 Yuta Tokusashi +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme, +* and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +* EP/P025374/1 alongside support from Xilinx Inc. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +* +********************************************************************************/ + + + module ip_lpm + #(parameter C_S_AXIS_DATA_WIDTH = 512, + parameter NUM_QUEUES = 8, + parameter LUT_DEPTH = 32, + parameter LUT_DEPTH_BITS = log2(LUT_DEPTH) + ) + (// --- Interface to the previous stage + input [C_S_AXIS_DATA_WIDTH-1:0] tdata, + + // --- Interface to arp_lut + output reg [31:0] next_hop_ip, + output reg [NUM_QUEUES-1:0] lpm_output_port, + output reg lpm_vld, + output reg lpm_hit, + + input arp_done, + output dest_fifo_nearly_full, + + // --- Interface to preprocess block + input word_IP_DST_HI, + input word_IP_DST_LO, + + // --- Interface to registers + // --- Read port + input [LUT_DEPTH_BITS-1:0] lpm_rd_addr, // address in table to read + input lpm_rd_req, // request a read + output [31:0] lpm_rd_ip, // ip to match in the CAM + output [31:0] lpm_rd_mask, // subnet mask + output [NUM_QUEUES-1:0] lpm_rd_oq, // output queue + output [31:0] lpm_rd_next_hop_ip, // ip addr of next hop + output lpm_rd_ack, // pulses high + + // --- Write port + input [LUT_DEPTH_BITS-1:0] lpm_wr_addr, + input lpm_wr_req, + input [NUM_QUEUES-1:0] lpm_wr_oq, + input [31:0] lpm_wr_next_hop_ip, // ip addr of next hop + input [31:0] lpm_wr_ip, // data to match in the CAM + input [31:0] lpm_wr_mask, + output lpm_wr_ack, + + // --- Misc + input reset, + input clk + ); + + localparam DEST_IP_POS = C_S_AXIS_DATA_WIDTH - 240; + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2= 512) begin + always @(posedge clk) begin + if(reset) begin + dst_ip <= 0; + dst_ip_vld <= 0; + end else begin + if(word_IP_DST_HI) begin + dst_ip[31:0] <= tdata[DEST_IP_POS-1:DEST_IP_POS-32]; // Big endian + dst_ip_vld <= 1; + end else begin + dst_ip_vld <= 0; + end + end // else: !if(reset) + end // always @ (posedge clk) + end + endgenerate + /***************************************************************** + * latch the outputs + *****************************************************************/ + always @(posedge clk) begin + lpm_output_port <= lookup_port_result; + next_hop_ip <= (next_hop_ip_result == 0) ? dst_ip_fifo : next_hop_ip_result; + lpm_hit <= lpm_hit_result; + + if(reset) begin + lpm_vld <= 0; + end + else begin + lpm_vld <= lpm_vld_result; + end // else: !if(reset) + end // always @ (posedge clk) +endmodule // ip_lpm + + + diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/op_lut_hdr_parser.v b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/op_lut_hdr_parser.v new file mode 100755 index 0000000..d0e0b15 --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/op_lut_hdr_parser.v @@ -0,0 +1,198 @@ +/******************************************************************************* +* +* Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +* Junior University +* Copyright (C) grg, Gianni Antichi +* Copyright (C) 2021 Yuta Tokusashi +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme, +* and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +* EP/P025374/1 alongside support from Xilinx Inc. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +* +********************************************************************************/ + + + module op_lut_hdr_parser + #(parameter C_S_AXIS_DATA_WIDTH = 512, + parameter C_S_AXIS_TUSER_WIDTH = 128, + parameter NUM_QUEUES = 8, + parameter NUM_QUEUES_WIDTH = log2(NUM_QUEUES) + ) + (// --- Interface to the previous stage + input [C_S_AXIS_DATA_WIDTH-1:0] tdata, + input [C_S_AXIS_TUSER_WIDTH-1:0] tuser, + input valid, + input tlast, + + // --- Interface to process block + output is_from_cpu, + output [NUM_QUEUES-1:0] to_cpu_output_port, // where to send pkts this pkt if it has to go to the CPU + output [NUM_QUEUES-1:0] from_cpu_output_port, // where to send this pkt if it is coming from the CPU + output [NUM_QUEUES_WIDTH-1:0] input_port_num, + input rd_hdr_parser, + output is_from_cpu_vld, + + // --- Misc + + input reset, + input clk + ); + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2= 512 ) begin + always @(*) begin + state_next = state; + word_IP_DST_HI = 0; + word_IP_DST_LO = 0; + + case(state) + WORD_1: begin + if(valid) begin + word_IP_DST_HI = 1; + word_IP_DST_LO = 1; + if (tlast) + state_next = STOP_0; + else + state_next = WAIT_EOP; + end + end + + STOP_0: begin + state_next = STOP_1; + end + + STOP_1: begin + state_next = WORD_1; + end + + WAIT_EOP: begin + if(valid && tlast) begin + state_next = STOP_0; + end + end + default: state_next = WORD_1; + endcase // case(state) + end // always @ (*) + end + endgenerate + + assign ready = (state != STOP_0) && (state != STOP_1); + + always@(posedge clk) begin + if(reset) begin + state <= WORD_1; + end + else begin + state <= state_next; + end + end + +endmodule // op_lut_hdr_parser diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/router_output_port_lookup.v b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/router_output_port_lookup.v new file mode 100755 index 0000000..5f168e9 --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/router_output_port_lookup.v @@ -0,0 +1,562 @@ +//- +// Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +// Junior University +// Copyright (C) 2010, 2011 Muhammad Shahbaz +// Copyright (C) 2015 Gianni Antichi, Noa Zilberman, Salvator Galea +// All rights reserved. +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`include "output_port_lookup_cpu_regs_defines.v" + +module router_output_port_lookup +#( + // -- Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH = 512, + parameter C_S_AXIS_DATA_WIDTH = 512, + parameter C_M_AXIS_TUSER_WIDTH = 128, + parameter C_S_AXIS_TUSER_WIDTH = 128, + + // -- AXI Registers Data Width + parameter C_S_AXI_DATA_WIDTH = 32, + parameter C_S_AXI_ADDR_WIDTH = 12, + parameter C_USE_WSTRB = 0, + parameter C_DPHASE_TIMEOUT = 0, + parameter C_NUM_ADDRESS_RANGES = 1, + parameter C_TOTAL_NUM_CE = 1, + parameter C_S_AXI_MIN_SIZE = 32'h0000_FFFF, + parameter C_FAMILY = "virtex7", + parameter C_BASEADDR = 32'h00000000, + parameter C_HIGHADDR = 32'h0000FFFF +) +( + // -- Global Ports + input axis_aclk, + input axis_resetn, + + // -- Master Stream Ports (interface to data path) + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_tuser, + output m_axis_tvalid, + input m_axis_tready, + output m_axis_tlast, + + // -- Slave Stream Ports (interface to RX queues) + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_tuser, + input s_axis_tvalid, + output s_axis_tready, + input s_axis_tlast, + + + // -- Slave AXI Ports + input S_AXI_ACLK, + input S_AXI_ARESETN, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input S_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S_AXI_WSTRB, + input S_AXI_WVALID, + input S_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input S_AXI_ARVALID, + input S_AXI_RREADY, + output S_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output [1 : 0] S_AXI_RRESP, + output S_AXI_RVALID, + output S_AXI_WREADY, + output [1 : 0] S_AXI_BRESP, + output S_AXI_BVALID, + output S_AXI_AWREADY +); + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 {(`REG_PKT_SENT_FROM_CPU_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_sent_from_cpu_cntr_reg[`REG_PKT_SENT_FROM_CPU_CNTR_WIDTH - 1]; + + + // -- pkt_sent_to_cpu_options_ver counter + pkt_sent_to_cpu_options_ver_cntr_reg[`REG_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_sent_to_cpu_options_ver_cntr_reg_clear) ? 'h0 : pkt_sent_to_cpu_options_ver_cntr_reg[`REG_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_WIDTH - 2 : 0] + pkt_sent_to_cpu_options_ver; + pkt_sent_to_cpu_options_ver_cntr_reg[`REG_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_WIDTH - 1] <= (clear_counters | pkt_sent_to_cpu_options_ver_cntr_reg_clear) ? 1'b0 : pkt_sent_to_cpu_options_ver & (pkt_sent_to_cpu_options_ver_cntr_reg[`REG_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_sent_to_cpu_options_ver_cntr_reg[`REG_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR_WIDTH - 1]; + + + // -- pkt_sent_to_cpu_bad_ttl counter + pkt_sent_to_cpu_bad_ttl_cntr_reg[`REG_PKT_SENT_TO_CPU_BAD_TTL_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_sent_to_cpu_bad_ttl_cntr_reg_clear) ? 'h0 : pkt_sent_to_cpu_bad_ttl_cntr_reg[`REG_PKT_SENT_TO_CPU_BAD_TTL_CNTR_WIDTH - 2 : 0] + pkt_sent_to_cpu_bad_ttl; + pkt_sent_to_cpu_bad_ttl_cntr_reg[`REG_PKT_SENT_TO_CPU_BAD_TTL_CNTR_WIDTH - 1] <= (clear_counters | pkt_sent_to_cpu_bad_ttl_cntr_reg_clear) ? 1'b0 : pkt_sent_to_cpu_bad_ttl & (pkt_sent_to_cpu_bad_ttl_cntr_reg[`REG_PKT_SENT_TO_CPU_BAD_TTL_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_SENT_TO_CPU_BAD_TTL_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_sent_to_cpu_bad_ttl_cntr_reg[`REG_PKT_SENT_TO_CPU_BAD_TTL_CNTR_WIDTH - 1]; + + + // -- pkt_sent_to_cpu_dest_ip_hit counter + pkt_sent_to_cpu_dest_ip_hit_cntr_reg[`REG_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_sent_to_cpu_dest_ip_hit_cntr_reg_clear) ? 'h0 : pkt_sent_to_cpu_dest_ip_hit_cntr_reg[`REG_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_WIDTH - 2 : 0] + pkt_sent_to_cpu_dest_ip_hit; + pkt_sent_to_cpu_dest_ip_hit_cntr_reg[`REG_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_WIDTH - 1] <= (clear_counters | pkt_sent_to_cpu_dest_ip_hit_cntr_reg_clear) ? 1'b0 : pkt_sent_to_cpu_dest_ip_hit & (pkt_sent_to_cpu_dest_ip_hit_cntr_reg[`REG_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_sent_to_cpu_dest_ip_hit_cntr_reg[`REG_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR_WIDTH - 1]; + + + // -- pkt_forwarded counter + pkt_forwarded_cntr_reg[`REG_PKT_FORWARDED_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_forwarded_cntr_reg_clear) ? 'h0 : pkt_forwarded_cntr_reg[`REG_PKT_FORWARDED_CNTR_WIDTH - 2 : 0] + pkt_forwarded; + pkt_forwarded_cntr_reg[`REG_PKT_FORWARDED_CNTR_WIDTH - 1] <= (clear_counters | pkt_forwarded_cntr_reg_clear) ? 1'b0 : pkt_forwarded & (pkt_forwarded_cntr_reg[`REG_PKT_FORWARDED_CNTR_WIDTH - 2 : 0] + (1'b1) > {(`REG_PKT_FORWARDED_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_forwarded_cntr_reg[`REG_PKT_FORWARDED_CNTR_WIDTH - 1]; + + + // -- pkt_dropped_checksum counter + pkt_dropped_checksum_cntr_reg[`REG_PKT_DROPPED_CHECKSUM_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_dropped_checksum_cntr_reg_clear) ? 'h0 : pkt_dropped_checksum_cntr_reg[`REG_PKT_DROPPED_CHECKSUM_CNTR_WIDTH - 2 : 0] + pkt_dropped_checksum; + pkt_dropped_checksum_cntr_reg[`REG_PKT_DROPPED_CHECKSUM_CNTR_WIDTH - 1 ] <= (clear_counters | pkt_dropped_checksum_cntr_reg_clear) ? 1'b0 : pkt_dropped_checksum & (pkt_dropped_checksum_cntr_reg[`REG_PKT_DROPPED_CHECKSUM_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_DROPPED_CHECKSUM_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_dropped_checksum_cntr_reg[`REG_PKT_DROPPED_CHECKSUM_CNTR_WIDTH - 1]; + + + // -- pkt_sent_to_cpu_non_ip counter + pkt_sent_to_cpu_non_ip_cntr_reg[`REG_PKT_SENT_TO_CPU_NON_IP_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_sent_to_cpu_non_ip_cntr_reg_clear) ? 'h0 : pkt_sent_to_cpu_non_ip_cntr_reg[`REG_PKT_SENT_TO_CPU_NON_IP_CNTR_WIDTH - 2 : 0] + pkt_sent_to_cpu_non_ip; + pkt_sent_to_cpu_non_ip_cntr_reg[`REG_PKT_SENT_TO_CPU_NON_IP_CNTR_WIDTH - 1 ] <= (clear_counters | pkt_sent_to_cpu_non_ip_cntr_reg_clear) ? 1'b0 : pkt_sent_to_cpu_non_ip & (pkt_sent_to_cpu_non_ip_cntr_reg[`REG_PKT_SENT_TO_CPU_NON_IP_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_SENT_TO_CPU_NON_IP_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_sent_to_cpu_non_ip_cntr_reg[`REG_PKT_SENT_TO_CPU_NON_IP_CNTR_WIDTH - 1]; + + + // -- pkt_sent_to_cpu_arp_miss counter + pkt_sent_to_cpu_arp_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_ARP_MISS_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_sent_to_cpu_arp_miss_cntr_reg_clear) ? 'h0 : pkt_sent_to_cpu_arp_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_ARP_MISS_CNTR_WIDTH - 2 : 0] + pkt_sent_to_cpu_arp_miss; + pkt_sent_to_cpu_arp_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_ARP_MISS_CNTR_WIDTH - 1 ] <= (clear_counters | pkt_sent_to_cpu_arp_miss_cntr_reg_clear) ? 1'b0 : pkt_sent_to_cpu_arp_miss & (pkt_sent_to_cpu_arp_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_ARP_MISS_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_SENT_TO_CPU_ARP_MISS_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_sent_to_cpu_arp_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_ARP_MISS_CNTR_WIDTH - 1]; + + + // -- pkt_sent_to_cpu_lpm_miss counter + pkt_sent_to_cpu_lpm_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_LPM_MISS_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_sent_to_cpu_lpm_miss_cntr_reg_clear) ? 'h0 : pkt_sent_to_cpu_lpm_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_LPM_MISS_CNTR_WIDTH - 2 : 0] + pkt_sent_to_cpu_lpm_miss; + pkt_sent_to_cpu_lpm_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_LPM_MISS_CNTR_WIDTH - 1 ] <= (clear_counters | pkt_sent_to_cpu_lpm_miss_cntr_reg_clear) ? 1'b0 : pkt_sent_to_cpu_lpm_miss & (pkt_sent_to_cpu_lpm_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_LPM_MISS_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_SENT_TO_CPU_LPM_MISS_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_sent_to_cpu_lpm_miss_cntr_reg[`REG_PKT_SENT_TO_CPU_LPM_MISS_CNTR_WIDTH - 1]; + + + // -- pkt_dropped_wrong_dst_mac counter + pkt_dropped_wrong_dst_mac_cntr_reg[`REG_PKT_DROPPED_WRONG_DST_MAC_CNTR_WIDTH - 2 : 0] <= (clear_counters | pkt_dropped_wrong_dst_mac_cntr_reg_clear) ? 'h0 : pkt_dropped_wrong_dst_mac_cntr_reg[`REG_PKT_DROPPED_WRONG_DST_MAC_CNTR_WIDTH - 2 : 0] + pkt_dropped_wrong_dst_mac; + pkt_dropped_wrong_dst_mac_cntr_reg[`REG_PKT_DROPPED_WRONG_DST_MAC_CNTR_WIDTH - 1 ] <= (clear_counters | pkt_dropped_wrong_dst_mac_cntr_reg_clear) ? 1'b0 : pkt_dropped_wrong_dst_mac & (pkt_dropped_wrong_dst_mac_cntr_reg[`REG_PKT_DROPPED_WRONG_DST_MAC_CNTR_WIDTH - 2 : 0] + 1'b1 > {(`REG_PKT_DROPPED_WRONG_DST_MAC_CNTR_WIDTH-1){1'b1}}) ? 1'b1 : pkt_dropped_wrong_dst_mac_cntr_reg[`REG_PKT_DROPPED_WRONG_DST_MAC_CNTR_WIDTH - 1]; + +end + + + + +endmodule // output_port_lookup + diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/unencoded_cam_lut_sm.v b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/unencoded_cam_lut_sm.v new file mode 100755 index 0000000..1efa776 --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/hdl/unencoded_cam_lut_sm.v @@ -0,0 +1,225 @@ +/******************************************************************************* +* +* Copyright (C) 2007 jnaous +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +* +*******************************************************************************/ + + + module unencoded_cam_lut_sm + #(parameter CMP_WIDTH = 32, + parameter DATA_WIDTH = 3, + parameter LUT_DEPTH = 32, + parameter LUT_DEPTH_BITS = log2(LUT_DEPTH), + parameter DEFAULT_DATA = 0, // DATA to return on a miss + parameter RESET_DATA = {DATA_WIDTH{1'b0}}, // value of data on reset + parameter RESET_CMP_DATA = {CMP_WIDTH{1'b0}}, // value of compare datae on reset + parameter RESET_CMP_DMASK = {CMP_WIDTH{1'b0}} // value compare of data mask on reset + ) (// --- Interface for lookups + input lookup_req, + input [CMP_WIDTH-1:0] lookup_cmp_data, + input [CMP_WIDTH-1:0] lookup_cmp_dmask, + output reg lookup_ack, + output reg lookup_hit, + output [DATA_WIDTH-1:0] lookup_data, + + // --- Interface to registers + // --- Read port + input [LUT_DEPTH_BITS-1:0] rd_addr, // address in table to read + input rd_req, // request a read + output [DATA_WIDTH-1:0] rd_data, // data found for the entry + output [CMP_WIDTH-1:0] rd_cmp_data, // matching data for the entry + output [CMP_WIDTH-1:0] rd_cmp_dmask, // don't cares entry + output reg rd_ack, // pulses high + + // --- Write port + input [LUT_DEPTH_BITS-1:0] wr_addr, + input wr_req, + input [DATA_WIDTH-1:0] wr_data, // data found for the entry + input [CMP_WIDTH-1:0] wr_cmp_data, // matching data for the entry + input [CMP_WIDTH-1:0] wr_cmp_dmask, // don't cares for the entry + output reg wr_ack, + + // --- CAM interface + input cam_busy, + input cam_match, + input [LUT_DEPTH-1:0] cam_match_addr, + output [CMP_WIDTH-1:0] cam_cmp_din, + output reg [CMP_WIDTH-1:0] cam_din, + output reg cam_we, + output reg [LUT_DEPTH_BITS-1:0] cam_wr_addr, + output [CMP_WIDTH-1:0] cam_cmp_data_mask, + output reg [CMP_WIDTH-1:0] cam_data_mask, + + // --- Misc + input reset, + input clk + ); + + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2= 0; i = i-1) begin + if (cam_match_unencoded_addr[i]) begin + cam_match_encoded_addr = i[LUT_DEPTH_BITS-1:0]; + end + end + end + + always @(posedge clk) begin + + if(reset) begin + lookup_latched <= 0; + cam_match_found <= 0; + cam_lookup_done <= 0; + rd_req_latched <= 0; + lookup_ack <= 0; + lookup_hit <= 0; + cam_we <= 0; + cam_wr_addr <= 0; + cam_din <= 0; + cam_data_mask <= 0; + wr_ack <= 0; + state <= RESET; + reset_count <= 0; + rd_ack <= 0; + lut_rd_data <= RESET_DATA; + end // if (reset) + else begin + if (state == RESET && !cam_busy) begin + if(reset_count == LUT_DEPTH) begin + state <= READY; + cam_we <= 1'b0; + end + else begin + reset_count <= reset_count + 1'b1; + cam_we <= 1'b1; + cam_wr_addr <= reset_count[LUT_DEPTH_BITS-1:0]; + cam_din <= RESET_CMP_DATA; + cam_data_mask <= RESET_CMP_DMASK; + lut_wr_data <= RESET_DATA; + end + end + + else if (state == READY) begin + /* first pipeline stage -- do CAM lookup */ + lookup_latched <= lookup_req; + + /* second pipeline stage -- CAM result/LUT input*/ + cam_match_found <= lookup_latched & cam_match; + cam_lookup_done <= lookup_latched; + cam_match_unencoded_addr <= cam_match_addr; + + /* third pipeline stage -- encode the CAM output */ + cam_match_encoded <= cam_lookup_done; + cam_match_found_d1 <= cam_match_found; + lut_rd_addr <= (!cam_match_found && rd_req) ? rd_addr : cam_match_encoded_addr; + rd_req_latched <= (!cam_match_found && rd_req); + + /* fourth pipeline stage -- read LUT */ + lookup_ack <= cam_match_encoded; + lookup_hit <= cam_match_found_d1; + lut_rd_data <= lut[lut_rd_addr]; + rd_ack <= rd_req_latched; + + /* Handle writes */ + if(wr_req & !cam_busy & !lookup_latched & !cam_match_found & !cam_match_found_d1) begin + cam_we <= 1; + cam_wr_addr <= wr_addr; + cam_din <= wr_cmp_data ; + cam_data_mask <= wr_cmp_dmask; + wr_ack <= 1; + lut_wr_data <= wr_data; + end + else begin + cam_we <= 0; + wr_ack <= 0; + end // else: !if(wr_req & !cam_busy & !lookup_latched & !cam_match_found & !cam_match_found_d1) + end // else: !if(state == RESET) + + end // else: !if(reset) + + // separate this out to allow implementation as BRAM + if(cam_we) begin + lut[cam_wr_addr] <= {cam_data_mask, cam_din, lut_wr_data}; + end + + end // always @ (posedge clk) + +endmodule // cam_lut_sm + diff --git a/hw/lib/std/router_output_port_lookup_v1_0_0/router_output_port_lookup.tcl b/hw/lib/std/router_output_port_lookup_v1_0_0/router_output_port_lookup.tcl new file mode 100755 index 0000000..841536b --- /dev/null +++ b/hw/lib/std/router_output_port_lookup_v1_0_0/router_output_port_lookup.tcl @@ -0,0 +1,166 @@ +# +# Copyright (c) 2015 Noa Zilberman, Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design router_output_port_lookup +set top router_output_port_lookup +set device $::env(DEVICE) +set proj_dir ./synth +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# set IP paths +##################################### + +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +puts "Creating Output Port Lookup IP" +# Project Constraints +##################################### +# Project Structure & IP Build +##################################### + +read_verilog "./hdl/output_port_lookup_cpu_regs_defines.v" +read_verilog "./hdl/output_port_lookup_cpu_regs.v" +read_verilog "./hdl/eth_parser.v" +read_verilog "./hdl/ip_arp.v" +read_verilog "./hdl/ip_lpm.v" +read_verilog "./hdl/dest_ip_filter.v" +read_verilog "./hdl/ip_checksum_ttl.v" +read_verilog "./hdl/op_lut_process_sm.v" +read_verilog "./hdl/op_lut_hdr_parser.v" +read_verilog "./hdl/preprocess_control.v" +read_verilog "./hdl/unencoded_cam_lut_sm.v" +read_verilog "./hdl/output_port_lookup.v" +read_verilog "./hdl/router_output_port_lookup.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::add_user_parameter {C_S_AXI_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property display_name {C_S_AXI_DATA_WIDTH} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXI_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property display_name {C_S_AXI_ADDR_WIDTH} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property display_name {C_M_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property display_name {C_S_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property display_name {C_M_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property display_name {C_S_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {SRC_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters SRC_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters SRC_PORT_POS] +set_property value {16} [ipx::get_user_parameters SRC_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters SRC_PORT_POS] + +ipx::add_user_parameter {DST_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters DST_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters DST_PORT_POS] +set_property value {24} [ipx::get_user_parameters DST_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters DST_PORT_POS] + +ipx::add_user_parameter {C_BASEADDR} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_BASEADDR] +set_property display_name {C_BASEADDR} [ipx::get_user_parameters C_BASEADDR] +set_property value {0x00000000} [ipx::get_user_parameters C_BASEADDR] +set_property value_format {bitstring} [ipx::get_user_parameters C_BASEADDR] + + +ipx::add_subcore xilinx:xilinx:cam:1.10 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore xilinx:xilinx:cam:1.10 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] +ipx::add_subcore xilinx:xilinx:tcam:1.10 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore xilinx:xilinx:tcam:1.10 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] + +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis -of_objects [ipx::current_core]] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + +file delete -force ${proj_dir} + + + + + + + + + + + + diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/Makefile b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/Makefile new file mode 100644 index 0000000..6bdaea4 --- /dev/null +++ b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (c) 2015 University of Cambridge +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source switch_lite_output_port_lookup.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/module_generation_switch_opl.xlsm b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/module_generation_switch_opl.xlsm new file mode 100644 index 0000000000000000000000000000000000000000..8594b2ad7e7dd2b7b7f07ccc19bdc7d38939f725 GIT binary patch literal 39968 zcmeFY^OI*mvp(2%PrG~Cwr$(CZQHhO+n=^EZTGZo+t$u|Z*1&t?EMe!w|=NBWW_nB zBJ+8w>QpL7gMy&~K>$Gk0Ra&L38WhB!h!$+b;AGwp#VXFXbaohxtQ9y=&N`-m^$my zdDz+z6oG+I6af8G`akJ^^9&5BO*<_xAoem3a(lR#+LVHG!J(9gx8f8s(;^f|WNV0| zv1qZ%Zs$G8D^a-S7+}!F;d=Jvx45+|Ov+j&v4Snm9ADC81Hfurq&7@vdUyOK`5VBB z0aCxs3C*v`o=mDf?unu@AMh?NjUY*>uk{j3>Kqo5R*>UM z0n05!AV5V2YGBDk$of5qJ0vlZaEHMO`kN=V*)>(sgcc6=>JC@)#-Kv2Q`dF07GdPc zJb1r8*n{LI6=46^6Rei78HLyvm6SBe9>(7Z$l`9B_*GrADkWn`{Kv#Ks7YyT*RCc5 zyMVRuiVhqy<6PqKX?6`MrSGP4Fu%)52{gar;FJF>LWQmW;^J0ik%4!F(GGrh%nti6 z-?0#wf_oy26K7|DeuKA5MHx;)8~fnHHptWM#P2Cv2fVlI>)*$|J*v6P90$R|D810_C-ZOsxK;Y*G6iDI!gCQ-d48)KBJVWMRFYG@I(RVVnai*vHPyTtN_Oi5Io_c^h##S?ozM)YLc~KZs=ap?vw! z%H@nH5wRe@GR=yQk`_GqYc;dnP3C$Iu|p45kKK+3MdMd&1OHD>(yYW|ME9>p3=9Ye z3kV9>!-oF9{lwkg$=b-?-ugdO`+xfk@ISu&r~AJZDu8h?DZ@_4F#KKY=zHoP|_;z zKq#%Y7#xmM7ic2URB*o(yhoX}&}Gu%{9G`sZ8}40?%ex5*@-I^ zKpdqfw4Q6CY%B4DY34*0&1nc$KU{oh`0H!uw6rpAa|SvviJM}(8@4MPbS#nw+?km= z#{L3u?#m6R_CGiqe?H;=XC(iBNUn1htXujA$I0M8KnVXd{#o1q+s|RIXz@kL2(&pG?K^ z;YM$+2CK;2CUD?p|L#XgWa@<<|GFQzL=m=}P|kw=Md%44$`{M;_Zv54vo>@U6RKZT zf~j`0(6o{yIH)R)BJf~bY%Iu1XQH-L3YtX~Gl0%%vgImIRbfOjnjz)p4`MdFv;kdG z6;PcvA~ffcguZEw3VAb;CxVXPQ61H^2r8*ijpodwGN@Dx5hh)$jzs4S<5lrNeuCpW zM5jR{s+5fjWMNI(VYUzMhEopP(VfMhlZVBm-QULUGErY?xtJU(+)^1~tRy_TVPLf35Gs}){5vg(qA_NLGzhubQU|K>_ zD_k_sR4GgJj!u`Wbgpt!dm0Z?tg!MerFO86=~YT4bs1r$m&=xB{ONZ*RNSXPgM;5I z1$$WH;$zD95s^_J&usiGTJbfjniAUc@OM4CUNBeL76{K?d^a~3Dj#*Xv`%4-{)#m5 z(wuebEe*|F+hQT!*oy_Tk93K_s1wyXG0+7DmuN{`eqh-va@Tr-vT(5&Tf(e1I*mE# z)6GMC76XqgCb{YlJt@tbgx{Re+LWmnB56w|ki$3|+2$6F?EH^-YvARU7W>coYlwk>;Q!kL zoLxL^Or8IOvx{0g_Qf2Ce*9IfTw+8%G#F$z?P`I9S${ zsu19eOT;6FtjPA*?l+(!5kIV(mOn|fh~>~jkb9FGRY>pc`RNZr3cC9^_4A%@N*eHLrOMTW(@JDewv^-tLGl#Hd(&wdJ3X; zn^(QtoRhN{!a$M(L9C$^Lzxp_Bay<24FM2EL#`XI19RGhXu$2wibjm*$bBo$;ykr-8$J^eUqgxd28#(>uow5RA-qF^A&bxI_iDYCRp`g+l|5I zMpkj$JlT=JLCT#7B0;-{fp5>@&GY7{BL7-ygvvU+>ZP0_z7hxpuwV!d~^STs_u!<@K1L*=G>XE z;9xI1aA3*8eJCcw8YIqA@NzYltY?uLA+-p8p^MD)et08%hx~P4R2^tD5vebdxKCncCSKVdQm?|!0&Y)VeLv!U*#oXm zUyWOj0>QLiGv>*W`uPWwut6Cdv8nFJ?uouJk@0XihvL+D20Ewknej~EcSj2)(Wm%1 zB5qehLeZQI&>4y zjp4qN5CBLb=U#+g;+*NK8oIB{4}Wk;CpiW(qs^5${7q#YkB^2hM%fB_H}P8yG2&bo zdZm89{R+f*7rj>c7y*qwN9&ro54%SYzA*2m^{Bk*7;&l+-QZ%=zOf{PS@LXbyEubUlI>Diwbp8<%W48yFjB=^ zQywj6df8~1FR#%P2BV>b0;Q{bp79+x{J6c#eFSUea}s(u_rhp>fqUuf<+F$U;lOiQ z+u@&2KDpAWO>ABJ5=|{U`}Df2La9#|M_}X+$JA{*c9+Mi<<#TnXx-*TP&gSJyDtX0 z@e;5o6Mt}Q4=457gPnzL-qM&eV&=S^amJa6Pk*u+jb6vRn?SYj3%>a5U8ID#N#*nM z^k3)BQyb2yMrD)w(v6lBXd({3id)VRPteNZi!1X?>`flkF1D)u(F%>=mD4$G>vhzp z-o|yDRANERw>G^~7rkp#s*Tv-R{x@cF>O{`(XfFEovd$s+~nEY*a7}Hu4iwth+MGe z{QU^IQH5hK2#&K3zv8=ewY=SuzU`7;Ce65#lB(Y*y!pT_cren8W6t7cvw^o3W(#*{ zdJgX3tw8t*B6qT14d#idB!(LR$svM0kw59*Y4!A(-TfFOa9r$1P7j?do@1$`;dp-WUJS@Njzy-yF%9Z?TNH zk!3uK&$7{(&(Gr#$H;K~Q|)W)_y+_1UK+8YKYQ6$YL6Q(?SrcAtMc4=NsG8i5B(O{ z4Y!N=H>P{5rN#DN23G43GAtd8jV$x*;P6CN|7PB8m%3Q=A2_V8i63_c1r7&=g? z?xi(gCBFPW>l$YSY9koS6|pGn5%S~JrHjO*Frx#v?>wD4UD;}+c}rd1(cXSlOq zZw$Fx%KJz*?(Vy*m)oEd0B^^gP4bk))`3(qNP@SK%rE#N?FyJ%Y+Oeh4LY1%y{uTY z%p}asz36lW%u%Gey!ABB2vb8VC=_WE1);`{p$o8KB=tB$k&L=jugXqm7<}SL=Z-6x zITVetQnSpz3YNhvbTMuvKn%!S;kBZqz=-;LihoUR9;8n(*@O`PKFSx04(Afw3@K?j z7#}cpN**xcgz1U`+}7K_yr++)1~UBx9unE3;}O3<%IN&P4DtzceBUdqkVvR(Bfk1()gqBeF?d$IuX5m%B zlikSM!ZUhn&HDxSKW%JWs2AEON&ex29uN@Hf5U^Dk)eWD-prI)MT|=~@yg$r~_wqSluB`AF?`S=SMyfyEmzgp5%? z!_@Bh?=cezgCKZj8k2Dmh%|;w8$=YQXy&zH9^~DPFE+BZOb(f#XZ{yL-SH%S66Wl$ z_V>8!4%Kow)!ZsB*D5*H_#VcWMdMM7p2;%a6$a1`8=h#>(*f{ZuzO=e88D&Swb$2n zbhyXplXwY`K4DGfIgeo=;(o9KHg?cskVc@l02~220t5zeTW8p990iCBND8niNF9iF z8~_ji5da1F4FCh60^k5R3Gf=g0FWpkYT#<1YG6{JbM;aWec*Ovg}N}sSB%*kagbb^ zus+oFxyd3A@>M#Cw}Jf0zsAi;3OgJt%+Hf2;uCzBC~zVo@G<5n&WtCbM;xiEaIqyv z^bfg#>1p-P%gHVch{?CH)&jN&C9{;gzUQO-cf_~?uEmaAzMsi*1&$J2ML-Ue2l?}}Y~PajiWqb8{`1Twpj1Gq zR^KGdkOeRb@D+-K7q@kgHHv-p10Plbpu1T8EdgRcPrMlY@V7wSK==jFf8i{EYd~ut zn?ct9al%!=uYT76IRT6UYyc7f8h{A^ci`QH=vNa!*cIzf2kHsn3&8)200k5T1kC{S z8!QCKuwOR7HUP>1O28?44;OM1P68+?0M+0(02d%!T0G|iyQ|i38?Y6y0qhPm546YB z{Ao$>6QOsDzP*TDL7Y3(rL!X0i1+i#8AT}S3v|olAlM4gY*!8^Y~*+s4=zc;j3uU} zPUaURkedL=^+55P5y$kmwHO*7pfJ=j+!2Ip&|oNJWx2Y$`6}C{ZLCuh^#QqPlracr zO^i~f&QS9L_MHuDZ65dk^;s`|(`KkbL8#2whQ)j zwoW0#vC+Gb6?p8N)f5R@N-kqgDwo)pw%{U}PpxxMVLzLxEwytT(^HIgtF)c(o6prs zgzEdFjD0$8Je4U$I`B0}Np>e&w+;VINC3aNj+TT~nzEIZp8J(Jc`6@8xlzlOZM$e# z?Y=sJ$)0u6u36YFqG8#jx)Rm(U}qgQ^!}BIHc+kW=r7>Wf5I-Fq-6IuH{mlarH`M< z-&0&@Uyu^2yHZWL5~B~1VR3M$ZxHB5oxJZb>zSe_bM0BId15V|^=fSrdBFwO5y2JpY| z)WmQXhRkZf&>EOu_g(=tv9R9g<4uFF?PX;2BxsOx;Z>G%VV^+&Eh2yq-P|{?bsVQY z=9u1e=`dNI-lyxIpo{*G&-Hto89*OBmp}HZO}cD(tp4fG59CuHu5}LmC4VCqx$O{t&6m54+Sd+l5ZxAzw9Q5QFwMpo98ZL# z03yPKS;644qP@QI3=LcGS}rsJ5tfWd6;vOhwx2~^o^`WGDD{H1`~X3bh4 zBO;ZXK}eV*X3>QHLm04deQ7+53|i;05ZKW#v{Sozw)Lv5SLe6o zLkgXU_W>O9jXbTYISkjXCw>4c0-QvzP;K~F@DCVuXKPcT2^*^Cd)_t5)yBlG)sOmZ4};L)Y1?dmGlkDNj}9-cE#Ejn@DJ$$E>{? zL2U?4Dn1;;T|(c-A*e3j6&3}g?z>&&MK9=pZ{I&%$6x8HJ|(vX(ubL@4%*Xtd@lSd+0~zN~AW zKEWyXt^hLgj;-Y(VVcya`r4Y!hTyA;2&u}zSA+aMqO{*W%*D*nKXQQDE2bO@Oz2O* z74~E&6Kw8axf&VY^fux{{5|$SqF<%`Milk6FVD?7j{N&9@?N`h$u&9WOvdWKTHVVx z**HRpkkU>qJ3@G9TG8V&c^n9(SvW1iTt*K_ZD2BcG zY)B))$l9YWqd}fseN@~Q@OU+^Z*`7g+iwd%qrJPasYicA&G4Ruf)tOJ&&&s>&urG? z51!Pw4Y2(>Ah9j(TS6-5_LFLWJM2Tg=UFO|u*X4OlV$=J?V0KN=ScO#d0)tksrk0K z-hTxYGbrADcm}S-&4p!yr@V0+LDdYhR&)hsxhP!5`*;N7jr-(57#4z75YJ6Ce;R6d zUn%QtcyT%ncTXbZ#dwY_Cj}ymSbC!U>RLa8kHyyR%xwA!yQ{-_@F~XL&CQLA-6g;C zo2r-Cr)qndx3#&9g4m~mpC^qyE&Fyhk}S$wHe1$qTdr-@XYtgfrMcAwyZ$5`{Y|Tr z-9u9yrBn_I&>y)Ed0?u`9gC$b!)*YG{>Y<<`oJsLEZ z`Vd^-Y6?G&cXnCEbZjs>EGU499oBR_ov_Pnm?s89J( zZH}2!{Fg)V#FhiKsQRED@9n8$7os z??v^txwDy{Sc5Z*KkIL>;SQMwJ4=I+1{)pfPO~iaXWe?Ld^S|5Yh3Fvu@%ARp52}< zDyGxEcX?${Q}V}wiIP-$>%}_?YMC&`!KDQE3`g zk{-{3s*UiaTdj??p>bbqznD^sgX7uiayDJ87S7>DG~5t#4RUVZ^!N_H&gy zW6tbjh+kizzZb9;;<`gf8!)-)3MB z=3(sR#0{$2BYpOr-R>;PF@N0t>}j?bvu8<}-b3i|6NtgLm-GrB*{{?kWeuAb@6+9V z?eBVM-a)CJIUJDJe_aZve}sp7MxXka%?v*o_UFMHuj50X$fG7f_sekPxk&csGGx}Q z#u+Y@PorUo`8nE<&))X&u71;(!$Zxd^e8K^v)B8~$H;z1_;HD}6n{P1^{z*ds@yhT z^L`kWkANJ$c2CRZ=V=*YxY?>bzMH=J66k*D@kinJ?VAGJ2jdL3i$~BlL&<+$?hMr+ z%w}xAwGjFpZhan}!7-SKxII#l*e9qK`!jt*&1 zGB~n^lQ?tWySsp87eB5fs_8yf)0?(yQp_&d$Y|)3pbUDO>9(hyr*qb3<|^h&;^!*D zqBm*d<*0eY=+3Bk+=Ama->%t@H2OhoN^mgpbc}nPui2q$Q3YWCZAR918ul9pecMfc zT%bzDV`+%fj4o1JtLSbo(WELSU#<)}vH7lLs?79)`PjzH(0I8gh#OhjPg82=jPZ)S zCi^onDZNR`rW8V6tkbNR8ltCjAVG1WevcMD=SO+SRek}d z%l+4Ea~b`lGcASt(d(~;6fQf8-lmvrJ=;l*Rwqk?vu{!eL(KrwIU*rV(Gu6!h&7Sw zF7W0l1;@HwGcC!~3Jy<5Y&0GW@6j4zcyb@uy)zomA2q$wn2e)lUoJjw)tv5-aF@MN zm)8rf&y=WS_WKyRO&M^-H)mYE`ay0N4~gM%=}a;oEza?5PnE)kzg1`8;IlBO#oK-;H5<@I|SSuzh}Ig9sE?aKVA ze!xS@o5WWhbw$MzHfX^&H6omjm1O9}tcPekOFE5+Wo#%j`p#WkR7f zh?TBW@S(MqoC#QS9FVsNDoM7jRN!(!!re|Rxbav?L)-UAozSZ9e z#Oc;35F@Q-qog94rnkxvy=xY()r`oD$p!3GW-LX`ZgWuj*H*+*74@{-HXZps&wwsX z!{zsrYY~ZF`^F^Z`Fo6(=F=4z@BP z^Ta6iz|`@1K5L2g$jIthZ@&Y7E)L%?$+rZ!PC$!08Nu{G+*n1PF+YEJZ%5C1@Rn{D z-uOnV+Mu@MVJ=@#4X<>-c6PK5{|4$7xE(G;wszopEAm3whxgUP|FBmO+TKETns(B$ zirneHRQO$TIh3ZLo|`@%1+D{&6NSI; zO~MlMP<=d+fz8kitTk4M$El{%MC-L2_E>$b6mHtBC39w8bTC~0=ste0Xfb@&a@hq{ znC}lXW+hJeK);Fqsg%6BdH>?yAWb_ffbi!3yLx(AOSXHxC`!INt9t>Jd+Vp#Q;jl~V6j-&35IH@UFnU_ z%hEM#8%m3AQT@>+Wwz&aA(7w+<^i0da49)EtzIIy7UVsvQpf$eG|@=6)HEuw~*dc&d2vzPz zp*TRkVhq(ru*oLOF~?4|_x_YBv%{0?roWi`KtUP#n44FqN<9yY~Fx4DkL z^q%}PCQ3U%`~J>;C`WKlCwzsvy+)c_B`54Jx~>QQo)>O)_D8c*7;09elUy$Tlk*XY z+!Ja@uEZOlru@w2r0=)oB7dy%J+)>F1<<5gLx;us(L~Y6t zqEB2_vLl9h?!MG=U=PTpX7q-@15^u7mypgMw#eZc?bffEmU;mn&QraRC1`{LFmtPL z+N#pZA&iQ<#uubtD)&6dOYlYt$AWKEK3+3};*tE>2&wrsz%y}yH!HW>L{8o54dtuY zGBzp$-iU6X1>!0L;D3>(dDSgrsr1P--YdB~SiIVc63?f%ouTf`gy!y>!e3*LD&Z@I&+(}j` zy`7cbfhDHKlpb&lMuvY2ewZ)pqdh(xVPjrkpCyTRC=*7XNlcF%amjA)DARdn=~sRlw?BRd>j%dbSW62%U46~*j_Y_5?c(C;OSw20Y27y zYWY^1eJC#~Rt-EcSdP zABQ5>a6No`ze(Tly+*=&V7`$ymb zW*UM{w-;{b!gZ%^N4WRhZ*I&X$S@#hc+ryK+oYDIFtfugE3g?X@o!*Q0{R=vAU=eyN(wm}MBmJL|9O@1GVGn1G4CnF^{Sk)@ zB7m%9opER|nuAk%O5V^{;XLIPAM4K~Ce9mAz$6r9rFveZq#0>x$%p;l(n(Vn6B`D} zxc9JHazo!=1Ij|Bv}V5h3jp%;0q&tdXN_8^vuMq}cJLQ|M-GTpDRdFtID-S~KW+nh zUdU{$YqH{ZYV(#YbY`IYsjFDhReMh;pF%~TZ%@K_Vq%cYDK6Ga9*t*q$hx=h6npCO zCD8#puI(=#Zf{fy$!x6MjzN4>Yy~TB#5_>|unFC%{e7;~8CJn`(_ zJ88hlmsPtxkx%(*h_{iemB)j~EA6grFi+}zZ8lV&>}KfQHSefbF?4muhU%M=z9&)| z&pPy#6WDj&_??|u8#*ygxiAN8Awo}tYjjIZhFmH^jMuUoCri3eDFrTq;-E4`>@ut~ z;$(DXHIdSFJfUvQRN_or1!XalxRf#tKGEF#5cxwnC@IyGtdj+vqP4m7B9C37G2B#V zmkc`u7NAz@s~o}lcM|r~ADj+$H$Xa~9JjHTulqrYqcXvZIhUVOk*jqKTH~~O;|AgA z+vSP{<@@n!@(1;1fYbnW#a%HV`F8t@`ks^2;>|_~I_dU#j)MR@zc;(#tShM}{#j#? z&eJpWIe)9q3#<)MKLk{pbByBy%bNH2S5i9sQS6@V#~DKQ!TCE;tZPaD>#kI*yk7DZ zQf@o%GmDXWBX7c}l$!t^xO-HW<3S?vrQeXE51SX(xF6LP?|$s9t&@DJfi&MlgdmTG zkp|G<-EO#*@cYJ>ji9cTtATtI#Z-UWKI?>OrZ^6E$TkOKX#Wq(>_dhl9z59sPrajF zxKDsp-Ykba7ZpP3*P84{WBmKs>r(DR_KRscN%)6zr*=$-;8}%Fj8&g&E@L?(B6d)r z&q~(Q+lSMDM`>gc8W3PK8GL0BB97C)(w%YMRg5KJi@dcM4=;-@L z{Wz*-0$+mc(h-=bf_uS8j^DXd zht8KP6#Ly;h@bUT1f#I)DM|2yy;b}3 ztqD=L6F+Cwh05hYaO~A{p}dkW7d@5l$1?_g^d@wfHw^&q$Jpxu1ITQB5DF&WDBlfC zAFgq`|IYR5Z$MiI1tSkSlV3g%yW~B)dBK>tV%=(C=j(;RQjllolT)uf3U}MB+C{{~ z&u0!DigV6pbE$30OpRKg934G7CgUZ6O5FlkrDxvxBpOj=X6RMQ;e|iH4N3~VES#6( zd2+&Fc)9Q#$1zE`B6C5$LkG4Q4pjjZbvO+_golAiT!v@myk z(WkEGfBB}+H-CQH|2MB~ExXT#=i1kHufa$ z)ZbOl*?dPHogJ6Q^Zo#8tWtNrF+K3#pIuW9eq>|~|s+t5E6UCw^Zxza`O&oom= zde!Lx7g>p;6ey@uzsch@oJ8VdD!LhiofD`3S6*ml%<5?Y7M&}K;y(>^Jfp3>BIZ3<;?w2 z6avxr%OIh5463L;MMg3V(RZn?fP*RQ)cONyzp94zl$$=i*R)t7&i~j6c9RMavuH{q z!DiReU#6Z8no@R7a6XC3ExC7&6Zn~_J>YmH`l9&eSmE=HKncebBf|E@ZX~sm*}Ne$ zUjGwTLc3!C^TiPHY}h`D>Qr#onBn6bN%dYmm?HPR*!qEhHm?W>R9T1}(&fwQdp4dx zD&M^E3$}_%4e^odyN8KLpIZXmM0CxP?ti%|X}4ipt1A&@cw(XsC6bCDesAv+pUU~0~Z zuv2M9WCm~xq3>b$ia3twAO8w(h4Qy#{A3`DQTDY+P~rp@HxT8Qz*MC27f50G!d-~4 z;)@?#;*owL2I>65s)A-G!~E0Xbj2Q#Hrox5DrjHBdKIbMS2!iIK5ejK#W~1{n3)DT zO#HSe7V`R_I)kotmv2 z;uQU}%7FDP(Kr}wBpdygb-ep?Miy0hxQ4_U~Dz% zLq)4nsLx)7003_DZ1j>qR_KmVAn$g4*$JK;EV174?dv&jt5rr5D;@q;f%Jy%5nX&6 z*_H3)nM_yp0@*0A{W}s{#w|i(aD?PI9{VysBcs)n1uP^oBMl$KVYVNDGnn^^Paif$ z)>~FyTirW!dSPA5CEe5>yN!KWW!1y`XAC;e4*rGwGg8;4Cms6Ddz-1z(;H56WEA82 zEv-hr>q@qNUS8@fPzADPSrqb^gUy6)t-TzuM!Kro@b90}S`VEfLuya=?!ie7-GjG! zXGkcGvx&f5jxIvnQ@ zCD=9LpO%+DQ)s2J)|lRl{u;i?v(NIt{tzCh0%{bw++S3?^eS2Om-#;$&^+zmQT5dB ztSKnvAY_d2%JD%)uEavzbHoC?nmgx?QU8F159I~A zhH9tdJbS`8v)?fHEX~juRNemjXp8RVtG7*0`s=ZfImo9gzz)-=pfUe*i-VYX_i)1I zN&qwFlp{a>xgolMx3C!P*Q=|$r3hR4uf~dawN^%5+ZKjI-ZGXroR_*^A{IT z-oHd0byB10qM;vk-^Au*7!x`>RkA77rtOH-Sz#6VC_=!JA?n2{pOKhm4fd@Hwa}$1 zbd8I*2@Skp-Mx^PmQ|B~`w`}&4M=j7w)1hBgorm+509#>%&l!No^@|+AK2MjTkims z)DCa0ZG(dykyca_ENZIeX&*%_gV|Yfand&BLa4!k*8zO)ot)eYkq~EN5+$wPbQJ3>_s8t0Ul!FGt$s zP?W_NgFKHv)|HA_in^Y6J|8A1aqQIm=Uot{wHB8fn2+-9bZy>dW>?uWPyAh~I{J}V zqDxGR$*A%J=b~}@3<82-qcn>(SvzOSVv$QV$x7*5=2Ln&bzoCc(|yzO+Wy z|2dJr^SmFeN11n4+W{z_aBwT_1eYsN__hjOb$YJ7N{Uqe;o|HoeqohPZ0AOomE=}l zw6=v>7a9F)q)73HBQ5R=sd8e@pjJ!y$bln)9ct577G5oVvZc%|cF@>ab?r%jw{vjG zptfa2t)r@{N_Po{pnE(P?%akoFN>>d^q_HtTjy607Xr~kV;kEjAnNH_#*iQEq+P2B zv;q5}k=)A0zP+WYcVe%ywl%fO*V^XDt!qPF@20kns%FH_D^=7eec5J0xu#arQ{xZyze_{^L%>9Ikex;{1Q1Xh z)_>w)|0`g^#lqCql>WbR#{XOzzto(K#%4$D#dzn3b9VogYdR7-?$_ryeK)W zXfcidcRGtX-o;3$kYrq_kd>wf)AOXT4uO11`eofJYpFce_m_NnmALlEF3XO9R&$W4 z`0erWtcQIknFWJ>E4I=(L|IN_-mMygsxCMg2|L+j-Oc_NWNF!jLtqkP5zQZ4_rMNs z%a5-Yx*}Snz2Dq_`S-LduEd0CC0#u%+vN_~P;}U0EL-Vi4RgYVqv5KNyRdlki=0BuR|6cz zZahQop%)56;5-&xXiq0;ZS-k#YTJ=f@V+g6pik*9liV=~)>cz4UI47c2Os*=noDXR zw2OAXV*JP8R9O_~td_t3Y2FKF^(me|^MnVj7eFE%-^1$MhkSD2+(0uKIE_QwzV8t% zPQ#{GNPw@tOcIvSAYwbxin#{300BXlNF)p)MPud_AelHuP;g2_Hc6Kuk!-_}#t1u? zs$r^}-|Bz!xR&w+wKB|mN$d58)U!(R{lYIbAzQx=H&|LCpwIXHxnDy$IcgduN65?L zc|AMa8%&1eH*1ZFIKKlEraq&EW+KFa*aL|*f1tD+7 zbrU`$&c-;Lf>CHAe^x*qNC!KV z^5}>qQeh_p5~VrI@FB$X&{%?y_1o!f+VaT?+htxK6QaFPfkh#|h|0Z@Neem!8)i-s z#wFa|Xb}_Qjy?%-uDV%p5w9pp=Xc|&j@sE4)Z=RKFPMmE-b-&6r0g-31mWyy-Jy)Q z%Z5P)p}VPxOp?U7uK;|ZD54WC6t-79<{d;&1V@4K5r-Y3Rj8LWAqNx})p8Y*2p=YS z+J^3!%r`!|Q!v9)CW4Q!tWgq9<#qYU&L6qOrYaY$MQ+N5UM=qO5+9Uneu`aQ7Wq13 z5A$W%Rqijp@}27+y*~Dy$&>o^P=(+yjB3{ww|I8CE%K0g--ZH@^y($<@Ou_Kf#P+w zik>4YYWC<|rX7mk?Uqq0_~fSh#6(43P}2sH`l{G-l(Vw(9n8i!YTs3wwvl&~8&*FI z@h__!8x3mJPVQNekm5xa^{>@#tF{qvxGYh+s}tSpD{@PAo{|F3U*sgse`JtdVIxNx zk&15JNfxJOLPaMBiYTY)g9EVm&(KM?s7Evl3Q4mkhopreVIA;rKNTlG#JE;NRSL>? z8ojZhvS3ZKBUw`tl{W{Hbt?TG;q&X@I_ekN?iIgjYU_|0@rHI_9%lW3lwkTo|ajaezK-|`HqD@F`i^T!kf@8{) zxs^CIT+u2iZ_-wHm7%VYSAAK5oXoTNwYMEVGCBjCTh5MHlCe`E1sMk&4q9M!Jk1!0 zGM$=$_U2y2aMW0hPg#XCv5u50N>NYInPKigT13rtZg&KFMVHUa;j$G9sjO-6f@Vi`GGX&q}1j`H<4Q<&D;N5X#C=qnhQ{cevCeRe9!qUK)3^ zQtjKPb>?dQQV58ksC!>CPY2EspA-GQ6K$#Y4Tww^x5E&lp<{juEUk&CMqpT4KSp5q z1w7Y*u?SJ?RgImZ^)yp(_|!SAL=D$js)xwt6|8s4t{wbQ=UmdSSB~c;*ry3oWvFo< z6jicglZvHRyL^Y0YqoQ-Ih)SN@F2tIq#xjoR)5v^KXRDOQH=r-ArO$;F%Z!2|K_m& z1pPT%n3}pc)Bl%X`VWx}>Dt<3OFDhy5&Q`5m2;DrCqD3nl@8XCXg|Nxg>M|v2_S;8 zh-wZg6{VHf+$7j@yCF;- zeZyhpxnU%Se|^6_y}jAp0eo_9^lbCed~`Doi|#pm6uOk4><8Lgz+97d%up3-VhW%W5Pe0wd$Yy z<__d$@G$Ck{QcH#PV$$3C)zjJ^g?-Y-c;dl%Ug8%2opc1UtwARJ|8}jUS8MW9&Mcb z-j40SyRaK`Y|~#blJU*z`N>k>K%u{ETRuBsZ`b_3&rXiKI#%g#`s>Em{2o3XJ^T8! z>Q*q4jGcuC63)JsM;J$qN{dueLp^35%J zKT^4j8N8fkbfFt=mbHmU@~-VX`TaF-emdX0x^#T~Ru7iPtC`rb(6d>y4t{3w)JLcd z?%&woUoOt=ejFGjlhi#qWz8k+x)0cy;RK@7xBMPn-8VvNhN+OtL4LT;_jX;pOnnEvz(=-| z*9le-A`qM-HW5UO68xhc3Cbb(M3X*{hz@JBV_lm|Zi7X}&c+)Zi&IejGN3#^Ty&o$ z4k!m#Q1Id|Q4cOVeB4 zrm%zlN-Q5U+XD%a8`6TbBh*4vYG%)NYeG~06GIh&>hZYQKF3?x2}%EyxmgHFtsjQE zobx35aVFP!?))Uio=kcEHK71#NN$(5R*^^68*jr1Sdv;y&)@}4Nor`N@wcEVHMP^W zYeG`~)!3>8*ERmtdj35?JL@bax9oR`iLIuWJDs%SP{TikoA8jue?q>0jU{pI0BOCb zmOV6-I1-l79t>7qNVnpiaYl&Mlkj@lx-h91@z)gf!laSSYObturao3h3B%(pPI5ug z(BFeCYy}=?npnb1-UT7nM8cUA8LEcAjAZ0!*de+?%lKcbQJ0^C0)rv$5)+PpLG|51H3K=bG*A;PJVbhPtTa5$k0xq>K8>qza+~V9z#Dw+~I8=Lt#W7xVWo$5<=k9t8h4J;94G(E9@d8yUeO1 zlxZf;@%aU4vy^n><3ra1?Y`0I*2{8P`SEQYeaXa|_59`1(gi~Bex|0<1w?SU?(OPb zC~@G^YNHRpwN0fTu0&}Lb!?nG0T+{4xw!>tlbRxO0*Y8ODO+3^^0=vTfxHm zjuz7>hrNgmX6QQxvUg~B?(mU0b&#?Un3LMbB9=+F^JN{B zFS8os(R!2JYp}yUigz7e7AjTop*nzP0*OFfx zDF_d7Xh&4Cr^3IIRXevsQJ%%ig8icC=9LS0bRg4#CZf&3OymUr)atDR+YkA?q)cvj zL_qV?M%9)J{UwBIMLFHK_sQiP@bu+*yeozgOK24lJ=4GmRGAMJJqibqA?LS4HdQ*RTrtH`K9MC14F#tPNk2MblZ5KPv}$_CDwL&#RpUiD*WaWiA8 zF6Y->XTk-|>(d`qrXrmB*Il%CcRM!y z82bMVz1uAZ9;8Q}?l-VFb1WDuD8Ob2A2d1I^G1&}VDfJT$SENmNJRijtHjKiE3?@n z@F}C9N;;4sEh(FgTsS7m2c0SfR`=`}or_n$#s=}W22bE66rpQX7`OmyQ+jY(>BC1R z&Yf^?QGlR|@1E*?*ZjxgG&AQ;4?jzYUzCyEP)k(~#m_!S)4vMZB0DC*03c9Y4bR9Y zC;1gVh-idBR%C29L^)r|@ZNShjxB^L!YzKA%yhK${f2WE#-{aJ{@T9Md&04g;5&^2^jnjFcGRQsQI9(h@dh9 z2hj>&Z2gka2znNN11v9hnPXEDoxZOQrG`Q`OVPA_0dczq&aL^S+Ua#P`3~VfUGs#& z(zK;0O-RO!vy`koNP7Lqd@|?kfVJ^De)CV&mo)ewdHQSDSVi^1VpW*_nfA6t6i-xE>a#U|q)-Kzu82 z^aaV-e9ZkX2<>Ugq(x_W=l8QRRnj8^Bsa1)`wP(ub*f15TQ`L@2wrG#2MwTHh1K@A zw~}H1%G!vj=Y?fLsL+%q4oDrVLbP!)#^+ZOpAu?5LAe_@$YTMA^(nL4`yh4srK$iJ zfy^?pAIEsBfi33bxVh5xkqFQ>7R6)Ep%N=!(IwJ^5N{mwy9$9zHr|6J-)FtK_pH)) z^Py;Z?w)X@Jd!G&i(KER>#wZC6)Qy;pRcG*h9{$dM1_&QA5@}PcAp*kH@SS0eZ~N< z1Ni8MB$mcE- z5*LEUYe%-ZX~D&qn$ic8)SQU?+5=(m}0UU$%I|4F3bC@=D4jP$XCScNY+tOb3L zwrmW5Qkhr#;S!Ko+nKgt-m{D`z(4$d`1h?RNh3Q5a4vIjK6P`K^4@NC9h+d$?wSPX z1c<+#@UNy4!~xI=7X$42S0`*@ipvihcwj5{X>@D~d(Y2=1=BaI51V`S8s}sVCeuDp z{0j1Jf>>+R`J3ZY0oNQ$&AdT!{jJ8D}W>gmdG0FQ-;U#F<6NQc&+@XL9qJ=jiPidfqD1V zfK^!_!bjgSPQ2&jV<0vE)h_?kO%vT4Qmf$*tm_p^iCB{f;oZjnH}w{@!n8RVV5meO>t1nf#f4tCe=pZ+D* z!T%I%ZTP+2r|Zg~_XxR-YN3VjX7}k|^kx0;JwX5n_aFM|-n#f6E{Kex`KJQI16Cm4 zifM1X4-fDzcF_NocxVa6`#4Gbl00_hk@-J3xR9nq#Ipx>Q$UZ1CS^Tvl#u)4MniXBye~`;qpi(Y;HgepTj5G)63WH$Mb(_Z@Bz!$wY}%Yb0k8w++1 z;f7CT)v;`2vd$?|&9~`+uwv+63mNC|wz;f&-Jg4!xHc+NSD;lX!pUEJ|A9d5KAp?GPnXY1a4RClUhx8#6b$9Cr)o4UUur}~1GfwWuewN@McG}Z4U~s#E5Fw$R z{87p0v}bosF?|>oTA;|IRjr2CV$XSsl1i+Sa1U43`UhI9k~^t}>mtpsv$q!uJ50Ar z*y!D266>ODeThGvD<0B2HUW^=jGI%8qUt|E-?8L`M>Qi+Nr+Aq5KtRERfq%$mOREd&*0t7_|AEQH?1S3jOXJiKnVuqmAtn)aa~#N% zwy1Y90{#aVjz*;hXY<`ZZe|}ANU*TF<31#JTw9;_yXwjQLJhXN_l5GS8ZJ_cJ*9#`QoDeu z8<}qGJDLh-;!wa1r0PDrgBYC{oF?Ys^)WE^OI0t@@faCrc-(eS1=VEoUJUxvBsLE- zG<<15U|bnhj?{NCf0B7Ei5M`qzt}w>15i>II}2F$lpz0M(jqR+Oi^lO#M35;xF?0n zBl~J$3*JI40l!5!xA9Ao#i(12CvhcuQ#HC*R(N{^yqQB%z0{a}tYGILuXiy8I*$`u zt<;FUhf`L)G-4%sS3suX!lU^Tap}SrVZnTpW%QyRD2lg0_|TO<0;qC6Ob8SDH{MvsI1c z^u3*Q+{pf6rNY?{^%S~@@*d&TLMilL`p#o%i=(-Kc_P|&DS$>zq(K)umQ~Y}0A!9} zzQ{yD{Z^bH&L80@G?aysS|g#vDqCWSA+AMBfhz!$nJWp?+~*1QFHv~9PQ^|D7S6pm zD-kLZ&=D^w$uWtlTtLuJjm7ONr25-GBze91`s{fwk0w=9h@8wmbdj;>M+?F4i6}FE089^Cxd%_cB=N))Iv(sJQL!^o=3+M>9CfKV3ef%9^O!xKNv4RHP)QWl9GytWRUKgb{d z1j}tC7ox0@;dY)X#dhCA`AO460el~=d$59{GE0a?_VX{?>#Np?{L{<6?uQ%@_!n3y zBe~qY6=31IfEq!I{a-@CtBGGZ4C*-^(;1NPjKPE#DGRB8KX|8~xE)7soLx|#6_?Z; zKzUVXm*d0_ju-i_ah~M;`>}IK8^I|OWFj#85o*9SyHfr)$K`pepmj*UB*ljvLV&oG zVBsJ1-{hV^8f4GK>rB`(nGC02MNpPAgDZYPJ)l=e#N;IWzv`Tv7HD%nzR4W~Ub;Qf z1vDPXsLyXb+7=?<5eN=FWoT2cd<}rq+W~nFKTqYIrczqioc1;zTKs^X0;1+%OVx3r zzDrda6Ht;t&j`%*zhD)NG(Dzx8WEOIBRu9}5!<43DA^H9)SxjAS=j{ zai&jEwg@lC?45Ht1sPw$8#mzgad(%=)qg<$7g+;PDeVCEV^kC1r|PLBASV3{Awob1 z!LBOtul4sK-n8e=_C5aI0MInxz4@-rpIZ(rzW1M=r>|}Rc)A%k)=3lS>o?%enO}>} zP!Z7su>(NvI4Ec~S)HuMu=xuRlqBCRe*M*B>yK>vD_HJaXMprSH9vpi+$}ceAP~7NGs6@E?A^ zcUsNadzg4fRLI);m`~ecwq=;TC1}Uan|E!Te$9eid%PY4<=pg+$9oa9t?zO3a0`MCBHzoe$kMe;;I)>l= zc$5+}jW*TvCba48N)sor<(F&W!2YO>`5wz?1;4^;jWu)Nv+_l5(&B3D05rdsbZSJ)l~TVj2PyMMM9c7 zv4Q7@c_=&+#oAJD!=>bJl~n^?pJ0}?zprVMHL$cqRrLUz8%;7T^a^lwfWW{Hf zwKq9xJ^5KKgZU-&Ho3|DCMw0!U>8@YwmuA=VF9v`BAnMTY?}YV@1l`wbksJ%*wTfR zX635-z7x1rBR+5|8h67b4`WTndg#7;XVu=bH`XitWw#M?=cGQ&hOWJc7O6AL7PdD1 zeY@Uwlbr-oE+Y>U1jOyxvXQFpRir|E%;vLMflJD7kg=SDZ0?WwX}qf?Yc(gw0qG~8>t1o zk<@EcxG06cILXV@?Cixoou$)Dc9Uy;2V1Q6tY7j;^f#vouu$d>2a^5KEg~h{k(L@1 zp!$30q`H3?Cc-%-3-OymJpZ*pF^?IShjwTMUwjrBqB!&Z=5;lMioo*Um@&s&`~D%> zqjNH(Cr4Don4z>lf2x-%nNG7#<>Zww;z6%JYuVFn?~`ntgy5w?dkxij!%-GPqe=vp z@Z{ylo$$zgC$IH6F9! zei}}91-YZI(PP6^HHeiFk)!rTuJ_-~DMX($u+Qoujq&znDP9g(@Sr_qr(*6FeN?oJ zadZX{+7(}NqF5bQ%_DmHp^T4=_@r%%Q69ODPOJ{Qhgs9hm@hD6pUzVsg|*qAHg+Dh zP6ZxwaUS9G_=jZopR69cl@?j(#Oy||gEV1;w7E$Ra3FHVwGZJugW{cqvRJq@Y`}+?}jpNSluQZnnZ66{D&8CMUp3(a0r&@ ze>S%j+(vXw+StA1oc*{wHL=O<&Z(H%(^$)RwS7N0&I-7oi;%iCF<=&s8AP-IUsIQj zM{qQIxiQ4bh5i`(jp4|=5U=7TqiZ6F8B!f0LHOmMk1q*zU+cn6Moe$bCr^z17EZ$0 zh2*B6Z+1GwGs2-S_-noSeqh5ze*63$cEIW`UBGH!)LDbr{*T-8mL}1*E555!vqTcB zmwc~6d%G9eJ?tCEj!H+?jHdV=QR!{SPo#vZsURErpfpna( zdCs*tEVW&?yB`Q|DO^>JT+-*MK2kSiCJ=UFubTKe>&od2nlc zc-(S(y$)MZd#rqTd_8zDd@J0sVt)%aB4^s%9Cd10V557LOk=G?LB*-8q(3v{&C-&6 zZFg&4@>qFU>Yte!Zh&Uff9PoCv~~g;+))XlU*p*d^iH+rub6ncxx~-NY6n}X|21w@ z3w6dm?vE(OXL&o1y#IEj%h{o!hjV<5w(5MBHoE!-DcZmP;@afx%IBWRPv5{_@#?eJ z1>;boMVobNP#!jTWz@1Zrphq*q5MtXkH54cO9qdKk^lE=_427|SYQ6h(acJ(!PBdi z(PtarH*76lPrj{R@%|e0{NorMS`BZaU-xV;9)nmPA6VAtD{T0$caE2~9!>8aZEYD{ z=g+dVv$D?65r+F8PG@#qAN={T-N)|k$4~aI`X6qSlJ@v%*rLW=0_A?)n7u7=a%t#% z$$mQ2tx=~Le{FugF|5<_tzTQOEgD&u)mZ%Y{O0Bz4Woa7|54iJ6!YT(4$9=6>1#0P z;|0XllY=Nux@Fc|HE)Z?>bUl-JGVcg`)WDtpwBM-)9BKS+vwXx(oEOuj&1wA6&?8- z?@N}qYlDZnmG0@=%h4tCe#dgE=bx)Wh`{G#+bhF|yP4Mwv!?Gj6p&|v@qK6vo-MAe z9#*(oscIc#Ypp?^1s$q{8PpI@0-8N1pn6X?unN%18P?X z+yyLmj_}2vJlDn#EcgpK<;x&s59w=6C;I0VjGj=N*c`2M;P^SGy6%tmB*3o1%UwYRr|(hi)u{}u`@`2S99v!avfgdP{>rocYV$QxaHq{R zZ#o19=QNnD$XCH+$%a5uL!rADl0K%uwzc541JVF*+$4*+@`-1JKV3T6V@U%e0JU*y zvqo^oT~vO<^2MSKI&(R39}Dpho0hwJi~w9Mfe9n|L{+hKqIWi=1;+V=iw9u+{?11S9X|B3M5^(%i7E{&6UuMQpnR0r=& z<#j^N7AlfuSI$30jQ@aX9IMvDU%et^9fcG!twgzEu$N-o@$gJTue#Pu0(mX?t(&M2 z3z6lI$`A|gs&iTk1tAfPV#pZwwoMPnughDbhtQ1R19_8#Poz!BzjGocd704-!qmad z@KW=pXU&lm4{&zK(Aql(d=yk(Zn{FgPt;<}vnVoBDDrz?7h!x#)oc9{H!iW&%7pZS)0eCO zLsG&Vkud}DBEO5gy_FvQ=Wq=Je+q8&xuX={s5iLX{bDvkDAtp?QnwEC$Nc_y{J*aO z-rVicO9%}tX9bqL{%@88{UvOksuoa26V($aqe-~mmPk1yYdKHX4ABRJDpFOu#7r_( zk0>!sN-leMeF|!Z(cgZ0}r!roz!pLr*qnD7+?96jmPpKVO{HP#udy7mrhv7-a6!x?3Mpru{Ei?8 z?}KsLM9}o2*LhAJu->HR`O$UZw?f`1yKD&$eGH!%uX?#P`zAj7)Qe06bD`QrpK!4f z_w#-v>e4y004fmsSvB~W$Ov<7==lL+7+T;Sk^1~=Fh$;z!~COt{FoxXKCKHZ-**?8 zhZIry-nY-R_idA*iq_3C%I?Z_h?_nH3-(lRs7d@Tc3e`y4n9-*F+$+yYs1Lba27D` z%2`RB}3NbDEB$K7!7&cTAZ)6cmGT%Bp1k4|tBfav3Ua*lx*$k}5 z5Rz7q%E(3i*$9x3yV8>Phe9M`zNP7H*RVVj5F`X8y zAWP#a%J|4SyMMxoH=x8Eur=a;E*f|1?AcC9_Y0oJrKrt#?So(2w7pPJTVFN#a&_1_ z`Nz9(MNKDI@>cf1VlUYK2c!)d*k-nhr-{p4h_eXY5`u19uP=>!ip#% z0~NMKcBTr+p`&8qI8wQW>>aMM!TICz*se|*Rz+XiSn~sqnR7y3VOd1MDtnmi9bA_q z_4=b`%(t>15oZU~7>d@py^Tvy8;e&~^w|TiK)io@J65xl+u}fcrRFr}UzTWNlTdv8 zNsc_Bk8vRKcrV7%!?$mxD?GNUQueg znWk9YIvz#_@D8J{E{=p@(BY-1E_Y}gZ9>8?0teGx2usw3nk{xEHm-Uq8xk+bH!s}u zpw4egWHwha5C~deOLIy4R^PimUrCTW`bF$JS99vS39*Xk7%=Um4*Q3a6zi3+${DFR zm8osVNz949cJ0$(jQnw?yn=3#K^tbmC7iuxB(v;oVGRW<` z9`~Xt#dKPl_d_seVqG`wLd^3ra~_i~xS1st}5_i&cy5li>d zA}f7@w9xnY(k|xmHgi2m>uz}Ade}WvTT$moj*8MNN`L5N5| zbl3;MxL=!t#`aAdvVSzQKx`a7o)ZO%-lr)ju=Xe(l z;XE;$-0R~D4O3ld=0CV|&#;q!jI@!=EH&(>T)%x$!i zbHp_n9nRQ2t^R7$)u9cc!*zG+MBzZ2jIL`GJcUqB!i}9RoLbYc!6ZK7GUgoqju4+| zEW_i@a$y$rVoqmM)hcjQXS;09=hSdgdlHn}d~sW&lkTe`Ta;>R6R(5xdC2N6BtOwo zjB%EUHm~S1Ng3+qb7^DD&-$eNNJX*6dfs z9fqGek0f+oSUGn#?8pjoV)-7HUiS*`XmnvVRx!ZLOp%G_RA{W{jm!6fq@kwJKQM#H z34`6LFv0gVD6+!jLrwIT2U0H-eujB;hw`p7Anh$V=vc{bH0d4v3OnM~)RLYffM!&y znMQ?x{mW6YJ9BBt3i`yy!WM#os|{y0VNl z4m)BS#=bY9OOi9$a5b3;+LvlWR1*{us|kI96FaglO*`R8nqrYR_ca^U`nX;B>7bct z=BwRN$o?zm{=QISyq_24(cNL1Fej4QSPit>duwxkIF!Vcs+30=blVbQz;fv;xhs7% zqaYU?a1hP(4YdKhuiV4cYNrmln*r8!e)YFGU;Xvxjg;jf1=!heb{EGJ4rxyugf zrv~ulUJz;@4<}eTZJ|G+^>!WcMj1qSH#muQoUiu4qW?Z&k#zd`eb9uo(J}TL$@B9 zCuA@2K&&j6i&8x7e`vg(3F)>t5BpMOx=+GacLSxYJ|$@jRYGg<+^i}nrR#0$f|Pr7 zL53}1jj(Z|dv%-r#~u_Pg7VgqVF{0kz-gyC2LHgok$9O2qr9cYozdDa~PC@|4t!;3f`pSnoD?hPu`-WN~W4QF2UK%!2g+wc5rx zSx5`P($un$eIo7O(Et6u0Y_rDX)H7THMVXVOC}kb>}kav8%R<(OdE{trFo&reR6eH1tFU> z;_T^1pDmo!%Z815zG#wY8&$QJIgZhr$MiQiLVeT*_hhmlJ38*596EAeSB^|^Rpa>+)TIB{x&rD39MIfZkfVk$^y&o zE{-=TxaVf)%Y`aYO+4`vVY%LO3myLO!)$`>h$rp$fK|M^C}n8zX-OrM+lXGQPo@ts zx)A8Eal%Vq^)Ydj%sW{SV3^bQhD7qFon$e(xCwYdiW+~&*2_qkAw*3fL~1Oly_%rm zC*LbvcrJ74A@-Ghq;|(BN6gX0n2imI)yyG&mW%RNyl4{qkb`*LD~D_&y~BGJ^AVXb zJGbWxw5fz!ci2%BzvtWeh~(hDpCWB63>X?e-RUoOnT^X1rW_afRkkgnN^u(IW{D?) zbTSY0KyE!#s@bZxmvh!baHHJMpX$T~L{(m+DnvApz%tSm%1xVUkT=;MUERH+2|zH@ z1U7R}KH)pqmD;Hkc=Vz{rO}IaTe-SZN*|C`+bV)`qg1%k5Ue=}lsi-pbxm|i6@m&h zN)EhX5k!@UyZ*e4;zY0E01;-7^I&wm02cLVpR>llO1V~Lw_Msq6}BUXh*nd3r=B50 zif9K&oo1flh=biz`=wBp&f< z6+V;MUWom!{-l~I#6CvjQ1U%6C7}vJ1h?tNV1BUf2dMnMi`pJ_jlb=d}MNX!K+M^i6 z4k($N^L=8r0=JGR)=2!L0$mo-K&IUKQsY-%j21SX6b6nl1R_lIFw}6xFb2F7jh@**GRY^%wl{(SR z=)l{SqIn7}*VoS7COWhMr`sH;2oQ)qCrKsD11@g;q)i&YwgXz4QvN z9o-a$Ei9)2n|Uof#W6kRe*e~$kzb?oYvoEkqne$7xy|<57H{J@qe$&y67y;S&7gZA zj37ceVQ{}01nC74@&Tk)>;p{XO~rP00|+)w+FpoNaI;v*S! zpf+dj>8zy_Pq(;If1j-Fqn>a5p6vl@P14QHrMl0=>cz46kwBSTPJqI7jJfF;GLxgu ztUY1ekhh(~i-1R&7eX?wHT|36I<0I``;o}uFwVwh&abTa*d+1Dv>{z*(jtNYgk%Ac zWd6-X8*oRQZqWuoirzEDa7pQW3$yf}Z&hvn$WknDp`S+#5rwG@<%1|;C&SbJ1W%dp zK<-RPX1hW&6jm16tf`p9(fLG{Dbd%jldxoWk(#h95syJ~-5YYL6^sN!&7DFkTQSB< zuoHJGySIJfh20AarG#c+YRC<$uGkd~Q!2ks-0+e1L^)T**Q-QL_A(0`!y5t*TDC-v zt2%|s@OvPUwq36ktB-ebsikh^s7`@HAM?=VqQuq#L)$)}ySr-Z%KIT&Ex0myTnW>3Cv}S2rXqJ#s@>MS`hI9_OKFB3Ybdw{^{UUC zStFL{>Oan8jRK-*PhlANLAZ9c#*LmJ=?Jw8_0;rtVI1_vaHuxSsYFwkPU`XP z+aza?M=;t`487=B`FoR#+Q#u<&Ax$+diXiREX;zJ!^z?7PxMYp2N!YirtNdXj(i|E zRsQ0FdnzDK95K_11!v4EO={GQwGF$6P?Wd7kS5zU=`o)*=^{Ce7v;Nz=Xw7W4eLz~)E{fA zi*Gs)x@&|OLWDHBN+!jkiy6fQ?yk5gJ(MbV-1=!?EvavO{j$mRG^Iu@TGQoS!Zse9 z7*F?G`wU(+l$_1ElFXC}xDKA-MFR$7Ju;!*FNUjFdUm zwX=ILJ|H<_=c$|dj57mQ4)u9tlUm=tg60M&kujc^ShZ@#um;mLVLW;rA4qoa8I+6tr+gw2r9En?{@OuNivCUkH~@i@ptG?L12x zNEIKJ3k_CV8OF*zR~hdu6lj1%+=(z^^;BkQ2U$enDBJNuA6YFe-z;1hu{pFX$R4&) zk(?>Bf!!*Tzf^jw>7P~h5nen6)t)*Wz$Adz)AeFvH8ZA%Xqe0e2Dcm?mMp{^udE~p z(FD2Nbn}V&#v`UoB`_*vgXEG8+neQL&Bh{$KT4z(1gM1O-;X!4pU4#2{(*L{ais{Q zbIa(Fiyfo6G`8i*LfGm&uF=B#QaQs0PsjH0VCe9<@nYlZEBDH(!7(RVi*;cMAF;V% zP1srbjZ-ymYf!t%ISlPA|1hp5AvHSpGp8(+8< zvV=dou|voUqM>M`;V2TPziStlS5T>C1~|8tp?AT`6fL4=Xg^~u6ZL#c+040V{MzCF z$(_iqp$oC^hz;|%$X2Ffamend(yqoYBha<=&p-NFgTy+?iiS9TF{o23 zT0>|C+aTTu1^WikA8rh9ZhW$BfY`l-Vi;o}se3($N}819 z;jbAfJ9WJdD1kSN{gsy>t*p3setZ5`5QA1_Um>HP`S%>Ue|ws|s)k3xztLRhGPoke zN8WvgOL{Vhk4$q1kyZ8_BJQ-Tr}X~lO83BhJPh5d%3l6b5S$Kgx}J~ zdXDkn!o7u*`S|)d?9KV%S|@6{4JFoXBDQ(7P+O31r7ZXhe{}UDlH)Lyb(N>O1;x1U zNlq4S&)x>HxJ};qr9bRbyUk_zd?3?GE|a)}kOhK%o+&o=Uv*C^DH$2>8{I_mg zcf>D{=KW$io_UX#;A;Hdom>kftf-Z8Dlii23JrN)5P58&e=x+&RB!6N-DKPU?XO)j zv;!oL5ah*Z8)xCqr~hMXG7OJ>MfEc%O*$AalYDf zml^8*7TPI*n6^-*e!P-vBWpE)Rwnz@+10<5eycr#WJ!cNYMX(YymBu3*$Y8K%t^YI zF861AInM1?b*Za8gOKE@i>N-=k>&`z2axp|9qu9st4H=5*t$Bb=|c1*VL%ksAA}89 zLXy6+9F)grM}1ViWy3@_ZCo;_%`9TD@-2fQDBJhzPDuCR7Hs#Mo?W57R+plX4i4A( zyo%I`DmCA&B}(0aylYag;(O}u8`u6-A|IdT(}X(eSYhl}KW9IE9hlG-VP!5NKU3?Z zF;R6MC}#BDzOU8Uq$7_u*-8U@d7#vIeM9$)zKdM88#l#GO$lx#Uv}oJZ81ET1iNF= z>hG!@aM0<;o8%vRk#uj%W-8sL8oYa(SR$Y&}yc zi>60vO6lCKbOvoapfL)Qa}l1gZ3?j%1JgUOj|N{B@kOv}LG~xzQ?#}yzYF-!;N2{L z;G2ygU4o?Xs$k}r4VE18#a@0CN3DiaK56+aH<;L~x_AF?erMy01}o=41`Vg;Ft}tZ zWTHubkMwARP3v=PxdE)zyc*$}T0?J~VlA6AZF|Fj1}x{tY$)vSKPBfHwW3rIc>M+) z%kHyqJBBVRCV^@esalD&?zp%kFGLSpe}+@E9qk_T#WM6;=;an}G6d_ZWH-2rA@-L$saR- zPbz``K;fYGl>zz=b{4>PWH$Ey`HJ;@>H#*A5x$E77Q~tK716bjQW|wq1uP^bhlel^ z9*)!&4QKi_vy^>#rAb>)o`2++vaYhiOg@<=g0D^81-4-Y2{lY27dpN&01fNWs)dt# z=t5G0DZpK&H?}cA!hp|o)Tzs)F?7{P&rac6XlnWuI_o&r=m5&ko@@lim3>jMEtJo0 z?UO^5V`L5wq4K&u$Hu=!hH&>!fnVeQ=L{zzd2UKNFme(DLKGsfQ@Me){yz=UwXu0` z3gJ)i|GPgq(Anv6Yt~Z?i2Z9ZxBOqcv@;xk$nUra;Z;I@oLP)8-qOT2kHmW@&)KQi z`(yI0nTY7ZiNF2vaI2-Jd6Av(h%hHC2N9!2(*V(eMr$5@)9dQt*>50P`g24SD2y!# zs_Nr$gnItG5HVzOmB??Q=`SZjlC`WXAB~scmy7kxU~N_s+gPxd(^((np$^Kb6QdrX!xy= zi9u#ibIQytVk1bg%_dwxN%CP#!zFu}P;Vid%}oCMAjN37?{zi5OZ;St=$0zU1=T%mT;LvWSQgg$J(z1iEH{z zlJ4K!>mGjE3zjs__|^1?gjimO@lMpec#O*rf@}~rCXzzzP*E}=rnI})jd%S`^ z{`=)6pk&hYrU0WefgRD2{yU@ft?dl|FQox4|LdPetd_YS17^S(Sa$lNspOVHe*DCmud-P6rV@UV}Aa=iuvF>8y-e1 zlIF3qN+^ayj7ez@O3CFTI(+;{mBUm}=WDDiB_HVLL?f}EJcN1@9>ds|dYVnVSOcRQ zwWO}xGcTvCBe4%j2@=%K-;IXZ6-?9!+H6PolR0)0l=7~`0yJFja}Jm;3w$excI`){ z{5O``q?qc>T~f=S!fXB5EM29zZzylzqo#wcq`CGRxGA)1 z9Ps-bX=KadP2kZs5NO)s9P)#+US`?xjJ{%W#j{-qW0mx756&7{eHFobs{Dh>-p4nT z!txFqKi5-wi&hsVJS2C4*}&J=pVjmL(El^y1}6F{y8+xxMg{?SUxNmu5gTCA+QHCH z(a^!+@7A~f%X`MZTV1Ni$)O0MzSSv_#C(zFabdhDz=#7&aLL#5Dansp`Pqq*c5=j| zdn;#D7;v*ad5`prd=7d~h|lA?sj;4x4?$}4HJogrVZrt4b>!)4DP?e%@OWdqSfP7` zfWvJ+!y~g;4}I;F{nRqY7m}k?IfY=>h~pjx+dF3K^3RZ(uItPgMW|F{mu1J>w~o%9 zE%~TVd~YLsKRo3Q8r>ZBnk~=+e0O(=u$f(6^PP6pn|^}Yp5LrXY}j_`qdB#TCrpi1 zh#P<9A9m8>%zsTJv~e{jxC*@EYGbc|cJ-)eHpva3o4tsaTL3`@?SPiT2alrVbCoLU z?))g_TleE!_;Q<~OENdP1$Bt@BiD427clH#V1Zt=HkDD;^JP2bJ-qcwt1m8>=AnwkoE_U*%`KHPo;6p#eG|5@qDc z6&>N3t`7x=4HG*+emF`uF;_BitY7Uy`>vQOZG+r2KGeHLTHkCwN;sJc_8};oURiP2 zCMXxCB6vq(*_l)$?3H|RR4r26xZUn^oGwqXj7ua7ciuQ?)k6ZoG5Sp)dTdC+FleaC z7zPG3ucX|Qli%mHQ3ICkQ(B{X-i8zMz)q9hPZfvyGOALcGR}GZmyq>G19L4XO;fp^ z-2*)z7L4T%s3U7I%E+raxr&jnuDa*g}o%X3G}%3Zi#i zvcl@k>F***lGnUSEXJ*pFswsi=jI^mj_-|3{-Blt^OxHb9FSK;A(7N0a)x7W%>_x~5j| zDZ?UK2BzzM{h_ZjR852FPnDPgEmR&Ke8Rk3+U-J8!RuQi-B7)xt5J7re8mR2+`$i? zm>FolLy@7>cOEBKAvEdtMv=sW|J*8Yhk<>^%(k5Ur7ls{EEt)X2aW>{%P31B>4!Zr zAm0dWxwxFp&QvhDW}3`1#0MKZX)-ii{gWI*K#_VA!olK`0qSp`eI*E!-Qq6f^2Cb` zKV$Btml)6bf>rIHd5?o6`})#7&J+XQjI}?l|8_!5YXps%0{A2v_(}W!Ec`INhaWow zaoqu9aXoQEc^xPn8(kZHLO6zMhRPM)`7Z3|cAuCSpEzCg252#u4yFa3n6SnyT zV2N`vB}bdk@$H1mOCXMd_b~7^XZ|1@XP|(fQio-g1e5+${mTqC2FuM{fTFwrG%0>Q&k(|0RHA%2wL6I-4iCTu&~iM|uE!!Xc* z?9yC6|N6ZSJ2L4CYxtW-t4AJ;91GJ|A?(UtQi|#73KKR07FGd<2@CB1nb76nX5-aC zk~KlzUP0Xl{w%msGC^oTK$2Hl+^%e|DlO*b^f<>%&jPB3e`hfN$FeN7XknHFpT1}K)Io~XQHJj8koM0pClDq;u~ z07QApY>36wEz!S)wZN1q4DQ=OI;{D*xv6<2#oz+^NYL#pCPRT*@jvZ~@1>>&t$DMq zBUDF3C+^1clJXMqqMK?Lv-a)?3yKm~I_i^I@M<;k!*tQww5)7cM(- zE<)92XW9AK)W9d}9KLvca$H}2eyWD4w^HGU){XCyRHEC>9+}RH;o&m3o$vj8zwCw` z-8UaMIG(LPmF(7E(7Iy7w#g?RcM9pu72kD-U8c3?CiCNkT_$2)b02eR7T@4sFjx9* z_9ZtFw@!w4Em}`^y0J4ph`(B6)YzfE|K zn=59^itR5S?R)|p2gGa?5|#c;hCupbWYPt$$Y5jO02YXf3=UJ19&iKOx_h`F2Q32y zkwCO_KCs!FR}vpmS&&*B3-VonH>v?!Lk*O_0JZo44FRsuLIN(pNgc>;4Db#Cbd6hr zY?AbVY2OW~3^Z7S0GYsbBfvH{L@(&b%%uGMY>?ep%~@CMxb7;@^2xyMAfWyx0$c~K zwg;MnYy!F?5~|9k^#V1nQD$J^Md$>wZUXPS2Wl=Zsmw_QuU0|V8qCqJ`wW?7#VB;E}j7zRF;$o z9P!CYO)de|^XS^qkIF_Ez+ny6j(%`9x&i3tlp+i`;|MkY>#3#arl9Z2L71YFjBX0n zJv!(HqHjV$7}%DA$3VoE6m$d8H(($Pyq$_}AY%Uzx+&-j4iTmp=7UXvM?3QJLv&Nn zmq#H?IavfY1!J)kx(VphrU(;0S7CJrxI#fU1%2)VVM<9osws#>44w%=Hwe9WL>Oe( z3^oYIKrFgBsH2?-Q-GyY3j+iC*eAMf)R84*-A~()bi>A((6ys?{1FDUc7i>D*6l|h z761_19vgd4aM!Xf_@xc z1GlA#H^+4X4s*cSoOpAjCgLy$++svG2fbN_2(0%|bC4Tp=(=%-%B;yaTmf!31bDLo SdwdKGGC(*RSOw-!0r3DLwmeh- literal 0 HcmV?d00001 diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h new file mode 100644 index 0000000..d49c8e8 --- /dev/null +++ b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.h +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +##########This text should be copied to the head file ############# + #Registers offset definitions + +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_OFFSET 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_DEFAULT 0x0001DA02 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_OFFSET 0x4 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_DEFAULT 0x1 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_OFFSET 0x8 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_WIDTH 16 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_OFFSET 0xC +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_OFFSET 0x10 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_OFFSET 0x14 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_OFFSET 0x18 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTHIT_0_OFFSET 0x1C +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTHIT_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTHIT_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTMISS_0_OFFSET 0x20 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTMISS_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTMISS_0_WIDTH 32 diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl new file mode 100644 index 0000000..500e13c --- /dev/null +++ b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.tcl @@ -0,0 +1,62 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# +# File: +# output_port_lookup_regs_defines.tcl +# +# Description: +# This file is automatically generated with tcl defines for the software +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +set OUTPUT_PORT_LOOKUP_REGS_ID_0_OFFSET 0x0 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_DEFAULT 0x0001DA02 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_OFFSET 0x4 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_DEFAULT 0x1 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_OFFSET 0x8 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_WIDTH 16 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_OFFSET 0xC +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_OFFSET 0x10 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_OFFSET 0x14 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_OFFSET 0x18 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_LUTHIT_0_OFFSET 0x1C +set OUTPUT_PORT_LOOKUP_REGS_LUTHIT_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_LUTHIT_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_LUTMISS_0_OFFSET 0x20 +set OUTPUT_PORT_LOOKUP_REGS_LUTMISS_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_LUTMISS_0_WIDTH 32 diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt new file mode 100644 index 0000000..0f0f981 --- /dev/null +++ b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt @@ -0,0 +1,62 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.txt +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +#define NFPLUS OUTPUT_PORT_LOOKUP ID OFFSET 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP ID DEFAULT 0x0001DA02 +#define NFPLUS OUTPUT_PORT_LOOKUP ID WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION OFFSET 0x4 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION DEFAULT 0x1 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET OFFSET 0x8 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET WIDTH 16 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP OFFSET 0xC +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG OFFSET 0x10 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN OFFSET 0x14 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT OFFSET 0x18 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTHIT OFFSET 0x1C +#define NFPLUS OUTPUT_PORT_LOOKUP LUTHIT DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTHIT WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTMISS OFFSET 0x20 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTMISS DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTMISS WIDTH 32 diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/eth_parser.v b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/eth_parser.v new file mode 100644 index 0000000..7861bff --- /dev/null +++ b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/eth_parser.v @@ -0,0 +1,144 @@ +/******************************************************************************* +* +* Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +* Junior University +* Copyright (C) 2010, 2011 Muhammad Shahbaz +* Copyright (C) 2015 Gianni Antichi +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +* +*/ +/****************************************************************************** +* +* File: +* eth_parser.v +* +* Module: +* eth_parser +* +* Author: +* Gianni Antichi, Muhammad Shahbaz +* +* Description: +* parsing of the L2 header +* +*/ + + `timescale 1ns/1ps + + module eth_parser + #(parameter C_S_AXIS_DATA_WIDTH = 512, + parameter C_S_AXIS_TUSER_WIDTH = 128, + parameter SRC_PORT_POS = 16, + parameter NUM_QUEUES = 8 + ) + ( + // --- Interface to the previous stage + input [C_S_AXIS_DATA_WIDTH-1:0] tdata, + input [C_S_AXIS_TUSER_WIDTH-1:0] tuser, + input valid, + input tlast, + + // --- Interface to output_port_lookup + output reg [47:0] dst_mac, + output reg [47:0] src_mac, + output reg eth_done, + output reg [NUM_QUEUES-1:0] src_port, + + // --- Misc + input reset, + input clk + ); + + // ------------ Internal Params -------- + + localparam NUM_STATES = 2; + localparam READ_MAC_ADDRESSES = 1; + localparam WAIT_EOP = 2; + + // ------------- Regs/ wires ----------- + + reg [47:0] dst_mac_w; + reg [47:0] src_mac_w; + reg eth_done_w; + reg [NUM_QUEUES-1:0] src_port_w; + + reg [NUM_STATES-1:0] state, state_next; + + // ------------ Logic ---------------- + + always @(*) begin + src_mac_w = 0; + dst_mac_w = 0; + eth_done_w = 0; + src_port_w = 0; + state_next = state; + + case(state) + /* read the input source header and get the first word */ + READ_MAC_ADDRESSES: begin + if(valid && tlast) begin + src_port_w = tuser[SRC_PORT_POS+7:SRC_PORT_POS]; + dst_mac_w = tdata[47:0]; + src_mac_w = tdata[95:48]; + eth_done_w = 1; + state_next = READ_MAC_ADDRESSES; + end else if(valid) begin + src_port_w = tuser[SRC_PORT_POS+7:SRC_PORT_POS]; + dst_mac_w = tdata[47:0]; + src_mac_w = tdata[95:48]; + eth_done_w = 1; + state_next = WAIT_EOP; + end + end // case: READ_WORD_1 + + WAIT_EOP: begin + if(valid && tlast) + state_next = READ_MAC_ADDRESSES; + end + endcase // case(state) + end // always @ (*) + + always @(posedge clk) begin + if(reset) begin + src_port <= {NUM_QUEUES{1'b0}}; + dst_mac <= 48'b0; + src_mac <= 48'b0; + eth_done <= 0; + + state <= READ_MAC_ADDRESSES; + end + else begin + src_port <= src_port_w; + dst_mac <= dst_mac_w; + src_mac <= src_mac_w; + eth_done <= eth_done_w; + + state <= state_next; + end // else: !if(reset) + end // always @ (posedge clk) + +endmodule // ethernet_parser + diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/mac_cam_lut.v b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/mac_cam_lut.v new file mode 100644 index 0000000..3b6493d --- /dev/null +++ b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/hdl/mac_cam_lut.v @@ -0,0 +1,178 @@ +/******************************************************************************* +* +* Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +* Junior University +* Copyright (C) 2010, 2011 Muhammad Shahbaz +* Copyright (C) 2015 Noa Zilberman +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +*/ +/****************************************************************************** +* +* File: +* mac_cam_lut.v +* +* Module: +* mac_cam_lut +* +* Author: +* Muhammad Shahbaz +* Modified by Noa Zilberman +* +* Description: +* learning CAM switch core functionality +* +*/ + + `timescale 1ns/1ps + + module mac_cam_lut + #( + parameter NUM_OUTPUT_QUEUES = 8, + parameter LUT_DEPTH_BITS = 4, + parameter LUT_DEPTH = 2**LUT_DEPTH_BITS, + parameter DEFAULT_MISS_OUTPUT_PORTS = 8'h05 // only send to the MAC txfifos not the cpu + ) + ( + // --- core functionality signals + input [47:0] dst_mac, + input [47:0] src_mac, + input [NUM_OUTPUT_QUEUES-1:0] src_port, + input lookup_req, + output reg [NUM_OUTPUT_QUEUES-1:0] dst_ports, + + // --- lookup done signal + output reg lookup_done, // pulses high on lookup done + output reg lut_miss, + output reg lut_hit, + + // --- Misc + input clk, + input reset + ); + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 {(`REG_PKTIN_WIDTH-1){1'b1}} ? 1'b1 : pktin_reg[`REG_PKTIN_WIDTH-1]; + + pktout_reg [`REG_PKTOUT_WIDTH-2:0]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tvalid && m_axis_tlast && m_axis_tready) ; + pktout_reg [`REG_PKTOUT_WIDTH-1]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tvalid && m_axis_tlast && m_axis_tready) > {(`REG_PKTOUT_WIDTH-1){1'b1}} ? + 1'b1 : pktout_reg [`REG_PKTOUT_WIDTH-1]; + luthit_reg[`REG_LUTHIT_WIDTH -2: 0] <= #1 clear_counters | luthit_reg_clear ? 'h0 : luthit_reg[`REG_LUTHIT_WIDTH-2:0] + (lut_hit & lookup_done) ; + luthit_reg[`REG_LUTHIT_WIDTH-1] <= #1 clear_counters | luthit_reg_clear ? 1'h0 : luthit_reg_clear ? 'h0 : luthit_reg[`REG_LUTHIT_WIDTH-2:0] + (lut_hit & lookup_done) + > {(`REG_LUTHIT_WIDTH-1){1'b1}} ? 1'b1 : pktin_reg[`REG_LUTHIT_WIDTH-1]; + + lutmiss_reg [`REG_LUTMISS_WIDTH-2:0]<= #1 clear_counters | lutmiss_reg_clear ? 'h0 : lutmiss_reg [`REG_LUTMISS_WIDTH-2:0] + (lut_miss & lookup_done) ; + lutmiss_reg [`REG_LUTMISS_WIDTH-1]<= #1 clear_counters | lutmiss_reg_clear ? 'h0 : lutmiss_reg [`REG_LUTMISS_WIDTH-2:0] + (lut_miss & lookup_done) > {(`REG_LUTMISS_WIDTH-1){1'b1}} ? + 1'b1 : lutmiss_reg [`REG_LUTMISS_WIDTH-1]; + + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT+cpu2ip_debug_reg; + end + + + + +endmodule // output_port_lookup + diff --git a/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/switch_lite_output_port_lookup.tcl b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/switch_lite_output_port_lookup.tcl new file mode 100644 index 0000000..92cce31 --- /dev/null +++ b/hw/lib/std/switch_lite_output_port_lookup_v1_0_0/switch_lite_output_port_lookup.tcl @@ -0,0 +1,161 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design switch_lite_output_port_lookup +set top switch_lite_output_port_lookup +set device $::env(DEVICE) +set proj_dir ./synth +set ip_version 1.00 +set lib_name NetFPGA +##################################### +# set IP paths +##################################### + +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +puts "Creating Output Port Lookup IP" +##################################### +# Project Structure & IP Build +##################################### + +read_verilog "./hdl/output_port_lookup_cpu_regs_defines.v" +read_verilog "./hdl/output_port_lookup_cpu_regs.v" +read_verilog "./hdl/eth_parser.v" +read_verilog "./hdl/mac_cam_lut.v" +read_verilog "./hdl/switch_lite_output_port_lookup.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::add_user_parameter {C_S_AXI_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property display_name {C_S_AXI_DATA_WIDTH} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXI_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property display_name {C_S_AXI_ADDR_WIDTH} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property display_name {C_M_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property display_name {C_S_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property display_name {C_M_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property display_name {C_S_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {SRC_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters SRC_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters SRC_PORT_POS] +set_property value {16} [ipx::get_user_parameters SRC_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters SRC_PORT_POS] + +ipx::add_user_parameter {DST_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters DST_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters DST_PORT_POS] +set_property value {24} [ipx::get_user_parameters DST_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters DST_PORT_POS] + +ipx::add_user_parameter {C_BASEADDR} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_BASEADDR] +set_property display_name {C_BASEADDR} [ipx::get_user_parameters C_BASEADDR] +set_property value {0x00000000} [ipx::get_user_parameters C_BASEADDR] +set_property value_format {bitstring} [ipx::get_user_parameters C_BASEADDR] + +ipx::add_user_parameter {C_LUT_DEPTH_BITS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_LUT_DEPTH_BITS] +set_property display_name {C_LUT_DEPTH_BITS} [ipx::get_user_parameters C_LUT_DEPTH_BITS] +set_property value {4} [ipx::get_user_parameters C_LUT_DEPTH_BITS] +set_property value_format {bitstring} [ipx::get_user_parameters C_LUT_DEPTH_BITS] + +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] + +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis -of_objects [ipx::current_core]] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + +file delete -force ${proj_dir} + + + + + + + + + + + + diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/Makefile b/hw/lib/std/switch_output_port_lookup_v1_0_1/Makefile new file mode 100644 index 0000000..6ee3d67 --- /dev/null +++ b/hw/lib/std/switch_output_port_lookup_v1_0_1/Makefile @@ -0,0 +1,32 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: clean + vivado -mode batch -source switch_output_port_lookup.tcl + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/data/module_generation_switch_opl.xlsm b/hw/lib/std/switch_output_port_lookup_v1_0_1/data/module_generation_switch_opl.xlsm new file mode 100644 index 0000000000000000000000000000000000000000..8594b2ad7e7dd2b7b7f07ccc19bdc7d38939f725 GIT binary patch literal 39968 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 SdwdKGGC(*RSOw-!0r3DLwmeh- literal 0 HcmV?d00001 diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.h b/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.h new file mode 100644 index 0000000..d49c8e8 --- /dev/null +++ b/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.h +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +##########This text should be copied to the head file ############# + #Registers offset definitions + +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_OFFSET 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_DEFAULT 0x0001DA02 +#define NFPLUS_OUTPUT_PORT_LOOKUP_ID_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_OFFSET 0x4 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_DEFAULT 0x1 +#define NFPLUS_OUTPUT_PORT_LOOKUP_VERSION_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_OFFSET 0x8 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_RESET_0_WIDTH 16 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_OFFSET 0xC +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_FLIP_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_OFFSET 0x10 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_DEBUG_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_OFFSET 0x14 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTIN_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_OFFSET 0x18 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_PKTOUT_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTHIT_0_OFFSET 0x1C +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTHIT_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTHIT_0_WIDTH 32 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTMISS_0_OFFSET 0x20 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTMISS_0_DEFAULT 0x0 +#define NFPLUS_OUTPUT_PORT_LOOKUP_LUTMISS_0_WIDTH 32 diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.tcl b/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.tcl new file mode 100644 index 0000000..500e13c --- /dev/null +++ b/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.tcl @@ -0,0 +1,62 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# +# File: +# output_port_lookup_regs_defines.tcl +# +# Description: +# This file is automatically generated with tcl defines for the software +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +set OUTPUT_PORT_LOOKUP_REGS_ID_0_OFFSET 0x0 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_DEFAULT 0x0001DA02 +set OUTPUT_PORT_LOOKUP_REGS_ID_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_OFFSET 0x4 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_DEFAULT 0x1 +set OUTPUT_PORT_LOOKUP_REGS_VERSION_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_OFFSET 0x8 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_RESET_0_WIDTH 16 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_OFFSET 0xC +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_FLIP_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_OFFSET 0x10 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_DEBUG_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_OFFSET 0x14 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKTIN_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_OFFSET 0x18 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_PKTOUT_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_LUTHIT_0_OFFSET 0x1C +set OUTPUT_PORT_LOOKUP_REGS_LUTHIT_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_LUTHIT_0_WIDTH 32 +set OUTPUT_PORT_LOOKUP_REGS_LUTMISS_0_OFFSET 0x20 +set OUTPUT_PORT_LOOKUP_REGS_LUTMISS_0_DEFAULT 0x0 +set OUTPUT_PORT_LOOKUP_REGS_LUTMISS_0_WIDTH 32 diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.txt b/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.txt new file mode 100644 index 0000000..0f0f981 --- /dev/null +++ b/hw/lib/std/switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.txt @@ -0,0 +1,62 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// +// File: +// output_port_lookup_regs_defines.txt +// +// Description: +// This file is automatically generated with header defines for the software +// +// This software was developed by +// Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +#define NFPLUS OUTPUT_PORT_LOOKUP ID OFFSET 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP ID DEFAULT 0x0001DA02 +#define NFPLUS OUTPUT_PORT_LOOKUP ID WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION OFFSET 0x4 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION DEFAULT 0x1 +#define NFPLUS OUTPUT_PORT_LOOKUP VERSION WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET OFFSET 0x8 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP RESET WIDTH 16 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP OFFSET 0xC +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP FLIP WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG OFFSET 0x10 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP DEBUG WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN OFFSET 0x14 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTIN WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT OFFSET 0x18 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP PKTOUT WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTHIT OFFSET 0x1C +#define NFPLUS OUTPUT_PORT_LOOKUP LUTHIT DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTHIT WIDTH 32 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTMISS OFFSET 0x20 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTMISS DEFAULT 0x0 +#define NFPLUS OUTPUT_PORT_LOOKUP LUTMISS WIDTH 32 diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/eth_parser.v b/hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/eth_parser.v new file mode 100644 index 0000000..5ceabb9 --- /dev/null +++ b/hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/eth_parser.v @@ -0,0 +1,144 @@ +/******************************************************************************* +* +* Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +* Junior University +* Copyright (C) 2010, 2011 Muhammad Shahbaz +* Copyright (C) 2015 Gianni Antichi +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +* +*/ +/****************************************************************************** +* +* File: +* eth_parser.v +* +* Module: +* eth_parser +* +* Author: +* Gianni Antichi, Muhammad Shahbaz +* +* Description: +* parsing of the L2 header +* +*/ + + `timescale 1ns/1ps + + module eth_parser + #(parameter C_S_AXIS_DATA_WIDTH = 256, + parameter C_S_AXIS_TUSER_WIDTH = 128, + parameter SRC_PORT_POS = 16, + parameter NUM_QUEUES = 8 + ) + ( + // --- Interface to the previous stage + input [C_S_AXIS_DATA_WIDTH-1:0] tdata, + input [C_S_AXIS_TUSER_WIDTH-1:0] tuser, + input valid, + input tlast, + + // --- Interface to output_port_lookup + output reg [47:0] dst_mac, + output reg [47:0] src_mac, + output reg eth_done, + output reg [NUM_QUEUES-1:0] src_port, + + // --- Misc + input reset, + input clk + ); + + // ------------ Internal Params -------- + + localparam NUM_STATES = 2; + localparam READ_MAC_ADDRESSES = 1; + localparam WAIT_EOP = 2; + + // ------------- Regs/ wires ----------- + + reg [47:0] dst_mac_w; + reg [47:0] src_mac_w; + reg eth_done_w; + reg [NUM_QUEUES-1:0] src_port_w; + + reg [NUM_STATES-1:0] state, state_next; + + // ------------ Logic ---------------- + + always @(*) begin + src_mac_w = 0; + dst_mac_w = 0; + eth_done_w = 0; + src_port_w = 0; + state_next = state; + + case(state) + /* read the input source header and get the first word */ + READ_MAC_ADDRESSES: begin + if(valid && tlast) begin + src_port_w = tuser[SRC_PORT_POS+7:SRC_PORT_POS]; + dst_mac_w = tdata[47:0]; + src_mac_w = tdata[95:48]; + eth_done_w = 1; + state_next = READ_MAC_ADDRESSES; + end else if(valid) begin + src_port_w = tuser[SRC_PORT_POS+7:SRC_PORT_POS]; + dst_mac_w = tdata[47:0]; + src_mac_w = tdata[95:48]; + eth_done_w = 1; + state_next = WAIT_EOP; + end + end // case: READ_WORD_1 + + WAIT_EOP: begin + if(valid && tlast) + state_next = READ_MAC_ADDRESSES; + end + endcase // case(state) + end // always @ (*) + + always @(posedge clk) begin + if(reset) begin + src_port <= {NUM_QUEUES{1'b0}}; + dst_mac <= 48'b0; + src_mac <= 48'b0; + eth_done <= 0; + + state <= READ_MAC_ADDRESSES; + end + else begin + src_port <= src_port_w; + dst_mac <= dst_mac_w; + src_mac <= src_mac_w; + eth_done <= eth_done_w; + + state <= state_next; + end // else: !if(reset) + end // always @ (posedge clk) + +endmodule // ethernet_parser + diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/mac_cam_lut.v b/hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/mac_cam_lut.v new file mode 100644 index 0000000..7ed0c24 --- /dev/null +++ b/hw/lib/std/switch_output_port_lookup_v1_0_1/hdl/mac_cam_lut.v @@ -0,0 +1,355 @@ +/******************************************************************************* +* +* Copyright (C) 2013 Gianni Antichi +* Copyright (C) 2015 Noa Zilberman +* All rights reserved. +* +* This software was developed by +* Stanford University and the University of Cambridge Computer Laboratory +* under National Science Foundation under Grant No. CNS-0855268, +* the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +* by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +* as part of the DARPA MRC research programme. +* +* @NETFPGA_LICENSE_HEADER_START@ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @NETFPGA_LICENSE_HEADER_END@ +*/ +/****************************************************************************** +* +* File: +* mac_cam_lut.v +* +* Module: +* mac_cam_lut +* +* Author: +* Gianni Antichi +* Modified by Noa Zilberman +* +* Description: +* learning CAM switch core functionality +* +*/ + +`timescale 1ns/1ps + +module mac_cam_lut + #(parameter NUM_OUTPUT_QUEUES = 8, + parameter LUT_DEPTH_BITS = 4, + parameter LUT_DEPTH = 2**LUT_DEPTH_BITS, + parameter DEFAULT_MISS_OUTPUT_PORTS = 8'h05) // only send to the MAC txfifos not the cpu + + ( // --- core functionality signals + input [47:0] dst_mac, + input [47:0] src_mac, + input [NUM_OUTPUT_QUEUES-1:0] src_port, + input lookup_req, + output[NUM_OUTPUT_QUEUES-1:0] dst_ports, + + // --- lookup done signal + output reg lookup_done, // pulses high on lookup done + output reg lut_miss, + output reg lut_hit, + + // --- Misc + input clk, + input reset + + ); + + + function integer log2; + input integer number; + begin + log2=0; + while(2**log2 {(`REG_PKTIN_WIDTH-1){1'b1}} ? 1'b1 : pktin_reg[`REG_PKTIN_WIDTH-1]; + + pktout_reg [`REG_PKTOUT_WIDTH-2:0]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tvalid && m_axis_tlast && m_axis_tready) ; + pktout_reg [`REG_PKTOUT_WIDTH-1]<= #1 clear_counters | pktout_reg_clear ? 'h0 : pktout_reg [`REG_PKTOUT_WIDTH-2:0] + (m_axis_tvalid && m_axis_tlast && m_axis_tready) > {(`REG_PKTOUT_WIDTH-1){1'b1}} ? + 1'b1 : pktout_reg [`REG_PKTOUT_WIDTH-1]; + luthit_reg[`REG_LUTHIT_WIDTH -2: 0] <= #1 clear_counters | luthit_reg_clear ? 'h0 : luthit_reg[`REG_LUTHIT_WIDTH-2:0] + (lut_hit & lookup_done) ; + luthit_reg[`REG_LUTHIT_WIDTH-1] <= #1 clear_counters | luthit_reg_clear ? 1'h0 : luthit_reg_clear ? 'h0 : luthit_reg[`REG_LUTHIT_WIDTH-2:0] + (lut_hit & lookup_done) + > {(`REG_LUTHIT_WIDTH-1){1'b1}} ? 1'b1 : pktin_reg[`REG_LUTHIT_WIDTH-1]; + + lutmiss_reg [`REG_LUTMISS_WIDTH-2:0]<= #1 clear_counters | lutmiss_reg_clear ? 'h0 : lutmiss_reg [`REG_LUTMISS_WIDTH-2:0] + (lut_miss & lookup_done) ; + lutmiss_reg [`REG_LUTMISS_WIDTH-1]<= #1 clear_counters | lutmiss_reg_clear ? 'h0 : lutmiss_reg [`REG_LUTMISS_WIDTH-2:0] + (lut_miss & lookup_done) > {(`REG_LUTMISS_WIDTH-1){1'b1}} ? + 1'b1 : lutmiss_reg [`REG_LUTMISS_WIDTH-1]; + + ip2cpu_debug_reg <= #1 `REG_DEBUG_DEFAULT+cpu2ip_debug_reg; + end + +endmodule // output_port_lookup + diff --git a/hw/lib/std/switch_output_port_lookup_v1_0_1/switch_output_port_lookup.tcl b/hw/lib/std/switch_output_port_lookup_v1_0_1/switch_output_port_lookup.tcl new file mode 100644 index 0000000..f7dfd4b --- /dev/null +++ b/hw/lib/std/switch_output_port_lookup_v1_0_1/switch_output_port_lookup.tcl @@ -0,0 +1,153 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design switch_output_port_lookup +set top switch_output_port_lookup +set device $::env(DEVICE) +set proj_dir ./synth +set ip_version 1.01 +set lib_name NetFPGA +##################################### +# set IP paths +##################################### + +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +puts "Creating Output Port Lookup IP" +# Project Constraints +##################################### +# Project Structure & IP Build +##################################### + +read_verilog "./hdl/output_port_lookup_cpu_regs_defines.v" +read_verilog "./hdl/output_port_lookup_cpu_regs.v" +read_verilog "./hdl/eth_parser.v" +read_verilog "./hdl/mac_cam_lut.v" +read_verilog "./hdl/switch_output_port_lookup.v" +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {NetFPGA} [ipx::current_core] +set_property company_url {http://www.netfpga.org} [ipx::current_core] +set_property vendor {NetFPGA} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::add_user_parameter {C_S_AXI_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property display_name {C_S_AXI_DATA_WIDTH} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXI_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property display_name {C_S_AXI_ADDR_WIDTH} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value {32} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXI_ADDR_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property display_name {C_M_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property display_name {C_S_AXIS_DATA_WIDTH} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value {512} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_DATA_WIDTH] + +ipx::add_user_parameter {C_M_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property display_name {C_M_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_M_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {C_S_AXIS_TUSER_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property display_name {C_S_AXIS_TUSER_WIDTH} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value {128} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_S_AXIS_TUSER_WIDTH] + +ipx::add_user_parameter {SRC_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters SRC_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters SRC_PORT_POS] +set_property value {16} [ipx::get_user_parameters SRC_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters SRC_PORT_POS] + +ipx::add_user_parameter {DST_PORT_POS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters DST_PORT_POS] +set_property display_name {SRC_PORT_POS} [ipx::get_user_parameters DST_PORT_POS] +set_property value {24} [ipx::get_user_parameters DST_PORT_POS] +set_property value_format {long} [ipx::get_user_parameters DST_PORT_POS] + +ipx::add_user_parameter {C_BASEADDR} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_BASEADDR] +set_property display_name {C_BASEADDR} [ipx::get_user_parameters C_BASEADDR] +set_property value {0x00000000} [ipx::get_user_parameters C_BASEADDR] +set_property value_format {bitstring} [ipx::get_user_parameters C_BASEADDR] + +ipx::add_user_parameter {C_CAM_LUT_DEPTH_BITS} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_CAM_LUT_DEPTH_BITS] +set_property display_name {C_CAM_LUT_DEPTH_BITS} [ipx::get_user_parameters C_CAM_LUT_DEPTH_BITS] +set_property value {4} [ipx::get_user_parameters C_CAM_LUT_DEPTH_BITS] +set_property value_format {bitstring} [ipx::get_user_parameters C_CAM_LUT_DEPTH_BITS] + +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore NetFPGA:NetFPGA:fallthrough_small_fifo:1.00 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] +ipx::add_subcore xilinx:xilinx:cam:1.10 [ipx::get_file_groups xilinx_anylanguagesynthesis -of_objects [ipx::current_core]] +ipx::add_subcore xilinx:xilinx:cam:1.10 [ipx::get_file_groups xilinx_anylanguagebehavioralsimulation -of_objects [ipx::current_core]] + +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces m_axis -of_objects [ipx::current_core]] +ipx::add_bus_parameter FREQ_HZ [ipx::get_bus_interfaces s_axis -of_objects [ipx::current_core]] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project + +file delete -force ${proj_dir} + diff --git a/hw/lib/xilinx/cam_v1_1_0/Makefile b/hw/lib/xilinx/cam_v1_1_0/Makefile new file mode 100644 index 0000000..65fd0d5 --- /dev/null +++ b/hw/lib/xilinx/cam_v1_1_0/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +.PHONY: all +.PHONY: update +.PHONY: sim + +all: clean + vivado -mode tcl -source cam.tcl + +update: + unzip xapp1151_Param_CAM.zip + bash ./scripts/run_update_lib.sh + cp -f ./xapp1151_cam_v1_1/src/vhdl/*.vhd ./hdl/vhdl/cam/ + +sim: + bash ./sim/run_cam_sim.sh + +clean: + rm -rf vivado*.* *.xml xgui/ .Xil* ip_pro* xv* *.wdb xsim* xe* we* diff --git a/hw/lib/xilinx/cam_v1_1_0/README b/hw/lib/xilinx/cam_v1_1_0/README new file mode 100644 index 0000000..b2b2a4a --- /dev/null +++ b/hw/lib/xilinx/cam_v1_1_0/README @@ -0,0 +1,43 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +Follow the instruction below to create a TCAM IP for NetFPGA NFPLUS platform step by step. The TCAM IPs created by the instruction is based on SRL only to support Ternary mode. More detailed information of the TCAM can be found on xapp1151_Param_CAM.pdf in Xilinx web site. TCAM IPs on NFPLUS platform are separated into TCAM and CAM, but they are almost the same and share the same libraries. + +1) At first, users need to find and download xapp1151 module on Xilinx web site. After searching 'xapp1151', xapp1151_Param_CAM.zip and related documents can be downloaded from the web site. + +2) Copy xapp1151_Param_CAM.zip into the NetFPGA-NFPLUS-live/lib/hw/xilinx/cores/cam_v*_*_*/ and go to the 'cam_v*_*_*' directory. + +3) Run 'make update' to decompress and update the xapp1151 libraries. + +4) Run 'make sim' and find what is the simulation result. Before run 'make sim', source Vivado license to run the tool commands. + +5) Run 'make' to create IP. + + +If it is succeeded, now users can call the TCAM IP in the project for block design and ip creation. + +(Note: Whenever you run 'make clean' in the $NFPLUS_FOLDER, you need to run again 'make' into cam_v*_*_* folder, to create the IP.) diff --git a/hw/lib/xilinx/cam_v1_1_0/cam.tcl b/hw/lib/xilinx/cam_v1_1_0/cam.tcl new file mode 100644 index 0000000..8e76996 --- /dev/null +++ b/hw/lib/xilinx/cam_v1_1_0/cam.tcl @@ -0,0 +1,113 @@ +# +# Copyright (c) 2015 University of Cambridge +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Set variables +set lib_name xilinx +set ip_version 1.10 +set design cam + +set device $::env(DEVICE) +set proj_dir ip_proj + +# Project setting +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip + +set_property source_mgmt_mode All [current_project] +set_property top ${design} [current_fileset] + +# IP build +read_verilog "./hdl/verilog/cam.v" +read_verilog "./hdl/verilog/cam_wrapper.v" + +read_vhdl "./hdl/vhdl/cam/cam_init_file_pack_xst.vhd" +read_vhdl "./hdl/vhdl/cam/cam_pkg.vhd" + +read_vhdl "./hdl/vhdl/cam/cam_input_ternary_ternenc.vhd" +read_vhdl "./hdl/vhdl/cam/cam_input_ternary.vhd" +read_vhdl "./hdl/vhdl/cam/cam_input.vhd" +read_vhdl "./hdl/vhdl/cam/cam_control.vhd" +read_vhdl "./hdl/vhdl/cam/cam_decoder.vhd" +read_vhdl "./hdl/vhdl/cam/cam_match_enc.vhd" + +read_vhdl "./hdl/vhdl/cam/cam_regouts.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_srl16_ternwrcomp.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_srl16_wrcomp.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_srl16_block_word.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_srl16_block.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_srl16.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_blk_extdepth_prim.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_blk_extdepth.vhd" +read_vhdl "./hdl/vhdl/cam/dmem.vhd" +read_vhdl "./hdl/vhdl/cam/cam_mem_blk.vhd" + +read_vhdl "./hdl/vhdl/cam/cam_mem.vhd" +read_vhdl "./hdl/vhdl/cam/cam_rtl.vhd" +read_vhdl "./hdl/vhdl/cam/cam_top.vhd" + +update_compile_order -fileset sources_1 + +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {xilinx} [ipx::current_core] +set_property company_url {http://www.xilinx.com} [ipx::current_core] +set_property vendor {xilinx} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::add_user_parameter {C_TCAM_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_TCAM_ADDR_WIDTH] +set_property display_name {C_TCAM_ADDR_WIDTH} [ipx::get_user_parameters C_TCAM_ADDR_WIDTH] +set_property value {5} [ipx::get_user_parameters C_TCAM_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_TCAM_ADDR_WIDTH] + +ipx::add_user_parameter {C_TCAM_DATA_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_TCAM_DATA_WIDTH] +set_property display_name {C_TCAM_DATA_WIDTH} [ipx::get_user_parameters C_TCAM_DATA_WIDTH] +set_property value {48} [ipx::get_user_parameters C_TCAM_DATA_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_TCAM_DATA_WIDTH] + +ipx::add_user_parameter {C_TCAM_MATCH_ADDR_WIDTH} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters C_TCAM_MATCH_ADDR_WIDTH] +set_property display_name {C_TCAM_MATCH_ADDR_WIDTH} [ipx::get_user_parameters C_TCAM_MATCH_ADDR_WIDTH] +set_property value {5} [ipx::get_user_parameters C_TCAM_MATCH_ADDR_WIDTH] +set_property value_format {long} [ipx::get_user_parameters C_TCAM_MATCH_ADDR_WIDTH] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog + +close_project +exit + diff --git a/hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam.v b/hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam.v new file mode 100644 index 0000000..8c7cc3a --- /dev/null +++ b/hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam.v @@ -0,0 +1,70 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// This software was developed by SRI International and the University of +// Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1, +// National Science Foundation under Grant No. CNS-0855268, and Defense +// Advanced Research Projects Agency (DARPA) and Air Force Research Laboratory +// (AFRL), under contract FA8750-11-C-0249. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +`timescale 1ns/1ps + +module cam +#( + parameter C_TCAM_ADDR_WIDTH = 5, + parameter C_TCAM_DATA_WIDTH = 32, + parameter C_TCAM_ADDR_TYPE = 0, + parameter C_TCAM_MATCH_ADDR_WIDTH = 5 +) +( + input CLK, + input WE, + input [C_TCAM_ADDR_WIDTH-1:0] ADDR_WR, + input [C_TCAM_DATA_WIDTH-1:0] DIN, + output BUSY, + + input [C_TCAM_DATA_WIDTH-1:0] CMP_DIN, + output MATCH, + output [C_TCAM_MATCH_ADDR_WIDTH-1:0] MATCH_ADDR +); + +localparam C_TCAM_DATA_DEPTH = 2**C_TCAM_ADDR_WIDTH; + +cam_wrapper +#( + .C_TCAM_ADDR_WIDTH ( C_TCAM_ADDR_WIDTH ), + .C_TCAM_DATA_WIDTH ( C_TCAM_DATA_WIDTH ), + .C_TCAM_ADDR_TYPE ( C_TCAM_ADDR_TYPE ), + .C_TCAM_MATCH_ADDR_WIDTH ( C_TCAM_MATCH_ADDR_WIDTH ) +) +cam_wrapper +( + .CLK ( CLK ), + .WE ( WE ), + .WR_ADDR ( ADDR_WR ), + .DIN ( DIN ), + .BUSY ( BUSY ), + + .MATCH ( MATCH ), + .MATCH_ADDR ( MATCH_ADDR ), + .CMP_DIN ( CMP_DIN ) +); + +endmodule diff --git a/hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam_wrapper.v b/hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam_wrapper.v new file mode 100644 index 0000000..834d71a --- /dev/null +++ b/hw/lib/xilinx/cam_v1_1_0/hdl/verilog/cam_wrapper.v @@ -0,0 +1,85 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// This software was developed by SRI International and the University of +// Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1, +// National Science Foundation under Grant No. CNS-0855268, and Defense +// Advanced Research Projects Agency (DARPA) and Air Force Research Laboratory +// (AFRL), under contract FA8750-11-C-0249. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// +`timescale 1ns/1ps + +module cam_wrapper +#( + parameter C_TCAM_ADDR_WIDTH = 4, + parameter C_TCAM_DATA_WIDTH = 16, + parameter C_TCAM_ADDR_TYPE = 0, + parameter C_TCAM_MATCH_ADDR_WIDTH = 4 +) +( + input CLK, + input WE, + input [C_TCAM_ADDR_WIDTH-1:0] WR_ADDR, + input [C_TCAM_DATA_WIDTH-1:0] DIN, + output BUSY, + + input [C_TCAM_DATA_WIDTH-1:0] CMP_DIN, + output MATCH, + output [C_TCAM_MATCH_ADDR_WIDTH-1:0] MATCH_ADDR +); + +localparam C_TCAM_DATA_DEPTH = 2**C_TCAM_ADDR_WIDTH; + +cam_top +#( + .C_ADDR_TYPE ( C_TCAM_ADDR_TYPE ), + .C_DEPTH ( C_TCAM_DATA_DEPTH ), + .C_FAMILY ( "virtex5" ), + .C_HAS_CMP_DIN ( 1 ), + .C_HAS_EN ( 0 ), + .C_HAS_MULTIPLE_MATCH ( 0 ), + .C_HAS_READ_WARNING ( 0 ), + .C_HAS_SINGLE_MATCH ( 0 ), + .C_HAS_WE ( 1 ), + .C_MATCH_RESOLUTION_TYPE ( 0 ), + .C_MEM_INIT ( 0 ), + .C_MEM_TYPE ( 1 ), + .C_REG_OUTPUTS ( 0 ), + .C_TERNARY_MODE ( 0 ), + .C_WIDTH ( C_TCAM_DATA_WIDTH ) +) +cam_top ( + .CLK ( CLK ), + .CMP_DATA_MASK ( {C_TCAM_DATA_WIDTH{1'b0}} ), + .CMP_DIN ( CMP_DIN ), + .DATA_MASK ( {C_TCAM_DATA_WIDTH{1'b0}} ), + .DIN ( DIN ), + .EN ( 1'b1 ), + .WE ( WE ), + .WR_ADDR ( WR_ADDR ), + .BUSY ( BUSY ), + .MATCH ( MATCH ), + .MATCH_ADDR ( MATCH_ADDR ), + .MULTIPLE_MATCH ( ), + .READ_WARNING ( ), + .SINGLE_MATCH ( ) +); + +endmodule diff --git a/hw/lib/xilinx/cam_v1_1_0/hdl/vhdl/cam/.keep b/hw/lib/xilinx/cam_v1_1_0/hdl/vhdl/cam/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/lib/xilinx/cam_v1_1_0/scripts/run_update_lib.sh b/hw/lib/xilinx/cam_v1_1_0/scripts/run_update_lib.sh new file mode 100644 index 0000000..84d4280 --- /dev/null +++ b/hw/lib/xilinx/cam_v1_1_0/scripts/run_update_lib.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +cam_dir=./xapp1151_cam_v1_1/src + +file_list=`find $cam_dir -name *.vhd` + +for in_file in $file_list; do + + sed -i -e 's/LIBRARY cam/LIBRARY xil_defaultlib/' $in_file + sed -i -e 's/ENTITY cam\./ENTITY xil_defaultlib\./' $in_file + sed -i -e 's/USE cam\./USE xil_defaultlib\./' $in_file +done + +sed -i '/virtex6l/a CONSTANT VIRTEX7 : STRING := "virtex7";' $cam_dir/vhdl/cam_pkg.vhd +sed -i -e 's/spartan6)/spartan6) OR (C_FAMILY = virtex7)/' $cam_dir/vhdl/cam_rtl.vhd +sed -i -e 's/or spartan6/spartan6, or virtex7/' $cam_dir/vhdl/cam_rtl.vhd diff --git a/hw/lib/xilinx/tcam_v1_1_0/Makefile b/hw/lib/xilinx/tcam_v1_1_0/Makefile new file mode 100644 index 0000000..da1f108 --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +.PHONY: all +.PHONY: update +.PHONY: sim + +all: clean + vivado -mode tcl -source tcam.tcl + +update: + unzip xapp1151_Param_CAM.zip + bash ./scripts/run_update_lib.sh + cp -f ./xapp1151_cam_v1_1/src/vhdl/*.vhd ./hdl/vhdl/tcam/ + +sim: + bash ./sim/run_tcam_sim.sh + +clean: + rm -rf vivado*.* *.xml xgui/ .Xil* ip_pro* xv* *.wdb xsim* xe* we* diff --git a/hw/lib/xilinx/tcam_v1_1_0/README b/hw/lib/xilinx/tcam_v1_1_0/README new file mode 100644 index 0000000..f737e21 --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/README @@ -0,0 +1,43 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +Follow the instruction below to create a TCAM IP for NetFPGA NFPLUS platform step by step. The TCAM IPs created by the instruction is based on SRL only to support Ternary mode. More detailed information of the TCAM can be found on xapp1151_Param_CAM.pdf in Xilinx web site. TCAM IPs on NFPLUS platform are separated into TCAM and CAM, but they are almost the same and share the same libraries. + +1) At first, users need to find and download xapp1151 module on Xilinx web site. After searching 'xapp1151', xapp1151_Param_CAM.zip and related documents can be downloaded from the web site. + +2) Copy xapp1151_Param_CAM.zip into the NetFPGA-NFPLUS-live/lib/hw/xilinx/cores/tcam_v*_*_*/ and go to the 'tcam_v*_*_*' directory. + +3) Run 'make update' to decompress and update the xapp1151 libraries. + +4) Run 'make sim' and find what is the simulation result. Before run 'make sim', source Vivado license to run the tool commands. + +5) Run 'make' to create IP. + + +If it is succeeded, now users can call the TCAM IP in the project for block design and ip creation. + +(Note: Whenever you run 'make clean' in the $NFPLUS_FOLDER, you need to run again 'make' into tcam_v*_*_* folder, to create the IP.) diff --git a/hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam.v b/hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam.v new file mode 100644 index 0000000..da9890c --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam.v @@ -0,0 +1,73 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// This software was developed by SRI International and the University of +// Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1, +// National Science Foundation under Grant No. CNS-0855268, and Defense +// Advanced Research Projects Agency (DARPA) and Air Force Research Laboratory +// (AFRL), under contract FA8750-11-C-0249. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ + +`timescale 1ns/1ps + +module tcam +#( + parameter C_TCAM_ADDR_WIDTH = 5, + parameter C_TCAM_DATA_WIDTH = 32, + parameter C_TCAM_ADDR_TYPE = 0, + parameter C_TCAM_MATCH_ADDR_WIDTH = 5 +) +( + input CLK, + input WE, + input [C_TCAM_ADDR_WIDTH-1:0] ADDR_WR, + input [C_TCAM_DATA_WIDTH-1:0] DIN, + input [C_TCAM_DATA_WIDTH-1:0] DATA_MASK, + output BUSY, + + input [C_TCAM_DATA_WIDTH-1:0] CMP_DIN, + input [C_TCAM_DATA_WIDTH-1:0] CMP_DATA_MASK, + output MATCH, + output [C_TCAM_MATCH_ADDR_WIDTH-1:0] MATCH_ADDR +); + + +tcam_wrapper +#( + .C_TCAM_ADDR_WIDTH ( C_TCAM_ADDR_WIDTH ), + .C_TCAM_DATA_WIDTH ( C_TCAM_DATA_WIDTH ), + .C_TCAM_ADDR_TYPE ( C_TCAM_ADDR_TYPE ), + .C_TCAM_MATCH_ADDR_WIDTH ( C_TCAM_MATCH_ADDR_WIDTH ) +) +tcam_wrapper +( + .CLK ( CLK ), + .WE ( WE ), + .WR_ADDR ( ADDR_WR ), + .DIN ( DIN ), + .DATA_MASK ( DATA_MASK ), + .BUSY ( BUSY ), + + .MATCH ( MATCH ), + .MATCH_ADDR ( MATCH_ADDR ), + .CMP_DIN ( CMP_DIN ), + .CMP_DATA_MASK ( CMP_DATA_MASK ) +); + +endmodule diff --git a/hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam_wrapper.v b/hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam_wrapper.v new file mode 100644 index 0000000..040b064 --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/hdl/verilog/tcam_wrapper.v @@ -0,0 +1,87 @@ +// +// Copyright (c) 2015 University of Cambridge +// All rights reserved. +// +// This software was developed by SRI International and the University of +// Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1, +// National Science Foundation under Grant No. CNS-0855268, and Defense +// Advanced Research Projects Agency (DARPA) and Air Force Research Laboratory +// (AFRL), under contract FA8750-11-C-0249. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ + +`timescale 1ns/1ps + +module tcam_wrapper +#( + parameter C_TCAM_ADDR_WIDTH = 4, + parameter C_TCAM_DATA_WIDTH = 16, + parameter C_TCAM_ADDR_TYPE = 0, + parameter C_TCAM_MATCH_ADDR_WIDTH = 4 +) +( + input CLK, + input WE, + input [C_TCAM_ADDR_WIDTH-1:0] WR_ADDR, + input [C_TCAM_DATA_WIDTH-1:0] DIN, + input [C_TCAM_DATA_WIDTH-1:0] DATA_MASK, + output BUSY, + + input [C_TCAM_DATA_WIDTH-1:0] CMP_DIN, + input [C_TCAM_DATA_WIDTH-1:0] CMP_DATA_MASK, + output MATCH, + output [C_TCAM_MATCH_ADDR_WIDTH-1:0] MATCH_ADDR +); + +localparam C_TCAM_DATA_DEPTH = 2**C_TCAM_ADDR_WIDTH; + +cam_top +#( + .C_ADDR_TYPE ( C_TCAM_ADDR_TYPE ), + .C_DEPTH ( C_TCAM_DATA_DEPTH ), + .C_FAMILY ( "virtex5" ), + .C_HAS_CMP_DIN ( 1 ), + .C_HAS_EN ( 0 ), + .C_HAS_MULTIPLE_MATCH ( 0 ), + .C_HAS_READ_WARNING ( 0 ), + .C_HAS_SINGLE_MATCH ( 0 ), + .C_HAS_WE ( 1 ), + .C_MATCH_RESOLUTION_TYPE ( 0 ), + .C_MEM_INIT ( 0 ), + .C_MEM_TYPE ( 0 ), + .C_REG_OUTPUTS ( 0 ), + .C_TERNARY_MODE ( 1 ), + .C_WIDTH ( C_TCAM_DATA_WIDTH ) +) +cam_top ( + .CLK ( CLK ), + .CMP_DATA_MASK ( CMP_DATA_MASK ), + .CMP_DIN ( CMP_DIN ), + .DATA_MASK ( DATA_MASK ), + .DIN ( DIN ), + .EN ( 1'b1 ), + .WE ( WE ), + .WR_ADDR ( WR_ADDR ), + .BUSY ( BUSY ), + .MATCH ( MATCH ), + .MATCH_ADDR ( MATCH_ADDR ), + .MULTIPLE_MATCH ( ), + .READ_WARNING ( ), + .SINGLE_MATCH ( ) +); + +endmodule diff --git a/hw/lib/xilinx/tcam_v1_1_0/hdl/vhdl/tcam/.keep b/hw/lib/xilinx/tcam_v1_1_0/hdl/vhdl/tcam/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/lib/xilinx/tcam_v1_1_0/scripts/run_update_lib.sh b/hw/lib/xilinx/tcam_v1_1_0/scripts/run_update_lib.sh new file mode 100644 index 0000000..2526cf8 --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/scripts/run_update_lib.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +cam_dir=./xapp1151_cam_v1_1/src + +file_list=`find $cam_dir -name *.vhd` + +for in_file in $file_list; do + + sed -i -e 's/LIBRARY cam/LIBRARY xil_defaultlib/' $in_file + sed -i -e 's/ENTITY cam\./ENTITY xil_defaultlib\./' $in_file + sed -i -e 's/USE cam\./USE xil_defaultlib\./' $in_file +done + +sed -i '/virtex6l/a CONSTANT VIRTEX7 : STRING := "virtex7";' $cam_dir/vhdl/cam_pkg.vhd +sed -i -e 's/spartan6)/spartan6) OR (C_FAMILY = virtex7)/' $cam_dir/vhdl/cam_rtl.vhd +sed -i -e 's/or spartan6/spartan6, or virtex7/' $cam_dir/vhdl/cam_rtl.vhd diff --git a/hw/lib/xilinx/tcam_v1_1_0/sim/run_sim.tcl b/hw/lib/xilinx/tcam_v1_1_0/sim/run_sim.tcl new file mode 100644 index 0000000..f43cfff --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/sim/run_sim.tcl @@ -0,0 +1,31 @@ +# +# Copyright (c) 2015 University of Cambridge All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed to NetFPGA Open Systems C.I.C. (NetFPGA) under one or more +# contributor license agreements. See the NOTICE file distributed with this +# work for additional information regarding copyright ownership. NetFPGA +# licenses this file to you under the NetFPGA Hardware-Software License, +# Version 1.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.netfpga-cic.org +# +# Unless required by applicable law or agreed to in writing, Work distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +add_wave /testbench/sume_tcam/* +run 20us +exit + diff --git a/hw/lib/xilinx/tcam_v1_1_0/sim/run_tcam_sim.sh b/hw/lib/xilinx/tcam_v1_1_0/sim/run_tcam_sim.sh new file mode 100644 index 0000000..d3623dd --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/sim/run_tcam_sim.sh @@ -0,0 +1,62 @@ +# +# Copyright (c) 2015 University of Cambridge All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed to NetFPGA Open Systems C.I.C. (NetFPGA) under one or more +# contributor license agreements. See the NOTICE file distributed with this +# work for additional information regarding copyright ownership. NetFPGA +# licenses this file to you under the NetFPGA Hardware-Software License, +# Version 1.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.netfpga-cic.org +# +# Unless required by applicable law or agreed to in writing, Work distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +rm -rf *.log .Xil* *.jou xsim* *.wdb + +xvlog -d 32d -work work ./sim/testbench.v + +xvlog -work work ./hdl/verilog/tcam.v +xvlog -work work ./hdl/verilog/tcam_wrapper.v + +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_init_file_pack_xst.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_pkg.vhd + +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_input_ternary_ternenc.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_input_ternary.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_input.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_control.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_decoder.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_match_enc.vhd + +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_regouts.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_srl16_ternwrcomp.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_srl16_wrcomp.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_srl16_block_word.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_srl16_block.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_srl16.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_blk_extdepth_prim.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_blk_extdepth.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/dmem.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem_blk.vhd + +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_mem.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_rtl.vhd +xvhdl -work xil_defaultlib ./hdl/vhdl/tcam/cam_top.vhd + +xelab -L unisms_ver -L xil_defaultlib testbench -s testbench -debug all + +xsim testbench -tclbatch ./sim/run_sim.tcl diff --git a/hw/lib/xilinx/tcam_v1_1_0/sim/testbench.v b/hw/lib/xilinx/tcam_v1_1_0/sim/testbench.v new file mode 100644 index 0000000..9ec7026 --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/sim/testbench.v @@ -0,0 +1,243 @@ +// +// Copyright (c) 2015 University of Cambridge All rights reserved. +// +// This software was developed by the University of Cambridge Computer +// Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +// Foundation under Grant No. CNS-0855268, and Defense Advanced Research +// Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +// contract FA8750-11-C-0249. +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed to NetFPGA Open Systems C.I.C. (NetFPGA) under one or more +// contributor license agreements. See the NOTICE file distributed with this +// work for additional information regarding copyright ownership. NetFPGA +// licenses this file to you under the NetFPGA Hardware-Software License, +// Version 1.0 (the "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at: +// +// http://www.netfpga-cic.org +// +// Unless required by applicable law or agreed to in writing, Work distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ + +`timescale 1ns/1ps + +module testbench(); + +reg CLK, RSTN; +integer i; + +`ifdef 16d +localparam ADDR_WIDTH = 5; +localparam DATA_WIDTH = 16; +`elsif 32d +localparam ADDR_WIDTH = 5; +localparam DATA_WIDTH = 32; +`elsif 48d +localparam ADDR_WIDTH = 5; +localparam DATA_WIDTH = 48; +`else +localparam ADDR_WIDTH = 5; +localparam DATA_WIDTH = 16; +`endif + + +reg WE; +reg [ADDR_WIDTH-1:0] ADDR_WR; +reg [DATA_WIDTH-1:0] DIN, DATA_MASK; +reg [DATA_WIDTH-1:0] CMP_DIN, CMP_DATA_MASK; + +wire BUSY; +wire MATCH; +wire [ADDR_WIDTH-1:0] MATCH_ADDR; + +reg [7:0] match_cnt; + + +initial begin + CLK = 0; + RSTN = 0; + for (i=0; i<100; i=i+1) begin + @(posedge CLK); + end + RSTN = 1; +end + +always #2.5 CLK=~CLK; + +reg [31:0] count; +always @(posedge CLK) + if (~RSTN) begin + count <= 0; + end + else begin + count <= count + 1; + end + +`ifdef 16d +always @(*) begin + WE = 0; + ADDR_WR = 0; + DIN = 0; + DATA_MASK = 0; + CMP_DIN = 0; + CMP_DATA_MASK = 0; + // Start write + if (count == 100) begin + WE = 1; + ADDR_WR = 5'h0; + DIN = 16'h1234; + end + if (count == 120) begin + WE = 1; + ADDR_WR = 5'hf; + DIN = 16'habcd; + end + if (count == 140) begin + WE = 1; + ADDR_WR = 5'h1e; + DIN = 16'h5678; + end + // Start Lookup + if (count == 200) begin + CMP_DIN = 16'h1234; + end + if (count == 220) begin + CMP_DIN = 16'habcd; + end + if (count == 240) begin + CMP_DIN = 16'h5678; + end + if (count == 300) begin + if (match_cnt == 3) + $display ("\nPASS : Three matches...!"); + else + $display ("\nFAIL : Match failed...!"); + $display ("\n\n"); + $display ("Simulation finish...\n"); + $finish; + end +end +`elsif 32d +always @(*) begin + WE = 0; + ADDR_WR = 0; + DIN = 0; + DATA_MASK = 0; + CMP_DIN = 0; + CMP_DATA_MASK = 0; + // Start write + if (count == 100) begin + WE = 1; + ADDR_WR = 5'h0; + DIN = 32'h12341234; + end + if (count == 120) begin + WE = 1; + ADDR_WR = 5'hf; + DIN = 32'habcdabcd; + end + if (count == 140) begin + WE = 1; + ADDR_WR = 5'h1e; + DIN = 32'h56785678; + end + // Start Lookup + if (count == 200) begin + CMP_DIN = 32'h12341234; + end + if (count == 220) begin + CMP_DIN = 32'habcdabcd; + end + if (count == 240) begin + CMP_DIN = 32'h56785678; + end + if (count == 300) begin + if (match_cnt == 3) + $display ("\nPASS : Three matches...!"); + else + $display ("\nFAIL : Match failed...!"); + $display ("\n\n"); + $display ("Simulation finish...\n"); + $finish; + end +end +`elsif 48d +always @(*) begin + WE = 0; + ADDR_WR = 0; + DIN = 0; + DATA_MASK = 0; + CMP_DIN = 0; + CMP_DATA_MASK = 0; + // Start write + if (count == 100) begin + WE = 1; + ADDR_WR = 5'h0; + DIN = 48'h123412341234; + end + if (count == 120) begin + WE = 1; + ADDR_WR = 5'hf; + DIN = 48'habcdabcdabcd; + end + if (count == 140) begin + WE = 1; + ADDR_WR = 5'h1e; + DIN = 48'h567856785678; + end + // Start Lookup + if (count == 200) begin + CMP_DIN = 48'h123412341234; + end + if (count == 220) begin + CMP_DIN = 48'habcdabcdabcd; + end + if (count == 240) begin + CMP_DIN = 48'h567856785678; + end + if (count == 300) begin + if (match_cnt == 3) + $display ("\nPASS : Three matches...!"); + else + $display ("\nFAIL : Match failed...!"); + $display ("\n\n"); + $display ("Simulation finish...\n"); + $finish; + end +end +`endif + +always @(posedge CLK) + if (~RSTN) + match_cnt <= 0; + else if (MATCH) + match_cnt <= match_cnt + 1; + + +tcam +#( + .C_TCAM_ADDR_WIDTH ( ADDR_WIDTH ), + .C_TCAM_DATA_WIDTH ( DATA_WIDTH ) +) +sume_tcam +( + .CLK ( CLK ), + .WE ( WE ), + .ADDR_WR ( ADDR_WR ), + .DIN ( DIN ), + .DATA_MASK ( DATA_MASK ), + .BUSY ( BUSY ), + + .CMP_DIN ( CMP_DIN ), + .CMP_DATA_MASK ( CMP_DATA_MASK ), + .MATCH ( MATCH ), + .MATCH_ADDR ( MATCH_ADDR ) +); + +endmodule diff --git a/hw/lib/xilinx/tcam_v1_1_0/tcam.tcl b/hw/lib/xilinx/tcam_v1_1_0/tcam.tcl new file mode 100644 index 0000000..e2dfb13 --- /dev/null +++ b/hw/lib/xilinx/tcam_v1_1_0/tcam.tcl @@ -0,0 +1,92 @@ +# +# Copyright (c) 2015 University of Cambridge +# Modified by Salvator Galea +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC INTERNET Project EP/H040536/1, National Science +# Foundation under Grant No. CNS-0855268, and Defense Advanced Research +# Projects Agency (DARPA) and Air Force Research Laboratory (AFRL), under +# contract FA8750-11-C-0249. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Set variables +set lib_name xilinx +set ip_version 1.10 +set design tcam + +set device $::env(DEVICE) +set proj_dir ip_proj + +# Project setting +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip + +set_property source_mgmt_mode All [current_project] +set_property top ${design} [current_fileset] + +# IP build +read_verilog "./hdl/verilog/tcam.v" +read_verilog "./hdl/verilog/tcam_wrapper.v" + +read_vhdl "./hdl/vhdl/tcam/cam_init_file_pack_xst.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_pkg.vhd" + +read_vhdl "./hdl/vhdl/tcam/cam_input_ternary_ternenc.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_input_ternary.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_input.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_control.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_decoder.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_match_enc.vhd" + +read_vhdl "./hdl/vhdl/tcam/cam_regouts.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_srl16_ternwrcomp.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_srl16_wrcomp.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_srl16_block_word.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_srl16_block.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_srl16.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_blk_extdepth_prim.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_blk_extdepth.vhd" +read_vhdl "./hdl/vhdl/tcam/dmem.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_mem_blk.vhd" + +read_vhdl "./hdl/vhdl/tcam/cam_mem.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_rtl.vhd" +read_vhdl "./hdl/vhdl/tcam/cam_top.vhd" + +update_compile_order -fileset sources_1 + +ipx::package_project + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {xilinx} [ipx::current_core] +set_property company_url {http://www.xilinx.com} [ipx::current_core] +set_property vendor {xilinx} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::infer_user_parameters [ipx::current_core] +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] + +close_project +exit + diff --git a/hw/lib/xilinx/xilinx_shell_v1_0_0/Makefile b/hw/lib/xilinx/xilinx_shell_v1_0_0/Makefile new file mode 100644 index 0000000..c6a1e85 --- /dev/null +++ b/hw/lib/xilinx/xilinx_shell_v1_0_0/Makefile @@ -0,0 +1,35 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +all: update clean + sed -i -e "s/parameter int NUM_PHYS_FUNC = 1/parameter int NUM_PHYS_FUNC = 2/g" hdl/open_nic_shell.sv + sed -i -e "s/parameter int NUM_CMAC_PORT = 1/parameter int NUM_CMAC_PORT = 2/g" hdl/open_nic_shell.sv + vivado -mode batch -source xilinx_shell.tcl + +update: + bash update.sh + +clean: + rm -rf ip_* vivado*.* *.xml xgui/ .Xil* *.*~ *.zip proj + diff --git a/hw/lib/xilinx/xilinx_shell_v1_0_0/hdl/open_nic_shell.sv b/hw/lib/xilinx/xilinx_shell_v1_0_0/hdl/open_nic_shell.sv new file mode 100644 index 0000000..3b2316e --- /dev/null +++ b/hw/lib/xilinx/xilinx_shell_v1_0_0/hdl/open_nic_shell.sv @@ -0,0 +1,755 @@ +// ************************************************************************* +// +// Copyright 2020 Xilinx, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ************************************************************************* +`include "open_nic_shell_macros.vh" +//`define __synthesis__ +`timescale 1ns/1ps +module open_nic_shell #( + parameter int MAX_PKT_LEN = 1518, + parameter int MIN_PKT_LEN = 64, + parameter int USE_PHYS_FUNC = 1, + parameter int NUM_PHYS_FUNC = 2, + parameter int NUM_QUEUE = 2048, + parameter int NUM_CMAC_PORT = 2 +) ( +`ifndef sim +`ifdef __au280__ + output hbm_cattrip, // Fix the CATTRIP issue for AU280 custom flow +`endif + + input [15:0] pcie_rxp, + input [15:0] pcie_rxn, + output [15:0] pcie_txp, + output [15:0] pcie_txn, + input pcie_refclk_p, + input pcie_refclk_n, + input pcie_rstn, + + input [4*NUM_CMAC_PORT-1:0] qsfp_rxp, + input [4*NUM_CMAC_PORT-1:0] qsfp_rxn, + output [4*NUM_CMAC_PORT-1:0] qsfp_txp, + output [4*NUM_CMAC_PORT-1:0] qsfp_txn, + input [NUM_CMAC_PORT-1:0] qsfp_refclk_p, + input [NUM_CMAC_PORT-1:0] qsfp_refclk_n, +`else // !`ifndef sim + input s_axil_sim_awvalid, + input [31:0] s_axil_sim_awaddr, + output s_axil_sim_awready, + input s_axil_sim_wvalid, + input [31:0] s_axil_sim_wdata, + output s_axil_sim_wready, + output s_axil_sim_bvalid, + output [1:0] s_axil_sim_bresp, + input s_axil_sim_bready, + input s_axil_sim_arvalid, + input [31:0] s_axil_sim_araddr, + output s_axil_sim_arready, + output s_axil_sim_rvalid, + output [31:0] s_axil_sim_rdata, + output [1:0] s_axil_sim_rresp, + input s_axil_sim_rready, + + input s_axis_qdma_h2c_sim_tvalid, + input [511:0] s_axis_qdma_h2c_sim_tdata, + input [31:0] s_axis_qdma_h2c_sim_tcrc, + input s_axis_qdma_h2c_sim_tlast, + input [10:0] s_axis_qdma_h2c_sim_tuser_qid, + input [2:0] s_axis_qdma_h2c_sim_tuser_port_id, + input s_axis_qdma_h2c_sim_tuser_err, + input [31:0] s_axis_qdma_h2c_sim_tuser_mdata, + input [5:0] s_axis_qdma_h2c_sim_tuser_mty, + input s_axis_qdma_h2c_sim_tuser_zero_byte, + output s_axis_qdma_h2c_sim_tready, + + output m_axis_qdma_c2h_sim_tvalid, + output [511:0] m_axis_qdma_c2h_sim_tdata, + output [31:0] m_axis_qdma_c2h_sim_tcrc, + output m_axis_qdma_c2h_sim_tlast, + output m_axis_qdma_c2h_sim_ctrl_marker, + output [2:0] m_axis_qdma_c2h_sim_ctrl_port_id, + output [6:0] m_axis_qdma_c2h_sim_ctrl_ecc, + output [15:0] m_axis_qdma_c2h_sim_ctrl_len, + output [10:0] m_axis_qdma_c2h_sim_ctrl_qid, + output m_axis_qdma_c2h_sim_ctrl_has_cmpt, + output [5:0] m_axis_qdma_c2h_sim_mty, + input m_axis_qdma_c2h_sim_tready, + + output m_axis_qdma_cpl_sim_tvalid, + output [511:0] m_axis_qdma_cpl_sim_tdata, + output [1:0] m_axis_qdma_cpl_sim_size, + output [15:0] m_axis_qdma_cpl_sim_dpar, + output [10:0] m_axis_qdma_cpl_sim_ctrl_qid, + output [1:0] m_axis_qdma_cpl_sim_ctrl_cmpt_type, + output [15:0] m_axis_qdma_cpl_sim_ctrl_wait_pld_pkt_id, + output [2:0] m_axis_qdma_cpl_sim_ctrl_port_id, + output m_axis_qdma_cpl_sim_ctrl_marker, + output m_axis_qdma_cpl_sim_ctrl_user_trig, + output [2:0] m_axis_qdma_cpl_sim_ctrl_col_idx, + output [2:0] m_axis_qdma_cpl_sim_ctrl_err_idx, + output m_axis_qdma_cpl_sim_ctrl_no_wrb_marker, + input m_axis_qdma_cpl_sim_tready, + + output [NUM_CMAC_PORT-1:0] m_axis_cmac_tx_sim_tvalid, + output [512*NUM_CMAC_PORT-1:0] m_axis_cmac_tx_sim_tdata, + output [64*NUM_CMAC_PORT-1:0] m_axis_cmac_tx_sim_tkeep, + output [NUM_CMAC_PORT-1:0] m_axis_cmac_tx_sim_tlast, + output [NUM_CMAC_PORT-1:0] m_axis_cmac_tx_sim_tuser_err, + input [NUM_CMAC_PORT-1:0] m_axis_cmac_tx_sim_tready, + + input [NUM_CMAC_PORT-1:0] s_axis_cmac_rx_sim_tvalid, + input [512*NUM_CMAC_PORT-1:0] s_axis_cmac_rx_sim_tdata, + input [64*NUM_CMAC_PORT-1:0] s_axis_cmac_rx_sim_tkeep, + input [NUM_CMAC_PORT-1:0] s_axis_cmac_rx_sim_tlast, + input [NUM_CMAC_PORT-1:0] s_axis_cmac_rx_sim_tuser_err, + + input powerup_rstn, +`endif + + output m_axil_box0_awvalid, + output [31:0] m_axil_box0_awaddr, + input m_axil_box0_awready, + output m_axil_box0_wvalid, + output [31:0] m_axil_box0_wdata, + input m_axil_box0_wready, + input m_axil_box0_bvalid, + input [1:0] m_axil_box0_bresp, + output m_axil_box0_bready, + output m_axil_box0_arvalid, + output [31:0] m_axil_box0_araddr, + input m_axil_box0_arready, + input m_axil_box0_rvalid, + input [31:0] m_axil_box0_rdata, + input [1:0] m_axil_box0_rresp, + output m_axil_box0_rready, + + output m_axil_box1_awvalid, + output [31:0] m_axil_box1_awaddr, + input m_axil_box1_awready, + output m_axil_box1_wvalid, + output [31:0] m_axil_box1_wdata, + input m_axil_box1_wready, + input m_axil_box1_bvalid, + input [1:0] m_axil_box1_bresp, + output m_axil_box1_bready, + output m_axil_box1_arvalid, + output [31:0] m_axil_box1_araddr, + input m_axil_box1_arready, + input m_axil_box1_rvalid, + input [31:0] m_axil_box1_rdata, + input [1:0] m_axil_box1_rresp, + output m_axil_box1_rready, + + // QDMA subsystem interfaces to the box running at 250MHz + output [NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tvalid, + output [512*NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tdata, + output [64*NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tkeep, + output [NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tlast, + output [16*NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tuser_size, + output [16*NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tuser_src, + output [16*NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tuser_dst, + input [NUM_PHYS_FUNC-1:0] m_axis_qdma_h2c_tready, + + input [NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tvalid, + input [512*NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tdata, + input [64*NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tkeep, + input [NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tlast, + input [16*NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tuser_size, + input [16*NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tuser_src, + input [16*NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tuser_dst, + output [NUM_PHYS_FUNC-1:0] s_axis_qdma_c2h_tready, + + // Packet adapter interfaces to the box running at 250MHz + input [NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tvalid, + input [512*NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tdata, + input [64*NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tkeep, + input [NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tlast, + input [16*NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tuser_size, + input [16*NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tuser_src, + input [16*NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tuser_dst, + output [NUM_CMAC_PORT-1:0] s_axis_adap_tx_250mhz_tready, + + output [NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tvalid, + output [512*NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tdata, + output [64*NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tkeep, + output [NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tlast, + output [16*NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tuser_size, + output [16*NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tuser_src, + output [16*NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tuser_dst, + input [NUM_CMAC_PORT-1:0] m_axis_adap_rx_250mhz_tready, + + // Packet adapter interfaces to the box running at 322MHz + output [NUM_CMAC_PORT-1:0] m_axis_adap_tx_322mhz_tvalid, + output [512*NUM_CMAC_PORT-1:0] m_axis_adap_tx_322mhz_tdata, + output [64*NUM_CMAC_PORT-1:0] m_axis_adap_tx_322mhz_tkeep, + output [NUM_CMAC_PORT-1:0] m_axis_adap_tx_322mhz_tlast, + output [NUM_CMAC_PORT-1:0] m_axis_adap_tx_322mhz_tuser_err, + input [NUM_CMAC_PORT-1:0] m_axis_adap_tx_322mhz_tready, + + input [NUM_CMAC_PORT-1:0] s_axis_adap_rx_322mhz_tvalid, + input [512*NUM_CMAC_PORT-1:0] s_axis_adap_rx_322mhz_tdata, + input [64*NUM_CMAC_PORT-1:0] s_axis_adap_rx_322mhz_tkeep, + input [NUM_CMAC_PORT-1:0] s_axis_adap_rx_322mhz_tlast, + input [NUM_CMAC_PORT-1:0] s_axis_adap_rx_322mhz_tuser_err, + + // CMAC subsystem interfaces to the box running at 322MHz + input [NUM_CMAC_PORT-1:0] s_axis_cmac_tx_tvalid, + input [512*NUM_CMAC_PORT-1:0] s_axis_cmac_tx_tdata, + input [64*NUM_CMAC_PORT-1:0] s_axis_cmac_tx_tkeep, + input [NUM_CMAC_PORT-1:0] s_axis_cmac_tx_tlast, + input [NUM_CMAC_PORT-1:0] s_axis_cmac_tx_tuser_err, + output [NUM_CMAC_PORT-1:0] s_axis_cmac_tx_tready, + + output [NUM_CMAC_PORT-1:0] m_axis_cmac_rx_tvalid, + output [512*NUM_CMAC_PORT-1:0] m_axis_cmac_rx_tdata, + output [64*NUM_CMAC_PORT-1:0] m_axis_cmac_rx_tkeep, + output [NUM_CMAC_PORT-1:0] m_axis_cmac_rx_tlast, + output [NUM_CMAC_PORT-1:0] m_axis_cmac_rx_tuser_err, + + output [31:0] user_rstn, + input [31:0] user_rst_done, + + output axil_aclk, + output axis_aclk, + output [NUM_CMAC_PORT-1:0] cmac_clk +); + + // Parameter DRC + initial begin + if (MAX_PKT_LEN > 9600 || MAX_PKT_LEN < 256) begin + $fatal("[%m] Maximum packet length should be within the range [256, 9600]"); + end + if (MIN_PKT_LEN > 256 || MIN_PKT_LEN < 64) begin + $fatal("[%m] Minimum packet length should be within the range [64, 256]"); + end + if (USE_PHYS_FUNC) begin + if (NUM_QUEUE > 2048 || NUM_QUEUE < 1) begin + $fatal("[%m] Number of queues should be within the range [1, 2048]"); + end + if ((NUM_QUEUE & (NUM_QUEUE - 1)) != 0) begin + $fatal("[%m] Number of queues should be 2^n"); + end + if (NUM_PHYS_FUNC > 4 || NUM_PHYS_FUNC < 1) begin + $fatal("[%m] Number of physical functions should be within the range [1, 4]"); + end + end + if (NUM_CMAC_PORT > 2 || NUM_CMAC_PORT < 1) begin + $fatal("[%m] Number of CMACs should be within the range [1, 2]"); + end + end + +`ifndef sim + wire powerup_rstn; + wire pcie_user_lnk_up; + wire pcie_phy_ready; + + // BAR2-mapped master AXI-Lite feeding into system configuration block + wire axil_pcie_awvalid; + wire [31:0] axil_pcie_awaddr; + wire axil_pcie_awready; + wire axil_pcie_wvalid; + wire [31:0] axil_pcie_wdata; + wire axil_pcie_wready; + wire axil_pcie_bvalid; + wire [1:0] axil_pcie_bresp; + wire axil_pcie_bready; + wire axil_pcie_arvalid; + wire [31:0] axil_pcie_araddr; + wire axil_pcie_arready; + wire axil_pcie_rvalid; + wire [31:0] axil_pcie_rdata; + wire [1:0] axil_pcie_rresp; + wire axil_pcie_rready; + + IBUF pcie_rstn_ibuf_inst (.I(pcie_rstn), .O(pcie_rstn_int)); + +`ifdef __au280__ + // Fix the CATTRIP issue for AU280 custom flow + // + // This pin must be tied to 0; otherwise the board might be unrecoverable + // after programming + OBUF hbm_cattrip_obuf_inst (.I(1'b0), .O(hbm_cattrip)); +`endif + +`ifdef __zynq_family__ + zynq_usplus_ps zynq_usplus_ps_inst (); +`endif +`endif + + wire [31:0] shell_rstn; + wire [31:0] shell_rst_done; + wire qdma_rstn; + wire qdma_rst_done; + wire [NUM_CMAC_PORT-1:0] adap_rstn; + wire [NUM_CMAC_PORT-1:0] adap_rst_done; + wire [NUM_CMAC_PORT-1:0] cmac_rstn; + wire [NUM_CMAC_PORT-1:0] cmac_rst_done; + + wire axil_qdma_awvalid; + wire [31:0] axil_qdma_awaddr; + wire axil_qdma_awready; + wire axil_qdma_wvalid; + wire [31:0] axil_qdma_wdata; + wire axil_qdma_wready; + wire axil_qdma_bvalid; + wire [1:0] axil_qdma_bresp; + wire axil_qdma_bready; + wire axil_qdma_arvalid; + wire [31:0] axil_qdma_araddr; + wire axil_qdma_arready; + wire axil_qdma_rvalid; + wire [31:0] axil_qdma_rdata; + wire [1:0] axil_qdma_rresp; + wire axil_qdma_rready; + + wire [NUM_CMAC_PORT-1:0] axil_adap_awvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_adap_awaddr; + wire [NUM_CMAC_PORT-1:0] axil_adap_awready; + wire [NUM_CMAC_PORT-1:0] axil_adap_wvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_adap_wdata; + wire [NUM_CMAC_PORT-1:0] axil_adap_wready; + wire [NUM_CMAC_PORT-1:0] axil_adap_bvalid; + wire [2*NUM_CMAC_PORT-1:0] axil_adap_bresp; + wire [NUM_CMAC_PORT-1:0] axil_adap_bready; + wire [NUM_CMAC_PORT-1:0] axil_adap_arvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_adap_araddr; + wire [NUM_CMAC_PORT-1:0] axil_adap_arready; + wire [NUM_CMAC_PORT-1:0] axil_adap_rvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_adap_rdata; + wire [2*NUM_CMAC_PORT-1:0] axil_adap_rresp; + wire [NUM_CMAC_PORT-1:0] axil_adap_rready; + + wire [NUM_CMAC_PORT-1:0] axil_cmac_awvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_cmac_awaddr; + wire [NUM_CMAC_PORT-1:0] axil_cmac_awready; + wire [NUM_CMAC_PORT-1:0] axil_cmac_wvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_cmac_wdata; + wire [NUM_CMAC_PORT-1:0] axil_cmac_wready; + wire [NUM_CMAC_PORT-1:0] axil_cmac_bvalid; + wire [2*NUM_CMAC_PORT-1:0] axil_cmac_bresp; + wire [NUM_CMAC_PORT-1:0] axil_cmac_bready; + wire [NUM_CMAC_PORT-1:0] axil_cmac_arvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_cmac_araddr; + wire [NUM_CMAC_PORT-1:0] axil_cmac_arready; + wire [NUM_CMAC_PORT-1:0] axil_cmac_rvalid; + wire [32*NUM_CMAC_PORT-1:0] axil_cmac_rdata; + wire [2*NUM_CMAC_PORT-1:0] axil_cmac_rresp; + wire [NUM_CMAC_PORT-1:0] axil_cmac_rready; + + // Unused reset pairs must have their "reset_done" tied to 1 + + // First 4-bit for QDMA subsystem + assign qdma_rstn = shell_rstn[0]; + assign shell_rst_done[0] = qdma_rst_done; + assign shell_rst_done[3:1] = 3'b111; + + // For each CMAC port, use the subsequent 4-bit: bit 0 for CMAC subsystem and + // bit 1 for the corresponding adapter + generate for (genvar i = 0; i < NUM_CMAC_PORT; i++) begin: cmac_rst + assign {adap_rstn[i], cmac_rstn[i]} = {shell_rstn[(i+1)*4+1], shell_rstn[(i+1)*4]}; + assign shell_rst_done[(i+1)*4 +: 4] = {2'b11, adap_rst_done[i], cmac_rst_done[i]}; + end: cmac_rst + endgenerate + + generate for (genvar i = (NUM_CMAC_PORT+1)*4; i < 32; i++) begin: unused_rst + assign shell_rst_done[i] = 1'b1; + end: unused_rst + endgenerate + + system_config #( + .NUM_CMAC_PORT (NUM_CMAC_PORT) + ) system_config_inst ( +`ifndef sim + .s_axil_awvalid (axil_pcie_awvalid), + .s_axil_awaddr (axil_pcie_awaddr), + .s_axil_awready (axil_pcie_awready), + .s_axil_wvalid (axil_pcie_wvalid), + .s_axil_wdata (axil_pcie_wdata), + .s_axil_wready (axil_pcie_wready), + .s_axil_bvalid (axil_pcie_bvalid), + .s_axil_bresp (axil_pcie_bresp), + .s_axil_bready (axil_pcie_bready), + .s_axil_arvalid (axil_pcie_arvalid), + .s_axil_araddr (axil_pcie_araddr), + .s_axil_arready (axil_pcie_arready), + .s_axil_rvalid (axil_pcie_rvalid), + .s_axil_rdata (axil_pcie_rdata), + .s_axil_rresp (axil_pcie_rresp), + .s_axil_rready (axil_pcie_rready), +`else // !`ifndef sim + .s_axil_awvalid (s_axil_sim_awvalid), + .s_axil_awaddr (s_axil_sim_awaddr), + .s_axil_awready (s_axil_sim_awready), + .s_axil_wvalid (s_axil_sim_wvalid), + .s_axil_wdata (s_axil_sim_wdata), + .s_axil_wready (s_axil_sim_wready), + .s_axil_bvalid (s_axil_sim_bvalid), + .s_axil_bresp (s_axil_sim_bresp), + .s_axil_bready (s_axil_sim_bready), + .s_axil_arvalid (s_axil_sim_arvalid), + .s_axil_araddr (s_axil_sim_araddr), + .s_axil_arready (s_axil_sim_arready), + .s_axil_rvalid (s_axil_sim_rvalid), + .s_axil_rdata (s_axil_sim_rdata), + .s_axil_rresp (s_axil_sim_rresp), + .s_axil_rready (s_axil_sim_rready), +`endif + + .m_axil_qdma_awvalid (axil_qdma_awvalid), + .m_axil_qdma_awaddr (axil_qdma_awaddr), + .m_axil_qdma_awready (axil_qdma_awready), + .m_axil_qdma_wvalid (axil_qdma_wvalid), + .m_axil_qdma_wdata (axil_qdma_wdata), + .m_axil_qdma_wready (axil_qdma_wready), + .m_axil_qdma_bvalid (axil_qdma_bvalid), + .m_axil_qdma_bresp (axil_qdma_bresp), + .m_axil_qdma_bready (axil_qdma_bready), + .m_axil_qdma_arvalid (axil_qdma_arvalid), + .m_axil_qdma_araddr (axil_qdma_araddr), + .m_axil_qdma_arready (axil_qdma_arready), + .m_axil_qdma_rvalid (axil_qdma_rvalid), + .m_axil_qdma_rdata (axil_qdma_rdata), + .m_axil_qdma_rresp (axil_qdma_rresp), + .m_axil_qdma_rready (axil_qdma_rready), + + .m_axil_adap_awvalid (axil_adap_awvalid), + .m_axil_adap_awaddr (axil_adap_awaddr), + .m_axil_adap_awready (axil_adap_awready), + .m_axil_adap_wvalid (axil_adap_wvalid), + .m_axil_adap_wdata (axil_adap_wdata), + .m_axil_adap_wready (axil_adap_wready), + .m_axil_adap_bvalid (axil_adap_bvalid), + .m_axil_adap_bresp (axil_adap_bresp), + .m_axil_adap_bready (axil_adap_bready), + .m_axil_adap_arvalid (axil_adap_arvalid), + .m_axil_adap_araddr (axil_adap_araddr), + .m_axil_adap_arready (axil_adap_arready), + .m_axil_adap_rvalid (axil_adap_rvalid), + .m_axil_adap_rdata (axil_adap_rdata), + .m_axil_adap_rresp (axil_adap_rresp), + .m_axil_adap_rready (axil_adap_rready), + + .m_axil_cmac_awvalid (axil_cmac_awvalid), + .m_axil_cmac_awaddr (axil_cmac_awaddr), + .m_axil_cmac_awready (axil_cmac_awready), + .m_axil_cmac_wvalid (axil_cmac_wvalid), + .m_axil_cmac_wdata (axil_cmac_wdata), + .m_axil_cmac_wready (axil_cmac_wready), + .m_axil_cmac_bvalid (axil_cmac_bvalid), + .m_axil_cmac_bresp (axil_cmac_bresp), + .m_axil_cmac_bready (axil_cmac_bready), + .m_axil_cmac_arvalid (axil_cmac_arvalid), + .m_axil_cmac_araddr (axil_cmac_araddr), + .m_axil_cmac_arready (axil_cmac_arready), + .m_axil_cmac_rvalid (axil_cmac_rvalid), + .m_axil_cmac_rdata (axil_cmac_rdata), + .m_axil_cmac_rresp (axil_cmac_rresp), + .m_axil_cmac_rready (axil_cmac_rready), + + .m_axil_box0_awvalid (m_axil_box0_awvalid), + .m_axil_box0_awaddr (m_axil_box0_awaddr), + .m_axil_box0_awready (m_axil_box0_awready), + .m_axil_box0_wvalid (m_axil_box0_wvalid), + .m_axil_box0_wdata (m_axil_box0_wdata), + .m_axil_box0_wready (m_axil_box0_wready), + .m_axil_box0_bvalid (m_axil_box0_bvalid), + .m_axil_box0_bresp (m_axil_box0_bresp), + .m_axil_box0_bready (m_axil_box0_bready), + .m_axil_box0_arvalid (m_axil_box0_arvalid), + .m_axil_box0_araddr (m_axil_box0_araddr), + .m_axil_box0_arready (m_axil_box0_arready), + .m_axil_box0_rvalid (m_axil_box0_rvalid), + .m_axil_box0_rdata (m_axil_box0_rdata), + .m_axil_box0_rresp (m_axil_box0_rresp), + .m_axil_box0_rready (m_axil_box0_rready), + + .m_axil_box1_awvalid (m_axil_box1_awvalid), + .m_axil_box1_awaddr (m_axil_box1_awaddr), + .m_axil_box1_awready (m_axil_box1_awready), + .m_axil_box1_wvalid (m_axil_box1_wvalid), + .m_axil_box1_wdata (m_axil_box1_wdata), + .m_axil_box1_wready (m_axil_box1_wready), + .m_axil_box1_bvalid (m_axil_box1_bvalid), + .m_axil_box1_bresp (m_axil_box1_bresp), + .m_axil_box1_bready (m_axil_box1_bready), + .m_axil_box1_arvalid (m_axil_box1_arvalid), + .m_axil_box1_araddr (m_axil_box1_araddr), + .m_axil_box1_arready (m_axil_box1_arready), + .m_axil_box1_rvalid (m_axil_box1_rvalid), + .m_axil_box1_rdata (m_axil_box1_rdata), + .m_axil_box1_rresp (m_axil_box1_rresp), + .m_axil_box1_rready (m_axil_box1_rready), + + .shell_rstn (shell_rstn), + .shell_rst_done (shell_rst_done), + .user_rstn (user_rstn), + .user_rst_done (user_rst_done), + + .aclk (axil_aclk), + .aresetn (powerup_rstn) + ); + + qdma_subsystem #( + .MAX_PKT_LEN (MAX_PKT_LEN), + .MIN_PKT_LEN (MIN_PKT_LEN), + .USE_PHYS_FUNC (USE_PHYS_FUNC), + .NUM_PHYS_FUNC (NUM_PHYS_FUNC), + .NUM_QUEUE (NUM_QUEUE) + ) qdma_subsystem_inst ( + .s_axil_awvalid (axil_qdma_awvalid), + .s_axil_awaddr (axil_qdma_awaddr), + .s_axil_awready (axil_qdma_awready), + .s_axil_wvalid (axil_qdma_wvalid), + .s_axil_wdata (axil_qdma_wdata), + .s_axil_wready (axil_qdma_wready), + .s_axil_bvalid (axil_qdma_bvalid), + .s_axil_bresp (axil_qdma_bresp), + .s_axil_bready (axil_qdma_bready), + .s_axil_arvalid (axil_qdma_arvalid), + .s_axil_araddr (axil_qdma_araddr), + .s_axil_arready (axil_qdma_arready), + .s_axil_rvalid (axil_qdma_rvalid), + .s_axil_rdata (axil_qdma_rdata), + .s_axil_rresp (axil_qdma_rresp), + .s_axil_rready (axil_qdma_rready), + + .m_axis_h2c_tvalid (m_axis_qdma_h2c_tvalid), + .m_axis_h2c_tdata (m_axis_qdma_h2c_tdata), + .m_axis_h2c_tkeep (m_axis_qdma_h2c_tkeep), + .m_axis_h2c_tlast (m_axis_qdma_h2c_tlast), + .m_axis_h2c_tuser_size (m_axis_qdma_h2c_tuser_size), + .m_axis_h2c_tuser_src (m_axis_qdma_h2c_tuser_src), + .m_axis_h2c_tuser_dst (m_axis_qdma_h2c_tuser_dst), + .m_axis_h2c_tready (m_axis_qdma_h2c_tready), + + .s_axis_c2h_tvalid (s_axis_qdma_c2h_tvalid), + .s_axis_c2h_tdata (s_axis_qdma_c2h_tdata), + .s_axis_c2h_tkeep (s_axis_qdma_c2h_tkeep), + .s_axis_c2h_tlast (s_axis_qdma_c2h_tlast), + .s_axis_c2h_tuser_size (s_axis_qdma_c2h_tuser_size), + .s_axis_c2h_tuser_src (s_axis_qdma_c2h_tuser_src), + .s_axis_c2h_tuser_dst (s_axis_qdma_c2h_tuser_dst), + .s_axis_c2h_tready (s_axis_qdma_c2h_tready), + +`ifndef sim + .pcie_rxp (pcie_rxp), + .pcie_rxn (pcie_rxn), + .pcie_txp (pcie_txp), + .pcie_txn (pcie_txn), + + .m_axil_pcie_awvalid (axil_pcie_awvalid), + .m_axil_pcie_awaddr (axil_pcie_awaddr), + .m_axil_pcie_awready (axil_pcie_awready), + .m_axil_pcie_wvalid (axil_pcie_wvalid), + .m_axil_pcie_wdata (axil_pcie_wdata), + .m_axil_pcie_wready (axil_pcie_wready), + .m_axil_pcie_bvalid (axil_pcie_bvalid), + .m_axil_pcie_bresp (axil_pcie_bresp), + .m_axil_pcie_bready (axil_pcie_bready), + .m_axil_pcie_arvalid (axil_pcie_arvalid), + .m_axil_pcie_araddr (axil_pcie_araddr), + .m_axil_pcie_arready (axil_pcie_arready), + .m_axil_pcie_rvalid (axil_pcie_rvalid), + .m_axil_pcie_rdata (axil_pcie_rdata), + .m_axil_pcie_rresp (axil_pcie_rresp), + .m_axil_pcie_rready (axil_pcie_rready), + + .pcie_refclk_p (pcie_refclk_p), + .pcie_refclk_n (pcie_refclk_n), + .pcie_rstn (pcie_rstn_int), + .user_lnk_up (pcie_user_lnk_up), + .phy_ready (pcie_phy_ready), + .powerup_rstn (powerup_rstn), +`else // !`ifndef sim + .s_axis_qdma_h2c_tvalid (s_axis_qdma_h2c_sim_tvalid), + .s_axis_qdma_h2c_tdata (s_axis_qdma_h2c_sim_tdata), + .s_axis_qdma_h2c_tcrc (s_axis_qdma_h2c_sim_tcrc), + .s_axis_qdma_h2c_tlast (s_axis_qdma_h2c_sim_tlast), + .s_axis_qdma_h2c_tuser_qid (s_axis_qdma_h2c_sim_tuser_qid), + .s_axis_qdma_h2c_tuser_port_id (s_axis_qdma_h2c_sim_tuser_port_id), + .s_axis_qdma_h2c_tuser_err (s_axis_qdma_h2c_sim_tuser_err), + .s_axis_qdma_h2c_tuser_mdata (s_axis_qdma_h2c_sim_tuser_mdata), + .s_axis_qdma_h2c_tuser_mty (s_axis_qdma_h2c_sim_tuser_mty), + .s_axis_qdma_h2c_tuser_zero_byte (s_axis_qdma_h2c_sim_tuser_zero_byte), + .s_axis_qdma_h2c_tready (s_axis_qdma_h2c_sim_tready), + + .m_axis_qdma_c2h_tvalid (m_axis_qdma_c2h_sim_tvalid), + .m_axis_qdma_c2h_tdata (m_axis_qdma_c2h_sim_tdata), + .m_axis_qdma_c2h_tcrc (m_axis_qdma_c2h_sim_tcrc), + .m_axis_qdma_c2h_tlast (m_axis_qdma_c2h_sim_tlast), + .m_axis_qdma_c2h_ctrl_marker (m_axis_qdma_c2h_sim_ctrl_marker), + .m_axis_qdma_c2h_ctrl_port_id (m_axis_qdma_c2h_sim_ctrl_port_id), + .m_axis_qdma_c2h_ctrl_ecc (m_axis_qdma_c2h_sim_ctrl_ecc), + .m_axis_qdma_c2h_ctrl_len (m_axis_qdma_c2h_sim_ctrl_len), + .m_axis_qdma_c2h_ctrl_qid (m_axis_qdma_c2h_sim_ctrl_qid), + .m_axis_qdma_c2h_ctrl_has_cmpt (m_axis_qdma_c2h_sim_ctrl_has_cmpt), + .m_axis_qdma_c2h_mty (m_axis_qdma_c2h_sim_mty), + .m_axis_qdma_c2h_tready (m_axis_qdma_c2h_sim_tready), + + .m_axis_qdma_cpl_tvalid (m_axis_qdma_cpl_sim_tvalid), + .m_axis_qdma_cpl_tdata (m_axis_qdma_cpl_sim_tdata), + .m_axis_qdma_cpl_size (m_axis_qdma_cpl_sim_size), + .m_axis_qdma_cpl_dpar (m_axis_qdma_cpl_sim_dpar), + .m_axis_qdma_cpl_ctrl_qid (m_axis_qdma_cpl_sim_ctrl_qid), + .m_axis_qdma_cpl_ctrl_cmpt_type (m_axis_qdma_cpl_sim_ctrl_cmpt_type), + .m_axis_qdma_cpl_ctrl_wait_pld_pkt_id (m_axis_qdma_cpl_sim_ctrl_wait_pld_pkt_id), + .m_axis_qdma_cpl_ctrl_port_id (m_axis_qdma_cpl_sim_ctrl_port_id), + .m_axis_qdma_cpl_ctrl_marker (m_axis_qdma_cpl_sim_ctrl_marker), + .m_axis_qdma_cpl_ctrl_user_trig (m_axis_qdma_cpl_sim_ctrl_user_trig), + .m_axis_qdma_cpl_ctrl_col_idx (m_axis_qdma_cpl_sim_ctrl_col_idx), + .m_axis_qdma_cpl_ctrl_err_idx (m_axis_qdma_cpl_sim_ctrl_err_idx), + .m_axis_qdma_cpl_ctrl_no_wrb_marker (m_axis_qdma_cpl_sim_ctrl_no_wrb_marker), + .m_axis_qdma_cpl_tready (m_axis_qdma_cpl_sim_tready), +`endif + + .mod_rstn (qdma_rstn), + .mod_rst_done (qdma_rst_done), + + .axil_aclk (axil_aclk), + .axis_aclk (axis_aclk) + ); + + generate for (genvar i = 0; i < NUM_CMAC_PORT; i++) begin: cmac_port + //packet_adapter #( + // .CMAC_ID (i), + // .MAX_PKT_LEN (MAX_PKT_LEN), + // .MIN_PKT_LEN (MIN_PKT_LEN) + //) packet_adapter_inst ( + // .s_axil_awvalid (axil_adap_awvalid[i]), + // .s_axil_awaddr (axil_adap_awaddr[`getvec(32, i)]), + // .s_axil_awready (axil_adap_awready[i]), + // .s_axil_wvalid (axil_adap_wvalid[i]), + // .s_axil_wdata (axil_adap_wdata[`getvec(32, i)]), + // .s_axil_wready (axil_adap_wready[i]), + // .s_axil_bvalid (axil_adap_bvalid[i]), + // .s_axil_bresp (axil_adap_bresp[`getvec(2, i)]), + // .s_axil_bready (axil_adap_bready[i]), + // .s_axil_arvalid (axil_adap_arvalid[i]), + // .s_axil_araddr (axil_adap_araddr[`getvec(32, i)]), + // .s_axil_arready (axil_adap_arready[i]), + // .s_axil_rvalid (axil_adap_rvalid[i]), + // .s_axil_rdata (axil_adap_rdata[`getvec(32, i)]), + // .s_axil_rresp (axil_adap_rresp[`getvec(2, i)]), + // .s_axil_rready (axil_adap_rready[i]), + + // .s_axis_tx_tvalid (s_axis_adap_tx_250mhz_tvalid[i]), + // .s_axis_tx_tdata (s_axis_adap_tx_250mhz_tdata[`getvec(512, i)]), + // .s_axis_tx_tkeep (s_axis_adap_tx_250mhz_tkeep[`getvec(64, i)]), + // .s_axis_tx_tlast (s_axis_adap_tx_250mhz_tlast[i]), + // .s_axis_tx_tuser_size (s_axis_adap_tx_250mhz_tuser_size[`getvec(16, i)]), + // .s_axis_tx_tuser_src (s_axis_adap_tx_250mhz_tuser_src[`getvec(16, i)]), + // .s_axis_tx_tuser_dst (s_axis_adap_tx_250mhz_tuser_dst[`getvec(16, i)]), + // .s_axis_tx_tready (s_axis_adap_tx_250mhz_tready[i]), + + // .m_axis_rx_tvalid (m_axis_adap_rx_250mhz_tvalid[i]), + // .m_axis_rx_tdata (m_axis_adap_rx_250mhz_tdata[`getvec(512, i)]), + // .m_axis_rx_tkeep (m_axis_adap_rx_250mhz_tkeep[`getvec(64, i)]), + // .m_axis_rx_tlast (m_axis_adap_rx_250mhz_tlast[i]), + // .m_axis_rx_tuser_size (m_axis_adap_rx_250mhz_tuser_size[`getvec(16, i)]), + // .m_axis_rx_tuser_src (m_axis_adap_rx_250mhz_tuser_src[`getvec(16, i)]), + // .m_axis_rx_tuser_dst (m_axis_adap_rx_250mhz_tuser_dst[`getvec(16, i)]), + // .m_axis_rx_tready (m_axis_adap_rx_250mhz_tready[i]), + + // .m_axis_tx_tvalid (m_axis_adap_tx_322mhz_tvalid[i]), + // .m_axis_tx_tdata (m_axis_adap_tx_322mhz_tdata[`getvec(512, i)]), + // .m_axis_tx_tkeep (m_axis_adap_tx_322mhz_tkeep[`getvec(64, i)]), + // .m_axis_tx_tlast (m_axis_adap_tx_322mhz_tlast[i]), + // .m_axis_tx_tuser_err (m_axis_adap_tx_322mhz_tuser_err[i]), + // .m_axis_tx_tready (m_axis_adap_tx_322mhz_tready[i]), + + // .s_axis_rx_tvalid (s_axis_adap_rx_322mhz_tvalid[i]), + // .s_axis_rx_tdata (s_axis_adap_rx_322mhz_tdata[`getvec(512, i)]), + // .s_axis_rx_tkeep (s_axis_adap_rx_322mhz_tkeep[`getvec(64, i)]), + // .s_axis_rx_tlast (s_axis_adap_rx_322mhz_tlast[i]), + // .s_axis_rx_tuser_err (s_axis_adap_rx_322mhz_tuser_err[i]), + + // .mod_rstn (adap_rstn[i]), + // .mod_rst_done (adap_rst_done[i]), + + // .axil_aclk (axil_aclk), + // .axis_aclk (axis_aclk), + // .cmac_clk (cmac_clk[i]) + //); + + cmac_subsystem #( + .CMAC_ID (i), + .MAX_PKT_LEN (MAX_PKT_LEN), + .MIN_PKT_LEN (MIN_PKT_LEN) + ) cmac_subsystem_inst ( + .s_axil_awvalid (axil_cmac_awvalid[i]), + .s_axil_awaddr (axil_cmac_awaddr[`getvec(32, i)]), + .s_axil_awready (axil_cmac_awready[i]), + .s_axil_wvalid (axil_cmac_wvalid[i]), + .s_axil_wdata (axil_cmac_wdata[`getvec(32, i)]), + .s_axil_wready (axil_cmac_wready[i]), + .s_axil_bvalid (axil_cmac_bvalid[i]), + .s_axil_bresp (axil_cmac_bresp[`getvec(2, i)]), + .s_axil_bready (axil_cmac_bready[i]), + .s_axil_arvalid (axil_cmac_arvalid[i]), + .s_axil_araddr (axil_cmac_araddr[`getvec(32, i)]), + .s_axil_arready (axil_cmac_arready[i]), + .s_axil_rvalid (axil_cmac_rvalid[i]), + .s_axil_rdata (axil_cmac_rdata[`getvec(32, i)]), + .s_axil_rresp (axil_cmac_rresp[`getvec(2, i)]), + .s_axil_rready (axil_cmac_rready[i]), + + .s_axis_cmac_tx_tvalid (s_axis_cmac_tx_tvalid[i]), + .s_axis_cmac_tx_tdata (s_axis_cmac_tx_tdata[`getvec(512, i)]), + .s_axis_cmac_tx_tkeep (s_axis_cmac_tx_tkeep[`getvec(64, i)]), + .s_axis_cmac_tx_tlast (s_axis_cmac_tx_tlast[i]), + .s_axis_cmac_tx_tuser_err (s_axis_cmac_tx_tuser_err[i]), + .s_axis_cmac_tx_tready (s_axis_cmac_tx_tready[i]), + + .m_axis_cmac_rx_tvalid (m_axis_cmac_rx_tvalid[i]), + .m_axis_cmac_rx_tdata (m_axis_cmac_rx_tdata[`getvec(512, i)]), + .m_axis_cmac_rx_tkeep (m_axis_cmac_rx_tkeep[`getvec(64, i)]), + .m_axis_cmac_rx_tlast (m_axis_cmac_rx_tlast[i]), + .m_axis_cmac_rx_tuser_err (m_axis_cmac_rx_tuser_err[i]), + +`ifndef sim + .gt_rxp (qsfp_rxp[`getvec(4, i)]), + .gt_rxn (qsfp_rxn[`getvec(4, i)]), + .gt_txp (qsfp_txp[`getvec(4, i)]), + .gt_txn (qsfp_txn[`getvec(4, i)]), + .gt_refclk_p (qsfp_refclk_p[i]), + .gt_refclk_n (qsfp_refclk_n[i]), + + .cmac_clk (cmac_clk[i]), +`else + .m_axis_cmac_tx_sim_tvalid (m_axis_cmac_tx_sim_tvalid[i]), + .m_axis_cmac_tx_sim_tdata (m_axis_cmac_tx_sim_tdata[`getvec(512, i)]), + .m_axis_cmac_tx_sim_tkeep (m_axis_cmac_tx_sim_tkeep[`getvec(64, i)]), + .m_axis_cmac_tx_sim_tlast (m_axis_cmac_tx_sim_tlast[i]), + .m_axis_cmac_tx_sim_tuser_err (m_axis_cmac_tx_sim_tuser_err[i]), + .m_axis_cmac_tx_sim_tready (m_axis_cmac_tx_sim_tready[i]), + + .s_axis_cmac_rx_sim_tvalid (s_axis_cmac_rx_sim_tvalid[i]), + .s_axis_cmac_rx_sim_tdata (s_axis_cmac_rx_sim_tdata[`getvec(512, i)]), + .s_axis_cmac_rx_sim_tkeep (s_axis_cmac_rx_sim_tkeep[`getvec(64, i)]), + .s_axis_cmac_rx_sim_tlast (s_axis_cmac_rx_sim_tlast[i]), + .s_axis_cmac_rx_sim_tuser_err (s_axis_cmac_rx_sim_tuser_err[i]), + + .cmac_clk (cmac_clk[i]), +`endif + + .mod_rstn (cmac_rstn[i]), + .mod_rst_done (cmac_rst_done[i]), + .axil_aclk (axil_aclk) + ); + end: cmac_port + endgenerate + +endmodule: open_nic_shell diff --git a/hw/lib/xilinx/xilinx_shell_v1_0_0/open-nic-shell b/hw/lib/xilinx/xilinx_shell_v1_0_0/open-nic-shell new file mode 160000 index 0000000..39c82df --- /dev/null +++ b/hw/lib/xilinx/xilinx_shell_v1_0_0/open-nic-shell @@ -0,0 +1 @@ +Subproject commit 39c82dfdf046e1e06f72a8cafe4fbc006659dfb6 diff --git a/hw/lib/xilinx/xilinx_shell_v1_0_0/update.sh b/hw/lib/xilinx/xilinx_shell_v1_0_0/update.sh new file mode 100755 index 0000000..118a327 --- /dev/null +++ b/hw/lib/xilinx/xilinx_shell_v1_0_0/update.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +ip_dir="vivado_ip" +cmac_dir="open-nic-shell/src/cmac_subsystem/vivado_ip/" +qdma_dir="open-nic-shell/src/qdma_subsystem/vivado_ip/" + +if [ ! -d "${cmac_dir}" ] || [ ! -d "${qdma_dir}" ]; then + git submodule update --init open-nic-shell +fi + +if [ ! -f "${ip_dir}/cmac_usplus_0_au250.tcl" ]; then + sed -e "s/CONFIG.GT_REF_CLK_FREQ {156.25}/CONFIG.GT_REF_CLK_FREQ {161.1328125}/g" \ + -e "s/CONFIG.DIFFCLK_BOARD_INTERFACE {qsfp0_156mhz}/CONFIG.DIFFCLK_BOARD_INTERFACE {qsfp0_161mhz}/g" \ + ${cmac_dir}/cmac_usplus_0_au250.tcl > ${ip_dir}/cmac_usplus_0_au250.tcl +fi +if [ ! -f "${ip_dir}/cmac_usplus_1_au250.tcl" ]; then + sed -e "s/CONFIG.GT_REF_CLK_FREQ {156.25}/CONFIG.GT_REF_CLK_FREQ {161.1328125}/g" \ + -e "s/CONFIG.DIFFCLK_BOARD_INTERFACE {qsfp1_156mhz}/CONFIG.DIFFCLK_BOARD_INTERFACE {qsfp1_161mhz}/g" \ + ${cmac_dir}/cmac_usplus_1_au250.tcl > ${ip_dir}/cmac_usplus_1_au250.tcl +fi +if [ ! -f "${ip_dir}/cmac_usplus_0_vcu1525.tcl" ]; then + sed -e 's/156.25/161.1328125/' -e 's/CMACE4_X0Y6/CMACE4_X0Y7/' \ + -e 's/X0Y40~X0Y43/X1Y44~X1Y47/' -e 's/X0Y40/X1Y44/' \ + -e 's/X0Y41/X1Y45/' -e 's/X0Y42/X1Y46/' -e 's/X0Y43/X1Y47/' \ + -e 's/RX_GT_BUFFER {1}/RX_GT_BUFFER {NA}/' \ + -e 's/GT_RX_BUFFER_BYPASS {0}/GT_RX_BUFFER_BYPASS {NA}/' \ + -e '/ETHERNET_BOARD/d' -e '/DIFFCLK_BOARD/d' \ + ${cmac_dir}/cmac_usplus_0_au280.tcl > ${ip_dir}/cmac_usplus_0_vcu1525.tcl +fi +if [ ! -f "${ip_dir}/cmac_usplus_1_vcu1525.tcl" ]; then + sed -e 's/156.25/161.1328125/' -e 's/CMACE4_X0Y7/CMACE4_X0Y8/' \ + -e 's/X0Y44~X0Y47/X1Y48~X1Y51/' -e 's/X0Y40/X1Y48/' \ + -e 's/X0Y41/X1Y49/' -e 's/X0Y42/X1Y50/' -e 's/X0Y43/X1Y51/' \ + -e 's/RX_GT_BUFFER {1}/RX_GT_BUFFER {NA}/' \ + -e 's/GT_RX_BUFFER_BYPASS {0}/GT_RX_BUFFER_BYPASS {NA}/' \ + -e '/ETHERNET_BOARD/d' -e '/DIFFCLK_BOARD/d' \ + ${cmac_dir}/cmac_usplus_1_au280.tcl > ${ip_dir}/cmac_usplus_1_vcu1525.tcl +fi +if [ ! -f "${ip_dir}/qdma_no_sriov_au200.tcl " ]; then + sed -e 's/AU280/AU200/g' ${qdma_dir}/qdma_no_sriov_au280.tcl > ${ip_dir}/qdma_no_sriov_au200.tcl +fi +if [ ! -f "${ip_dir}/qdma_no_sriov_au200.tcl " ]; then + sed -e 's/AU280/VCU1525/g' ${qdma_dir}/qdma_no_sriov_au280.tcl > ${ip_dir}/qdma_no_sriov_vcu1525.tcl +fi + diff --git a/hw/lib/xilinx/xilinx_shell_v1_0_0/vivado_ip/.keep b/hw/lib/xilinx/xilinx_shell_v1_0_0/vivado_ip/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/lib/xilinx/xilinx_shell_v1_0_0/xilinx_shell.tcl b/hw/lib/xilinx/xilinx_shell_v1_0_0/xilinx_shell.tcl new file mode 100644 index 0000000..1621bb9 --- /dev/null +++ b/hw/lib/xilinx/xilinx_shell_v1_0_0/xilinx_shell.tcl @@ -0,0 +1,225 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design xilinx_shell +set top open_nic_shell +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) +set proj_dir ./ip_proj +set ip_version 1.00 +set lib_name xilinx +set proj ./proj +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} -ip +set_property BOARD_PART $board [current_project] +set_property source_mgmt_mode All [current_project] +set_property top ${top} [current_fileset] +set_property ip_repo_paths $::env(NFPLUS_FOLDER)/hw/lib/ [current_fileset] +set_property verilog_define { {__synthesis__} } [current_fileset] +puts "Creating Xiilnx Xilinx OpenNIC Shell IP" +##################################### +# Design Parameters +##################################### +set num_phys_func 2 +set num_queue 2048 +set min_pkt_len 64 +set max_pkt_len 1518 +##################################### +# Project Structure & IP Build +##################################### +read_verilog -sv "./hdl/open_nic_shell.sv" + +read_verilog "open-nic-shell/src/open_nic_shell_macros.vh" +read_verilog "open-nic-shell/src/cmac_subsystem/cmac_subsystem_address_map.v" +read_verilog -sv "open-nic-shell/src/cmac_subsystem/cmac_subsystem_cmac_wrapper.sv" +read_verilog -sv "open-nic-shell/src/cmac_subsystem/cmac_subsystem.sv" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem_address_map.sv" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem_c2h.sv" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem_function_register.sv" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem_function.sv" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem_h2c.sv" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem_hash.sv" +read_verilog "open-nic-shell/src/qdma_subsystem/qdma_subsystem_qdma_wrapper.v" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem_register.sv" +read_verilog -sv "open-nic-shell/src/qdma_subsystem/qdma_subsystem.sv" +read_verilog -sv "open-nic-shell/src/system_config/system_config_address_map.sv" +read_verilog "open-nic-shell/src/system_config/system_config_register.v" +read_verilog -sv "open-nic-shell/src/system_config/system_config.sv" +read_verilog -sv "open-nic-shell/src/utility/axi_lite_register.sv" +read_verilog -sv "open-nic-shell/src/utility/axi_lite_slave.sv" +read_verilog -sv "open-nic-shell/src/utility/axi_stream_packet_buffer.sv" +read_verilog -sv "open-nic-shell/src/utility/axi_stream_packet_fifo.sv" +read_verilog -sv "open-nic-shell/src/utility/axi_stream_register_slice.sv" +read_verilog -sv "open-nic-shell/src/utility/axi_stream_size_counter.sv" +read_verilog "open-nic-shell/src/utility/crc32.v" +read_verilog -sv "open-nic-shell/src/utility/generic_reset.sv" +read_verilog -sv "open-nic-shell/src/utility/level_trigger_cdc.sv" +read_verilog -sv "open-nic-shell/src/utility/rr_arbiter.sv" + +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 +ipx::package_project + +if {[file exists ${proj}]} { + file delete -force ${proj} + file mkdir ${proj} +} else { + file mkdir ${proj} +} + +set ip_build_dir ${proj} + +if {[string match $board_name "au280"]} { + source "open-nic-shell/src/cmac_subsystem/vivado_ip/cmac_usplus_0_au280.tcl" +} elseif {[string match $board_name "au250"]} { + source "vivado_ip/cmac_usplus_0_au250.tcl" +} elseif {[string match $board_name "au200"]} { + source "vivado_ip/cmac_usplus_0_au250.tcl" +} elseif {[string match $board_name "vcu1525"]} { + source "vivado_ip/cmac_usplus_0_vcu1525.tcl" +} +generate_target {instantiation_template} [get_files ./${proj}/${cmac_usplus}/${cmac_usplus}.xci] +generate_target all [get_files ./${proj}/${cmac_usplus}/${cmac_usplus}.xci] +ipx::package_project -force -import_files ./${proj}/${cmac_usplus}/${cmac_usplus}.xci + +if {[string match $board_name "au280"]} { + source "open-nic-shell/src/cmac_subsystem/vivado_ip/cmac_usplus_1_au280.tcl" +} elseif {[string match $board_name "au250"]} { + source "vivado_ip/cmac_usplus_1_au250.tcl" +} elseif {[string match $board_name "au200"]} { + source "vivado_ip/cmac_usplus_1_au250.tcl" +} elseif {[string match $board_name "vcu1525"]} { + source "vivado_ip/cmac_usplus_1_vcu1525.tcl" +} +generate_target {instantiation_template} [get_files ./${proj}/${cmac_usplus}/${cmac_usplus}.xci] +generate_target all [get_files ./${proj}/${cmac_usplus}/${cmac_usplus}.xci] +ipx::package_project -force -import_files ./${proj}/${cmac_usplus}/${cmac_usplus}.xci + +source "open-nic-shell/src/cmac_subsystem/vivado_ip/cmac_subsystem_axi_crossbar.tcl" +generate_target {instantiation_template} [get_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci] +generate_target all [get_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci] +ipx::package_project -force -import_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci + +source "open-nic-shell/src/qdma_subsystem/vivado_ip/qdma_subsystem_axi_cdc.tcl" +generate_target {instantiation_template} [get_files ./${proj}/${axi_clock_converter}/${axi_clock_converter}.xci] +generate_target all [get_files ./${proj}/${axi_clock_converter}/${axi_clock_converter}.xci] +ipx::package_project -force -import_files ./${proj}/${axi_clock_converter}/${axi_clock_converter}.xci + +source "open-nic-shell/src/qdma_subsystem/vivado_ip/qdma_subsystem_axi_crossbar.tcl" +generate_target {instantiation_template} [get_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci] +generate_target all [get_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci] +ipx::package_project -force -import_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci + +source "open-nic-shell/src/qdma_subsystem/vivado_ip/qdma_subsystem_clk_div.tcl" +generate_target {instantiation_template} [get_files ./${proj}/${clk_wiz}/${clk_wiz}.xci] +generate_target all [get_files ./${proj}/${clk_wiz}/${clk_wiz}.xci] +ipx::package_project -force -import_files ./${proj}/${clk_wiz}/${clk_wiz}.xci + +source "open-nic-shell/src/qdma_subsystem/vivado_ip/qdma_subsystem_c2h_ecc.tcl" +generate_target {instantiation_template} [get_files ./${proj}/${ecc}/${ecc}.xci] +generate_target all [get_files ./${proj}/${ecc}/${ecc}.xci] +ipx::package_project -force -import_files ./${proj}/${ecc}/${ecc}.xci + +if {[string match $board_name "au280"]} { + source "open-nic-shell/src/qdma_subsystem/vivado_ip/qdma_no_sriov_au280.tcl" +} elseif {[string match $board_name "au250"]} { + source "open-nic-shell/src/qdma_subsystem/vivado_ip/qdma_no_sriov_au250.tcl" +} elseif {[string match $board_name "au200"]} { + source "vivado_ip/qdma_no_sriov_au200.tcl" +} elseif {[string match $board_name "vcu1525"]} { + source "vivado_ip/qdma_no_sriov_vcu1525.tcl" +} +generate_target {instantiation_template} [get_files ./${proj}/${qdma}/${qdma}.xci] +generate_target all [get_files ./${proj}/${qdma}/${qdma}.xci] +ipx::package_project -force -import_files ./${proj}/${qdma}/${qdma}.xci + +source "open-nic-shell/src/system_config/vivado_ip/system_config_axi_crossbar.tcl" +generate_target {instantiation_template} [get_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci] +generate_target all [get_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci] +ipx::package_project -force -import_files ./${proj}/${axi_crossbar}/${axi_crossbar}.xci + +update_ip_catalog -rebuild +ipx::infer_user_parameters [ipx::current_core] + +set_property name ${design} [ipx::current_core] +set_property library ${lib_name} [ipx::current_core] +set_property vendor_display_name {xilinx} [ipx::current_core] +set_property company_url {http://www.xilinx.com} [ipx::current_core] +set_property vendor {xilinx} [ipx::current_core] +set_property supported_families {{virtexuplus} {Production} {virtexuplushbm} {Production}} [ipx::current_core] +set_property taxonomy {{/NetFPGA/Generic}} [ipx::current_core] +set_property version ${ip_version} [ipx::current_core] +set_property display_name ${design} [ipx::current_core] +set_property description ${design} [ipx::current_core] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::add_user_parameter {MAX_PKT_LEN} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters MAX_PKT_LEN] +set_property display_name {MAX_PKT_LEN} [ipx::get_user_parameters MAX_PKT_LEN] +set_property value {1518} [ipx::get_user_parameters MAX_PKT_LEN] +set_property value_format {bitstring} [ipx::get_user_parameters MAX_PKT_LEN] + +ipx::add_user_parameter {MIN_PKT_LEN} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters MIN_PKT_LEN] +set_property display_name {MIN_PKT_LEN} [ipx::get_user_parameters MIN_PKT_LEN] +set_property value {64} [ipx::get_user_parameters MIN_PKT_LEN] +set_property value_format {bitstring} [ipx::get_user_parameters MIN_PKT_LEN] + +ipx::add_user_parameter {NUM_QUEUE} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters NUM_QUEUE] +set_property display_name {NUM_QUEUE} [ipx::get_user_parameters NUM_QUEUE] +set_property value {2048} [ipx::get_user_parameters NUM_QUEUE] +set_property value_format {bitstring} [ipx::get_user_parameters NUM_QUEUE] + +ipx::add_user_parameter {NUM_PHYS_FUNC} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters NUM_PHYS_FUNC] +set_property display_name {NUM_PHYS_FUNC} [ipx::get_user_parameters NUM_PHYS_FUNC] +set_property value {2} [ipx::get_user_parameters NUM_PHYS_FUNC] +set_property value_format {bitstring} [ipx::get_user_parameters NUM_PHYS_FUNC] + +ipx::add_user_parameter {NUM_CMAC_PORT} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters NUM_CMAC_PORT] +set_property display_name {NUM_CMAC_PORT} [ipx::get_user_parameters NUM_CMAC_PORT] +set_property value {2} [ipx::get_user_parameters NUM_CMAC_PORT] +set_property value_format {bitstring} [ipx::get_user_parameters NUM_CMAC_PORT] + +ipx::add_user_parameter {USE_PHYS_FUNC} [ipx::current_core] +set_property value_resolve_type {user} [ipx::get_user_parameters USE_PHYS_FUNC] +set_property display_name {USE_PHYS_FUNC} [ipx::get_user_parameters USE_PHYS_FUNC] +set_property value {1} [ipx::get_user_parameters USE_PHYS_FUNC] +set_property value_format {bitstring} [ipx::get_user_parameters USE_PHYS_FUNC] + +ipx::infer_user_parameters [ipx::current_core] + +ipx::check_integrity [ipx::current_core] +ipx::save_core [ipx::current_core] +update_ip_catalog +close_project diff --git a/hw/projects/reference_nic/bitfiles/README b/hw/projects/reference_nic/bitfiles/README new file mode 100644 index 0000000..61f32f8 --- /dev/null +++ b/hw/projects/reference_nic/bitfiles/README @@ -0,0 +1,42 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +Reference NIC bitfile is available for a direct download from the University of Cambridge servers: + +1. Reference NIC (VCU1525) +url: +md5 checksum: + +2. Reference NIC (U200) +url: +md5 checksum: + +3. Reference NIC (U250) +url: +md5 checksum: + +4. Reference NIC (U280) +url: +md5 checksum: diff --git a/hw/projects/reference_nic/hw/Makefile b/hw/projects/reference_nic/hw/Makefile new file mode 100644 index 0000000..4c3486c --- /dev/null +++ b/hw/projects/reference_nic/hw/Makefile @@ -0,0 +1,90 @@ +################################################################################ +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +################################################################################ +PROJ = ${NF_PROJECT_NAME} + +all: project + +project: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode batch -source tcl/${PROJ}.tcl; \ + fi + +projectgui: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode gui -source tcl/${PROJ}.tcl; \ + fi + +sim: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_${NF_PROJECT_NAME}.py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_${NF_PROJECT_NAME}.py + vivado -mode batch -source ../../../projects/${PROJ}/hw/tcl/${NF_PROJECT_NAME}_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +reg: + vivado -mode batch -source $(NF_DESIGN_DIR)/hw/tcl/export_registers.tcl + cd ../test && cp ../../../../tools/scripts/xparam2regdefines.py . && python xparam2regdefines.py + cd ../test && rm -f xparam2regdefines.py + cd ../test && cp ../../../../tools/scripts/python_parser.py . && python python_parser.py + cd ../test && rm -f python_parser.py && mv reg_defines.py reg_defines_${NF_PROJECT_NAME}.py + +simgui: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_$(NF_PROJECT_NAME).py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_$(NF_PROJECT_NAME).py + vivado -mode gui -source ../../../projects/${PROJ}/hw/tcl/$(NF_PROJECT_NAME)_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +simclean: + rm -rf proj_* vivado*.* *.*~ .Xil* $(NF_DESIGN_DIR)/hw/ip_repo/ $(NF_DESIGN_DIR)/hw/project/ + rm -rf *[0-9]_{stim,expected,log}.axi + rm -f *.axi + rm -f portconfig.sim + rm -f seed + rm -f *.log + rm -f ../test/Makefile + rm -rf ../test/*.log + rm -rf ../test/*.axi + rm -rf ../test/seed + rm -rf ../test/*.sim + rm -rf ../test/proj_* + rm -rf ../test/ip_repo + rm -f ../test/vivado*.* + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.py + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.pyc + +clean: + rm -rf project + rm -f vivado* + rm -rf ip_repo diff --git a/hw/projects/reference_nic/hw/constraints/au200_vcu1525_user_timing.tcl b/hw/projects/reference_nic/hw/constraints/au200_vcu1525_user_timing.tcl new file mode 100644 index 0000000..c5c4dfb --- /dev/null +++ b/hw/projects/reference_nic/hw/constraints/au200_vcu1525_user_timing.tcl @@ -0,0 +1,29 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +create_pblock pblock_nf_datapath +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list nf_datapath_0]] +resize_pblock [get_pblocks pblock_nf_datapath] -add {SLR2} + diff --git a/hw/projects/reference_nic/hw/hdl/nf_datapath.v b/hw/projects/reference_nic/hw/hdl/nf_datapath.v new file mode 100644 index 0000000..8936d92 --- /dev/null +++ b/hw/projects/reference_nic/hw/hdl/nf_datapath.v @@ -0,0 +1,332 @@ +`timescale 1ns / 1ps +//- +// Copyright (c) 2015 Noa Zilberman +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// nf_datapath.v +// +// Module: +// nf_datapath +// +// Author: Noa Zilberman +// +// Description: +// NetFPGA user data path wrapper, wrapping input arbiter, output port lookup and output queues +// +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + +module nf_datapath #( + //Slave AXI parameters + parameter C_S_AXI_DATA_WIDTH = 32, + parameter C_S_AXI_ADDR_WIDTH = 32, + parameter C_BASEADDR = 32'h00000000, + + // Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH=512, + parameter C_S_AXIS_DATA_WIDTH=512, + parameter C_M_AXIS_TUSER_WIDTH=128, + parameter C_S_AXIS_TUSER_WIDTH=128, + parameter NUM_QUEUES=5 +) ( + //Datapath clock + input axis_aclk, + input axis_resetn, + //Registers clock + input axi_aclk, + input axi_resetn, + + // Slave AXI Ports + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_AWADDR, + input S0_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S0_AXI_WSTRB, + input S0_AXI_WVALID, + input S0_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_ARADDR, + input S0_AXI_ARVALID, + input S0_AXI_RREADY, + output S0_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_RDATA, + output [1 : 0] S0_AXI_RRESP, + output S0_AXI_RVALID, + output S0_AXI_WREADY, + output [1 :0] S0_AXI_BRESP, + output S0_AXI_BVALID, + output S0_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_AWADDR, + input S1_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S1_AXI_WSTRB, + input S1_AXI_WVALID, + input S1_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_ARADDR, + input S1_AXI_ARVALID, + input S1_AXI_RREADY, + output S1_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_RDATA, + output [1 : 0] S1_AXI_RRESP, + output S1_AXI_RVALID, + output S1_AXI_WREADY, + output [1 :0] S1_AXI_BRESP, + output S1_AXI_BVALID, + output S1_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_AWADDR, + input S2_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S2_AXI_WSTRB, + input S2_AXI_WVALID, + input S2_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_ARADDR, + input S2_AXI_ARVALID, + input S2_AXI_RREADY, + output S2_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_RDATA, + output [1 : 0] S2_AXI_RRESP, + output S2_AXI_RVALID, + output S2_AXI_WREADY, + output [1 :0] S2_AXI_BRESP, + output S2_AXI_BVALID, + output S2_AXI_AWREADY, + + + // Slave Stream Ports (interface from Rx queues) + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_0_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_0_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_0_tuser, + input s_axis_0_tvalid, + output s_axis_0_tready, + input s_axis_0_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_1_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_1_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_1_tuser, + input s_axis_1_tvalid, + output s_axis_1_tready, + input s_axis_1_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_2_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_2_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_2_tuser, + input s_axis_2_tvalid, + output s_axis_2_tready, + input s_axis_2_tlast, + + + // Master Stream Ports (interface to TX queues) + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_0_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_0_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_0_tuser, + output m_axis_0_tvalid, + input m_axis_0_tready, + output m_axis_0_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_1_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_1_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_1_tuser, + output m_axis_1_tvalid, + input m_axis_1_tready, + output m_axis_1_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_2_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_2_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_2_tuser, + output m_axis_2_tvalid, + input m_axis_2_tready, + output m_axis_2_tlast + + ); + + //internal connectivity + + wire [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_opl_tuser; + wire m_axis_opl_tvalid; + wire m_axis_opl_tready; + wire m_axis_opl_tlast; + + wire [C_M_AXIS_DATA_WIDTH - 1:0] s_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] s_axis_opl_tuser; + wire s_axis_opl_tvalid; + wire s_axis_opl_tready; + wire s_axis_opl_tlast; + + //Input Arbiter + input_arbiter_ip input_arbiter_v1_0 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (s_axis_opl_tdata), + .m_axis_tkeep (s_axis_opl_tkeep), + .m_axis_tuser (s_axis_opl_tuser), + .m_axis_tvalid(s_axis_opl_tvalid), + .m_axis_tready(s_axis_opl_tready), + .m_axis_tlast (s_axis_opl_tlast), + .s_axis_0_tdata (s_axis_0_tdata), + .s_axis_0_tkeep (s_axis_0_tkeep), + .s_axis_0_tuser (s_axis_0_tuser), + .s_axis_0_tvalid(s_axis_0_tvalid), + .s_axis_0_tready(s_axis_0_tready), + .s_axis_0_tlast (s_axis_0_tlast), + .s_axis_1_tdata (s_axis_1_tdata), + .s_axis_1_tkeep (s_axis_1_tkeep), + .s_axis_1_tuser (s_axis_1_tuser), + .s_axis_1_tvalid(s_axis_1_tvalid), + .s_axis_1_tready(s_axis_1_tready), + .s_axis_1_tlast (s_axis_1_tlast), + .s_axis_2_tdata (s_axis_2_tdata), + .s_axis_2_tkeep (s_axis_2_tkeep), + .s_axis_2_tuser (s_axis_2_tuser), + .s_axis_2_tvalid(s_axis_2_tvalid), + .s_axis_2_tready(s_axis_2_tready), + .s_axis_2_tlast (s_axis_2_tlast), + .S_AXI_AWADDR(S0_AXI_AWADDR), + .S_AXI_AWVALID(S0_AXI_AWVALID), + .S_AXI_WDATA(S0_AXI_WDATA), + .S_AXI_WSTRB(S0_AXI_WSTRB), + .S_AXI_WVALID(S0_AXI_WVALID), + .S_AXI_BREADY(S0_AXI_BREADY), + .S_AXI_ARADDR(S0_AXI_ARADDR), + .S_AXI_ARVALID(S0_AXI_ARVALID), + .S_AXI_RREADY(S0_AXI_RREADY), + .S_AXI_ARREADY(S0_AXI_ARREADY), + .S_AXI_RDATA(S0_AXI_RDATA), + .S_AXI_RRESP(S0_AXI_RRESP), + .S_AXI_RVALID(S0_AXI_RVALID), + .S_AXI_WREADY(S0_AXI_WREADY), + .S_AXI_BRESP(S0_AXI_BRESP), + .S_AXI_BVALID(S0_AXI_BVALID), + .S_AXI_AWREADY(S0_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + + + + //Output Port Lookup + nic_output_port_lookup_ip output_port_lookup_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (m_axis_opl_tdata), + .m_axis_tkeep (m_axis_opl_tkeep), + .m_axis_tuser (m_axis_opl_tuser), + .m_axis_tvalid(m_axis_opl_tvalid), + .m_axis_tready(m_axis_opl_tready), + .m_axis_tlast (m_axis_opl_tlast), + .s_axis_tdata (s_axis_opl_tdata), + .s_axis_tkeep (s_axis_opl_tkeep), + .s_axis_tuser (s_axis_opl_tuser), + .s_axis_tvalid(s_axis_opl_tvalid), + .s_axis_tready(s_axis_opl_tready), + .s_axis_tlast (s_axis_opl_tlast), + + .S_AXI_AWADDR(S1_AXI_AWADDR), + .S_AXI_AWVALID(S1_AXI_AWVALID), + .S_AXI_WDATA(S1_AXI_WDATA), + .S_AXI_WSTRB(S1_AXI_WSTRB), + .S_AXI_WVALID(S1_AXI_WVALID), + .S_AXI_BREADY(S1_AXI_BREADY), + .S_AXI_ARADDR(S1_AXI_ARADDR), + .S_AXI_ARVALID(S1_AXI_ARVALID), + .S_AXI_RREADY(S1_AXI_RREADY), + .S_AXI_ARREADY(S1_AXI_ARREADY), + .S_AXI_RDATA(S1_AXI_RDATA), + .S_AXI_RRESP(S1_AXI_RRESP), + .S_AXI_RVALID(S1_AXI_RVALID), + .S_AXI_WREADY(S1_AXI_WREADY), + .S_AXI_BRESP(S1_AXI_BRESP), + .S_AXI_BVALID(S1_AXI_BVALID), + .S_AXI_AWREADY(S1_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + + + ); + + + //Output queues + output_queues_ip bram_output_queues_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .s_axis_tdata (m_axis_opl_tdata), + .s_axis_tkeep (m_axis_opl_tkeep), + .s_axis_tuser (m_axis_opl_tuser), + .s_axis_tvalid (m_axis_opl_tvalid), + .s_axis_tready (m_axis_opl_tready), + .s_axis_tlast (m_axis_opl_tlast), + .m_axis_0_tdata (m_axis_0_tdata), + .m_axis_0_tkeep (m_axis_0_tkeep), + .m_axis_0_tuser (m_axis_0_tuser), + .m_axis_0_tvalid(m_axis_0_tvalid), + .m_axis_0_tready(m_axis_0_tready), + .m_axis_0_tlast (m_axis_0_tlast), + .m_axis_1_tdata (m_axis_1_tdata), + .m_axis_1_tkeep (m_axis_1_tkeep), + .m_axis_1_tuser (m_axis_1_tuser), + .m_axis_1_tvalid(m_axis_1_tvalid), + .m_axis_1_tready(m_axis_1_tready), + .m_axis_1_tlast (m_axis_1_tlast), + .m_axis_2_tdata (m_axis_2_tdata), + .m_axis_2_tkeep (m_axis_2_tkeep), + .m_axis_2_tuser (m_axis_2_tuser), + .m_axis_2_tvalid(m_axis_2_tvalid), + .m_axis_2_tready(m_axis_2_tready), + .m_axis_2_tlast (m_axis_2_tlast), + .bytes_stored(), + .pkt_stored(), + .bytes_removed_0(), + .bytes_removed_1(), + .bytes_removed_2(), + .pkt_removed_0(), + .pkt_removed_1(), + .pkt_removed_2(), + .bytes_dropped(), + .pkt_dropped(), + + .S_AXI_AWADDR(S2_AXI_AWADDR), + .S_AXI_AWVALID(S2_AXI_AWVALID), + .S_AXI_WDATA(S2_AXI_WDATA), + .S_AXI_WSTRB(S2_AXI_WSTRB), + .S_AXI_WVALID(S2_AXI_WVALID), + .S_AXI_BREADY(S2_AXI_BREADY), + .S_AXI_ARADDR(S2_AXI_ARADDR), + .S_AXI_ARVALID(S2_AXI_ARVALID), + .S_AXI_RREADY(S2_AXI_RREADY), + .S_AXI_ARREADY(S2_AXI_ARREADY), + .S_AXI_RDATA(S2_AXI_RDATA), + .S_AXI_RRESP(S2_AXI_RRESP), + .S_AXI_RVALID(S2_AXI_RVALID), + .S_AXI_WREADY(S2_AXI_WREADY), + .S_AXI_BRESP(S2_AXI_BRESP), + .S_AXI_BVALID(S2_AXI_BVALID), + .S_AXI_AWREADY(S2_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + +endmodule diff --git a/hw/projects/reference_nic/hw/hdl/top_sim.v b/hw/projects/reference_nic/hw/hdl/top_sim.v new file mode 100644 index 0000000..14e47a3 --- /dev/null +++ b/hw/projects/reference_nic/hw/hdl/top_sim.v @@ -0,0 +1,677 @@ +//- +// Copyright (c) 2015 Noa Zilberman, Georgina Kalogeridou +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// top_sim.v +// +// Module: +// top +// +// Author: Noa Zilberman, Georgina Kalogeridou +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ps / 100 fs + + module top_sim # ( + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter C_TUSER_WIDTH = 128, // RX/TX interface data width + parameter C_NF_DATA_WIDTH = 1024, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32 + ) ( + +//PCI Express + input [15:0] pcie_rxn, + input [15:0] pcie_rxp, + output [15:0] pcie_txn, + output [15:0] pcie_txp, + //Network Interface + input [3:0] qsfp0_rxp, + input [3:0] qsfp0_rxn, + output [3:0] qsfp0_txp, + output [3:0] qsfp0_txn, + + input [3:0] qsfp1_rxp, + input [3:0] qsfp1_rxn, + output [3:0] qsfp1_txp, + output [3:0] qsfp1_txn, + + // PCIe Clock + input pci_clk_p, + input pci_clk_n, + + //200MHz Clock + input fpga_sysclk_p, + input fpga_sysclk_n, + + // 156.25 MHz clock in + input qsfp_refclk_p, + input qsfp_refclk_n, + + input sys_reset_n +); + + //----------------------------------------------------------------------------------------------------------------// + // System(SYS) Interface // + //----------------------------------------------------------------------------------------------------------------// + + wire sys_clk; + wire clk_200_i; + wire clk_200; + wire sys_rst_n_c; + + //----------------------------------------------------------------------------------------------------------------------- + + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + wire[C_NF_DATA_WIDTH-1:0] axis_i_0_tdata , axis_o_0_tdata; + wire axis_i_0_tvalid, axis_o_0_tvalid; + wire axis_i_0_tlast , axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_0_tuser , axis_o_0_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_0_tkeep , axis_o_0_tkeep; + wire axis_i_0_tready, axis_o_0_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_i_1_tdata , axis_o_1_tdata; + wire axis_i_1_tvalid, axis_o_1_tvalid; + wire axis_i_1_tlast , axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_1_tuser , axis_o_1_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_1_tkeep , axis_o_1_tkeep; + wire axis_i_1_tready, axis_o_1_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_dma_i_tdata , axis_dma_o_tdata; + wire axis_dma_i_tvalid, axis_dma_o_tvalid; + wire axis_dma_i_tlast , axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] axis_dma_i_tuser , axis_dma_o_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_dma_i_tkeep , axis_dma_o_tkeep; + wire axis_dma_i_tready, axis_dma_o_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_0_tdata , p_axis_o_0_tdata; + wire p_axis_i_0_tvalid, p_axis_o_0_tvalid; + wire p_axis_i_0_tlast , p_axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_0_tuser , p_axis_o_0_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_0_tkeep , p_axis_o_0_tkeep; + wire p_axis_i_0_tready, p_axis_o_0_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_1_tdata , p_axis_o_1_tdata; + wire p_axis_i_1_tvalid, p_axis_o_1_tvalid; + wire p_axis_i_1_tlast , p_axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_1_tuser , p_axis_o_1_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_1_tkeep , p_axis_o_1_tkeep; + wire p_axis_i_1_tready, p_axis_o_1_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_dma_i_tdata , p_axis_dma_o_tdata; + wire p_axis_dma_i_tvalid, p_axis_dma_o_tvalid; + wire p_axis_dma_i_tlast , p_axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_dma_i_tuser , p_axis_dma_o_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_dma_i_tkeep , p_axis_dma_o_tkeep; + wire p_axis_dma_i_tready, p_axis_dma_o_tready; + //----------------------------------------------------------------------------------------------------------------// + // AXI Lite interface // + //----------------------------------------------------------------------------------------------------------------// + wire [31:0] M0_AXI_araddr , M1_AXI_araddr , M2_AXI_araddr; + wire [2:0] M0_AXI_arprot , M1_AXI_arprot , M2_AXI_arprot; + wire M0_AXI_arready, M1_AXI_arready, M2_AXI_arready; + wire M0_AXI_arvalid, M1_AXI_arvalid, M2_AXI_arvalid; + wire [31:0] M0_AXI_awaddr , M1_AXI_awaddr , M2_AXI_awaddr; + wire [2:0] M0_AXI_awprot , M1_AXI_awprot , M2_AXI_awprot; + wire M0_AXI_awready, M1_AXI_awready, M2_AXI_awready; + wire M0_AXI_awvalid, M1_AXI_awvalid, M2_AXI_awvalid; + wire M0_AXI_bready , M1_AXI_bready , M2_AXI_bready; + wire [1:0] M0_AXI_bresp , M1_AXI_bresp , M2_AXI_bresp; + wire M0_AXI_bvalid , M1_AXI_bvalid , M2_AXI_bvalid; + wire [31:0] M0_AXI_rdata , M1_AXI_rdata , M2_AXI_rdata; + wire M0_AXI_rready , M1_AXI_rready , M2_AXI_rready; + wire [1:0] M0_AXI_rresp , M1_AXI_rresp , M2_AXI_rresp; + wire M0_AXI_rvalid , M1_AXI_rvalid , M2_AXI_rvalid; + wire [31:0] M0_AXI_wdata , M1_AXI_wdata , M2_AXI_wdata; + wire M0_AXI_wready , M1_AXI_wready , M2_AXI_wready; + wire [3:0] M0_AXI_wstrb , M1_AXI_wstrb , M2_AXI_wstrb; + wire M0_AXI_wvalid , M1_AXI_wvalid , M2_AXI_wvalid; + + wire [31:0] M3_AXI_araddr , M4_AXI_araddr , M5_AXI_araddr; + wire [2:0] M3_AXI_arprot , M4_AXI_arprot , M5_AXI_arprot; + wire M3_AXI_arready, M4_AXI_arready, M5_AXI_arready; + wire M3_AXI_arvalid, M4_AXI_arvalid, M5_AXI_arvalid; + wire [31:0] M3_AXI_awaddr , M4_AXI_awaddr , M5_AXI_awaddr; + wire [2:0] M3_AXI_awprot , M4_AXI_awprot , M5_AXI_awprot; + wire M3_AXI_awready, M4_AXI_awready, M5_AXI_awready; + wire M3_AXI_awvalid, M4_AXI_awvalid, M5_AXI_awvalid; + wire M3_AXI_bready , M4_AXI_bready , M5_AXI_bready; + wire [1:0] M3_AXI_bresp , M4_AXI_bresp , M5_AXI_bresp; + wire M3_AXI_bvalid , M4_AXI_bvalid , M5_AXI_bvalid; + wire [31:0] M3_AXI_rdata , M4_AXI_rdata , M5_AXI_rdata; + wire M3_AXI_rready , M4_AXI_rready , M5_AXI_rready; + wire [1:0] M3_AXI_rresp , M4_AXI_rresp , M5_AXI_rresp; + wire M3_AXI_rvalid , M4_AXI_rvalid , M5_AXI_rvalid; + wire [31:0] M3_AXI_wdata , M4_AXI_wdata , M5_AXI_wdata; + wire M3_AXI_wready , M4_AXI_wready , M5_AXI_wready; + wire [3:0] M3_AXI_wstrb , M4_AXI_wstrb , M5_AXI_wstrb; + wire M3_AXI_wvalid , M4_AXI_wvalid , M5_AXI_wvalid; + + wire [31:0] S00_AXI_araddr; + wire [2:0] S00_AXI_arprot /*= 3'b010*/; + wire S00_AXI_arready; + wire S00_AXI_arvalid; + wire [31:0] S00_AXI_awaddr; + wire [2:0] S00_AXI_awprot /*= 3'b010*/; + wire S00_AXI_awready; + wire S00_AXI_awvalid; + wire S00_AXI_bready; + wire [1:0] S00_AXI_bresp; + wire S00_AXI_bvalid; + wire [31:0] S00_AXI_rdata; + wire S00_AXI_rready; + wire [1:0] S00_AXI_rresp; + wire S00_AXI_rvalid; + wire [31:0] S00_AXI_wdata; + wire S00_AXI_wready; + wire [3:0] S00_AXI_wstrb; + wire S00_AXI_wvalid; + + // Network Interfaces + wire axi_aresetn; + wire axi_clk; + wire [10:0] counter0,counter1,counter2,counter3,counter4; + wire activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0; + wire activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0; + wire barrier_req0, barrier_req1, barrier_req2, barrier_req3, barrier_req4; + wire barrier_proceed; + wire activity_trans_sim; + wire activity_trans_log; + wire barrier_req_trans; + + //--------------------------------------------------------------------- + // Misc + //--------------------------------------------------------------------- + IBUF sys_reset_n_ibuf ( .O(sys_rst_n_c), .I(sys_reset_n)); + + reg [15:0] sys_clk_count; + always @(posedge ~sys_clk) + sys_clk_count <= sys_clk_count + 1'b1; + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_inst ( + .O (sys_clk), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (pci_clk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (pci_clk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_core_inst ( + .O (clk_200), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (fpga_sysclk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (fpga_sysclk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + // drive AXI-lite from sys_clk & sys_rst + assign axi_clk = sys_clk; + assign axi_aresetn = sys_rst_n_c; + +//-----------------------------------------------------------------------------------------------// +// Network modules // +//-----------------------------------------------------------------------------------------------// + + nf_datapath + #( + // Master AXI Stream Data Width + .C_M_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_S_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_M_AXIS_TUSER_WIDTH (128), + .C_S_AXIS_TUSER_WIDTH (128), + .NUM_QUEUES (5) + ) + nf_datapath_0 + ( + .axis_aclk (clk_200), + .axis_resetn (sys_rst_n_c), + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + + // Slave Stream Ports (interface from Rx queues) + .s_axis_0_tdata (axis_i_0_tdata), + .s_axis_0_tkeep (axis_i_0_tkeep), + .s_axis_0_tuser (axis_i_0_tuser), + .s_axis_0_tvalid (axis_i_0_tvalid), + .s_axis_0_tready (axis_i_0_tready), + .s_axis_0_tlast (axis_i_0_tlast), + .s_axis_1_tdata (axis_i_1_tdata), + .s_axis_1_tkeep (axis_i_1_tkeep), + .s_axis_1_tuser (axis_i_1_tuser), + .s_axis_1_tvalid (axis_i_1_tvalid), + .s_axis_1_tready (axis_i_1_tready), + .s_axis_1_tlast (axis_i_1_tlast), + .s_axis_2_tdata (axis_dma_i_tdata), + .s_axis_2_tkeep (axis_dma_i_tkeep), + .s_axis_2_tuser (axis_dma_i_tuser), + .s_axis_2_tvalid (axis_dma_i_tvalid), + .s_axis_2_tready (axis_dma_i_tready), + .s_axis_2_tlast (axis_dma_i_tlast), + + + // Master Stream Ports (interface to TX queues) + .m_axis_0_tdata (axis_o_0_tdata), + .m_axis_0_tkeep (axis_o_0_tkeep), + .m_axis_0_tuser (axis_o_0_tuser), + .m_axis_0_tvalid (axis_o_0_tvalid), + .m_axis_0_tready (axis_o_0_tready), + .m_axis_0_tlast (axis_o_0_tlast), + .m_axis_1_tdata (axis_o_1_tdata), + .m_axis_1_tkeep (axis_o_1_tkeep), + .m_axis_1_tuser (axis_o_1_tuser), + .m_axis_1_tvalid (axis_o_1_tvalid), + .m_axis_1_tready (axis_o_1_tready), + .m_axis_1_tlast (axis_o_1_tlast), + .m_axis_2_tdata (axis_dma_o_tdata), + .m_axis_2_tkeep (axis_dma_o_tkeep), + .m_axis_2_tuser (axis_dma_o_tuser), + .m_axis_2_tvalid (axis_dma_o_tvalid), + .m_axis_2_tready (axis_dma_o_tready), + .m_axis_2_tlast (axis_dma_o_tlast), + + //AXI-Lite interface + .S0_AXI_AWADDR (M0_AXI_awaddr), + .S0_AXI_AWVALID (M0_AXI_awvalid), + .S0_AXI_WDATA (M0_AXI_wdata), + .S0_AXI_WSTRB (M0_AXI_wstrb), + .S0_AXI_WVALID (M0_AXI_wvalid), + .S0_AXI_BREADY (M0_AXI_bready), + .S0_AXI_ARADDR (M0_AXI_araddr), + .S0_AXI_ARVALID (M0_AXI_arvalid), + .S0_AXI_RREADY (M0_AXI_rready), + .S0_AXI_ARREADY (M0_AXI_arready), + .S0_AXI_RDATA (M0_AXI_rdata), + .S0_AXI_RRESP (M0_AXI_rresp), + .S0_AXI_RVALID (M0_AXI_rvalid), + .S0_AXI_WREADY (M0_AXI_wready), + .S0_AXI_BRESP (M0_AXI_bresp), + .S0_AXI_BVALID (M0_AXI_bvalid), + .S0_AXI_AWREADY (M0_AXI_awready), + + .S1_AXI_AWADDR (M1_AXI_awaddr), + .S1_AXI_AWVALID (M1_AXI_awvalid), + .S1_AXI_WDATA (M1_AXI_wdata), + .S1_AXI_WSTRB (M1_AXI_wstrb), + .S1_AXI_WVALID (M1_AXI_wvalid), + .S1_AXI_BREADY (M1_AXI_bready), + .S1_AXI_ARADDR (M1_AXI_araddr), + .S1_AXI_ARVALID (M1_AXI_arvalid), + .S1_AXI_RREADY (M1_AXI_rready), + .S1_AXI_ARREADY (M1_AXI_arready), + .S1_AXI_RDATA (M1_AXI_rdata), + .S1_AXI_RRESP (M1_AXI_rresp), + .S1_AXI_RVALID (M1_AXI_rvalid), + .S1_AXI_WREADY (M1_AXI_wready), + .S1_AXI_BRESP (M1_AXI_bresp), + .S1_AXI_BVALID (M1_AXI_bvalid), + .S1_AXI_AWREADY (M1_AXI_awready), + + .S2_AXI_AWADDR (M2_AXI_awaddr), + .S2_AXI_AWVALID (M2_AXI_awvalid), + .S2_AXI_WDATA (M2_AXI_wdata), + .S2_AXI_WSTRB (M2_AXI_wstrb), + .S2_AXI_WVALID (M2_AXI_wvalid), + .S2_AXI_BREADY (M2_AXI_bready), + .S2_AXI_ARADDR (M2_AXI_araddr), + .S2_AXI_ARVALID (M2_AXI_arvalid), + .S2_AXI_RREADY (M2_AXI_rready), + .S2_AXI_ARREADY (M2_AXI_arready), + .S2_AXI_RDATA (M2_AXI_rdata), + .S2_AXI_RRESP (M2_AXI_rresp), + .S2_AXI_RVALID (M2_AXI_rvalid), + .S2_AXI_WREADY (M2_AXI_wready), + .S2_AXI_BRESP (M2_AXI_bresp), + .S2_AXI_BVALID (M2_AXI_bvalid), + .S2_AXI_AWREADY (M2_AXI_awready) + ); + + axis_sim_stim_ip0 axis_sim_stim_0 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_0_tdata), + .M_AXIS_TKEEP (p_axis_i_0_tkeep), + .M_AXIS_TUSER (p_axis_i_0_tuser), + .M_AXIS_TVALID (p_axis_i_0_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_0_tlast), + + .counter (counter0), + .activity_stim (activity_stim0), + .barrier_req (barrier_req0), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip1 axis_sim_stim_1 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_1_tdata), + .M_AXIS_TKEEP (p_axis_i_1_tkeep), + .M_AXIS_TUSER (p_axis_i_1_tuser), + .M_AXIS_TVALID (p_axis_i_1_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_1_tlast), + + .counter (counter1), + .activity_stim (activity_stim1), + .barrier_req (barrier_req1), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip2 axis_sim_stim_2 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_dma_i_tdata), + .M_AXIS_TKEEP (p_axis_dma_i_tkeep), + .M_AXIS_TUSER (p_axis_dma_i_tuser), + .M_AXIS_TVALID (p_axis_dma_i_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_dma_i_tlast), + + .counter (counter4), + .activity_stim (activity_stim4), + .barrier_req (barrier_req4), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_record_ip0 axis_sim_record_0 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_0_tdata), + .s_axis_tkeep (p_axis_o_0_tkeep), + .s_axis_tuser (p_axis_o_0_tuser), + .s_axis_tvalid(p_axis_o_0_tvalid), + .s_axis_tready(p_axis_o_0_tready), + .s_axis_tlast (p_axis_o_0_tlast), + + .counter (counter0), + .activity_rec(activity_rec0) + ); + + axis_sim_record_ip1 axis_sim_record_1 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_1_tdata), + .s_axis_tkeep (p_axis_o_1_tkeep), + .s_axis_tuser (p_axis_o_1_tuser), + .s_axis_tvalid(p_axis_o_1_tvalid), + .s_axis_tready(p_axis_o_1_tready), + .s_axis_tlast (p_axis_o_1_tlast), + + .counter (counter1), + .activity_rec(activity_rec1) + ); + + axis_sim_record_ip2 axis_sim_record_2 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_dma_o_tdata), + .s_axis_tkeep (p_axis_dma_o_tkeep), + .s_axis_tuser (p_axis_dma_o_tuser), + .s_axis_tvalid(p_axis_dma_o_tvalid), + .s_axis_tready(p_axis_dma_o_tready), + .s_axis_tlast (p_axis_dma_o_tlast), + + .counter (counter4), + .activity_rec(activity_rec4) + ); + + nf_mac_attachment_dma_ip u_nf_attachment_dma ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_dma_i_tdata), + .m_axis_mac_tkeep (p_axis_dma_i_tkeep), + .m_axis_mac_tvalid (p_axis_dma_i_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_dma_i_tuser), + .m_axis_mac_tlast (p_axis_dma_i_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_dma_o_tdata), + .s_axis_mac_tkeep (p_axis_dma_o_tkeep), + .s_axis_mac_tvalid (p_axis_dma_o_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_dma_o_tuser), + .s_axis_mac_tlast (p_axis_dma_o_tlast), + .s_axis_mac_tready (p_axis_dma_o_tready), + + // TX/RX DATA channels + .interface_number (8'd0), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_dma_o_tdata), + .s_axis_pipe_tkeep (axis_dma_o_tkeep), + .s_axis_pipe_tlast (axis_dma_o_tlast), + .s_axis_pipe_tuser (axis_dma_o_tuser), + .s_axis_pipe_tvalid (axis_dma_o_tvalid), + .s_axis_pipe_tready (axis_dma_o_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_dma_i_tdata), + .m_axis_pipe_tkeep (axis_dma_i_tkeep), + .m_axis_pipe_tlast (axis_dma_i_tlast), + .m_axis_pipe_tuser (axis_dma_i_tuser), + .m_axis_pipe_tvalid (axis_dma_i_tvalid), + .m_axis_pipe_tready (axis_dma_i_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_0 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_0_tdata), + .m_axis_mac_tkeep (p_axis_i_0_tkeep), + .m_axis_mac_tvalid (p_axis_i_0_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_0_tuser), + .m_axis_mac_tlast (p_axis_i_0_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_0_tdata), + .s_axis_mac_tkeep (p_axis_o_0_tkeep), + .s_axis_mac_tvalid (p_axis_o_0_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_o_0_tuser), + .s_axis_mac_tlast (p_axis_o_0_tlast), + .s_axis_mac_tready (p_axis_o_0_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0001), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_0_tdata), + .s_axis_pipe_tkeep (axis_o_0_tkeep), + .s_axis_pipe_tlast (axis_o_0_tlast), + .s_axis_pipe_tuser (axis_o_0_tuser), + .s_axis_pipe_tvalid (axis_o_0_tvalid), + .s_axis_pipe_tready (axis_o_0_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_0_tdata), + .m_axis_pipe_tkeep (axis_i_0_tkeep), + .m_axis_pipe_tlast (axis_i_0_tlast), + .m_axis_pipe_tuser (axis_i_0_tuser), + .m_axis_pipe_tvalid (axis_i_0_tvalid), + .m_axis_pipe_tready (axis_i_0_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_1 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_1_tdata), + .m_axis_mac_tkeep (p_axis_i_1_tkeep), + .m_axis_mac_tvalid (p_axis_i_1_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_1_tuser), + .m_axis_mac_tlast (p_axis_i_1_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_1_tdata), + .s_axis_mac_tkeep (p_axis_o_1_tkeep), + .s_axis_mac_tvalid (p_axis_o_1_tvalid), + .s_axis_mac_tuser_err (p_axis_o_1_tuser), //underrun + .s_axis_mac_tuser (p_axis_o_1_tuser), + .s_axis_mac_tlast (p_axis_o_1_tlast), + .s_axis_mac_tready (p_axis_o_1_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0100), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_1_tdata), + .s_axis_pipe_tkeep (axis_o_1_tkeep), + .s_axis_pipe_tlast (axis_o_1_tlast), + .s_axis_pipe_tuser (axis_o_1_tuser), + .s_axis_pipe_tvalid (axis_o_1_tvalid), + .s_axis_pipe_tready (axis_o_1_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_1_tdata), + .m_axis_pipe_tkeep (axis_i_1_tkeep), + .m_axis_pipe_tlast (axis_i_1_tlast), + .m_axis_pipe_tuser (axis_i_1_tuser), + .m_axis_pipe_tvalid (axis_i_1_tvalid), + .m_axis_pipe_tready (axis_i_1_tready) + ); + + axi_crossbar_0 u_interconnect( + .aclk (axi_clk), + .aresetn (axi_aresetn), + .s_axi_awaddr (S00_AXI_awaddr), + .s_axi_awprot (3'b010), + .s_axi_awvalid (S00_AXI_awvalid), + .s_axi_awready (S00_AXI_awready), + .s_axi_wdata (S00_AXI_wdata ), + .s_axi_wstrb (4'hf), + .s_axi_wvalid (S00_AXI_wvalid ), + .s_axi_wready (S00_AXI_wready ), + .s_axi_bresp (S00_AXI_bresp ), + .s_axi_bvalid (S00_AXI_bvalid ), + .s_axi_bready (S00_AXI_bready ), + .s_axi_araddr (S00_AXI_araddr[31:0]), + .s_axi_arprot (3'b010), + .s_axi_arvalid (S00_AXI_arvalid ), + .s_axi_arready (S00_AXI_arready ), + .s_axi_rdata (S00_AXI_rdata ), + .s_axi_rresp (S00_AXI_rresp ), + .s_axi_rvalid (S00_AXI_rvalid ), + .s_axi_rready (S00_AXI_rready ), + .m_axi_awaddr ({M2_AXI_awaddr[31:0] ,M1_AXI_awaddr[31:0] ,M0_AXI_awaddr[31:0] }), + .m_axi_awprot (), + .m_axi_awvalid ({M2_AXI_awvalid,M1_AXI_awvalid,M0_AXI_awvalid}), + .m_axi_awready ({M2_AXI_awready,M1_AXI_awready,M0_AXI_awready}), + .m_axi_wdata ({M2_AXI_wdata ,M1_AXI_wdata ,M0_AXI_wdata }), + .m_axi_wstrb ({M2_AXI_wstrb ,M1_AXI_wstrb ,M0_AXI_wstrb }), + .m_axi_wvalid ({M2_AXI_wvalid ,M1_AXI_wvalid ,M0_AXI_wvalid }), + .m_axi_wready ({M2_AXI_wready ,M1_AXI_wready ,M0_AXI_wready }), + .m_axi_bresp ({M2_AXI_bresp ,M1_AXI_bresp ,M0_AXI_bresp }), + .m_axi_bvalid ({M2_AXI_bvalid ,M1_AXI_bvalid ,M0_AXI_bvalid }), + .m_axi_bready ({M2_AXI_bready ,M1_AXI_bready ,M0_AXI_bready }), + .m_axi_araddr ({M2_AXI_araddr ,M1_AXI_araddr ,M0_AXI_araddr }), + .m_axi_arprot (), + .m_axi_arvalid ({M2_AXI_arvalid,M1_AXI_arvalid,M0_AXI_arvalid}), + .m_axi_arready ({M2_AXI_arready,M1_AXI_arready,M0_AXI_arready}), + .m_axi_rdata ({M2_AXI_rdata ,M1_AXI_rdata ,M0_AXI_rdata }), + .m_axi_rresp ({M2_AXI_rresp ,M1_AXI_rresp ,M0_AXI_rresp }), + .m_axi_rvalid ({M2_AXI_rvalid ,M1_AXI_rvalid ,M0_AXI_rvalid }), + .m_axi_rready ({M2_AXI_rready ,M1_AXI_rready ,M0_AXI_rready }) + ); + + + axi_sim_transactor_ip axi_sim_transactor_i ( + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + //AXI Write address channel + .M_AXI_AWADDR (S00_AXI_awaddr), + .M_AXI_AWVALID (S00_AXI_awvalid), + .M_AXI_AWREADY (S00_AXI_awready), + // AXI Write data channel + .M_AXI_WDATA (S00_AXI_wdata), + .M_AXI_WSTRB (S00_AXI_wstrb), + .M_AXI_WVALID (S00_AXI_wvalid), + .M_AXI_WREADY (S00_AXI_wready), + //AXI Write response channel + .M_AXI_BRESP (S00_AXI_bresp), + .M_AXI_BVALID (S00_AXI_bvalid), + .M_AXI_BREADY (S00_AXI_bready), + //AXI Read address channel + .M_AXI_ARADDR (S00_AXI_araddr), + .M_AXI_ARVALID (S00_AXI_arvalid), + .M_AXI_ARREADY (S00_AXI_arready), + //AXI Read data & response channel + .M_AXI_RDATA (S00_AXI_rdata), + .M_AXI_RRESP (S00_AXI_rresp), + .M_AXI_RVALID (S00_AXI_rvalid), + .M_AXI_RREADY (S00_AXI_rready), + + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + + barrier_ip barrier_i ( + .activity_stim ({activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0}), + .activity_rec ({activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0}), + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req ({barrier_req4, barrier_req3, barrier_req2, barrier_req1, barrier_req0}), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + +endmodule + diff --git a/hw/projects/reference_nic/hw/hdl/top_tb.v b/hw/projects/reference_nic/hw/hdl/top_tb.v new file mode 100644 index 0000000..ddd5847 --- /dev/null +++ b/hw/projects/reference_nic/hw/hdl/top_tb.v @@ -0,0 +1,180 @@ +//- +// Copyright (c) 2015 Noa Zilberman +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// File: +// top_tb.v +// +// Module: +// top +// +// Author: Noa Zilberman +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ns / 100ps + + module top_tb # ( + parameter PL_SIM_FAST_LINK_TRAINING = "TRUE", // Simulation Speedup + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32, + parameter integer USER_CLK2_FREQ = 4, + parameter REF_CLK_FREQ = 0, // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz + parameter AXISTEN_IF_RQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_RC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_ENABLE_CLIENT_TAG = 0, + parameter AXISTEN_IF_RQ_PARITY_CHECK = 0, + parameter AXISTEN_IF_CC_PARITY_CHECK = 0, + parameter AXISTEN_IF_MC_RX_STRADDLE = 0, + parameter AXISTEN_IF_ENABLE_RX_MSG_INTFC = 0, + parameter [17:0] AXISTEN_IF_ENABLE_MSG_ROUTE = 18'h2FFFF +) ( + +); + + parameter PCIE_PERIOD = 4.0; + parameter XPHY_PERIOD = 6.4; + parameter real CORE_PERIOD = 2.9; + + localparam TCQ = 1; + localparam BAR0AXI = 32'h40000000; + localparam BAR1AXI = 32'h10000000; + localparam BAR2AXI = 32'h20000000; + localparam BAR3AXI = 32'h30000000; + localparam BAR4AXI = 32'h40000000; + localparam BAR5AXI = 32'h50000000; + localparam BAR0SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR1SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR2SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR3SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR4SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR5SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam throttle_percent = 50; + + reg sys_reset_n; + + reg sys_clk; + wire sys_clkp,sys_clkn; + reg xphy_clk; + wire xphy_refclk_p,xphy_refclk_n; + reg clk_ref; + wire clk_ref_p,clk_ref_n; + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + + + top_sim # ( + .PL_SIM_FAST_LINK_TRAINING (PL_SIM_FAST_LINK_TRAINING ), + .C_DATA_WIDTH (C_DATA_WIDTH ), + .KEEP_WIDTH (KEEP_WIDTH ), + .USER_CLK2_FREQ (USER_CLK2_FREQ ), + .REF_CLK_FREQ (REF_CLK_FREQ ), + .AXISTEN_IF_RQ_ALIGNMENT_MODE (AXISTEN_IF_RQ_ALIGNMENT_MODE ), + .AXISTEN_IF_CC_ALIGNMENT_MODE (AXISTEN_IF_CC_ALIGNMENT_MODE ), + .AXISTEN_IF_CQ_ALIGNMENT_MODE (AXISTEN_IF_CQ_ALIGNMENT_MODE ), + .AXISTEN_IF_RC_ALIGNMENT_MODE (AXISTEN_IF_RC_ALIGNMENT_MODE ), + .AXISTEN_IF_ENABLE_CLIENT_TAG (AXISTEN_IF_ENABLE_CLIENT_TAG ), + .AXISTEN_IF_RQ_PARITY_CHECK (AXISTEN_IF_RQ_PARITY_CHECK ), + .AXISTEN_IF_CC_PARITY_CHECK (AXISTEN_IF_CC_PARITY_CHECK ), + .AXISTEN_IF_MC_RX_STRADDLE (AXISTEN_IF_MC_RX_STRADDLE ), + .AXISTEN_IF_ENABLE_RX_MSG_INTFC (AXISTEN_IF_ENABLE_RX_MSG_INTFC ), + .AXISTEN_IF_ENABLE_MSG_ROUTE (AXISTEN_IF_ENABLE_MSG_ROUTE ) + ) top_sim ( + + //PCI Express + .pcie_rxn(pcie_7x_mgt_rxn), + .pcie_rxp(pcie_7x_mgt_rxp), + .pcie_txn(pcie_7x_mgt_txn), + .pcie_txp(pcie_7x_mgt_txp), + //10G Interface + + .qsfp0_rxp(rxp), + .qsfp0_rxn(rxn), + .qsfp0_txp(txp), + .qsfp0_txn(txn), + + // PCIe Clock + .pci_clk_p(sys_clkp), + .pci_clk_n(sys_clkn), + + //200MHz Clock + .fpga_sysclk_p(clk_ref_p), + .fpga_sysclk_n(clk_ref_n), + + // 156.25 MHz clock in + .qsfp_refclk_p (xphy_refclk_p), + .qsfp_refclk_n (xphy_refclk_n), + + .sys_reset_n(sys_reset_n) + ); + +//Reset handling + // Important! polarity here is opposite the one in the actual design + initial begin + sys_reset_n = 1'b0; + #(CORE_PERIOD * 200); + sys_reset_n = 1'b1; + $display("Reset Deasserted"); + end + +//Clock generation + initial begin + sys_clk = 1'b0; + #(PCIE_PERIOD/2); + forever + #(PCIE_PERIOD/2) sys_clk = ~sys_clk; + end + + assign sys_clkp = sys_clk; + assign sys_clkn = ~sys_clk; + + + initial begin + xphy_clk = 1'b0; + #(XPHY_PERIOD/2); + forever + #(XPHY_PERIOD/2) xphy_clk = ~xphy_clk; + end + + assign xphy_refclk_p = xphy_clk; + assign xphy_refclk_n = ~xphy_clk; + + initial begin + clk_ref = 1'b0; + #(CORE_PERIOD/2); + forever + #(CORE_PERIOD/2) clk_ref = ~clk_ref; +end + +assign clk_ref_p = clk_ref; +assign clk_ref_n = ~clk_ref; + +endmodule diff --git a/hw/projects/reference_nic/hw/tcl/export_registers.tcl b/hw/projects/reference_nic/hw/tcl/export_registers.tcl new file mode 100644 index 0000000..b68f620 --- /dev/null +++ b/hw/projects/reference_nic/hw/tcl/export_registers.tcl @@ -0,0 +1,160 @@ +# +# Copyright (c) 2015 Noa Zilberman, Jingyun Zhang +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# The following list include all the items that are mapped to memory segments +# The structure of each item is as follows { } + +set DEF_LIST { + {INPUT_ARBITER 0 1 input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt} \ + {OUTPUT_QUEUES 0 1 output_queues_v1_0_0/data/output_queues_regs_defines.txt} \ + {OUTPUT_PORT_LOOKUP 0 1 nic_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt} \ +} + +set target_path $::env(NF_DESIGN_DIR)/test +set target_file $target_path/nf_register_defines.h + +if {[file exists ${target_path}] == 0} { + exec mkdir -p ${target_path} +} + +###################################################### +# the following function writes the license header +# into the file +###################################################### + +proc write_header { target_file } { + +# creat a blank header file +# do a fresh rewrite in case the file already exits +file delete -force $target_file +open $target_file "w" +set h_file [open $target_file "w"] + + +puts $h_file "//-" +puts $h_file "// Copyright (c) 2015,2021 University of Cambridge" +puts $h_file "// All rights reserved." +puts $h_file "//" +puts $h_file "// This software was developed by Stanford University and the University of Cambridge Computer Laboratory " +puts $h_file "// under National Science Foundation under Grant No. CNS-0855268," +puts $h_file "// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and" +puts $h_file "// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 (\"MRC2\"), " +puts $h_file "// as part of the DARPA MRC research programme," +puts $h_file "// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project" +puts $h_file "// EP/P025374/1 alongside support from Xilinx Inc." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_START@" +puts $h_file "//" +puts $h_file "// Licensed to NetFPGA C.I.C. (NetFPGA) under one or more contributor" +puts $h_file "// license agreements. See the NOTICE file distributed with this work for" +puts $h_file "// additional information regarding copyright ownership. NetFPGA licenses this" +puts $h_file "// file to you under the NetFPGA Hardware-Software License, Version 1.0 (the" +puts $h_file "// \"License\"); you may not use this file except in compliance with the" +puts $h_file "// License. You may obtain a copy of the License at:" +puts $h_file "//" +puts $h_file "// http://www.netfpga-cic.org" +puts $h_file "//" +puts $h_file "// Unless required by applicable law or agreed to in writing, Work distributed" +puts $h_file "// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR" +puts $h_file "// CONDITIONS OF ANY KIND, either express or implied. See the License for the" +puts $h_file "// specific language governing permissions and limitations under the License." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_END@" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "// This is an automatically generated header definitions file" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "" + +close $h_file + +}; # end of proc write_header + + +###################################################### +# the following function writes all the information +# of a specific core into a file +###################################################### + +proc write_core {target_file prefix id has_registers lib_name} { + + +set h_file [open $target_file "a"] + +#First, read the memory map information from the reference_project defines file +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ + + +set baseaddr [set $prefix\_BASEADDR] +set highaddr [set $prefix\_HIGHADDR] +set sizeaddr [set $prefix\_SIZEADDR] + +puts $h_file "//######################################################" +puts $h_file "//# Definitions for $prefix" +puts $h_file "//######################################################" + +puts $h_file "#define NFPLUS_$prefix\_BASEADDR $baseaddr" +puts $h_file "#define NFPLUS_$prefix\_HIGHADDR $highaddr" +puts $h_file "#define NFPLUS_$prefix\_SIZEADDR $sizeaddr" +puts $h_file "" + +#Second, read the registers information from the library defines file +if $has_registers { + set lib_path "$public_repo_dir/std/$lib_name" + set regs_h_define_file $lib_path + set regs_h_define_file_read [open $regs_h_define_file r] + set regs_h_define_file_data [read $regs_h_define_file_read] + close $regs_h_define_file_read + set regs_h_define_file_data_line [split $regs_h_define_file_data "\n"] + + foreach read_line $regs_h_define_file_data_line { + if {[regexp "#define" $read_line]} { + puts $h_file "#define NFPLUS_[lindex $read_line 2]\_$id\_[lindex $read_line 3]\_[lindex $read_line 4] [lindex $read_line 5]" + } + } +} +puts $h_file "" +close $h_file +}; # end of proc write_core + + + +###################################################### +# the main function +###################################################### + + + +write_header $target_file + +foreach lib_item $DEF_LIST { + write_core $target_file [lindex $lib_item 0] [lindex $lib_item 1] [lindex $lib_item 2] [lindex $lib_item 3] +} + diff --git a/hw/projects/reference_nic/hw/tcl/reference_nic.tcl b/hw/projects/reference_nic/hw/tcl/reference_nic.tcl new file mode 100644 index 0000000..fd8c347 --- /dev/null +++ b/hw/projects/reference_nic/hw/tcl/reference_nic.tcl @@ -0,0 +1,365 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib +set repo_dir ./ip_repo +set project_constraints "${public_repo_dir}/common/constraints/${board_name}_general.xdc" + +set start_time [exec date +%s] +set_param general.maxThreads 8 +set_param synth.elaboration.rodinMoreOptions "rt::set_parameter max_loop_limit 200000" +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +set datapath_freq_mhz 250 +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +if {[string match $board_name "au280"]} { + set_property verilog_define { {BOARD_AU280} {au280} {__synthesis__} } [current_fileset] + set board_param "AU280" +} elseif {[string match $board_name "au250"]} { + set_property verilog_define { {BOARD_AU250} {__synthesis__} } [current_fileset] + set board_param "AU250" +} elseif {[string match $board_name "au200"]} { + set_property verilog_define { {BOARD_AU200} {__synthesis__} } [current_fileset] + set board_param "AU200" +} elseif {[string match $board_name "vcu1525"]} { + set_property verilog_define { {BOARD_VCU1525} {__synthesis__} } [current_fileset] + set board_param "VCU1525" +} +set_property generic "C_NF_DATA_WIDTH=${datapath_width_bit} BOARD=\"${board_param}\"" [current_fileset] + +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] +##################################### +# Project Constraints +##################################### +add_files -fileset constraints -norecurse ${project_constraints} +if {[string match $board_name "au280"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au280_timing.tcl +} elseif {[string match $board_name "au200"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au200_vcu1525_user_timing.tcl +} elseif {[string match $board_name "vcu1525"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au200_vcu1525_user_timing.tcl +} else { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au250_timing.tcl +} +set_property is_enabled true [get_files ${project_constraints}] +set_property constrset constraints [get_runs synth_1] +set_property constrset constraints [get_runs impl_1] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name nic_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name nic_output_port_lookup_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nic_output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nic_output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files nic_output_port_lookup_ip.xci] +reset_target all [get_ips nic_output_port_lookup_ip] +generate_target all [get_ips nic_output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] + +create_ip -name xilinx_shell -vendor xilinx -library xilinx -module_name xilinx_shell_ip +set_property CONFIG.MAX_PKT_LEN 1518 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_QUEUE 2048 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_PHYS_FUNC 2 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_CMAC_PORT 2 [get_ips xilinx_shell_ip] +set_property generate_synth_checkpoint false [get_files xilinx_shell_ip.xci] +reset_target all [get_ips xilinx_shell_ip] +generate_target all [get_ips xilinx_shell_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000000000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000020000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + +#Add a clock wizard +create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name clk_wiz_1 +if {[string match "${datapath_freq_mhz}" "200"]} { +#200MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {6.000} \ + CONFIG.CLKOUT1_JITTER {119.392} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "250"]} { +#250MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {250.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {1} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {4.750} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.750} \ + CONFIG.CLKOUT1_JITTER {85.152} \ + CONFIG.CLKOUT1_PHASE_ERROR {78.266}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "260"]} { +#260MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {260.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {120.250} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.625} \ + CONFIG.CLKOUT1_JITTER {182.359} \ + CONFIG.CLKOUT1_PHASE_ERROR {351.991}] [get_ips clk_wiz_10] +} elseif {[string match "${datapath_freq_mhz}" "280"]} { +#280MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {280.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {119.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.250} \ + CONFIG.CLKOUT1_JITTER {183.720} \ + CONFIG.CLKOUT1_PHASE_ERROR {357.524}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "300"]} { +#300MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {300.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.000} \ + CONFIG.CLKOUT1_JITTER {111.430} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "320"]} { +#320MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {320.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.750} \ + CONFIG.CLKOUT1_JITTER {110.215} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} else { + puts "Error: the specified clock is error" + exit -1 +} +set_property generate_synth_checkpoint false [get_files clk_wiz_1.xci] +reset_target all [get_ips clk_wiz_1] +generate_target all [get_ips clk_wiz_1] + +read_verilog "./hdl/nf_datapath.v" +read_verilog -sv "${public_repo_dir}/common/hdl/top_wrapper.sv" +read_verilog -sv "${public_repo_dir}/common/hdl/nf_attachment.sv" +read_verilog "${public_repo_dir}/common/hdl/top.v" + +#Setting Synthesis options +create_run -flow {Vivado Synthesis 2020} synth +set_property write_incremental_synth_checkpoint true [get_runs synth_1] +set_property AUTO_INCREMENTAL_CHECKPOINT 1 [get_runs synth_1] +#Setting Implementation options +create_run impl -parent_run synth -flow {Vivado Implementation 2020} +set_property strategy Performance_Explore [get_runs impl_1] +set_property steps.phys_opt_design.is_enabled true [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AlternateFlowWithRetiming [get_runs impl_1] +set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE ExploreWithHoldFix [get_runs impl_1] +set_property STEPS.PLACE_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.is_enabled true [get_runs impl_1] + +#set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +# The following implementation options will increase runtime, but get the best timing results +#set_property strategy Performance_Explore [get_runs impl_1] +### Solves synthesis crash in 2013.2 +##set_param synth.filterSetMaxDelayWithDataPathOnly true +set_property SEVERITY {Warning} [get_drc_checks UCIO-1] +launch_runs synth +wait_on_run synth +launch_runs impl_1 +wait_on_run impl_1 +open_checkpoint project/${design}.runs/impl_1/top_postroute_physopt.dcp +if {![file exists "../bitfiles"]} { + file mkdir "../bitfiles" +} +write_bitstream -force ../bitfiles/${design}_${board_name}.bit + +# -- For Report -- +set end_time [exec date +%s] +set elapsed_time [expr ${end_time} - ${start_time}] +if {[catch {exec grep -A 4 "VIOLAT" project/${design}.runs/impl_1/top_timing_summary_postroute_physopted.rpt} timing_report_data]} { + set timing_report "Met" + set timing_report_data "" +} else { + set timing_report "VIOLATED" +} +puts " --- Report : ${design} for ${board_name} --- " +puts " Synth time : ${elapsed_time}" +puts " Timing Closure: ${timing_report}" +puts "${timing_report_data}" + +exit + diff --git a/hw/projects/reference_nic/hw/tcl/reference_nic_defines.tcl b/hw/projects/reference_nic/hw/tcl/reference_nic_defines.tcl new file mode 100644 index 0000000..dba3b82 --- /dev/null +++ b/hw/projects/reference_nic/hw/tcl/reference_nic_defines.tcl @@ -0,0 +1,79 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +####################### +# Segments Assignment # +####################### +#M00 +set M00_BASEADDR 0x00010000 +set M00_HIGHADDR 0x00010FFF +set M00_SIZEADDR 0x1000 + +#M01 +set M01_BASEADDR 0x00020000 +set M01_HIGHADDR 0x00020FFF +set M01_SIZEADDR 0x1000 + +#M02 +set M02_BASEADDR 0x00030000 +set M02_HIGHADDR 0x00030FFF +set M02_SIZEADDR 0x1000 + +##M03 +#set M03_BASEADDR 0x44030000 +#set M03_HIGHADDR 0x44030FFF +#set M03_SIZEADDR 0x1000 +# + +####################### +# IP_ASSIGNMENT # +####################### +# Note that physical connectivity must match this mapping + +##IDENTIFIER base address and size +#set IDENTIFIER_BASEADDR $M00_BASEADDR +#set IDENTIFIER_HIGHADDR $M00_HIGHADDR +#set IDENTIFIER_SIZEADDR $M00_SIZEADDR + + +#INPUT ARBITER base address and size +set INPUT_ARBITER_BASEADDR $M00_BASEADDR +set INPUT_ARBITER_HIGHADDR $M00_HIGHADDR +set INPUT_ARBITER_SIZEADDR $M00_SIZEADDR + +#OUTPUT_QUEUES base address and size +set OUTPUT_QUEUES_BASEADDR $M02_BASEADDR +set OUTPUT_QUEUES_HIGHADDR $M02_HIGHADDR +set OUTPUT_QUEUES_SIZEADDR $M02_SIZEADDR + +#OUPUT_PORT_LOOKUP base address and size +set OUTPUT_PORT_LOOKUP_BASEADDR $M01_BASEADDR +set OUTPUT_PORT_LOOKUP_HIGHADDR $M01_HIGHADDR +set OUTPUT_PORT_LOOKUP_SIZEADDR $M01_SIZEADDR diff --git a/hw/projects/reference_nic/hw/tcl/reference_nic_sim.tcl b/hw/projects/reference_nic/hw/tcl/reference_nic_sim.tcl new file mode 100644 index 0000000..8bcaa4a --- /dev/null +++ b/hw/projects/reference_nic/hw/tcl/reference_nic_sim.tcl @@ -0,0 +1,248 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top_sim +set sim_top top_tb +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) + +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ +set repo_dir ./ip_repo +set project_constraints ./constraints/${board_name}_switch.xdc + +set test_name [lindex $argv 0] +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl + +set_param general.maxThreads 8 +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name nic_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name nic_output_port_lookup_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nic_output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nic_output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files nic_output_port_lookup_ip.xci] +reset_target all [get_ips nic_output_port_lookup_ip] +generate_target all [get_ips nic_output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] +create_ip -name barrier -vendor NetFPGA -library NetFPGA -module_name barrier_ip +reset_target all [get_ips barrier_ip] +generate_target all [get_ips barrier_ip] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip0 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_0_log.axi] [get_ips axis_sim_record_ip0] +reset_target all [get_ips axis_sim_record_ip0] +generate_target all [get_ips axis_sim_record_ip0] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip1 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_1_log.axi] [get_ips axis_sim_record_ip1] +reset_target all [get_ips axis_sim_record_ip1] +generate_target all [get_ips axis_sim_record_ip1] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip2 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/dma_0_log.axi] [get_ips axis_sim_record_ip2] +reset_target all [get_ips axis_sim_record_ip2] +generate_target all [get_ips axis_sim_record_ip2] + + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip0 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_0_stim.axi] [get_ips axis_sim_stim_ip0] +generate_target all [get_ips axis_sim_stim_ip0] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip1 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_1_stim.axi] [get_ips axis_sim_stim_ip1] +generate_target all [get_ips axis_sim_stim_ip1] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip2 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/dma_0_stim.axi] [get_ips axis_sim_stim_ip2] +generate_target all [get_ips axis_sim_stim_ip2] + + +create_ip -name axi_sim_transactor -vendor NetFPGA -library NetFPGA -module_name axi_sim_transactor_ip +set_property -dict [list CONFIG.STIM_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.axi CONFIG.EXPECT_FILE $::env(NF_DESIGN_DIR)/test/reg_expect.axi CONFIG.LOG_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.log] [get_ips axi_sim_transactor_ip] +reset_target all [get_ips axi_sim_transactor_ip] +generate_target all [get_ips axi_sim_transactor_ip] + + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000020000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000030000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/nf_datapath.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_sim.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_tb.v" + +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 + +set_property top ${sim_top} [get_filesets sim_1] +set_property include_dirs ${proj_dir} [get_filesets sim_1] +set_property simulator_language Mixed [current_project] +set_property verilog_define { {SIMULATION=1} } [get_filesets sim_1] +set_property -name xsim.more_options -value {-testplusarg TESTNAME=basic_test} -objects [get_filesets sim_1] +set_property runtime {} [get_filesets sim_1] +set_property target_simulator xsim [current_project] +set_property compxlib.compiled_library_dir {} [current_project] +set_property top_lib xil_defaultlib [get_filesets sim_1] +update_compile_order -fileset sim_1 + +unset env(PYTHONPATH) +unset env(PYTHONHOME) +set env(PYTHONPATH) ".:$::env(NFPLUS_FOLDER)/tools/scripts/:$::env(NFPLUS_FOLDER)/tools/scripts/NFTest" +set output [exec $::env(PYTHON_BNRY) $::env(NF_DESIGN_DIR)/test/${test_name}/run.py] +puts $output + +launch_simulation -simset sim_1 -mode behavioral +run 140us + diff --git a/hw/projects/reference_nic/test/both_inc_size/run.py b/hw/projects/reference_nic/test/both_inc_size/run.py new file mode 100755 index 0000000..fe791e5 --- /dev/null +++ b/hw/projects/reference_nic/test/both_inc_size/run.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_nic import * + +conn = ('../connections/conn', []) +nftest_init(sim_loop = ['nf0', 'nf1'], hw_config = [conn]) + +if isHW(): + # reset_counters (triggered by Write only event) for all the modules + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +nftest_start() + +# set parameters +SA = "aa:bb:cc:dd:ee:ff" +TTL = 64 +DST_IP = "192.168.1.1" +SRC_IP = "192.168.0.1" +nextHopMAC = "dd:55:dd:66:dd:77" +if isHW(): + NUM_PKTS = 1454 +else: + NUM_PKTS = 1454 +num_ports = 2 + +pkts = [] + +print("Sending now: ") +totalPktLengths = [0,0] +# send NUM_PKTS from ports nf2c0...nf2c1 +for i in range(NUM_PKTS): + if isHW(): + for port in range(num_ports): + DA = "00:0a:35:03:00:%02x"%port + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=60+i) + totalPktLengths[port] += len(pkt) + + nftest_send_dma('nf' + str(port), pkt) + nftest_expect_dma('nf' + str(port), pkt) + else: + DA = "00:ca:fe:00:00:00" + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=60+i) + pkt.time = ((i*(1e-8)) + (1e-6)) + pkts.append(pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_dma('nf0', pkts) + +print("") + +nftest_barrier() + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), NUM_PKTS*num_ports*2) + rres2=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), NUM_PKTS*num_ports*2) + rres3=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTSTOREDPORT2(), NUM_PKTS*num_ports) + rres4=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTREMOVEDPORT2(), NUM_PKTS*num_ports) + rres5=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), NUM_PKTS*num_ports*2) + rres6=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), NUM_PKTS*num_ports*2) + mres=[rres1,rres2,rres3,rres4,rres5,rres6] +else: + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), NUM_PKTS) + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), NUM_PKTS) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTSTOREDPORT2(), NUM_PKTS) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTREMOVEDPORT2(), NUM_PKTS) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), NUM_PKTS) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), NUM_PKTS) + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_nic/test/both_loopback_maxsize/run.py b/hw/projects/reference_nic/test/both_loopback_maxsize/run.py new file mode 100755 index 0000000..46a0805 --- /dev/null +++ b/hw/projects/reference_nic/test/both_loopback_maxsize/run.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_nic import * + +conn = ('../connections/conn', []) +nftest_init(sim_loop = ['nf0', 'nf1'], hw_config = [conn]) + +if isHW(): + # reset_counters (triggered by Write only event) for all the modules + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +nftest_start() + +# set parameters +SA = "aa:bb:cc:dd:ee:ff" +TTL = 64 +DST_IP = "192.168.1.1" +SRC_IP = "192.168.0.1" +nextHopMAC = "dd:55:dd:66:dd:77" +if isHW(): + NUM_PKTS = 5 +else: + NUM_PKTS = 5 + +pkts = [] + +print("Sending now: ") +totalPktLengths = [0,0] +# send NUM_PKTS from ports nf2c0...nf2c3 +for i in range(NUM_PKTS): + if isHW(): + for port in range(2): + DA = "00:0a:35:03:00:%02x"%port + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=1514) + totalPktLengths[port] += len(pkt) + nftest_send_dma('nf' + str(port), pkt) + nftest_expect_dma('nf' + str(port), pkt) + else: + DA = "00:0a:35:03:00:00" + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=1514) + pkt.time = ((i*(1e-8)) + (1e-6)) + pkts.append(pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_dma('nf0', pkts) + +print("") + +simReg.regDelay(3000) +nftest_barrier() +if isHW(): + rres1=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), 0x14) + rres2=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), 0x14) + rres3=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), 0x14) + rres4=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), 0x14) + rres5=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTIN(), 0x14) + rres6=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTOUT(), 0x14) + mres=[rres1,rres2,rres3,rres4,rres5,rres6] + +else: + + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), 0x5) + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTSTOREDPORT2(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTREMOVEDPORT2(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), 0x5) + + mres=[] +nftest_finish(mres) diff --git a/hw/projects/reference_nic/test/both_loopback_minsize/run.py b/hw/projects/reference_nic/test/both_loopback_minsize/run.py new file mode 100755 index 0000000..d61a551 --- /dev/null +++ b/hw/projects/reference_nic/test/both_loopback_minsize/run.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_nic import * + +conn = ('../connections/conn', []) +nftest_init(sim_loop = ['nf0', 'nf1'], hw_config = [conn]) + +if isHW(): + # reset_counters (triggered by Write only event) for all the modules + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +nftest_start() + +# set parameters +SA = "aa:bb:cc:dd:ee:ff" +TTL = 64 +DST_IP = "192.168.1.1" +SRC_IP = "192.168.0.1" +nextHopMAC = "dd:55:dd:66:dd:77" +if isHW(): + NUM_PKTS = 5 +else: + NUM_PKTS = 5 + +pkts = [] + +print("Sending now: ") +totalPktLengths = [0,0] +simReg.regDelay(3000) +nftest_barrier() + +# send NUM_PKTS from ports nf2c0...nf2c3 +for i in range(NUM_PKTS): + if isHW(): + for port in range(2): + DA = "00:0a:35:03:00:%02x"%port + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=60) + totalPktLengths[port] += len(pkt) + + nftest_send_dma('nf' + str(port), pkt) + nftest_expect_dma('nf' + str(port), pkt) + else: + DA = "00:0a:35:03:00:00" + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=60) + pkt.time = (i*(1e-8)) + pkts.append(pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_dma('nf0', pkts) + +print("") + +nftest_barrier() + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), 0x14) + rres2=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), 0x14) + rres3=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), 0x14) + rres4=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), 0x14) + rres5=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTIN(), 0x14) + rres6=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTOUT(), 0x14) + mres=[rres1,rres2,rres3,rres4,rres5,rres6] + +else: + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), 0x5) + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTSTOREDPORT2(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTREMOVEDPORT2(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), 0x5) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), 0x5) + + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_nic/test/both_loopback_random/run.py b/hw/projects/reference_nic/test/both_loopback_random/run.py new file mode 100755 index 0000000..8efb599 --- /dev/null +++ b/hw/projects/reference_nic/test/both_loopback_random/run.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import random +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_nic import * + +conn = ('../connections/conn', []) +nftest_init(sim_loop = ['nf0', 'nf1'], hw_config = [conn]) + +if isHW(): + # reset_counters (triggered by Write only event) for all the modules + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +nftest_start() + +# set parameters +SA = "aa:bb:cc:dd:ee:ff" +TTL = 64 +DST_IP = "192.168.1.1" +SRC_IP = "192.168.0.1" +nextHopMAC = "dd:55:dd:66:dd:77" +if isHW(): + NUM_PKTS = 5 +else: + NUM_PKTS = 1024 + +pkts = [] + +print("Sending now: ") +totalPktLengths = [0,0] +simReg.regDelay(3000) +nftest_barrier() +# send NUM_PKTS from ports nf2c0...nf2c3 +for i in range(NUM_PKTS): + if isHW(): + for port in range(2): + DA = "00:0a:35:03:00:%02x"%port + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=random.randint(60,1514)) + totalPktLengths[port] += len(pkt) + nftest_send_dma('nf' + str(port), pkt) + nftest_expect_dma('nf' + str(port), pkt) + else: + DA = "00:0a:35:03:00:00" + pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, + src_IP=SRC_IP, TTL=TTL, + pkt_len=random.randint(60,1514)) + pkt.time = (i*(1e-8)) + pkts.append(pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_dma('nf0', pkts) + +print("") + +nftest_barrier() + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), 0x14) + rres2=nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), 0x14) + rres3=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), 0x14) + rres4=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), 0x14) + rres5=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTIN(), 0x14) + rres6=nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTOUT(), 0x14) + mres=[rres1,rres2,rres3,rres4,rres5,rres6] + +else: + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTIN(), 0x400) + nftest_regread_expect(NFPLUS_INPUT_ARBITER_0_PKTOUT(), 0x400) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTSTOREDPORT2(), 0x400) + nftest_regread_expect(NFPLUS_OUTPUT_QUEUES_0_PKTREMOVEDPORT2(), 0x400) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTIN(), 0x400) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKTOUT(), 0x400) + mres=[] + +nftest_finish(mres) + diff --git a/hw/projects/reference_nic/test/connections/conn b/hw/projects/reference_nic/test/connections/conn new file mode 100644 index 0000000..f1f8140 --- /dev/null +++ b/hw/projects/reference_nic/test/connections/conn @@ -0,0 +1,30 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +nf0:nf0 +nf1:nf1 diff --git a/hw/projects/reference_nic/test/global/setup b/hw/projects/reference_nic/test/global/setup new file mode 100644 index 0000000..1d4cdb9 --- /dev/null +++ b/hw/projects/reference_nic/test/global/setup @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +from subprocess import Popen, PIPE + +proc = Popen(["ifconfig","eth1","192.168.100.1"], stdout=PIPE) +proc = Popen(["ifconfig","eth2","192.168.101.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf0","192.168.200.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf1","192.168.201.1"], stdout=PIPE) diff --git a/hw/projects/reference_router/bitfiles/README b/hw/projects/reference_router/bitfiles/README new file mode 100644 index 0000000..0021f72 --- /dev/null +++ b/hw/projects/reference_router/bitfiles/README @@ -0,0 +1,42 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +Reference Router bitfile is available for a direct download from the University of Cambridge servers: + +1. Reference Router (VCU1525) +url: +md5 checksum: + +2. Reference Router (U200) +url: +md5 checksum: + +3. Reference Router (U250) +url: +md5 checksum: + +4. Reference Router (U280) +url: +md5 checksum: diff --git a/hw/projects/reference_router/hw/Makefile b/hw/projects/reference_router/hw/Makefile new file mode 100644 index 0000000..7267004 --- /dev/null +++ b/hw/projects/reference_router/hw/Makefile @@ -0,0 +1,104 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +################################################################################ +# File: +# Makefile +# +# Project: +# Makes all the cores of NetFPGA library +# +# Description: +# This makefile is used to generate and compile SDK project for NetFPGA reference projects. +# The first argument is target + +PROJ = ${NF_PROJECT_NAME} + +all: project + +project: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode batch -source tcl/${PROJ}.tcl; \ + fi + +projectgui: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode gui -source tcl/${PROJ}.tcl; \ + fi + +sim: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_${NF_PROJECT_NAME}.py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_${NF_PROJECT_NAME}.py + vivado -mode batch -source ../../../projects/${PROJ}/hw/tcl/${NF_PROJECT_NAME}_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +reg: + vivado -mode batch -source $(NF_DESIGN_DIR)/hw/tcl/export_registers.tcl + cd ../test && cp ../../../../tools/scripts/xparam2regdefines.py . && python xparam2regdefines.py + cd ../test && rm -f xparam2regdefines.py + cd ../test && cp ../../../../tools/scripts/python_parser.py . && python python_parser.py + cd ../test && rm -f python_parser.py && mv reg_defines.py reg_defines_${NF_PROJECT_NAME}.py + cp ../test/reg_defines.h $(NF_DESIGN_DIR)/sw/ + cp ../test/reg_defines.h $(NF_DESIGN_DIR)/sw/common/ + +simgui: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_$(NF_PROJECT_NAME).py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_$(NF_PROJECT_NAME).py + vivado -mode gui -source ../../../projects/${PROJ}/hw/tcl/${NF_PROJECT_NAME}_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +simclean: + rm -rf proj_* vivado*.* *.*~ .Xil* $(NF_DESIGN_DIR)/hw/ip_repo/ $(NF_DESIGN_DIR)/hw/project/ + rm -rf *[0-9]_{stim,expected,log}.axi + rm -f *.axi + rm -f portconfig.sim + rm -f nf_register_defines.h reg_defines.h + rm -f seed + rm -f *.log + rm -f ../test/Makefile + rm -rf ../test/*.log + rm -rf ../test/*.axi + rm -rf ../test/seed + rm -rf ../test/*.sim + rm -rf ../test/proj_* + rm -rf ../test/ip_repo + rm -f ../test/vivado*.* + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.py + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.pyc + +clean: + rm -rf project + rm -f vivado* + rm -rf ip_repo + rm -f nf_register_defines.h reg_defines.h diff --git a/hw/projects/reference_router/hw/constraints/au200_vcu1525_user_timing.tcl b/hw/projects/reference_router/hw/constraints/au200_vcu1525_user_timing.tcl new file mode 100644 index 0000000..c5c4dfb --- /dev/null +++ b/hw/projects/reference_router/hw/constraints/au200_vcu1525_user_timing.tcl @@ -0,0 +1,29 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +create_pblock pblock_nf_datapath +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list nf_datapath_0]] +resize_pblock [get_pblocks pblock_nf_datapath] -add {SLR2} + diff --git a/hw/projects/reference_router/hw/hdl/nf_datapath.v b/hw/projects/reference_router/hw/hdl/nf_datapath.v new file mode 100644 index 0000000..c3837e0 --- /dev/null +++ b/hw/projects/reference_router/hw/hdl/nf_datapath.v @@ -0,0 +1,378 @@ +`timescale 1ns / 1ps +//- +// Copyright (c) 2015 Noa Zilberman +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// nf_datapath.v +// +// Module: +// nf_datapath +// +// Author: Noa Zilberman +// +// Description: +// NetFPGA user data path wrapper, wrapping input arbiter, output port lookup and output queues +// +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + +module nf_datapath #( + //Slave AXI parameters + parameter C_S_AXI_DATA_WIDTH = 32, + parameter C_S_AXI_ADDR_WIDTH = 32, + parameter C_BASEADDR = 32'h00000000, + + // Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH=512, + parameter C_S_AXIS_DATA_WIDTH=512, + parameter C_M_AXIS_TUSER_WIDTH=128, + parameter C_S_AXIS_TUSER_WIDTH=128, + parameter NUM_QUEUES=5 +) ( + //Datapath clock + input axis_aclk, + input axis_resetn, + //Registers clock + input axi_aclk, + input axi_resetn, + + // Slave AXI Ports + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_AWADDR, + input S0_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S0_AXI_WSTRB, + input S0_AXI_WVALID, + input S0_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_ARADDR, + input S0_AXI_ARVALID, + input S0_AXI_RREADY, + output S0_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_RDATA, + output [1 : 0] S0_AXI_RRESP, + output S0_AXI_RVALID, + output S0_AXI_WREADY, + output [1 :0] S0_AXI_BRESP, + output S0_AXI_BVALID, + output S0_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_AWADDR, + input S1_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S1_AXI_WSTRB, + input S1_AXI_WVALID, + input S1_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_ARADDR, + input S1_AXI_ARVALID, + input S1_AXI_RREADY, + output S1_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_RDATA, + output [1 : 0] S1_AXI_RRESP, + output S1_AXI_RVALID, + output S1_AXI_WREADY, + output [1 :0] S1_AXI_BRESP, + output S1_AXI_BVALID, + output S1_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_AWADDR, + input S2_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S2_AXI_WSTRB, + input S2_AXI_WVALID, + input S2_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_ARADDR, + input S2_AXI_ARVALID, + input S2_AXI_RREADY, + output S2_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_RDATA, + output [1 : 0] S2_AXI_RRESP, + output S2_AXI_RVALID, + output S2_AXI_WREADY, + output [1 :0] S2_AXI_BRESP, + output S2_AXI_BVALID, + output S2_AXI_AWREADY, + + + // Slave Stream Ports (interface from Rx queues) + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_0_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_0_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_0_tuser, + input s_axis_0_tvalid, + output s_axis_0_tready, + input s_axis_0_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_1_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_1_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_1_tuser, + input s_axis_1_tvalid, + output s_axis_1_tready, + input s_axis_1_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_2_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_2_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_2_tuser, + input s_axis_2_tvalid, + output s_axis_2_tready, + input s_axis_2_tlast, + + // Master Stream Ports (interface to TX queues) + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_0_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_0_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_0_tuser, + output m_axis_0_tvalid, + input m_axis_0_tready, + output m_axis_0_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_1_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_1_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_1_tuser, + output m_axis_1_tvalid, + input m_axis_1_tready, + output m_axis_1_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_2_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_2_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_2_tuser, + output m_axis_2_tvalid, + input m_axis_2_tready, + output m_axis_2_tlast + + ); + + //internal connectivity + + wire [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_opl_tuser; + wire m_axis_opl_tvalid; + wire m_axis_opl_tready; + wire m_axis_opl_tlast; + + wire [C_M_AXIS_DATA_WIDTH - 1:0] s_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] s_axis_opl_tuser; + wire s_axis_opl_tvalid; + wire s_axis_opl_tready; + wire s_axis_opl_tlast; + + wire [C_M_AXIS_DATA_WIDTH - 1:0] s_axis_end_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_end_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] s_axis_end_tuser; + wire s_axis_end_tvalid; + wire s_axis_end_tready; + wire s_axis_end_tlast; + + wire [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_end_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_end_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_end_tuser; + wire m_axis_end_tvalid; + wire m_axis_end_tready; + wire m_axis_end_tlast; + + + //Input Arbiter + input_arbiter_ip input_arbiter_v1_0 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (s_axis_end_tdata), + .m_axis_tkeep (s_axis_end_tkeep), + .m_axis_tuser (s_axis_end_tuser), + .m_axis_tvalid(s_axis_end_tvalid), + .m_axis_tready(s_axis_end_tready), + .m_axis_tlast (s_axis_end_tlast), + .s_axis_0_tdata (s_axis_0_tdata), + .s_axis_0_tkeep (s_axis_0_tkeep), + .s_axis_0_tuser (s_axis_0_tuser), + .s_axis_0_tvalid(s_axis_0_tvalid), + .s_axis_0_tready(s_axis_0_tready), + .s_axis_0_tlast (s_axis_0_tlast), + .s_axis_1_tdata (s_axis_1_tdata), + .s_axis_1_tkeep (s_axis_1_tkeep), + .s_axis_1_tuser (s_axis_1_tuser), + .s_axis_1_tvalid(s_axis_1_tvalid), + .s_axis_1_tready(s_axis_1_tready), + .s_axis_1_tlast (s_axis_1_tlast), + .s_axis_2_tdata (s_axis_2_tdata), + .s_axis_2_tkeep (s_axis_2_tkeep), + .s_axis_2_tuser (s_axis_2_tuser), + .s_axis_2_tvalid(s_axis_2_tvalid), + .s_axis_2_tready(s_axis_2_tready), + .s_axis_2_tlast (s_axis_2_tlast), + .S_AXI_AWADDR(S0_AXI_AWADDR), + .S_AXI_AWVALID(S0_AXI_AWVALID), + .S_AXI_WDATA(S0_AXI_WDATA), + .S_AXI_WSTRB(S0_AXI_WSTRB), + .S_AXI_WVALID(S0_AXI_WVALID), + .S_AXI_BREADY(S0_AXI_BREADY), + .S_AXI_ARADDR(S0_AXI_ARADDR), + .S_AXI_ARVALID(S0_AXI_ARVALID), + .S_AXI_RREADY(S0_AXI_RREADY), + .S_AXI_ARREADY(S0_AXI_ARREADY), + .S_AXI_RDATA(S0_AXI_RDATA), + .S_AXI_RRESP(S0_AXI_RRESP), + .S_AXI_RVALID(S0_AXI_RVALID), + .S_AXI_WREADY(S0_AXI_WREADY), + .S_AXI_BRESP(S0_AXI_BRESP), + .S_AXI_BVALID(S0_AXI_BVALID), + .S_AXI_AWREADY(S0_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + + nf_endianess_manager_ip nf_endianess_manager_ip0 ( + .ACLK (axis_aclk), + .ARESETN (axis_resetn), + + .S_AXIS_TREADY (s_axis_end_tready), + .S_AXIS_TDATA (s_axis_end_tdata), + .S_AXIS_TLAST (s_axis_end_tlast), + .S_AXIS_TVALID (s_axis_end_tvalid), + .S_AXIS_TKEEP (s_axis_end_tkeep), + .S_AXIS_TUSER (s_axis_end_tuser), + + .M_AXIS_TVALID (m_axis_end_tvalid), + .M_AXIS_TDATA (m_axis_end_tdata), + .M_AXIS_TLAST (m_axis_end_tlast), + .M_AXIS_TREADY (m_axis_end_tready), + .M_AXIS_TKEEP (m_axis_end_tkeep), + .M_AXIS_TUSER (m_axis_end_tuser), + + .S_AXIS_INT_TREADY (m_axis_opl_tready), + .S_AXIS_INT_TLAST (m_axis_opl_tlast), + .S_AXIS_INT_TDATA (m_axis_opl_tdata), + .S_AXIS_INT_TVALID (m_axis_opl_tvalid), + .S_AXIS_INT_TKEEP (m_axis_opl_tkeep), + .S_AXIS_INT_TUSER (m_axis_opl_tuser), + + .M_AXIS_INT_TKEEP (s_axis_opl_tkeep), + .M_AXIS_INT_TUSER (s_axis_opl_tuser), + .M_AXIS_INT_TVALID (s_axis_opl_tvalid), + .M_AXIS_INT_TDATA (s_axis_opl_tdata), + .M_AXIS_INT_TLAST (s_axis_opl_tlast), + .M_AXIS_INT_TREADY (s_axis_opl_tready) + ); + + + //Output Port Lookup + router_output_port_lookup_ip output_port_lookup_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (m_axis_opl_tdata), + .m_axis_tkeep (m_axis_opl_tkeep), + .m_axis_tuser (m_axis_opl_tuser), + .m_axis_tvalid(m_axis_opl_tvalid), + .m_axis_tready(m_axis_opl_tready), + .m_axis_tlast (m_axis_opl_tlast), + .s_axis_tdata (s_axis_opl_tdata), + .s_axis_tkeep (s_axis_opl_tkeep), + .s_axis_tuser (s_axis_opl_tuser), + .s_axis_tvalid(s_axis_opl_tvalid), + .s_axis_tready(s_axis_opl_tready), + .s_axis_tlast (s_axis_opl_tlast), + + .S_AXI_AWADDR(S1_AXI_AWADDR), + .S_AXI_AWVALID(S1_AXI_AWVALID), + .S_AXI_WDATA(S1_AXI_WDATA), + .S_AXI_WSTRB(S1_AXI_WSTRB), + .S_AXI_WVALID(S1_AXI_WVALID), + .S_AXI_BREADY(S1_AXI_BREADY), + .S_AXI_ARADDR(S1_AXI_ARADDR), + .S_AXI_ARVALID(S1_AXI_ARVALID), + .S_AXI_RREADY(S1_AXI_RREADY), + .S_AXI_ARREADY(S1_AXI_ARREADY), + .S_AXI_RDATA(S1_AXI_RDATA), + .S_AXI_RRESP(S1_AXI_RRESP), + .S_AXI_RVALID(S1_AXI_RVALID), + .S_AXI_WREADY(S1_AXI_WREADY), + .S_AXI_BRESP(S1_AXI_BRESP), + .S_AXI_BVALID(S1_AXI_BVALID), + .S_AXI_AWREADY(S1_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + + + ); + + + //Output queues + output_queues_ip bram_output_queues_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .s_axis_tdata (m_axis_end_tdata), + .s_axis_tkeep (m_axis_end_tkeep), + .s_axis_tuser (m_axis_end_tuser), + .s_axis_tvalid (m_axis_end_tvalid), + .s_axis_tready (m_axis_end_tready), + .s_axis_tlast (m_axis_end_tlast), + .m_axis_0_tdata (m_axis_0_tdata), + .m_axis_0_tkeep (m_axis_0_tkeep), + .m_axis_0_tuser (m_axis_0_tuser), + .m_axis_0_tvalid(m_axis_0_tvalid), + .m_axis_0_tready(m_axis_0_tready), + .m_axis_0_tlast (m_axis_0_tlast), + .m_axis_1_tdata (m_axis_1_tdata), + .m_axis_1_tkeep (m_axis_1_tkeep), + .m_axis_1_tuser (m_axis_1_tuser), + .m_axis_1_tvalid(m_axis_1_tvalid), + .m_axis_1_tready(m_axis_1_tready), + .m_axis_1_tlast (m_axis_1_tlast), + .m_axis_2_tdata (m_axis_2_tdata), + .m_axis_2_tkeep (m_axis_2_tkeep), + .m_axis_2_tuser (m_axis_2_tuser), + .m_axis_2_tvalid(m_axis_2_tvalid), + .m_axis_2_tready(m_axis_2_tready), + .m_axis_2_tlast (m_axis_2_tlast), + .bytes_stored(), + .pkt_stored(), + .bytes_removed_0(), + .bytes_removed_1(), + .bytes_removed_2(), + .pkt_removed_0(), + .pkt_removed_1(), + .pkt_removed_2(), + .bytes_dropped(), + .pkt_dropped(), + + .S_AXI_AWADDR(S2_AXI_AWADDR), + .S_AXI_AWVALID(S2_AXI_AWVALID), + .S_AXI_WDATA(S2_AXI_WDATA), + .S_AXI_WSTRB(S2_AXI_WSTRB), + .S_AXI_WVALID(S2_AXI_WVALID), + .S_AXI_BREADY(S2_AXI_BREADY), + .S_AXI_ARADDR(S2_AXI_ARADDR), + .S_AXI_ARVALID(S2_AXI_ARVALID), + .S_AXI_RREADY(S2_AXI_RREADY), + .S_AXI_ARREADY(S2_AXI_ARREADY), + .S_AXI_RDATA(S2_AXI_RDATA), + .S_AXI_RRESP(S2_AXI_RRESP), + .S_AXI_RVALID(S2_AXI_RVALID), + .S_AXI_WREADY(S2_AXI_WREADY), + .S_AXI_BRESP(S2_AXI_BRESP), + .S_AXI_BVALID(S2_AXI_BVALID), + .S_AXI_AWREADY(S2_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + +endmodule diff --git a/hw/projects/reference_router/hw/hdl/top_sim.v b/hw/projects/reference_router/hw/hdl/top_sim.v new file mode 100644 index 0000000..14e47a3 --- /dev/null +++ b/hw/projects/reference_router/hw/hdl/top_sim.v @@ -0,0 +1,677 @@ +//- +// Copyright (c) 2015 Noa Zilberman, Georgina Kalogeridou +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// top_sim.v +// +// Module: +// top +// +// Author: Noa Zilberman, Georgina Kalogeridou +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ps / 100 fs + + module top_sim # ( + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter C_TUSER_WIDTH = 128, // RX/TX interface data width + parameter C_NF_DATA_WIDTH = 1024, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32 + ) ( + +//PCI Express + input [15:0] pcie_rxn, + input [15:0] pcie_rxp, + output [15:0] pcie_txn, + output [15:0] pcie_txp, + //Network Interface + input [3:0] qsfp0_rxp, + input [3:0] qsfp0_rxn, + output [3:0] qsfp0_txp, + output [3:0] qsfp0_txn, + + input [3:0] qsfp1_rxp, + input [3:0] qsfp1_rxn, + output [3:0] qsfp1_txp, + output [3:0] qsfp1_txn, + + // PCIe Clock + input pci_clk_p, + input pci_clk_n, + + //200MHz Clock + input fpga_sysclk_p, + input fpga_sysclk_n, + + // 156.25 MHz clock in + input qsfp_refclk_p, + input qsfp_refclk_n, + + input sys_reset_n +); + + //----------------------------------------------------------------------------------------------------------------// + // System(SYS) Interface // + //----------------------------------------------------------------------------------------------------------------// + + wire sys_clk; + wire clk_200_i; + wire clk_200; + wire sys_rst_n_c; + + //----------------------------------------------------------------------------------------------------------------------- + + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + wire[C_NF_DATA_WIDTH-1:0] axis_i_0_tdata , axis_o_0_tdata; + wire axis_i_0_tvalid, axis_o_0_tvalid; + wire axis_i_0_tlast , axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_0_tuser , axis_o_0_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_0_tkeep , axis_o_0_tkeep; + wire axis_i_0_tready, axis_o_0_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_i_1_tdata , axis_o_1_tdata; + wire axis_i_1_tvalid, axis_o_1_tvalid; + wire axis_i_1_tlast , axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_1_tuser , axis_o_1_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_1_tkeep , axis_o_1_tkeep; + wire axis_i_1_tready, axis_o_1_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_dma_i_tdata , axis_dma_o_tdata; + wire axis_dma_i_tvalid, axis_dma_o_tvalid; + wire axis_dma_i_tlast , axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] axis_dma_i_tuser , axis_dma_o_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_dma_i_tkeep , axis_dma_o_tkeep; + wire axis_dma_i_tready, axis_dma_o_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_0_tdata , p_axis_o_0_tdata; + wire p_axis_i_0_tvalid, p_axis_o_0_tvalid; + wire p_axis_i_0_tlast , p_axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_0_tuser , p_axis_o_0_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_0_tkeep , p_axis_o_0_tkeep; + wire p_axis_i_0_tready, p_axis_o_0_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_1_tdata , p_axis_o_1_tdata; + wire p_axis_i_1_tvalid, p_axis_o_1_tvalid; + wire p_axis_i_1_tlast , p_axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_1_tuser , p_axis_o_1_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_1_tkeep , p_axis_o_1_tkeep; + wire p_axis_i_1_tready, p_axis_o_1_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_dma_i_tdata , p_axis_dma_o_tdata; + wire p_axis_dma_i_tvalid, p_axis_dma_o_tvalid; + wire p_axis_dma_i_tlast , p_axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_dma_i_tuser , p_axis_dma_o_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_dma_i_tkeep , p_axis_dma_o_tkeep; + wire p_axis_dma_i_tready, p_axis_dma_o_tready; + //----------------------------------------------------------------------------------------------------------------// + // AXI Lite interface // + //----------------------------------------------------------------------------------------------------------------// + wire [31:0] M0_AXI_araddr , M1_AXI_araddr , M2_AXI_araddr; + wire [2:0] M0_AXI_arprot , M1_AXI_arprot , M2_AXI_arprot; + wire M0_AXI_arready, M1_AXI_arready, M2_AXI_arready; + wire M0_AXI_arvalid, M1_AXI_arvalid, M2_AXI_arvalid; + wire [31:0] M0_AXI_awaddr , M1_AXI_awaddr , M2_AXI_awaddr; + wire [2:0] M0_AXI_awprot , M1_AXI_awprot , M2_AXI_awprot; + wire M0_AXI_awready, M1_AXI_awready, M2_AXI_awready; + wire M0_AXI_awvalid, M1_AXI_awvalid, M2_AXI_awvalid; + wire M0_AXI_bready , M1_AXI_bready , M2_AXI_bready; + wire [1:0] M0_AXI_bresp , M1_AXI_bresp , M2_AXI_bresp; + wire M0_AXI_bvalid , M1_AXI_bvalid , M2_AXI_bvalid; + wire [31:0] M0_AXI_rdata , M1_AXI_rdata , M2_AXI_rdata; + wire M0_AXI_rready , M1_AXI_rready , M2_AXI_rready; + wire [1:0] M0_AXI_rresp , M1_AXI_rresp , M2_AXI_rresp; + wire M0_AXI_rvalid , M1_AXI_rvalid , M2_AXI_rvalid; + wire [31:0] M0_AXI_wdata , M1_AXI_wdata , M2_AXI_wdata; + wire M0_AXI_wready , M1_AXI_wready , M2_AXI_wready; + wire [3:0] M0_AXI_wstrb , M1_AXI_wstrb , M2_AXI_wstrb; + wire M0_AXI_wvalid , M1_AXI_wvalid , M2_AXI_wvalid; + + wire [31:0] M3_AXI_araddr , M4_AXI_araddr , M5_AXI_araddr; + wire [2:0] M3_AXI_arprot , M4_AXI_arprot , M5_AXI_arprot; + wire M3_AXI_arready, M4_AXI_arready, M5_AXI_arready; + wire M3_AXI_arvalid, M4_AXI_arvalid, M5_AXI_arvalid; + wire [31:0] M3_AXI_awaddr , M4_AXI_awaddr , M5_AXI_awaddr; + wire [2:0] M3_AXI_awprot , M4_AXI_awprot , M5_AXI_awprot; + wire M3_AXI_awready, M4_AXI_awready, M5_AXI_awready; + wire M3_AXI_awvalid, M4_AXI_awvalid, M5_AXI_awvalid; + wire M3_AXI_bready , M4_AXI_bready , M5_AXI_bready; + wire [1:0] M3_AXI_bresp , M4_AXI_bresp , M5_AXI_bresp; + wire M3_AXI_bvalid , M4_AXI_bvalid , M5_AXI_bvalid; + wire [31:0] M3_AXI_rdata , M4_AXI_rdata , M5_AXI_rdata; + wire M3_AXI_rready , M4_AXI_rready , M5_AXI_rready; + wire [1:0] M3_AXI_rresp , M4_AXI_rresp , M5_AXI_rresp; + wire M3_AXI_rvalid , M4_AXI_rvalid , M5_AXI_rvalid; + wire [31:0] M3_AXI_wdata , M4_AXI_wdata , M5_AXI_wdata; + wire M3_AXI_wready , M4_AXI_wready , M5_AXI_wready; + wire [3:0] M3_AXI_wstrb , M4_AXI_wstrb , M5_AXI_wstrb; + wire M3_AXI_wvalid , M4_AXI_wvalid , M5_AXI_wvalid; + + wire [31:0] S00_AXI_araddr; + wire [2:0] S00_AXI_arprot /*= 3'b010*/; + wire S00_AXI_arready; + wire S00_AXI_arvalid; + wire [31:0] S00_AXI_awaddr; + wire [2:0] S00_AXI_awprot /*= 3'b010*/; + wire S00_AXI_awready; + wire S00_AXI_awvalid; + wire S00_AXI_bready; + wire [1:0] S00_AXI_bresp; + wire S00_AXI_bvalid; + wire [31:0] S00_AXI_rdata; + wire S00_AXI_rready; + wire [1:0] S00_AXI_rresp; + wire S00_AXI_rvalid; + wire [31:0] S00_AXI_wdata; + wire S00_AXI_wready; + wire [3:0] S00_AXI_wstrb; + wire S00_AXI_wvalid; + + // Network Interfaces + wire axi_aresetn; + wire axi_clk; + wire [10:0] counter0,counter1,counter2,counter3,counter4; + wire activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0; + wire activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0; + wire barrier_req0, barrier_req1, barrier_req2, barrier_req3, barrier_req4; + wire barrier_proceed; + wire activity_trans_sim; + wire activity_trans_log; + wire barrier_req_trans; + + //--------------------------------------------------------------------- + // Misc + //--------------------------------------------------------------------- + IBUF sys_reset_n_ibuf ( .O(sys_rst_n_c), .I(sys_reset_n)); + + reg [15:0] sys_clk_count; + always @(posedge ~sys_clk) + sys_clk_count <= sys_clk_count + 1'b1; + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_inst ( + .O (sys_clk), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (pci_clk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (pci_clk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_core_inst ( + .O (clk_200), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (fpga_sysclk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (fpga_sysclk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + // drive AXI-lite from sys_clk & sys_rst + assign axi_clk = sys_clk; + assign axi_aresetn = sys_rst_n_c; + +//-----------------------------------------------------------------------------------------------// +// Network modules // +//-----------------------------------------------------------------------------------------------// + + nf_datapath + #( + // Master AXI Stream Data Width + .C_M_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_S_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_M_AXIS_TUSER_WIDTH (128), + .C_S_AXIS_TUSER_WIDTH (128), + .NUM_QUEUES (5) + ) + nf_datapath_0 + ( + .axis_aclk (clk_200), + .axis_resetn (sys_rst_n_c), + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + + // Slave Stream Ports (interface from Rx queues) + .s_axis_0_tdata (axis_i_0_tdata), + .s_axis_0_tkeep (axis_i_0_tkeep), + .s_axis_0_tuser (axis_i_0_tuser), + .s_axis_0_tvalid (axis_i_0_tvalid), + .s_axis_0_tready (axis_i_0_tready), + .s_axis_0_tlast (axis_i_0_tlast), + .s_axis_1_tdata (axis_i_1_tdata), + .s_axis_1_tkeep (axis_i_1_tkeep), + .s_axis_1_tuser (axis_i_1_tuser), + .s_axis_1_tvalid (axis_i_1_tvalid), + .s_axis_1_tready (axis_i_1_tready), + .s_axis_1_tlast (axis_i_1_tlast), + .s_axis_2_tdata (axis_dma_i_tdata), + .s_axis_2_tkeep (axis_dma_i_tkeep), + .s_axis_2_tuser (axis_dma_i_tuser), + .s_axis_2_tvalid (axis_dma_i_tvalid), + .s_axis_2_tready (axis_dma_i_tready), + .s_axis_2_tlast (axis_dma_i_tlast), + + + // Master Stream Ports (interface to TX queues) + .m_axis_0_tdata (axis_o_0_tdata), + .m_axis_0_tkeep (axis_o_0_tkeep), + .m_axis_0_tuser (axis_o_0_tuser), + .m_axis_0_tvalid (axis_o_0_tvalid), + .m_axis_0_tready (axis_o_0_tready), + .m_axis_0_tlast (axis_o_0_tlast), + .m_axis_1_tdata (axis_o_1_tdata), + .m_axis_1_tkeep (axis_o_1_tkeep), + .m_axis_1_tuser (axis_o_1_tuser), + .m_axis_1_tvalid (axis_o_1_tvalid), + .m_axis_1_tready (axis_o_1_tready), + .m_axis_1_tlast (axis_o_1_tlast), + .m_axis_2_tdata (axis_dma_o_tdata), + .m_axis_2_tkeep (axis_dma_o_tkeep), + .m_axis_2_tuser (axis_dma_o_tuser), + .m_axis_2_tvalid (axis_dma_o_tvalid), + .m_axis_2_tready (axis_dma_o_tready), + .m_axis_2_tlast (axis_dma_o_tlast), + + //AXI-Lite interface + .S0_AXI_AWADDR (M0_AXI_awaddr), + .S0_AXI_AWVALID (M0_AXI_awvalid), + .S0_AXI_WDATA (M0_AXI_wdata), + .S0_AXI_WSTRB (M0_AXI_wstrb), + .S0_AXI_WVALID (M0_AXI_wvalid), + .S0_AXI_BREADY (M0_AXI_bready), + .S0_AXI_ARADDR (M0_AXI_araddr), + .S0_AXI_ARVALID (M0_AXI_arvalid), + .S0_AXI_RREADY (M0_AXI_rready), + .S0_AXI_ARREADY (M0_AXI_arready), + .S0_AXI_RDATA (M0_AXI_rdata), + .S0_AXI_RRESP (M0_AXI_rresp), + .S0_AXI_RVALID (M0_AXI_rvalid), + .S0_AXI_WREADY (M0_AXI_wready), + .S0_AXI_BRESP (M0_AXI_bresp), + .S0_AXI_BVALID (M0_AXI_bvalid), + .S0_AXI_AWREADY (M0_AXI_awready), + + .S1_AXI_AWADDR (M1_AXI_awaddr), + .S1_AXI_AWVALID (M1_AXI_awvalid), + .S1_AXI_WDATA (M1_AXI_wdata), + .S1_AXI_WSTRB (M1_AXI_wstrb), + .S1_AXI_WVALID (M1_AXI_wvalid), + .S1_AXI_BREADY (M1_AXI_bready), + .S1_AXI_ARADDR (M1_AXI_araddr), + .S1_AXI_ARVALID (M1_AXI_arvalid), + .S1_AXI_RREADY (M1_AXI_rready), + .S1_AXI_ARREADY (M1_AXI_arready), + .S1_AXI_RDATA (M1_AXI_rdata), + .S1_AXI_RRESP (M1_AXI_rresp), + .S1_AXI_RVALID (M1_AXI_rvalid), + .S1_AXI_WREADY (M1_AXI_wready), + .S1_AXI_BRESP (M1_AXI_bresp), + .S1_AXI_BVALID (M1_AXI_bvalid), + .S1_AXI_AWREADY (M1_AXI_awready), + + .S2_AXI_AWADDR (M2_AXI_awaddr), + .S2_AXI_AWVALID (M2_AXI_awvalid), + .S2_AXI_WDATA (M2_AXI_wdata), + .S2_AXI_WSTRB (M2_AXI_wstrb), + .S2_AXI_WVALID (M2_AXI_wvalid), + .S2_AXI_BREADY (M2_AXI_bready), + .S2_AXI_ARADDR (M2_AXI_araddr), + .S2_AXI_ARVALID (M2_AXI_arvalid), + .S2_AXI_RREADY (M2_AXI_rready), + .S2_AXI_ARREADY (M2_AXI_arready), + .S2_AXI_RDATA (M2_AXI_rdata), + .S2_AXI_RRESP (M2_AXI_rresp), + .S2_AXI_RVALID (M2_AXI_rvalid), + .S2_AXI_WREADY (M2_AXI_wready), + .S2_AXI_BRESP (M2_AXI_bresp), + .S2_AXI_BVALID (M2_AXI_bvalid), + .S2_AXI_AWREADY (M2_AXI_awready) + ); + + axis_sim_stim_ip0 axis_sim_stim_0 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_0_tdata), + .M_AXIS_TKEEP (p_axis_i_0_tkeep), + .M_AXIS_TUSER (p_axis_i_0_tuser), + .M_AXIS_TVALID (p_axis_i_0_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_0_tlast), + + .counter (counter0), + .activity_stim (activity_stim0), + .barrier_req (barrier_req0), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip1 axis_sim_stim_1 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_1_tdata), + .M_AXIS_TKEEP (p_axis_i_1_tkeep), + .M_AXIS_TUSER (p_axis_i_1_tuser), + .M_AXIS_TVALID (p_axis_i_1_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_1_tlast), + + .counter (counter1), + .activity_stim (activity_stim1), + .barrier_req (barrier_req1), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip2 axis_sim_stim_2 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_dma_i_tdata), + .M_AXIS_TKEEP (p_axis_dma_i_tkeep), + .M_AXIS_TUSER (p_axis_dma_i_tuser), + .M_AXIS_TVALID (p_axis_dma_i_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_dma_i_tlast), + + .counter (counter4), + .activity_stim (activity_stim4), + .barrier_req (barrier_req4), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_record_ip0 axis_sim_record_0 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_0_tdata), + .s_axis_tkeep (p_axis_o_0_tkeep), + .s_axis_tuser (p_axis_o_0_tuser), + .s_axis_tvalid(p_axis_o_0_tvalid), + .s_axis_tready(p_axis_o_0_tready), + .s_axis_tlast (p_axis_o_0_tlast), + + .counter (counter0), + .activity_rec(activity_rec0) + ); + + axis_sim_record_ip1 axis_sim_record_1 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_1_tdata), + .s_axis_tkeep (p_axis_o_1_tkeep), + .s_axis_tuser (p_axis_o_1_tuser), + .s_axis_tvalid(p_axis_o_1_tvalid), + .s_axis_tready(p_axis_o_1_tready), + .s_axis_tlast (p_axis_o_1_tlast), + + .counter (counter1), + .activity_rec(activity_rec1) + ); + + axis_sim_record_ip2 axis_sim_record_2 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_dma_o_tdata), + .s_axis_tkeep (p_axis_dma_o_tkeep), + .s_axis_tuser (p_axis_dma_o_tuser), + .s_axis_tvalid(p_axis_dma_o_tvalid), + .s_axis_tready(p_axis_dma_o_tready), + .s_axis_tlast (p_axis_dma_o_tlast), + + .counter (counter4), + .activity_rec(activity_rec4) + ); + + nf_mac_attachment_dma_ip u_nf_attachment_dma ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_dma_i_tdata), + .m_axis_mac_tkeep (p_axis_dma_i_tkeep), + .m_axis_mac_tvalid (p_axis_dma_i_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_dma_i_tuser), + .m_axis_mac_tlast (p_axis_dma_i_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_dma_o_tdata), + .s_axis_mac_tkeep (p_axis_dma_o_tkeep), + .s_axis_mac_tvalid (p_axis_dma_o_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_dma_o_tuser), + .s_axis_mac_tlast (p_axis_dma_o_tlast), + .s_axis_mac_tready (p_axis_dma_o_tready), + + // TX/RX DATA channels + .interface_number (8'd0), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_dma_o_tdata), + .s_axis_pipe_tkeep (axis_dma_o_tkeep), + .s_axis_pipe_tlast (axis_dma_o_tlast), + .s_axis_pipe_tuser (axis_dma_o_tuser), + .s_axis_pipe_tvalid (axis_dma_o_tvalid), + .s_axis_pipe_tready (axis_dma_o_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_dma_i_tdata), + .m_axis_pipe_tkeep (axis_dma_i_tkeep), + .m_axis_pipe_tlast (axis_dma_i_tlast), + .m_axis_pipe_tuser (axis_dma_i_tuser), + .m_axis_pipe_tvalid (axis_dma_i_tvalid), + .m_axis_pipe_tready (axis_dma_i_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_0 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_0_tdata), + .m_axis_mac_tkeep (p_axis_i_0_tkeep), + .m_axis_mac_tvalid (p_axis_i_0_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_0_tuser), + .m_axis_mac_tlast (p_axis_i_0_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_0_tdata), + .s_axis_mac_tkeep (p_axis_o_0_tkeep), + .s_axis_mac_tvalid (p_axis_o_0_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_o_0_tuser), + .s_axis_mac_tlast (p_axis_o_0_tlast), + .s_axis_mac_tready (p_axis_o_0_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0001), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_0_tdata), + .s_axis_pipe_tkeep (axis_o_0_tkeep), + .s_axis_pipe_tlast (axis_o_0_tlast), + .s_axis_pipe_tuser (axis_o_0_tuser), + .s_axis_pipe_tvalid (axis_o_0_tvalid), + .s_axis_pipe_tready (axis_o_0_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_0_tdata), + .m_axis_pipe_tkeep (axis_i_0_tkeep), + .m_axis_pipe_tlast (axis_i_0_tlast), + .m_axis_pipe_tuser (axis_i_0_tuser), + .m_axis_pipe_tvalid (axis_i_0_tvalid), + .m_axis_pipe_tready (axis_i_0_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_1 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_1_tdata), + .m_axis_mac_tkeep (p_axis_i_1_tkeep), + .m_axis_mac_tvalid (p_axis_i_1_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_1_tuser), + .m_axis_mac_tlast (p_axis_i_1_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_1_tdata), + .s_axis_mac_tkeep (p_axis_o_1_tkeep), + .s_axis_mac_tvalid (p_axis_o_1_tvalid), + .s_axis_mac_tuser_err (p_axis_o_1_tuser), //underrun + .s_axis_mac_tuser (p_axis_o_1_tuser), + .s_axis_mac_tlast (p_axis_o_1_tlast), + .s_axis_mac_tready (p_axis_o_1_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0100), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_1_tdata), + .s_axis_pipe_tkeep (axis_o_1_tkeep), + .s_axis_pipe_tlast (axis_o_1_tlast), + .s_axis_pipe_tuser (axis_o_1_tuser), + .s_axis_pipe_tvalid (axis_o_1_tvalid), + .s_axis_pipe_tready (axis_o_1_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_1_tdata), + .m_axis_pipe_tkeep (axis_i_1_tkeep), + .m_axis_pipe_tlast (axis_i_1_tlast), + .m_axis_pipe_tuser (axis_i_1_tuser), + .m_axis_pipe_tvalid (axis_i_1_tvalid), + .m_axis_pipe_tready (axis_i_1_tready) + ); + + axi_crossbar_0 u_interconnect( + .aclk (axi_clk), + .aresetn (axi_aresetn), + .s_axi_awaddr (S00_AXI_awaddr), + .s_axi_awprot (3'b010), + .s_axi_awvalid (S00_AXI_awvalid), + .s_axi_awready (S00_AXI_awready), + .s_axi_wdata (S00_AXI_wdata ), + .s_axi_wstrb (4'hf), + .s_axi_wvalid (S00_AXI_wvalid ), + .s_axi_wready (S00_AXI_wready ), + .s_axi_bresp (S00_AXI_bresp ), + .s_axi_bvalid (S00_AXI_bvalid ), + .s_axi_bready (S00_AXI_bready ), + .s_axi_araddr (S00_AXI_araddr[31:0]), + .s_axi_arprot (3'b010), + .s_axi_arvalid (S00_AXI_arvalid ), + .s_axi_arready (S00_AXI_arready ), + .s_axi_rdata (S00_AXI_rdata ), + .s_axi_rresp (S00_AXI_rresp ), + .s_axi_rvalid (S00_AXI_rvalid ), + .s_axi_rready (S00_AXI_rready ), + .m_axi_awaddr ({M2_AXI_awaddr[31:0] ,M1_AXI_awaddr[31:0] ,M0_AXI_awaddr[31:0] }), + .m_axi_awprot (), + .m_axi_awvalid ({M2_AXI_awvalid,M1_AXI_awvalid,M0_AXI_awvalid}), + .m_axi_awready ({M2_AXI_awready,M1_AXI_awready,M0_AXI_awready}), + .m_axi_wdata ({M2_AXI_wdata ,M1_AXI_wdata ,M0_AXI_wdata }), + .m_axi_wstrb ({M2_AXI_wstrb ,M1_AXI_wstrb ,M0_AXI_wstrb }), + .m_axi_wvalid ({M2_AXI_wvalid ,M1_AXI_wvalid ,M0_AXI_wvalid }), + .m_axi_wready ({M2_AXI_wready ,M1_AXI_wready ,M0_AXI_wready }), + .m_axi_bresp ({M2_AXI_bresp ,M1_AXI_bresp ,M0_AXI_bresp }), + .m_axi_bvalid ({M2_AXI_bvalid ,M1_AXI_bvalid ,M0_AXI_bvalid }), + .m_axi_bready ({M2_AXI_bready ,M1_AXI_bready ,M0_AXI_bready }), + .m_axi_araddr ({M2_AXI_araddr ,M1_AXI_araddr ,M0_AXI_araddr }), + .m_axi_arprot (), + .m_axi_arvalid ({M2_AXI_arvalid,M1_AXI_arvalid,M0_AXI_arvalid}), + .m_axi_arready ({M2_AXI_arready,M1_AXI_arready,M0_AXI_arready}), + .m_axi_rdata ({M2_AXI_rdata ,M1_AXI_rdata ,M0_AXI_rdata }), + .m_axi_rresp ({M2_AXI_rresp ,M1_AXI_rresp ,M0_AXI_rresp }), + .m_axi_rvalid ({M2_AXI_rvalid ,M1_AXI_rvalid ,M0_AXI_rvalid }), + .m_axi_rready ({M2_AXI_rready ,M1_AXI_rready ,M0_AXI_rready }) + ); + + + axi_sim_transactor_ip axi_sim_transactor_i ( + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + //AXI Write address channel + .M_AXI_AWADDR (S00_AXI_awaddr), + .M_AXI_AWVALID (S00_AXI_awvalid), + .M_AXI_AWREADY (S00_AXI_awready), + // AXI Write data channel + .M_AXI_WDATA (S00_AXI_wdata), + .M_AXI_WSTRB (S00_AXI_wstrb), + .M_AXI_WVALID (S00_AXI_wvalid), + .M_AXI_WREADY (S00_AXI_wready), + //AXI Write response channel + .M_AXI_BRESP (S00_AXI_bresp), + .M_AXI_BVALID (S00_AXI_bvalid), + .M_AXI_BREADY (S00_AXI_bready), + //AXI Read address channel + .M_AXI_ARADDR (S00_AXI_araddr), + .M_AXI_ARVALID (S00_AXI_arvalid), + .M_AXI_ARREADY (S00_AXI_arready), + //AXI Read data & response channel + .M_AXI_RDATA (S00_AXI_rdata), + .M_AXI_RRESP (S00_AXI_rresp), + .M_AXI_RVALID (S00_AXI_rvalid), + .M_AXI_RREADY (S00_AXI_rready), + + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + + barrier_ip barrier_i ( + .activity_stim ({activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0}), + .activity_rec ({activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0}), + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req ({barrier_req4, barrier_req3, barrier_req2, barrier_req1, barrier_req0}), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + +endmodule + diff --git a/hw/projects/reference_router/hw/hdl/top_tb.v b/hw/projects/reference_router/hw/hdl/top_tb.v new file mode 100644 index 0000000..8d062fe --- /dev/null +++ b/hw/projects/reference_router/hw/hdl/top_tb.v @@ -0,0 +1,180 @@ +//- +// Copyright (c) 2015 Noa Zilberman +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// File: +// top_tb.v +// +// Module: +// top +// +// Author: Noa Zilberman +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ns / 100ps + + module top_tb # ( + parameter PL_SIM_FAST_LINK_TRAINING = "TRUE", // Simulation Speedup + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32, + parameter integer USER_CLK2_FREQ = 4, + parameter REF_CLK_FREQ = 0, // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz + parameter AXISTEN_IF_RQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_RC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_ENABLE_CLIENT_TAG = 0, + parameter AXISTEN_IF_RQ_PARITY_CHECK = 0, + parameter AXISTEN_IF_CC_PARITY_CHECK = 0, + parameter AXISTEN_IF_MC_RX_STRADDLE = 0, + parameter AXISTEN_IF_ENABLE_RX_MSG_INTFC = 0, + parameter [17:0] AXISTEN_IF_ENABLE_MSG_ROUTE = 18'h2FFFF +) ( + +); + + parameter PCIE_PERIOD = 4.0; + parameter XPHY_PERIOD = 6.4; + parameter real CORE_PERIOD = 2.941; + + localparam TCQ = 1; + localparam BAR0AXI = 32'h40000000; + localparam BAR1AXI = 32'h10000000; + localparam BAR2AXI = 32'h20000000; + localparam BAR3AXI = 32'h30000000; + localparam BAR4AXI = 32'h40000000; + localparam BAR5AXI = 32'h50000000; + localparam BAR0SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR1SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR2SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR3SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR4SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR5SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam throttle_percent = 50; + + reg sys_reset_n; + + reg sys_clk; + wire sys_clkp,sys_clkn; + reg xphy_clk; + wire xphy_refclk_p,xphy_refclk_n; + reg clk_ref; + wire clk_ref_p,clk_ref_n; + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + + + top_sim # ( + .PL_SIM_FAST_LINK_TRAINING (PL_SIM_FAST_LINK_TRAINING ), + .C_DATA_WIDTH (C_DATA_WIDTH ), + .KEEP_WIDTH (KEEP_WIDTH ), + .USER_CLK2_FREQ (USER_CLK2_FREQ ), + .REF_CLK_FREQ (REF_CLK_FREQ ), + .AXISTEN_IF_RQ_ALIGNMENT_MODE (AXISTEN_IF_RQ_ALIGNMENT_MODE ), + .AXISTEN_IF_CC_ALIGNMENT_MODE (AXISTEN_IF_CC_ALIGNMENT_MODE ), + .AXISTEN_IF_CQ_ALIGNMENT_MODE (AXISTEN_IF_CQ_ALIGNMENT_MODE ), + .AXISTEN_IF_RC_ALIGNMENT_MODE (AXISTEN_IF_RC_ALIGNMENT_MODE ), + .AXISTEN_IF_ENABLE_CLIENT_TAG (AXISTEN_IF_ENABLE_CLIENT_TAG ), + .AXISTEN_IF_RQ_PARITY_CHECK (AXISTEN_IF_RQ_PARITY_CHECK ), + .AXISTEN_IF_CC_PARITY_CHECK (AXISTEN_IF_CC_PARITY_CHECK ), + .AXISTEN_IF_MC_RX_STRADDLE (AXISTEN_IF_MC_RX_STRADDLE ), + .AXISTEN_IF_ENABLE_RX_MSG_INTFC (AXISTEN_IF_ENABLE_RX_MSG_INTFC ), + .AXISTEN_IF_ENABLE_MSG_ROUTE (AXISTEN_IF_ENABLE_MSG_ROUTE ) + ) top_sim ( + + //PCI Express + .pcie_rxn(pcie_7x_mgt_rxn), + .pcie_rxp(pcie_7x_mgt_rxp), + .pcie_txn(pcie_7x_mgt_txn), + .pcie_txp(pcie_7x_mgt_txp), + //10G Interface + + .qsfp0_rxp(rxp), + .qsfp0_rxn(rxn), + .qsfp0_txp(txp), + .qsfp0_txn(txn), + + // PCIe Clock + .pci_clk_p(sys_clkp), + .pci_clk_n(sys_clkn), + + //200MHz Clock + .fpga_sysclk_p(clk_ref_p), + .fpga_sysclk_n(clk_ref_n), + + // 156.25 MHz clock in + .qsfp_refclk_p (xphy_refclk_p), + .qsfp_refclk_n (xphy_refclk_n), + + .sys_reset_n(sys_reset_n) + ); + +//Reset handling + // Important! polarity here is opposite the one in the actual design + initial begin + sys_reset_n = 1'b0; + #(CORE_PERIOD * 200); + sys_reset_n = 1'b1; + $display("Reset Deasserted"); + end + +//Clock generation + initial begin + sys_clk = 1'b0; + #(PCIE_PERIOD/2); + forever + #(PCIE_PERIOD/2) sys_clk = ~sys_clk; + end + + assign sys_clkp = sys_clk; + assign sys_clkn = ~sys_clk; + + + initial begin + xphy_clk = 1'b0; + #(XPHY_PERIOD/2); + forever + #(XPHY_PERIOD/2) xphy_clk = ~xphy_clk; + end + + assign xphy_refclk_p = xphy_clk; + assign xphy_refclk_n = ~xphy_clk; + + initial begin + clk_ref = 1'b0; + #(CORE_PERIOD/2); + forever + #(CORE_PERIOD/2) clk_ref = ~clk_ref; +end + +assign clk_ref_p = clk_ref; +assign clk_ref_n = ~clk_ref; + +endmodule diff --git a/hw/projects/reference_router/hw/tcl/export_registers.tcl b/hw/projects/reference_router/hw/tcl/export_registers.tcl new file mode 100644 index 0000000..d2cdd74 --- /dev/null +++ b/hw/projects/reference_router/hw/tcl/export_registers.tcl @@ -0,0 +1,156 @@ +# +# Copyright (c) 2015 Noa Zilberman, Jingyun Zhang +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# The following list include all the items that are mapped to memory segments +# The structure of each item is as follows { } + +set DEF_LIST { + {INPUT_ARBITER 0 1 input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt} \ + {OUTPUT_QUEUES 0 1 output_queues_v1_0_0/data/output_queues_regs_defines.txt} \ + {OUTPUT_PORT_LOOKUP 0 1 router_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt } \ +} + +set target_path $::env(NF_DESIGN_DIR)/test +set target_file $target_path/nf_register_defines.h + +if {[file exists ${target_path}] == 0} { + exec mkdir -p ${target_path} +} + +###################################################### +# the following function writes the license header +# into the file +###################################################### + +proc write_header { target_file } { + +# creat a blank header file +# do a fresh rewrite in case the file already exits +file delete -force $target_file +open $target_file "w" +set h_file [open $target_file "w"] + + +puts $h_file "//-" +puts $h_file "// Copyright (c) 2015,2021 University of Cambridge" +puts $h_file "// All rights reserved." +puts $h_file "//" +puts $h_file "// This software was developed by Stanford University and the University of Cambridge Computer Laboratory " +puts $h_file "// under National Science Foundation under Grant No. CNS-0855268," +puts $h_file "// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and" +puts $h_file "// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 (\"MRC2\"), " +puts $h_file "// as part of the DARPA MRC research programme," +puts $h_file "// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project" +puts $h_file "// EP/P025374/1 alongside support from Xilinx Inc." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_START@" +puts $h_file "//" +puts $h_file "// Licensed to NetFPGA C.I.C. (NetFPGA) under one or more contributor" +puts $h_file "// license agreements. See the NOTICE file distributed with this work for" +puts $h_file "// additional information regarding copyright ownership. NetFPGA licenses this" +puts $h_file "// file to you under the NetFPGA Hardware-Software License, Version 1.0 (the" +puts $h_file "// \"License\"); you may not use this file except in compliance with the" +puts $h_file "// License. You may obtain a copy of the License at:" +puts $h_file "//" +puts $h_file "// http://www.netfpga-cic.org" +puts $h_file "//" +puts $h_file "// Unless required by applicable law or agreed to in writing, Work distributed" +puts $h_file "// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR" +puts $h_file "// CONDITIONS OF ANY KIND, either express or implied. See the License for the" +puts $h_file "// specific language governing permissions and limitations under the License." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_END@" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "// This is an automatically generated header definitions file" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "" + +close $h_file + +}; # end of proc write_header + + +###################################################### +# the following function writes all the information +# of a specific core into a file +###################################################### + +proc write_core {target_file prefix id has_registers lib_name} { + + +set h_file [open $target_file "a"] + +#First, read the memory map information from the reference_project defines file +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ + + +set baseaddr [set $prefix\_BASEADDR] +set highaddr [set $prefix\_HIGHADDR] +set sizeaddr [set $prefix\_SIZEADDR] + +puts $h_file "//######################################################" +puts $h_file "//# Definitions for $prefix" +puts $h_file "//######################################################" + +puts $h_file "#define NFPLUS_$prefix\_BASEADDR $baseaddr" +puts $h_file "#define NFPLUS_$prefix\_HIGHADDR $highaddr" +puts $h_file "#define NFPLUS_$prefix\_SIZEADDR $sizeaddr" +puts $h_file "" + +#Second, read the registers information from the library defines file +if $has_registers { + set lib_path "$public_repo_dir/std/$lib_name" + set regs_h_define_file $lib_path + set regs_h_define_file_read [open $regs_h_define_file r] + set regs_h_define_file_data [read $regs_h_define_file_read] + close $regs_h_define_file_read + set regs_h_define_file_data_line [split $regs_h_define_file_data "\n"] + + foreach read_line $regs_h_define_file_data_line { + if {[regexp "#define" $read_line]} { + puts $h_file "#define NFPLUS_[lindex $read_line 2]\_$id\_[lindex $read_line 3]\_[lindex $read_line 4] [lindex $read_line 5]" + } + } +} +puts $h_file "" +close $h_file +}; # end of proc write_core + +###################################################### +# the main function +###################################################### +# +write_header $target_file + +foreach lib_item $DEF_LIST { + write_core $target_file [lindex $lib_item 0] [lindex $lib_item 1] [lindex $lib_item 2] [lindex $lib_item 3] +} + diff --git a/hw/projects/reference_router/hw/tcl/reference_router.tcl b/hw/projects/reference_router/hw/tcl/reference_router.tcl new file mode 100644 index 0000000..94a7a59 --- /dev/null +++ b/hw/projects/reference_router/hw/tcl/reference_router.tcl @@ -0,0 +1,382 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib +set repo_dir ./ip_repo +set project_constraints "${public_repo_dir}/common/constraints/${board_name}_general.xdc" + +set start_time [exec date +%s] +set_param general.maxThreads 8 +set_param synth.elaboration.rodinMoreOptions "rt::set_parameter max_loop_limit 200000" +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +set datapath_freq_mhz 340 +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +if {[string match $board_name "au280"]} { + set_property verilog_define { {BOARD_AU280} {au280} {__synthesis__} } [current_fileset] + set board_param "AU280" +} elseif {[string match $board_name "au250"]} { + set_property verilog_define { {BOARD_AU250} {__synthesis__} } [current_fileset] + set board_param "AU250" +} elseif {[string match $board_name "au200"]} { + set_property verilog_define { {BOARD_AU200} {__synthesis__} } [current_fileset] + set board_param "AU200" +} elseif {[string match $board_name "vcu1525"]} { + set_property verilog_define { {BOARD_VCU1525} {__synthesis__} } [current_fileset] + set board_param "VCU1525" +} +set_property generic "C_NF_DATA_WIDTH=${datapath_width_bit} BOARD=\"${board_param}\"" [current_fileset] + +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] +##################################### +# Project Constraints +##################################### +add_files -fileset constraints -norecurse ${project_constraints} +if {[string match $board_name "au280"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au280_timing.tcl +} elseif {[string match $board_name "au200"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au200_vcu1525_user_timing.tcl +} elseif {[string match $board_name "vcu1525"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au200_vcu1525_user_timing.tcl +} else { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au250_timing.tcl +} +set_property is_enabled true [get_files ${project_constraints}] +set_property constrset constraints [get_runs synth_1] +set_property constrset constraints [get_runs impl_1] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name router_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name router_output_port_lookup_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips router_output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips router_output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files router_output_port_lookup_ip.xci] +reset_target all [get_ips router_output_port_lookup_ip] +generate_target all [get_ips router_output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] +# endianess_manager +create_ip -name nf_endianess_manager -vendor NetFPGA -library NetFPGA -module_name nf_endianess_manager_ip +set_property CONFIG.C_M_AXIS_TDATA_WIDTH ${datapath_width_bit} [get_ips nf_endianess_manager_ip] +set_property CONFIG.C_S_AXIS_TDATA_WIDTH ${datapath_width_bit} [get_ips nf_endianess_manager_ip] +set_property generate_synth_checkpoint false [get_files nf_endianess_manager_ip.xci] +reset_target all [get_ips nf_endianess_manager_ip] +generate_target all [get_ips nf_endianess_manager_ip] + +create_ip -name xilinx_shell -vendor xilinx -library xilinx -module_name xilinx_shell_ip +set_property CONFIG.MAX_PKT_LEN 1518 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_QUEUE 2048 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_PHYS_FUNC 2 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_CMAC_PORT 2 [get_ips xilinx_shell_ip] +set_property generate_synth_checkpoint false [get_files xilinx_shell_ip.xci] +reset_target all [get_ips xilinx_shell_ip] +generate_target all [get_ips xilinx_shell_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000000000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000020000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + +#Add a clock wizard +create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name clk_wiz_1 +if {[string match "${datapath_freq_mhz}" "200"]} { +#200MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {6.000} \ + CONFIG.CLKOUT1_JITTER {119.392} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "250"]} { +#250MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {250.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {1} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {4.750} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.750} \ + CONFIG.CLKOUT1_JITTER {85.152} \ + CONFIG.CLKOUT1_PHASE_ERROR {78.266}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "260"]} { +#260MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {260.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {120.250} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.625} \ + CONFIG.CLKOUT1_JITTER {182.359} \ + CONFIG.CLKOUT1_PHASE_ERROR {351.991}] [get_ips clk_wiz_10] +} elseif {[string match "${datapath_freq_mhz}" "280"]} { +#280MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {280.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {119.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.250} \ + CONFIG.CLKOUT1_JITTER {183.720} \ + CONFIG.CLKOUT1_PHASE_ERROR {357.524}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "300"]} { +#300MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {300.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.000} \ + CONFIG.CLKOUT1_JITTER {111.430} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "320"]} { +#320MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {320.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.750} \ + CONFIG.CLKOUT1_JITTER {110.215} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "340"]} { +#340MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {340.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {119.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.500} \ + CONFIG.CLKOUT1_JITTER {179.007} \ + CONFIG.CLKOUT1_PHASE_ERROR {357.524}] [get_ips clk_wiz_1] +} else { + puts "Error: the specified clock is error" + exit -1 +} +set_property generate_synth_checkpoint false [get_files clk_wiz_1.xci] +reset_target all [get_ips clk_wiz_1] +generate_target all [get_ips clk_wiz_1] + +read_verilog "./hdl/nf_datapath.v" +read_verilog -sv "${public_repo_dir}/common/hdl/top_wrapper.sv" +read_verilog -sv "${public_repo_dir}/common/hdl/nf_attachment.sv" +read_verilog "${public_repo_dir}/common/hdl/top.v" + +#Setting Synthesis options +create_run -flow {Vivado Synthesis 2020} synth +set_property write_incremental_synth_checkpoint true [get_runs synth_1] +set_property AUTO_INCREMENTAL_CHECKPOINT 1 [get_runs synth_1] +#Setting Implementation options +create_run impl -parent_run synth -flow {Vivado Implementation 2020} +set_property strategy Performance_Explore [get_runs impl_1] +set_property steps.phys_opt_design.is_enabled true [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AlternateFlowWithRetiming [get_runs impl_1] +set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE ExploreWithHoldFix [get_runs impl_1] +set_property STEPS.PLACE_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.is_enabled true [get_runs impl_1] + +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +# The following implementation options will increase runtime, but get the best timing results +set_property SEVERITY {Warning} [get_drc_checks UCIO-1] +launch_runs synth +wait_on_run synth +launch_runs impl_1 +wait_on_run impl_1 +open_checkpoint project/${design}.runs/impl_1/top_postroute_physopt.dcp +if {![file exists "../bitfiles"]} { + file mkdir "../bitfiles" +} +write_bitstream -force ../bitfiles/${design}_${board_name}.bit +#write_debug_probes -file ${design}.ltx -force + +# -- For Report -- +set end_time [exec date +%s] +set elapsed_time [expr ${end_time} - ${start_time}] +if {[catch {exec grep -A 4 "VIOLAT" project/${design}.runs/impl_1/top_timing_summary_postroute_physopted.rpt} timing_report_data]} { + set timing_report "Met" + set timing_report_data "" +} else { + set timing_report "VIOLATED" +} +puts " --- Report : ${design} for ${board_name} --- " +puts " Synth time : ${elapsed_time}" +puts " Timing Closure: ${timing_report}" +puts "${timing_report_data}" + +exit + diff --git a/hw/projects/reference_router/hw/tcl/reference_router_defines.tcl b/hw/projects/reference_router/hw/tcl/reference_router_defines.tcl new file mode 100644 index 0000000..5461aca --- /dev/null +++ b/hw/projects/reference_router/hw/tcl/reference_router_defines.tcl @@ -0,0 +1,82 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + + +####################### +# Segments Assignment # +####################### +#M00 +set M00_BASEADDR 0x00010000 +set M00_HIGHADDR 0x00010FFF +set M00_SIZEADDR 0x1000 + +#M01 +set M01_BASEADDR 0x00020000 +set M01_HIGHADDR 0x00020FFF +set M01_SIZEADDR 0x1000 + +#M02 +set M02_BASEADDR 0x00030000 +set M02_HIGHADDR 0x00030FFF +set M02_SIZEADDR 0x1000 + +##M03 +#set M03_BASEADDR 0x44030000 +#set M03_HIGHADDR 0x44030FFF +#set M03_SIZEADDR 0x1000 +# + +####################### +# IP_ASSIGNMENT # +####################### +# Note that physical connectivity must match this mapping + +##IDENTIFIER base address and size +#set IDENTIFIER_BASEADDR $M00_BASEADDR +#set IDENTIFIER_HIGHADDR $M00_HIGHADDR +#set IDENTIFIER_SIZEADDR $M00_SIZEADDR + + +#INPUT ARBITER base address and size +set INPUT_ARBITER_BASEADDR $M00_BASEADDR +set INPUT_ARBITER_HIGHADDR $M00_HIGHADDR +set INPUT_ARBITER_SIZEADDR $M00_SIZEADDR + +#OUTPUT_QUEUES base address and size +set OUTPUT_QUEUES_BASEADDR $M02_BASEADDR +set OUTPUT_QUEUES_HIGHADDR $M02_HIGHADDR +set OUTPUT_QUEUES_SIZEADDR $M02_SIZEADDR + +#OUPUT_PORT_LOOKUP base address and size +set OUTPUT_PORT_LOOKUP_BASEADDR $M01_BASEADDR +set OUTPUT_PORT_LOOKUP_HIGHADDR $M01_HIGHADDR +set OUTPUT_PORT_LOOKUP_SIZEADDR $M01_SIZEADDR + diff --git a/hw/projects/reference_router/hw/tcl/reference_router_sim.tcl b/hw/projects/reference_router/hw/tcl/reference_router_sim.tcl new file mode 100644 index 0000000..25c929b --- /dev/null +++ b/hw/projects/reference_router/hw/tcl/reference_router_sim.tcl @@ -0,0 +1,264 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top_sim +set sim_top top_tb +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) + +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ +set repo_dir ./ip_repo +set project_constraints ./constraints/${board_name}_switch.xdc + +set test_name [lindex $argv 0] +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl + +set_param general.maxThreads 8 +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name router_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name router_output_port_lookup_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips router_output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips router_output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files router_output_port_lookup_ip.xci] +reset_target all [get_ips router_output_port_lookup_ip] +generate_target all [get_ips router_output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] +# Endianess +create_ip -name nf_endianess_manager -vendor NetFPGA -library NetFPGA -module_name nf_endianess_manager_ip +set_property CONFIG.C_M_AXIS_TDATA_WIDTH ${datapath_width_bit} [get_ips nf_endianess_manager_ip] +set_property CONFIG.C_S_AXIS_TDATA_WIDTH ${datapath_width_bit} [get_ips nf_endianess_manager_ip] +set_property generate_synth_checkpoint false [get_files nf_endianess_manager_ip.xci] +reset_target all [get_ips nf_endianess_manager_ip] +generate_target all [get_ips nf_endianess_manager_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] + +create_ip -name barrier -vendor NetFPGA -library NetFPGA -module_name barrier_ip +reset_target all [get_ips barrier_ip] +generate_target all [get_ips barrier_ip] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip0 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_0_log.axi] [get_ips axis_sim_record_ip0] +reset_target all [get_ips axis_sim_record_ip0] +generate_target all [get_ips axis_sim_record_ip0] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip1 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_1_log.axi] [get_ips axis_sim_record_ip1] +reset_target all [get_ips axis_sim_record_ip1] +generate_target all [get_ips axis_sim_record_ip1] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip2 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/dma_0_log.axi] [get_ips axis_sim_record_ip2] +reset_target all [get_ips axis_sim_record_ip2] +generate_target all [get_ips axis_sim_record_ip2] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip0 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_0_stim.axi] [get_ips axis_sim_stim_ip0] +generate_target all [get_ips axis_sim_stim_ip0] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip1 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_1_stim.axi] [get_ips axis_sim_stim_ip1] +generate_target all [get_ips axis_sim_stim_ip1] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip2 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/dma_0_stim.axi] [get_ips axis_sim_stim_ip2] +generate_target all [get_ips axis_sim_stim_ip2] + +create_ip -name axi_sim_transactor -vendor NetFPGA -library NetFPGA -module_name axi_sim_transactor_ip +set_property -dict [list CONFIG.STIM_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.axi CONFIG.EXPECT_FILE $::env(NF_DESIGN_DIR)/test/reg_expect.axi CONFIG.LOG_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.log] [get_ips axi_sim_transactor_ip] +reset_target all [get_ips axi_sim_transactor_ip] +generate_target all [get_ips axi_sim_transactor_ip] + + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000020000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000030000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + +#create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name clk_wiz_ip +#set_property -dict [list CONFIG.PRIM_IN_FREQ {200.00} CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200.000} CONFIG.USE_SAFE_CLOCK_STARTUP {true} CONFIG.RESET_TYPE {ACTIVE_LOW} CONFIG.CLKIN1_JITTER_PS {50.0} CONFIG.CLKOUT1_DRIVES {BUFGCE} CONFIG.CLKOUT2_DRIVES {BUFGCE} CONFIG.CLKOUT3_DRIVES {BUFGCE} CONFIG.CLKOUT4_DRIVES {BUFGCE} CONFIG.CLKOUT5_DRIVES {BUFGCE} CONFIG.CLKOUT6_DRIVES {BUFGCE} CONFIG.CLKOUT7_DRIVES {BUFGCE} CONFIG.MMCM_CLKFBOUT_MULT_F {5.000} CONFIG.MMCM_CLKIN1_PERIOD {5.0} CONFIG.MMCM_CLKOUT0_DIVIDE_F {5.000} CONFIG.RESET_PORT {resetn} CONFIG.CLKOUT1_JITTER {98.146} CONFIG.CLKOUT1_PHASE_ERROR {89.971}] [get_ips clk_wiz_ip] +#set_property generate_synth_checkpoint false [get_files clk_wiz_ip.xci] +#reset_target all [get_ips clk_wiz_ip] +#generate_target all [get_ips clk_wiz_ip] + + +#read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/axi_clocking.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/nf_datapath.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_sim.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_tb.v" + + +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 + +set_property top ${sim_top} [get_filesets sim_1] +set_property include_dirs ${proj_dir} [get_filesets sim_1] +set_property simulator_language Mixed [current_project] +set_property verilog_define { {SIMULATION=1} } [get_filesets sim_1] +set_property -name xsim.more_options -value {-testplusarg TESTNAME=basic_test} -objects [get_filesets sim_1] +set_property runtime {} [get_filesets sim_1] +set_property target_simulator xsim [current_project] +set_property compxlib.compiled_library_dir {} [current_project] +set_property top_lib xil_defaultlib [get_filesets sim_1] +update_compile_order -fileset sim_1 + +unset env(PYTHONPATH) +unset env(PYTHONHOME) +set env(PYTHONPATH) ".:$::env(NFPLUS_FOLDER)/tools/scripts/:$::env(NFPLUS_FOLDER)/tools/scripts/NFTest:$::env(NFPLUS_FOLDER)/hw/projects/reference_router/lib" +set output [exec $::env(PYTHON_BNRY) $::env(NF_DESIGN_DIR)/test/${test_name}/run.py] +puts $output + +launch_simulation -simset sim_1 -mode behavioral +run 60us + diff --git a/hw/projects/reference_router/lib/Python/RegressRouterLib.py b/hw/projects/reference_router/lib/Python/RegressRouterLib.py new file mode 100755 index 0000000..c009712 --- /dev/null +++ b/hw/projects/reference_router/lib/Python/RegressRouterLib.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +from RouterLib import * + +import re + +import sys +import os + +################################################################ +# Name: nftest_set_router_MAC +# +# Sets the MAC of a port +# +# Arguments: ifaceName string +# MAC string in format xx:xx:xx:xx:xx:xx +# +# Return: +################################################################ +def nftest_set_router_MAC(ifaceName, MAC): + if not ifaceName.startswith('nf'): + print("Interface has to be an nf2cX interface") + sys.exit(1) + portNum = int(ifaceName[2:3]) + portNum += 1 + set_router_MAC(portNum, MAC) + +################################################################ +# Name: nftest_get_router_MAC +# +# Gets the MAC of a port +# +# Arguments: ifaceName string +# +# Return: MAC address of interface in xx:xx:xx:xx:xx:xx format +################################################################ +def nftest_get_router_MAC(ifaceName): + if not ifaceName.startswith('nf'): + print("Interface has to be an nf2cX interface") + sys.exit(1) + portNum = int(ifaceName[2:3]) + portNum += 1 + return get_router_MAC(portNum) + +################################################################ +# Name: nftest_add_LPM_table_entry +# +# Adds an entry to the routing table in the hardware. +# +# Arguments: entryIndex int +# subnetIP string in format w.x.y.z +# subnetMask string in format w.x.y.z +# nextHopIP string in format w.x.y.z +# outputPort one-hot-encoded ports +# 0x01 is MAC0, 0x02 is CPU0, +# 0x04 is MAC1, 0x08 is CPU1, +# 0x10 is MAC2, 0x20 is CPU2, +# 0x40 is MAC3, 0x80 is CPU3, +# Return: +################################################################ +def nftest_add_LPM_table_entry(entryIndex, subnetIP, subnetMask, nextHopIP, outputPort): + add_LPM_table_entry(entryIndex, subnetIP, subnetMask, nextHopIP, outputPort) + +################################################################ +# Name: nftest_invalidate_LPM_table +# +# clears all entries in the routing table (by setting everything +# to 0) +# +# Arguments: depth int +# +# Return: +################################################################ +def nftest_invalidate_LPM_table(depth): + for i in range(depth): + invalidate_LPM_table_entry(i) + +################################################################ +# Name: nftest_invalidate_LPM_table_entry +# +# clears an entry in the routing table (by setting everything +# to 0) +# +# Arguments: entryIndex int +# +# Return: +################################################################ +def nftest_invalidate_LPM_table_entry(entryIndex): + invalidate_LPM_table_entry(entryIndex) + +################################################################ +# Name: nftest_contains_LPM_table_entries +# +# Compares the expected_entries array against what is in hardware +# returning any expected_entries that do not exist in hardware +# +# Arguments: expected_entries array of entries, with each field +# separated by a hyphen ('-') +# +# Return: array of missing entries as strings +################################################################ +def nftest_contains_LPM_table_entries(expected_entries): + actual_entries = {} + missing_entries = [] + + for i in range(LPM_LUT_ROWS - 1): + entry = get_LPM_table_entry(i) + actual_entries[entry] = entry + for expected_entry in expected_entries: + try: + tmp = actual_entries[expected_entry] + except(KeyError): + missing_entries.append(expected_entry) + return missing_entries + +################################################################ +# Name: nftest_add_dst_ip_filter_entry +# +# Adds an entry in the IP destination filtering table. Any +# packets with IP dst addr that matches in this table is sent to +# the CPU. This is also used to set the IP address of the +# router's ports. +# +# Arguments: entryIndex int +# destIP string in format w.x.y.z +# Return: +################################################################ +def nftest_add_dst_ip_filter_entry(entryIndex, destIP): + add_dst_ip_filter_entry(entryIndex, destIP) + +################################################################ +# Name: nftest_invalidate_dst_ip_filter_table +# +# Removes contents of the IP destination filtering table by +# setting all entries to 0. +# +# Arguments: depth int +# +# Return: +################################################################ +def nftest_invalidate_dst_ip_filter_table(depth): + for i in range(depth): + invalidate_dst_ip_filter_entry(i) + +################################################################ +# Name: nftest_invalidate_dst_ip_filter_entry +# +# Removes an entry from the IP destination filtering table by +# setting it to 0. +# +# Arguments: entryIndex int +# +# Return: +################################################################ +def nftest_invalidate_dst_ip_filter_entry(entryIndex): + invalidate_dst_ip_filter_entry(entryIndex) + +################################################################ +# Name: nftest_contains_dst_ip_filter_entries +# +# Compares the expected_ips array against what is in hardware +# returning any expected_ips that do not exist in hardware +# +# Arguments: expected_ips array of ip address strings +# +# Return: array of missing ip address strings +################################################################ +def nftest_contains_dst_ip_filter_entries(expected_ips): + actual_ips = {} + missing_ips = [] + for i in range(FILTER_ROWS - 1): + ip = get_dst_ip_filter_entry(i) + actual_ips[ip] = ip + for expected_ip in expected_ips: + try: + tmp = actual_ips[dotted(expected_ip)] + except(KeyError): + missing_ips.append(expected_ip) + return missing_ips + +################################################################ +# Name: nftest_add_ARP_table_entry +# +# adds an entry to the hardware's ARP table. +# +# Arguments: entryIndex int +# nextHopIP string in format w.x.y.z +# nextHopMAC string in format w.x.y.z +# +# Return: +################################################################ +def nftest_add_ARP_table_entry(entryIndex, nextHopIP, nextHopMAC): + add_ARP_table_entry(entryIndex, nextHopIP, nextHopMAC) + +################################################################ +# Name: nftest_invalidate_ARP_table +# +# clears all entries from the hardware's ARP table by setting to +# all zeros. +# +# Arguments: depth int +# +# Return: +################################################################ +def nftest_invalidate_ARP_table(depth): + for i in range(depth): + invalidate_ARP_table_entry(i) + +################################################################ +# Name: nftest_invalidate_ARP_table_entry +# +# clears an entry from the hardware's ARP table by setting to +# all zeros. +# +# Arguments: entryIndex int +# +# Return: +################################################################ +def nftest_invalidate_ARP_table_entry(entryIndex): + invalidate_ARP_table_entry(entryIndex) + +################################################################ +# Name: nftest_contains_ARP_table_entries +# +# Compares the expected_entries array against what is in hardware +# returning any expected_entries that do not exist in hardware +# +# Arguments: expected_entries array of entries, with each field +# separated by a hyphen ('-') +# +# Return: array of missing entries as strings +################################################################ +def nftest_contains_ARP_table_entries(expected_entries): + actual_entries = {} + missing_entries = [] + for i in range(ARP_LUT_ROWS - 1): + entry = get_ARP_table_entry(i) + actual_entries[entry] = entry + for expected_entry in expected_entries: + try: + tmp = actual_entries[expected_entry] + except(KeyError): + missing_entries.append(expected_entry) + return missing_entries + +################################################################ +# Name: nftest_invalidate_all_tables +# +# Invalidates the entries in the following tables: +# - ARP +# - LPM +# - dst IP filter +# +# Arguments: arp_depth int +# lpm_depth int +# dst_ip_filter_depth int +# +# Default values taken from reg_defines.ROUTER_OP_LUT_*_TABLE_DEPTH +# +# Return: +################################################################ +def nftest_invalidate_all_tables(): + invalidate_all_tables() diff --git a/hw/projects/reference_router/lib/Python/RouterLib.py b/hw/projects/reference_router/lib/Python/RouterLib.py new file mode 100755 index 0000000..41b03ff --- /dev/null +++ b/hw/projects/reference_router/lib/Python/RouterLib.py @@ -0,0 +1,292 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) Salvator Galea +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from NFTest.hwRegLib import regread +import NFTest.simReg + +import sys +import os + +import re + +import socket +import struct + +from ctypes import * +from reg_defines_reference_router import * + +# Number of entries in each table (default=32) +LPM_LUT_ROWS = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_IP_LPM_TCAM_DEPTH() +ARP_LUT_ROWS = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_IP_ARP_CAM_DEPTH() +FILTER_ROWS = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_DEST_IP_CAM_DEPTH() + +# Check the reg_defines_reference_router.py +# for the address space of these memories +# LPM_TABLE = int("0",16)<<28 +# ARP_TABLE = int("1",16)<<28 +# FILTER_TABLE = int("2",16)<<28 +LPM_TABLE = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_IP_LPM_TCAM_ADDRESS() +ARP_TABLE = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_IP_ARP_CAM_ADDRESS() +FILTER_TABLE = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_DEST_IP_CAM_ADDRESS() + +# Write and read command for the indirect register access +WR_IND_COM = 0x0001 +RD_IND_COM = 0x0011 + +################################################################ +# +# Setting and getting the router MAC addresses +# +################################################################ +def set_router_MAC(port, MAC): + port = int(port) + if port < 1 or port > 4: + print('bad port number') + sys.exit(1) + mac = MAC.split(':') + mac_hi = int(mac[0],16)<<8 | int(mac[1],16) + mac_lo = int(mac[2],16)<<24 | int(mac[3],16)<<16 | int(mac[4],16)<<8 | int(mac[5],16) + + port -= 1 + + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_0_HI() + port * 8, mac_hi) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_0_LOW() + port * 8, mac_lo) + +def get_router_MAC(port, MAC): + port = int(port) + if port < 1 or port > 4: + print('bad port number') + port -= 1 + mac_hi = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_0_HI() + port * 8) + mac_lo = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_0_LOW() + port * 8) + mac_tmp = "%04x%08x"%(mac_hi, mac_lo) + grp_mac = re.search("^(..)(..)(..)(..)(..)(..)$", mac_tmp).groups() + str_mac = '' + for octet in grp_mac: + str_mac += grp_mac + ":" + str_mac.rstrip(':') + return str_mac + +################################################################ +# +# LPM table stuff +# +################################################################ +def add_LPM_table_entry(index, IP, mask, next_IP, next_port): + if index < 0 or index > LPM_LUT_ROWS - 1 or next_port < 0 or next_port > 255: + print('Bad data') + sys.exit(1) + if re.match("(\d+)\.", IP): + IP = dotted(IP) + if re.match("(\d+)\.", mask): + mask = dotted(mask) + if re.match("(\d+)\.", next_IP): + next_IP = dotted(next_IP) + + # Configuration for the Register Table (write data) + # |-- INDIRECTWRDATA 128bit --| + # |- -INDIRECTWRDATA_A_HI 32bit- -INDIRECTWRDATA_A_LOW 32bit- -INDIRECTWRDATA_B_HI 32bit- -INDIRECTWRDATA_B_LOW 32bit- -| + # |-- IP -- next_IP -- mask -- next_port --| + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_HI(), IP) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_HI(), mask) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_LOW(), next_IP) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_LOW(), next_port) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), LPM_TABLE | index) # Address of the table + index + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM) # Configure command - WRITE + +def invalidate_LPM_table_entry(index): + if index < 0 or index > LPM_LUT_ROWS-1: + print('Bad data') + sys.exit(1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_HI(), 0) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_HI(), 0xffffffff) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_LOW(), 0) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_LOW(), 0) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), LPM_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM) + +def invalidate_LPM_table(): + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(),0x0200) # Configure lpm_table reset + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM)# Configure command - WRITE + +def get_LPM_table_entry(index): + if index < 0 or index > LPM_LUT_ROWS - 1: + print('get_LPM_table_entry_generic: Bad data') + sys.exit(1) + + # Configuration for the Register Table (read data) + # |-- INDIRECTREPLY 128bit --| + # |- -INDIRECTREPLY_A_HI 32bit- -INDIRECTREPLY_A_LOW 32bit- -INDIRECTREPLY_B_HI 32bit- -INDIRECTREPLY_B_LOW 32bit- -| + # |-- IP -- next_IP -- mask -- next_port --| + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), LPM_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), RD_IND_COM) + IP = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_HI()) + mask = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_HI()) + next_hop = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_LOW()) + output_port = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW()) + + ip_str = socket.inet_ntoa(struct.pack('!L', IP)) + mask_str = socket.inet_ntoa(struct.pack('!L', mask)) + next_hop_str = socket.inet_ntoa(struct.pack('!L', next_hop)) + return ip_str + '-' + mask_str + '-' + next_hop_str + "-0x%02x"%output_port + +################################################################ +# +# Destination IP filter table stuff +# +################################################################ +def add_dst_ip_filter_entry(index, IP): + if index < 0 or index > FILTER_ROWS - 1: + print('Bad data') + sys.exit(1) + if re.match("(\d+)\.", IP): + IP = dotted(IP) + # Configuration for the Register Table (write data) + # |-- INDIRECTWRDATA 128bit --| + # |- -INDIRECTWRDATA_A_HI 32bit- -INDIRECTWRDATA_A_LOW 32bit- -INDIRECTWRDATA_B_HI 32bit- -INDIRECTWRDATA_B_LOW 32bit- -| + # |-- 0x0000 -- 0x0000 -- 0x0000 -- IP --| + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_LOW(), IP) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), FILTER_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM) + +def invalidate_dst_ip_filter_entry(index): + if index < 0 or index > FILTER_ROWS-1: + print('Bad data') + sys.exit(1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_LOW(), 0) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), FILTER_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM) + +def invalidate_dst_ip_filter_table(): + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x0800) # Configure dst_ip_filter reset + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM)# Configure command - WRITE + +def get_dst_ip_filter_entry(index): + if index < 0 or index > FILTER_ROWS-1: + print('Bad data') + sys.exit(1) + # Configuration for the Register Table (read data) + # |-- INDIRECTREPLY 128bit --| + # |- -INDIRECTREPLY_A_HI 32bit- -INDIRECTREPLY_A_LOW 32bit- -INDIRECTREPLY_B_HI 32bit- -INDIRECTREPLY_B_LOW 32bit- -| + # |-- 0x0000 -- 0x0000 -- 0x0000 -- IP --| + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), FILTER_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), RD_IND_COM) + return nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW()) + + +################################################################ +# +# ARP stuff +# +################################################################ +def add_ARP_table_entry(index, IP, MAC): + if index < 0 or index > ARP_LUT_ROWS-1: + print('Bad data') + sys.exit(1) + if re.match("(\d+)\.", IP): + IP = dotted(IP) + mac = MAC.split(':') + mac_hi = int(mac[0],16)<<8 | int(mac[1],16) + mac_lo = int(mac[2],16)<<24 | int(mac[3],16)<<16 | int(mac[4],16)<<8 | int(mac[5],16) + + # Configuration for the Register Table (write data) + # |-- INDIRECTWRDATA 128bit --| + # |- -INDIRECTWRDATA_A_HI 32bit- -INDIRECTWRDATA_A_LOW 32bit- -INDIRECTWRDATA_B_HI 32bit- -INDIRECTWRDATA_B_LOW 32bit- -| + # |-- mac_hi -- mac_lo -- 0x0000 -- IP --| + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_LOW(), IP) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_HI(), mac_hi) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_LOW(), mac_lo) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), ARP_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM) + +def invalidate_ARP_table_entry(index): + if index < 0 or index > ARP_LUT_ROWS-1: + print('Bad data') + sys.exit(1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_B_LOW(), 0) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_HI(), 0) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTWRDATA_A_LOW(), 0) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), ARP_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM) + +def invalidate_ARP_table(): + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(),0x0400) # Configure arp_table reset + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), WR_IND_COM)# Configure command - WRITE + + +def get_ARP_table_entry(index): + if index < 0 or index > ARP_LUT_ROWS-1: + print('check_ARP_table_entry: Bad data') + sys.exit(1) + + # -- Configuration for the Register Table (read data) + # |-- INDIRECTREPLY 128bit --| + # |- -INDIRECTREPLY_A_HI 32bit- -INDIRECTREPLY_A_LOW 32bit- -INDIRECTREPLY_B_HI 32bit- -INDIRECTREPLY_B_LOW 32bit- -| + # |-- mac_hi -- mac_lo -- 0x0000 -- IP --| + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), ARP_TABLE | index) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), RD_IND_COM) + IP = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW()) + mac_hi = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_HI()) + mac_lo = nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_LOW()) + + IP_str = socket.inet_ntoa(struct.pack('!L', IP)) + mac_tmp = "%04x%08x"%(mac_hi, mac_lo) + grp_mac = re.search("^(..)(..)(..)(..)(..)(..)$", mac_tmp).groups() + str_mac = '' + for octet in grp_mac: + str_mac += octet + ":" + str_mac = str_mac.rstrip(':') + return IP_str + '-' + str_mac + + +################################################################ +# +# Misc routines +# +################################################################ +def dotted(strIP): + octet = strIP.split('.') + newip = int(octet[0])<<24 | int(octet[1])<<16 | int(octet[2])<<8 | int(octet[3]) + return newip + + +def invalidate_all_tables(): + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x0e00) # Configure reset in all tables + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), 0x1)# Configure command - WRITE + + + + + + + diff --git a/hw/projects/reference_router/test/both_arp_misses/run.py b/hw/projects/reference_router/test/both_arp_misses/run.py new file mode 100755 index 0000000..6273a2d --- /dev/null +++ b/hw/projects/reference_router/test/both_arp_misses/run.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + + + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +index = 0 +subnetIP = "192.168.1.0" +subnetMask = "255.255.255.0" +nextHopIP = "192.168.1.54" +outPort = 0x4 +nextHopMAC = "dd:55:dd:66:dd:77" + +nftest_add_LPM_table_entry(index, subnetIP, subnetMask, nextHopIP, outPort) + +nftest_barrier() + +DA = routerMAC[0] +SA = "aa:bb:cc:dd:ee:ff" +TTL = 64 +DST_IP = "192.168.1.1" +#DST_IP = "192.168.5.1" +SRC_IP = "192.168.0.1" +nextHopMAC = "dd:55:dd:66:dd:77" +sent_pkts = [] +pkts_num = 30 + +print("Sending packets") + +for i in range(pkts_num): + sent_pkt = make_IP_pkt(src_MAC=SA, dst_MAC=DA, dst_IP=DST_IP, src_IP=SRC_IP, pkt_len=random.randint(60,1514)) + if isHW(): + nftest_send_phy('nf0', sent_pkt) + nftest_expect_dma('nf0', sent_pkt) + else: + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_expect_dma('nf0', sent_pkts) + +nftest_barrier() + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_ARP_MISS_CNTR(), pkts_num) + mres=[rres1] +else: + simReg.regDelay(300) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_ARP_MISS_CNTR(), pkts_num) + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_badipchksum_packet/run.py b/hw/projects/reference_router/test/both_badipchksum_packet/run.py new file mode 100755 index 0000000..ecc04d2 --- /dev/null +++ b/hw/projects/reference_router/test/both_badipchksum_packet/run.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + + + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +SA = "aa:bb:cc:dd:ee:ff" +DST_IP = "192.168.2.1"; #not in the lpm table +SRC_IP = "192.168.0.1" +VERSION = 0x4 +nextHopMAC = "dd:55:dd:66:dd:77" +sent_pkts = [] +pkts_num = 30 + +nftest_barrier() + +# loop for 30 packets +for i in range(pkts_num): + if isHW(): + for port in range(2): + DA = routerMAC[port] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, src_IP=SRC_IP, pkt_len=random.randint(60,1514)) + sent_pkt.chksum = 0 + nftest_send_phy('nf%d'%port, sent_pkt) + nftest_barrier() + else: + DA = routerMAC[0] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, src_IP=SRC_IP, pkt_len=random.randint(60,1514)) + sent_pkt.chksum = 0 + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_barrier() + simReg.regDelay(1000) + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_DROPPED_CHECKSUM_CNTR(), pkts_num*2) + mres=[rres1] +else: + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_DROPPED_CHECKSUM_CNTR(), pkts_num) + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_invalidttl_packet/run.py b/hw/projects/reference_router/test/both_invalidttl_packet/run.py new file mode 100755 index 0000000..64ed95e --- /dev/null +++ b/hw/projects/reference_router/test/both_invalidttl_packet/run.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +SA = "aa:bb:cc:dd:ee:ff" +TTL = 0 +DST_IP = "192.168.2.1"; #not in the lpm table +SRC_IP = "192.168.0.1" +VERSION = 0x4 +nextHopMAC = "dd:55:dd:66:dd:77" +sent_pkts = [] +pkts_num = 30 + +nftest_barrier() + +# loop for 30 packets +for i in range(pkts_num): + if isHW(): + for port in range(2): + DA = routerMAC[port] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, src_IP=SRC_IP, pkt_len=random.randint(60,1514)) + sent_pkt.ttl = TTL + nftest_send_phy('nf%d'%port, sent_pkt) + nftest_expect_dma('nf%d'%port, sent_pkt) + else: + DA = routerMAC[0] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, src_IP=SRC_IP, pkt_len=random.randint(60,1514)) + sent_pkt.ttl = TTL + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_expect_dma('nf0', sent_pkts) + +nftest_barrier() + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_BAD_TTL_CNTR(), pkts_num*2) + mres=[rres1] +else: + simReg.regDelay(200) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_BAD_TTL_CNTR(), pkts_num) + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_ipdestfilter_hit/run.py b/hw/projects/reference_router/test/both_ipdestfilter_hit/run.py new file mode 100755 index 0000000..75d5aa3 --- /dev/null +++ b/hw/projects/reference_router/test/both_ipdestfilter_hit/run.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] +dstIP = ["192.168.0.50", "192.168.1.50"] +dstMAC = ["aa:bb:cc:dd:ee:01", "aa:bb:cc:dd:ee:02"] + +ALLSPFRouters = "224.0.0.5" + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(3000) # Give enough time for the mem initialization + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +nftest_add_dst_ip_filter_entry (4, ALLSPFRouters) +nftest_add_dst_ip_filter_entry (5, dstIP[0]) + + +SA = "aa:bb:cc:dd:ee:ff" +DST_IP = dstIP[0] +SRC_IP = "192.168.0.1" +sent_pkts = [] +pkts_num = 30 + +# Give enough time for the previous memory operation +if not isHW(): + simReg.regDelay(500) + +nftest_barrier() + +# loop for 30 packets +for i in range(pkts_num): + if isHW(): + for portid in range(2): + DA = routerMAC[portid] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, src_IP=SRC_IP, dst_IP=DST_IP, pkt_len=random.randint(60,1514)) + nftest_send_phy('nf%d'%portid, sent_pkt) + nftest_expect_dma('nf%d'%portid, sent_pkt) + else: + DA = routerMAC[0] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, src_IP=SRC_IP, dst_IP=DST_IP, pkt_len=random.randint(60,1514)) + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_expect_dma('nf0', sent_pkts) + +nftest_barrier() + +# Read the counters +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR(), pkts_num*2) + mres=[rres1] +else: + simReg.regDelay(250) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_DEST_IP_HIT_CNTR(), pkts_num) + mres=[] + +nftest_barrier() + +nftest_finish(mres) + diff --git a/hw/projects/reference_router/test/both_lpm_generic/run.py b/hw/projects/reference_router/test/both_lpm_generic/run.py new file mode 100755 index 0000000..415099a --- /dev/null +++ b/hw/projects/reference_router/test/both_lpm_generic/run.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +subnetIP = ["192.168.1.1", "192.168.1.0"] +subnetMask = ["255.255.255.225", "255.255.255.0"] +nextHopIP = ["192.168.3.12", "192.168.1.54"] +outPort = [0x4, 0x1] +nextHopMAC = "dd:55:dd:66:dd:77" +pkts = [] +exp_pkts = [] +pkts_num = 100 + +for i in range(2): + nftest_add_LPM_table_entry(i, subnetIP[i], subnetMask[i], nextHopIP[i], outPort[i]) + nftest_add_ARP_table_entry(i, nextHopIP[i], nextHopMAC) + +nftest_barrier() + +for i in range(pkts_num): + hdr = make_MAC_hdr(src_MAC="aa:bb:cc:dd:ee:ff", dst_MAC=routerMAC[0],)/scapy.IP(src="192.168.0.1", dst="192.168.1.1") + exp_hdr = make_MAC_hdr(src_MAC=routerMAC[1], dst_MAC=nextHopMAC,)/scapy.IP(src="192.168.0.1", dst="192.168.1.1", ttl=63) + load = generate_load(100) + pkt = hdr/load + exp_pkt = exp_hdr/load + if isHW(): + nftest_send_phy('nf0', pkt) + nftest_expect_phy('nf1', exp_pkt) + else: + pkt.time = ((i*(1e-8)) + (2e-6)) + pkts.append(pkt) + exp_pkt.time = ((i*(1e-8)) + (2e-6)) + exp_pkts.append(exp_pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_phy('nf1', exp_pkts) + +mres=[] +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_lpm_misses/run.py b/hw/projects/reference_router/test/both_lpm_misses/run.py new file mode 100755 index 0000000..04fd347 --- /dev/null +++ b/hw/projects/reference_router/test/both_lpm_misses/run.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +index = 0 +subnetIP = "192.168.1.0" +subnetMask = "255.255.255.0" +nextHopIP = "192.168.1.54" +outPort = 0x4 +nextHopMAC = "dd:55:dd:66:dd:77" +pkts = [] +pkts_num = 100 + +nftest_add_LPM_table_entry(index, subnetIP, subnetMask, nextHopIP, outPort) +nftest_add_ARP_table_entry(index, nextHopIP, nextHopMAC) + +nftest_barrier() + +for i in range(pkts_num): + pkt = make_IP_pkt(src_MAC="aa:bb:cc:dd:ee:ff", dst_MAC=routerMAC[0], src_IP="192.168.0.1", dst_IP="192.168.2.1") + if isHW(): + nftest_send_phy('nf0', pkt) + nftest_expect_dma('nf0', pkt) + else: + pkt.time = ((i*(1e-8)) + (2e-6)) + pkts.append(pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_dma('nf0', pkts) + +nftest_barrier() + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_LPM_MISS_CNTR(), pkts_num) + mres=[rres1] +else: + simReg.regDelay(3000) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_LPM_MISS_CNTR(), pkts_num) + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_lpm_nexthop/run.py b/hw/projects/reference_router/test/both_lpm_nexthop/run.py new file mode 100755 index 0000000..5d76b8f --- /dev/null +++ b/hw/projects/reference_router/test/both_lpm_nexthop/run.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + + + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +index = 0 +subnetIP = ["192.168.1.1" , "192.168.1.0"] +subnetMask = ["255.255.255.225" , "255.255.255.0"] +nextHopIP = ["0.0.0.0" , "192.168.1.54"] +arpNextHopIP = ["192.168.1.54" , "192.168.1.1"] +outPort = [0x4 , 0x1] +nextHopMAC = "dd:55:dd:66:dd:77" +pkts = [] +exp_pkts = [] +pkts_num = 100 + +for i in range(2): + nftest_add_LPM_table_entry(i, subnetIP[i], subnetMask[i], nextHopIP[i], outPort[i]) + nftest_add_ARP_table_entry(i, arpNextHopIP[i], nextHopMAC) + +nftest_barrier() + +for i in range(pkts_num): + hdr = make_MAC_hdr(src_MAC="aa:bb:cc:dd:ee:ff", dst_MAC=routerMAC[0],)/scapy.IP(src="192.168.0.1", dst="192.168.1.1") + exp_hdr = make_MAC_hdr(src_MAC=routerMAC[1], dst_MAC=nextHopMAC,)/scapy.IP(src="192.168.0.1", dst="192.168.1.1", ttl=63) + load = generate_load(100) + pkt = hdr/load + exp_pkt = exp_hdr/load + if isHW(): + nftest_send_phy('nf0', pkt) + nftest_expect_phy('nf1', exp_pkt) + else: + pkt.time = ((i*(1e-8)) + (2e-6)) + pkts.append(pkt) + exp_pkt.time = ((i*(1e-8)) + (2e-6)) + exp_pkts.append(exp_pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_phy('nf1', exp_pkts) + +mres=[] +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_nonip_packet/run.py b/hw/projects/reference_router/test/both_nonip_packet/run.py new file mode 100755 index 0000000..9c5d067 --- /dev/null +++ b/hw/projects/reference_router/test/both_nonip_packet/run.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +SA = "aa:bb:cc:dd:ee:ff" +DST_IP = "192.168.2.1"; #not in the lpm table +SRC_IP = "192.168.0.1" +nextHopMAC = "dd:55:dd:66:dd:77" +# Non IP packets +EtherType = 0x802 +sent_pkts = [] +pkts_num = 30 + +nftest_barrier() + +# loop for 30 packets +for i in range(pkts_num): + if isHW(): + for port in range(2): + DA = routerMAC[port] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, EtherType=EtherType, pkt_len=random.randint(60,1514)) + nftest_send_phy('nf%d'%port, sent_pkt) + nftest_expect_dma('nf%d'%port, sent_pkt) + else: + DA = routerMAC[0] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, EtherType=EtherType, pkt_len=random.randint(60,1514)) + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_expect_dma('nf0', sent_pkts) + +nftest_barrier() + +# Read the counters +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_NON_IP_CNTR(), pkts_num*2) + mres=[rres1] +else: + simReg.regDelay(200) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_NON_IP_CNTR(), pkts_num) + mres=[] + +nftest_finish(mres) + diff --git a/hw/projects/reference_router/test/both_nonipv4_packet/run.py b/hw/projects/reference_router/test/both_nonipv4_packet/run.py new file mode 100755 index 0000000..fcd603c --- /dev/null +++ b/hw/projects/reference_router/test/both_nonipv4_packet/run.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) +nftest_start() + + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +SA = "aa:bb:cc:dd:ee:ff" +DST_IP = "192.168.2.1"; #not in the lpm table +SRC_IP = "192.168.0.1" +nextHopMAC = "dd:55:dd:66:dd:77" +# Non IP option or ip_ver not 4 +VERSION = 5 +sent_pkts = [] +pkts_num = 30 + +nftest_barrier() + +# loop for 30 packets +for i in range(pkts_num): + if isHW(): + for port in range(2): + DA = routerMAC[port] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, src_IP=SRC_IP, dst_IP=DST_IP, pkt_len=random.randint(60,1514)) + sent_pkt.version= VERSION + nftest_send_phy('nf%d'%port, sent_pkt) + nftest_expect_dma('nf%d'%port, sent_pkt) + else: + DA = routerMAC[0] + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, src_IP=SRC_IP, dst_IP=DST_IP, pkt_len=random.randint(60,1514)) + sent_pkt.version= VERSION + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_expect_dma('nf0', sent_pkts) + +nftest_barrier() + +# Read the counters +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR(), pkts_num*2) + mres=[rres1] +else: + simReg.regDelay(400) + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_SENT_TO_CPU_OPTIONS_VER_CNTR(), pkts_num) + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_packet_forwarding/run.py b/hw/projects/reference_router/test/both_packet_forwarding/run.py new file mode 100755 index 0000000..fc5848a --- /dev/null +++ b/hw/projects/reference_router/test/both_packet_forwarding/run.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + + + +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + + +# add an entry in the routing table: +subnetIP = ["192.168.2.0", "192.168.1.0"] +subnetMask = ["255.255.255.0", "255.255.255.0"] +nextHopIP = ["192.168.1.54", "192.168.3.12"] +outPort = [0x1, 0x4] +nextHopMAC = "dd:55:dd:66:dd:77" +SA = "aa:bb:cc:dd:ee:ff" +SRC_IP = "192.168.0.1" +length = 100 + +for i in range(2): + nftest_add_LPM_table_entry (i, subnetIP[i], subnetMask[i], nextHopIP[i], outPort[i]) + nftest_add_ARP_table_entry (i, nextHopIP[i], nextHopMAC) + + +nftest_barrier() + +precreated = [[], []] +precreated_exp = [[], []] +sent_pkts = [] +exp_pkts = [] + +# loop for 20 packets from eth1 to eth2 +pkts_num = 20 + +for i in range(pkts_num): + + if isHW(): + for port in range(2): + DA = routerMAC[port] + DST_IP = "192.168.%d.1"%(port + 1) + sent_pkt= make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, src_IP=SRC_IP, pkt_len=length) + exp_pkt = make_IP_pkt(dst_MAC=nextHopMAC, src_MAC=routerMAC[1 - port], TTL = 63, dst_IP=DST_IP, src_IP=SRC_IP) + exp_pkt[scapy.Raw].load = sent_pkt[scapy.Raw].load + + # send packet out of eth1->nf0 + nftest_send_phy('nf%d'%port, sent_pkt); + nftest_expect_phy('nf%d'%(1-port), exp_pkt); + else: + DA = routerMAC[0] + DST_IP = "192.168.1.1" + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, dst_IP=DST_IP, src_IP=SRC_IP, pkt_len=length) + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + + exp_pkt = make_IP_pkt(dst_MAC=nextHopMAC, src_MAC=routerMAC[1], TTL = 63, dst_IP=DST_IP, src_IP=SRC_IP) + exp_pkt[scapy.Raw].load = sent_pkt[scapy.Raw].load + exp_pkt.time = ((i*(1e-8)) + (2e-6)) + exp_pkts.append(exp_pkt) + + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_expect_phy('nf1', exp_pkts) + +nftest_barrier() + + +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_FORWARDED_CNTR(), pkts_num*2); + mres=[rres1] +else: + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_FORWARDED_CNTR(), pkts_num); + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_router_table/run.py b/hw/projects/reference_router/test/both_router_table/run.py new file mode 100755 index 0000000..64e30f7 --- /dev/null +++ b/hw/projects/reference_router/test/both_router_table/run.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou, Salvator Galea +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) +nftest_start() +mres=[] + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +# Write and read command for the indirect register access +WR_IND_COM = 0x0001 +RD_IND_COM = 0x0011 +NUM_PORTS = 2 + +dest_MACs = ["00:0a:35:03:00:01", "00:0a:35:03:00:00"] +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +ALLSPFRouters = "224.0.0.5" + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(3000) # Give enough time to initiliaze all the memories + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +nftest_add_dst_ip_filter_entry (2, ALLSPFRouters) + +# router mac 0 +reg0=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_0_HI(), 0x000a) +reg1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_0_LOW(), 0x35030000) +# router mac 1 +reg2=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_1_HI(), 0x000a) +reg3=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_1_LOW(), 0x35030001) +mres.extend([reg0, reg1, reg2, reg3]) +## router mac 2 +#nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_2_HI(), 0xca) +#nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_2_LOW(), 0xfe000003) +## router mac 3 +#nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_3_HI(), 0xca) +#nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_MAC_3_LOW(), 0xfe000004) + +# add LPM and ARP entries for each port +for i in range(NUM_PORTS): + i_plus_1 = i + 1 + subnetIP = "192.168." + str(i_plus_1) + ".1" + subnetMask = "255.255.255.225" + nextHopIP = "192.168.5." + str(i_plus_1) + outPort = 1 << (2 * i) + nextHopMAC = dest_MACs[i] + + # add an entry in the routing table + nftest_add_LPM_table_entry(i, subnetIP, subnetMask, nextHopIP, outPort) + # add and entry in the ARP table + nftest_add_ARP_table_entry(i, nextHopIP, nextHopMAC) + + +num = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_IP_ARP_CAM_DEPTH() - 1 +# ARP table +mac_hi = 0x000a +mac_lo = [0x35030001, 0x35030000] +router_ip = [0xc0a80501, 0xc0a80502] + +for i in range(num): + #nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), int("0x10000000",16) | i) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_IP_ARP_CAM_ADDRESS() | i) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), RD_IND_COM) + # ARP MAC + # |- -INDIRECTREPLY_A_HI 32bit- -INDIRECTREPLY_A_LOW 32bit- -INDIRECTREPLY_B_HI 32bit- -INDIRECTREPLY_B_LOW 32bit- -| + # |-- mac_hi -- mac_lo -- 0x0000 -- IP --| + if i < 2: + reg0 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_HI(), mac_hi) + reg1 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_LOW(), mac_lo[i]) + reg2 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW(), router_ip[i]) + mres.extend([reg0, reg1, reg2]) + else: + reg0 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_HI(), 0) + reg1 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_LOW(), 0) + reg2 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW(), 0) + mres.extend([reg0, reg1, reg2]) + +# Routing table +router_ip = [0xc0a80101, 0xc0a80201] +subnet_mask = [0xffffffe1, 0xffffffe1] +arp_port = [1, 4] +next_hop_ip = [0xc0a80501, 0xc0a80502] + +for i in range(num): + #nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), int("0x00000000",16) | i) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_IP_LPM_TCAM_ADDRESS() | i) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), RD_IND_COM) + # |- -INDIRECTREPLY_A_HI 32bit- -INDIRECTREPLY_A_LOW 32bit- -INDIRECTREPLY_B_HI 32bit- -INDIRECTREPLY_B_LOW 32bit- -| + # |-- IP -- next_IP -- mask -- next_port --| + if i < 2: + reg0 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW(), arp_port[i]) + mres.append(reg0) + if i < 2: + # Router IP + reg0 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_HI(), router_ip[i]) + reg1 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_LOW(), next_hop_ip[i]) + # Router subnet mask + reg2 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_HI(), subnet_mask[i]) + mres.extend([reg0, reg1, reg2]) + else: + # Router IP + reg0 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_HI(), 0) + reg1 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_A_LOW(), 0) + # Router subnet mask + reg2 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_HI(), 0xffffffff) + mres.extend([reg0, reg1, reg2]) + +# IP filter +num = NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_DEST_IP_CAM_DEPTH() - 1 +filters = [0xc0a80028, 0xc0a80128, 0xe0000005] + +for i in range(num): + #nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), int("0x20000000",16) | i) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTADDRESS(), NFPLUS_OUTPUT_PORT_LOOKUP_0_MEM_DEST_IP_CAM_ADDRESS() | i) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTCOMMAND(), RD_IND_COM) + # |- -INDIRECTREPLY_A_HI 32bit- -INDIRECTREPLY_A_LOW 32bit- -INDIRECTREPLY_B_HI 32bit- -INDIRECTREPLY_B_LOW 32bit- -| + # |-- 0x0000 -- 0x0000 -- 0x0000 -- IP --| + if i < 3: + reg0 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW(), filters[i]) + mres.append(reg0) + else: + reg0 = nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_INDIRECTREPLY_B_LOW(), 0) + mres.append(reg0) + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/both_wrong_destMAC/run.py b/hw/projects/reference_router/test/both_wrong_destMAC/run.py new file mode 100755 index 0000000..63ab677 --- /dev/null +++ b/hw/projects/reference_router/test/both_wrong_destMAC/run.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +from RegressRouterLib import * +import sys +import os +import random +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_router import * + +phy2loop0 = ('../connections/conn', []) + +nftest_init(sim_loop = [], hw_config = [phy2loop0]) +nftest_start() + +if isHW(): + # asserting the reset_counter to 1 for clearing the registers + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + +routerMAC = ["00:0a:35:03:00:00", "00:0a:35:03:00:01"] +routerIP = ["192.168.0.40", "192.168.1.40"] + +# Clear all tables in a hardware test (not needed in software) +if isHW(): + nftest_invalidate_all_tables() +else: + simReg.regDelay(2000) + + +# Write the mac and IP addresses +for port in range(2): + nftest_add_dst_ip_filter_entry (port, routerIP[port]) + nftest_set_router_MAC ('nf%d'%port, routerMAC[port]) + +# set parameters +SA = "aa:bb:cc:dd:ee:ff" +DST_IP = "192.168.2.1"; #not in the lpm table +SRC_IP = "192.168.0.1" +VERSION = 0x4 +nextHopMAC = "dd:55:dd:66:dd:77" + +# Wrong mac destination +DA = "00:ca:fe:00:00:11" +sent_pkts = [] +pkts_num = 30 + +nftest_barrier() + +# loop for 30 packets +for i in range(pkts_num): + if isHW(): + for port in range(2): + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, src_IP=SRC_IP, dst_IP=DST_IP, pkt_len=random.randint(60, 1514)) + nftest_send_phy('nf%d'%port, sent_pkt) + nftest_barrier() + else: + sent_pkt = make_IP_pkt(dst_MAC=DA, src_MAC=SA, src_IP=SRC_IP, dst_IP=DST_IP, pkt_len=random.randint(60, 1514)) + sent_pkt.time = ((i*(1e-8)) + (2e-6)) + sent_pkts.append(sent_pkt) + +if not isHW(): + nftest_send_phy('nf0', sent_pkts) + nftest_barrier() + simReg.regDelay(1000) + +# Read the counters +if isHW(): + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_DROPPED_WRONG_DST_MAC_CNTR(), pkts_num*2) + mres=[rres1] +else: + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_PKT_DROPPED_WRONG_DST_MAC_CNTR(), pkts_num) + mres=[] + +nftest_barrier() + +nftest_finish(mres) diff --git a/hw/projects/reference_router/test/connections/conn b/hw/projects/reference_router/test/connections/conn new file mode 100755 index 0000000..0827e9b --- /dev/null +++ b/hw/projects/reference_router/test/connections/conn @@ -0,0 +1,30 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +nf0:eth1 +nf1:eth2 diff --git a/hw/projects/reference_router/test/global/setup b/hw/projects/reference_router/test/global/setup new file mode 100755 index 0000000..1d4cdb9 --- /dev/null +++ b/hw/projects/reference_router/test/global/setup @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +from subprocess import Popen, PIPE + +proc = Popen(["ifconfig","eth1","192.168.100.1"], stdout=PIPE) +proc = Popen(["ifconfig","eth2","192.168.101.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf0","192.168.200.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf1","192.168.201.1"], stdout=PIPE) diff --git a/hw/projects/reference_switch/bitfiles/README b/hw/projects/reference_switch/bitfiles/README new file mode 100644 index 0000000..67d4c12 --- /dev/null +++ b/hw/projects/reference_switch/bitfiles/README @@ -0,0 +1,42 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +Reference Switch bitfile is available for a direct download from the University of Cambridge servers: + +1. Reference Switch (VCU1525) +url: +md5 checksum: + +2. Reference Switch (U200) +url: +md5 checksum: + +3. Reference Switch (U250) +url: +md5 checksum: + +4. Reference Switch (U280) +url: +md5 checksum: diff --git a/hw/projects/reference_switch/hw/Makefile b/hw/projects/reference_switch/hw/Makefile new file mode 100644 index 0000000..8bcb4de --- /dev/null +++ b/hw/projects/reference_switch/hw/Makefile @@ -0,0 +1,91 @@ +################################################################################ +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +################################################################################ +PROJ = ${NF_PROJECT_NAME} + +all: project + +project: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode batch -source tcl/${PROJ}.tcl; \ + fi + +projectgui: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode gui -source tcl/${PROJ}.tcl; \ + fi + +sim: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_${NF_PROJECT_NAME}.py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_${NF_PROJECT_NAME}.py + vivado -mode batch -source ../../../projects/${PROJ}/hw/tcl/${NF_PROJECT_NAME}_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +reg: + vivado -mode batch -source $(NF_DESIGN_DIR)/hw/tcl/export_registers.tcl + cd ../test && cp ../../../../tools/scripts/xparam2regdefines.py . && python xparam2regdefines.py + cd ../test && rm -f xparam2regdefines.py + cd ../test && cp ../../../../tools/scripts/python_parser.py . && python python_parser.py + cd ../test && rm -f python_parser.py && mv reg_defines.py reg_defines_${NF_PROJECT_NAME}.py + +simgui: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_reference_switch.py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_reference_switch.py + vivado -mode gui -source ../../../projects/${PROJ}/hw/tcl/${NF_PROJECT_NAME}_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +simclean: + rm -rf proj_* vivado*.* *.*~ .Xil* $(NF_DESIGN_DIR)/hw/ip_repo/ $(NF_DESIGN_DIR)/hw/project/ + rm -rf *[0-9]_{stim,expected,log}.axi + rm -f *.axi + rm -f portconfig.sim + rm -f seed + rm -f *.log + rm -f ../test/Makefile + rm -rf ../test/*.log + rm -rf ../test/*.axi + rm -rf ../test/seed + rm -rf ../test/*.sim + rm -rf ../test/proj_* + rm -rf ../test/ip_repo + rm -f ../test/vivado*.* + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.py + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.pyc + + +clean: + rm -rf project + rm -f vivado* + rm -rf ip_repo diff --git a/hw/projects/reference_switch/hw/constraints/au250_au200_vcu1525_user_timing.tcl b/hw/projects/reference_switch/hw/constraints/au250_au200_vcu1525_user_timing.tcl new file mode 100644 index 0000000..6dd258f --- /dev/null +++ b/hw/projects/reference_switch/hw/constraints/au250_au200_vcu1525_user_timing.tcl @@ -0,0 +1,29 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +create_pblock pblock_nf_datapath +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list nf_datapath_0]] +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list u_top_wrapper/u_nf_attachment]] +resize_pblock [get_pblocks pblock_nf_datapath] -add {SLR2} diff --git a/hw/projects/reference_switch/hw/hdl/nf_datapath.v b/hw/projects/reference_switch/hw/hdl/nf_datapath.v new file mode 100644 index 0000000..da8cd0a --- /dev/null +++ b/hw/projects/reference_switch/hw/hdl/nf_datapath.v @@ -0,0 +1,332 @@ +`timescale 1ns / 1ps +//- +// Copyright (c) 2015 Noa Zilberman +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// nf_datapath.v +// +// Module: +// nf_datapath +// +// Author: Noa Zilberman +// +// Description: +// NetFPGA user data path wrapper, wrapping input arbiter, output port lookup and output queues +// +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + +module nf_datapath #( + //Slave AXI parameters + parameter C_S_AXI_DATA_WIDTH = 32, + parameter C_S_AXI_ADDR_WIDTH = 32, + parameter C_BASEADDR = 32'h00000000, + + // Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH=512, + parameter C_S_AXIS_DATA_WIDTH=512, + parameter C_M_AXIS_TUSER_WIDTH=128, + parameter C_S_AXIS_TUSER_WIDTH=128, + parameter NUM_QUEUES=5 +) ( + //Datapath clock + input axis_aclk, + input axis_resetn, + //Registers clock + input axi_aclk, + input axi_resetn, + + // Slave AXI Ports + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_AWADDR, + input S0_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S0_AXI_WSTRB, + input S0_AXI_WVALID, + input S0_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_ARADDR, + input S0_AXI_ARVALID, + input S0_AXI_RREADY, + output S0_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_RDATA, + output [1 : 0] S0_AXI_RRESP, + output S0_AXI_RVALID, + output S0_AXI_WREADY, + output [1 :0] S0_AXI_BRESP, + output S0_AXI_BVALID, + output S0_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_AWADDR, + input S1_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S1_AXI_WSTRB, + input S1_AXI_WVALID, + input S1_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_ARADDR, + input S1_AXI_ARVALID, + input S1_AXI_RREADY, + output S1_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_RDATA, + output [1 : 0] S1_AXI_RRESP, + output S1_AXI_RVALID, + output S1_AXI_WREADY, + output [1 :0] S1_AXI_BRESP, + output S1_AXI_BVALID, + output S1_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_AWADDR, + input S2_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S2_AXI_WSTRB, + input S2_AXI_WVALID, + input S2_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_ARADDR, + input S2_AXI_ARVALID, + input S2_AXI_RREADY, + output S2_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_RDATA, + output [1 : 0] S2_AXI_RRESP, + output S2_AXI_RVALID, + output S2_AXI_WREADY, + output [1 :0] S2_AXI_BRESP, + output S2_AXI_BVALID, + output S2_AXI_AWREADY, + + + // Slave Stream Ports (interface from Rx queues) + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_0_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_0_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_0_tuser, + input s_axis_0_tvalid, + output s_axis_0_tready, + input s_axis_0_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_1_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_1_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_1_tuser, + input s_axis_1_tvalid, + output s_axis_1_tready, + input s_axis_1_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_2_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_2_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_2_tuser, + input s_axis_2_tvalid, + output s_axis_2_tready, + input s_axis_2_tlast, + + + // Master Stream Ports (interface to TX queues) + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_0_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_0_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_0_tuser, + output m_axis_0_tvalid, + input m_axis_0_tready, + output m_axis_0_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_1_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_1_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_1_tuser, + output m_axis_1_tvalid, + input m_axis_1_tready, + output m_axis_1_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_2_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_2_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_2_tuser, + output m_axis_2_tvalid, + input m_axis_2_tready, + output m_axis_2_tlast + + ); + + //internal connectivity + + wire [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_opl_tuser; + wire m_axis_opl_tvalid; + wire m_axis_opl_tready; + wire m_axis_opl_tlast; + + wire [C_M_AXIS_DATA_WIDTH - 1:0] s_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] s_axis_opl_tuser; + wire s_axis_opl_tvalid; + wire s_axis_opl_tready; + wire s_axis_opl_tlast; + + //Input Arbiter + input_arbiter_ip input_arbiter_v1_0 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (s_axis_opl_tdata), + .m_axis_tkeep (s_axis_opl_tkeep), + .m_axis_tuser (s_axis_opl_tuser), + .m_axis_tvalid(s_axis_opl_tvalid), + .m_axis_tready(s_axis_opl_tready), + .m_axis_tlast (s_axis_opl_tlast), + .s_axis_0_tdata (s_axis_0_tdata), + .s_axis_0_tkeep (s_axis_0_tkeep), + .s_axis_0_tuser (s_axis_0_tuser), + .s_axis_0_tvalid(s_axis_0_tvalid), + .s_axis_0_tready(s_axis_0_tready), + .s_axis_0_tlast (s_axis_0_tlast), + .s_axis_1_tdata (s_axis_1_tdata), + .s_axis_1_tkeep (s_axis_1_tkeep), + .s_axis_1_tuser (s_axis_1_tuser), + .s_axis_1_tvalid(s_axis_1_tvalid), + .s_axis_1_tready(s_axis_1_tready), + .s_axis_1_tlast (s_axis_1_tlast), + .s_axis_2_tdata (s_axis_2_tdata), + .s_axis_2_tkeep (s_axis_2_tkeep), + .s_axis_2_tuser (s_axis_2_tuser), + .s_axis_2_tvalid(s_axis_2_tvalid), + .s_axis_2_tready(s_axis_2_tready), + .s_axis_2_tlast (s_axis_2_tlast), + .S_AXI_AWADDR(S0_AXI_AWADDR), + .S_AXI_AWVALID(S0_AXI_AWVALID), + .S_AXI_WDATA(S0_AXI_WDATA), + .S_AXI_WSTRB(S0_AXI_WSTRB), + .S_AXI_WVALID(S0_AXI_WVALID), + .S_AXI_BREADY(S0_AXI_BREADY), + .S_AXI_ARADDR(S0_AXI_ARADDR), + .S_AXI_ARVALID(S0_AXI_ARVALID), + .S_AXI_RREADY(S0_AXI_RREADY), + .S_AXI_ARREADY(S0_AXI_ARREADY), + .S_AXI_RDATA(S0_AXI_RDATA), + .S_AXI_RRESP(S0_AXI_RRESP), + .S_AXI_RVALID(S0_AXI_RVALID), + .S_AXI_WREADY(S0_AXI_WREADY), + .S_AXI_BRESP(S0_AXI_BRESP), + .S_AXI_BVALID(S0_AXI_BVALID), + .S_AXI_AWREADY(S0_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + + + + //Output Port Lookup + switch_output_port_lookup_ip output_port_lookup_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (m_axis_opl_tdata), + .m_axis_tkeep (m_axis_opl_tkeep), + .m_axis_tuser (m_axis_opl_tuser), + .m_axis_tvalid(m_axis_opl_tvalid), + .m_axis_tready(m_axis_opl_tready), + .m_axis_tlast (m_axis_opl_tlast), + .s_axis_tdata (s_axis_opl_tdata), + .s_axis_tkeep (s_axis_opl_tkeep), + .s_axis_tuser (s_axis_opl_tuser), + .s_axis_tvalid(s_axis_opl_tvalid), + .s_axis_tready(s_axis_opl_tready), + .s_axis_tlast (s_axis_opl_tlast), + + .S_AXI_AWADDR(S1_AXI_AWADDR), + .S_AXI_AWVALID(S1_AXI_AWVALID), + .S_AXI_WDATA(S1_AXI_WDATA), + .S_AXI_WSTRB(S1_AXI_WSTRB), + .S_AXI_WVALID(S1_AXI_WVALID), + .S_AXI_BREADY(S1_AXI_BREADY), + .S_AXI_ARADDR(S1_AXI_ARADDR), + .S_AXI_ARVALID(S1_AXI_ARVALID), + .S_AXI_RREADY(S1_AXI_RREADY), + .S_AXI_ARREADY(S1_AXI_ARREADY), + .S_AXI_RDATA(S1_AXI_RDATA), + .S_AXI_RRESP(S1_AXI_RRESP), + .S_AXI_RVALID(S1_AXI_RVALID), + .S_AXI_WREADY(S1_AXI_WREADY), + .S_AXI_BRESP(S1_AXI_BRESP), + .S_AXI_BVALID(S1_AXI_BVALID), + .S_AXI_AWREADY(S1_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + + + ); + + + //Output queues + output_queues_ip bram_output_queues_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .s_axis_tdata (m_axis_opl_tdata), + .s_axis_tkeep (m_axis_opl_tkeep), + .s_axis_tuser (m_axis_opl_tuser), + .s_axis_tvalid (m_axis_opl_tvalid), + .s_axis_tready (m_axis_opl_tready), + .s_axis_tlast (m_axis_opl_tlast), + .m_axis_0_tdata (m_axis_0_tdata), + .m_axis_0_tkeep (m_axis_0_tkeep), + .m_axis_0_tuser (m_axis_0_tuser), + .m_axis_0_tvalid(m_axis_0_tvalid), + .m_axis_0_tready(m_axis_0_tready), + .m_axis_0_tlast (m_axis_0_tlast), + .m_axis_1_tdata (m_axis_1_tdata), + .m_axis_1_tkeep (m_axis_1_tkeep), + .m_axis_1_tuser (m_axis_1_tuser), + .m_axis_1_tvalid(m_axis_1_tvalid), + .m_axis_1_tready(m_axis_1_tready), + .m_axis_1_tlast (m_axis_1_tlast), + .m_axis_2_tdata (m_axis_2_tdata), + .m_axis_2_tkeep (m_axis_2_tkeep), + .m_axis_2_tuser (m_axis_2_tuser), + .m_axis_2_tvalid(m_axis_2_tvalid), + .m_axis_2_tready(m_axis_2_tready), + .m_axis_2_tlast (m_axis_2_tlast), + .bytes_stored(), + .pkt_stored(), + .bytes_removed_0(), + .bytes_removed_1(), + .bytes_removed_2(), + .pkt_removed_0(), + .pkt_removed_1(), + .pkt_removed_2(), + .bytes_dropped(), + .pkt_dropped(), + + .S_AXI_AWADDR(S2_AXI_AWADDR), + .S_AXI_AWVALID(S2_AXI_AWVALID), + .S_AXI_WDATA(S2_AXI_WDATA), + .S_AXI_WSTRB(S2_AXI_WSTRB), + .S_AXI_WVALID(S2_AXI_WVALID), + .S_AXI_BREADY(S2_AXI_BREADY), + .S_AXI_ARADDR(S2_AXI_ARADDR), + .S_AXI_ARVALID(S2_AXI_ARVALID), + .S_AXI_RREADY(S2_AXI_RREADY), + .S_AXI_ARREADY(S2_AXI_ARREADY), + .S_AXI_RDATA(S2_AXI_RDATA), + .S_AXI_RRESP(S2_AXI_RRESP), + .S_AXI_RVALID(S2_AXI_RVALID), + .S_AXI_WREADY(S2_AXI_WREADY), + .S_AXI_BRESP(S2_AXI_BRESP), + .S_AXI_BVALID(S2_AXI_BVALID), + .S_AXI_AWREADY(S2_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + +endmodule diff --git a/hw/projects/reference_switch/hw/hdl/top_sim.v b/hw/projects/reference_switch/hw/hdl/top_sim.v new file mode 100644 index 0000000..14e47a3 --- /dev/null +++ b/hw/projects/reference_switch/hw/hdl/top_sim.v @@ -0,0 +1,677 @@ +//- +// Copyright (c) 2015 Noa Zilberman, Georgina Kalogeridou +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// top_sim.v +// +// Module: +// top +// +// Author: Noa Zilberman, Georgina Kalogeridou +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ps / 100 fs + + module top_sim # ( + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter C_TUSER_WIDTH = 128, // RX/TX interface data width + parameter C_NF_DATA_WIDTH = 1024, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32 + ) ( + +//PCI Express + input [15:0] pcie_rxn, + input [15:0] pcie_rxp, + output [15:0] pcie_txn, + output [15:0] pcie_txp, + //Network Interface + input [3:0] qsfp0_rxp, + input [3:0] qsfp0_rxn, + output [3:0] qsfp0_txp, + output [3:0] qsfp0_txn, + + input [3:0] qsfp1_rxp, + input [3:0] qsfp1_rxn, + output [3:0] qsfp1_txp, + output [3:0] qsfp1_txn, + + // PCIe Clock + input pci_clk_p, + input pci_clk_n, + + //200MHz Clock + input fpga_sysclk_p, + input fpga_sysclk_n, + + // 156.25 MHz clock in + input qsfp_refclk_p, + input qsfp_refclk_n, + + input sys_reset_n +); + + //----------------------------------------------------------------------------------------------------------------// + // System(SYS) Interface // + //----------------------------------------------------------------------------------------------------------------// + + wire sys_clk; + wire clk_200_i; + wire clk_200; + wire sys_rst_n_c; + + //----------------------------------------------------------------------------------------------------------------------- + + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + wire[C_NF_DATA_WIDTH-1:0] axis_i_0_tdata , axis_o_0_tdata; + wire axis_i_0_tvalid, axis_o_0_tvalid; + wire axis_i_0_tlast , axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_0_tuser , axis_o_0_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_0_tkeep , axis_o_0_tkeep; + wire axis_i_0_tready, axis_o_0_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_i_1_tdata , axis_o_1_tdata; + wire axis_i_1_tvalid, axis_o_1_tvalid; + wire axis_i_1_tlast , axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_1_tuser , axis_o_1_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_1_tkeep , axis_o_1_tkeep; + wire axis_i_1_tready, axis_o_1_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_dma_i_tdata , axis_dma_o_tdata; + wire axis_dma_i_tvalid, axis_dma_o_tvalid; + wire axis_dma_i_tlast , axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] axis_dma_i_tuser , axis_dma_o_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_dma_i_tkeep , axis_dma_o_tkeep; + wire axis_dma_i_tready, axis_dma_o_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_0_tdata , p_axis_o_0_tdata; + wire p_axis_i_0_tvalid, p_axis_o_0_tvalid; + wire p_axis_i_0_tlast , p_axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_0_tuser , p_axis_o_0_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_0_tkeep , p_axis_o_0_tkeep; + wire p_axis_i_0_tready, p_axis_o_0_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_1_tdata , p_axis_o_1_tdata; + wire p_axis_i_1_tvalid, p_axis_o_1_tvalid; + wire p_axis_i_1_tlast , p_axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_1_tuser , p_axis_o_1_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_1_tkeep , p_axis_o_1_tkeep; + wire p_axis_i_1_tready, p_axis_o_1_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_dma_i_tdata , p_axis_dma_o_tdata; + wire p_axis_dma_i_tvalid, p_axis_dma_o_tvalid; + wire p_axis_dma_i_tlast , p_axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_dma_i_tuser , p_axis_dma_o_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_dma_i_tkeep , p_axis_dma_o_tkeep; + wire p_axis_dma_i_tready, p_axis_dma_o_tready; + //----------------------------------------------------------------------------------------------------------------// + // AXI Lite interface // + //----------------------------------------------------------------------------------------------------------------// + wire [31:0] M0_AXI_araddr , M1_AXI_araddr , M2_AXI_araddr; + wire [2:0] M0_AXI_arprot , M1_AXI_arprot , M2_AXI_arprot; + wire M0_AXI_arready, M1_AXI_arready, M2_AXI_arready; + wire M0_AXI_arvalid, M1_AXI_arvalid, M2_AXI_arvalid; + wire [31:0] M0_AXI_awaddr , M1_AXI_awaddr , M2_AXI_awaddr; + wire [2:0] M0_AXI_awprot , M1_AXI_awprot , M2_AXI_awprot; + wire M0_AXI_awready, M1_AXI_awready, M2_AXI_awready; + wire M0_AXI_awvalid, M1_AXI_awvalid, M2_AXI_awvalid; + wire M0_AXI_bready , M1_AXI_bready , M2_AXI_bready; + wire [1:0] M0_AXI_bresp , M1_AXI_bresp , M2_AXI_bresp; + wire M0_AXI_bvalid , M1_AXI_bvalid , M2_AXI_bvalid; + wire [31:0] M0_AXI_rdata , M1_AXI_rdata , M2_AXI_rdata; + wire M0_AXI_rready , M1_AXI_rready , M2_AXI_rready; + wire [1:0] M0_AXI_rresp , M1_AXI_rresp , M2_AXI_rresp; + wire M0_AXI_rvalid , M1_AXI_rvalid , M2_AXI_rvalid; + wire [31:0] M0_AXI_wdata , M1_AXI_wdata , M2_AXI_wdata; + wire M0_AXI_wready , M1_AXI_wready , M2_AXI_wready; + wire [3:0] M0_AXI_wstrb , M1_AXI_wstrb , M2_AXI_wstrb; + wire M0_AXI_wvalid , M1_AXI_wvalid , M2_AXI_wvalid; + + wire [31:0] M3_AXI_araddr , M4_AXI_araddr , M5_AXI_araddr; + wire [2:0] M3_AXI_arprot , M4_AXI_arprot , M5_AXI_arprot; + wire M3_AXI_arready, M4_AXI_arready, M5_AXI_arready; + wire M3_AXI_arvalid, M4_AXI_arvalid, M5_AXI_arvalid; + wire [31:0] M3_AXI_awaddr , M4_AXI_awaddr , M5_AXI_awaddr; + wire [2:0] M3_AXI_awprot , M4_AXI_awprot , M5_AXI_awprot; + wire M3_AXI_awready, M4_AXI_awready, M5_AXI_awready; + wire M3_AXI_awvalid, M4_AXI_awvalid, M5_AXI_awvalid; + wire M3_AXI_bready , M4_AXI_bready , M5_AXI_bready; + wire [1:0] M3_AXI_bresp , M4_AXI_bresp , M5_AXI_bresp; + wire M3_AXI_bvalid , M4_AXI_bvalid , M5_AXI_bvalid; + wire [31:0] M3_AXI_rdata , M4_AXI_rdata , M5_AXI_rdata; + wire M3_AXI_rready , M4_AXI_rready , M5_AXI_rready; + wire [1:0] M3_AXI_rresp , M4_AXI_rresp , M5_AXI_rresp; + wire M3_AXI_rvalid , M4_AXI_rvalid , M5_AXI_rvalid; + wire [31:0] M3_AXI_wdata , M4_AXI_wdata , M5_AXI_wdata; + wire M3_AXI_wready , M4_AXI_wready , M5_AXI_wready; + wire [3:0] M3_AXI_wstrb , M4_AXI_wstrb , M5_AXI_wstrb; + wire M3_AXI_wvalid , M4_AXI_wvalid , M5_AXI_wvalid; + + wire [31:0] S00_AXI_araddr; + wire [2:0] S00_AXI_arprot /*= 3'b010*/; + wire S00_AXI_arready; + wire S00_AXI_arvalid; + wire [31:0] S00_AXI_awaddr; + wire [2:0] S00_AXI_awprot /*= 3'b010*/; + wire S00_AXI_awready; + wire S00_AXI_awvalid; + wire S00_AXI_bready; + wire [1:0] S00_AXI_bresp; + wire S00_AXI_bvalid; + wire [31:0] S00_AXI_rdata; + wire S00_AXI_rready; + wire [1:0] S00_AXI_rresp; + wire S00_AXI_rvalid; + wire [31:0] S00_AXI_wdata; + wire S00_AXI_wready; + wire [3:0] S00_AXI_wstrb; + wire S00_AXI_wvalid; + + // Network Interfaces + wire axi_aresetn; + wire axi_clk; + wire [10:0] counter0,counter1,counter2,counter3,counter4; + wire activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0; + wire activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0; + wire barrier_req0, barrier_req1, barrier_req2, barrier_req3, barrier_req4; + wire barrier_proceed; + wire activity_trans_sim; + wire activity_trans_log; + wire barrier_req_trans; + + //--------------------------------------------------------------------- + // Misc + //--------------------------------------------------------------------- + IBUF sys_reset_n_ibuf ( .O(sys_rst_n_c), .I(sys_reset_n)); + + reg [15:0] sys_clk_count; + always @(posedge ~sys_clk) + sys_clk_count <= sys_clk_count + 1'b1; + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_inst ( + .O (sys_clk), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (pci_clk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (pci_clk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_core_inst ( + .O (clk_200), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (fpga_sysclk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (fpga_sysclk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + // drive AXI-lite from sys_clk & sys_rst + assign axi_clk = sys_clk; + assign axi_aresetn = sys_rst_n_c; + +//-----------------------------------------------------------------------------------------------// +// Network modules // +//-----------------------------------------------------------------------------------------------// + + nf_datapath + #( + // Master AXI Stream Data Width + .C_M_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_S_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_M_AXIS_TUSER_WIDTH (128), + .C_S_AXIS_TUSER_WIDTH (128), + .NUM_QUEUES (5) + ) + nf_datapath_0 + ( + .axis_aclk (clk_200), + .axis_resetn (sys_rst_n_c), + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + + // Slave Stream Ports (interface from Rx queues) + .s_axis_0_tdata (axis_i_0_tdata), + .s_axis_0_tkeep (axis_i_0_tkeep), + .s_axis_0_tuser (axis_i_0_tuser), + .s_axis_0_tvalid (axis_i_0_tvalid), + .s_axis_0_tready (axis_i_0_tready), + .s_axis_0_tlast (axis_i_0_tlast), + .s_axis_1_tdata (axis_i_1_tdata), + .s_axis_1_tkeep (axis_i_1_tkeep), + .s_axis_1_tuser (axis_i_1_tuser), + .s_axis_1_tvalid (axis_i_1_tvalid), + .s_axis_1_tready (axis_i_1_tready), + .s_axis_1_tlast (axis_i_1_tlast), + .s_axis_2_tdata (axis_dma_i_tdata), + .s_axis_2_tkeep (axis_dma_i_tkeep), + .s_axis_2_tuser (axis_dma_i_tuser), + .s_axis_2_tvalid (axis_dma_i_tvalid), + .s_axis_2_tready (axis_dma_i_tready), + .s_axis_2_tlast (axis_dma_i_tlast), + + + // Master Stream Ports (interface to TX queues) + .m_axis_0_tdata (axis_o_0_tdata), + .m_axis_0_tkeep (axis_o_0_tkeep), + .m_axis_0_tuser (axis_o_0_tuser), + .m_axis_0_tvalid (axis_o_0_tvalid), + .m_axis_0_tready (axis_o_0_tready), + .m_axis_0_tlast (axis_o_0_tlast), + .m_axis_1_tdata (axis_o_1_tdata), + .m_axis_1_tkeep (axis_o_1_tkeep), + .m_axis_1_tuser (axis_o_1_tuser), + .m_axis_1_tvalid (axis_o_1_tvalid), + .m_axis_1_tready (axis_o_1_tready), + .m_axis_1_tlast (axis_o_1_tlast), + .m_axis_2_tdata (axis_dma_o_tdata), + .m_axis_2_tkeep (axis_dma_o_tkeep), + .m_axis_2_tuser (axis_dma_o_tuser), + .m_axis_2_tvalid (axis_dma_o_tvalid), + .m_axis_2_tready (axis_dma_o_tready), + .m_axis_2_tlast (axis_dma_o_tlast), + + //AXI-Lite interface + .S0_AXI_AWADDR (M0_AXI_awaddr), + .S0_AXI_AWVALID (M0_AXI_awvalid), + .S0_AXI_WDATA (M0_AXI_wdata), + .S0_AXI_WSTRB (M0_AXI_wstrb), + .S0_AXI_WVALID (M0_AXI_wvalid), + .S0_AXI_BREADY (M0_AXI_bready), + .S0_AXI_ARADDR (M0_AXI_araddr), + .S0_AXI_ARVALID (M0_AXI_arvalid), + .S0_AXI_RREADY (M0_AXI_rready), + .S0_AXI_ARREADY (M0_AXI_arready), + .S0_AXI_RDATA (M0_AXI_rdata), + .S0_AXI_RRESP (M0_AXI_rresp), + .S0_AXI_RVALID (M0_AXI_rvalid), + .S0_AXI_WREADY (M0_AXI_wready), + .S0_AXI_BRESP (M0_AXI_bresp), + .S0_AXI_BVALID (M0_AXI_bvalid), + .S0_AXI_AWREADY (M0_AXI_awready), + + .S1_AXI_AWADDR (M1_AXI_awaddr), + .S1_AXI_AWVALID (M1_AXI_awvalid), + .S1_AXI_WDATA (M1_AXI_wdata), + .S1_AXI_WSTRB (M1_AXI_wstrb), + .S1_AXI_WVALID (M1_AXI_wvalid), + .S1_AXI_BREADY (M1_AXI_bready), + .S1_AXI_ARADDR (M1_AXI_araddr), + .S1_AXI_ARVALID (M1_AXI_arvalid), + .S1_AXI_RREADY (M1_AXI_rready), + .S1_AXI_ARREADY (M1_AXI_arready), + .S1_AXI_RDATA (M1_AXI_rdata), + .S1_AXI_RRESP (M1_AXI_rresp), + .S1_AXI_RVALID (M1_AXI_rvalid), + .S1_AXI_WREADY (M1_AXI_wready), + .S1_AXI_BRESP (M1_AXI_bresp), + .S1_AXI_BVALID (M1_AXI_bvalid), + .S1_AXI_AWREADY (M1_AXI_awready), + + .S2_AXI_AWADDR (M2_AXI_awaddr), + .S2_AXI_AWVALID (M2_AXI_awvalid), + .S2_AXI_WDATA (M2_AXI_wdata), + .S2_AXI_WSTRB (M2_AXI_wstrb), + .S2_AXI_WVALID (M2_AXI_wvalid), + .S2_AXI_BREADY (M2_AXI_bready), + .S2_AXI_ARADDR (M2_AXI_araddr), + .S2_AXI_ARVALID (M2_AXI_arvalid), + .S2_AXI_RREADY (M2_AXI_rready), + .S2_AXI_ARREADY (M2_AXI_arready), + .S2_AXI_RDATA (M2_AXI_rdata), + .S2_AXI_RRESP (M2_AXI_rresp), + .S2_AXI_RVALID (M2_AXI_rvalid), + .S2_AXI_WREADY (M2_AXI_wready), + .S2_AXI_BRESP (M2_AXI_bresp), + .S2_AXI_BVALID (M2_AXI_bvalid), + .S2_AXI_AWREADY (M2_AXI_awready) + ); + + axis_sim_stim_ip0 axis_sim_stim_0 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_0_tdata), + .M_AXIS_TKEEP (p_axis_i_0_tkeep), + .M_AXIS_TUSER (p_axis_i_0_tuser), + .M_AXIS_TVALID (p_axis_i_0_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_0_tlast), + + .counter (counter0), + .activity_stim (activity_stim0), + .barrier_req (barrier_req0), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip1 axis_sim_stim_1 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_1_tdata), + .M_AXIS_TKEEP (p_axis_i_1_tkeep), + .M_AXIS_TUSER (p_axis_i_1_tuser), + .M_AXIS_TVALID (p_axis_i_1_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_1_tlast), + + .counter (counter1), + .activity_stim (activity_stim1), + .barrier_req (barrier_req1), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip2 axis_sim_stim_2 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_dma_i_tdata), + .M_AXIS_TKEEP (p_axis_dma_i_tkeep), + .M_AXIS_TUSER (p_axis_dma_i_tuser), + .M_AXIS_TVALID (p_axis_dma_i_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_dma_i_tlast), + + .counter (counter4), + .activity_stim (activity_stim4), + .barrier_req (barrier_req4), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_record_ip0 axis_sim_record_0 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_0_tdata), + .s_axis_tkeep (p_axis_o_0_tkeep), + .s_axis_tuser (p_axis_o_0_tuser), + .s_axis_tvalid(p_axis_o_0_tvalid), + .s_axis_tready(p_axis_o_0_tready), + .s_axis_tlast (p_axis_o_0_tlast), + + .counter (counter0), + .activity_rec(activity_rec0) + ); + + axis_sim_record_ip1 axis_sim_record_1 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_1_tdata), + .s_axis_tkeep (p_axis_o_1_tkeep), + .s_axis_tuser (p_axis_o_1_tuser), + .s_axis_tvalid(p_axis_o_1_tvalid), + .s_axis_tready(p_axis_o_1_tready), + .s_axis_tlast (p_axis_o_1_tlast), + + .counter (counter1), + .activity_rec(activity_rec1) + ); + + axis_sim_record_ip2 axis_sim_record_2 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_dma_o_tdata), + .s_axis_tkeep (p_axis_dma_o_tkeep), + .s_axis_tuser (p_axis_dma_o_tuser), + .s_axis_tvalid(p_axis_dma_o_tvalid), + .s_axis_tready(p_axis_dma_o_tready), + .s_axis_tlast (p_axis_dma_o_tlast), + + .counter (counter4), + .activity_rec(activity_rec4) + ); + + nf_mac_attachment_dma_ip u_nf_attachment_dma ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_dma_i_tdata), + .m_axis_mac_tkeep (p_axis_dma_i_tkeep), + .m_axis_mac_tvalid (p_axis_dma_i_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_dma_i_tuser), + .m_axis_mac_tlast (p_axis_dma_i_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_dma_o_tdata), + .s_axis_mac_tkeep (p_axis_dma_o_tkeep), + .s_axis_mac_tvalid (p_axis_dma_o_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_dma_o_tuser), + .s_axis_mac_tlast (p_axis_dma_o_tlast), + .s_axis_mac_tready (p_axis_dma_o_tready), + + // TX/RX DATA channels + .interface_number (8'd0), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_dma_o_tdata), + .s_axis_pipe_tkeep (axis_dma_o_tkeep), + .s_axis_pipe_tlast (axis_dma_o_tlast), + .s_axis_pipe_tuser (axis_dma_o_tuser), + .s_axis_pipe_tvalid (axis_dma_o_tvalid), + .s_axis_pipe_tready (axis_dma_o_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_dma_i_tdata), + .m_axis_pipe_tkeep (axis_dma_i_tkeep), + .m_axis_pipe_tlast (axis_dma_i_tlast), + .m_axis_pipe_tuser (axis_dma_i_tuser), + .m_axis_pipe_tvalid (axis_dma_i_tvalid), + .m_axis_pipe_tready (axis_dma_i_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_0 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_0_tdata), + .m_axis_mac_tkeep (p_axis_i_0_tkeep), + .m_axis_mac_tvalid (p_axis_i_0_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_0_tuser), + .m_axis_mac_tlast (p_axis_i_0_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_0_tdata), + .s_axis_mac_tkeep (p_axis_o_0_tkeep), + .s_axis_mac_tvalid (p_axis_o_0_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_o_0_tuser), + .s_axis_mac_tlast (p_axis_o_0_tlast), + .s_axis_mac_tready (p_axis_o_0_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0001), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_0_tdata), + .s_axis_pipe_tkeep (axis_o_0_tkeep), + .s_axis_pipe_tlast (axis_o_0_tlast), + .s_axis_pipe_tuser (axis_o_0_tuser), + .s_axis_pipe_tvalid (axis_o_0_tvalid), + .s_axis_pipe_tready (axis_o_0_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_0_tdata), + .m_axis_pipe_tkeep (axis_i_0_tkeep), + .m_axis_pipe_tlast (axis_i_0_tlast), + .m_axis_pipe_tuser (axis_i_0_tuser), + .m_axis_pipe_tvalid (axis_i_0_tvalid), + .m_axis_pipe_tready (axis_i_0_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_1 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_1_tdata), + .m_axis_mac_tkeep (p_axis_i_1_tkeep), + .m_axis_mac_tvalid (p_axis_i_1_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_1_tuser), + .m_axis_mac_tlast (p_axis_i_1_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_1_tdata), + .s_axis_mac_tkeep (p_axis_o_1_tkeep), + .s_axis_mac_tvalid (p_axis_o_1_tvalid), + .s_axis_mac_tuser_err (p_axis_o_1_tuser), //underrun + .s_axis_mac_tuser (p_axis_o_1_tuser), + .s_axis_mac_tlast (p_axis_o_1_tlast), + .s_axis_mac_tready (p_axis_o_1_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0100), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_1_tdata), + .s_axis_pipe_tkeep (axis_o_1_tkeep), + .s_axis_pipe_tlast (axis_o_1_tlast), + .s_axis_pipe_tuser (axis_o_1_tuser), + .s_axis_pipe_tvalid (axis_o_1_tvalid), + .s_axis_pipe_tready (axis_o_1_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_1_tdata), + .m_axis_pipe_tkeep (axis_i_1_tkeep), + .m_axis_pipe_tlast (axis_i_1_tlast), + .m_axis_pipe_tuser (axis_i_1_tuser), + .m_axis_pipe_tvalid (axis_i_1_tvalid), + .m_axis_pipe_tready (axis_i_1_tready) + ); + + axi_crossbar_0 u_interconnect( + .aclk (axi_clk), + .aresetn (axi_aresetn), + .s_axi_awaddr (S00_AXI_awaddr), + .s_axi_awprot (3'b010), + .s_axi_awvalid (S00_AXI_awvalid), + .s_axi_awready (S00_AXI_awready), + .s_axi_wdata (S00_AXI_wdata ), + .s_axi_wstrb (4'hf), + .s_axi_wvalid (S00_AXI_wvalid ), + .s_axi_wready (S00_AXI_wready ), + .s_axi_bresp (S00_AXI_bresp ), + .s_axi_bvalid (S00_AXI_bvalid ), + .s_axi_bready (S00_AXI_bready ), + .s_axi_araddr (S00_AXI_araddr[31:0]), + .s_axi_arprot (3'b010), + .s_axi_arvalid (S00_AXI_arvalid ), + .s_axi_arready (S00_AXI_arready ), + .s_axi_rdata (S00_AXI_rdata ), + .s_axi_rresp (S00_AXI_rresp ), + .s_axi_rvalid (S00_AXI_rvalid ), + .s_axi_rready (S00_AXI_rready ), + .m_axi_awaddr ({M2_AXI_awaddr[31:0] ,M1_AXI_awaddr[31:0] ,M0_AXI_awaddr[31:0] }), + .m_axi_awprot (), + .m_axi_awvalid ({M2_AXI_awvalid,M1_AXI_awvalid,M0_AXI_awvalid}), + .m_axi_awready ({M2_AXI_awready,M1_AXI_awready,M0_AXI_awready}), + .m_axi_wdata ({M2_AXI_wdata ,M1_AXI_wdata ,M0_AXI_wdata }), + .m_axi_wstrb ({M2_AXI_wstrb ,M1_AXI_wstrb ,M0_AXI_wstrb }), + .m_axi_wvalid ({M2_AXI_wvalid ,M1_AXI_wvalid ,M0_AXI_wvalid }), + .m_axi_wready ({M2_AXI_wready ,M1_AXI_wready ,M0_AXI_wready }), + .m_axi_bresp ({M2_AXI_bresp ,M1_AXI_bresp ,M0_AXI_bresp }), + .m_axi_bvalid ({M2_AXI_bvalid ,M1_AXI_bvalid ,M0_AXI_bvalid }), + .m_axi_bready ({M2_AXI_bready ,M1_AXI_bready ,M0_AXI_bready }), + .m_axi_araddr ({M2_AXI_araddr ,M1_AXI_araddr ,M0_AXI_araddr }), + .m_axi_arprot (), + .m_axi_arvalid ({M2_AXI_arvalid,M1_AXI_arvalid,M0_AXI_arvalid}), + .m_axi_arready ({M2_AXI_arready,M1_AXI_arready,M0_AXI_arready}), + .m_axi_rdata ({M2_AXI_rdata ,M1_AXI_rdata ,M0_AXI_rdata }), + .m_axi_rresp ({M2_AXI_rresp ,M1_AXI_rresp ,M0_AXI_rresp }), + .m_axi_rvalid ({M2_AXI_rvalid ,M1_AXI_rvalid ,M0_AXI_rvalid }), + .m_axi_rready ({M2_AXI_rready ,M1_AXI_rready ,M0_AXI_rready }) + ); + + + axi_sim_transactor_ip axi_sim_transactor_i ( + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + //AXI Write address channel + .M_AXI_AWADDR (S00_AXI_awaddr), + .M_AXI_AWVALID (S00_AXI_awvalid), + .M_AXI_AWREADY (S00_AXI_awready), + // AXI Write data channel + .M_AXI_WDATA (S00_AXI_wdata), + .M_AXI_WSTRB (S00_AXI_wstrb), + .M_AXI_WVALID (S00_AXI_wvalid), + .M_AXI_WREADY (S00_AXI_wready), + //AXI Write response channel + .M_AXI_BRESP (S00_AXI_bresp), + .M_AXI_BVALID (S00_AXI_bvalid), + .M_AXI_BREADY (S00_AXI_bready), + //AXI Read address channel + .M_AXI_ARADDR (S00_AXI_araddr), + .M_AXI_ARVALID (S00_AXI_arvalid), + .M_AXI_ARREADY (S00_AXI_arready), + //AXI Read data & response channel + .M_AXI_RDATA (S00_AXI_rdata), + .M_AXI_RRESP (S00_AXI_rresp), + .M_AXI_RVALID (S00_AXI_rvalid), + .M_AXI_RREADY (S00_AXI_rready), + + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + + barrier_ip barrier_i ( + .activity_stim ({activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0}), + .activity_rec ({activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0}), + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req ({barrier_req4, barrier_req3, barrier_req2, barrier_req1, barrier_req0}), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + +endmodule + diff --git a/hw/projects/reference_switch/hw/hdl/top_tb.v b/hw/projects/reference_switch/hw/hdl/top_tb.v new file mode 100644 index 0000000..a57d63a --- /dev/null +++ b/hw/projects/reference_switch/hw/hdl/top_tb.v @@ -0,0 +1,180 @@ +//- +// Copyright (c) 2015 Noa Zilberman +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// File: +// top_tb.v +// +// Module: +// top +// +// Author: Noa Zilberman +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ns / 100ps + + module top_tb # ( + parameter PL_SIM_FAST_LINK_TRAINING = "TRUE", // Simulation Speedup + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32, + parameter integer USER_CLK2_FREQ = 4, + parameter REF_CLK_FREQ = 0, // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz + parameter AXISTEN_IF_RQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_RC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_ENABLE_CLIENT_TAG = 0, + parameter AXISTEN_IF_RQ_PARITY_CHECK = 0, + parameter AXISTEN_IF_CC_PARITY_CHECK = 0, + parameter AXISTEN_IF_MC_RX_STRADDLE = 0, + parameter AXISTEN_IF_ENABLE_RX_MSG_INTFC = 0, + parameter [17:0] AXISTEN_IF_ENABLE_MSG_ROUTE = 18'h2FFFF +) ( + +); + + parameter PCIE_PERIOD = 4.0; + parameter XPHY_PERIOD = 6.4; + parameter real CORE_PERIOD = 2.941; + + localparam TCQ = 1; + localparam BAR0AXI = 32'h40000000; + localparam BAR1AXI = 32'h10000000; + localparam BAR2AXI = 32'h20000000; + localparam BAR3AXI = 32'h30000000; + localparam BAR4AXI = 32'h40000000; + localparam BAR5AXI = 32'h50000000; + localparam BAR0SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR1SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR2SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR3SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR4SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR5SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam throttle_percent = 50; + + reg sys_reset_n; + + reg sys_clk; + wire sys_clkp,sys_clkn; + reg xphy_clk; + wire xphy_refclk_p,xphy_refclk_n; + reg clk_ref; + wire clk_ref_p,clk_ref_n; + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + + + top_sim # ( + .PL_SIM_FAST_LINK_TRAINING (PL_SIM_FAST_LINK_TRAINING ), + .C_DATA_WIDTH (C_DATA_WIDTH ), + .KEEP_WIDTH (KEEP_WIDTH ), + .USER_CLK2_FREQ (USER_CLK2_FREQ ), + .REF_CLK_FREQ (REF_CLK_FREQ ), + .AXISTEN_IF_RQ_ALIGNMENT_MODE (AXISTEN_IF_RQ_ALIGNMENT_MODE ), + .AXISTEN_IF_CC_ALIGNMENT_MODE (AXISTEN_IF_CC_ALIGNMENT_MODE ), + .AXISTEN_IF_CQ_ALIGNMENT_MODE (AXISTEN_IF_CQ_ALIGNMENT_MODE ), + .AXISTEN_IF_RC_ALIGNMENT_MODE (AXISTEN_IF_RC_ALIGNMENT_MODE ), + .AXISTEN_IF_ENABLE_CLIENT_TAG (AXISTEN_IF_ENABLE_CLIENT_TAG ), + .AXISTEN_IF_RQ_PARITY_CHECK (AXISTEN_IF_RQ_PARITY_CHECK ), + .AXISTEN_IF_CC_PARITY_CHECK (AXISTEN_IF_CC_PARITY_CHECK ), + .AXISTEN_IF_MC_RX_STRADDLE (AXISTEN_IF_MC_RX_STRADDLE ), + .AXISTEN_IF_ENABLE_RX_MSG_INTFC (AXISTEN_IF_ENABLE_RX_MSG_INTFC ), + .AXISTEN_IF_ENABLE_MSG_ROUTE (AXISTEN_IF_ENABLE_MSG_ROUTE ) + ) top_sim ( + + //PCI Express + .pcie_rxn(pcie_7x_mgt_rxn), + .pcie_rxp(pcie_7x_mgt_rxp), + .pcie_txn(pcie_7x_mgt_txn), + .pcie_txp(pcie_7x_mgt_txp), + //10G Interface + + .qsfp0_rxp(rxp), + .qsfp0_rxn(rxn), + .qsfp0_txp(txp), + .qsfp0_txn(txn), + + // PCIe Clock + .pci_clk_p(sys_clkp), + .pci_clk_n(sys_clkn), + + //200MHz Clock + .fpga_sysclk_p(clk_ref_p), + .fpga_sysclk_n(clk_ref_n), + + // 156.25 MHz clock in + .qsfp_refclk_p (xphy_refclk_p), + .qsfp_refclk_n (xphy_refclk_n), + + .sys_reset_n(sys_reset_n) + ); + +//Reset handling + // Important! polarity here is opposite the one in the actual design + initial begin + sys_reset_n = 1'b0; + #(CORE_PERIOD * 200); + sys_reset_n = 1'b1; + $display("Reset Deasserted"); + end + +//Clock generation + initial begin + sys_clk = 1'b0; + #(PCIE_PERIOD/2); + forever + #(PCIE_PERIOD/2) sys_clk = ~sys_clk; + end + + assign sys_clkp = sys_clk; + assign sys_clkn = ~sys_clk; + + + initial begin + xphy_clk = 1'b0; + #(XPHY_PERIOD/2); + forever + #(XPHY_PERIOD/2) xphy_clk = ~xphy_clk; + end + + assign xphy_refclk_p = xphy_clk; + assign xphy_refclk_n = ~xphy_clk; + + initial begin + clk_ref = 1'b0; + #(CORE_PERIOD/2); + forever + #(CORE_PERIOD/2) clk_ref = ~clk_ref; + end + + assign clk_ref_p = clk_ref; + assign clk_ref_n = ~clk_ref; + +endmodule diff --git a/hw/projects/reference_switch/hw/tcl/export_registers.tcl b/hw/projects/reference_switch/hw/tcl/export_registers.tcl new file mode 100644 index 0000000..6e8f923 --- /dev/null +++ b/hw/projects/reference_switch/hw/tcl/export_registers.tcl @@ -0,0 +1,160 @@ +# +# Copyright (c) 2015 Noa Zilberman, Jingyun Zhang +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# The following list include all the items that are mapped to memory segments +# The structure of each item is as follows { } + +set DEF_LIST { + {INPUT_ARBITER 0 1 input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt} \ + {OUTPUT_QUEUES 0 1 output_queues_v1_0_0/data/output_queues_regs_defines.txt} \ + {OUTPUT_PORT_LOOKUP 0 1 switch_output_port_lookup_v1_0_1/data/output_port_lookup_regs_defines.txt} \ +} + +set target_path $::env(NF_DESIGN_DIR)/test/ +set target_file $target_path/nf_register_defines.h + +if {[file exists ${target_path}] == 0} { + exec mkdir -p ${target_path} +} + +###################################################### +# the following function writes the license header +# into the file +###################################################### + +proc write_header { target_file } { + +# creat a blank header file +# do a fresh rewrite in case the file already exits +file delete -force $target_file +open $target_file "w" +set h_file [open $target_file "w"] + + +puts $h_file "//-" +puts $h_file "// Copyright (c) 2015,2021 University of Cambridge" +puts $h_file "// All rights reserved." +puts $h_file "//" +puts $h_file "// This software was developed by Stanford University and the University of Cambridge Computer Laboratory " +puts $h_file "// under National Science Foundation under Grant No. CNS-0855268," +puts $h_file "// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and" +puts $h_file "// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 (\"MRC2\"), " +puts $h_file "// as part of the DARPA MRC research programme," +puts $h_file "// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project" +puts $h_file "// EP/P025374/1 alongside support from Xilinx Inc." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_START@" +puts $h_file "//" +puts $h_file "// Licensed to NetFPGA C.I.C. (NetFPGA) under one or more contributor" +puts $h_file "// license agreements. See the NOTICE file distributed with this work for" +puts $h_file "// additional information regarding copyright ownership. NetFPGA licenses this" +puts $h_file "// file to you under the NetFPGA Hardware-Software License, Version 1.0 (the" +puts $h_file "// \"License\"); you may not use this file except in compliance with the" +puts $h_file "// License. You may obtain a copy of the License at:" +puts $h_file "//" +puts $h_file "// http://www.netfpga-cic.org" +puts $h_file "//" +puts $h_file "// Unless required by applicable law or agreed to in writing, Work distributed" +puts $h_file "// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR" +puts $h_file "// CONDITIONS OF ANY KIND, either express or implied. See the License for the" +puts $h_file "// specific language governing permissions and limitations under the License." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_END@" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "// This is an automatically generated header definitions file" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "" + +close $h_file + +}; # end of proc write_header + + +###################################################### +# the following function writes all the information +# of a specific core into a file +###################################################### + +proc write_core {target_file prefix id has_registers lib_name} { + + +set h_file [open $target_file "a"] + +#First, read the memory map information from the reference_project defines file +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ + + +set baseaddr [set $prefix\_BASEADDR] +set highaddr [set $prefix\_HIGHADDR] +set sizeaddr [set $prefix\_SIZEADDR] + +puts $h_file "//######################################################" +puts $h_file "//# Definitions for $prefix" +puts $h_file "//######################################################" + +puts $h_file "#define NFPLUS_$prefix\_BASEADDR $baseaddr" +puts $h_file "#define NFPLUS_$prefix\_HIGHADDR $highaddr" +puts $h_file "#define NFPLUS_$prefix\_SIZEADDR $sizeaddr" +puts $h_file "" + +#Second, read the registers information from the library defines file +if $has_registers { + set lib_path "$public_repo_dir/std/$lib_name" + set regs_h_define_file $lib_path + set regs_h_define_file_read [open $regs_h_define_file r] + set regs_h_define_file_data [read $regs_h_define_file_read] + close $regs_h_define_file_read + set regs_h_define_file_data_line [split $regs_h_define_file_data "\n"] + + foreach read_line $regs_h_define_file_data_line { + if {[regexp "#define" $read_line]} { + puts $h_file "#define NFPLUS_[lindex $read_line 2]\_$id\_[lindex $read_line 3]\_[lindex $read_line 4] [lindex $read_line 5]" + } + } +} +puts $h_file "" +close $h_file +}; # end of proc write_core + + + +###################################################### +# the main function +###################################################### + + + +write_header $target_file + +foreach lib_item $DEF_LIST { + write_core $target_file [lindex $lib_item 0] [lindex $lib_item 1] [lindex $lib_item 2] [lindex $lib_item 3] +} + diff --git a/hw/projects/reference_switch/hw/tcl/reference_switch.tcl b/hw/projects/reference_switch/hw/tcl/reference_switch.tcl new file mode 100644 index 0000000..6c10346 --- /dev/null +++ b/hw/projects/reference_switch/hw/tcl/reference_switch.tcl @@ -0,0 +1,417 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) + +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib +set repo_dir ./ip_repo +set project_constraints "${public_repo_dir}/common/constraints/${board_name}_general.xdc" + +set start_time [exec date +%s] +set_param general.maxThreads 8 +set_param synth.elaboration.rodinMoreOptions "rt::set_parameter max_loop_limit 200000" +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +set datapath_freq_mhz 340 +set opl_bcam_size 16 + +set opl_cam_depth_bits [expr int(log(${opl_bcam_size})/log(2))] +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +if {[string match $board_name "au280"]} { + set_property verilog_define { {BOARD_AU280} {au280} {__synthesis__} } [current_fileset] + set board_param "AU280" +} elseif {[string match $board_name "au250"]} { + set_property verilog_define { {BOARD_AU250} {__synthesis__} } [current_fileset] + set board_param "AU250" +} elseif {[string match $board_name "au200"]} { + set_property verilog_define { {BOARD_AU200} {__synthesis__} } [current_fileset] + set board_param "AU200" +} elseif {[string match $board_name "vcu1525"]} { + set_property verilog_define { {BOARD_VCU1525} {__synthesis__} } [current_fileset] + set board_param "VCU1525" +} +set_property generic "C_NF_DATA_WIDTH=${datapath_width_bit} BOARD=\"${board_param}\"" [current_fileset] + +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] +##################################### +# Project Constraints +##################################### +add_files -fileset constraints -norecurse ${project_constraints} +if {[string match $board_name "au280"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au280_timing.tcl +} elseif {[string match $board_name "au200"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au250_au200_vcu1525_user_timing.tcl +} elseif {[string match $board_name "vcu1525"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au250_au200_vcu1525_user_timing.tcl +} else { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au250_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au250_au200_vcu1525_user_timing.tcl +} +set_property is_enabled true [get_files ${project_constraints}] +set_property constrset constraints [get_runs synth_1] +set_property constrset constraints [get_runs impl_1] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name switch_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name switch_output_port_lookup_ip +set_property CONFIG.C_CAM_LUT_DEPTH_BITS ${opl_cam_depth_bits} [get_ips switch_output_port_lookup_ip] +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips switch_output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips switch_output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files switch_output_port_lookup_ip.xci] +reset_target all [get_ips switch_output_port_lookup_ip] +generate_target all [get_ips switch_output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] + +create_ip -name xilinx_shell -vendor xilinx -library xilinx -module_name xilinx_shell_ip +set_property CONFIG.MAX_PKT_LEN 1518 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_QUEUE 2048 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_PHYS_FUNC 2 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_CMAC_PORT 2 [get_ips xilinx_shell_ip] +set_property generate_synth_checkpoint false [get_files xilinx_shell_ip.xci] +reset_target all [get_ips xilinx_shell_ip] +generate_target all [get_ips xilinx_shell_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000000000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000020000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + +#Add a clock wizard +create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name clk_wiz_1 +if {[string match "${datapath_freq_mhz}" "200"]} { +#200MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {6.000} \ + CONFIG.CLKOUT1_JITTER {119.392} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "250"]} { +#250MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {250.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {1} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {4.750} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.750} \ + CONFIG.CLKOUT1_JITTER {85.152} \ + CONFIG.CLKOUT1_PHASE_ERROR {78.266}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "260"]} { +#260MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {260.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {120.250} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.625} \ + CONFIG.CLKOUT1_JITTER {182.359} \ + CONFIG.CLKOUT1_PHASE_ERROR {351.991}] [get_ips clk_wiz_10] +} elseif {[string match "${datapath_freq_mhz}" "280"]} { +#280MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {280.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {119.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.250} \ + CONFIG.CLKOUT1_JITTER {183.720} \ + CONFIG.CLKOUT1_PHASE_ERROR {357.524}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "300"]} { +#300MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {300.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.000} \ + CONFIG.CLKOUT1_JITTER {111.430} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "320"]} { +#320MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {320.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.750} \ + CONFIG.CLKOUT1_JITTER {110.215} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "340"]} { +#340MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {340.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {119.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.500} \ + CONFIG.CLKOUT1_JITTER {179.007} \ + CONFIG.CLKOUT1_PHASE_ERROR {357.524}] [get_ips clk_wiz_1] +} else { + puts "Error: the specified clock is error" + exit -1 +} +#360MHz clock +#set_property -dict [list \ +# CONFIG.PRIM_IN_FREQ {250.000} \ +# CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {360.000} \ +# CONFIG.CLKIN1_JITTER_PS {40.0} \ +# CONFIG.MMCM_DIVCLK_DIVIDE {25} \ +# CONFIG.MMCM_CLKFBOUT_MULT_F {121.500} \ +# CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ +# CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ +# CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.375} \ +# CONFIG.CLKOUT1_JITTER {171.636} \ +# CONFIG.CLKOUT1_PHASE_ERROR {346.603}] [get_ips clk_wiz_1] +#380MHz clock +#set_property -dict [list \ +# CONFIG.PRIM_IN_FREQ {250.000} \ +# CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {380.000} \ +# CONFIG.CLKIN1_JITTER_PS {40.0} \ +# CONFIG.MMCM_DIVCLK_DIVIDE {1} \ +# CONFIG.MMCM_CLKFBOUT_MULT_F {4.750} \ +# CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ +# CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ +# CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.125} \ +# CONFIG.CLKOUT1_JITTER {78.466} \ +# CONFIG.CLKOUT1_PHASE_ERROR {78.266}] [get_ips clk_wiz_1] +#400MHz clock +#set_property -dict [list \ +# CONFIG.PRIM_IN_FREQ {250.000} \ +# CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {400.000} \ +# CONFIG.CLKIN1_JITTER_PS {40.0} \ +# CONFIG.MMCM_DIVCLK_DIVIDE {5} \ +# CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ +# CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ +# CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ +# CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.000} \ +# CONFIG.CLKOUT1_JITTER {106.119} \ +# CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +set_property generate_synth_checkpoint false [get_files clk_wiz_1.xci] +reset_target all [get_ips clk_wiz_1] +generate_target all [get_ips clk_wiz_1] + +read_verilog "./hdl/nf_datapath.v" +read_verilog -sv "${public_repo_dir}/common/hdl/top_wrapper.sv" +read_verilog -sv "${public_repo_dir}/common/hdl/nf_attachment.sv" +read_verilog "${public_repo_dir}/common/hdl/top.v" + +#Setting Synthesis options +create_run -flow {Vivado Synthesis 2020} synth +set_property write_incremental_synth_checkpoint true [get_runs synth_1] +set_property AUTO_INCREMENTAL_CHECKPOINT 1 [get_runs synth_1] +#Setting Implementation options +create_run impl -parent_run synth -flow {Vivado Implementation 2020} +set_property strategy Performance_Explore [get_runs impl_1] +set_property steps.phys_opt_design.is_enabled true [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AlternateFlowWithRetiming [get_runs impl_1] +set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE ExploreWithHoldFix [get_runs impl_1] +set_property STEPS.PLACE_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.is_enabled true [get_runs impl_1] + +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +# The following implementation options will increase runtime, but get the best timing results +set_property SEVERITY {Warning} [get_drc_checks UCIO-1] +launch_runs synth +wait_on_run synth +launch_runs impl_1 +wait_on_run impl_1 +open_checkpoint project/${design}.runs/impl_1/top_postroute_physopt.dcp + +if {![file exists "../bitfiles"]} { + file mkdir "../bitfiles" +} +write_bitstream -force ../bitfiles/${design}_${board_name}.bit +write_debug_probes -file ../bitfiles/${design}_${board_name}.ltx -force + +# -- For Report -- +set end_time [exec date +%s] +set elapsed_time [expr ${end_time} - ${start_time}] +if {[catch {exec grep -A 4 "VIOLAT" project/${design}.runs/impl_1/top_timing_summary_postroute_physopted.rpt} timing_report_data]} { + set timing_report "Met" + set timing_report_data "" +} else { + set timing_report "VIOLATED" +} +puts " --- Report : ${design} for ${board_name} --- " +puts " Synth time : ${elapsed_time}" +puts " Timing Closure: ${timing_report}" +puts "${timing_report_data}" + +exit + diff --git a/hw/projects/reference_switch/hw/tcl/reference_switch_defines.tcl b/hw/projects/reference_switch/hw/tcl/reference_switch_defines.tcl new file mode 100644 index 0000000..75e1d79 --- /dev/null +++ b/hw/projects/reference_switch/hw/tcl/reference_switch_defines.tcl @@ -0,0 +1,81 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +####################### +# Segments Assignment # +####################### +#M00 +set M00_BASEADDR 0x00010000 +set M00_HIGHADDR 0x00010FFF +set M00_SIZEADDR 0x1000 + +#M01 +set M01_BASEADDR 0x00020000 +set M01_HIGHADDR 0x00020FFF +set M01_SIZEADDR 0x1000 + +#M02 +set M02_BASEADDR 0x00030000 +set M02_HIGHADDR 0x00030FFF +set M02_SIZEADDR 0x1000 + +##M03 +#set M03_BASEADDR 0x44030000 +#set M03_HIGHADDR 0x44030FFF +#set M03_SIZEADDR 0x1000 +# + +####################### +# IP_ASSIGNMENT # +####################### +# Note that physical connectivity must match this mapping + +##IDENTIFIER base address and size +#set IDENTIFIER_BASEADDR $M00_BASEADDR +#set IDENTIFIER_HIGHADDR $M00_HIGHADDR +#set IDENTIFIER_SIZEADDR $M00_SIZEADDR + + +#INPUT ARBITER base address and size +set INPUT_ARBITER_BASEADDR $M00_BASEADDR +set INPUT_ARBITER_HIGHADDR $M00_HIGHADDR +set INPUT_ARBITER_SIZEADDR $M00_SIZEADDR + +#OUTPUT_QUEUES base address and size +set OUTPUT_QUEUES_BASEADDR $M02_BASEADDR +set OUTPUT_QUEUES_HIGHADDR $M02_HIGHADDR +set OUTPUT_QUEUES_SIZEADDR $M02_SIZEADDR + +#OUPUT_PORT_LOOKUP base address and size +set OUTPUT_PORT_LOOKUP_BASEADDR $M01_BASEADDR +set OUTPUT_PORT_LOOKUP_HIGHADDR $M01_HIGHADDR +set OUTPUT_PORT_LOOKUP_SIZEADDR $M01_SIZEADDR + diff --git a/hw/projects/reference_switch/hw/tcl/reference_switch_sim.tcl b/hw/projects/reference_switch/hw/tcl/reference_switch_sim.tcl new file mode 100644 index 0000000..152b5db --- /dev/null +++ b/hw/projects/reference_switch/hw/tcl/reference_switch_sim.tcl @@ -0,0 +1,253 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top_sim +set sim_top top_tb +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) + +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ +set repo_dir ./ip_repo +set project_constraints ./constraints/${board_name}_switch.xdc + +set test_name [lindex $argv 0] +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl + +set_param general.maxThreads 8 +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +set opl_bcam_size 16 + +set opl_cam_depth_bits [expr int(log(${opl_bcam_size})/log(2))] +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name switch_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name switch_output_port_lookup_ip +set_property CONFIG.C_CAM_LUT_DEPTH_BITS ${opl_cam_depth_bits} [get_ips switch_output_port_lookup_ip] +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips switch_output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips switch_output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files switch_output_port_lookup_ip.xci] +reset_target all [get_ips switch_output_port_lookup_ip] +generate_target all [get_ips switch_output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] + +create_ip -name barrier -vendor NetFPGA -library NetFPGA -module_name barrier_ip +reset_target all [get_ips barrier_ip] +generate_target all [get_ips barrier_ip] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip0 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_0_log.axi] [get_ips axis_sim_record_ip0] +reset_target all [get_ips axis_sim_record_ip0] +generate_target all [get_ips axis_sim_record_ip0] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip1 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_1_log.axi] [get_ips axis_sim_record_ip1] +reset_target all [get_ips axis_sim_record_ip1] +generate_target all [get_ips axis_sim_record_ip1] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip2 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/dma_0_log.axi] [get_ips axis_sim_record_ip2] +reset_target all [get_ips axis_sim_record_ip2] +generate_target all [get_ips axis_sim_record_ip2] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip0 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_0_stim.axi] [get_ips axis_sim_stim_ip0] +generate_target all [get_ips axis_sim_stim_ip0] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip1 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_1_stim.axi] [get_ips axis_sim_stim_ip1] +generate_target all [get_ips axis_sim_stim_ip1] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip2 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/dma_0_stim.axi] [get_ips axis_sim_stim_ip2] +generate_target all [get_ips axis_sim_stim_ip2] + +create_ip -name axi_sim_transactor -vendor NetFPGA -library NetFPGA -module_name axi_sim_transactor_ip +set_property -dict [list CONFIG.STIM_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.axi CONFIG.EXPECT_FILE $::env(NF_DESIGN_DIR)/test/reg_expect.axi CONFIG.LOG_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.log] [get_ips axi_sim_transactor_ip] +reset_target all [get_ips axi_sim_transactor_ip] +generate_target all [get_ips axi_sim_transactor_ip] + + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000020000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000030000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + + +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/nf_datapath.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_sim.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_tb.v" + + +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 + +set_property top ${sim_top} [get_filesets sim_1] +set_property include_dirs ${proj_dir} [get_filesets sim_1] +set_property simulator_language Mixed [current_project] +set_property verilog_define { {SIMULATION=1} } [get_filesets sim_1] +set_property -name xsim.more_options -value {-testplusarg TESTNAME=basic_test} -objects [get_filesets sim_1] +set_property runtime {} [get_filesets sim_1] +set_property target_simulator xsim [current_project] +set_property compxlib.compiled_library_dir {} [current_project] +set_property top_lib xil_defaultlib [get_filesets sim_1] +update_compile_order -fileset sim_1 + +unset env(PYTHONPATH) +unset env(PYTHONHOME) +set env(PYTHONPATH) ".:$::env(NFPLUS_FOLDER)/tools/scripts/:$::env(NFPLUS_FOLDER)/tools/scripts/NFTest" +set output [exec $::env(PYTHON_BNRY) $::env(NF_DESIGN_DIR)/test/${test_name}/run.py] +puts $output + +launch_simulation -simset sim_1 -mode behavioral +run 10us + diff --git a/hw/projects/reference_switch/test/both_learning_sw/run.py b/hw/projects/reference_switch/test/both_learning_sw/run.py new file mode 100755 index 0000000..68a62aa --- /dev/null +++ b/hw/projects/reference_switch/test/both_learning_sw/run.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_switch import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + + +if isHW(): + # Clearing the LUT_HIT and LUT_MISS by asserting the reset_counters + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x101) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + + # Reset the switch table lookup counters (value is reset every time is read) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT()) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS()) + +nftest_start() + + +routerMAC = [] +routerIP = [] +for i in range(2): + routerMAC.append("00:0a:35:03:00:0%d"%(i+1)) + routerIP.append("192.168.%s.40"%i) + +num_broadcast = 10 + +pkts = [] +pkta = [] +for i in range(num_broadcast): + pkt = make_IP_pkt(src_MAC="aa:bb:cc:dd:ee:ff", dst_MAC=routerMAC[0], + src_IP="192.168.0.1", dst_IP="192.168.1.1", pkt_len=512) + + pkt.time = ((i*(1e-8)) + (2e-6)) + pkts.append(pkt) + if isHW(): + nftest_send_phy('nf0', pkt) + nftest_expect_phy('nf1', pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_phy('nf1', pkts) + +nftest_barrier() + +num_normal = 10 + +for i in range(num_normal): + pkt = make_IP_pkt(dst_MAC="aa:bb:cc:dd:ee:ff", src_MAC=routerMAC[1], + src_IP="192.168.0.1", dst_IP="192.168.1.1", pkt_len=512) + pkt.time = (((i+5)*(1e-8)) + (2e-6)) + pkta.append(pkt) + if isHW(): + nftest_send_phy('nf1', pkt) + nftest_expect_phy('nf0', pkt) + +if not isHW(): + nftest_send_phy('nf1', pkta) + nftest_expect_phy('nf0', pkta) + +nftest_barrier() + +if isHW(): + # Now we expect to see the lut_hit and lut_miss registers incremented and we + # verify this by doing a regread_expect + rres1= nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), num_normal) + rres2= nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) + # List containing the return values of the reg_reads + mres=[rres1,rres2] +else: + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), num_normal) # lut_hit + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) # lut_miss + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_switch/test/both_simple_broadcast/run.py b/hw/projects/reference_switch/test/both_simple_broadcast/run.py new file mode 100755 index 0000000..eaeb973 --- /dev/null +++ b/hw/projects/reference_switch/test/both_simple_broadcast/run.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_switch import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + +if isHW(): + # reset_counters (triggered by Write only event) for all the modules + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x101) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + + # Reset the switch table lookup counters (value is reset every time is read) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT()) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS()) + +nftest_start() + + +routerMAC = [] +routerIP = [] +for i in range(2): + routerMAC.append("00:0a:35:03:00:0%d"%(i+1)) + routerIP.append("192.168.%s.40"%i) + +num_broadcast = 20 + +pkts = [] +for i in range(num_broadcast): + pkt = make_IP_pkt(src_MAC="aa:bb:cc:dd:ee:ff", dst_MAC=routerMAC[0], + EtherType=0x800, src_IP="192.168.0.1", + dst_IP="192.168.1.1", pkt_len=60) + + pkt.time = ((i*(1e-8)) + (2e-6)) + pkts.append(pkt) + if isHW(): + nftest_expect_phy('nf1', pkt) + nftest_send_phy('nf0', pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_phy('nf1', pkts) + +nftest_barrier() + +if isHW(): + # Expecting the LUT_MISS counter to be incremented by 0x14, 20 packets + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) + rres2=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), 0) + mres=[rres1,rres2] +else: + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) # lut_miss + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), 0) # lut_hit + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_switch/test/connections/conn b/hw/projects/reference_switch/test/connections/conn new file mode 100644 index 0000000..0827e9b --- /dev/null +++ b/hw/projects/reference_switch/test/connections/conn @@ -0,0 +1,30 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +nf0:eth1 +nf1:eth2 diff --git a/hw/projects/reference_switch/test/global/setup b/hw/projects/reference_switch/test/global/setup new file mode 100644 index 0000000..1d4cdb9 --- /dev/null +++ b/hw/projects/reference_switch/test/global/setup @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +from subprocess import Popen, PIPE + +proc = Popen(["ifconfig","eth1","192.168.100.1"], stdout=PIPE) +proc = Popen(["ifconfig","eth2","192.168.101.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf0","192.168.200.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf1","192.168.201.1"], stdout=PIPE) diff --git a/hw/projects/reference_switch_lite/bitfiles/README b/hw/projects/reference_switch_lite/bitfiles/README new file mode 100644 index 0000000..61bba95 --- /dev/null +++ b/hw/projects/reference_switch_lite/bitfiles/README @@ -0,0 +1,42 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +Reference Switch Lite bitfile is available for a direct download from the University of Cambridge servers: + +1. Reference Switch Lite (VCU1525) +url: +md5 checksum: + +2. Reference Switch Lite (U200) +url: +md5 checksum: + +3. Reference Switch Lite (U250) +url: +md5 checksum: + +4. Reference Switch Lite (U280) +url: +md5 checksum: diff --git a/hw/projects/reference_switch_lite/hw/Makefile b/hw/projects/reference_switch_lite/hw/Makefile new file mode 100644 index 0000000..854fecb --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/Makefile @@ -0,0 +1,91 @@ +################################################################################ +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +################################################################################ +PROJ = ${NF_PROJECT_NAME} + +all: project + +project: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode batch -source tcl/${PROJ}.tcl; \ + fi + +projectgui: + echo "Create reference project under folder /project"; + @if test -d project/; then \ + echo "Project already exists"; \ + else \ + vivado -mode gui -source tcl/${PROJ}.tcl; \ + fi + +sim: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_${NF_PROJECT_NAME}.py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_${NF_PROJECT_NAME}.py + vivado -mode batch -source ../../../projects/${PROJ}/hw/tcl/${NF_PROJECT_NAME}_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +reg: + vivado -mode batch -source $(NF_DESIGN_DIR)/hw/tcl/export_registers.tcl + cd ../test && cp ../../../../tools/scripts/xparam2regdefines.py . && python xparam2regdefines.py + cd ../test && rm -f xparam2regdefines.py + cd ../test && cp ../../../../tools/scripts/python_parser.py . && python python_parser.py + cd ../test && rm -f python_parser.py && mv reg_defines.py reg_defines_${NF_PROJECT_NAME}.py + +simgui: simclean + cp -f $(NF_DESIGN_DIR)/test/reg_defines_$(NF_PROJECT_NAME).py $(NF_DESIGN_DIR)/test/${TESTNAME}/reg_defines_$(NF_PROJECT_NAME).py + vivado -mode gui -source ../../../projects/${PROJ}/hw/tcl/$(NF_PROJECT_NAME)_sim.tcl -tclargs ${TESTNAME} + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_reconcile_axi_logs.py + $(NFPLUS_FOLDER)/tools/scripts/nf_sim_registers_axi_logs.py + +simclean: + rm -rf proj_* vivado*.* *.*~ .Xil* $(NF_DESIGN_DIR)/hw/ip_repo/ $(NF_DESIGN_DIR)/hw/project/ + rm -rf *[0-9]_{stim,expected,log}.axi + rm -f *.axi + rm -f portconfig.sim + rm -f seed + rm -f *.log + rm -f ../test/Makefile + rm -rf ../test/*.log + rm -rf ../test/*.axi + rm -rf ../test/seed + rm -rf ../test/*.sim + rm -rf ../test/proj_* + rm -rf ../test/ip_repo + rm -f ../test/vivado*.* + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.py + rm -f ../test/*_*_*/reg_defines_${NF_PROJECT_NAME}.pyc + + +clean: + rm -rf project + rm -f vivado* + rm -rf ip_repo diff --git a/hw/projects/reference_switch_lite/hw/constraints/au200_vcu1525_user_timing.tcl b/hw/projects/reference_switch_lite/hw/constraints/au200_vcu1525_user_timing.tcl new file mode 100644 index 0000000..c5c4dfb --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/constraints/au200_vcu1525_user_timing.tcl @@ -0,0 +1,29 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +create_pblock pblock_nf_datapath +add_cells_to_pblock [get_pblocks pblock_nf_datapath] [get_cells -quiet [list nf_datapath_0]] +resize_pblock [get_pblocks pblock_nf_datapath] -add {SLR2} + diff --git a/hw/projects/reference_switch_lite/hw/hdl/nf_datapath.v b/hw/projects/reference_switch_lite/hw/hdl/nf_datapath.v new file mode 100644 index 0000000..05e1051 --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/hdl/nf_datapath.v @@ -0,0 +1,339 @@ +`timescale 1ns / 1ps +//- +// Copyright (c) 2015 Noa Zilberman +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// nf_datapath.v +// +// Module: +// nf_datapath +// +// Author: Noa Zilberman +// +// Description: +// NetFPGA user data path wrapper, wrapping input arbiter, output port lookup and output queues +// +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + + +module nf_datapath #( + //Slave AXI parameters + parameter C_S_AXI_DATA_WIDTH = 32, + parameter C_S_AXI_ADDR_WIDTH = 32, + parameter C_BASEADDR = 32'h00000000, + + // Master AXI Stream Data Width + parameter C_M_AXIS_DATA_WIDTH = 512, + parameter C_S_AXIS_DATA_WIDTH = 512, + parameter C_M_AXIS_TUSER_WIDTH = 128, + parameter C_S_AXIS_TUSER_WIDTH = 128, + parameter NUM_QUEUES=3 +) +( + //Datapath clock + input axis_aclk, + input axis_resetn, + //Registers clock + input axi_aclk, + input axi_resetn, + + // Slave AXI Ports + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_AWADDR, + input S0_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S0_AXI_WSTRB, + input S0_AXI_WVALID, + input S0_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S0_AXI_ARADDR, + input S0_AXI_ARVALID, + input S0_AXI_RREADY, + output S0_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S0_AXI_RDATA, + output [1 : 0] S0_AXI_RRESP, + output S0_AXI_RVALID, + output S0_AXI_WREADY, + output [1 :0] S0_AXI_BRESP, + output S0_AXI_BVALID, + output S0_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_AWADDR, + input S1_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S1_AXI_WSTRB, + input S1_AXI_WVALID, + input S1_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S1_AXI_ARADDR, + input S1_AXI_ARVALID, + input S1_AXI_RREADY, + output S1_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S1_AXI_RDATA, + output [1 : 0] S1_AXI_RRESP, + output S1_AXI_RVALID, + output S1_AXI_WREADY, + output [1 :0] S1_AXI_BRESP, + output S1_AXI_BVALID, + output S1_AXI_AWREADY, + + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_AWADDR, + input S2_AXI_AWVALID, + input [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_WDATA, + input [C_S_AXI_DATA_WIDTH/8-1 : 0] S2_AXI_WSTRB, + input S2_AXI_WVALID, + input S2_AXI_BREADY, + input [C_S_AXI_ADDR_WIDTH-1 : 0] S2_AXI_ARADDR, + input S2_AXI_ARVALID, + input S2_AXI_RREADY, + output S2_AXI_ARREADY, + output [C_S_AXI_DATA_WIDTH-1 : 0] S2_AXI_RDATA, + output [1 : 0] S2_AXI_RRESP, + output S2_AXI_RVALID, + output S2_AXI_WREADY, + output [1 :0] S2_AXI_BRESP, + output S2_AXI_BVALID, + output S2_AXI_AWREADY, + + + // Slave Stream Ports (interface from Rx queues) + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_0_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_0_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_0_tuser, + input s_axis_0_tvalid, + output s_axis_0_tready, + input s_axis_0_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_1_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_1_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_1_tuser, + input s_axis_1_tvalid, + output s_axis_1_tready, + input s_axis_1_tlast, + input [C_S_AXIS_DATA_WIDTH - 1:0] s_axis_2_tdata, + input [((C_S_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_2_tkeep, + input [C_S_AXIS_TUSER_WIDTH-1:0] s_axis_2_tuser, + input s_axis_2_tvalid, + output s_axis_2_tready, + input s_axis_2_tlast, + + + // Master Stream Ports (interface to TX queues) + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_0_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_0_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_0_tuser, + output m_axis_0_tvalid, + input m_axis_0_tready, + output m_axis_0_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_1_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_1_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_1_tuser, + output m_axis_1_tvalid, + input m_axis_1_tready, + output m_axis_1_tlast, + output [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_2_tdata, + output [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_2_tkeep, + output [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_2_tuser, + output m_axis_2_tvalid, + input m_axis_2_tready, + output m_axis_2_tlast +); + + //internal connectivity + + wire [C_M_AXIS_DATA_WIDTH - 1:0] m_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] m_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] m_axis_opl_tuser; + wire m_axis_opl_tvalid; + wire m_axis_opl_tready; + wire m_axis_opl_tlast; + + wire [C_M_AXIS_DATA_WIDTH - 1:0] s_axis_opl_tdata; + wire [((C_M_AXIS_DATA_WIDTH / 8)) - 1:0] s_axis_opl_tkeep; + wire [C_M_AXIS_TUSER_WIDTH-1:0] s_axis_opl_tuser; + wire s_axis_opl_tvalid; + wire s_axis_opl_tready; + wire s_axis_opl_tlast; + + //Input Arbiter + input_arbiter_ip + input_arbiter_v1_0 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (s_axis_opl_tdata), + .m_axis_tkeep (s_axis_opl_tkeep), + .m_axis_tuser (s_axis_opl_tuser), + .m_axis_tvalid(s_axis_opl_tvalid), + .m_axis_tready(s_axis_opl_tready), + .m_axis_tlast (s_axis_opl_tlast), + .s_axis_0_tdata (s_axis_0_tdata), + .s_axis_0_tkeep (s_axis_0_tkeep), + .s_axis_0_tuser (s_axis_0_tuser), + .s_axis_0_tvalid(s_axis_0_tvalid), + .s_axis_0_tready(s_axis_0_tready), + .s_axis_0_tlast (s_axis_0_tlast), + .s_axis_1_tdata (s_axis_1_tdata), + .s_axis_1_tkeep (s_axis_1_tkeep), + .s_axis_1_tuser (s_axis_1_tuser), + .s_axis_1_tvalid(s_axis_1_tvalid), + .s_axis_1_tready(s_axis_1_tready), + .s_axis_1_tlast (s_axis_1_tlast), + .s_axis_2_tdata (s_axis_2_tdata), + .s_axis_2_tkeep (s_axis_2_tkeep), + .s_axis_2_tuser (s_axis_2_tuser), + .s_axis_2_tvalid(s_axis_2_tvalid), + .s_axis_2_tready(s_axis_2_tready), + .s_axis_2_tlast (s_axis_2_tlast), + .S_AXI_AWADDR(S0_AXI_AWADDR), + .S_AXI_AWVALID(S0_AXI_AWVALID), + .S_AXI_WDATA(S0_AXI_WDATA), + .S_AXI_WSTRB(S0_AXI_WSTRB), + .S_AXI_WVALID(S0_AXI_WVALID), + .S_AXI_BREADY(S0_AXI_BREADY), + .S_AXI_ARADDR(S0_AXI_ARADDR), + .S_AXI_ARVALID(S0_AXI_ARVALID), + .S_AXI_RREADY(S0_AXI_RREADY), + .S_AXI_ARREADY(S0_AXI_ARREADY), + .S_AXI_RDATA(S0_AXI_RDATA), + .S_AXI_RRESP(S0_AXI_RRESP), + .S_AXI_RVALID(S0_AXI_RVALID), + .S_AXI_WREADY(S0_AXI_WREADY), + .S_AXI_BRESP(S0_AXI_BRESP), + .S_AXI_BVALID(S0_AXI_BVALID), + .S_AXI_AWREADY(S0_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + + + + //Output Port Lookup + output_port_lookup_ip + output_port_lookup_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .m_axis_tdata (m_axis_opl_tdata), + .m_axis_tkeep (m_axis_opl_tkeep), + .m_axis_tuser (m_axis_opl_tuser), + .m_axis_tvalid(m_axis_opl_tvalid), + .m_axis_tready(m_axis_opl_tready), + .m_axis_tlast (m_axis_opl_tlast), + .s_axis_tdata (s_axis_opl_tdata), + .s_axis_tkeep (s_axis_opl_tkeep), + .s_axis_tuser (s_axis_opl_tuser), + .s_axis_tvalid(s_axis_opl_tvalid), + .s_axis_tready(s_axis_opl_tready), + .s_axis_tlast (s_axis_opl_tlast), + + .S_AXI_AWADDR(S1_AXI_AWADDR), + .S_AXI_AWVALID(S1_AXI_AWVALID), + .S_AXI_WDATA(S1_AXI_WDATA), + .S_AXI_WSTRB(S1_AXI_WSTRB), + .S_AXI_WVALID(S1_AXI_WVALID), + .S_AXI_BREADY(S1_AXI_BREADY), + .S_AXI_ARADDR(S1_AXI_ARADDR), + .S_AXI_ARVALID(S1_AXI_ARVALID), + .S_AXI_RREADY(S1_AXI_RREADY), + .S_AXI_ARREADY(S1_AXI_ARREADY), + .S_AXI_RDATA(S1_AXI_RDATA), + .S_AXI_RRESP(S1_AXI_RRESP), + .S_AXI_RVALID(S1_AXI_RVALID), + .S_AXI_WREADY(S1_AXI_WREADY), + .S_AXI_BRESP(S1_AXI_BRESP), + .S_AXI_BVALID(S1_AXI_BVALID), + .S_AXI_AWREADY(S1_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + + + ); + + + //Output queues + output_queues_ip + bram_output_queues_1 ( + .axis_aclk(axis_aclk), + .axis_resetn(axis_resetn), + .s_axis_tdata (m_axis_opl_tdata), + .s_axis_tkeep (m_axis_opl_tkeep), + .s_axis_tuser (m_axis_opl_tuser), + .s_axis_tvalid (m_axis_opl_tvalid), + .s_axis_tready (m_axis_opl_tready), + .s_axis_tlast (m_axis_opl_tlast), + .m_axis_0_tdata (m_axis_0_tdata), + .m_axis_0_tkeep (m_axis_0_tkeep), + .m_axis_0_tuser (m_axis_0_tuser), + .m_axis_0_tvalid(m_axis_0_tvalid), + .m_axis_0_tready(m_axis_0_tready), + .m_axis_0_tlast (m_axis_0_tlast), + .m_axis_1_tdata (m_axis_1_tdata), + .m_axis_1_tkeep (m_axis_1_tkeep), + .m_axis_1_tuser (m_axis_1_tuser), + .m_axis_1_tvalid(m_axis_1_tvalid), + .m_axis_1_tready(m_axis_1_tready), + .m_axis_1_tlast (m_axis_1_tlast), + .m_axis_2_tdata (m_axis_2_tdata), + .m_axis_2_tkeep (m_axis_2_tkeep), + .m_axis_2_tuser (m_axis_2_tuser), + .m_axis_2_tvalid(m_axis_2_tvalid), + .m_axis_2_tready(m_axis_2_tready), + .m_axis_2_tlast (m_axis_2_tlast), + .bytes_stored(), + .pkt_stored(), + .bytes_removed_0(), + .bytes_removed_1(), + .bytes_removed_2(), + .pkt_removed_0(), + .pkt_removed_1(), + .pkt_removed_2(), + .bytes_dropped(), + .pkt_dropped(), + + .S_AXI_AWADDR(S2_AXI_AWADDR), + .S_AXI_AWVALID(S2_AXI_AWVALID), + .S_AXI_WDATA(S2_AXI_WDATA), + .S_AXI_WSTRB(S2_AXI_WSTRB), + .S_AXI_WVALID(S2_AXI_WVALID), + .S_AXI_BREADY(S2_AXI_BREADY), + .S_AXI_ARADDR(S2_AXI_ARADDR), + .S_AXI_ARVALID(S2_AXI_ARVALID), + .S_AXI_RREADY(S2_AXI_RREADY), + .S_AXI_ARREADY(S2_AXI_ARREADY), + .S_AXI_RDATA(S2_AXI_RDATA), + .S_AXI_RRESP(S2_AXI_RRESP), + .S_AXI_RVALID(S2_AXI_RVALID), + .S_AXI_WREADY(S2_AXI_WREADY), + .S_AXI_BRESP(S2_AXI_BRESP), + .S_AXI_BVALID(S2_AXI_BVALID), + .S_AXI_AWREADY(S2_AXI_AWREADY), + .S_AXI_ACLK (axi_aclk), + .S_AXI_ARESETN(axi_resetn) + ); + + + + +endmodule + diff --git a/hw/projects/reference_switch_lite/hw/hdl/top_sim.v b/hw/projects/reference_switch_lite/hw/hdl/top_sim.v new file mode 100644 index 0000000..14e47a3 --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/hdl/top_sim.v @@ -0,0 +1,677 @@ +//- +// Copyright (c) 2015 Noa Zilberman, Georgina Kalogeridou +// Copyright (c) 2021 Yuta Tokusashi +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme, +// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +// EP/P025374/1 alongside support from Xilinx Inc. +// +// File: +// top_sim.v +// +// Module: +// top +// +// Author: Noa Zilberman, Georgina Kalogeridou +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ps / 100 fs + + module top_sim # ( + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter C_TUSER_WIDTH = 128, // RX/TX interface data width + parameter C_NF_DATA_WIDTH = 1024, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32 + ) ( + +//PCI Express + input [15:0] pcie_rxn, + input [15:0] pcie_rxp, + output [15:0] pcie_txn, + output [15:0] pcie_txp, + //Network Interface + input [3:0] qsfp0_rxp, + input [3:0] qsfp0_rxn, + output [3:0] qsfp0_txp, + output [3:0] qsfp0_txn, + + input [3:0] qsfp1_rxp, + input [3:0] qsfp1_rxn, + output [3:0] qsfp1_txp, + output [3:0] qsfp1_txn, + + // PCIe Clock + input pci_clk_p, + input pci_clk_n, + + //200MHz Clock + input fpga_sysclk_p, + input fpga_sysclk_n, + + // 156.25 MHz clock in + input qsfp_refclk_p, + input qsfp_refclk_n, + + input sys_reset_n +); + + //----------------------------------------------------------------------------------------------------------------// + // System(SYS) Interface // + //----------------------------------------------------------------------------------------------------------------// + + wire sys_clk; + wire clk_200_i; + wire clk_200; + wire sys_rst_n_c; + + //----------------------------------------------------------------------------------------------------------------------- + + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + wire[C_NF_DATA_WIDTH-1:0] axis_i_0_tdata , axis_o_0_tdata; + wire axis_i_0_tvalid, axis_o_0_tvalid; + wire axis_i_0_tlast , axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_0_tuser , axis_o_0_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_0_tkeep , axis_o_0_tkeep; + wire axis_i_0_tready, axis_o_0_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_i_1_tdata , axis_o_1_tdata; + wire axis_i_1_tvalid, axis_o_1_tvalid; + wire axis_i_1_tlast , axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] axis_i_1_tuser , axis_o_1_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_i_1_tkeep , axis_o_1_tkeep; + wire axis_i_1_tready, axis_o_1_tready; + + wire[C_NF_DATA_WIDTH-1:0] axis_dma_i_tdata , axis_dma_o_tdata; + wire axis_dma_i_tvalid, axis_dma_o_tvalid; + wire axis_dma_i_tlast , axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] axis_dma_i_tuser , axis_dma_o_tuser; + wire[C_NF_DATA_WIDTH/8-1:0] axis_dma_i_tkeep , axis_dma_o_tkeep; + wire axis_dma_i_tready, axis_dma_o_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_0_tdata , p_axis_o_0_tdata; + wire p_axis_i_0_tvalid, p_axis_o_0_tvalid; + wire p_axis_i_0_tlast , p_axis_o_0_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_0_tuser , p_axis_o_0_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_0_tkeep , p_axis_o_0_tkeep; + wire p_axis_i_0_tready, p_axis_o_0_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_i_1_tdata , p_axis_o_1_tdata; + wire p_axis_i_1_tvalid, p_axis_o_1_tvalid; + wire p_axis_i_1_tlast , p_axis_o_1_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_i_1_tuser , p_axis_o_1_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_i_1_tkeep , p_axis_o_1_tkeep; + wire p_axis_i_1_tready, p_axis_o_1_tready; + + wire[C_DATA_WIDTH-1:0] p_axis_dma_i_tdata , p_axis_dma_o_tdata; + wire p_axis_dma_i_tvalid, p_axis_dma_o_tvalid; + wire p_axis_dma_i_tlast , p_axis_dma_o_tlast; + wire[C_TUSER_WIDTH-1:0] p_axis_dma_i_tuser , p_axis_dma_o_tuser; + wire[C_DATA_WIDTH/8-1:0] p_axis_dma_i_tkeep , p_axis_dma_o_tkeep; + wire p_axis_dma_i_tready, p_axis_dma_o_tready; + //----------------------------------------------------------------------------------------------------------------// + // AXI Lite interface // + //----------------------------------------------------------------------------------------------------------------// + wire [31:0] M0_AXI_araddr , M1_AXI_araddr , M2_AXI_araddr; + wire [2:0] M0_AXI_arprot , M1_AXI_arprot , M2_AXI_arprot; + wire M0_AXI_arready, M1_AXI_arready, M2_AXI_arready; + wire M0_AXI_arvalid, M1_AXI_arvalid, M2_AXI_arvalid; + wire [31:0] M0_AXI_awaddr , M1_AXI_awaddr , M2_AXI_awaddr; + wire [2:0] M0_AXI_awprot , M1_AXI_awprot , M2_AXI_awprot; + wire M0_AXI_awready, M1_AXI_awready, M2_AXI_awready; + wire M0_AXI_awvalid, M1_AXI_awvalid, M2_AXI_awvalid; + wire M0_AXI_bready , M1_AXI_bready , M2_AXI_bready; + wire [1:0] M0_AXI_bresp , M1_AXI_bresp , M2_AXI_bresp; + wire M0_AXI_bvalid , M1_AXI_bvalid , M2_AXI_bvalid; + wire [31:0] M0_AXI_rdata , M1_AXI_rdata , M2_AXI_rdata; + wire M0_AXI_rready , M1_AXI_rready , M2_AXI_rready; + wire [1:0] M0_AXI_rresp , M1_AXI_rresp , M2_AXI_rresp; + wire M0_AXI_rvalid , M1_AXI_rvalid , M2_AXI_rvalid; + wire [31:0] M0_AXI_wdata , M1_AXI_wdata , M2_AXI_wdata; + wire M0_AXI_wready , M1_AXI_wready , M2_AXI_wready; + wire [3:0] M0_AXI_wstrb , M1_AXI_wstrb , M2_AXI_wstrb; + wire M0_AXI_wvalid , M1_AXI_wvalid , M2_AXI_wvalid; + + wire [31:0] M3_AXI_araddr , M4_AXI_araddr , M5_AXI_araddr; + wire [2:0] M3_AXI_arprot , M4_AXI_arprot , M5_AXI_arprot; + wire M3_AXI_arready, M4_AXI_arready, M5_AXI_arready; + wire M3_AXI_arvalid, M4_AXI_arvalid, M5_AXI_arvalid; + wire [31:0] M3_AXI_awaddr , M4_AXI_awaddr , M5_AXI_awaddr; + wire [2:0] M3_AXI_awprot , M4_AXI_awprot , M5_AXI_awprot; + wire M3_AXI_awready, M4_AXI_awready, M5_AXI_awready; + wire M3_AXI_awvalid, M4_AXI_awvalid, M5_AXI_awvalid; + wire M3_AXI_bready , M4_AXI_bready , M5_AXI_bready; + wire [1:0] M3_AXI_bresp , M4_AXI_bresp , M5_AXI_bresp; + wire M3_AXI_bvalid , M4_AXI_bvalid , M5_AXI_bvalid; + wire [31:0] M3_AXI_rdata , M4_AXI_rdata , M5_AXI_rdata; + wire M3_AXI_rready , M4_AXI_rready , M5_AXI_rready; + wire [1:0] M3_AXI_rresp , M4_AXI_rresp , M5_AXI_rresp; + wire M3_AXI_rvalid , M4_AXI_rvalid , M5_AXI_rvalid; + wire [31:0] M3_AXI_wdata , M4_AXI_wdata , M5_AXI_wdata; + wire M3_AXI_wready , M4_AXI_wready , M5_AXI_wready; + wire [3:0] M3_AXI_wstrb , M4_AXI_wstrb , M5_AXI_wstrb; + wire M3_AXI_wvalid , M4_AXI_wvalid , M5_AXI_wvalid; + + wire [31:0] S00_AXI_araddr; + wire [2:0] S00_AXI_arprot /*= 3'b010*/; + wire S00_AXI_arready; + wire S00_AXI_arvalid; + wire [31:0] S00_AXI_awaddr; + wire [2:0] S00_AXI_awprot /*= 3'b010*/; + wire S00_AXI_awready; + wire S00_AXI_awvalid; + wire S00_AXI_bready; + wire [1:0] S00_AXI_bresp; + wire S00_AXI_bvalid; + wire [31:0] S00_AXI_rdata; + wire S00_AXI_rready; + wire [1:0] S00_AXI_rresp; + wire S00_AXI_rvalid; + wire [31:0] S00_AXI_wdata; + wire S00_AXI_wready; + wire [3:0] S00_AXI_wstrb; + wire S00_AXI_wvalid; + + // Network Interfaces + wire axi_aresetn; + wire axi_clk; + wire [10:0] counter0,counter1,counter2,counter3,counter4; + wire activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0; + wire activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0; + wire barrier_req0, barrier_req1, barrier_req2, barrier_req3, barrier_req4; + wire barrier_proceed; + wire activity_trans_sim; + wire activity_trans_log; + wire barrier_req_trans; + + //--------------------------------------------------------------------- + // Misc + //--------------------------------------------------------------------- + IBUF sys_reset_n_ibuf ( .O(sys_rst_n_c), .I(sys_reset_n)); + + reg [15:0] sys_clk_count; + always @(posedge ~sys_clk) + sys_clk_count <= sys_clk_count + 1'b1; + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_inst ( + .O (sys_clk), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (pci_clk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (pci_clk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + + IBUFDS_GTE2 #( + .CLKCM_CFG("TRUE"), // Refer to Transceiver User Guide + .CLKRCV_TRST("TRUE"), // Refer to Transceiver User Guide + .CLKSWING_CFG(2'b11) // Refer to Transceiver User Guide + ) IBUFDS_GTE2_core_inst ( + .O (clk_200), // 1-bit output: Refer to Transceiver User Guide + .ODIV2 (), // 1-bit output: Refer to Transceiver User Guide + .CEB (1'b0), // 1-bit input: Refer to Transceiver User Guide + .I (fpga_sysclk_p), // 1-bit input: Refer to Transceiver User Guide + .IB (fpga_sysclk_n) // 1-bit input: Refer to Transceiver User Guide + ); + + // drive AXI-lite from sys_clk & sys_rst + assign axi_clk = sys_clk; + assign axi_aresetn = sys_rst_n_c; + +//-----------------------------------------------------------------------------------------------// +// Network modules // +//-----------------------------------------------------------------------------------------------// + + nf_datapath + #( + // Master AXI Stream Data Width + .C_M_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_S_AXIS_DATA_WIDTH (C_NF_DATA_WIDTH), + .C_M_AXIS_TUSER_WIDTH (128), + .C_S_AXIS_TUSER_WIDTH (128), + .NUM_QUEUES (5) + ) + nf_datapath_0 + ( + .axis_aclk (clk_200), + .axis_resetn (sys_rst_n_c), + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + + // Slave Stream Ports (interface from Rx queues) + .s_axis_0_tdata (axis_i_0_tdata), + .s_axis_0_tkeep (axis_i_0_tkeep), + .s_axis_0_tuser (axis_i_0_tuser), + .s_axis_0_tvalid (axis_i_0_tvalid), + .s_axis_0_tready (axis_i_0_tready), + .s_axis_0_tlast (axis_i_0_tlast), + .s_axis_1_tdata (axis_i_1_tdata), + .s_axis_1_tkeep (axis_i_1_tkeep), + .s_axis_1_tuser (axis_i_1_tuser), + .s_axis_1_tvalid (axis_i_1_tvalid), + .s_axis_1_tready (axis_i_1_tready), + .s_axis_1_tlast (axis_i_1_tlast), + .s_axis_2_tdata (axis_dma_i_tdata), + .s_axis_2_tkeep (axis_dma_i_tkeep), + .s_axis_2_tuser (axis_dma_i_tuser), + .s_axis_2_tvalid (axis_dma_i_tvalid), + .s_axis_2_tready (axis_dma_i_tready), + .s_axis_2_tlast (axis_dma_i_tlast), + + + // Master Stream Ports (interface to TX queues) + .m_axis_0_tdata (axis_o_0_tdata), + .m_axis_0_tkeep (axis_o_0_tkeep), + .m_axis_0_tuser (axis_o_0_tuser), + .m_axis_0_tvalid (axis_o_0_tvalid), + .m_axis_0_tready (axis_o_0_tready), + .m_axis_0_tlast (axis_o_0_tlast), + .m_axis_1_tdata (axis_o_1_tdata), + .m_axis_1_tkeep (axis_o_1_tkeep), + .m_axis_1_tuser (axis_o_1_tuser), + .m_axis_1_tvalid (axis_o_1_tvalid), + .m_axis_1_tready (axis_o_1_tready), + .m_axis_1_tlast (axis_o_1_tlast), + .m_axis_2_tdata (axis_dma_o_tdata), + .m_axis_2_tkeep (axis_dma_o_tkeep), + .m_axis_2_tuser (axis_dma_o_tuser), + .m_axis_2_tvalid (axis_dma_o_tvalid), + .m_axis_2_tready (axis_dma_o_tready), + .m_axis_2_tlast (axis_dma_o_tlast), + + //AXI-Lite interface + .S0_AXI_AWADDR (M0_AXI_awaddr), + .S0_AXI_AWVALID (M0_AXI_awvalid), + .S0_AXI_WDATA (M0_AXI_wdata), + .S0_AXI_WSTRB (M0_AXI_wstrb), + .S0_AXI_WVALID (M0_AXI_wvalid), + .S0_AXI_BREADY (M0_AXI_bready), + .S0_AXI_ARADDR (M0_AXI_araddr), + .S0_AXI_ARVALID (M0_AXI_arvalid), + .S0_AXI_RREADY (M0_AXI_rready), + .S0_AXI_ARREADY (M0_AXI_arready), + .S0_AXI_RDATA (M0_AXI_rdata), + .S0_AXI_RRESP (M0_AXI_rresp), + .S0_AXI_RVALID (M0_AXI_rvalid), + .S0_AXI_WREADY (M0_AXI_wready), + .S0_AXI_BRESP (M0_AXI_bresp), + .S0_AXI_BVALID (M0_AXI_bvalid), + .S0_AXI_AWREADY (M0_AXI_awready), + + .S1_AXI_AWADDR (M1_AXI_awaddr), + .S1_AXI_AWVALID (M1_AXI_awvalid), + .S1_AXI_WDATA (M1_AXI_wdata), + .S1_AXI_WSTRB (M1_AXI_wstrb), + .S1_AXI_WVALID (M1_AXI_wvalid), + .S1_AXI_BREADY (M1_AXI_bready), + .S1_AXI_ARADDR (M1_AXI_araddr), + .S1_AXI_ARVALID (M1_AXI_arvalid), + .S1_AXI_RREADY (M1_AXI_rready), + .S1_AXI_ARREADY (M1_AXI_arready), + .S1_AXI_RDATA (M1_AXI_rdata), + .S1_AXI_RRESP (M1_AXI_rresp), + .S1_AXI_RVALID (M1_AXI_rvalid), + .S1_AXI_WREADY (M1_AXI_wready), + .S1_AXI_BRESP (M1_AXI_bresp), + .S1_AXI_BVALID (M1_AXI_bvalid), + .S1_AXI_AWREADY (M1_AXI_awready), + + .S2_AXI_AWADDR (M2_AXI_awaddr), + .S2_AXI_AWVALID (M2_AXI_awvalid), + .S2_AXI_WDATA (M2_AXI_wdata), + .S2_AXI_WSTRB (M2_AXI_wstrb), + .S2_AXI_WVALID (M2_AXI_wvalid), + .S2_AXI_BREADY (M2_AXI_bready), + .S2_AXI_ARADDR (M2_AXI_araddr), + .S2_AXI_ARVALID (M2_AXI_arvalid), + .S2_AXI_RREADY (M2_AXI_rready), + .S2_AXI_ARREADY (M2_AXI_arready), + .S2_AXI_RDATA (M2_AXI_rdata), + .S2_AXI_RRESP (M2_AXI_rresp), + .S2_AXI_RVALID (M2_AXI_rvalid), + .S2_AXI_WREADY (M2_AXI_wready), + .S2_AXI_BRESP (M2_AXI_bresp), + .S2_AXI_BVALID (M2_AXI_bvalid), + .S2_AXI_AWREADY (M2_AXI_awready) + ); + + axis_sim_stim_ip0 axis_sim_stim_0 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_0_tdata), + .M_AXIS_TKEEP (p_axis_i_0_tkeep), + .M_AXIS_TUSER (p_axis_i_0_tuser), + .M_AXIS_TVALID (p_axis_i_0_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_0_tlast), + + .counter (counter0), + .activity_stim (activity_stim0), + .barrier_req (barrier_req0), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip1 axis_sim_stim_1 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_i_1_tdata), + .M_AXIS_TKEEP (p_axis_i_1_tkeep), + .M_AXIS_TUSER (p_axis_i_1_tuser), + .M_AXIS_TVALID (p_axis_i_1_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_i_1_tlast), + + .counter (counter1), + .activity_stim (activity_stim1), + .barrier_req (barrier_req1), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_stim_ip2 axis_sim_stim_2 ( + .ACLK (clk_200), + .ARESETN (sys_rst_n_c), + + //axi streaming data interface + .M_AXIS_TDATA (p_axis_dma_i_tdata), + .M_AXIS_TKEEP (p_axis_dma_i_tkeep), + .M_AXIS_TUSER (p_axis_dma_i_tuser), + .M_AXIS_TVALID (p_axis_dma_i_tvalid), + .M_AXIS_TREADY (1'b1), + .M_AXIS_TLAST (p_axis_dma_i_tlast), + + .counter (counter4), + .activity_stim (activity_stim4), + .barrier_req (barrier_req4), + .barrier_proceed (barrier_proceed) + ); + + axis_sim_record_ip0 axis_sim_record_0 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_0_tdata), + .s_axis_tkeep (p_axis_o_0_tkeep), + .s_axis_tuser (p_axis_o_0_tuser), + .s_axis_tvalid(p_axis_o_0_tvalid), + .s_axis_tready(p_axis_o_0_tready), + .s_axis_tlast (p_axis_o_0_tlast), + + .counter (counter0), + .activity_rec(activity_rec0) + ); + + axis_sim_record_ip1 axis_sim_record_1 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_o_1_tdata), + .s_axis_tkeep (p_axis_o_1_tkeep), + .s_axis_tuser (p_axis_o_1_tuser), + .s_axis_tvalid(p_axis_o_1_tvalid), + .s_axis_tready(p_axis_o_1_tready), + .s_axis_tlast (p_axis_o_1_tlast), + + .counter (counter1), + .activity_rec(activity_rec1) + ); + + axis_sim_record_ip2 axis_sim_record_2 ( + .axi_aclk (clk_200), + // Slave Stream Ports (interface to data path) + .s_axis_tdata (p_axis_dma_o_tdata), + .s_axis_tkeep (p_axis_dma_o_tkeep), + .s_axis_tuser (p_axis_dma_o_tuser), + .s_axis_tvalid(p_axis_dma_o_tvalid), + .s_axis_tready(p_axis_dma_o_tready), + .s_axis_tlast (p_axis_dma_o_tlast), + + .counter (counter4), + .activity_rec(activity_rec4) + ); + + nf_mac_attachment_dma_ip u_nf_attachment_dma ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_dma_i_tdata), + .m_axis_mac_tkeep (p_axis_dma_i_tkeep), + .m_axis_mac_tvalid (p_axis_dma_i_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_dma_i_tuser), + .m_axis_mac_tlast (p_axis_dma_i_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_dma_o_tdata), + .s_axis_mac_tkeep (p_axis_dma_o_tkeep), + .s_axis_mac_tvalid (p_axis_dma_o_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_dma_o_tuser), + .s_axis_mac_tlast (p_axis_dma_o_tlast), + .s_axis_mac_tready (p_axis_dma_o_tready), + + // TX/RX DATA channels + .interface_number (8'd0), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_dma_o_tdata), + .s_axis_pipe_tkeep (axis_dma_o_tkeep), + .s_axis_pipe_tlast (axis_dma_o_tlast), + .s_axis_pipe_tuser (axis_dma_o_tuser), + .s_axis_pipe_tvalid (axis_dma_o_tvalid), + .s_axis_pipe_tready (axis_dma_o_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_dma_i_tdata), + .m_axis_pipe_tkeep (axis_dma_i_tkeep), + .m_axis_pipe_tlast (axis_dma_i_tlast), + .m_axis_pipe_tuser (axis_dma_i_tuser), + .m_axis_pipe_tvalid (axis_dma_i_tvalid), + .m_axis_pipe_tready (axis_dma_i_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_0 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_0_tdata), + .m_axis_mac_tkeep (p_axis_i_0_tkeep), + .m_axis_mac_tvalid (p_axis_i_0_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_0_tuser), + .m_axis_mac_tlast (p_axis_i_0_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_0_tdata), + .s_axis_mac_tkeep (p_axis_o_0_tkeep), + .s_axis_mac_tvalid (p_axis_o_0_tvalid), + .s_axis_mac_tuser_err (), //underrun + .s_axis_mac_tuser (p_axis_o_0_tuser), + .s_axis_mac_tlast (p_axis_o_0_tlast), + .s_axis_mac_tready (p_axis_o_0_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0001), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_0_tdata), + .s_axis_pipe_tkeep (axis_o_0_tkeep), + .s_axis_pipe_tlast (axis_o_0_tlast), + .s_axis_pipe_tuser (axis_o_0_tuser), + .s_axis_pipe_tvalid (axis_o_0_tvalid), + .s_axis_pipe_tready (axis_o_0_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_0_tdata), + .m_axis_pipe_tkeep (axis_i_0_tkeep), + .m_axis_pipe_tlast (axis_i_0_tlast), + .m_axis_pipe_tuser (axis_i_0_tuser), + .m_axis_pipe_tvalid (axis_i_0_tvalid), + .m_axis_pipe_tready (axis_i_0_tready) + ); + + nf_mac_attachment_ip u_nf_attachment_1 ( + // 10GE block clk & rst + .clk156 (clk_200), + .areset_clk156 (!sys_rst_n_c), + // RX MAC 64b@clk156 (no backpressure) -> rx_queue 64b@axis_clk + .m_axis_mac_tdata (p_axis_i_1_tdata), + .m_axis_mac_tkeep (p_axis_i_1_tkeep), + .m_axis_mac_tvalid (p_axis_i_1_tvalid), + .m_axis_mac_tuser_err (1'b1), // valid frame + .m_axis_mac_tuser (p_axis_i_1_tuser), + .m_axis_mac_tlast (p_axis_i_1_tlast), + // tx_queue 64b@axis_clk -> mac 64b@clk156 + .s_axis_mac_tdata (p_axis_o_1_tdata), + .s_axis_mac_tkeep (p_axis_o_1_tkeep), + .s_axis_mac_tvalid (p_axis_o_1_tvalid), + .s_axis_mac_tuser_err (p_axis_o_1_tuser), //underrun + .s_axis_mac_tuser (p_axis_o_1_tuser), + .s_axis_mac_tlast (p_axis_o_1_tlast), + .s_axis_mac_tready (p_axis_o_1_tready), + + // TX/RX DATA channels + .interface_number (8'b0000_0100), + + // NFPLUS pipeline clk & rst + .axis_aclk (clk_200), + .axis_aresetn (sys_rst_n_c), + // input from ref pipeline 256b -> MAC + .s_axis_pipe_tdata (axis_o_1_tdata), + .s_axis_pipe_tkeep (axis_o_1_tkeep), + .s_axis_pipe_tlast (axis_o_1_tlast), + .s_axis_pipe_tuser (axis_o_1_tuser), + .s_axis_pipe_tvalid (axis_o_1_tvalid), + .s_axis_pipe_tready (axis_o_1_tready), + // output to ref pipeline 256b -> DMA + .m_axis_pipe_tdata (axis_i_1_tdata), + .m_axis_pipe_tkeep (axis_i_1_tkeep), + .m_axis_pipe_tlast (axis_i_1_tlast), + .m_axis_pipe_tuser (axis_i_1_tuser), + .m_axis_pipe_tvalid (axis_i_1_tvalid), + .m_axis_pipe_tready (axis_i_1_tready) + ); + + axi_crossbar_0 u_interconnect( + .aclk (axi_clk), + .aresetn (axi_aresetn), + .s_axi_awaddr (S00_AXI_awaddr), + .s_axi_awprot (3'b010), + .s_axi_awvalid (S00_AXI_awvalid), + .s_axi_awready (S00_AXI_awready), + .s_axi_wdata (S00_AXI_wdata ), + .s_axi_wstrb (4'hf), + .s_axi_wvalid (S00_AXI_wvalid ), + .s_axi_wready (S00_AXI_wready ), + .s_axi_bresp (S00_AXI_bresp ), + .s_axi_bvalid (S00_AXI_bvalid ), + .s_axi_bready (S00_AXI_bready ), + .s_axi_araddr (S00_AXI_araddr[31:0]), + .s_axi_arprot (3'b010), + .s_axi_arvalid (S00_AXI_arvalid ), + .s_axi_arready (S00_AXI_arready ), + .s_axi_rdata (S00_AXI_rdata ), + .s_axi_rresp (S00_AXI_rresp ), + .s_axi_rvalid (S00_AXI_rvalid ), + .s_axi_rready (S00_AXI_rready ), + .m_axi_awaddr ({M2_AXI_awaddr[31:0] ,M1_AXI_awaddr[31:0] ,M0_AXI_awaddr[31:0] }), + .m_axi_awprot (), + .m_axi_awvalid ({M2_AXI_awvalid,M1_AXI_awvalid,M0_AXI_awvalid}), + .m_axi_awready ({M2_AXI_awready,M1_AXI_awready,M0_AXI_awready}), + .m_axi_wdata ({M2_AXI_wdata ,M1_AXI_wdata ,M0_AXI_wdata }), + .m_axi_wstrb ({M2_AXI_wstrb ,M1_AXI_wstrb ,M0_AXI_wstrb }), + .m_axi_wvalid ({M2_AXI_wvalid ,M1_AXI_wvalid ,M0_AXI_wvalid }), + .m_axi_wready ({M2_AXI_wready ,M1_AXI_wready ,M0_AXI_wready }), + .m_axi_bresp ({M2_AXI_bresp ,M1_AXI_bresp ,M0_AXI_bresp }), + .m_axi_bvalid ({M2_AXI_bvalid ,M1_AXI_bvalid ,M0_AXI_bvalid }), + .m_axi_bready ({M2_AXI_bready ,M1_AXI_bready ,M0_AXI_bready }), + .m_axi_araddr ({M2_AXI_araddr ,M1_AXI_araddr ,M0_AXI_araddr }), + .m_axi_arprot (), + .m_axi_arvalid ({M2_AXI_arvalid,M1_AXI_arvalid,M0_AXI_arvalid}), + .m_axi_arready ({M2_AXI_arready,M1_AXI_arready,M0_AXI_arready}), + .m_axi_rdata ({M2_AXI_rdata ,M1_AXI_rdata ,M0_AXI_rdata }), + .m_axi_rresp ({M2_AXI_rresp ,M1_AXI_rresp ,M0_AXI_rresp }), + .m_axi_rvalid ({M2_AXI_rvalid ,M1_AXI_rvalid ,M0_AXI_rvalid }), + .m_axi_rready ({M2_AXI_rready ,M1_AXI_rready ,M0_AXI_rready }) + ); + + + axi_sim_transactor_ip axi_sim_transactor_i ( + .axi_aclk (axi_clk), + .axi_resetn (axi_aresetn), + //AXI Write address channel + .M_AXI_AWADDR (S00_AXI_awaddr), + .M_AXI_AWVALID (S00_AXI_awvalid), + .M_AXI_AWREADY (S00_AXI_awready), + // AXI Write data channel + .M_AXI_WDATA (S00_AXI_wdata), + .M_AXI_WSTRB (S00_AXI_wstrb), + .M_AXI_WVALID (S00_AXI_wvalid), + .M_AXI_WREADY (S00_AXI_wready), + //AXI Write response channel + .M_AXI_BRESP (S00_AXI_bresp), + .M_AXI_BVALID (S00_AXI_bvalid), + .M_AXI_BREADY (S00_AXI_bready), + //AXI Read address channel + .M_AXI_ARADDR (S00_AXI_araddr), + .M_AXI_ARVALID (S00_AXI_arvalid), + .M_AXI_ARREADY (S00_AXI_arready), + //AXI Read data & response channel + .M_AXI_RDATA (S00_AXI_rdata), + .M_AXI_RRESP (S00_AXI_rresp), + .M_AXI_RVALID (S00_AXI_rvalid), + .M_AXI_RREADY (S00_AXI_rready), + + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + + barrier_ip barrier_i ( + .activity_stim ({activity_stim4, activity_stim3, activity_stim2, activity_stim1, activity_stim0}), + .activity_rec ({activity_rec4, activity_rec3, activity_rec2, activity_rec1, activity_rec0}), + .activity_trans_sim (activity_trans_sim), + .activity_trans_log (activity_trans_log), + .barrier_req ({barrier_req4, barrier_req3, barrier_req2, barrier_req1, barrier_req0}), + .barrier_req_trans (barrier_req_trans), + .barrier_proceed (barrier_proceed) + ); + +endmodule + diff --git a/hw/projects/reference_switch_lite/hw/hdl/top_tb.v b/hw/projects/reference_switch_lite/hw/hdl/top_tb.v new file mode 100644 index 0000000..8ec9052 --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/hdl/top_tb.v @@ -0,0 +1,180 @@ +//- +// Copyright (c) 2015 Noa Zilberman +// All rights reserved. +// +// This software was developed by Stanford University and the University of Cambridge Computer Laboratory +// under National Science Foundation under Grant No. CNS-0855268, +// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +// as part of the DARPA MRC research programme. +// +// File: +// top_tb.v +// +// Module: +// top +// +// Author: Noa Zilberman +// +// Description: +// reference nic top module +// +// @NETFPGA_LICENSE_HEADER_START@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// @NETFPGA_LICENSE_HEADER_END@ +// + +`timescale 1ns / 100ps + + module top_tb # ( + parameter PL_SIM_FAST_LINK_TRAINING = "TRUE", // Simulation Speedup + parameter C_DATA_WIDTH = 512, // RX/TX interface data width + parameter KEEP_WIDTH = C_DATA_WIDTH / 32, + parameter integer USER_CLK2_FREQ = 4, + parameter REF_CLK_FREQ = 0, // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz + parameter AXISTEN_IF_RQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_CQ_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_RC_ALIGNMENT_MODE = "FALSE", + parameter AXISTEN_IF_ENABLE_CLIENT_TAG = 0, + parameter AXISTEN_IF_RQ_PARITY_CHECK = 0, + parameter AXISTEN_IF_CC_PARITY_CHECK = 0, + parameter AXISTEN_IF_MC_RX_STRADDLE = 0, + parameter AXISTEN_IF_ENABLE_RX_MSG_INTFC = 0, + parameter [17:0] AXISTEN_IF_ENABLE_MSG_ROUTE = 18'h2FFFF +) ( + +); + + parameter PCIE_PERIOD = 4.0; + parameter XPHY_PERIOD = 6.4; + parameter real CORE_PERIOD = 2.941; + + localparam TCQ = 1; + localparam BAR0AXI = 32'h40000000; + localparam BAR1AXI = 32'h10000000; + localparam BAR2AXI = 32'h20000000; + localparam BAR3AXI = 32'h30000000; + localparam BAR4AXI = 32'h40000000; + localparam BAR5AXI = 32'h50000000; + localparam BAR0SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR1SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR2SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR3SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR4SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam BAR5SIZE = 64'hFFFF_FFFF_FFFF_FF80; + localparam throttle_percent = 50; + + reg sys_reset_n; + + reg sys_clk; + wire sys_clkp,sys_clkn; + reg xphy_clk; + wire xphy_refclk_p,xphy_refclk_n; + reg clk_ref; + wire clk_ref_p,clk_ref_n; + //----------------------------------------------------------------------------------------------------------------// + // axis interface // + //----------------------------------------------------------------------------------------------------------------// + + + + top_sim # ( + .PL_SIM_FAST_LINK_TRAINING (PL_SIM_FAST_LINK_TRAINING ), + .C_DATA_WIDTH (C_DATA_WIDTH ), + .KEEP_WIDTH (KEEP_WIDTH ), + .USER_CLK2_FREQ (USER_CLK2_FREQ ), + .REF_CLK_FREQ (REF_CLK_FREQ ), + .AXISTEN_IF_RQ_ALIGNMENT_MODE (AXISTEN_IF_RQ_ALIGNMENT_MODE ), + .AXISTEN_IF_CC_ALIGNMENT_MODE (AXISTEN_IF_CC_ALIGNMENT_MODE ), + .AXISTEN_IF_CQ_ALIGNMENT_MODE (AXISTEN_IF_CQ_ALIGNMENT_MODE ), + .AXISTEN_IF_RC_ALIGNMENT_MODE (AXISTEN_IF_RC_ALIGNMENT_MODE ), + .AXISTEN_IF_ENABLE_CLIENT_TAG (AXISTEN_IF_ENABLE_CLIENT_TAG ), + .AXISTEN_IF_RQ_PARITY_CHECK (AXISTEN_IF_RQ_PARITY_CHECK ), + .AXISTEN_IF_CC_PARITY_CHECK (AXISTEN_IF_CC_PARITY_CHECK ), + .AXISTEN_IF_MC_RX_STRADDLE (AXISTEN_IF_MC_RX_STRADDLE ), + .AXISTEN_IF_ENABLE_RX_MSG_INTFC (AXISTEN_IF_ENABLE_RX_MSG_INTFC ), + .AXISTEN_IF_ENABLE_MSG_ROUTE (AXISTEN_IF_ENABLE_MSG_ROUTE ) + ) top_sim ( + + //PCI Express + .pcie_rxn(pcie_7x_mgt_rxn), + .pcie_rxp(pcie_7x_mgt_rxp), + .pcie_txn(pcie_7x_mgt_txn), + .pcie_txp(pcie_7x_mgt_txp), + //10G Interface + + .qsfp0_rxp(rxp), + .qsfp0_rxn(rxn), + .qsfp0_txp(txp), + .qsfp0_txn(txn), + + // PCIe Clock + .pci_clk_p(sys_clkp), + .pci_clk_n(sys_clkn), + + //200MHz Clock + .fpga_sysclk_p(clk_ref_p), + .fpga_sysclk_n(clk_ref_n), + + // 156.25 MHz clock in + .qsfp_refclk_p (xphy_refclk_p), + .qsfp_refclk_n (xphy_refclk_n), + + .sys_reset_n(sys_reset_n) + ); + +//Reset handling + // Important! polarity here is opposite the one in the actual design + initial begin + sys_reset_n = 1'b0; + #(CORE_PERIOD * 200); + sys_reset_n = 1'b1; + $display("Reset Deasserted"); + end + +//Clock generation + initial begin + sys_clk = 1'b0; + #(PCIE_PERIOD/2); + forever + #(PCIE_PERIOD/2) sys_clk = ~sys_clk; + end + + assign sys_clkp = sys_clk; + assign sys_clkn = ~sys_clk; + + + initial begin + xphy_clk = 1'b0; + #(XPHY_PERIOD/2); + forever + #(XPHY_PERIOD/2) xphy_clk = ~xphy_clk; + end + + assign xphy_refclk_p = xphy_clk; + assign xphy_refclk_n = ~xphy_clk; + + initial begin + clk_ref = 1'b0; + #(CORE_PERIOD/2); + forever + #(CORE_PERIOD/2) clk_ref = ~clk_ref; + end + + assign clk_ref_p = clk_ref; + assign clk_ref_n = ~clk_ref; + +endmodule diff --git a/hw/projects/reference_switch_lite/hw/tcl/export_registers.tcl b/hw/projects/reference_switch_lite/hw/tcl/export_registers.tcl new file mode 100644 index 0000000..0ad9852 --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/tcl/export_registers.tcl @@ -0,0 +1,160 @@ +# +# Copyright (c) 2015 Noa Zilberman, Jingyun Zhang +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# The following list include all the items that are mapped to memory segments +# The structure of each item is as follows { } + +set DEF_LIST { + {INPUT_ARBITER 0 1 input_arbiter_v1_0_0/data/input_arbiter_regs_defines.txt} \ + {OUTPUT_QUEUES 0 1 output_queues_v1_0_0/data/output_queues_regs_defines.txt} \ + {OUTPUT_PORT_LOOKUP 0 1 switch_lite_output_port_lookup_v1_0_0/data/output_port_lookup_regs_defines.txt} \ +} + +set target_path $::env(NF_DESIGN_DIR)/test/ +set target_file $target_path/nf_register_defines.h + +if {[file exists ${target_path}] == 0} { + exec mkdir -p ${target_path} +} + +###################################################### +# the following function writes the license header +# into the file +###################################################### + +proc write_header { target_file } { + +# creat a blank header file +# do a fresh rewrite in case the file already exits +file delete -force $target_file +open $target_file "w" +set h_file [open $target_file "w"] + + +puts $h_file "//-" +puts $h_file "// Copyright (c) 2015,2021 University of Cambridge" +puts $h_file "// All rights reserved." +puts $h_file "//" +puts $h_file "// This software was developed by Stanford University and the University of Cambridge Computer Laboratory " +puts $h_file "// under National Science Foundation under Grant No. CNS-0855268," +puts $h_file "// the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and" +puts $h_file "// by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 (\"MRC2\"), " +puts $h_file "// as part of the DARPA MRC research programme," +puts $h_file "// and by the University of Cambridge Computer Laboratory under EPSRC EARL Project" +puts $h_file "// EP/P025374/1 alongside support from Xilinx Inc." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_START@" +puts $h_file "//" +puts $h_file "// Licensed to NetFPGA C.I.C. (NetFPGA) under one or more contributor" +puts $h_file "// license agreements. See the NOTICE file distributed with this work for" +puts $h_file "// additional information regarding copyright ownership. NetFPGA licenses this" +puts $h_file "// file to you under the NetFPGA Hardware-Software License, Version 1.0 (the" +puts $h_file "// \"License\"); you may not use this file except in compliance with the" +puts $h_file "// License. You may obtain a copy of the License at:" +puts $h_file "//" +puts $h_file "// http://www.netfpga-cic.org" +puts $h_file "//" +puts $h_file "// Unless required by applicable law or agreed to in writing, Work distributed" +puts $h_file "// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR" +puts $h_file "// CONDITIONS OF ANY KIND, either express or implied. See the License for the" +puts $h_file "// specific language governing permissions and limitations under the License." +puts $h_file "//" +puts $h_file "// @NETFPGA_LICENSE_HEADER_END@" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "// This is an automatically generated header definitions file" +puts $h_file "/////////////////////////////////////////////////////////////////////////////////" +puts $h_file "" + +close $h_file + +}; # end of proc write_header + + +###################################################### +# the following function writes all the information +# of a specific core into a file +###################################################### + +proc write_core {target_file prefix id has_registers lib_name} { + + +set h_file [open $target_file "a"] + +#First, read the memory map information from the reference_project defines file +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ + + +set baseaddr [set $prefix\_BASEADDR] +set highaddr [set $prefix\_HIGHADDR] +set sizeaddr [set $prefix\_SIZEADDR] + +puts $h_file "//######################################################" +puts $h_file "//# Definitions for $prefix" +puts $h_file "//######################################################" + +puts $h_file "#define NFPLUS_$prefix\_BASEADDR $baseaddr" +puts $h_file "#define NFPLUS_$prefix\_HIGHADDR $highaddr" +puts $h_file "#define NFPLUS_$prefix\_SIZEADDR $sizeaddr" +puts $h_file "" + +#Second, read the registers information from the library defines file +if $has_registers { + set lib_path "$public_repo_dir/std/$lib_name" + set regs_h_define_file $lib_path + set regs_h_define_file_read [open $regs_h_define_file r] + set regs_h_define_file_data [read $regs_h_define_file_read] + close $regs_h_define_file_read + set regs_h_define_file_data_line [split $regs_h_define_file_data "\n"] + + foreach read_line $regs_h_define_file_data_line { + if {[regexp "#define" $read_line]} { + puts $h_file "#define NFPLUS_[lindex $read_line 2]\_$id\_[lindex $read_line 3]\_[lindex $read_line 4] [lindex $read_line 5]" + } + } +} +puts $h_file "" +close $h_file +}; # end of proc write_core + + + +###################################################### +# the main function +###################################################### + + + +write_header $target_file + +foreach lib_item $DEF_LIST { + write_core $target_file [lindex $lib_item 0] [lindex $lib_item 1] [lindex $lib_item 2] [lindex $lib_item 3] +} + diff --git a/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite.tcl b/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite.tcl new file mode 100644 index 0000000..59a311a --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite.tcl @@ -0,0 +1,379 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +# Vivado Launch Script +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib +set repo_dir ./ip_repo +set project_constraints "${public_repo_dir}/common/constraints/${board_name}_general.xdc" + +set start_time [exec date +%s] +set_param general.maxThreads 8 +set_param synth.elaboration.rodinMoreOptions "rt::set_parameter max_loop_limit 200000" +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +set datapath_freq_mhz 340 +set opl_lut_size 16 + +set opl_lut_depth_bits [expr int(log(${opl_lut_size})/log(2))] +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +if {[string match $board_name "au280"]} { + set_property verilog_define { {BOARD_AU280} {au280} {__synthesis__} } [current_fileset] + set board_param "AU280" +} elseif {[string match $board_name "au250"]} { + set_property verilog_define { {BOARD_AU250} {__synthesis__} } [current_fileset] + set board_param "AU250" +} elseif {[string match $board_name "au200"]} { + set_property verilog_define { {BOARD_AU200} {__synthesis__} } [current_fileset] + set board_param "AU200" +} elseif {[string match $board_name "vcu1525"]} { + set_property verilog_define { {BOARD_VCU1525} {__synthesis__} } [current_fileset] + set board_param "VCU1525" +} +set_property generic "C_NF_DATA_WIDTH=${datapath_width_bit} BOARD=\"${board_param}\"" [current_fileset] + +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] +##################################### +# Project Constraints +##################################### +add_files -fileset constraints -norecurse ${project_constraints} +if {[string match $board_name "au280"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au280_timing.tcl +} elseif {[string match $board_name "au200"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au200_vcu1525_user_timing.tcl +} elseif {[string match $board_name "vcu1525"]} { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au200_vcu1525_timing.tcl + add_files -fileset constraints -norecurse ./constraints/au200_vcu1525_user_timing.tcl +} else { + add_files -fileset constraints -norecurse ${public_repo_dir}/common/constraints/au250_timing.tcl +} +set_property is_enabled true [get_files ${project_constraints}] +set_property constrset constraints [get_runs synth_1] +set_property constrset constraints [get_runs impl_1] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name switch_lite_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name output_port_lookup_ip +set_property CONFIG.C_LUT_DEPTH_BITS ${opl_lut_depth_bits} [get_ips output_port_lookup_ip] +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files output_port_lookup_ip.xci] +reset_target all [get_ips output_port_lookup_ip] +generate_target all [get_ips output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] + +create_ip -name xilinx_shell -vendor xilinx -library xilinx -module_name xilinx_shell_ip +set_property CONFIG.MAX_PKT_LEN 1518 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_QUEUE 2048 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_PHYS_FUNC 2 [get_ips xilinx_shell_ip] +set_property CONFIG.NUM_CMAC_PORT 2 [get_ips xilinx_shell_ip] +set_property generate_synth_checkpoint false [get_files xilinx_shell_ip.xci] +reset_target all [get_ips xilinx_shell_ip] +generate_target all [get_ips xilinx_shell_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000000000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000020000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + +#Add a clock wizard +create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name clk_wiz_1 +if {[string match "${datapath_freq_mhz}" "200"]} { +#200MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {6.000} \ + CONFIG.CLKOUT1_JITTER {119.392} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "250"]} { +#250MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {250.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {1} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {4.750} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.750} \ + CONFIG.CLKOUT1_JITTER {85.152} \ + CONFIG.CLKOUT1_PHASE_ERROR {78.266}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "260"]} { +#260MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {260.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {120.250} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.625} \ + CONFIG.CLKOUT1_JITTER {182.359} \ + CONFIG.CLKOUT1_PHASE_ERROR {351.991}] [get_ips clk_wiz_10] +} elseif {[string match "${datapath_freq_mhz}" "280"]} { +#280MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {280.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {119.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.250} \ + CONFIG.CLKOUT1_JITTER {183.720} \ + CONFIG.CLKOUT1_PHASE_ERROR {357.524}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "300"]} { +#300MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {300.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.000} \ + CONFIG.CLKOUT1_JITTER {111.430} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "320"]} { +#320MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {320.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {5} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {24.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.750} \ + CONFIG.CLKOUT1_JITTER {110.215} \ + CONFIG.CLKOUT1_PHASE_ERROR {154.678}] [get_ips clk_wiz_1] +} elseif {[string match "${datapath_freq_mhz}" "340"]} { +#340MHz clock + set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {250.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {340.000} \ + CONFIG.CLKIN1_JITTER_PS {40.0} \ + CONFIG.MMCM_DIVCLK_DIVIDE {25} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {119.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {4.000} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {3.500} \ + CONFIG.CLKOUT1_JITTER {179.007} \ + CONFIG.CLKOUT1_PHASE_ERROR {357.524}] [get_ips clk_wiz_1] +} else { + puts "Error: the specified clock is error" + exit -1 +} +set_property generate_synth_checkpoint false [get_files clk_wiz_1.xci] +reset_target all [get_ips clk_wiz_1] +generate_target all [get_ips clk_wiz_1] + +read_verilog "./hdl/nf_datapath.v" +read_verilog -sv "${public_repo_dir}/common/hdl/top_wrapper.sv" +read_verilog -sv "${public_repo_dir}/common/hdl/nf_attachment.sv" +read_verilog "${public_repo_dir}/common/hdl/top.v" + +#Setting Synthesis options +create_run -flow {Vivado Synthesis 2020} synth +set_property write_incremental_synth_checkpoint true [get_runs synth_1] +set_property AUTO_INCREMENTAL_CHECKPOINT 1 [get_runs synth_1] +#Setting Implementation options +create_run impl -parent_run synth -flow {Vivado Implementation 2020} +set_property strategy Performance_Explore [get_runs impl_1] +set_property steps.phys_opt_design.is_enabled true [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +#set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE AlternateFlowWithRetiming [get_runs impl_1] +set_property STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE ExploreWithHoldFix [get_runs impl_1] +set_property STEPS.PLACE_DESIGN.ARGS.DIRECTIVE Explore [get_runs impl_1] +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.is_enabled true [get_runs impl_1] + +set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] +# The following implementation options will increase runtime, but get the best timing results +#set_property strategy Performance_Explore [get_runs impl_1] +set_property SEVERITY {Warning} [get_drc_checks UCIO-1] +launch_runs synth +wait_on_run synth +launch_runs impl_1 +wait_on_run impl_1 +open_checkpoint project/${design}.runs/impl_1/top_postroute_physopt.dcp +if {![file exists "../bitfiles"]} { + file mkdir "../bitfiles" +} +write_bitstream -force ../bitfiles/${design}_${board_name}.bit + +# -- For Report -- +set end_time [exec date +%s] +set elapsed_time [expr ${end_time} - ${start_time}] +if {[catch {exec grep -A 4 "VIOLAT" project/${design}.runs/impl_1/top_timing_summary_postroute_physopted.rpt} timing_report_data]} { + set timing_report "Met" + set timing_report_data "" +} else { + set timing_report "VIOLATED" +} +puts " --- Report : ${design} for ${board_name} --- " +puts " Synth time : ${elapsed_time}" +puts " Timing Closure: ${timing_report}" +puts "${timing_report_data}" + +exit + diff --git a/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_defines.tcl b/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_defines.tcl new file mode 100644 index 0000000..ffa7681 --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_defines.tcl @@ -0,0 +1,99 @@ +# +# Copyright (c) 2015 Noa Zilberman +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +####################### +# Segments Assignment # +####################### +#M00 +set M00_BASEADDR 0x00010000 +set M00_HIGHADDR 0x00010FFF +set M00_SIZEADDR 0x1000 + +#M01 +set M01_BASEADDR 0x00020000 +set M01_HIGHADDR 0x00020FFF +set M01_SIZEADDR 0x1000 + +#M02 +set M02_BASEADDR 0x00030000 +set M02_HIGHADDR 0x00030FFF +set M02_SIZEADDR 0x1000 + +##M03 +#set M03_BASEADDR 0x44030000 +#set M03_HIGHADDR 0x44030FFF +#set M03_SIZEADDR 0x1000 +# +##M04 +#set M04_BASEADDR 0x44040000 +#set M04_HIGHADDR 0x44040FFF +#set M04_SIZEADDR 0x1000 +# +##M05 +#set M05_BASEADDR 0x44050000 +#set M05_HIGHADDR 0x44050FFF +#set M05_SIZEADDR 0x1000 +# +##M06 +#set M06_BASEADDR 0x44060000 +#set M06_HIGHADDR 0x44060FFF +#set M06_SIZEADDR 0x1000 +# +##M07 +#set M07_BASEADDR 0x44070000 +#set M07_HIGHADDR 0x44070FFF +#set M07_SIZEADDR 0x1000 +# +##M08 +#set M08_BASEADDR 0x44080000 +#set M08_HIGHADDR 0x44080FFF +#set M08_SIZEADDR 0x1000 + + + +####################### +# IP_ASSIGNMENT # +####################### +# Note that physical connectivity must match this mapping + +#INPUT ARBITER base address and size +set INPUT_ARBITER_BASEADDR $M00_BASEADDR +set INPUT_ARBITER_HIGHADDR $M00_HIGHADDR +set INPUT_ARBITER_SIZEADDR $M00_SIZEADDR + +#OUTPUT_QUEUES base address and size +set OUTPUT_QUEUES_BASEADDR $M02_BASEADDR +set OUTPUT_QUEUES_HIGHADDR $M02_HIGHADDR +set OUTPUT_QUEUES_SIZEADDR $M02_SIZEADDR + +#OUPUT_PORT_LOOKUP base address and size +set OUTPUT_PORT_LOOKUP_BASEADDR $M01_BASEADDR +set OUTPUT_PORT_LOOKUP_HIGHADDR $M01_HIGHADDR +set OUTPUT_PORT_LOOKUP_SIZEADDR $M01_SIZEADDR diff --git a/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_sim.tcl b/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_sim.tcl new file mode 100644 index 0000000..3c64ddf --- /dev/null +++ b/hw/projects/reference_switch_lite/hw/tcl/reference_switch_lite_sim.tcl @@ -0,0 +1,253 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +#### Change design settings here ####### +set design $::env(NF_PROJECT_NAME) +set top top_sim +set sim_top top_tb +set device $::env(DEVICE) +set board $::env(BOARD) +set board_name $::env(BOARD_NAME) + +set proj_dir ./project +set public_repo_dir $::env(NFPLUS_FOLDER)/hw/lib/ +set repo_dir ./ip_repo +set project_constraints ./constraints/${board_name}_switch.xdc + +set test_name [lindex $argv 0] +source $::env(NF_DESIGN_DIR)/hw/tcl/$::env(NF_PROJECT_NAME)_defines.tcl + +set_param general.maxThreads 8 +##################################### +# Design Parameters on NF_DATAPATH +##################################### +set datapath_width_bit 1024 +set opl_lut_size 16 + +set opl_lut_depth_bits [expr int(log(${opl_lut_size})/log(2))] +##################################### +# Project Settings +##################################### +create_project -name ${design} -force -dir "./${proj_dir}" -part ${device} +set_property board_part ${board} [current_project] +set_property source_mgmt_mode DisplayOnly [current_project] +set_property top ${top} [current_fileset] +puts "Creating User Datapath reference project" +##################################### +# set IP paths +##################################### +create_fileset -constrset -quiet constraints +file copy ${public_repo_dir}/ ${repo_dir} +set_property ip_repo_paths ${repo_dir} [current_fileset] + +##################################### +# Project +##################################### +update_ip_catalog +# OPL +create_ip -name switch_lite_output_port_lookup -vendor NetFPGA -library NetFPGA -module_name output_port_lookup_ip +set_property CONFIG.C_LUT_DEPTH_BITS ${opl_lut_depth_bits} [get_ips output_port_lookup_ip] +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_port_lookup_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_port_lookup_ip] +set_property generate_synth_checkpoint false [get_files output_port_lookup_ip.xci] +reset_target all [get_ips output_port_lookup_ip] +generate_target all [get_ips output_port_lookup_ip] +# input_arbiter +create_ip -name input_arbiter -vendor NetFPGA -library NetFPGA -module_name input_arbiter_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips input_arbiter_ip] +set_property generate_synth_checkpoint false [get_files input_arbiter_ip.xci] +reset_target all [get_ips input_arbiter_ip] +generate_target all [get_ips input_arbiter_ip] +# output_queues +create_ip -name output_queues -vendor NetFPGA -library NetFPGA -module_name output_queues_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips output_queues_ip] +set_property generate_synth_checkpoint false [get_files output_queues_ip.xci] +reset_target all [get_ips output_queues_ip] +generate_target all [get_ips output_queues_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_ip.xci] +reset_target all [get_ips nf_mac_attachment_ip] +generate_target all [get_ips nf_mac_attachment_ip] + +create_ip -name nf_mac_attachment -vendor NetFPGA -library NetFPGA -module_name nf_mac_attachment_dma_ip +set_property CONFIG.C_M_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_S_AXIS_DATA_WIDTH ${datapath_width_bit} [get_ips nf_mac_attachment_dma_ip] +set_property CONFIG.C_DEFAULT_VALUE_ENABLE 0 [get_ips nf_mac_attachment_dma_ip] +set_property generate_synth_checkpoint false [get_files nf_mac_attachment_dma_ip.xci] +reset_target all [get_ips nf_mac_attachment_dma_ip] +generate_target all [get_ips nf_mac_attachment_dma_ip] + +create_ip -name barrier -vendor NetFPGA -library NetFPGA -module_name barrier_ip +reset_target all [get_ips barrier_ip] +generate_target all [get_ips barrier_ip] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip0 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_0_log.axi] [get_ips axis_sim_record_ip0] +reset_target all [get_ips axis_sim_record_ip0] +generate_target all [get_ips axis_sim_record_ip0] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip1 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/nf_interface_1_log.axi] [get_ips axis_sim_record_ip1] +reset_target all [get_ips axis_sim_record_ip1] +generate_target all [get_ips axis_sim_record_ip1] + +create_ip -name axis_sim_record -vendor NetFPGA -library NetFPGA -module_name axis_sim_record_ip2 +set_property -dict [list CONFIG.OUTPUT_FILE $::env(NF_DESIGN_DIR)/test/dma_0_log.axi] [get_ips axis_sim_record_ip2] +reset_target all [get_ips axis_sim_record_ip2] +generate_target all [get_ips axis_sim_record_ip2] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip0 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_0_stim.axi] [get_ips axis_sim_stim_ip0] +generate_target all [get_ips axis_sim_stim_ip0] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip1 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/nf_interface_1_stim.axi] [get_ips axis_sim_stim_ip1] +generate_target all [get_ips axis_sim_stim_ip1] + +create_ip -name axis_sim_stim -vendor NetFPGA -library NetFPGA -module_name axis_sim_stim_ip2 +set_property -dict [list CONFIG.input_file $::env(NF_DESIGN_DIR)/test/dma_0_stim.axi] [get_ips axis_sim_stim_ip2] +generate_target all [get_ips axis_sim_stim_ip2] + +create_ip -name axi_sim_transactor -vendor NetFPGA -library NetFPGA -module_name axi_sim_transactor_ip +set_property -dict [list CONFIG.STIM_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.axi CONFIG.EXPECT_FILE $::env(NF_DESIGN_DIR)/test/reg_expect.axi CONFIG.LOG_FILE $::env(NF_DESIGN_DIR)/test/reg_stim.log] [get_ips axi_sim_transactor_ip] +reset_target all [get_ips axi_sim_transactor_ip] +generate_target all [get_ips axi_sim_transactor_ip] + + +create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 +set_property -dict [list \ +CONFIG.NUM_MI {3} \ +CONFIG.PROTOCOL {AXI4LITE} \ +CONFIG.CONNECTIVITY_MODE {SASD} \ +CONFIG.R_REGISTER {1} \ +CONFIG.S00_WRITE_ACCEPTANCE {1} \ +CONFIG.S01_WRITE_ACCEPTANCE {1} \ +CONFIG.S02_WRITE_ACCEPTANCE {1} \ +CONFIG.S03_WRITE_ACCEPTANCE {1} \ +CONFIG.S04_WRITE_ACCEPTANCE {1} \ +CONFIG.S05_WRITE_ACCEPTANCE {1} \ +CONFIG.S06_WRITE_ACCEPTANCE {1} \ +CONFIG.S07_WRITE_ACCEPTANCE {1} \ +CONFIG.S08_WRITE_ACCEPTANCE {1} \ +CONFIG.S09_WRITE_ACCEPTANCE {1} \ +CONFIG.S10_WRITE_ACCEPTANCE {1} \ +CONFIG.S11_WRITE_ACCEPTANCE {1} \ +CONFIG.S12_WRITE_ACCEPTANCE {1} \ +CONFIG.S13_WRITE_ACCEPTANCE {1} \ +CONFIG.S14_WRITE_ACCEPTANCE {1} \ +CONFIG.S15_WRITE_ACCEPTANCE {1} \ +CONFIG.S00_READ_ACCEPTANCE {1} \ +CONFIG.S01_READ_ACCEPTANCE {1} \ +CONFIG.S02_READ_ACCEPTANCE {1} \ +CONFIG.S03_READ_ACCEPTANCE {1} \ +CONFIG.S04_READ_ACCEPTANCE {1} \ +CONFIG.S05_READ_ACCEPTANCE {1} \ +CONFIG.S06_READ_ACCEPTANCE {1} \ +CONFIG.S07_READ_ACCEPTANCE {1} \ +CONFIG.S08_READ_ACCEPTANCE {1} \ +CONFIG.S09_READ_ACCEPTANCE {1} \ +CONFIG.S10_READ_ACCEPTANCE {1} \ +CONFIG.S11_READ_ACCEPTANCE {1} \ +CONFIG.S12_READ_ACCEPTANCE {1} \ +CONFIG.S13_READ_ACCEPTANCE {1} \ +CONFIG.S14_READ_ACCEPTANCE {1} \ +CONFIG.S15_READ_ACCEPTANCE {1} \ +CONFIG.M00_WRITE_ISSUING {1} \ +CONFIG.M01_WRITE_ISSUING {1} \ +CONFIG.M02_WRITE_ISSUING {1} \ +CONFIG.M03_WRITE_ISSUING {1} \ +CONFIG.M04_WRITE_ISSUING {1} \ +CONFIG.M05_WRITE_ISSUING {1} \ +CONFIG.M06_WRITE_ISSUING {1} \ +CONFIG.M07_WRITE_ISSUING {1} \ +CONFIG.M08_WRITE_ISSUING {1} \ +CONFIG.M09_WRITE_ISSUING {1} \ +CONFIG.M10_WRITE_ISSUING {1} \ +CONFIG.M11_WRITE_ISSUING {1} \ +CONFIG.M12_WRITE_ISSUING {1} \ +CONFIG.M13_WRITE_ISSUING {1} \ +CONFIG.M14_WRITE_ISSUING {1} \ +CONFIG.M15_WRITE_ISSUING {1} \ +CONFIG.M00_READ_ISSUING {1} \ +CONFIG.M01_READ_ISSUING {1} \ +CONFIG.M02_READ_ISSUING {1} \ +CONFIG.M03_READ_ISSUING {1} \ +CONFIG.M04_READ_ISSUING {1} \ +CONFIG.M05_READ_ISSUING {1} \ +CONFIG.M06_READ_ISSUING {1} \ +CONFIG.M07_READ_ISSUING {1} \ +CONFIG.M08_READ_ISSUING {1} \ +CONFIG.M09_READ_ISSUING {1} \ +CONFIG.M10_READ_ISSUING {1} \ +CONFIG.M11_READ_ISSUING {1} \ +CONFIG.M12_READ_ISSUING {1} \ +CONFIG.M13_READ_ISSUING {1} \ +CONFIG.M14_READ_ISSUING {1} \ +CONFIG.M15_READ_ISSUING {1} \ +CONFIG.S00_SINGLE_THREAD {1} \ +CONFIG.M00_A00_ADDR_WIDTH {16} \ +CONFIG.M01_A00_ADDR_WIDTH {16} \ +CONFIG.M02_A00_ADDR_WIDTH {16} \ +CONFIG.M00_A00_BASE_ADDR {0x0000000000010000}\ +CONFIG.M01_A00_BASE_ADDR {0x0000000000020000}\ +CONFIG.M02_A00_BASE_ADDR {0x0000000000030000}] [get_ips axi_crossbar_0] +set_property generate_synth_checkpoint false [get_files axi_crossbar_0.xci] +reset_target all [get_ips axi_crossbar_0] +generate_target all [get_ips axi_crossbar_0] + + +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/nf_datapath.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_sim.v" +read_verilog "$::env(NF_DESIGN_DIR)/hw/hdl/top_tb.v" + +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 + +set_property top ${sim_top} [get_filesets sim_1] +set_property include_dirs ${proj_dir} [get_filesets sim_1] +set_property simulator_language Mixed [current_project] +set_property verilog_define { {SIMULATION=1} } [get_filesets sim_1] +set_property -name xsim.more_options -value {-testplusarg TESTNAME=basic_test} -objects [get_filesets sim_1] +set_property runtime {} [get_filesets sim_1] +set_property target_simulator xsim [current_project] +set_property compxlib.compiled_library_dir {} [current_project] +set_property top_lib xil_defaultlib [get_filesets sim_1] +update_compile_order -fileset sim_1 + +unset env(PYTHONPATH) +unset env(PYTHONHOME) +set env(PYTHONPATH) ".:$::env(NFPLUS_FOLDER)/tools/scripts/:$::env(NFPLUS_FOLDER)/tools/scripts/NFTest" +set output [exec $::env(PYTHON_BNRY) $::env(NF_DESIGN_DIR)/test/${test_name}/run.py] +puts $output + +launch_simulation -simset sim_1 -mode behavioral +run 10us + diff --git a/hw/projects/reference_switch_lite/test/both_learning_sw/run.py b/hw/projects/reference_switch_lite/test/both_learning_sw/run.py new file mode 100755 index 0000000..096b07a --- /dev/null +++ b/hw/projects/reference_switch_lite/test/both_learning_sw/run.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_switch_lite import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + + +if isHW(): + # Clearing the LUT_HIT and LUT_MISS by asserting the reset_counters + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x101) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + + # Reset the switch table lookup counters (value is reset every time is read) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT()) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS()) + +nftest_start() + + +routerMAC = [] +routerIP = [] +for i in range(2): + routerMAC.append("00:0a:35:03:00:0%d"%(i+1)) + routerIP.append("192.168.%s.40"%i) + +num_broadcast = 10 + +pkts = [] +pkta = [] +for i in range(num_broadcast): + pkt = make_IP_pkt(src_MAC="aa:bb:cc:dd:ee:ff", dst_MAC=routerMAC[0], + src_IP="192.168.0.1", dst_IP="192.168.1.1", pkt_len=100) + + pkt.time = ((i*(1e-8)) + (2e-6)) + pkts.append(pkt) + if isHW(): + nftest_send_phy('nf0', pkt) + nftest_expect_phy('nf1', pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_phy('nf1', pkts) + +nftest_barrier() + +num_normal = 10 + +for i in range(num_normal): + pkt = make_IP_pkt(dst_MAC="aa:bb:cc:dd:ee:ff", src_MAC=routerMAC[1], + src_IP="192.168.0.1", dst_IP="192.168.1.1", pkt_len=100) + pkt.time = (((i+5)*(1e-8)) + (2e-6)) + pkta.append(pkt) + if isHW(): + nftest_send_phy('nf1', pkt) + nftest_expect_phy('nf0', pkt) + +if not isHW(): + nftest_send_phy('nf1', pkta) + nftest_expect_phy('nf0', pkta) + +nftest_barrier() + +if isHW(): + # Now we expect to see the lut_hit and lut_miss registers incremented and we + # verify this by doing a regread_expect + rres1= nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), num_normal) + rres2= nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) + # List containing the return values of the reg_reads + mres=[rres1,rres2] +else: + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), num_normal) # lut_hit + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) # lut_miss + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_switch_lite/test/both_simple_broadcast/run.py b/hw/projects/reference_switch_lite/test/both_simple_broadcast/run.py new file mode 100755 index 0000000..a36afde --- /dev/null +++ b/hw/projects/reference_switch_lite/test/both_simple_broadcast/run.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import logging +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) + +from NFTest import * +import sys +import os +from scapy.layers.all import Ether, IP, TCP +from reg_defines_reference_switch_lite import * + +phy2loop0 = ('../connections/conn', []) +nftest_init(sim_loop = [], hw_config = [phy2loop0]) + +if isHW(): + # reset_counters (triggered by Write only event) for all the modules + nftest_regwrite(NFPLUS_INPUT_ARBITER_0_RESET(), 0x1) + nftest_regwrite(NFPLUS_OUTPUT_PORT_LOOKUP_0_RESET(), 0x101) + nftest_regwrite(NFPLUS_OUTPUT_QUEUES_0_RESET(), 0x1) + + # Reset the switch table lookup counters (value is reset every time is read) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT()) + nftest_regread(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS()) + +nftest_start() + + +routerMAC = [] +routerIP = [] +for i in range(2): + routerMAC.append("00:0a:35:03:00:0%d"%(i+1)) + routerIP.append("192.168.%s.40"%i) + +num_broadcast = 20 + +pkts = [] +for i in range(num_broadcast): + pkt = make_IP_pkt(src_MAC="aa:bb:cc:dd:ee:ff", dst_MAC=routerMAC[0], + EtherType=0x800, src_IP="192.168.0.1", + dst_IP="192.168.1.1", pkt_len=60) + + pkt.time = ((i*(1e-8)) + (1e-6)) + pkts.append(pkt) + if isHW(): + nftest_expect_phy('nf1', pkt) + nftest_send_phy('nf0', pkt) + +if not isHW(): + nftest_send_phy('nf0', pkts) + nftest_expect_phy('nf1', pkts) + +nftest_barrier() + +if isHW(): + # Expecting the LUT_MISS counter to be incremented by 0x14, 20 packets + rres1=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) + rres2=nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), 0) + mres=[rres1,rres2] +else: + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTMISS(), num_broadcast) # lut_miss + nftest_regread_expect(NFPLUS_OUTPUT_PORT_LOOKUP_0_LUTHIT(), 0) # lut_hit + mres=[] + +nftest_finish(mres) diff --git a/hw/projects/reference_switch_lite/test/connections/conn b/hw/projects/reference_switch_lite/test/connections/conn new file mode 100644 index 0000000..0827e9b --- /dev/null +++ b/hw/projects/reference_switch_lite/test/connections/conn @@ -0,0 +1,30 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + + +nf0:eth1 +nf1:eth2 diff --git a/hw/projects/reference_switch_lite/test/global/setup b/hw/projects/reference_switch_lite/test/global/setup new file mode 100644 index 0000000..1d4cdb9 --- /dev/null +++ b/hw/projects/reference_switch_lite/test/global/setup @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +from subprocess import Popen, PIPE + +proc = Popen(["ifconfig","eth1","192.168.100.1"], stdout=PIPE) +proc = Popen(["ifconfig","eth2","192.168.101.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf0","192.168.200.1"], stdout=PIPE) +proc = Popen(["ifconfig","nf1","192.168.201.1"], stdout=PIPE) diff --git a/sw/app/Makefile b/sw/app/Makefile new file mode 100644 index 0000000..b975982 --- /dev/null +++ b/sw/app/Makefile @@ -0,0 +1,34 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +all: rwaxi + +rwaxi: main.c + cc -Wall -Werror -o rwaxi main.c + +clean: + rm -f rwaxi diff --git a/sw/app/main.c b/sw/app/main.c new file mode 100644 index 0000000..0b0409c --- /dev/null +++ b/sw/app/main.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015 Bjoern A. Zeeb + * All rights reserved. + * + * File: + * rwaxi.c + * + * $Id: rwaxi.c,v 1.3 2015/06/24 22:52:20 root Exp root $ + * + * Author: + * Bjoern A. Zeeb + * + * This software was developed by + * Stanford University and the University of Cambridge Computer Laboratory + * under National Science Foundation under Grant No. CNS-0855268, + * the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and + * by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), + * as part of the DARPA MRC research programme. + * + * @NETFPGA_LICENSE_HEADER_START@ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @NETFPGA_LICENSE_HEADER_END@ + * +*/ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct xlni_ioctl_ifreq { + uint32_t addr; + uint32_t val; +}; + +//#define NFPLUS_DEFAULT_TEST_ADDR 0x44020000 +#define NFDP_IOCTL_CMD_WRITE_REG (SIOCDEVPRIVATE+1) +#define NFDP_IOCTL_CMD_READ_REG (SIOCDEVPRIVATE+2) + +#define HAVE_ADDR 0x01 +#define HAVE_VALUE 0x02 +#define HAVE_IFACE 0x04 + +static void +usage(const char *progname) +{ + + printf("Usage: %s -a [-w ] [-i ]\n", + progname); + _exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *ifnam; + struct xlni_ioctl_ifreq sifr; + struct ifreq ifr; + size_t ifnamlen; + unsigned long l; + uint32_t addr, value; + int fd, flags, rc, req; + + flags = 0x00; + addr = 0;//NFPLUS_DEFAULT_TEST_ADDR; + ifnam = "nf0";//NFPLUS_IFNAM_DEFAULT; + req = NFDP_IOCTL_CMD_READ_REG; + value = 0; + while ((rc = getopt(argc, argv, "+a:hi:w:")) != -1) { + switch (rc) { + case 'a': + l = strtoul(optarg, NULL, 0); + if (l == ULONG_MAX || l > UINT32_MAX) + errx(1, "Invalid address"); + addr = (uint32_t)l; + flags |= HAVE_ADDR; + break; + case 'i': + ifnam = optarg; + flags |= HAVE_IFACE; + break; + case 'w': + l = strtoul(optarg, NULL, 0); + if (l == ULONG_MAX || l > UINT32_MAX) + errx(1, "Invalid value"); + value = (uint32_t)l; + flags |= HAVE_VALUE; + break; + case 'h': + case '?': + default: + usage(argv[0]); + /* NOT REACHED */ + } + } + + ifnamlen = strlen(ifnam); +#if 0 + if ((flags & HAVE_IFACE) == 0) + fprintf(stderr, "WARNING: using default interface %s\n", ifnam); +#endif + if ((flags & HAVE_ADDR) == 0) + fprintf(stderr, "WARNING: using default test address 0x%08x\n", + addr); + + fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd == -1) { + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd == -1) + err(1, "socket failed for AF_INET6 and AF_INET"); + } + + memset(&sifr, 0, sizeof(sifr)); + sifr.addr = addr; + if ((flags & HAVE_VALUE) != 0) { + sifr.val = value; + req = NFDP_IOCTL_CMD_WRITE_REG; + } + + memset(&ifr, 0, sizeof(ifr)); + if (ifnamlen >= sizeof(ifr.ifr_name)) + errx(1, "Interface name too long"); + memcpy(ifr.ifr_name, ifnam, ifnamlen); + ifr.ifr_name[ifnamlen] = '\0'; + ifr.ifr_data = (char *)&sifr; + + rc = ioctl(fd, req, &ifr); + if (rc == -1) + err(1, "ioctl"); + + close(fd); + + printf("%s 0x%08x = 0x%04x\n", ((flags & HAVE_VALUE) != 0) ? "WROTE" : + "READ ", sifr.addr, sifr.val); + + return (0); +} + +/* end */ diff --git a/sw/driver/Makefile b/sw/driver/Makefile new file mode 100644 index 0000000..c2844a9 --- /dev/null +++ b/sw/driver/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +PATCH_FILE := opennic-driver.patch +OUTFILE := .updated.txt +GITOUTFILE := .git_updated +DRIVER_DIR := open-nic-driver + +all: fetch patch driver + +.PHONY: fetch patch driver +patch: $(OUTFILE) +$(OUTFILE): + patch -d $(DRIVER_DIR) < $(PATCH_FILE) > $(OUTFILE) + +fetch: $(GITOUTFILE) +$(GITOUTFILE): + touch $(GITOUTFILE) + git submodule update --init $(DRIVER_DIR) + +driver: + cd $(DRIVER_DIR) && $(MAKE) + +clean: + $(MAKE) -C $(DRIVER_DIR) clean diff --git a/sw/driver/open-nic-driver b/sw/driver/open-nic-driver new file mode 160000 index 0000000..1e3ed21 --- /dev/null +++ b/sw/driver/open-nic-driver @@ -0,0 +1 @@ +Subproject commit 1e3ed2174859832217a9137b426be99506954148 diff --git a/sw/driver/opennic-driver.patch b/sw/driver/opennic-driver.patch new file mode 100644 index 0000000..d86d81a --- /dev/null +++ b/sw/driver/opennic-driver.patch @@ -0,0 +1,298 @@ +# +# Copyright (c) 2021 Yuta Tokusashi +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +diff -uprN ./onic_hardware.h ./onic_hardware.h +--- ./onic_hardware.h 2020-10-10 22:22:57.000000000 +0900 ++++ ./onic_hardware.h 2021-02-02 14:52:46.000000000 +0900 +@@ -26,6 +26,7 @@ struct onic_hardware { + unsigned long qdma; + u8 num_cmacs; + void __iomem *addr; /* mapping of shell registers */ ++ unsigned long nfdp_handle; + }; + + struct onic_qdma_h2c_param { +diff -uprN ./onic_main.c ./onic_main.c +--- ./onic_main.c 2020-10-10 22:22:57.000000000 +0900 ++++ ./onic_main.c 2021-02-02 14:52:46.000000000 +0900 +@@ -187,7 +187,9 @@ + strlcpy(netdev->name, dev_name, sizeof(netdev->name)); + + memset(&saddr, 0, sizeof(struct sockaddr)); + memcpy(saddr.sa_data, onic_default_dev_addr, 6); +- get_random_bytes(saddr.sa_data + 3, 3); ++ saddr.sa_data[3] = pdev->bus->number; ++ saddr.sa_data[4] = PCI_SLOT(pdev->devfn); ++ saddr.sa_data[5] = PCI_FUNC(pdev->devfn); + onic_set_mac_address(netdev, (void *)&saddr); + +diff -uprN ./onic_main.c ./onic_main.c +--- ./onic_main.c 2020-10-10 22:22:57.000000000 +0900 ++++ ./onic_main.c 2021-02-02 14:52:46.000000000 +0900 +@@ -223,6 +223,15 @@ static int onic_probe(struct pci_dev *pd + netif_set_real_num_tx_queues(netdev, priv->num_tx_queues); + netif_set_real_num_rx_queues(netdev, priv->num_rx_queues); + ++#ifdef NF_IOCTL ++ rv = onic_create_nfdp_dev(&priv->hw.nfdp_handle, priv->pdev); ++ if (rv < 0) { ++ pr_info("create_nfdp_dev() faileed %d", rv); ++ onic_destroy_nfdp_dev(priv->hw.nfdp_handle); ++ goto free_netdev; ++ } ++#endif /* NF_IOCTL */ ++ + rv = register_netdev(netdev); + if (rv < 0) { + dev_err(&pdev->dev, "register_netdev, err = %d", rv); +diff -uprN ./onic_netdev.c ./onic_netdev.c +--- ./onic_netdev.c 2020-10-10 22:22:57.000000000 +0900 ++++ ./onic_netdev.c 2021-02-02 14:52:46.000000000 +0900 +@@ -24,6 +24,97 @@ + + #define ONIC_RX_DESC_STEP 256 + ++#ifdef NF_IOCTL ++#define NFDP_OFFSET 0x0000 ++#define NFDP_END 0x70000 ++#define NFDP_MAXLEN NFDP_END - NFDP_OFFSET ++ ++#define NFDP_IOCTL_CMD_WRITE_REG (SIOCDEVPRIVATE+1) ++#define NFDP_IOCTL_CMD_READ_REG (SIOCDEVPRIVATE+2) ++ ++ ++// This should be here ++static struct nfdp_dev *onic_get_nfdp_dev(unsigned long handle) ++{ ++ return (struct nfdp_dev *)handle; ++} ++ ++// This should move to onic_main.c ++struct nfdp_dev *nfdp_create_dev(struct pci_dev *pdev, u8 bar) ++{ ++ struct nfdp_dev *nfdev; ++ ++ if (!pdev || (bar > 6)) ++ return NULL; ++ ++ nfdev = kzalloc(sizeof(struct nfdp_dev), GFP_KERNEL); ++ if (!nfdev) ++ return NULL; ++ ++ nfdev->pdev = pdev; ++ ++ nfdev->addr = pci_iomap_range(pdev, bar, NFDP_OFFSET, NFDP_MAXLEN); ++ if (!nfdev->addr) { ++ kfree(nfdev); ++ return NULL; ++ } ++ pr_info("BAR2 address is nfdev->addr[0x%p]", nfdev->addr); ++ ++ return nfdev; ++} ++ ++int onic_create_nfdp_dev(unsigned long *handle, struct pci_dev *pdev) ++{ ++ struct nfdp_dev *nfdev; ++ ++ if (!handle || !pdev) ++ return -EINVAL; ++ ++ /* assume that CMAC registers are mapped at BAR2 */ ++ nfdev = nfdp_create_dev(pdev, 2); ++ if (!nfdev) ++ return -ENOMEM; ++ ++ spin_lock_init(&nfdev->lock); ++ ++ *handle = (unsigned long)nfdev; ++ return 0; ++} ++ ++void nfdp_destroy_dev(struct nfdp_dev *nfdev) ++{ ++ if (!nfdev) ++ return; ++ ++ pci_iounmap(nfdev->pdev, nfdev->addr); ++ kfree(nfdev); ++} ++ ++void onic_destroy_nfdp_dev(unsigned long handle) ++{ ++ struct nfdp_dev *nfdev = onic_get_nfdp_dev(handle); ++ ++ if (!nfdev) ++ return; ++ ++ nfdp_destroy_dev(nfdev); ++} ++ ++ ++// This should be here ++static inline u32 nfdp_read_reg(struct nfdp_dev *nfdev, u32 offset) ++{ ++ return ioread32(nfdev->addr + offset); ++} ++ ++// This should be here ++static inline void nfdp_write_reg(struct nfdp_dev *nfdev, u32 offset, u32 val) ++{ ++ iowrite32(val, nfdev->addr + offset); ++} ++#endif /*NF_IOCTL*/ ++ ++ + inline static u16 onic_ring_get_real_count(struct onic_ring *ring) + { + /* Valid writeback entry means one less count of descriptor entries */ +@@ -609,6 +700,34 @@ netdev_tx_t onic_xmit_frame(struct sk_bu + return NETDEV_TX_OK; + } + ++#ifdef NF_IOCTL ++static int ioctl_read_reg(struct nfdp_dev *nfdev, ++ struct onic_ioctl_ifreq *sifr) ++{ ++ unsigned long flags; ++ // Spin lock ? ++ spin_lock_irqsave(&nfdev->lock, flags); ++ sifr->val = nfdp_read_reg(nfdev, (u32)sifr->addr); ++ spin_unlock_irqrestore(&nfdev->lock, flags); ++ pr_info("sifr->addr[%08x] sifr->val[%08x]", sifr->addr, sifr->val); ++ ++ return 0; ++} ++ ++static int ioctl_write_reg(struct nfdp_dev *nfdev, ++ struct onic_ioctl_ifreq *sifr) ++{ ++ unsigned long flags; ++ pr_info("sifr->addr[%08x] sifr->val[%08x]", sifr->addr, sifr->val); ++ // Spin lock ? ++ spin_lock_irqsave(&nfdev->lock, flags); ++ nfdp_write_reg(nfdev, (u32)sifr->addr, (u32)sifr->val); ++ spin_unlock_irqrestore(&nfdev->lock, flags); ++ ++ return 0; ++} ++#endif /*NF_IOCTl*/ ++ + int onic_set_mac_address(struct net_device *dev, void *addr) + { + u8 *dev_addr = (u8 *)addr; +@@ -622,6 +741,50 @@ int onic_set_mac_address(struct net_devi + + int onic_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { ++#ifdef NF_IOCTL ++ struct onic_private *priv = netdev_priv(dev); ++ struct nfdp_dev *nfdev = onic_get_nfdp_dev(priv->hw.nfdp_handle); ++ struct onic_ioctl_ifreq sifr; ++ int err; ++ ++ switch(cmd) { ++ case NFDP_IOCTL_CMD_WRITE_REG: ++ err = copy_from_user(&sifr, ifr->ifr_data, ++ sizeof(struct onic_ioctl_ifreq)); ++ if (err != 0) { ++ err = -EFAULT; ++ break; ++ } ++ err = ioctl_write_reg(nfdev, &sifr); ++ break; ++ case NFDP_IOCTL_CMD_READ_REG: ++ err = copy_from_user(&sifr, ifr->ifr_data, ++ sizeof(struct onic_ioctl_ifreq)); ++ if (err != 0) { ++ err = -EFAULT; ++ break; ++ } ++ //err = ioctl_write_reg(nfdev, &sifr); ++ //if (err != 0) { ++ // err = -EFAULT; ++ // break; ++ //} ++ err = ioctl_read_reg(nfdev, &sifr); ++ if (err != 0) { ++ err = -EFAULT; ++ break; ++ } ++ err = copy_to_user(ifr->ifr_data, &sifr, ++ sizeof(struct onic_ioctl_ifreq)); ++ if (err != 0) ++ err = -EFAULT; ++ break; ++ default: ++ pr_info("unspported ioctl 0x%8x", cmd); ++ err = -EOPNOTSUPP; ++ break; ++ } ++#endif /*NF_IOCTL*/ + return 0; + } + +diff -uprN ./onic_netdev.h ./onic_netdev.h +--- ./onic_netdev.h 2020-10-10 22:22:57.000000000 +0900 ++++ ./onic_netdev.h 2021-02-02 14:52:46.000000000 +0900 +@@ -49,4 +49,27 @@ void onic_get_stats64(struct net_device + + int onic_poll(struct napi_struct *napi, int budget); + ++ ++#define NF_IOCTL ++#ifdef NF_IOCTL ++//#ifndef __NF_IOCTL__ ++//#define __NF_IOCTL__ ++ ++struct nfdp_dev { ++ struct pci_dev *pdev; ++ void __iomem *addr; ++ spinlock_t lock; ++}; ++ ++struct onic_ioctl_ifreq { ++ uint32_t addr; ++ uint32_t val; ++}; ++ ++int onic_create_nfdp_dev(unsigned long *handle, struct pci_dev *pdev); ++ ++void onic_destroy_nfdp_dev(unsigned long handle); ++//#endif /*__NF_IOCTL__ */ ++#endif /* NF_IOCTL */ ++ + #endif +diff -uprN ./onic_register.h ./onic_register.h +--- ./onic_register.h 2020-10-10 22:22:57.000000000 +0900 ++++ ./onic_register.h 2021-02-02 14:52:46.000000000 +0900 +@@ -30,7 +30,7 @@ static inline void onic_write_reg(struct + } + + #define SHELL_START 0x0 +-#define SHELL_END 0x10000 ++#define SHELL_END 0x40000 + #define SHELL_MAXLEN (SHELL_END - SHELL_START) + + /***** system config registers *****/ diff --git a/sw/hwtestlib/Makefile b/sw/hwtestlib/Makefile new file mode 100644 index 0000000..3147391 --- /dev/null +++ b/sw/hwtestlib/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (c) 2015 Bjoern A. Zeeb +# All rights reserved. +# +# File: +# Makefile +# +# This software was developed by +# Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# + +all: libsume + +libsume: sume_reg.c + cc -c -Wall -Werror -fPIC sume_reg.c + cc -shared -o libsume.so sume_reg.o + +clean: + rm -f sume_reg.o libsume.so + +# end diff --git a/sw/hwtestlib/sume_reg.c b/sw/hwtestlib/sume_reg.c new file mode 100644 index 0000000..60eea99 --- /dev/null +++ b/sw/hwtestlib/sume_reg.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2015 Bjoern A. Zeeb + * All rights reserved. + * + * File: + * sume_reg.c + * + * Author: + * Bjoern A. Zeeb + * + * This software was developed by + * Stanford University and the University of Cambridge Computer Laboratory + * under National Science Foundation under Grant No. CNS-0855268, + * the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and + * by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), + * as part of the DARPA MRC research programme. + * + * @NETFPGA_LICENSE_HEADER_START@ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @NETFPGA_LICENSE_HEADER_END@ + * +*/ + +#include +#include +#include +#if defined(__linux__) +#include +#elif defined(__FreeBSD__) +#include +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define NFPLUS_IFNAM_DEFAULT "nf0" +//#include "nf_sume.h" +/* + * We are trying to use the same (private, deprecated) IOCTLs NF10 is + * using. Unfortunately the old user space tools (rdax/wraxi) operated + * on a dedicated device node, rather using netdevice(7). + */ +#if defined(__linux__) +#define NFPLUS_IOCTL_CMD_WRITE_REG (SIOCDEVPRIVATE+1) +#define NFPLUS_IOCTL_CMD_READ_REG (SIOCDEVPRIVATE+2) +#elif defined(__FreeBSD__) +#define NFPLUS_IOCTL_CMD_WRITE_REG (SIOCGPRIVATE_0) +#define NFPLUS_IOCTL_CMD_READ_REG (SIOCGPRIVATE_1) +#else +#error NetFPGA NFPLUS ioctls not supported on this OS +#endif + +struct sume_ifreq { + uint32_t addr; + uint32_t val; +}; + +/* + * This is based on the function declarations used by python in NF10 + * ("spec") to maintain the API and compatibility: + * - uint32_t regread(uint32_t addr); + * - int regwrite(uint32_t addr, uint32_t val); + * - int regread_expect(uint32_t addr, uint32_t expval); + * and the error value define: + * - #define ERROR_CODE 0xdeadbeef + * Ideally we'd give them better (prefixed) names and 64bit data variables + * (if not address variables as well), to allow for a 20th century future. + * Further we'd add an const char *ifname, to allow working on more than + * one card. + */ + +#define _NFPLUS_REG_ERROR_CODE 0xdeadbeef + +int +sume_do_register(struct sume_ifreq *sifr, unsigned long request, char *ifnam) +{ + struct ifreq ifr; + size_t ifnamlen; + int fd, rc; + + memset(&ifr, 0, sizeof(ifr)); + ifnamlen = strlen(ifnam); + if (ifnamlen >= sizeof(ifr.ifr_name)) + return (EINVAL); + memcpy(ifr.ifr_name, ifnam, ifnamlen); + ifr.ifr_name[ifnamlen] = '\0'; + ifr.ifr_data = (char *)sifr; + + fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd == -1) { + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd == -1) + return (ENOPROTOOPT); + } + + rc = ioctl(fd, request, &ifr); + if (rc == -1) + rc = ENOTTY; + close(fd); + + return (rc); +} + +uint32_t +regread(uint32_t addr) +{ + struct sume_ifreq sifr; + int rc; + + sifr.addr = addr; + sifr.val = 0; + rc = sume_do_register(&sifr, NFPLUS_IOCTL_CMD_READ_REG, + NFPLUS_IFNAM_DEFAULT); + if (rc != 0) + return (_NFPLUS_REG_ERROR_CODE); + return (sifr.val); +} + +int +regread_expect(uint32_t addr, uint32_t expval) +{ + struct sume_ifreq sifr; + int rc; + + /* + * We unfortunately cannot just call regread, as we lose the error + * information making it indistinguishable to an actual register value. + */ + sifr.addr = addr; + sifr.val = 0; + rc = sume_do_register(&sifr, NFPLUS_IOCTL_CMD_READ_REG, + NFPLUS_IFNAM_DEFAULT); + if (rc != 0) + return (_NFPLUS_REG_ERROR_CODE); + + if (sifr.val == expval) + return (1); + else + return (0); +} + +int +regwrite(uint32_t addr, uint32_t val) +{ + struct sume_ifreq sifr; + int rc; + + sifr.addr = addr; + sifr.val = val; + rc = sume_do_register(&sifr, NFPLUS_IOCTL_CMD_WRITE_REG, + NFPLUS_IFNAM_DEFAULT); + if (rc != 0) + return (_NFPLUS_REG_ERROR_CODE); + + return (0); +} + +/* end */ diff --git a/tools/scripts/NFTest/NFTest/Makefile b/tools/scripts/NFTest/NFTest/Makefile new file mode 100644 index 0000000..43df41d --- /dev/null +++ b/tools/scripts/NFTest/NFTest/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2015 Neelakandan Manihatty Bojan +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# File: +# Makefile +# +# Project: +# Python Test Infrastructure +# +# Module: +# Python Library Files +# +# Description: +# Makefile for the Python test infrastructure +# + +clean: + rm -f *.pyc + rm -f ../*.pyc + +.PHONY: clean + diff --git a/tools/scripts/NFTest/NFTest/NFTestHeader.py b/tools/scripts/NFTest/NFTest/NFTestHeader.py new file mode 100644 index 0000000..9250ee7 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/NFTestHeader.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +# project register defines +import sys +import os +sys.path.append(os.path.abspath(os.environ['NF_DESIGN_DIR']+'/test')) +project = os.path.basename(os.environ['NF_DESIGN_DIR']) +if project == '': + project = os.path.basename(os.environ['NF_DESIGN_DIR'][0:-1]) + +# scapy +try: + import scapy.all as scapy +except: + try: + import scapy as scapy + except: + sys.exit("Error: need to install scapy for packet handling") diff --git a/tools/scripts/NFTest/NFTest/NFTestLib.py b/tools/scripts/NFTest/NFTest/NFTestLib.py new file mode 100755 index 0000000..cabf984 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/NFTestLib.py @@ -0,0 +1,474 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +from . import hwPktLib +from .hwPktLib import scapy +from . import hwRegLib +from . import simLib +from . import simReg +from . import simPkt +import sys +import os + +script_dir = os.path.dirname( sys.argv[0] ) +# Add path *relative to this script's location* of axitools module +sys.path.append( os.path.join( script_dir, '..','..','..','..','tools','scripts' ) ) +# Add project test folder +test_path = os.environ['NF_DESIGN_DIR'] +hwlog_path = os.path.join(test_path,'test','hwreg.log') + + +# NB: axitools import must preceed any scapy imports +import axitools + +sim = True # default, pass an argument if hardware is needed +iface_map = {} # key is interface specified by test, value is physical interface to use +connections = {} # key is an interface specified by test, value is connected interface specified by test + +ifaceArray = [] + +sent_phy = {} +sent_dma = {} +expected_phy = {} +expected_dma = {} + +CPCI_Control_reg = 0x08 +CPCI_Interrupt_Mask = 0x40 + +############################ +# Function: nftest_init +# Keyword Arguments: sim_loop - list of interfaces to put into loopback for simulation tests +# all 4 ports are automatically initialized for simulation +# hw_config - list of valid hardware configurations for hardware tests +# configurations are formatted ('path/to/conn/file', ['looped', 'ifaces']) +# Description: parses the configurations to find a valid configuration +# populates iface_map and connections dictionaries +############################ +def nftest_init(sim_loop = [], hw_config=None): + global sim + global ifaceArray + global connections + global sent_phy, sent_dma, expected_phy, expected_dma + + # handle simulation separately + if not isHW(): + sim = True + simLib.init() + ifaceArray = ['nf0', 'nf1'] + for iface in ifaceArray: + connections[iface] = 'phy_dummy' + sent_phy[iface] = [] + sent_dma[iface] = [] + expected_phy[iface] = [] + expected_dma[iface] = [] + + looped = [False, False, False, False] + for iface in sim_loop: + if not iface.startswith('nf'): + print("Error1: Only nfX interfaces can be put in loopback") + sys.exit(1) + else: + looped[int(iface[2])] = True + portcfgfile = 'portconfig.sim' + portcfg = open(portcfgfile, 'w') + portcfg.write('LOOPBACK=') + for loop_state in reversed(looped): + if loop_state: + portcfg.write('1') + else: + portcfg.write('0') + portcfg.close() + return 'sim' + + # running a hardware test, check connections + else: + ifaceTuple = ('nf0', 'nf1') + if hw_config is None: + print("Error: trying to run hardware test without specifying hardware configurations. Verify the keyword argument hw_config is being used in nftest_init") + sys.exit(1) + sim = False + + # validate connections and process loopback + portConfig = 0 + if '--conn' in sys.argv: + specified_connections = {} + # read specified connections + fp = open(sys.argv[sys.argv.index('--conn')+1], 'r') + for lineNum, tmp_line in enumerate(fp): + if tmp_line.startswith(ifaceTuple): + break + fp.close() + + # lines = open(sys.argv[sys.argv.index('--conn')+1], 'r').readlines()[29:] + lines = open(sys.argv[sys.argv.index('--conn')+1], 'r').readlines()[lineNum:] + for line in lines: + conn = line.strip().split(':') + specified_connections[conn[0]] = conn[1] + + # find matching configuration + for portConfig in range(len(hw_config)): + conns = {} + # lines = open(hw_config[portConfig][0]).readlines()[29:] + lines = open(hw_config[portConfig][0]).readlines()[lineNum:] + for line in lines: + conn = line.strip().split(':') + conns[conn[0]] = conn[1] + # physical connections match + if conns == specified_connections: + connections = specified_connections + # check if we've got disconnected interfaces + for connection in connections: + if connections[connection] == '': + hwRegLib.phy_isolate(iface) + # specify loopback + for iface in hw_config[portConfig][1]: + if iface.startswith('nf'): + hwRegLib.phy_loopback(iface) + else: + print("Error2: Only nfX interfaces can be put in loopback") + sys.exit(1) + break + # incompatible configuration + elif portConfig == len(hw_config) - 1: + print("Specified connections file incompatible with this test.") + sys.exit(1) + + else: + portConfig = 0 + # use the first valid_conn_file if not specified + #lines = open(hw_config[0][0], 'r').readlines()[29:] + fp = open(hw_config[0][0], 'r') + for lineNum, tmp_line in enumerate(fp): + if tmp_line.startswith(ifaceTuple): + break + fp.close() + + lines = open(hw_config[0][0], 'r').readlines()[lineNum:] + for line in lines: + conn = line.strip().split(':') + connections[conn[0]] = conn[1] + # specify loopback + + if len(hw_config[0][1]) > 0: + for iface in hw_config[0][1]: + if iface.startswith('nf'): + if isHW(): + hwRegLib.phy_loopback(iface) + else: + looped[int(iface[2])] = True + else: + print("Error3: Only nfX interfaces can be put in loopback") + sys.exit(1) + + # avoid duplicating interfaces + ifaces = list(set(list(connections.keys()) + list(connections.values()) + list(hw_config[portConfig][1])) - set([''])) + + global iface_map + # populate iface_map + if '--map' in sys.argv: + fp = open(sys.argv[sys.argv.index('--map')+1], 'r') + for lineNum, tmp_line in enumerate(fp): + if tmp_line.startswith(ifaceTuple): + break + fp.close() + + mapfile = open(sys.argv[sys.argv.index('--map')+1], 'r') + lines = mapfile.readlines()[lineNum:] + for line in lines: + mapping = line.strip().split(':') + iface_map[mapping[0]] = mapping[1] + if mapping[0] in ifaces: + ifaces.remove(mapping[0]) + ifaces.append(mapping[1]) + else: + for iface in ifaces: + iface_map[iface] = iface + + ifaceArray = ifaces + + for iface in ifaces: + sent_phy[iface] = [] + sent_dma[iface] = [] + expected_phy[iface] = [] + expected_dma[iface] = [] + + hwPktLib.init(ifaces) + # print setup for inspection + print('Running test using the following physical connections:') + for connection in list(connections.items()): + try: + print(iface_map[connection[0]] + ':' + iface_map[connection[1]]) + except KeyError: + print(iface_map[connection[0]] + ' initialized but not connected') + if len(list(hw_config[portConfig][1])) > 0: + print('Ports in loopback:') + for iface in list(hw_config[portConfig][1]): + print(iface_map[iface]) + print('------------------------------------------------------') + + return portConfig + +############################ +# Function: nftest_start +# Arguments: none +# Description: performs initialization +############################ +def nftest_start(): + logfile=open(hwlog_path,'w') + logfile.write('\ +#####################################################################\n\ +# This log file is automatically Generated from NetFPGA Hardware Test\n\ +# It is a test log for register dump reading, for debug purpose\n\ +#####################################################################\n') + logfile.close() + if not sim: + hwPktLib.start() + nftest_barrier() + +############################ +# Function: nftest_send_phy +# Arguments: interface name +# packet to send +# Description: send a packet from the phy +############################ +def nftest_send_phy(ifaceName, pkt): + if connections[ifaceName] == ifaceName: + print("Error: cannot send on phy of a port in loopback") + sys.exit(1) + sent_phy[ifaceName].append(pkt) + if sim: + for pkt_s in pkt: + pkt_s.tuser_sport = 1 << (int(ifaceName[2:3])*2) # physical ports are even-numbered + + for i in range(len(pkt)): + simPkt.pktSendPHY(int(ifaceName[2:3])+1, pkt) + f = simLib.fPort(int(ifaceName[2]) + 1) + axitools.axis_dump( pkt, f, 512, 1e-9 ) + else: + hwPktLib.send(iface_map[connections[ifaceName]], pkt) + +############################ +# Function: nftest_send_dma +# Arguments: interface name +# packet to send +# Description: send a packet from the dma +############################ +def nftest_send_dma(ifaceName, pkt): + sent_dma[ifaceName].append(pkt) + if sim: + for pkt_s in pkt: + pkt_s.tuser_sport = 1 << (int(ifaceName[2:3])%4*2 + 1) # PCI ports are odd-numbered + + for i in range(len(pkt)): + simPkt.pktSendDMA(int(ifaceName[2:3])+1, pkt) + f = simLib.fDMA() + axitools.axis_dump( pkt, f, 512, 1e-9 ) + else: + hwPktLib.send(iface_map[ifaceName], pkt) + +############################ +# Function: nftest_expect_phy +# Arguments: interface name +# packet to expect +# optional packet mask to ignore parts of packet +# Description: expect a packet on the phy +############################ +def nftest_expect_phy(ifaceName, pkt, mask = None): + expected_phy[ifaceName].append(pkt) + if sim: + for i in range(len(pkt)): + simPkt.pktExpectPHY(int(ifaceName[2:3])+1, pkt, mask) + f = simLib.fExpectPHY(int(ifaceName[2]) + 1) + axitools.axis_dump( pkt, f, 512, 1e-9 ) + else: + hwPktLib.expect(iface_map[connections[ifaceName]], pkt, mask) + +############################ +# Function: nftest_expect_dma +# Arguments: interface name +# packet to expect +# optional packet mask to ignore parts of packet +# Description: expect a packet on dma +############################ +def nftest_expect_dma(ifaceName, pkt, mask = None): + expected_dma[ifaceName].append(pkt) + if sim: + for i in range(len(pkt)): + simPkt.pktExpectDMA(int(ifaceName[2:3])+1, pkt, mask) + f = simLib.fExpectDMA(int(ifaceName[2]) + 1) + axitools.axis_dump( pkt, f, 512, 1e-9 ) + else: + hwPktLib.expect(iface_map[ifaceName], pkt, mask) + +############################ +# Function: nftest_barrier +# Arguments: none +# Description: pauses execution until expected packets arrive +############################ +def nftest_barrier(): + if sim: + simPkt.barrier() + else: + hwPktLib.barrier() + +############################ +# Function: nftest_finish +# Arguments: none +# Description: (sim) finalizes simulation files +# (hw) performs finalization, writes pcap files and prints success +############################ +def nftest_finish(reg_list): + total_errors = 0 + nftest_barrier() + reg_errors = 0 + reg_status = 0 + + + if sim: + simLib.close() + return 0 + else: + + # write out the sent/expected pcaps for easy viewing + if not os.path.isdir("./source_pcaps"): + os.mkdir("./source_pcaps") + for iface in ifaceArray: + if len(sent_phy[iface]) > 0: + scapy.wrpcap("./source_pcaps/%s_sent_phy.pcap"%iface, + sent_phy[iface]) + if len(sent_dma[iface]) > 0: + scapy.wrpcap("./source_pcaps/%s_sent_dma.pcap"%iface, + sent_dma[iface]) + if len(expected_phy[iface]) > 0: + scapy.wrpcap("./source_pcaps/%s_expected_phy.pcap"%iface, + expected_phy[iface]) + if len(expected_dma[iface]) > 0: + scapy.wrpcap("./source_pcaps/%s_expected_dma.pcap"%iface, + expected_dma[iface]) + + total_errors += hwPktLib.finish() + for i in range(len(reg_list)): + if(reg_list[i]!=1): + reg_errors += 1 + reg_status = reg_read_result(reg_list) + print('\n'+'*****************') + print('HW Test results') + print('*****************') + if total_errors == 0 and reg_status == 1: + print('Test status : SUCCESS!') + sys.exit(0) + else: + print('\n'+'Test status : FAIL') + print('packet_missed errors : '+str(total_errors)) + print('register_read errors : '+str(reg_errors)) + print('Please check '+hwlog_path+' for details') + sys.exit(1) + +############################ +# Function: nftest_regread_expect +# Arguments: address to read +# value expected +# Description: reads the specified address and compares with passed value +# (hw) returns read data +############################ +def nftest_regread_expect(addr, val): + if sim: + #nftest_regread(addr) + simReg.regreadstim(addr) + simReg.regRead(addr, val) + return 1 + else: + read_value = hwRegLib.regread(addr) + logfile = open (hwlog_path,'a') + logfile.write('Read register address '+format(addr,'#08x')+': expected value -> '+format(val, '#08x')+', read as -> '+format(read_value, '#08x')+' ') + if (read_value == val): + logfile.write('<>\n') + logfile.close() + return 1 + else: + logfile.write('<>\n') + logfile.close() + return 0 +# return hwRegLib.regread_expect(addr, val) + +############################ +# Function: nftest_regread +# Arguments: address to read +############################ +def nftest_regread(addr): + if sim: + #simReg.regreadstim(addr) + return 0 + return hwRegLib.regread(addr) + +############################ +# Function: regread_result +# Arguments: list containing the status of regread_expect +# Description: returns the status of the regread_expect functionality +# 1 indicates all the regread_expects has passed +# 0 indicates the reg_read_expects has failed +############################ +def reg_read_result(nreg_list): + nreg_status = 1 + for i in range(len(nreg_list)): + nreg_status &= nreg_list[i] + return nreg_status + + +############################ +# Function: regwrite +# Arguments: address to write +# value to write +# Description: writes a value to a register +############################ +def nftest_regwrite(addr, val): + if sim: + simReg.regWrite(addr, val) + else: + hwRegLib.regwrite(addr, val) + +############################ +# Function: nftest_fpga_reset +# Arguments: none +# Description: resets the fpga +############################ +def nftest_fpga_reset(): + if sim: + simReg.regWrite(simReg.CPCI_REG_CTRL, simReg.CPCI_REG_CTRL_RESET) + else: + hwRegLib.fpga_reset() + +############################ +# Function: isHW +# Arguments: none +# Description: helper for HW specific tasks in tests supporting hw and sim +############################ +def isHW(): + if '--hw' in sys.argv: + return True + return False diff --git a/tools/scripts/NFTest/NFTest/PacketLib.py b/tools/scripts/NFTest/NFTest/PacketLib.py new file mode 100644 index 0000000..4cb2b46 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/PacketLib.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +import sys +import os +from random import randint +from random import seed +from scapy.all import Raw, RandString +import scapy.all as scapy + +############################ +# Function: make_MAC_hdr +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# Description: creates and returns a scapy Ether layer +# if keyword arguments are not specified, scapy defaults are used +############################ +def make_MAC_hdr(src_MAC = None, dst_MAC = None, EtherType = None, **kwargs): + hdr = scapy.Ether() + if src_MAC: + hdr.src = src_MAC + if dst_MAC: + hdr.dst = dst_MAC + if EtherType: + hdr.type = EtherType + return hdr + +############################ +# Function: make_IP_hdr +# Keyword Arguments: src_IP, dst_IP, TTL +# Description: creates and returns a scapy Ether layer +# if keyword arguments are not specified, scapy defaults are used +############################ +def make_IP_hdr(src_IP = None, dst_IP = None, TTL = None, **kwargs): + hdr = scapy.IP() + if src_IP: + hdr[scapy.IP].src = src_IP + if dst_IP: + hdr[scapy.IP].dst = dst_IP + if TTL: + hdr[scapy.IP].ttl = TTL + return hdr + +############################ +# Function: make_ARP_hdr +# Keyword Arguments: src_IP, dst_IP, TTL +# Description: creates and returns a scapy ARP layer +# if keyword arguments are not specified, scapy defaults are used +############################ +def make_ARP_hdr(op = None, src_MAC = None, dst_MAC = None, src_IP = None, dst_IP = None, **kwargs): + hdr = scapy.ARP() + if op: + hdr.op = op + if src_MAC: + hdr.hwsrc = src_MAC + if dst_MAC: + hdr.hwdst = dst_MAC + if src_IP: + hdr.psrc = src_IP + if dst_IP: + hdr.pdst = dst_IP + return hdr + +############################ +# Function: make_VLAN_hdr +# Keyword Arguments: vlan, id, priority +# Description: creates and returns a scapy VLAN layer +# if keyword arguments are not specified, scapy defaults are used +############################ + +def make_VLAN_hdr(vlan = None, id = None, prio = None, **kwargs): + hdr = scapy.Dot1Q() + if vlan: + hdr.vlan = vlan + if id: + hdr.id = id + if prio: + hdr.prio = prio + return hdr + + +############################ +# Function: make_IP_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# src_IP, dst_IP, TTL +# pkt_len +# Description: creates and returns a complete IP packet of length pkt_len +############################ + +def make_IP_pkt(pkt_len = 60, **kwargs): + if pkt_len < 60: + pkt_len = 60 + pkt = make_MAC_hdr(**kwargs)/make_IP_hdr(**kwargs)/generate_load(pkt_len - 34) + return pkt + +############################ +# Function: make_VLAN_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# src_IP, dst_IP, TTL +# pkt_len +# Description: creates and returns a complete IP packet of length pkt_len with VLAN headers +############################ + +def make_VLAN_pkt(pkt_len = 60, **kwargs): + if pkt_len < 60: + pkt_len = 60 + pkt = make_MAC_hdr(**kwargs)/make_VLAN_hdr(**kwargs)/make_IP_hdr(**kwargs)/generate_load(pkt_len - 34) + return pkt + + +############################ +# Function: make_ICMP_reply_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# src_IP, dst_IP, TTL +# Description: creates and returns a complete ICMP reply packet +############################ +def make_ICMP_reply_pkt(data = None, **kwargs): + pkt = make_MAC_hdr(**kwargs)/make_IP_hdr(**kwargs)/scapy.ICMP(type="echo-reply") + if data: + pkt = pkt/data + else: + pkt = pkt/("\x00"*56) + return pkt + +############################ +# Function: make_ICMP_request_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# src_IP, dst_IP, TTL +# Description: creates and returns a complete ICMP request packet +############################ +def make_ICMP_request_pkt(**kwargs): + pkt = make_MAC_hdr(**kwargs)/make_IP_hdr(**kwargs)/scapy.ICMP(type="echo-request")/("\x00"*56) + return pkt + +############################ +# Function: make_ICMP_ttl_exceed_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# src_IP, dst_IP, TTL +# Description: creates and returns a complete ICMP reply packet +############################ +def make_ICMP_ttl_exceed_pkt(**kwargs): + pkt = make_MAC_hdr(**kwargs)/make_IP_hdr(**kwargs)/scapy.ICMP(type=11, code=0) + return pkt + +############################ +# Function: make_ICMP_host_unreach_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# src_IP, dst_IP, TTL +# Description: creates and returns a complete ICMP reply packet +############################ +def make_ICMP_host_unreach_pkt(**kwargs): + pkt = make_MAC_hdr(**kwargs)/make_IP_hdr(**kwargs)/scapy.ICMP(type=3, code=0) + return pkt + +############################ +# Function: make_ARP_request_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# src_IP, dst_IP +# Description: creates and returns a complete ICMP reply packet +############################ +def make_ARP_request_pkt(**kwargs): + pkt = make_MAC_hdr(**kwargs)/make_ARP_hdr(op="who-has", **kwargs)/("\x00"*18) + return pkt + +############################ +# Function: make_ARP_reply_pkt +# Keyword Arguments: src_MAC, dst_MAC, EtherType +# +# Description: creates and returns a complete ARP reply packet +############################ +def make_ARP_reply_pkt(**kwargs): + pkt = make_MAC_hdr(**kwargs)/make_ARP_hdr(op="is-at", **kwargs)/("\x00"*18) + return pkt + +############################ +# Function: generate_load +# Keyword Arguments: length +# Description: creates and returns a payload of the specified length +############################ +def generate_load(length): + return Raw(RandString(length)) + +############################ +# Function: set_seed +# Description: sets the seed for the random number generator if specified +# enables reproducibility in tests +############################ +def set_seed(): + global SEED + if '--seed' in sys.argv: + SEED = int(sys.argv[sys.argv.index('--seed')+1]) + else: + SEED = hash(os.urandom(32)) + seed(SEED) + +############################ +# Function: print_seed +# Description: returns the seed used by the random number generator +############################ +def print_seed(): + f = open('./seed', 'w') + f.write(str(SEED)) + f.close() + +set_seed() +print_seed() diff --git a/tools/scripts/NFTest/NFTest/__init__.py b/tools/scripts/NFTest/NFTest/__init__.py new file mode 100644 index 0000000..7920587 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/__init__.py @@ -0,0 +1,34 @@ +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +"""NetFPGA test library + +Library for NetFPGA simulation and hardware testing +""" + +from .NFTestLib import * +from .NFTestHeader import scapy +from .PacketLib import * diff --git a/tools/scripts/NFTest/NFTest/hwPkt.py b/tools/scripts/NFTest/NFTest/hwPkt.py new file mode 100644 index 0000000..3474787 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/hwPkt.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +# Junior University +# Copyright (C) 2011 Eric Lo +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +import sys +from threading import Thread, Lock, Event +import time +import socket +import os +from collections import deque +from select import select +from scapy.all import * +from .scapy_sniff_patch import sniff + +class pktExpect(Thread): + ############################ + # Function: __init__ + # Arguments: calling object + # device name to sniff + # Description: overrides Thread.__init__, initializes vars + ############################ + def __init__ (self, device): + Thread.__init__(self) + self.daemon = True + self.device = device + self.done = False + self.ready = False + self.count = 0 + self.pkts = [] + self.exp_pkts = [] + self.matched =[] + self.lock = Lock() + self.status = -1 + self.compareEvent = Event() + self.compare = pktCompare(self) + self.barrierEvent = Event() + self.started = False + + ############################ + # Function: run + # Arguments: calling object + # Description: starts background comparison thread, runs sniff + ############################ + def run(self): + self.compare.start() + self.started = True + while not self.done: + try: + sniff(prn=self.addPkt,iface=self.device, store=0, + stopperTimeout=1, stopper=self.isDone) + except(KeyboardInterrupt): + self.finish() + + ############################ + # Function: hasStarted + # Arguments: calling object + # Description: checks if the run method has been called + ############################ + def hasStarted(self): + return self.started + + ############################ + # Function: addPkt + # Arguments: calling object + # packet to add to pkts + # Description: adds packet to either matched or received packets list + # notifies background thread to compare packet lists + ############################ + def addPkt(self,pkt): + self.lock.acquire() + self.pkts.append(pkt) + self.count += 1 + self.barrierEvent.clear() + self.lock.release() + #if self.compareEvent.is_set(): + # pass + #else: + # self.compareEvent.set() + + ############################ + # Function: isDone + # Arguments: calling object + # Description: tells sniff if it should stop + # sets ready so client knows it can start sending packets + ############################ + def isDone(self): + self.ready = True + return self.done + + ############################ + # Function: isReady + # Arguments: calling object + # Description: tells client if sniff is ready to receive packets + ############################ + def isReady(self): + return self.ready + + ############################ + # Function: expectPkt + # Arguments: calling object + # packet to expect + # optional mask to apply to packet + # Description: adds packet to list of packets to expect + ############################ + def expectPkt(self, pkt, mask = None): + self.lock.acquire() + self.exp_pkts.append((pkt, mask)) + self.barrierEvent.clear() + self.lock.release() + + ############################ + # Function: comparePkts + # Arguments: calling object + # pkt A + # pkt B + # mask to use while comparing packets + # Description: compares to packets, using the optional mask to ignore + # certain bytes + ############################ + def comparePkts(self, pkta, pktb, mask = None): + if mask: + pkta = [ord(x) for x in pkta] + pktb = [ord(x) for x in pktb] + mask = [ord(x) for x in mask] + for i in range(min(len(pkta), len(mask))): + pkta[i] = pkta[i] & ~mask[i] + for i in range(min(len(pktb), len(mask))): + pktb[i] = pktb[i] & ~mask[i] + + pkta = ''.join([chr(x) for x in pkta]) + pktb = ''.join([chr(x) for x in pktb]) + + return pkta == pktb + + ############################ + # Function: resolvePkts + # Arguments: calling object + # Description: checks unmatched received packets against unmatched expected packets + # notifies barrierEvent if expected and received packet lists are empty + ############################ + def resolvePkts(self): + self.lock.acquire() + if (len(self.pkts) > 0) and (len(self.exp_pkts) > 0): + self.barrierEvent.clear() + i = 0 + numPkts = len(self.pkts) + while i < numPkts: + strpkt = str(self.pkts[i]) + for (exp, mask) in self.exp_pkts: + strexp = str(exp) + strmask = None + if mask: + strmask = str(mask) + matches = self.comparePkts(strexp, strpkt, strmask) + if not matches and len(exp) < 60 and self.pkts[i].haslayer(scapy.Padding): + matches = self.comparePkts( + ''.join([strexp,str(self.pkts[i][scapy.Padding])]), + strpkt, strmask) + if matches: + self.matched.append(self.pkts[i]) + self.pkts.remove(self.pkts[i]) + self.exp_pkts.remove((exp, mask)) + numPkts -= 1 + i -= 1 + break + i += 1 + self.lock.release() + if (len(self.exp_pkts) == 0): + self.barrierEvent.set() + return True + return False + + ############################ + # Function: restart + # Arguments: calling object + # Description: resets all packet lists + ############################ + def restart(self): + self.lock.acquire() + self.exp_pkts = [] + self.pkts = [] + self.matched = [] + self.lock.release() + + + ############################ + # Function: finish + # Arguments: calling object + # Description: tells sniff to stop sniffing + # returns packets + ############################ + def finish(self): + print(self.device, 'finishing up') + self.done = True + self.lock.acquire() + exp_pkts = [ exp for (exp, mask) in self.exp_pkts ] + #print "\n\n\n -------------- received=%d and exptected=%d --------------- \n\n" % (len(self.pkts), len(exp_pkts)) + return (self.matched, self.pkts, exp_pkts) + +class pktSend(Thread): + ############################ + # Function: __init__ + # Arguments: calling object + # device name + # socket configuration options + # Description: overrides Thread.__init__, initializes vars, opens socket + ############################ + def __init__(self, device, family = socket.AF_PACKET, + type = socket.SOCK_RAW, proto = socket.htons(3)): + Thread.__init__(self) + self.daemon = True + self.lock = Lock() + self.closed = False + self.toSend = deque() + self.sock = socket.socket(family, type, proto) + self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0) + while True: + r,w,x = select.select([self.sock.fileno()], [], [], 0) + if r: + os.read(self.sock.fileno(),1600) + else: + break + self.sock.bind((device,3)) + self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30) + self.sentcount = 0 + self.sendcount = 0 + self.device = device + + ############################ + # Function: run + # Arguments: calling object + # Description: overrides Thread.run, sends packets in queue + ############################ + def run(self): + while not self.closed: + try: + if len(self.toSend) > 0: + self.lock.acquire() + self.sock.send(bytes(self.toSend.popleft())) + self.sentcount += 1 + self.lock.release() + except(KeyboardInterrupt): + self.close() + + ############################ + # Function: sendPkt + # Arguments: calling object + # packet to send + # Description: adds packets to queue to be sent + # delays so scapy doesn't drop packets + ############################ + def sendPkt(self, pkt): + self.lock.acquire() + self.toSend.append(pkt) + self.sendcount += 1 + self.lock.release() + + ############################ + # Function: close + # Arguments: calling object + # Description: waits for packets to drain, then closes socket + ############################ + def close(self): + while len(self.toSend) > 0: + pass + if self.closed: + return + self.closed = True + self.sock.close() + +class pktCompare(Thread): + ############################ + # Function: __init__ + # Arguments: calling object + # pktExpect object + # Description: overrides Thread.__init__, initializes vars + ############################ + def __init__ (self, expect): + Thread.__init__(self) + self.daemon = True + self.done = False + self.compareEvent = expect.compareEvent + self.compare = expect.resolvePkts + + ############################ + # Function: run + # Arguments: calling object + # Description: waits until woken by addPkt, then calls resolvePkts + ############################ + def run(self): + while not self.done: + self.compareEvent.wait() + self.compare() + self.compareEvent.clear() diff --git a/tools/scripts/NFTest/NFTest/hwPktLib.py b/tools/scripts/NFTest/NFTest/hwPktLib.py new file mode 100644 index 0000000..e30613c --- /dev/null +++ b/tools/scripts/NFTest/NFTest/hwPktLib.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +from . import hwPkt +import sys +import os + +import time + +try: + import scapy.all as scapy +except: + try: + import scapy as scapy + except: + sys.exit("Error: need to install scapy for packet handling") + +ifaceArray = [] +captureThreads = {} +openSockets = {} +packets = {} +toIgnore = {} +barrier_timeouts = 0 + +pcap_dir = "hw_pcaps/" + +############################ +# Function: init +# Arguments: list of interfaces to sniff +# Description: populates ifaceArray +############################ +def init(active_ports): + for iface in active_ports: + ifaceArray.append(iface) + +############################ +# Function: start +# Arguments: none +# Description: starts capture threads +############################ +def start(): + for iface in ifaceArray: + captureThreads[iface] = hwPkt.pktExpect(iface) + openSockets[iface] = hwPkt.pktSend(iface) + packets[iface] = {} + toIgnore['layer'] = [] + toIgnore['method'] = [] + captureThreads[iface].start() + openSockets[iface].start() + alive = False + time.sleep(3.0) + # block until all capture threads are ready + while not alive: + alive = True + for iface in ifaceArray: + alive &= captureThreads[iface].isAlive() + if not captureThreads[iface].isAlive() and captureThreads[iface].hasStarted(): + raise RuntimeError("Thread on %s started and terminated..."%iface) + +############################ +# Function: restart +# Arguments: none +# Description: resets all packet lists +############################ +def restart(): + for pkts in packets: + pkts = {} + for iface in ifaceArray: + captureThreads[iface].restart() + +############################ +# Function: send +# Arguments: interface name +# packet to send +# (optional) expect packet, default is true +# Description: sends packet on an interface, expect the packet if specified +############################ +def send(ifaceName, pkt, exp = True): + try: + openSockets[ifaceName].sendPkt(pkt) + except(KeyError): + print('Error: invalid interface name') + if exp: + expect(ifaceName, pkt) + +############################ +# Function: expect +# Arguments: interface name +# packet to expect +# optional mask to apply to packet +# Description: expects a packet on an interface +############################ +def expect(ifaceName, pkt, mask = None): + captureThreads[ifaceName].expectPkt(pkt, mask) + +############################ +# Function: barrier +# Arguments: (optional) timeout in seconds, default is 10 sec +# Description: blocks execution until expected packets arrive, or times out +# returns False if timed out +############################ +def barrier(timeout = 10): + # wait until no more packets are received + # we assume that if no packets are received within 1 second, then no more traffic is expected + prevCount = 0 + while True: + sumCount = 0 + for iface in ifaceArray: + sumCount += captureThreads[iface].count + if sumCount == prevCount: + break + prevCount = sumCount + time.sleep(1.0) + + #print "\n\n--BARRIER1-------we are no longer receiving traffic--------" + + # trigger the post-test packet verification/comparison and wait it to finish + for iface in ifaceArray: + captureThreads[iface].compareEvent.set() # start verification in parallel + for iface in ifaceArray: + while captureThreads[iface].compareEvent.isSet(): + time.sleep(0.2) + + #print "\n--BARRIER2-------the bulk of the verification is done--------" + + # get the status of the verification and wait for potentially delayed packets + waitPerIteration = float(timeout)/(len(ifaceArray)*5.0) + stop = time.time() + timeout + good = False + while not good and stop > time.time(): + good = True + for iface in ifaceArray: + captureThreads[iface].compareEvent.set() + for iface in ifaceArray: + captureThreads[iface].barrierEvent.wait(waitPerIteration) + good &= captureThreads[iface].barrierEvent.is_set() + + #print "\n--BARRIER3-------the barrier is done--------" + + #start = time.clock() + #good = False + #while timeout + start - time.clock() > 0: + # good = True + # for iface in ifaceArray: + # captureThreads[iface].compareEvent.set() + # for iface in ifaceArray: + # captureThreads[iface].barrierEvent.wait(timeout-start) + # good &= captureThreads[iface].barrierEvent.is_set() + # if good: + # break + + if not good: + print('Error: barrier timed out after', str(timeout), 'seconds') + for iface in ifaceArray: + numUnexp = captureThreads[iface].pkts.__len__() + numExp = captureThreads[iface].exp_pkts.__len__() + if numUnexp > 0: + print('Error: device', iface, 'saw', end=' ') + print(str(numUnexp), 'unexpected packets') + if numExp > 0: + print('Error: device', iface, 'missed', end=' ') + print(str(numExp), 'expected packets') + print('') + global barrier_timeouts + barrier_timeouts += 1 + return good + +############################ +# Function: compare +# Arguments: list of expected packets +# list of unexpected packets +# Description: compares expected packets to unexpected packets +# prints comparison +############################ +def compare(exp, unexp): + numExp = exp.__len__() + numUnexp = unexp.__len__() + # check if there is anything to compare + if numExp == 0 and numUnexp == 0: + return 0 + elif numExp == 0: + print('Error:', str(numUnexp), 'unexpected packets seen') + return numUnexp + elif numUnexp == 0: + print('Error:', str(numExp), 'expected packets not seen') + return numExp + + # print differences between exp and unexp pkts + print(str(numExp), 'expected packets not seen') + print(str(numUnexp), 'unexpected packets') + for i in range(numExp): + print('Expected packet', str(i)) + for j in range(numUnexp): + if len(exp[i]) != len(unexp[j]): + print(' Unexpected packet ' + str(j), end=' ') + print(': Packet lengths do not match, expecting', end=' ') + print(str(len(exp[i])), 'but saw', str(len(unexp[j]))) + else: + str_exp_pkt = '' + str_unexp_pkt = '' + # generate a hex string + for x in str(exp[i]): + str_exp_pkt += "%02X"%ord(x) + for x in str(unexp[j]): + str_unexp_pkt += "%02X"%ord(x) + for k in range(len(str_exp_pkt)): + if str_unexp_pkt[k] != str_exp_pkt[k]: + print(' Unexpected packet ' + str(j) + ': byte', end=' ') + print(str(k/2), end=' ') + print('(starting from 0) not equivalent (EXP:', end=' ') + print(str_exp_pkt[i:i+2] + ', ACTUAL:', end=' ') + print(str_unexp_pkt[k:k+2] + ')') + break + + return numExp + numUnexp + +############################ +# Function: finish +# Arguments: none +# Description: closes capture threads, filters by toIgnore, +# calls pktCmp, writes pcap files, return # errors +############################ +def finish(): + pkts = () + ignored = [] + from .hwRegLib import get_bad_reads + bad_reads = get_bad_reads() + error_count = 0 + + if not os.path.isdir(pcap_dir): + os.mkdir(pcap_dir) + for iface in ifaceArray: + openSockets[iface].close() + # close capture threads, record packets + pkts = captureThreads[iface].finish() + # filter packets + packets[iface]['Matched'] = pkts[0] + packets[iface]['Unexpected'] = pkts[1] + packets[iface]['Expected'] = pkts[2] + # list(filter(packets[iface]['Matched'], ignored)) + # list(filter(packets[iface]['Unexpected'], ignored)) + # list(filter(packets[iface]['Expected'], ignored)) + + # show differences between packets + error_count += compare(packets[iface]['Expected'], + packets[iface]['Unexpected']) + + # write pcap files - TO IMPLEMENT: write to tmp dir + if packets[iface]['Matched'].__len__() > 0: + scapy.wrpcap(pcap_dir + iface+"_matched.pcap", packets[iface]['Matched']) + if packets[iface]['Expected'].__len__() > 0: + scapy.wrpcap(pcap_dir + iface+"_expected.pcap", packets[iface]['Expected']) + if packets[iface]['Unexpected'].__len__() > 0: + scapy.wrpcap(pcap_dir + iface+"_extra.pcap", packets[iface]['Unexpected']) + if ignored.__len__() > 0: + scapy.wrpcap(pcap_dir + iface + "_ignored.pcap", ignored) + # check for bad regread_expect + try: + num_bad_reads = bad_reads[iface].__len__() + error_count += num_bad_reads + except(KeyError): + pass + error_count += barrier_timeouts + return error_count + +############################ +# Function: filter +# Arguments: list of packets to filter, list to add ignored packets to +# Description: removes packets to be ignored +############################ +def filter(pktlist, ignorelist): + if pktlist.__len__() <= 0: + return + ignored = [] + for layer in toIgnore['layer']: + for pkt in pktlist: + if pkt.haslayer(layer): + duplicate = False + for ignorepkt in ignored: + if pkt == ignorepkt: + duplicate = True + if not duplicate: + ignored.append(pkt) + for method in toIgnore['method']: + for pkt in pktlist: + if method(pkt): + duplicate = False + for ignorepkt in ignored: + if pkt == ignorepkt: + duplicate = True + if not duplicate: + ignored.append(pkt) + for pkt in ignored: + pktlist.remove(pkt) + ignorelist.extend(ignored) + +############################ +# Function: ignore +# Arguments: filter +# (optional) method +# Description: adds string name of scapy layer to ignore +# or adds method to ignore if method is True +############################ +def ignore(filter, method = False): + # filter by layer + if not method: + toIgnore['layer'].append(filter) + # filter by method(pkt), returning truth value + else: + toIgnore['method'].append(filter) + +############################ +# Function: len +# Arguments: packet +# Description: overrides len(pkt) to account for packets of length < 60 +############################ +def len(pkt): + length = pkt.__str__().__len__() + if length < 60: + return 60 + return length diff --git a/tools/scripts/NFTest/NFTest/hwReg.py b/tools/scripts/NFTest/NFTest/hwReg.py new file mode 100755 index 0000000..be8a198 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/hwReg.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +from NFTest import * +import os +from fcntl import * +from ctypes import * + +# Loading the NFPLUS shared library +print("loading libsume..") +lib_path=os.path.join(os.environ['NFPLUS_FOLDER'],'sw','hwtestlib','libsume.so') +libsume=cdll.LoadLibrary(lib_path) + +# argtypes for the functions called from C +libsume.regread.argtypes = [c_uint] +libsume.regread.restype = c_uint +libsume.regwrite.argtypes= [c_uint, c_uint] + +def readReg(reg): + return libsume.regread(reg) + +def writeReg(reg, val): + return libsume.regwrite(reg, val) + +def regread_expect(reg, val): + return libsume.regread_expect(reg, val) diff --git a/tools/scripts/NFTest/NFTest/hwRegLib.py b/tools/scripts/NFTest/NFTest/hwRegLib.py new file mode 100644 index 0000000..9f791cb --- /dev/null +++ b/tools/scripts/NFTest/NFTest/hwRegLib.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +from . import hwReg +import time + +from .hwPktLib import ifaceArray + +import sys +import os + +# Import __main__ to access the reverse register map... +import __main__ + +sys.path.append(os.path.abspath(os.environ['NF_DESIGN_DIR']+'/lib/Python')) +project = os.path.basename(os.path.abspath(os.environ['NF_DESIGN_DIR'])) + +badReads = {} + +############################ +# Function: regwrite +# Arguments: nf2 interface to write to, register, value +# Description: writes value to register +############################ +def regwrite(reg, val): + hwReg.writeReg(reg, val) + +############################ +# Function: regread +# Arguments: nf2 interface to read from, register +# Description: reads value from register +############################ +def regread(reg): + return hwReg.readReg(reg) + +############################ +# Function: regread_expect +# Arguments: nf2 interface to read from, register, expected value, (optional) mask +# Description: reads value from register and compares with expected value +############################ +def regread_expect(reg, exp): + return hwReg.regread_expect(reg, exp) + +############################ +# Function: fpga_reset +# Arguments: none +# Description: resets the fpga +############################ +#def fpga_reset(): +# hwReg.resetNETFPGA('nf0') + +############################ +# Function: reset_phy +# Arguments: none +# Description: resets the phy +############################ +def reset_phy(): + for iface in ifaceArray: + if iface.startswith('nf'): + phy_reset(iface) + time.sleep(6) + +############################ +# Function: phy_loopback +# Arguments: nf2 interface to put in loopback +# Description: puts the specified nf2 interface in loopback +############################ +def phy_loopback(ifaceName): + if ifaceName.startswith('nf') and ifaceName[2].isdigit(): + portNum = int(ifaceName[2]) + else: + print('Interface has to be an nfX interface\n') + return + addr = (reg_defines.MDIO_PHY_0_CONTROL_REG(), + reg_defines.MDIO_PHY_1_CONTROL_REG(), + reg_defines.MDIO_PHY_2_CONTROL_REG(), + reg_defines.MDIO_PHY_3_CONTROL_REG()) + +############################ +# Function: phy_isolate +# Arguments: nf2 interface to isolate +# Description: puts the specified nf2 interface in isolation +############################ +def phy_isolate(ifaceName): + if ifaceName.startswith('nf') and ifaceName[2].isdigit(): + portNum = int(ifaceName[2]) + else: + print('Interface has to be an nfX interface\n') + return + addr = (reg_defines.MDIO_PHY_0_CONTROL_REG(), + reg_defines.MDIO_PHY_1_CONTROL_REG(), + reg_defines.MDIO_PHY_2_CONTROL_REG(), + reg_defines.MDIO_PHY_3_CONTROL_REG()) + +############################ +# Function: phy_reset +# Arguments: nf2 interface to reset +# Description: resets the phy for the specified interface +############################ +def phy_reset(ifaceName): + if ifaceName.startswith('nf') and ifaceName[2].isdigit(): + portNum = int(ifaceName[2]) + else: + print('Interface has to be an nfX interface\n') + return + addr = (reg_defines.MDIO_PHY_0_CONTROL_REG(), + reg_defines.MDIO_PHY_1_CONTROL_REG(), + reg_defines.MDIO_PHY_2_CONTROL_REG(), + reg_defines.MDIO_PHY_3_CONTROL_REG()) + +############################ +# Function: get_bad_reads +# Arguments: none +# Description: returns the dictionary of bad reads +############################ +def get_bad_reads(): + return badReads diff --git a/tools/scripts/NFTest/NFTest/scapy_sniff_patch.py b/tools/scripts/NFTest/NFTest/scapy_sniff_patch.py new file mode 100644 index 0000000..0ce8c5b --- /dev/null +++ b/tools/scripts/NFTest/NFTest/scapy_sniff_patch.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +import sys +import time +import select +from scapy.all import * + +# Override sniff from scapy to implement custom stopper +# from http://trac.secdev.org/scapy/wiki/PatchSelectStopperTimeout +def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, stopperTimeout=None, stopper = None, lst = [], *arg, **karg): + """Sniff packets +sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets + count: number of packets to capture. 0 means infinity + store: wether to store sniffed packets or discard them + prn: function to apply to each packet. If something is returned, + it is displayed. Ex: + ex: prn = lambda x: x.summary() +lfilter: python function applied to each packet to determine + if further action may be done + ex: lfilter = lambda x: x.haslayer(Padding) +offline: pcap file to read packets from, instead of sniffing them +timeout: stop sniffing after a given time (default: None) +stopperTimeout: break the select to check the returned value of + stopper() and stop sniffing if needed (select timeout) +stopper: function returning true or false to stop the sniffing process +L2socket: use the provided L2socket + """ + c = 0 + + if offline is None: + if L2socket is None: + L2socket = conf.L2listen + s = L2socket(type=ETH_P_ALL, *arg, **karg) + else: + s = PcapReader(offline) + + if timeout is not None: + stoptime = time.time()+timeout + remain = None + + if stopperTimeout is not None: + stopperStoptime = time.time()+stopperTimeout + remainStopper = None + while 1: + try: + if timeout is not None: + remain = stoptime-time.time() + if remain <= 0: + break + + if stopperTimeout is not None: + remainStopper = stopperStoptime-time.time() + if remainStopper <=0: + if stopper and stopper(): + break + stopperStoptime = time.time()+stopperTimeout + remainStopper = stopperStoptime-time.time() + + sel = select.select([s],[],[],remainStopper) + if s not in sel[0]: + if stopper and stopper(): + break + else: + sel = select.select([s],[],[],remain) + + if s in sel[0]: + p = s.recv(MTU) + if p is None: + break + if lfilter and not lfilter(p): + continue + if store: + lst.append(p) + c += 1 + if prn: + r = prn(p) + if r != None: + print(r) + if count > 0 and c >= count: + break + except KeyboardInterrupt: + break + s.close() + return scapy.plist.PacketList(lst,"Sniffed") diff --git a/tools/scripts/NFTest/NFTest/simLib.py b/tools/scripts/NFTest/NFTest/simLib.py new file mode 100644 index 0000000..e7c8a96 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/simLib.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +# Junior University +# Copyright (C) 2011 James Hsi, Eric Lo +# Copyright (c) 2015 Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +################################################################################ +# Description: +# Overarching test module. +# Creates and maintains file objects through file writes during tests. +# python -m pdb +# + +from NFTest import * +import os + +NUM_PORTS = 2 +NF2_MAX_PORTS = 2 +DMA_QUEUES = 2 + +#instantiation +f_ingress = [] +f_expectPHY = [] +f_expectDMA = [] +f_dma = [] +f_regstim = [] +f_regexpect = [] + +# directory = 'packet_data' +dma_stim = 'dma_0_stim.axi' +dma_expect = 'dma_' +ingress_fileHeader = 'nf_interface_' # 'ingress_port_' +expectPHY_fileHeader = 'nf_interface_' # 'expected_port_' +reg_expect = 'reg_expect.axi' +reg_stim = 'reg_stim.axi' + +############################ +# Function: init() +# Creates the hardware and simulation files to be read by ModelSim, +############################ +def init(): + + global f_dma; global f_regstim; global f_regexpect + f_dma = open(dma_stim,'w') + f_regstim = open(reg_stim, 'w') + f_regexpect = open(reg_expect, 'w') + + for i in range(NUM_PORTS): + filename = ingress_fileHeader + str(i) + "_stim.axi" + f_ingress.append(open(filename, 'w')) + + for i in range(NUM_PORTS): + filename = expectPHY_fileHeader + str(i) + "_expected.axi" + f_expectPHY.append(open(filename, 'w')) + + for i in range(NUM_PORTS): + filename = dma_expect + str(i) + "_expected.axi" + f_expectDMA.append(open(filename, 'w')) + +############################ +# Function: writeFileHeader +# Writes timestamp and general information to file head. +############################ +def writeFileHeader(fp, filePath): + from time import gmtime, strftime + fp.write("//File " + filePath + " created " + + strftime("%a %b %d %H:%M:%S %Y", gmtime())+"\n") + fp.write("//\n//This is a data file intended to be read in by a " + + "Verilog simulation.\n//\n") + + +############################ +# Function: writeXMLHeader +# Writes timestamp and general information to file head. +############################ +def writeXMLHeader(fp, filePath): + from time import gmtime, strftime + fp.write("\n") + fp.write("\n") + if str.find(filePath, expectPHY_fileHeader)>0: + fp.write("\n") + fp.write("\n") + elif str.find(filePath, expectDMA_fileHeader)>0: + fp.write("") + fp.write("\n") + fp.write("\n") + + +############################ +# Function: close() +# Closes all file pointers created during initialization. +# Must be called at the end of every test file. +############################ +def close(): + f_dma.close() + f_regstim.close() + f_regexpect.close() + + for i in range(NUM_PORTS): + f_ingress[i].close() + + for i in range(NUM_PORTS): + f_expectPHY[i].close() + + for i in range(NUM_PORTS): + f_expectDMA[i].close() + +############################ +# Function: fregstim(), fregexpect() +# A Getter that returns the file pointer for file with +# register read/write info. +############################ +def fregstim(): + return f_regstim + +def fregexpect(): + return f_regexpect + +############################ +# Function: fDMA +# A Getter that returns the file pointer for file with DMA read/write info. +############################ +def fDMA(): + return f_dma + + +############################ +# Function: fPort +# Argument: port - int - port for which read/write is occurring +# (Should be 1-4, NOT THE INDEX OF ARRAY) +# A Getter that returns the file pointer for file with PHY read/write info. +# +############################ +def fPort(port): + return f_ingress[port-1] # 0,1,2,3 + + +############################ +# Function: fExpectPHY +# Argument: port - int - port for which read/write is occurring +# (Should be 1-4, NOT THE INDEX OF ARRAY) +# A Getter that returns the file pointer for file with PHY read/write info. +# +############################ +def fExpectPHY(port): + return f_expectPHY[port-1] + + +############################ +# Function: fExpectDMA +# Argument: port - int - port for which read/write is occurring +# (Should be 1-4, NOT THE INDEX OF ARRAY) +# A Getter that returns the file pointer for file with DMA read/write info. +# +############################ +def fExpectDMA(port): + return f_expectDMA[port-1] diff --git a/tools/scripts/NFTest/NFTest/simPkt.py b/tools/scripts/NFTest/NFTest/simPkt.py new file mode 100644 index 0000000..6f5c671 --- /dev/null +++ b/tools/scripts/NFTest/NFTest/simPkt.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +# Junior University +# Copyright (C) 2011 James Hsi, Eric Lo +# Copyright (c) 2015 Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +from NFTest import * + +from . import simLib +from . import simReg +import os +import sys + +script_dir = os.path.dirname( sys.argv[0] ) +# Add path *relative to this script's location* of axitools module +sys.path.append( os.path.join( script_dir, '..','..','..','..','tools','scripts' ) ) + +# NB: axitools import must preceed any scapy imports +import axitools + +NUM_PORTS = 2 + +CMD_SEND = 1 +CMD_BARRIER = 2 +CMD_DELAY = 3 + +CMD_BARRIER_REG = 4 +CMD_PCI_DELAY = 5 + +f = [] + +# Global counters for synchronization +numExpectedPktsPHY = [0, 0, 0, 0]; numExpectedPktsDMA = [0, 0, 0, 0] +numSendPktsPHY = [0, 0, 0, 0]; numSendPktsDMA = [0, 0, 0, 0] + +# Packet counters +SentPktsPHYcount = [0, 0, 0, 0]; SentPktsDMAcount = [0, 0, 0, 0] +ExpectedPktsPHYcount = [0, 0, 0, 0]; ExpectedPktsDMAcount = [0, 0, 0, 0] + + +############################ +# Function: pktSendPHY +# Arguments: toPort - the port the packet will be sent to (1-4) +# pkt - the packet data, class scapy.Packet +# +############################ +def pktSendPHY(toPort, pkt): + numSendPktsPHY[toPort-1] += 1 + +############################ +# Function: pktSendDMA +# Arguments: toPort - the port the packet will be sent to (1-4) +# pkt - the packet data, class scapy.Packet +# +############################ +def pktSendDMA(toPort, pkt): + numSendPktsDMA[toPort-1] += 1 + +############################ +# Function: pktExpectPHY +# Arguments: atPort - the port the packet will be sent at (1-4) +# pkt - the packet data, class scapy.Packet +# mask - mask packet data, class scapy.Packet +# +############################ +def pktExpectPHY(atPort, pkt, mask = None): + numExpectedPktsPHY[atPort-1] += 1 + +############################ +# Function: pktExpectDMA +# Arguments: atPort - the port the packet will be expected at (1-4) +# pkt - the packet data, class scapy.Packet +# mask - mask packet data, class scapy.Packet +# +############################ +def pktExpectDMA(atPort, pkt, mask = None): + numExpectedPktsDMA[atPort-1] += 1 + +# Synchronization ######################################################## + +############################ +# Function: resetBarrier() +# +# Private function to be called by pktBarrier +############################ +def resetBarrier(): + global numExpectedPktsPHY; global numExpectedPktsDMA; global numSendPktsDMA; global numSendPktsPHY + numExpectedPktsPHY = [0, 0, 0, 0] + numExpectedPktsDMA = [0, 0, 0, 0] + numSendPktsPHY = [0, 0, 0, 0] + numSendPktsDMA = [0, 0, 0, 0] + +############################ +# Function: barrier +# Parameters: num - number of packets that must arrive +# Modifies appropriate files for each port and ingress_dma to denote +# a barrier request +############################ +def barrier(): + for i in range(NUM_PORTS): # 0,1,2,3 + simLib.fPort(i + 1).write("# BARRIER\n") + simLib.fPort(i + 1).write("B " + "%d\n"%CMD_BARRIER) + simLib.fPort(i + 1).write("# EXPECTED\n") + simLib.fPort(i + 1).write("N " + "%d\n"%(numExpectedPktsPHY[i])) + simLib.fPort(i + 1).write("# SENT\n") + simLib.fPort(i + 1).write("S " + "%d\n\n"%(numSendPktsPHY[i])) + simLib.fDMA().write("# BARRIER\n") + simLib.fDMA().write("B " + "%d\n"%CMD_BARRIER) + simLib.fDMA().write("# EXPECTED\n") + simLib.fDMA().write("N " + "%d\n"%(numExpectedPktsDMA[0])) + simLib.fDMA().write("# SENT\n") + simLib.fDMA().write("S " + "%d\n\n"%(numSendPktsDMA[0])) + simLib.fregstim().write("# BARRIER\n") + simLib.fregstim().write("B " + "%d\n"%CMD_BARRIER_REG) + for i in range(NUM_PORTS): + simLib.fregstim().write("# Interface " + "%d\n"%(i)) + simLib.fregstim().write("N " + "%d\n"%(numExpectedPktsPHY[i])) + simLib.fregstim().write("S " + "%d\n"%(numSendPktsPHY[i])) + simLib.fregstim().write("# DMA\n") + simLib.fregstim().write("N " + "%d\n"%(numExpectedPktsDMA[i])) + simLib.fregstim().write("S " + "%d\n"%(numSendPktsDMA[i])) + + resetBarrier() + +MSB_MASK = (0xFFFFFFFF00000000) +LSB_MASK = (0x00000000FFFFFFF) + +########################### +# Function: pktDelay +# +########################### +def delay(nanoSeconds): + for i in range(NUM_PORTS): + simLib.fPort(i+1).write("%08d"%CMD_DELAY + " // DELAY\n") + simLib.fPort(i+1).write("%08x"%(MSB_MASK & nanoSeconds) + + " // Delay (MSB) " + str(nanoSeconds)+" ns\n") + simLib.fPort(i+1).write("%08x"%(MSB_MASK & nanoSeconds) + + " // Delay (LSB) " + str(nanoSeconds)+" ns\n") + + simLib.fPCI().write("%08d"%CMD_PCI_DELAY+" // DELAY\n") + simLib.fPCI().write("%08x"%(MSB_MASK & nanoSeconds) + " // Delay (MSB) " + + str(nanoSeconds) + " ns\n") + simLib.fPCI().write("%08x"%(LSB_MASK & nanoSeconds) + " // Delay (LSB) " + + str(nanoSeconds) + " ns\n") diff --git a/tools/scripts/NFTest/NFTest/simReg.py b/tools/scripts/NFTest/NFTest/simReg.py new file mode 100644 index 0000000..0a7830b --- /dev/null +++ b/tools/scripts/NFTest/NFTest/simReg.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +# Junior University +# Copyright (C) 2011 James Hsi, Eric Lo +# Copyright (c) 2015 Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +from NFTest import * + +from . import simLib +from . import simPkt + +# IOCTL Commands +SIOCREGREAD = 0x89F0 +SIOCREGWRITE = 0x89F1 + +# Register Constants +CPCI_REG_CTRL = 0x008 + +# Register Values +CPCI_REG_CTRL_RESET = 0x00000100 + +NUM_PORTS = 4 +CMD_READ = 1 +CMD_WRITE = 2 +CMD_DMA = 3 +CMD_BARRIER = 4 +CMD_DELAY = 5 + +NUM_PORTS = 4 + +############################ +# Function: regDMA +# Arguments: +# queue is DMA queue #, length is packet length +############################ +def regDMA(queue, length): + f = simLib.fPCI() + f.write("// DMA: QUEUE: "+hex(queue)+ " LENGTH: "+hex(length)+"\n") + f.write("00000003 // DMA\n") + f.write("%08x"%queue +" // Queue ("+hex(queue)+")\n") + f.write("%08x"%length+" // Length ("+hex(length)+")\n") + f.write("00000000"+" // Mask (0x0)\n") + +############################ +# Function: regRead +# Arguments: +# reg is an address, value is data +############################ +def regRead(reg, val): + f = simLib.fregexpect() + simLib.fregexpect().write("# READ\n") + f.write("R " + "%08x\n"%CMD_READ) # // READ + f.write("%08x, "%reg) # // Address + f.write("%08x.\n"%val) # // Data + +############################ +# Frunction: regread +# Arguments: address +############################ +def regreadstim(reg): + f = simLib.fregstim() + simLib.fregstim().write("# READ\n") + f.write("R " + "%08x\n"%CMD_READ) # // READ + f.write("-, -, -, " + "%08x"%reg + ".\n") + +############################ +# Function: regWrite +# Arguments: +# reg is an address, value is data +############################ +def regWrite(reg, value): + f = simLib.fregstim() + f.write("# WRITE\n") + f.write("W " + "%08x\n"%CMD_WRITE) + f.write("%08x, "%reg) # // Address + f.write("%08x, "%value) # // Data + f.write("f, -.\n") + g = simLib.fregexpect() + g.write("# WRITE\n") + g.write("W " + "%08x\n"%CMD_WRITE) + g.write("%08x, "%reg) # // Address + g.write("%08x, "%value) # // Data + g.write("f, -.\n") + +# Synchronization ################################## + +MSB_MASK = (0xFFFFFFFF00000000) +LSB_MASK = (0x00000000FFFFFFF) + +############################ +# Function: regDelay +# Parameters: nanoSeconds - time to delay the entire simulation (in ns) +# Writes +############################ +def regDelay(nanoSeconds): + simLib.fregstim().write("# DELAY \n") + simLib.fregstim().write("D " + "%0d\n"%nanoSeconds) + simLib.fregstim().write("# DELAY (MSB) " + "%08x, "%(MSB_MASK & nanoSeconds) + str(nanoSeconds) + " ns\n") + simLib.fregstim().write("# DELAY (LSB) " + "%08x, "%(LSB_MASK & nanoSeconds) + str(nanoSeconds) + " ns\n") + diff --git a/tools/scripts/NFTest/testcheck.py b/tools/scripts/NFTest/testcheck.py new file mode 100644 index 0000000..168815a --- /dev/null +++ b/tools/scripts/NFTest/testcheck.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2015 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +import re + +oe = 1 + +def tcGetTestSeparator(): + return ' - ' + +def tcTestStarted(test): + if oe: + print("##testcheck[testStarted name='" + str(test) + "']") + +def tcTestFailed(test, msg, details): + if oe: + re.sub("'", "|'", msg) + re.sub("\n", "|n", msg) + re.sub("\r", "|r", msg) + + re.sub("'", "|'", details) + re.sub("\n", "|n", details) + re.sub("\r", "|r", details) + + if details == '': + details = msg + + print("##testcheck[testFailed name='" + str(test) + "' message='" + str(msg) + "' details='" + str(details) + "']") + +def tcTestFinished(test): + if oe: + print("##testcheck[testFinished name='" + str(test) + "']") + +def tcEnableOutput(): + global oe + oe = 1 + +def tcDisableOutput(): + global oe + oe = 0 + +def tcIsEnabled(): + return oe diff --git a/tools/scripts/axitools.py b/tools/scripts/axitools.py new file mode 100755 index 0000000..cc9ca01 --- /dev/null +++ b/tools/scripts/axitools.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +# Junior University +# Copyright (C) 2015 David J. Miller +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +################################################################################ +# +# File: +# axitools.py +# +# Description: +# A python module for manipulating AXI grammar formatted text. +# + +import math +import sys +import os +from NFTest import * + +# under cygwin, there is no hardware support - so suppress hardware initialisation +if sys.platform.startswith('cygwin'): + import scapy.config + scapy.config.conf.iface = '' + +from scapy.layers.all import Ether, raw + + +class BadAXIDataException( Exception ): + """ + AXI file format exceptions. + """ + def __init__( self, filename, lineno, msg ): + self.filename = filename + self.lineno = lineno + self.msg = msg + + def __str__( self ): + return '%s: %d: bad AXI data: %s' % (self.filename, self.lineno, self.msg) + + +def axis_dump( packets, f, bus_width, period, tuser_width = 128 ): + """ + Dumps the list of packets to an AXI Stream-grammar formatted text file. + Attribute .tuser (array of 128-bit integers) will supply TUSER if present, + and .tuser_sport and .tuser_dport, if present, will be applied (overriding) + any .tuser. + """ + + def tuser_mask( partial_mask ): + """ + Returns a full, tuser-width mask from partial_mask + """ + return int( ('%x' % partial_mask).rjust( tuser_width//4, 'f' ), 16 ) + + if bus_width % 8 != 0: + print("bus_width must be a multiple of 8!") + return + + bus_width = bus_width // 8 + strb_mask = (1 << bus_width) - 1 + last_ts = None + period = int(period * 1e9) + + #Cope with the case of individual packets being sent instead of a list + if isinstance(packets,Ether): + packets = [packets] + + for packet in packets: + # Output delay parameter + if last_ts is not None: + if (int(packet.time * 1e9)-last_ts) > 0 : + f.write( '+ %d\n' % (int(packet.time * 1e9)-last_ts) ) + else: + f.write( '@ %d\n' % (int(packet.time * 1e9))) + last_ts = int(packet.time * 1e9) + + # Set up TUSER + if hasattr( packet, 'tuser' ): + if type(packet.tuser) == list and type(packet.tuser[0]) == int: + tuser = packet.tuser + elif type(packet.tuser) == int: + tuser = [packet.tuser] + elif type(packet.tuser) == str: + tuser = [int(packet.tuser, 16)] + else: + raise TypeError( 'bad tuser data (not an array of ints)' ) + else: + tuser = [0] + # Override length, sport, dport fields as appropriate + tuser[0] = (tuser[0] & tuser_mask(0xffffff0000) ) | len(packet) + if hasattr( packet, 'tuser_sport' ): + tuser[0] = (tuser[0] & tuser_mask(0xffff00ffff) ) | (packet.tuser_sport << 16) + if hasattr( packet, 'tuser_dport' ): + tuser[0] = (tuser[0] & tuser_mask(0xff00ffffff) ) | (packet.tuser_dport << 24) + + # Turn into a list of bytes + packet = [x for x in bytes(packet)] + # Dump word-by-word + for i in range(0, len(packet), bus_width): + if len(packet)-i < bus_width: + padding = bus_width - (len(packet)-i) + word = packet[i:] + [0] * padding + else: + padding = 0 + word = packet[i:i+bus_width] + word.reverse() # TDATA is little-endian + if i + bus_width >= len(packet): + terminal = '.' + else: + terminal = ',' + + # Add TUSER pad to guarantee something is there to pop + tuser.append(0) + f.write( '%s, %s, %s%s\n' % ( + ''.join( '%02x' % x for x in word ), # TDATA + ('%x' % (strb_mask >> padding)).zfill(bus_width//4), # TSTRB + ('%x' % tuser.pop(0)).zfill(tuser_width//4), # TUSER + terminal ) ) # TLAST + + # one clock tick + last_ts += period + f.write( '\n' ) + +def axis_reg( packets, f ): + last_ts = None + for packet in packets: + if last_ts is not None: + if (int(packet.time * 1e9)-last_ts) > 0 : + f.write( '+ %d\n' % (int(packet.time * 1e9)-last_ts) ) + else: + f.write( '@ %d\n' % (int(packet.time * 1e9))) + last_ts = int(packet.time * 1e9) + + +def axis_load( f, period ): + """ + Loads packets from an AXI Stream-grammar formatted text file as a list of + Scapy packet instances. The following extra attributes are added to each + instance: + .tuser raw contents of TUSER, stored as array of 128-bit ints + .tuser_len packet length (from TUSER) + .tuser_sport source port (one-hot, from TUSER) + .tuser_dport dest port (one-hot, from TUSER) + """ + def as_bytes(x): + """ + Splits hex string X into list of bytes. + """ + return [int(x[i:i+2],16) for i in range(0,len(x),2)] + + bus_width = None + time = 0 + pkt_data = [] + tuser = [] + pkts = [] + for lno, line in enumerate(f): + lno += 1 + try: + # Look to see if a comment is present. If not, index() will throw + # an exception, and we skip this section. + hash_index = line.index( '#' ) + except ValueError: + pass + else: + line = line[:hash_index] + line = line.strip() + if not line: + continue + + # Handle delay specs + if line[0] == '@': + a = line.lstrip('@') + b = a.lstrip(' ') + time = int(b) + elif line[0] == '+': + time += int(line[1:])/1e9 + elif line[0] == '*': + time += period * int(line[1:]) + else: # treat as data + terminal = line[-1] + line = line[:-1] + if terminal not in [',', '.']: + raise BadAXIDataException( f.name, lno, 'unknown terminal %s' % terminal ) + line = [x.strip() for x in line.split(',')] + if len(line) != 3: + raise BadAXIDataException( f.name, lno, 'invalid data (expected 3 fields, got %d)' %len(line) ) + + # handle start of packet + if not pkt_data: + SoP_time = time + if bus_width is None: + bus_width = len(line[0]) * 4 + if math.log(bus_width,2) - int(math.log(bus_width,2)) != 0: + print('%s: data bus not a power of two in width' % f.name) + # accumulate packet and TUSER data + pkt_data += reversed( as_bytes( line[0].zfill( bus_width//4 ) ) ) + tuser.append( int( line[2], 16 ) ) + # handle end of packet + if terminal == '.': + valid_bytes = int( math.log( int( line[1], 16 ) + 1, 2 ) ) + if valid_bytes < bus_width//8: # trim off any padding + del pkt_data[valid_bytes-bus_width//8:] + pkts.append(Ether(raw(pkt_data))) + pkts[-1].time = SoP_time + pkts[-1].tuser = tuser + pkts[-1].tuser_len = tuser[0] & 0xffff + pkts[-1].tuser_sport = (tuser[0] >> 16) & 0xff + pkts[-1].tuser_dport = (tuser[0] >> 24) & 0xff + pkt_data = [] + tuser = [] + if len(pkts[-1]) != pkts[-1].tuser_len: + print('*** warning: meta length (%d) disagrees with actual length (%d) -- %s, line: %d' % ( pkts[-1].tuser_len , len(pkts[-1]), f.name, lno)) + time += period + return pkts diff --git a/tools/scripts/nf_sim_reconcile_axi_logs.py b/tools/scripts/nf_sim_reconcile_axi_logs.py new file mode 100755 index 0000000..61565bf --- /dev/null +++ b/tools/scripts/nf_sim_reconcile_axi_logs.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2010, 2011 The Board of Trustees of The Leland Stanford +# Junior University +# Copyright (C) 2015 David J. Miller +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +################################################################################ +# +# File: +# nf10_sim_reconcile_axi_logs.py +# +# Description: +# Reconciles *_log.axi with *_expected.axi. +# + +import axitools +import glob +import os +import sys + +EXPECTED_AXI = '_expected.axi' +LOG_AXI = '_log.axi' + +def reconcile_axi( log_pkts, exp_pkts ): + """ + Reconcile list of logged AXI packets with list of expected packets. + """ + if log_pkts == exp_pkts: + print('\tPASS (%d packets expected, %d packets received)' % (len(exp_pkts), len(log_pkts))) + return False + else: + print('\tFAIL (%d packets expected, %d packets received)' % (len(exp_pkts), len(log_pkts))) + return True + + +def main(): + fail = False + for expected_axi in glob.glob( '*%s' % EXPECTED_AXI ): + # Find log/expected pairs + log_axi = '%s%s' % (expected_axi[:-len(EXPECTED_AXI)], LOG_AXI) + if not os.path.isfile( log_axi ): + continue + print('Reconciliation of %s with %s' % (log_axi, expected_axi)) + # Load packets (time is ignored, so period=1e-9 is hard-coded) + with open( log_axi ) as f: + log_pkts = axitools.axis_load( f, 1e-9 ) + with open( expected_axi ) as f: + exp_pkts = axitools.axis_load( f, 1e-9 ) + fail |= reconcile_axi( log_pkts, exp_pkts ) + print() + sys.exit( fail ) + +if __name__ == '__main__': + main() diff --git a/tools/scripts/nf_sim_registers_axi_logs.py b/tools/scripts/nf_sim_registers_axi_logs.py new file mode 100755 index 0000000..36842ce --- /dev/null +++ b/tools/scripts/nf_sim_registers_axi_logs.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +import glob +import os +import sys +import csv, collections +import re + +REG_STIM = 'reg_stim.log' +REG_EXPECT = 'reg_expect.axi' +REG_AXI = 'reg_stim.axi' + +def expected(): + i = 0 + with open(REG_EXPECT) as f: + for line in f.readlines(): + i = i + 1 + return i + +def main(): + reg_stim = '%s' % (REG_STIM) + print('Check registers') + + with open(REG_EXPECT) as g: + r = 0 + w = 0 + for line in g.readlines(): + if 'R 00000001' in line: + r = r + 1 # read + elif 'W 00000002' in line: + w = w + 1 # write + + with open(REG_AXI) as k: + h = 0 + t = 0 + for line in k.readlines(): + if 'R 00000001' in line: + h = 1 # read + elif 'W 00000002' in line: + t = 1 # write + + with open( reg_stim ) as output: + f = output.readlines() + a = 0 + b = 0 + c = 0 + d = 0 + e = 0 + lines = 0 + + for line in f: + lines = lines + 1 + if 'Error' in line: + e = 1 + if '<' in line: + c = c + 1 # write + elif '>' in line: + d = d + 1 # read + else: + c = c + d = d + + elif 'WARNING' in line: + e = 2 + + else: + if '<' in line: + a = a + 1 # write + elif '>' in line: + b = b + 1 # read + else: + a = a + b = b + + if e == 1 or w != a or r != b: + print('\tFAIL ( Check reg_stim.log file!!!! )') + elif e == 2: + print('\tPASS ( WARNING! Check reg_stim.log file!!!! )') + elif lines == 0 and expected() != 0: + print('\tFAIL ( Did not get any results! )') + elif h != 1 and t != 1: + print('\tPASS ( No registers checked )') + else: + print('\tPASS') + + print() + return 0 + +if __name__ == '__main__': + main() diff --git a/tools/scripts/nf_test.py b/tools/scripts/nf_test.py new file mode 100755 index 0000000..0435260 --- /dev/null +++ b/tools/scripts/nf_test.py @@ -0,0 +1,642 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 University of Cambridge +# Copyright (c) 2015 Neelakandan Manihatty Bojan, Georgina Kalogeridou +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +# Author: +# Modified by Neelakandan Manihatty Bojan, Georgina Kalogeridou + +import os +import sys +import argparse +import glob +import subprocess + +script_dir = os.path.dirname( sys.argv[0] ) +# Add path *relative to this script's location* of testcheck module +sys.path.append( os.path.join( script_dir, 'NFTest' ) ) + +import testcheck + +import re + +GLOBAL_SETUP = 'global setup' +GLOBAL_TEARDOWN = 'global teardown' + +args = None + +rootDir = '' +project = '' +projDir = '' +workDir = '' + +work_test_dir = '' + +proj_test_dir = '' +src_test_dir = '' + +sim_opt = '' + +tests = [] + +REQUIRED = 1 +OPTIONAL = 0 + +teardown = 'teardown' +setup = 'setup' +run = 'run.py' +commonDir = 'common' +globalDir = 'global' +projectRoot = 'projects' +testRoot = 'test' + + +def run_hw_test(): + print('Root directory is ' + rootDir) + + #verify ci is correct if set + verifyCI() + + #verify the mapfile exists + if args.map: + try: + mapfile = open(args.map) + mapfile.close() + except IOError as exc: + print('Error opening mapfile ' + args.map) + print(exc.strerror) + sys.exit(1) + + #run regression tests on each project one-by-one + results = [] + testResults = {} + passed = True + commonPass = True + + test = args.citest + testcheck.tcGetTestSeparator() + 'global.setup' + if not args.quiet: + print(' Running global setup... ', end=' ') + testcheck.tcTestStarted(test) + (gsResult, output) = runGlobalSetup(project) + if not gsResult: + passed = False + + # Store the test results for later + testResults[GLOBAL_SETUP] = gsResult + test_result = ( GLOBAL_SETUP, gsResult, output) + results.append(test_result) + + # run checks + printScriptOutput(gsResult, output) + if not gsResult: + testcheck.tcTestFailed(test, 'Test failed', output) + testcheck.tcTestFinished(test) + + if gsResult: + for test in tests: + testStr = args.citest + testcheck.tcGetTestSeparator() + test + testcheck.tcTestStarted(testStr) + prepareTestWorkDir(test) + if not args.quiet: + sys.stdout.write(' Running test ' + os.path.basename(test) + '... ') + sys.stdout.flush() + + # Common setup + (csResult, csOutput) = runCommonSetup(project) + testResults[test] = csResult + passed &= csResult + commonPass &= csResult + + # Local setup -- only run if common setup passed + if csResult: + (lsResult, lsOutput) = runLocalSetup(project, test) + testResults[test] = lsResult + passed &= lsResult + + # Actual test -- only run if both setups succeed + if csResult and lsResult: + (testResult, testOutput) = runTest(project, test) + testResults[test] = testResult + passed &= testResult + + # Local teardown -- only run if both setups succeeded + if csResult and lsResult: + (ltResult, ltOutput) = runLocalTeardown(project, test) + testResults[test] = ltResult + passed &= ltResult + + # Common teardown -- only run if the common setup succeeded + if csResult: + (ctResult, ctOutput) = runCommonTeardown(project) + testResults[test] = ctResult + passed &= ctResult + commonPass &= ctResult + + testResult &= csResult & lsResult & ltResult & ctResult + + output = '' + if not csResult: + output += csOutput + if not lsResult: + output += lsOutput + if not testResult: + if testOutput != None: + output += testOutput + if not ltResult: + output += ltOutput + if not ctResult: + output += ctOutput + + if testResult: + output = testOutput + test_result = (test, testResult, output) + results.append(test_result) + + printScriptOutput(testResult, output) + if not testResult: + testcheck.tcTestFailed(testStr, 'Test failed', output) + testcheck.tcTestFinished(testStr) + + # store outputs, push (test, testResult, output) to results + if not commonPass: + break + if args.failfast and not testResult: + break + + # Run the teardown if the global setup passed and the tests passed or not failfast + if gsResult and ( not args.failfast or passed): + if not args.quiet: + print(' Running global teardown... ', end=' ') + (result, output) = runGlobalTeardown(project) + if not result: + passed = False + testResults[GLOBAL_TEARDOWN] = result + test_result = (GLOBAL_TEARDOWN, result, output) + results.append(test_result) + printScriptOutput(result, output) + if not result: + testcheck.tcTestFailed(test, 'Test failed', output) + testcheck.tcTestFinished(test) + if not args.quiet: + print('\n') + + if args.quiet and not passed: + print('Regression test suite failed\n') + print('Project failing tests: ' + project) + print('Tests failing within each project') + for testSummary in results: + if not testSummary[1]: + print('Test: ' + testSummary[0]) + print('-' * len(testSummary[0])) + print(testSummary[2]) + print('') + +def run_sim_test(): + verifyCI() + #set up test dirs + passed = []; failed = []; gui = [] + for td in tests: + if args.tx: + if args.gui: + if args.packet_length and args.packet_no: + charis = os.system("make simtxgui TESTNAME=sim_tx_dma PKTLEN=%d PKTNO=%d -C %s" % (length, number, designDIr + '/test/')) + elif args.packet_length: + charis = os.system("make simtxgui TESTNAME=sim_tx_dma PKTLEN=%d -C %s" % (length, designDIr + '/test/')) + elif args.packet_no: + charis = os.system("make simtxgui TESTNAME=sim_tx_dma PKTNO=%d -C %s" % (number, designDIr + '/test/')) + else: + charis = os.system("make simtxgui TESTNAME=sim_tx_dma -C %s" % (designDIr + '/test/')) + else: + if args.packet_length and args.packet_no: + charis = os.system("make simtx TESTNAME=sim_tx_dma PKTLEN=%d PKTNO=%d -C %s" % (length, number, designDIr + '/test/')) + elif args.packet_length: + charis = os.system("make simtx TESTNAME=sim_tx_dma PKTLEN=%d -C %s" % (length, designDIr + '/test/')) + elif args.packet_no: + charis = os.system("make simtx TESTNAME=sim_tx_dma PKTNO=%d -C %s" % (number, designDIr + '/test/')) + else: + charis = os.system("make simtx TESTNAME=sim_tx_dma -C %s" % (designDIr + '/test/')) + elif args.rx: + if args.gui: + if args.packet_length and args.packet_no: + charis = os.system("make simrxgui TESTNAME=sim_rx_dma PKTLEN=%d PKTNO=%d -C %s" % (length, number, designDIr + '/test/')) + elif args.packet_length: + charis = os.system("make simrxgui TESTNAME=sim_rx_dma PKTLEN=%d -C %s" % (length, designDIr + '/test/')) + elif args.packet_no: + charis = os.system("make simrxgui TESTNAME=sim_rx_dma PKTNO=%d -C %s" % (number, designDIr + '/test/')) + else: + charis = os.system("make simrxgui TESTNAME=sim_rx_dma -C %s" % (designDIr + '/test/')) + else: + if args.packet_length and args.packet_no: + charis = os.system("make simrx TESTNAME=sim_rx_dma PKTLEN=%d PKTNO=%d -C %s" % (length, number, designDIr + '/test/')) + elif args.packet_length: + charis = os.system("make simrx TESTNAME=sim_rx_dma PKTLEN=%d -C %s" % (length, designDIr + '/test/')) + elif args.packet_no: + charis = os.system("make simrx TESTNAME=sim_rx_dma PKTNO=%d -C %s" % (number, designDIr + '/test/')) + else: + charis = os.system("make simrx TESTNAME=sim_rx_dma -C %s" % (designDIr + '/test/')) + elif args.txrx: + if args.gui: + if args.packet_length and args.packet_no: + charis = os.system("make simtxrxgui TESTNAME=sim_txrx_dma PKTLEN=%d PKTNO=%d -C %s" % (length, number, designDIr + '/test/')) + elif args.packet_length: + charis = os.system("make simtxrxgui TESTNAME=sim_txrx_dma PKTLEN=%d -C %s" % (length, designDIr + '/test/')) + elif args.packet_no: + charis = os.system("make simtxrxgui TESTNAME=sim_txrx_dma PKTNO=%d -C %s" % (number, designDIr + '/test/')) + else: + charis = os.system("make simtxrxgui TESTNAME=sim_txrx_dma -C %s" % (designDIr + '/test/')) + else: + if args.packet_length and args.packet_no: + charis = os.system("make simtxrx TESTNAME=sim_txrx_dma PKTLEN=%d PKTNO=%d -C %s" % (length, number, designDIr + '/test/')) + elif args.packet_length: + charis = os.system("make simtxrx TESTNAME=sim_txrx_dma PKTLEN=%d -C %s" % (length, designDIr + '/test/')) + elif args.packet_no: + charis = os.system("make simtxrx TESTNAME=sim_txrx_dma PKTNO=%d -C %s" % (number, designDIr + '/test/')) + else: + charis = os.system("make simtxrx TESTNAME=sim_txrx_dma -C %s" % (designDIr + '/test/')) + elif args.gui: + charis = os.system("make simgui TESTNAME=%s -C %s" % (td, designDIr + '/test/')) + else: + charis = os.system("make sim TESTNAME=%s -C %s" % (td, designDIr + '/test/')) + print(charis) + + if args.type == 'sim': + subprocess.call(['cp', '-r', '-p', designDIr + '/hw/Makefile', src_test_dir]) + + if not args.no_compile: + buildSim() + if args.compile_only: + sys.exit(0) + prepareTestWorkDir(td) + global_run = designDIr + '/test/' + td + '/run.py' + dst_dir = proj_test_dir + '/' + td + which_run = global_run + cmd = [which_run, '--sim'] + os.chdir(dst_dir) + if args.isim: + cmd.append('isim') + elif args.vcs: + cmd.append('vcs') + elif args.vsim: + cmd.append('vsim') + else: + cmd.append('xsim') + if args.dump: + cmd.append('--dump') + if args.gui: + cmd.append('--gui') + if args.ci: + cmd.append('--ci') + cmd.append(args.ci) + cmd.append('--citest') + cmd.append(args.citest) + + #run tests + print('=== Running test ' + dst_dir + ' ...', end = " ") + print('using cmd', cmd) + +def handleArgs(): + parser = argparse.ArgumentParser() + parser.add_argument('type', choices=['hw','sim'], help='Type of test to run: hw or sw') + parser.add_argument('--quiet', action='store_true', help='Hardware only. Run in quiet mode; don\'t output anything unless there are errors.', default = False) + parser.add_argument('--major', help='Specify the string to match on the first part of the test directory name.', metavar='', default='') + parser.add_argument('--minor', help='Specify the string to match on the last part of the test directory name.', metavar='', default='') + parser.add_argument('--packet_length', help='Specify the lenght of the packet.', type=int) + parser.add_argument('--packet_no', help='Specify the number of the packet.', type=int) + parser.add_argument('--conn', help='Specify the conn file specifying the physical connections of the nfX ports. Formatting is one connection per line, nfX:ethY.', metavar='') + parser.add_argument('--map', help='Remap interfaces per mapfile, which is a list of two interfaces per line.', metavar='') + parser.add_argument('--ci', choices=['testcheck'], help='For use when using a continuout integration tool. Instructs the system to print out extra debugging information used by the CI tool.', metavar='') + parser.add_argument('--citest', help='The name of the top-level test to print error messages in when using the \'ci\' option.', metavar='', default='') + parser.add_argument('--failfast', action='store_true', help='Fail fast causes the regression suite to fail as soon as a test fails and not to run the teardown scripts.') + parser.add_argument('--common-setup', help='Hardware only. Run a custom setup script for each test', metavar='') + parser.add_argument('--common-teardown', help='Hardware only. Run a custom teardown script for each test.', metavar='') + parser.add_argument('--work_test_dir', help='Specify the directory where the compiled binary should be placed. Each test will have its own directory created beneath this directory.', metavar='') + parser.add_argument('--src_test_dir', help='Specify the directory where the test directories are located. Each directory should be named type__(where type is \'hw\', \'sw\'. or \'both\') and should contain an executable script called \'run.py\' that will perform the actual simulation and check the results if necessary.') + parser.add_argument('--make_opt', help='Simulation only. Specify a single string to be passed to make (e.g. to invoke a different make rule). Make is invoked using \'make -f ', default = '') + parser.add_argument('--sim_opt', help='Simulation only. This option allows the string to be passed to the HDL simulator. For example, a macro definition which is checked by the HDL testbench, a post-processing option, or a simulation delay model option.', default = '') + parser.add_argument('--dump', action='store_true', help='Simulation only. Normally the simulation will not produce a VCD file. If you want a VCD file then place a file \'dump.v\' in your src directory and specify this option. Then dump.v will be compile as a top level module.') + parser.add_argument('--vcs', action='store_true', help='Simulation only. If this option is present, vcs will run. Otherwise vsim will run.') + parser.add_argument('--vsim', action='store_true', help='Simulation only. If this option is present, vcs will run. Otherwise vsim will run.') + parser.add_argument('--isim', action='store_true', help='Simulation only. If this option is present, ISIM will run. Otherwise vsim will run.') + parser.add_argument('--gui', action='store_true', help='Simulation only. This will run the simulator in interactive mode (usually with a GUI).') + parser.add_argument('--tx', action='store_true', help='Simulation only. This will run the simulator sending from dma to phy.') + parser.add_argument('--rx', action='store_true', help='Simulation only. This will run the simulator sending from phy to dma.') + parser.add_argument('--txrx', action='store_true', help='Simulation only. This will run the simulator for loopback.') + parser.add_argument('--lenmin', action='store_true', help='Simulation only. This will run the simulator for min length of the packet.') + parser.add_argument('--lenmax', action='store_true', help='Simulation only. This will run the simulator for max length of the packet.') + parser.add_argument('--no_compile', action='store_true', help='Simulation only. This will not compile the simulation binary.') + parser.add_argument('--compile_only', action='store_true', help='Simulation only. This will only compile the simulation.') + parser.add_argument('--seed', nargs=1, help='Specify a seed for the random number generator to replay a previous run.') + + global args; args = parser.parse_args() + if args.type == 'sim': + if args.quiet or args.common_setup or args.common_teardown: + print('Error: --quiet, --common-setup, and --common-teardown are only compatible with hardware tests') + sys.exit(1) + else: + if args.make_opt or args.sim_opt or args.dump or args.vcs or args.vsim or args.isim or args.gui or args.no_compile or args.compile_only: + print('Error: --make_opt, --sim_opt, --dump, --vcs, --vsim --isim, and --gui are only compatible with simulation tests') + sys.exit(1) + +def printEnv(): + print("NetFPGA environment:") + print(" Root dir: " + rootDir) + print(" Project name: " + project) + print(" Project dir: " + projDir) + print(" Work dir: " + workDir) + + if args.type == 'sim': + subprocess.call(['cp', '-r', '-p', designDIr + '/hw/Makefile', src_test_dir]) + os.system("make reg -C %s" % (designDIr + '/test/')) + else: + os.system("make reg -C %s" % (designDIr + '/hw/')) + +# verify that NF_ROOT has been set and exists +def identifyRoot(): + global rootDir; global projDir; global designDIr + try: + rootDir = os.path.abspath(os.environ['NFPLUS_FOLDER']) + designDIr = os.path.abspath(os.environ['NF_DESIGN_DIR']) + projDir = designDIr + + if not os.path.exists(rootDir): + print("NetFPGA directory " + rootDir + " as referenced by environment variable 'NFPLUS_FOLDER' does not exist") + except(KeyError): + print("Please set the environment variable 'NFPLUS_FOLDER' to point to the local NetFPGA source") + os.environ['NFPLUS_FOLDER'] = rootDir + +def identifyWorkDir(): + global workDir + try: + workDir = os.path.abspath(os.environ['NF_WORK_DIR']) + except(KeyError): + login = os.getlogin() + workDir = '/tmp/' + login + + if not os.path.exists(workDir): + try: + os.mkdir(workDir) + user = os.environ['USER'] + subprocess.call(['chown', '-R', user + ':' + user, workDir]) + except OSError as exc: + print("Cannot create work directory '" + workDir + "'") + print(exc.strerror, exc.filename) + sys.exit(1) + os.environ['NF_WORK_DIR'] = workDir + global work_test_dir + if args.work_test_dir: + work_test_dir = args.work_test_dir + else: + work_test_dir = workDir + '/test' + global proj_test_dir; global src_test_dir + global project; global projDir + project = os.path.basename(os.path.abspath(os.environ['NF_DESIGN_DIR'])) + projDir = os.environ['NF_WORK_DIR'] + '/test/' + project + proj_test_dir = work_test_dir + '/' + project + if args.src_test_dir: + src_test_dir = args.src_test_dir + else: + src_test_dir = os.environ['NF_DESIGN_DIR'] + '/test' + +def identifyTests(): + test_name = ''; both_test_name = '' + global length + global number + if args.major: + both_test_name = 'both_' + args.major + '_' + args.minor + if args.type == 'sim': + test_name = 'sim_' + args.major + '_' + args.minor + else: + test_name = 'hw_' + args.major + '_' + args.minor + else: + both_test_name = 'both_' + if args.type == 'sim': + test_name = 'sim_' + else: + test_name = 'hw_' + + if args.packet_length: + length = args.packet_length + + if args.packet_no: + number = args.packet_no + + dirs = os.listdir(os.environ['NF_DESIGN_DIR'] + '/test') + global tests;tests = [] + for test in dirs: + if test.endswith(test_name) or test.endswith(both_test_name): + tests.append(test) + if len(tests) == 0: + print('=== Error: No tests match ' + test_name + ' - exiting') + sys.exit(0) + +def prepareWorkDir(): + global project; global projDir + + if not os.path.exists(projDir): + user = os.environ['USER'] + try: + if not os.path.exists(os.environ['NF_WORK_DIR'] + '/test/'): + os.mkdir(os.environ['NF_WORK_DIR'] + '/test') + subprocess.call(['chown', '-R', user + ':' + user, os.environ['NF_WORK_DIR'] + '/test']) + os.mkdir(projDir) + subprocess.call(['chown', '-R', user + ':' + user, projDir]) + except OSError as exc: + print('Error: Unable to create project directory ' + projDir) + print(exc.strerror, exc.filename) + sys.exit(1) + # copy the connections directory for sim + subprocess.call(['cp', '-r', '-p', src_test_dir + '/connections', projDir]) + +def prepareTestWorkDir(testName): + dst_dir = proj_test_dir + '/' + testName + src_dir = src_test_dir + '/' + testName + # look for a test + if args.type == 'sim': + print('=== Setting up test in ' + dst_dir) + # check if exists, make if doesn't, error if fail + if not os.path.exists(dst_dir): + try: + os.mkdir(dst_dir) + except OSError as exc: + print('Error: Unable to create test directory ' + dst_dir) + print(exc.strerror, exc.filename) + sys.exit(1) + # cp files to dst_dir + if args.type == 'sim': + for file in glob.glob(src_dir + '/*'): + subprocess.call(['cp', '-r', '-p', file, dst_dir]) + for i in range(2): + subprocess.call(['cp', '-r', '-p', src_test_dir + '/nf_interface_%d_log.axi' %i, dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/nf_interface_%d_stim.axi' %i, dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/nf_interface_%d_expected.axi' %i, dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/dma_0_log.axi', dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/dma_0_expected.axi', dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/Makefile', dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/reg_stim.log', dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/reg_expect.axi', dst_dir]) + subprocess.call(['cp', '-r', '-p', src_test_dir + '/reg_stim.axi', dst_dir]) + +def buildSim(): + project = os.path.basename(os.path.abspath(os.environ['NF_DESIGN_DIR'])) + + print('=== Work directory is ' + proj_test_dir) + + if args.dump: + dumpfile = 'dump.v' + else: + dumpfile = '' + +def verifyCI(): + if args.ci and args.ci != 'testcheck': + print('Unknown continuous integration ' + args.ci + '. Supported CI programs: testcheck') + if args.ci and not args.citest: + print('The name of the test was not specified in \'citest\'') + + if args.ci != 'testcheck': + testcheck.tcDisableOutput() + +###### hw specific functions + +def runTest(project, test): + testDir = designDIr + '/' + testRoot + '/' + test + if os.path.exists(testDir) and os.path.isdir(testDir): + script = run + ' --hw' + if args.seed: + script += ' --seed ' + str(args.seed[0]) + if args.conn: + script += ' --conn ' + str(args.conn) + return runScript(project, test, script, REQUIRED) + else: + match = re.search(r'/(.*)\/([^\/]*)/', test) + if match: + script = match.group(2) + ' --hw' + if args.seed: + script += ' --seed ' + str(args.seed[0]) + if args.conn: + script += ' --conn ' + str(args.conn) + return runScript(project, match.group(1), script, REQUIRED) + else: + print('Error finding test file: ' + test) + sys.exit(1) + +def runGlobalSetup(project): + return runScript(project, globalDir, setup, OPTIONAL) + +def runGlobalTeardown(project): + return runScript(project, globalDir, teardown, OPTIONAL) + +def runCommonSetup(project): + return runScript(project, commonDir, commonSetup, OPTIONAL) + +def runCommonTeardown(project): + return runScript(project, commonDir, commonTeardown, OPTIONAL) + +def runLocalSetup(project, test): + match = re.search(r'/(.*)\/([^\/]*)/', test) + if match: + return runScript(project, match.group(1), setup, OPTIONAL) + else: + return runScript(project, test, setup, OPTIONAL) + +def runLocalTeardown(project, test): + match = re.search(r'/(.*)\/([^\/]*)/', test) + if match: + return runScript(project, match.group(1), teardown, OPTIONAL) + else: + return runScript(project, test, teardown, OPTIONAL) + +def runScript(project, subdir, script, required): + testDir = designDIr + '/' + testRoot + '/' + subdir + + if os.path.exists(testDir): + subprocess.call(['cp', '-r', '-p', testDir, proj_test_dir]) + user = os.environ['USER'] + subprocess.call(['chown', '-R', user + ':' + user, proj_test_dir + '/' + subdir]) + cmd = proj_test_dir + '/' + subdir + '/' + script + if args.map: + cmd += ' --map ' + args.map + + status = 0 + output = '' + + origDir = os.getcwd() + + try: + os.chdir(proj_test_dir + '/' + subdir) + # process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + process = subprocess.Popen(cmd.split(), stderr=subprocess.STDOUT) + output = process.communicate()[0] + status = process.returncode + except OSError as exc: + if required == REQUIRED: + print('Unable to run test ' + script + ' for project ' + project) + print(exc.strerror, exc.filename) + else: + return (1, '') + finally: + os.chdir(origDir) + + if status != 0: + print(cmd + ' exited with value ' + str(status)) + + return (status == 0, output) + +def printScriptOutput(result, output): + if not args.quiet: + if result: + print('PASS') + else: + print('FAIL') + print('Output was:') + print(output) + +####### method calls + +handleArgs() +identifyRoot() + +if args.common_setup: + commonSetup = args.common_setup +else: + commonSetup = setup +if args.common_teardown: + commonTeardown = args.common_teardown +else: + commonTeardown = teardown + +identifyWorkDir() +prepareWorkDir() +identifyTests() +printEnv() + +if args.type == 'sim': + run_sim_test() +else: + run_hw_test() + + + + diff --git a/tools/scripts/pci_rescan_run.sh b/tools/scripts/pci_rescan_run.sh new file mode 100755 index 0000000..84f159f --- /dev/null +++ b/tools/scripts/pci_rescan_run.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (c) 2015-2021 University of Cambridge +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme, +# and by the University of Cambridge Computer Laboratory under EPSRC EARL Project +# EP/P025374/1 alongside support from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ + +# Run bash pci_rescan_run.sh + +PcieBusPath=/sys/bus/pci/devices +PcieDeviceList=`ls /sys/bus/pci/devices/` +bus0="fail" +bus1="fail" +for BusNo in $PcieDeviceList +do + VenderId=`cat $PcieBusPath/$BusNo/device` + if [[ "$VenderId" = "0x903f" ]]; then + echo 1 > /sys/bus/pci/devices/$BusNo/remove + sleep 1 + echo 1 > /sys/bus/pci/rescan + echo + echo "Completed rescan PCIe information !" + echo + bus0="pass" + fi +done + +for BusNo in $PcieDeviceList +do + VenderId=`cat $PcieBusPath/$BusNo/device` + if [[ "$VenderId" = "0x913f" ]]; then + echo 1 > /sys/bus/pci/devices/$BusNo/remove + sleep 1 + echo 1 > /sys/bus/pci/rescan + echo + echo "Completed rescan PCIe information !" + echo + bus1="pass" + fi +done + +if [ $bus0 == "fail" ] | [ $bus1 == "fail" ]; then + echo "Check programming FPGA or Reboot machine !" +fi diff --git a/tools/scripts/python_parser.py b/tools/scripts/python_parser.py new file mode 100755 index 0000000..ae5b9c4 --- /dev/null +++ b/tools/scripts/python_parser.py @@ -0,0 +1,57 @@ +#!/usr/bin/python3 + +# Copyright (c) 2015 Neelakandan Manihatty Bojan +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +################################################################################ +# Description: +# This is used to convert reg_defines.h to reg_defines.py +# + +import re + +input_file = open("reg_defines.h", "r") +output_file = open("reg_defines.py", "w") +output_file.write("#!/usr/bin/python") +for line in input_file: + match_defines = re.match(r'\s*#define ([a-zA-Z_0-9]+) (.*)', line) + match_comments = re.match(r'\s*[/\*][\s*\*](.*)', line) + match_slash = re.match(r'\s*[/*](.*)', line) + + if match_defines: + newline1= "\ndef %s():\n return %s" % (match_defines.group(1),match_defines.group(2)) + output_file.write(newline1) + + elif match_comments: + newline2= "\n# %s" % (match_comments.group(1)) + output_file.write(newline2) + + elif match_slash: + newline3= "\n# %s" % (match_slash.group(1)) + output_file.write(newline3) + + else: + output_file.write(line) + + diff --git a/tools/scripts/xparam2regdefines.py b/tools/scripts/xparam2regdefines.py new file mode 100755 index 0000000..7910f95 --- /dev/null +++ b/tools/scripts/xparam2regdefines.py @@ -0,0 +1,97 @@ +#!/usr/bin/python3 + +# +# Copyright (c) 2015 Neelakandan Manihatty Bojan +# All rights reserved. +# +# This software was developed by Stanford University and the University of Cambridge Computer Laboratory +# under National Science Foundation under Grant No. CNS-0855268, +# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and +# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), +# as part of the DARPA MRC research programme. +# +# @NETFPGA_LICENSE_HEADER_START@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +################################################################################ +# Description: +# This is used to convert xparameters.h to reg_defines.h +# + +import re + +input_file = open("nf_register_defines.h", "r") +output_file = open("reg_defines.h", "w") +baseaddr = 0 +baseaddr_int = 0 +highaddr = 0 +highaddr_int = 0 +sizeaddr = 0 +sizeaddr_int = 0 +default = 0 +default_int = 0 +width = 0 +width_int = 0 + +offset_int =0 + +for line in input_file: + match_baseaddr = re.match(r'\s*#define .*_BASEADDR (0x[a-zA-Z_0-9]{8})', line) + match_highaddr = re.match(r'\s*#define .*_HIGHADDR (0x[a-zA-Z_0-9]{8})', line) + match_sizeaddr = re.match(r'\s*#define .*_SIZEADDR (0x[a-zA-Z_0-9])', line) + match_default = re.match(r'\s*#define .*_DEFAULT (0x[a-zA-Z_0-9])', line) + match_width = re.match(r'\s*#define .*_WIDTH ([a-zA-Z_0-9])', line) + match_offset = re.match(r'\s*#define (.*)_OFFSET (0x[a-zA-Z_0-9]+)', line) + match_comment = re.match(r'\s*//', line) + + if match_baseaddr: + baseaddr = match_baseaddr.group(1) + baseaddr_int= int(baseaddr,16) + output_file.write(line) + + elif match_highaddr: + highaddr = match_highaddr.group(1) + highaddr_int= int(highaddr,16) + output_file.write(line) + + elif match_sizeaddr: + sizeaddr = match_sizeaddr.group(1) + sizeaddr_int= int(sizeaddr,16) + output_file.write(line) + + elif match_default: + default = match_default.group(1) + default_int = int(default,16) + output_file.write(line) + + elif match_width: + width = match_width.group(1) + width_int= int(width,16) + output_file.write(line) + + elif match_comment: + output_file.write(line) + + elif match_offset: + offset = match_offset.group(2) + offset_int=int(offset,16) + new_val = hex(baseaddr_int+offset_int) + newline= "#define %s %s\n" % (match_offset.group(1),new_val) + output_file.write(newline) + + else: + output_file.write(line) + + diff --git a/tools/settings.sh b/tools/settings.sh new file mode 100644 index 0000000..42daf15 --- /dev/null +++ b/tools/settings.sh @@ -0,0 +1,98 @@ +# +# Copyright (c) 2021 University of Cambridge +# All rights reserved. +# +# This software was developed by the University of Cambridge Computer +# Laboratory under EPSRC EARL Project EP/P025374/1 alongside support +# from Xilinx Inc. +# +# @NETFPGA_LICENSE_HEADER_START@ + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @NETFPGA_LICENSE_HEADER_END@ +# +### User defined +export NFPLUS_FOLDER=${HOME}/NetFPGA-PLUS +export BOARD_NAME=au250 +export NF_PROJECT_NAME=reference_switch +export PYTHON_BNRY=/usr/bin/python3 + +### Don't change +export VERSION=2020.2 +export PROJECTS=${NFPLUS_FOLDER}/projects +export CONTRIB_PROJECTS=${NFPLUS_FOLDER}/contrib-projects +export NF_DESIGN_DIR=${NFPLUS_FOLDER}/hw/projects/${NF_PROJECT_NAME} +export NF_WORK_DIR=/tmp/${USER} +export PYTHONPATH=.:${NFPLUS_FOLDER}/tools/scripts/:${NF_DESIGN_DIR}/lib/Python:${NFPLUS_FOLDER}/tools/scripts/NFTest +export DRIVER_FOLDER=${NFPLUS_FOLDER}/lib/sw/std/driver/${DRIVER_NAME} +export APPS_FOLDER=${NFPLUS_FOLDER}/lib/sw/std/apps/${DRIVER_NAME} + + +# Check sequence +if [ ! -d ${NFPLUS_FOLDER} ] ; then + echo "Error: ${NFPLUS_FOLDER} is not found." + return -1 +fi + +if [ ${BOARD_NAME} != "au280" -a \ + ${BOARD_NAME} != "au250" -a \ + ${BOARD_NAME} != "au200" -a \ + ${BOARD_NAME} != "au50" -a \ + ${BOARD_NAME} != "vcu1525" ] ; then + echo "Error: ${BOARD_NAME} is not supported." + echo " Supported boards are au280, au250, au200, au50, and vcu1525." + return -1 +else + board_name=`echo "puts [get_board_parts -quiet -latest_file_version \"*:${BOARD_NAME}:*\"]" | vivado -nolog -nojournal -mode tcl | grep xilinx` + if [ ${BOARD_NAME} = "au280" ] ; then + device="xcu280-fsvh2892-2L-e" + elif [ ${BOARD_NAME} = "au250" ] ; then + device="xcu250-figd2104-2L-e" + elif [ ${BOARD_NAME} = "au200" ] ; then + device="xcu200-fsgd2104-2-e" + elif [ ${BOARD_NAME} = "au50" ] ; then + device="xcu50-fsvh2104-2-e" + elif [ ${BOARD_NAME} = "vcu1525" ] ; then + device="xcvu9p-fsgd2104-2L-e" + fi +fi + +if [ ! -d ${NF_DESIGN_DIR} ] ; then + echo "Error: ${NF_PROJECT_NAME} cannot be found." + return -1 +fi + +echo "[ok] All parameters has been checked." + +vivado_version=`echo $XILINX_VIVADO | awk -F "/" 'NF>1{print $NF}'` +if [ -z ${vivado_version} ]; then + echo "Error: please source vivado scripts. e.g.) /tools/Xilinx/Vivado/2019.2/settings64.sh" + return -1 +fi +if [ ${VERSION} != ${vivado_version} -a \ + ${VERSION}* != ${vivado_version} ] ; then + echo "Error: you don't have proper Vivado version (${VERSION})." + return -1 +fi + +echo "[ok] Vivado Version (${VERSION}) has been checked." +echo " NFPLUS_FOLDER : ${NFPLUS_FOLDER}" +echo " BOARD_NAME : ${BOARD_NAME}" +echo " NF_PROJECT_NAME: ${NF_PROJECT_NAME}" + +echo "Done..." + +export BOARD=${board_name} +export DEVICE=${device} +