From 9c71cdac85bc0f059b19934740e5eeca44623685 Mon Sep 17 00:00:00 2001 From: Tomas Hak Date: Tue, 15 Oct 2024 15:05:00 +0200 Subject: [PATCH 1/2] TCAM2: [MAINTENANCE] refactor TCAM2 Fix RW address width in fragmented mem mode. Remove duplicit code (VHDL). Adjust code to comply with the coding style. Extend and refactor verification. --- comp/base/mem/tcam2/tcam2.vhd | 143 +++++++----------- comp/base/mem/tcam2/ver/Modules.tcl | 20 ++- .../mem/tcam2/ver/tbench/read_bus/Modules.tcl | 13 ++ .../ver/tbench/read_bus/rb_transaction.sv | 21 +++ .../tcam2/ver/tbench/read_bus/sv_rb_pkg.sv | 14 ++ comp/base/mem/tcam2/ver/tbench/scoreboard.sv | 78 +++++----- comp/base/mem/tcam2/ver/tbench/test.sv | 20 +-- comp/base/mem/tcam2/ver/tbench/test_pkg.sv | 10 +- comp/base/mem/tcam2/ver/tbench/testbench.sv | 4 +- .../tcam2/ver/tbench/write_bus/wb_driver.sv | 4 +- .../ver/tbench/write_bus/wb_transaction.sv | 11 +- comp/base/mem/tcam2/ver/top_level.fdo | 10 +- comp/base/mem/tcam2/ver/ver_settings.py | 1 + 13 files changed, 185 insertions(+), 164 deletions(-) create mode 100644 comp/base/mem/tcam2/ver/tbench/read_bus/Modules.tcl create mode 100644 comp/base/mem/tcam2/ver/tbench/read_bus/rb_transaction.sv create mode 100644 comp/base/mem/tcam2/ver/tbench/read_bus/sv_rb_pkg.sv diff --git a/comp/base/mem/tcam2/tcam2.vhd b/comp/base/mem/tcam2/tcam2.vhd index 39a0b86ed..692b0afc4 100644 --- a/comp/base/mem/tcam2/tcam2.vhd +++ b/comp/base/mem/tcam2/tcam2.vhd @@ -54,7 +54,20 @@ entity TCAM2 is -- FPGA device -- available are "7SERIES", "ULTRASCALE", "ARRIA10", "STRATIX10", "AGILEX" - DEVICE : string := "ULTRASCALE" + DEVICE : string := "ULTRASCALE"; + + -- Manufacturer of FPGA device + IS_XILINX : boolean := (DEVICE = "7SERIES" or DEVICE = "ULTRASCALE"); + IS_INTEL : boolean := (DEVICE = "ARRIA10" or DEVICE = "STRATIX10" or DEVICE = "AGILEX"); + + -- Optimal parameters by FPGA device + INTEL_DATA_WIDTH : integer := tsel(USE_FRAGMENTED_MEM, 20, 16); + XILINX_DATA_WIDTH : integer := tsel(DEVICE = "ULTRASCALE", tsel(USE_FRAGMENTED_MEM, 14, 8), tsel(USE_FRAGMENTED_MEM, 6, 4)); + MEMORY_ADDR_WIDTH : integer := 5; + MEMORY_DATA_WIDTH : integer := tsel(IS_XILINX, XILINX_DATA_WIDTH, INTEL_DATA_WIDTH); + ALIGNED_DATA_WIDTH : integer := 2**log2(MEMORY_DATA_WIDTH); + ITEMS_ALIGNED : integer := tsel(USE_FRAGMENTED_MEM, div_roundup(ITEMS,MEMORY_DATA_WIDTH)*ALIGNED_DATA_WIDTH, ITEMS); + ADDR_WIDTH : integer := max(1, log2(ITEMS_ALIGNED)) ); Port ( -- CLOCK AND RESET @@ -62,7 +75,7 @@ entity TCAM2 is RST : in std_logic; -- READ INTERFACE (READ_FROM_TCAM must be set as true) - READ_ADDR : in std_logic_vector(max(1,log2(ITEMS))-1 downto 0); + READ_ADDR : in std_logic_vector(ADDR_WIDTH-1 downto 0); READ_EN : in std_logic; READ_RDY : out std_logic; READ_DATA : out std_logic_vector(DATA_WIDTH-1 downto 0); @@ -72,7 +85,7 @@ entity TCAM2 is -- WRITE INTERFACE WRITE_DATA : in std_logic_vector(DATA_WIDTH-1 downto 0); WRITE_MASK : in std_logic_vector(DATA_WIDTH-1 downto 0); - WRITE_ADDR : in std_logic_vector(max(1,log2(ITEMS))-1 downto 0); + WRITE_ADDR : in std_logic_vector(ADDR_WIDTH-1 downto 0); WRITE_EN : in std_logic; WRITE_RDY : out std_logic; @@ -92,24 +105,13 @@ end entity; -- ===================================================================== architecture FULL of TCAM2 is - -- Manufacturer of FPGA device - constant IS_XILINX : boolean := (DEVICE = "7SERIES" or DEVICE = "ULTRASCALE"); - constant IS_INTEL : boolean := (DEVICE = "ARRIA10" or DEVICE = "STRATIX10" or DEVICE = "AGILEX"); - - -- Optimal parameters by FPGA device - constant INTEL_DATA_WIDTH : integer := tsel(USE_FRAGMENTED_MEM, 20, 16); - constant XILINX_DATA_WIDTH : integer := tsel(DEVICE = "ULTRASCALE", tsel(USE_FRAGMENTED_MEM, 14, 8), tsel(USE_FRAGMENTED_MEM, 6, 4)); - constant MEMORY_ADDR_WIDTH : integer := 5; - constant MEMORY_DATA_WIDTH : integer := tsel(IS_XILINX, XILINX_DATA_WIDTH, INTEL_DATA_WIDTH); - constant ALIGNED_DATA_WIDTH : integer := 2**log2(MEMORY_DATA_WIDTH); - -- Setting TCAM2 resources parameters constant CELL_WIDTH : integer := MEMORY_ADDR_WIDTH - RESOURCES_SAVING; constant CELL_HEIGHT : integer := MEMORY_DATA_WIDTH * (2**RESOURCES_SAVING); constant ALIGNED_CELL_HEIGHT : integer := ALIGNED_DATA_WIDTH * (2**RESOURCES_SAVING); constant CELL_HEIGHT_RATIO : integer := CELL_HEIGHT/MEMORY_DATA_WIDTH; constant COLUMNS : integer := div_roundup(DATA_WIDTH, CELL_WIDTH); - constant ROWS : integer := div_roundup(ITEMS, ALIGNED_CELL_HEIGHT); + constant ROWS : integer := div_roundup(ITEMS_ALIGNED, ALIGNED_CELL_HEIGHT); -- -------------------------------------------------------------------------- -- I/O data signals @@ -125,7 +127,6 @@ architecture FULL of TCAM2 is signal input_m_data_reg_aug : std_logic_vector(COLUMNS*CELL_WIDTH-1 downto 0); signal input_wr_data_reg_aug : std_logic_vector(COLUMNS*CELL_WIDTH-1 downto 0) := (others => '0'); signal input_wr_mask_reg_aug : std_logic_vector(COLUMNS*CELL_WIDTH-1 downto 0) := (others => '0'); - signal input_wr_addr_reg_aug : std_logic_vector(log2(ROWS*ALIGNED_CELL_HEIGHT)-1 downto 0) := (others => '0'); -- Input registers augmented arrays signal input_m_data_reg_aug_arr : slv_array_t(COLUMNS-1 downto 0)(CELL_WIDTH-1 downto 0); @@ -218,14 +219,9 @@ architecture FULL of TCAM2 is signal sf_cnt_en : std_logic; signal sf_cnt_en_reg : std_logic; - -- output match register write enable - signal m_aug_reg_we : std_logic_vector(CELL_HEIGHT_RATIO-1 downto 0); - - -- output match vector register - signal m_aug_reg : slv_array_2d_t(ROWS-1 downto 0)(CELL_HEIGHT_RATIO-1 downto 0)(ALIGNED_DATA_WIDTH-1 downto 0); - - -- fit output match - signal m_aug : std_logic_vector(ROWS*ALIGNED_CELL_HEIGHT-1 downto 0); + -- output match register + signal m_reg_we : std_logic_vector(CELL_HEIGHT_RATIO-1 downto 0); + signal m_reg : slv_array_2d_t(ROWS-1 downto 0)(CELL_HEIGHT_RATIO-1 downto 0)(MEMORY_DATA_WIDTH-1 downto 0); begin @@ -289,60 +285,27 @@ begin -- memory element generate mem_rows_g : for r in 0 to ROWS-1 generate mem_colums_g : for c in 0 to COLUMNS-1 generate - - memory_xilinx_g : if IS_XILINX generate - -- write data block (backup other records and add new) - mem_wr_data_block(c)(r) <= (mem_match_vector(c)(r) and not mem_wr_bit_en_reg) or ((MEMORY_DATA_WIDTH-1 downto 0 => mem_wr_data_reg(c)) and mem_wr_bit_en_reg); - - -- Xilinx Single Port RAM - sp_distmem_i : entity work.GEN_LUTRAM - generic map ( - DATA_WIDTH => MEMORY_DATA_WIDTH, - ITEMS => 2**MEMORY_ADDR_WIDTH, - RD_PORTS => 1, - RD_LATENCY => 1, - WRITE_USE_RD_ADDR0 => False, - MLAB_CONSTR_RDW_DC => False, - DEVICE => DEVICE - ) - port map ( - CLK => CLK, - WR_EN => mem_wr_en_reg(r), - WR_ADDR => mem_wr_addr_reg, - WR_DATA => mem_wr_data_block(c)(r), - RD_ADDR => mem_addr_arr(c), - RD_DATA => mem_match_vector(c)(r) - ); - end generate; - - storage_intel_g : if IS_INTEL generate - -- write data block (backup other records and add new) - mem_wr_data_block(c)(r) <= (mem_match_vector(c)(r) and not mem_wr_bit_en_reg) or ((MEMORY_DATA_WIDTH-1 downto 0 => mem_wr_data_reg(c)) and mem_wr_bit_en_reg); - - -- INTEL MLAB simple dual port RAM - sdp_mlab_ram_i : entity work.GEN_LUTRAM - generic map ( - DATA_WIDTH => MEMORY_DATA_WIDTH, - ITEMS => 2**MEMORY_ADDR_WIDTH, - RD_PORTS => 1, - RD_LATENCY => 1, - WRITE_USE_RD_ADDR0 => False, - MLAB_CONSTR_RDW_DC => True, - DEVICE => DEVICE - ) - port map ( - CLK => CLK, - WR_EN => mem_wr_en_reg(r), - WR_ADDR => mem_wr_addr_reg, - WR_DATA => mem_wr_data_block(c)(r), - RD_ADDR => mem_addr_arr(c), - RD_DATA => mem_match_vector(c)(r) - ); - end generate; - - -- propagating match + -- write data block (backup other records and add new) + mem_wr_data_block(c)(r) <= (mem_match_vector(c)(r) and not mem_wr_bit_en_reg) or ((MEMORY_DATA_WIDTH-1 downto 0 => mem_wr_data_reg(c)) and mem_wr_bit_en_reg); + sp_distmem_i : entity work.GEN_LUTRAM + generic map ( + DATA_WIDTH => MEMORY_DATA_WIDTH, + ITEMS => 2**MEMORY_ADDR_WIDTH, + RD_PORTS => 1, + RD_LATENCY => 1, + WRITE_USE_RD_ADDR0 => False, + MLAB_CONSTR_RDW_DC => IS_INTEL, + DEVICE => DEVICE + ) + port map ( + CLK => CLK, + WR_EN => mem_wr_en_reg(r), + WR_ADDR => mem_wr_addr_reg, + WR_DATA => mem_wr_data_block(c)(r), + RD_ADDR => mem_addr_arr(c), + RD_DATA => mem_match_vector(c)(r) + ); mem_match_carry(c+1)(r) <= mem_match_carry(c)(r) and mem_match_vector(c)(r); - end generate; end generate; @@ -359,7 +322,7 @@ begin write_data_storage_i : entity work.SDP_BRAM_BEHAV generic map ( DATA_WIDTH => DATA_WIDTH, - ITEMS => ITEMS, + ITEMS => ITEMS_ALIGNED, OUTPUT_REG => OUTPUT_READ_REGS ) port map ( @@ -382,7 +345,7 @@ begin write_mask_storage_i : entity work.SDP_BRAM_BEHAV generic map ( DATA_WIDTH => DATA_WIDTH, - ITEMS => ITEMS, + ITEMS => ITEMS_ALIGNED, OUTPUT_REG => OUTPUT_READ_REGS ) port map ( @@ -434,7 +397,6 @@ begin -- write signals registers padding input_wr_data_reg_aug(input_wr_data_reg'range) <= input_wr_data_reg; input_wr_mask_reg_aug(input_wr_mask_reg'range) <= input_wr_mask_reg; - input_wr_addr_reg_aug(input_wr_addr_reg'range) <= input_wr_addr_reg; -- write data and mask registers arrays input_wr_data_reg_aug_arr <= slv_array_deser(input_wr_data_reg_aug,COLUMNS); input_wr_mask_reg_aug_arr <= slv_array_deser(input_wr_mask_reg_aug,COLUMNS); @@ -469,7 +431,7 @@ begin ITEMS => ROWS ) port map ( - ADDR => input_wr_addr_reg_aug(input_wr_addr_reg_aug'high downto log2(ALIGNED_CELL_HEIGHT)), + ADDR => input_wr_addr_reg(input_wr_addr_reg'high downto log2(ALIGNED_CELL_HEIGHT)), ENABLE => wr_cnt_en, DO => mem_wr_en ); @@ -480,7 +442,7 @@ begin -- cell height address mem_sf_addr_g : if CELL_HEIGHT_RATIO > 1 generate - mem_sf_addr <= input_wr_addr_reg_aug(log2(ALIGNED_CELL_HEIGHT)-1 downto log2(ALIGNED_DATA_WIDTH)); + mem_sf_addr <= input_wr_addr_reg(log2(ALIGNED_CELL_HEIGHT)-1 downto log2(ALIGNED_DATA_WIDTH)); end generate; fake_mem_sf_addr_g : if CELL_HEIGHT_RATIO = 1 generate mem_sf_addr(0) <= '0'; @@ -493,7 +455,7 @@ begin ITEMS => ALIGNED_DATA_WIDTH ) port map ( - ADDR => input_wr_addr_reg_aug(log2(ALIGNED_DATA_WIDTH)-1 downto 0), + ADDR => input_wr_addr_reg(log2(ALIGNED_DATA_WIDTH)-1 downto 0), DO => mem_wr_bit_en ); end generate; @@ -603,35 +565,32 @@ begin mem_match_en <= sf_cnt_en; -- output match register write enable decoder - m_aug_reg_we_dec_i : entity work.dec1fn_enable + m_reg_we_dec_i : entity work.dec1fn_enable generic map ( ITEMS => CELL_HEIGHT_RATIO ) port map ( ADDR => sf_cnt_reg, ENABLE => sf_cnt_en_reg, - DO => m_aug_reg_we + DO => m_reg_we ); -- output match vector register match_bits_reg_g : for i in 0 to ROWS-1 generate match_words_reg_g : for j in 0 to CELL_HEIGHT_RATIO-1 generate - m_aug_reg_p : process (CLK) + m_reg_p : process (CLK) begin if rising_edge(CLK) then - if (m_aug_reg_we(j) = '1') then - m_aug_reg(i)(j) <= (others=>'0'); - m_aug_reg(i)(j)(mem_match_out(i)'range) <= mem_match_out(i); + if (m_reg_we(j) = '1') then + m_reg(i)(j) <= mem_match_out(i); end if; end if; end process; end generate; end generate; - -- array conversion - m_aug <= slv_array_2d_ser(m_aug_reg); -- output length fit - MATCH_OUT_ADDR <= m_aug(MATCH_OUT_ADDR'range); + MATCH_OUT_ADDR <= slv_array_2d_ser(m_reg)(MATCH_OUT_ADDR'range); -- match hit MATCH_OUT_HIT <= or MATCH_OUT_ADDR; diff --git a/comp/base/mem/tcam2/ver/Modules.tcl b/comp/base/mem/tcam2/ver/Modules.tcl index d6091abb0..5ced75066 100644 --- a/comp/base/mem/tcam2/ver/Modules.tcl +++ b/comp/base/mem/tcam2/ver/Modules.tcl @@ -4,16 +4,14 @@ # # SPDX-License-Identifier: BSD-3-Clause -# set paths +set SV_MVB_BASE "$OFM_PATH/comp/mvb_tools/ver" +set SV_WB_BASE "$ENTITY_BASE/tbench/write_bus" +set SV_RB_BASE "$ENTITY_BASE/tbench/read_bus" -set SV_MVB_BASE "$OFM_PATH/comp/mvb_tools/ver" -set SV_WB_BASE "$ENTITY_BASE/tbench/write_bus" +lappend COMPONENTS [ list "SV_MVB" $SV_MVB_BASE "FULL" ] +lappend COMPONENTS [ list "SV_WB" $SV_WB_BASE "FULL" ] +lappend COMPONENTS [ list "SV_RB" $SV_RB_BASE "FULL" ] -set COMPONENTS [list \ - [ list "SV_MVB" $SV_MVB_BASE "FULL"] \ - [ list "SV_WB" $SV_WB_BASE "FULL"] \ -] - -set MOD "$MOD $ENTITY_BASE/tbench/test_pkg.sv" -set MOD "$MOD $ENTITY_BASE/tbench/dut.sv" -set MOD "$MOD $ENTITY_BASE/tbench/test.sv" +lappend MOD "$ENTITY_BASE/tbench/test_pkg.sv" +lappend MOD "$ENTITY_BASE/tbench/dut.sv" +lappend MOD "$ENTITY_BASE/tbench/test.sv" diff --git a/comp/base/mem/tcam2/ver/tbench/read_bus/Modules.tcl b/comp/base/mem/tcam2/ver/tbench/read_bus/Modules.tcl new file mode 100644 index 000000000..13062a342 --- /dev/null +++ b/comp/base/mem/tcam2/ver/tbench/read_bus/Modules.tcl @@ -0,0 +1,13 @@ +# Modules.tcl: Local include tcl script +# Copyright (C) 2024 CESNET z. s. p. o. +# Author: Tomas Hak +# +# SPDX-License-Identifier: BSD-3-Clause + +set SV_COMMON_BASE "$OFM_PATH/comp/ver" +set SV_MVB_BASE "$OFM_PATH/comp/mvb_tools/ver" + +lappend COMPONENTS [ list "SV_COMMON" $SV_COMMON_BASE "FULL" ] +lappend COMPONENTS [ list "SV_MVB" $SV_MVB_BASE "FULL" ] + +lappend MOD "$ENTITY_BASE/sv_rb_pkg.sv" diff --git a/comp/base/mem/tcam2/ver/tbench/read_bus/rb_transaction.sv b/comp/base/mem/tcam2/ver/tbench/read_bus/rb_transaction.sv new file mode 100644 index 000000000..745e43468 --- /dev/null +++ b/comp/base/mem/tcam2/ver/tbench/read_bus/rb_transaction.sv @@ -0,0 +1,21 @@ +// rb_transaction.sv: Read Bus transaction +// Copyright (C) 2024 CESNET z. s. p. o. +// Author: Tomas Hak +// +// SPDX-License-Identifier: BSD-3-Clause + +class RbTransaction #(ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE, ITEMS = 2**ADDR_WIDTH, BLOCK_ITEMS = 20) extends MvbTransaction#(.ITEM_WIDTH(ADDR_WIDTH)); + constraint mem_items_constr { data < ITEMS; } + // in fragmented mode top BLOCK addresses are not used + constraint frag_mem_constr { !FRAGMENTED_MEM || data[$clog2(BLOCK_ITEMS)-1 : 0] < BLOCK_ITEMS; } + + virtual function Transaction copy(Transaction to = null); + RbTransaction #(ADDR_WIDTH, FRAGMENTED_MEM, ITEMS, BLOCK_ITEMS) tr; + if (to == null) + tr = new(); + else + $cast(tr, to); + copy = super.copy(tr); + endfunction + +endclass diff --git a/comp/base/mem/tcam2/ver/tbench/read_bus/sv_rb_pkg.sv b/comp/base/mem/tcam2/ver/tbench/read_bus/sv_rb_pkg.sv new file mode 100644 index 000000000..a2dc4fd4c --- /dev/null +++ b/comp/base/mem/tcam2/ver/tbench/read_bus/sv_rb_pkg.sv @@ -0,0 +1,14 @@ +// sv_rb_pkg.sv: SystemVerilog package with Read Bus +// Copyright (C) 2024 CESNET z. s. p. o. +// Author: Tomas Hak +// +// SPDX-License-Identifier: BSD-3-Clause + +package sv_rb_pkg; + + import sv_common_pkg::*; + import sv_mvb_pkg::*; + + `include "rb_transaction.sv" + +endpackage diff --git a/comp/base/mem/tcam2/ver/tbench/scoreboard.sv b/comp/base/mem/tcam2/ver/tbench/scoreboard.sv index afe9edbe9..a85db49a2 100644 --- a/comp/base/mem/tcam2/ver/tbench/scoreboard.sv +++ b/comp/base/mem/tcam2/ver/tbench/scoreboard.sv @@ -6,9 +6,10 @@ import sv_common_pkg::*; import sv_wb_pkg::*; +import sv_rb_pkg::*; import sv_mvb_pkg::*; -class tcam_model #(int DATA_WIDTH, int ITEMS); +class tcam_model #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM, int ITEMS_ALIGNED, int BLOCK_ITEMS); local bit [DATA_WIDTH-1 : 0] data[]; local bit [DATA_WIDTH-1 : 0] mask[]; @@ -25,22 +26,29 @@ class tcam_model #(int DATA_WIDTH, int ITEMS); end endfunction - function int record(bit [log2(ITEMS)-1 : 0] a); - record = vld[a]; + function int trim_rw_addr(bit [log2(ITEMS_ALIGNED)-1 : 0] a); + if (FRAGMENTED_MEM) begin + int block_items_aligned = 2**$clog2(BLOCK_ITEMS); + return a/block_items_aligned*BLOCK_ITEMS + a%block_items_aligned; + end else begin + return a; + end endfunction - function void write(bit [DATA_WIDTH-1 : 0] d, bit [DATA_WIDTH-1 : 0] m, bit [log2(ITEMS)-1 : 0] a); - busy = 1; - data[a] = d; - mask[a] = m; - vld[a] = 1; - busy = 0; + function void write(bit [DATA_WIDTH-1 : 0] d, bit [DATA_WIDTH-1 : 0] m, bit [log2(ITEMS_ALIGNED)-1 : 0] a); + int addr = trim_rw_addr(a); + busy = 1; + data[addr] = d; + mask[addr] = m; + vld[addr] = 1; + busy = 0; endfunction - function void read(bit [log2(ITEMS)-1 : 0] a, output bit [DATA_WIDTH-1 : 0] d, output bit [DATA_WIDTH-1 : 0] m); + function void read(bit [log2(ITEMS_ALIGNED)-1 : 0] a, output bit [DATA_WIDTH-1 : 0] d, output bit [DATA_WIDTH-1 : 0] m); + int addr = trim_rw_addr(a); busy = 1; - d = data[a]; - m = mask[a]; + d = vld[addr] ? data[addr] : 0; + m = vld[addr] ? mask[addr] : 0; busy = 0; endfunction @@ -74,10 +82,10 @@ class tcam_model #(int DATA_WIDTH, int ITEMS); endclass -class ScoreboardWriteDriverCbs #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM) extends DriverCbs; - tcam_model #(DATA_WIDTH, ITEMS) tcam; +class ScoreboardWriteDriverCbs #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM, int ITEMS_ALIGNED, int BLOCK_ITEMS) extends DriverCbs; + tcam_model #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tcam; - function new(tcam_model #(DATA_WIDTH, ITEMS) tcam_i); + function new(tcam_model #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tcam_i); this.tcam = tcam_i; endfunction @@ -86,7 +94,7 @@ class ScoreboardWriteDriverCbs #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM) virtual task post_tx(Transaction transaction, string inst); //$write("Write transaction\n"); - WbTransaction #(DATA_WIDTH, log2(ITEMS), FRAGMENTED_MEM) tr; + WbTransaction #(DATA_WIDTH, log2(ITEMS_ALIGNED), FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tr; $cast(tr, transaction); if(FULL_PRINT == TRUE) begin $write("Write to TCAM model\n"); @@ -97,11 +105,11 @@ class ScoreboardWriteDriverCbs #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM) endtask endclass -class ScoreboardReadDriverCbs #(int DATA_WIDTH, int ITEMS) extends DriverCbs; - tcam_model #(DATA_WIDTH, ITEMS) tcam; - TransactionTable #(0) sc_table; +class ScoreboardReadDriverCbs #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM, int ITEMS_ALIGNED, int BLOCK_ITEMS) extends DriverCbs; + tcam_model #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tcam; + TransactionTable #(0) sc_table; - function new(tcam_model #(DATA_WIDTH, ITEMS) tcam_i, TransactionTable #(0) sc_table_i); + function new(tcam_model #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tcam_i, TransactionTable #(0) sc_table_i); this.tcam = tcam_i; this.sc_table = sc_table_i; endfunction @@ -110,7 +118,7 @@ class ScoreboardReadDriverCbs #(int DATA_WIDTH, int ITEMS) extends DriverCbs; endtask virtual task post_tx(Transaction transaction, string inst); - MvbTransaction #(log2(ITEMS)) tr; + MvbTransaction #(log2(ITEMS_ALIGNED)) tr; MvbTransaction #(2*DATA_WIDTH) read_out_tr; bit [DATA_WIDTH-1 : 0] read_data = {DATA_WIDTH{1'b0}}; bit [DATA_WIDTH-1 : 0] read_mask = {DATA_WIDTH{1'b0}}; @@ -122,9 +130,7 @@ class ScoreboardReadDriverCbs #(int DATA_WIDTH, int ITEMS) extends DriverCbs; tr.display(); end wait(!tcam.busy); - if(tcam.record(tr.data)) begin - tcam.read(tr.data, read_data, read_mask); - end + tcam.read(tr.data, read_data, read_mask); read_out_tr = new(); read_out_tr.data[2*DATA_WIDTH-1 : DATA_WIDTH] = read_data; @@ -134,11 +140,11 @@ class ScoreboardReadDriverCbs #(int DATA_WIDTH, int ITEMS) extends DriverCbs; endtask endclass -class ScoreboardMatchDriverCbs #(int DATA_WIDTH, int ITEMS) extends DriverCbs; - tcam_model #(DATA_WIDTH,ITEMS) tcam; - TransactionTable #(0) sc_table; +class ScoreboardMatchDriverCbs #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM, int ITEMS_ALIGNED, int BLOCK_ITEMS) extends DriverCbs; + tcam_model #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tcam; + TransactionTable #(0) sc_table; - function new(tcam_model #(DATA_WIDTH, ITEMS) tcam_i, TransactionTable #(0) sc_table_i); + function new(tcam_model #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tcam_i, TransactionTable #(0) sc_table_i); this.tcam = tcam_i; this.sc_table = sc_table_i; endfunction @@ -195,15 +201,15 @@ class ScoreboardMonitorCbs extends MonitorCbs; endclass -class Scoreboard #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM); +class Scoreboard #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM, int ITEMS_ALIGNED, int BLOCK_ITEMS); - ScoreboardWriteDriverCbs #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM) writeDriverCbs; - ScoreboardReadDriverCbs #(DATA_WIDTH, ITEMS) readDriverCbs; - ScoreboardMatchDriverCbs #(DATA_WIDTH, ITEMS) matchDriverCbs; - ScoreboardMonitorCbs readMonitorCbs; - ScoreboardMonitorCbs matchMonitorCbs; - tcam_model #(DATA_WIDTH,ITEMS) tcam; - TransactionTable #(0) scoreTable; + ScoreboardWriteDriverCbs #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) writeDriverCbs; + ScoreboardReadDriverCbs #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) readDriverCbs; + ScoreboardMatchDriverCbs #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) matchDriverCbs; + ScoreboardMonitorCbs readMonitorCbs; + ScoreboardMonitorCbs matchMonitorCbs; + tcam_model #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) tcam; + TransactionTable #(0) scoreTable; function new(); tcam = new(); diff --git a/comp/base/mem/tcam2/ver/tbench/test.sv b/comp/base/mem/tcam2/ver/tbench/test.sv index 619bd38e4..b554c66d3 100644 --- a/comp/base/mem/tcam2/ver/tbench/test.sv +++ b/comp/base/mem/tcam2/ver/tbench/test.sv @@ -7,6 +7,7 @@ import sv_common_pkg::*; import sv_mvb_pkg::*; import sv_wb_pkg::*; +import sv_rb_pkg::*; import test_pkg::*; program TEST ( @@ -21,24 +22,24 @@ program TEST ( iMvbTx.monitor MATCH_MONITOR ); - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, USE_FRAGMENTED_MEM) write_bp; - MvbTransaction #(ADDR_WIDTH) read_bp; - MvbTransaction #(DATA_WIDTH) match_bp; + WbTransaction #(DATA_WIDTH, ADDR_WIDTH, USE_FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) write_bp; + RbTransaction #(ADDR_WIDTH, USE_FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) read_bp; + MvbTransaction #(DATA_WIDTH) match_bp; Generator write_gen; Generator read_gen; Generator match_gen; - WbDriver #(DATA_WIDTH, ADDR_WIDTH, USE_FRAGMENTED_MEM) write_driver; - MvbDriver #(1, ADDR_WIDTH) read_driver; - MvbDriver #(1, DATA_WIDTH) match_driver; + WbDriver #(DATA_WIDTH, ADDR_WIDTH, USE_FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) write_driver; + MvbDriver #(1, ADDR_WIDTH) read_driver; + MvbDriver #(REPLICAS, DATA_WIDTH) match_driver; MvbResponder #(1, 2*DATA_WIDTH) read_responder; - MvbResponder #(1, ITEMS+1) match_responder; + MvbResponder #(REPLICAS, ITEMS+1) match_responder; MvbMonitor #(1, 2*DATA_WIDTH) read_monitor; - MvbMonitor #(1, ITEMS+1) match_monitor; + MvbMonitor #(REPLICAS, ITEMS+1) match_monitor; - Scoreboard #(DATA_WIDTH, ITEMS, USE_FRAGMENTED_MEM) scoreboard; + Scoreboard #(DATA_WIDTH, ITEMS, USE_FRAGMENTED_MEM, ITEMS_ALIGNED, BLOCK_ITEMS) scoreboard; task createGeneratorEnvironment(); write_gen = new("Write Generator", 0); @@ -84,6 +85,7 @@ program TEST ( task enableTestEnvironment(); write_driver.setEnabled(); read_driver.setEnabled(); + read_driver.mode = 1; match_driver.setEnabled(); read_responder.setEnabled(); match_responder.setEnabled(); diff --git a/comp/base/mem/tcam2/ver/tbench/test_pkg.sv b/comp/base/mem/tcam2/ver/tbench/test_pkg.sv index 6714e4650..a978c545e 100644 --- a/comp/base/mem/tcam2/ver/tbench/test_pkg.sv +++ b/comp/base/mem/tcam2/ver/tbench/test_pkg.sv @@ -9,9 +9,9 @@ package test_pkg; import math_pkg::*; import sv_common_pkg::*; // SystemVerilog Boolean + parameter REPLICAS = 1; parameter DATA_WIDTH = 8; parameter ITEMS = 64; - parameter ADDR_WIDTH = log2(ITEMS); parameter RESOURCES_SAVING = 0; parameter WRITE_BEFORE_MATCH = TRUE; parameter READ_FROM_TCAM = TRUE; @@ -19,6 +19,14 @@ package test_pkg; parameter USE_FRAGMENTED_MEM = FALSE; parameter DEVICE = "ULTRASCALE"; + parameter IS_INTEL = (DEVICE == "AGILEX" || DEVICE == "STRATIX10" || DEVICE == "ARRIA10"); + // with USE_FRAGMENTED_MEM = TRUE, ITEMS must be aligned to multiples of 20 for Intel FPGAs + parameter MLAB_ITEMS = USE_FRAGMENTED_MEM ? 20 : 16; + parameter SLICEM_ITEMS = DEVICE == "ULTRASCALE" ? (USE_FRAGMENTED_MEM ? 14 : 8) : (USE_FRAGMENTED_MEM ? 6 : 4); + parameter BLOCK_ITEMS = IS_INTEL ? MLAB_ITEMS : SLICEM_ITEMS; + parameter ITEMS_ALIGNED = USE_FRAGMENTED_MEM ? (ITEMS/BLOCK_ITEMS)*(2**log2(BLOCK_ITEMS)) : ITEMS; + parameter ADDR_WIDTH = log2(ITEMS_ALIGNED); + parameter WRITE_COUNT = 200; parameter MATCH_COUNT = 100000; parameter READ_COUNT = 200; diff --git a/comp/base/mem/tcam2/ver/tbench/testbench.sv b/comp/base/mem/tcam2/ver/tbench/testbench.sv index ae6949b72..23be2bcee 100644 --- a/comp/base/mem/tcam2/ver/tbench/testbench.sv +++ b/comp/base/mem/tcam2/ver/tbench/testbench.sv @@ -14,8 +14,8 @@ module testbench; iWbRx #(DATA_WIDTH, ADDR_WIDTH ) WRITE (CLK, RESET); iMvbRx #(1, ADDR_WIDTH ) READ (CLK, RESET); iMvbTx #(1, 2*DATA_WIDTH) READ_OUT (CLK, RESET); - iMvbRx #(1, DATA_WIDTH ) MATCH (CLK, RESET); - iMvbTx #(1, ITEMS+1 ) MATCH_OUT (CLK, RESET); + iMvbRx #(REPLICAS, DATA_WIDTH ) MATCH (CLK, RESET); + iMvbTx #(REPLICAS, ITEMS+1 ) MATCH_OUT (CLK, RESET); always #(CLK_PERIOD/2) CLK = ~CLK; diff --git a/comp/base/mem/tcam2/ver/tbench/write_bus/wb_driver.sv b/comp/base/mem/tcam2/ver/tbench/write_bus/wb_driver.sv index 15f63f865..bbfe6ab72 100644 --- a/comp/base/mem/tcam2/ver/tbench/write_bus/wb_driver.sv +++ b/comp/base/mem/tcam2/ver/tbench/write_bus/wb_driver.sv @@ -4,7 +4,7 @@ // // SPDX-License-Identifier: BSD-3-Clause -class WbDriver #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE) extends Driver; +class WbDriver #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE, ITEMS = 2**ADDR_WIDTH, BLOCK_ITEMS = 20) extends Driver; protected virtual iWbRx#(DATA_WIDTH,ADDR_WIDTH).tb vif; protected bit [DATA_WIDTH-1 : 0] data; @@ -55,7 +55,7 @@ class WbDriver #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE) extend task run(); Transaction transaction; - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM) tr; + WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM, ITEMS, BLOCK_ITEMS) tr; @(vif.cb); // initial sync while(enabled) begin while(transMbx.try_get(transaction) == 0) begin // wait for transaction diff --git a/comp/base/mem/tcam2/ver/tbench/write_bus/wb_transaction.sv b/comp/base/mem/tcam2/ver/tbench/write_bus/wb_transaction.sv index f62289864..4554e9c0d 100644 --- a/comp/base/mem/tcam2/ver/tbench/write_bus/wb_transaction.sv +++ b/comp/base/mem/tcam2/ver/tbench/write_bus/wb_transaction.sv @@ -4,14 +4,15 @@ // // SPDX-License-Identifier: BSD-3-Clause -class WbTransaction #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE) extends Transaction; +class WbTransaction #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE, ITEMS = 2**ADDR_WIDTH, BLOCK_ITEMS = 20) extends Transaction; rand bit [DATA_WIDTH-1 : 0] data; rand bit [DATA_WIDTH-1 : 0] mask; rand bit [ADDR_WIDTH-1 : 0] addr; - // in fragmented mode MLAB addresses 21-32 are not used - constraint frag_mem_constr { addr[4 : 0] < 20 || !FRAGMENTED_MEM; } + constraint mem_items_constr { addr < ITEMS; } + // in fragmented mode top BLOCK addresses are not used + constraint frag_mem_constr { !FRAGMENTED_MEM || addr[$clog2(BLOCK_ITEMS)-1 : 0] < BLOCK_ITEMS; } virtual function void display(string prefix = ""); if(prefix != "") begin @@ -25,7 +26,7 @@ class WbTransaction #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE) e endfunction virtual function Transaction copy(Transaction to = null); - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM) tr; + WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM, ITEMS, BLOCK_ITEMS) tr; if(to == null) begin tr = new(); end else begin @@ -38,7 +39,7 @@ class WbTransaction #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE) e endfunction virtual function bit compare(input Transaction to, output string diff, input int kind = -1); - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM) tr; + WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM, ITEMS, BLOCK_ITEMS) tr; $cast(tr, to); // TODO!!! return data == tr.data; diff --git a/comp/base/mem/tcam2/ver/top_level.fdo b/comp/base/mem/tcam2/ver/top_level.fdo index 06cd477a3..7da0cf198 100644 --- a/comp/base/mem/tcam2/ver/top_level.fdo +++ b/comp/base/mem/tcam2/ver/top_level.fdo @@ -12,13 +12,11 @@ set DUT_VER_BASE "." set TB_FILE "./tbench/testbench.sv" set SIG_FILE "./signals_sig.fdo" -set COMPONENTS [list \ - [list "DUT" $DUT_BASE "FULL"]\ - [list "DUT_VER" $DUT_VER_BASE "FULL"]\ -] +lappend COMPONENTS [ list "DUT" $DUT_BASE "FULL" ] +lappend COMPONENTS [ list "DUT_VER" $DUT_VER_BASE "FULL" ] -# Disable Code Coverage -set CODE_COVERAGE "false" +set SIM_FLAGS(CODE_COVERAGE) false +set SIM_FLAGS(DEBUG) false # Global include file for compilation source "$FIRMWARE_BASE/build/Modelsim.inc.fdo" diff --git a/comp/base/mem/tcam2/ver/ver_settings.py b/comp/base/mem/tcam2/ver/ver_settings.py index 2e901a0c8..51e7e692b 100644 --- a/comp/base/mem/tcam2/ver/ver_settings.py +++ b/comp/base/mem/tcam2/ver/ver_settings.py @@ -6,6 +6,7 @@ SETTINGS = { "default" : { # The default setting of verification + "REPLICAS" : "1" , "DATA_WIDTH" : "8" , "ITEMS" : "64" , "RESOURCES_SAVING" : "0" , From f5be7dbd6775f142a2ee0680aad375311b5f042d Mon Sep 17 00:00:00 2001 From: Tomas Hak Date: Wed, 16 Oct 2024 13:14:54 +0200 Subject: [PATCH 2/2] MVB_TCAM: [MAINTENANCE] refactor MVB_TCAM Fix RW address width in fragmented mem mode. Refactor code to comply with the coding style. Remove duplicit code (add links to TCAM2 component). --- comp/mvb_tools/storage/tcam/mvb_tcam.vhd | 26 +- comp/mvb_tools/storage/tcam/ver/Modules.tcl | 22 +- comp/mvb_tools/storage/tcam/ver/signals.fdo | 20 -- .../storage/tcam/ver/signals_sig.fdo | 6 +- comp/mvb_tools/storage/tcam/ver/tbench/dut.sv | 3 +- .../storage/tcam/ver/tbench/scoreboard.sv | 222 ------------------ .../mvb_tools/storage/tcam/ver/tbench/test.sv | 149 ------------ .../storage/tcam/ver/tbench/test_pkg.sv | 15 +- .../storage/tcam/ver/tbench/testbench.sv | 44 ---- .../tcam/ver/tbench/write_bus/Modules.tcl | 11 - .../tcam/ver/tbench/write_bus/sv_wb_pkg.sv | 16 -- .../tcam/ver/tbench/write_bus/wb_driver.sv | 79 ------- .../tcam/ver/tbench/write_bus/wb_ifc.sv | 34 --- .../ver/tbench/write_bus/wb_transaction.sv | 47 ---- comp/mvb_tools/storage/tcam/ver/top_level.fdo | 15 +- .../storage/tcam/ver/ver_settings.py | 3 +- 16 files changed, 58 insertions(+), 654 deletions(-) delete mode 100644 comp/mvb_tools/storage/tcam/ver/signals.fdo delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/scoreboard.sv delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/test.sv delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/testbench.sv delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/write_bus/Modules.tcl delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/write_bus/sv_wb_pkg.sv delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_driver.sv delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_ifc.sv delete mode 100644 comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_transaction.sv diff --git a/comp/mvb_tools/storage/tcam/mvb_tcam.vhd b/comp/mvb_tools/storage/tcam/mvb_tcam.vhd index 297dbac71..5806cce4b 100644 --- a/comp/mvb_tools/storage/tcam/mvb_tcam.vhd +++ b/comp/mvb_tools/storage/tcam/mvb_tcam.vhd @@ -23,8 +23,8 @@ entity MVB_TCAM is DATA_WIDTH : integer := 36; -- TCAM2 storage capacity - -- for XILINX (7SERIES, ULTRASCALE) optimal is a multiple of 1*(2^RS) - -- for INTEL (ARRIA10, STRATIX10) optimal is a multiple of 16*(2^RS), if memory fragmentation is not enabled, otherwise a multiple of 32*(2^RS) + -- optimal is a multiple of L*(2^RS), where L is number of LUTRAMs in each SLICEM/MLAB + -- this also applies to fragmented mem (see INTEL_DATA_WIDTH, XILINX_DATA_WIDTH generics/constants below) ITEMS : integer := 16; -- TCAM2 resources saving @@ -51,12 +51,26 @@ entity MVB_TCAM is -- But if the bit is 1, then it is UNMATCHABLE! USE_UNMATCHABLE : boolean := false; - -- set as true to use the entire Intel MLAB data width (20 instead of 16), but TCAM rows are addressed discontinuously (rows 21-32 are unused) + -- set as true to use the data widths more efficiently, but TCAM rows are addressed discontinuously + -- for Intel, rows 21-32 are unused + -- for Xilinx, rows 15-16/7-8 are unused USE_FRAGMENTED_MEM : boolean := false; -- FPGA device -- available are "7SERIES", "ULTRASCALE", "ARRIA10", "STRATIX10", "AGILEX" - DEVICE : string := "ULTRASCALE" + DEVICE : string := "ULTRASCALE"; + + -- Manufacturer of FPGA device + IS_XILINX : boolean := (DEVICE = "7SERIES" or DEVICE = "ULTRASCALE"); + IS_INTEL : boolean := (DEVICE = "ARRIA10" or DEVICE = "STRATIX10" or DEVICE = "AGILEX"); + + -- Optimal parameters by FPGA device + INTEL_DATA_WIDTH : integer := tsel(USE_FRAGMENTED_MEM, 20, 16); + XILINX_DATA_WIDTH : integer := tsel(DEVICE = "ULTRASCALE", tsel(USE_FRAGMENTED_MEM, 14, 8), tsel(USE_FRAGMENTED_MEM, 6, 4)); + MEMORY_DATA_WIDTH : integer := tsel(IS_XILINX, XILINX_DATA_WIDTH, INTEL_DATA_WIDTH); + ALIGNED_DATA_WIDTH : integer := 2**log2(MEMORY_DATA_WIDTH); + ITEMS_ALIGNED : natural := tsel(USE_FRAGMENTED_MEM, div_roundup(ITEMS,MEMORY_DATA_WIDTH)*ALIGNED_DATA_WIDTH, ITEMS); + ADDR_WIDTH : natural := max(1, log2(ITEMS_ALIGNED)) ); Port ( -- CLOCK AND RESET @@ -64,7 +78,7 @@ entity MVB_TCAM is RESET : in std_logic; -- READ INTERFACE (READ_FROM_TCAM must be set as true) - READ_ADDR : in std_logic_vector(max(1,log2(ITEMS))-1 downto 0); + READ_ADDR : in std_logic_vector(ADDR_WIDTH-1 downto 0); READ_EN : in std_logic; READ_RDY : out std_logic; READ_DATA : out std_logic_vector(DATA_WIDTH-1 downto 0); @@ -74,7 +88,7 @@ entity MVB_TCAM is -- WRITE INTERFACE WRITE_DATA : in std_logic_vector(DATA_WIDTH-1 downto 0); WRITE_MASK : in std_logic_vector(DATA_WIDTH-1 downto 0); - WRITE_ADDR : in std_logic_vector(max(1,log2(ITEMS))-1 downto 0); + WRITE_ADDR : in std_logic_vector(ADDR_WIDTH-1 downto 0); WRITE_EN : in std_logic; WRITE_RDY : out std_logic; diff --git a/comp/mvb_tools/storage/tcam/ver/Modules.tcl b/comp/mvb_tools/storage/tcam/ver/Modules.tcl index bac118c5c..149f83a92 100644 --- a/comp/mvb_tools/storage/tcam/ver/Modules.tcl +++ b/comp/mvb_tools/storage/tcam/ver/Modules.tcl @@ -1,19 +1,19 @@ # Modules.tcl: Local include tcl script # Copyright (C) 2023 CESNET z. s. p. o. -# Author: Tomas Fukac +# Author(s): Tomas Fukac +# Tomas Hak # # SPDX-License-Identifier: BSD-3-Clause -# set paths - set SV_MVB_BASE "$OFM_PATH/comp/mvb_tools/ver" -set SV_WB_BASE "$ENTITY_BASE/tbench/write_bus" +set SV_TCAM2_BASE "$OFM_PATH/comp/base/mem/tcam2/ver" +set SV_WB_BASE "$SV_TCAM2_BASE/tbench/write_bus" +set SV_RB_BASE "$SV_TCAM2_BASE/tbench/read_bus" -set COMPONENTS [list \ - [ list "SV_MVB" $SV_MVB_BASE "FULL"] \ - [ list "SV_WB" $SV_WB_BASE "FULL"] \ -] +lappend COMPONENTS [ list "SV_MVB" $SV_MVB_BASE "FULL" ] +lappend COMPONENTS [ list "SV_WB" $SV_WB_BASE "FULL" ] +lappend COMPONENTS [ list "SV_RB" $SV_RB_BASE "FULL" ] -set MOD "$MOD $ENTITY_BASE/tbench/test_pkg.sv" -set MOD "$MOD $ENTITY_BASE/tbench/dut.sv" -set MOD "$MOD $ENTITY_BASE/tbench/test.sv" +lappend MOD "$ENTITY_BASE/tbench/test_pkg.sv" +lappend MOD "$ENTITY_BASE/tbench/dut.sv" +lappend MOD "$SV_TCAM2_BASE/tbench/test.sv" diff --git a/comp/mvb_tools/storage/tcam/ver/signals.fdo b/comp/mvb_tools/storage/tcam/ver/signals.fdo deleted file mode 100644 index 0c701502e..000000000 --- a/comp/mvb_tools/storage/tcam/ver/signals.fdo +++ /dev/null @@ -1,20 +0,0 @@ -# signals.fdo : Include file with signals -# Copyright (C) 2023 CESNET z. s. p. o. -# Author: Tomas Fukac -# -# SPDX-License-Identifier: BSD-3-Clause - -proc read_p {NAME PATH} { - add wave -divider "$NAME" - add_wave "-noupdate -hex" $PATH/READ_* -} - -proc write_p {NAME PATH} { - add wave -divider "$NAME" - add_wave "-noupdate -hex" $PATH/WRITE_* -} - -proc match_p {NAME PATH} { - add wave -divider "$NAME" - add_wave "-noupdate -hex" $PATH/MATCH_* -} diff --git a/comp/mvb_tools/storage/tcam/ver/signals_sig.fdo b/comp/mvb_tools/storage/tcam/ver/signals_sig.fdo index 2f464e8ce..d6193cec3 100644 --- a/comp/mvb_tools/storage/tcam/ver/signals_sig.fdo +++ b/comp/mvb_tools/storage/tcam/ver/signals_sig.fdo @@ -1,10 +1,12 @@ # signals_sig.fdo : Include file with signals # Copyright (C) 2023 CESNET z. s. p. o. -# Author: Tomas Fukac +# Author(s): Tomas Fukac +# Tomas Hak # # SPDX-License-Identifier: BSD-3-Clause -source "./signals.fdo" +set SV_TCAM2_BASE "../../../../base/mem/tcam2/ver" +source "$SV_TCAM2_BASE/signals.fdo" add wave -divider "TCAM" add_wave "-noupdate -color yellow -label RESET" /testbench/DUT_U/VHDL_DUT_U/RESET diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/dut.sv b/comp/mvb_tools/storage/tcam/ver/tbench/dut.sv index 98cf5ec6b..4c5081ce0 100644 --- a/comp/mvb_tools/storage/tcam/ver/tbench/dut.sv +++ b/comp/mvb_tools/storage/tcam/ver/tbench/dut.sv @@ -1,6 +1,7 @@ // dut.sv: Design under test // Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac +// Author(s): Tomas Fukac +// Tomas Hak // // SPDX-License-Identifier: BSD-3-Clause diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/scoreboard.sv b/comp/mvb_tools/storage/tcam/ver/tbench/scoreboard.sv deleted file mode 100644 index 4037b5ee2..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/scoreboard.sv +++ /dev/null @@ -1,222 +0,0 @@ -// scoreboard.sv: TCAM Scoreboard -// Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac -// -// SPDX-License-Identifier: BSD-3-Clause - -import sv_common_pkg::*; -import sv_wb_pkg::*; -import sv_mvb_pkg::*; - -class tcam_model #(int DATA_WIDTH, int ITEMS); - - local bit [DATA_WIDTH-1 : 0] data[]; - local bit [DATA_WIDTH-1 : 0] mask[]; - local bit vld[]; - bit busy; - - function new(); - data = new[ITEMS]; - mask = new[ITEMS]; - vld = new[ITEMS]; - busy = 0; - for(int i = 0; i < ITEMS; i++) begin - vld[i] = 0; - end - endfunction - - function int record(bit [log2(ITEMS)-1 : 0] a); - record = vld[a]; - endfunction - - function void write(bit [DATA_WIDTH-1 : 0] d, bit [DATA_WIDTH-1 : 0] m, bit [log2(ITEMS)-1 : 0] a); - busy = 1; - data[a] = d; - mask[a] = m; - vld[a] = 1; - busy = 0; - endfunction - - function void read(bit [log2(ITEMS)-1 : 0] a, output bit [DATA_WIDTH-1 : 0] d, output bit [DATA_WIDTH-1 : 0] m); - busy = 1; - d = data[a]; - m = mask[a]; - busy = 0; - endfunction - - function void match(bit [DATA_WIDTH-1 : 0] d, output bit [ITEMS-1 : 0] bmp, output bit hit); - busy = 1; - for(int i = 0; i < ITEMS; i++) begin - if (FULL_PRINT == TRUE) begin - $write("addr : %d\n", i); - $write("data : %b\n", data[i]); - $write("mask : %b\n", mask[i]); - $write("match : %b\n", d); - end - if (vld[i]) begin - bmp[i] = (data[i] & mask[i]) == (d & mask[i]); - if (FULL_PRINT == TRUE) begin - $write("is match : %b\n", bmp[i]); - end - end else begin - bmp[i] = 0; - if (FULL_PRINT == TRUE) begin - $write("is match : %b\n", bmp[i]); - end - end - end - hit = |bmp; - if (FULL_PRINT == TRUE) begin - $write("TOTAL match: %h\n\n", bmp); - end - busy = 0; - endfunction -endclass - - -class ScoreboardWriteDriverCbs #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM) extends DriverCbs; - tcam_model #(DATA_WIDTH, ITEMS) tcam; - - function new(tcam_model #(DATA_WIDTH, ITEMS) tcam_i); - this.tcam = tcam_i; - endfunction - - virtual task pre_tx(ref Transaction transaction, string inst); - endtask - - virtual task post_tx(Transaction transaction, string inst); - //$write("Write transaction\n"); - WbTransaction #(DATA_WIDTH, log2(ITEMS), FRAGMENTED_MEM) tr; - $cast(tr, transaction); - if(FULL_PRINT == TRUE) begin - $write("Write to TCAM model\n"); - tr.display(); - end - wait(!tcam.busy); - tcam.write(tr.data, tr.mask, tr.addr); - endtask -endclass - -class ScoreboardReadDriverCbs #(int DATA_WIDTH, int ITEMS) extends DriverCbs; - tcam_model #(DATA_WIDTH, ITEMS) tcam; - TransactionTable #(0) sc_table; - - function new(tcam_model #(DATA_WIDTH, ITEMS) tcam_i, TransactionTable #(0) sc_table_i); - this.tcam = tcam_i; - this.sc_table = sc_table_i; - endfunction - - virtual task pre_tx(ref Transaction transaction, string inst); - endtask - - virtual task post_tx(Transaction transaction, string inst); - MvbTransaction #(log2(ITEMS)) tr; - MvbTransaction #(2*DATA_WIDTH) read_out_tr; - bit [DATA_WIDTH-1 : 0] read_data = {DATA_WIDTH{1'b0}}; - bit [DATA_WIDTH-1 : 0] read_mask = {DATA_WIDTH{1'b0}}; - - //$write("Read transaction\n"); - $cast(tr, transaction); - if(FULL_PRINT == TRUE) begin - $write("Read from TCAM model\n"); - tr.display(); - end - wait(!tcam.busy); - if(tcam.record(tr.data)) begin - tcam.read(tr.data, read_data, read_mask); - end - - read_out_tr = new(); - read_out_tr.data[2*DATA_WIDTH-1 : DATA_WIDTH] = read_data; - read_out_tr.data[ DATA_WIDTH-1 : 0] = read_mask; - - sc_table.add(read_out_tr); - endtask -endclass - -class ScoreboardMatchDriverCbs #(int DATA_WIDTH, int ITEMS) extends DriverCbs; - tcam_model #(DATA_WIDTH,ITEMS) tcam; - TransactionTable #(0) sc_table; - - function new(tcam_model #(DATA_WIDTH, ITEMS) tcam_i, TransactionTable #(0) sc_table_i); - this.tcam = tcam_i; - this.sc_table = sc_table_i; - endfunction - - virtual task pre_tx(ref Transaction transaction, string inst); - endtask - - virtual task post_tx(Transaction transaction, string inst); - MvbTransaction #(DATA_WIDTH) tr; - MvbTransaction #(ITEMS+1) match_out_tr; - bit [ITEMS-1 : 0] match_out; - bit match_out_hit; - - //$write("Match transaction\n"); - $cast(tr, transaction); - if (FULL_PRINT == TRUE) begin - $write("Match to TCAM model\n"); - tr.display(); - end - wait(!tcam.busy); - tcam.match(tr.data, match_out, match_out_hit); - - match_out_tr = new(); - match_out_tr.data[ITEMS-1 : 0] = match_out; - match_out_tr.data[ITEMS] = match_out_hit; - - sc_table.add(match_out_tr); - endtask -endclass - - -class ScoreboardMonitorCbs extends MonitorCbs; - TransactionTable #(0) sc_table; - - function new(TransactionTable #(0) sc_table_i); - this.sc_table = sc_table_i; - endfunction - - virtual task pre_rx(ref Transaction transaction, string inst); - endtask - - virtual task post_rx(Transaction transaction, string inst); - bit status = 0; - sc_table.remove(transaction, status); - if(status == 0) begin - $write("Unknown transaction received from monitor %s\n", inst); - $timeformat(-9, 3, " ns", 8); - $write("Time: %t\n", $time); - transaction.display(); - sc_table.display(); - $stop; - end; - endtask -endclass - - -class Scoreboard #(int DATA_WIDTH, int ITEMS, bit FRAGMENTED_MEM); - - ScoreboardWriteDriverCbs #(DATA_WIDTH, ITEMS, FRAGMENTED_MEM) writeDriverCbs; - ScoreboardReadDriverCbs #(DATA_WIDTH, ITEMS) readDriverCbs; - ScoreboardMatchDriverCbs #(DATA_WIDTH, ITEMS) matchDriverCbs; - ScoreboardMonitorCbs readMonitorCbs; - ScoreboardMonitorCbs matchMonitorCbs; - tcam_model #(DATA_WIDTH,ITEMS) tcam; - TransactionTable #(0) scoreTable; - - function new(); - tcam = new(); - scoreTable = new(); - readMonitorCbs = new(scoreTable); - matchMonitorCbs = new(scoreTable); - writeDriverCbs = new(tcam); - readDriverCbs = new(tcam, scoreTable); - matchDriverCbs = new(tcam, scoreTable); - endfunction - - task display(); - scoreTable.display(); - endtask - -endclass diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/test.sv b/comp/mvb_tools/storage/tcam/ver/tbench/test.sv deleted file mode 100644 index b22e459ba..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/test.sv +++ /dev/null @@ -1,149 +0,0 @@ -// test.sv: Automatic test -// Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac -// -// SPDX-License-Identifier: BSD-3-Clause - -import sv_common_pkg::*; -import sv_mvb_pkg::*; -import sv_wb_pkg::*; -import test_pkg::*; - -program TEST ( - input logic CLK, - output logic RESET, - iWbRx.tb WRITE, - iMvbRx.tb READ, - iMvbTx.tb READ_OUT, - iMvbRx.tb MATCH, - iMvbTx.tb MATCH_OUT, - iMvbTx.monitor READ_MONITOR, - iMvbTx.monitor MATCH_MONITOR -); - - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, USE_FRAGMENTED_MEM) write_bp; - MvbTransaction #(ADDR_WIDTH) read_bp; - MvbTransaction #(DATA_WIDTH) match_bp; - - Generator write_gen; - Generator read_gen; - Generator match_gen; - - WbDriver #(DATA_WIDTH, ADDR_WIDTH, USE_FRAGMENTED_MEM) write_driver; - MvbDriver #(1, ADDR_WIDTH) read_driver; - MvbDriver #(MVB_ITEMS, DATA_WIDTH) match_driver; - - MvbResponder #(1, 2*DATA_WIDTH) read_responder; - MvbResponder #(MVB_ITEMS, ITEMS+1) match_responder; - MvbMonitor #(1, 2*DATA_WIDTH) read_monitor; - MvbMonitor #(MVB_ITEMS, ITEMS+1) match_monitor; - - Scoreboard #(DATA_WIDTH, ITEMS, USE_FRAGMENTED_MEM) scoreboard; - - task createGeneratorEnvironment(); - write_gen = new("Write Generator", 0); - read_gen = new("Read Generator" , 0); - match_gen = new("Match Generator", 0); - write_bp = new; - read_bp = new; - match_bp = new; - write_gen.blueprint = write_bp; - read_gen.blueprint = read_bp; - match_gen.blueprint = match_bp; - endtask - - task createEnvironment(); - write_driver = new("Write Driver", write_gen.transMbx, WRITE); - read_driver = new("Read Driver" , read_gen.transMbx, READ ); - match_driver = new("Match Driver", match_gen.transMbx, MATCH); - - read_monitor = new("Read Monitor" , READ_MONITOR ); - match_monitor = new("Match Monitor", MATCH_MONITOR); - read_responder = new("Read Responder", READ_OUT); - read_responder.wordDelayEnable_wt = 0; - read_responder.wordDelayDisable_wt = 1; - match_responder = new("Match Responder", MATCH_OUT); - match_responder.wordDelayEnable_wt = 0; - match_responder.wordDelayDisable_wt = 1; - - scoreboard = new(); - - write_driver.setCallbacks(scoreboard.writeDriverCbs); - read_driver.setCallbacks(scoreboard.readDriverCbs); - match_driver.setCallbacks(scoreboard.matchDriverCbs); - - read_monitor.setCallbacks(scoreboard.readMonitorCbs); - match_monitor.setCallbacks(scoreboard.matchMonitorCbs); - endtask - - task resetDesign(); - RESET=1; - #RESET_TIME RESET = 0; - endtask - - task enableTestEnvironment(); - write_driver.setEnabled(); - read_driver.setEnabled(); - match_driver.setEnabled(); - read_responder.setEnabled(); - match_responder.setEnabled(); - endtask - - task disableTestEnvironment(); - wait(!write_driver.busy); - wait(!read_driver.busy); - wait(!match_driver.busy); - do begin - wait(!read_monitor.busy); - fork : ReadStayIdleWait - wait(read_monitor.busy) disable ReadStayIdleWait; - #(100*CLK_PERIOD) disable ReadStayIdleWait; - join - end while(read_monitor.busy); - do begin - wait(!match_monitor.busy); - fork : MatchStayIdleWait - wait(match_monitor.busy) disable MatchStayIdleWait; - #(100*CLK_PERIOD) disable MatchStayIdleWait; - join - end while(match_monitor.busy); - write_driver.setDisabled(); - read_driver.setDisabled(); - match_driver.setDisabled(); - read_monitor.setDisabled(); - match_monitor.setDisabled(); - read_responder.setDisabled(); - match_responder.setDisabled(); - endtask - - task test1(); - $write("\n\n############ TEST CASE 1 ############\n\n"); - read_monitor.setEnabled(); - match_monitor.setEnabled(); - write_gen.setEnabled(WRITE_COUNT); - wait(!write_gen.enabled); - wait(!write_driver.busy); - #(10*CLK_PERIOD) - match_gen.setEnabled(MATCH_COUNT); - wait(!match_gen.enabled); - wait(!match_driver.busy); - #(10*CLK_PERIOD) - if(READ_FROM_TCAM == TRUE) begin - read_gen.setEnabled(READ_COUNT); - wait(!read_gen.enabled); - end - disableTestEnvironment(); - scoreboard.display(); - endtask - - initial begin - createGeneratorEnvironment(); - createEnvironment(); - enableTestEnvironment(); - resetDesign(); - test1(); - $write("Verification finished successfully!\n"); - $stop(); - end - -endprogram diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/test_pkg.sv b/comp/mvb_tools/storage/tcam/ver/tbench/test_pkg.sv index e3b46e7d2..335988778 100644 --- a/comp/mvb_tools/storage/tcam/ver/tbench/test_pkg.sv +++ b/comp/mvb_tools/storage/tcam/ver/tbench/test_pkg.sv @@ -1,6 +1,7 @@ // test_pkg.sv: Test package // Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac +// Author(s): Tomas Fukac +// Tomas Hak // // SPDX-License-Identifier: BSD-3-Clause @@ -10,9 +11,9 @@ package test_pkg; import sv_common_pkg::*; // SystemVerilog Boolean parameter MVB_ITEMS = 4; + parameter REPLICAS = MVB_ITEMS; parameter DATA_WIDTH = 8; parameter ITEMS = 64; - parameter ADDR_WIDTH = log2(ITEMS); parameter RESOURCES_SAVING = 0; parameter WRITE_BEFORE_MATCH = TRUE; parameter READ_FROM_TCAM = TRUE; @@ -20,6 +21,14 @@ package test_pkg; parameter USE_FRAGMENTED_MEM = FALSE; parameter DEVICE = "ULTRASCALE"; + parameter IS_INTEL = (DEVICE == "AGILEX" || DEVICE == "STRATIX10" || DEVICE == "ARRIA10"); + // with USE_FRAGMENTED_MEM = TRUE, ITEMS must be aligned to multiples of 20 for Intel FPGAs + parameter MLAB_ITEMS = USE_FRAGMENTED_MEM ? 20 : 16; + parameter SLICEM_ITEMS = DEVICE == "ULTRASCALE" ? (USE_FRAGMENTED_MEM ? 14 : 8) : (USE_FRAGMENTED_MEM ? 6 : 4); + parameter BLOCK_ITEMS = IS_INTEL ? MLAB_ITEMS : SLICEM_ITEMS; + parameter ITEMS_ALIGNED = USE_FRAGMENTED_MEM ? (ITEMS/BLOCK_ITEMS)*(2**log2(BLOCK_ITEMS)) : ITEMS; + parameter ADDR_WIDTH = log2(ITEMS_ALIGNED); + parameter WRITE_COUNT = 200; parameter MATCH_COUNT = 100000; parameter READ_COUNT = 200; @@ -29,6 +38,6 @@ package test_pkg; parameter CLK_PERIOD = 10ns; parameter RESET_TIME = 10*CLK_PERIOD; - `include "scoreboard.sv" + `include "../../../../../base/mem/tcam2/ver/tbench/scoreboard.sv" endpackage diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/testbench.sv b/comp/mvb_tools/storage/tcam/ver/tbench/testbench.sv deleted file mode 100644 index 3dbdc6818..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/testbench.sv +++ /dev/null @@ -1,44 +0,0 @@ -// testbench.sv: Top Entity for automatic test -// Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac -// -// SPDX-License-Identifier: BSD-3-Clause - -import test_pkg::*; - -module testbench; - - logic CLK = 0; - logic RESET; - - iWbRx #(DATA_WIDTH, ADDR_WIDTH ) WRITE (CLK, RESET); - iMvbRx #(1, ADDR_WIDTH ) READ (CLK, RESET); - iMvbTx #(1, 2*DATA_WIDTH ) READ_OUT (CLK, RESET); - iMvbRx #(MVB_ITEMS, DATA_WIDTH ) MATCH (CLK, RESET); - iMvbTx #(MVB_ITEMS, ITEMS+1 ) MATCH_OUT (CLK, RESET); - - always #(CLK_PERIOD/2) CLK = ~CLK; - - DUT DUT_U ( - .CLK (CLK), - .RESET (RESET), - .WRITE (WRITE), - .READ (READ), - .READ_OUT (READ_OUT), - .MATCH (MATCH), - .MATCH_OUT (MATCH_OUT) - ); - - TEST TEST_U ( - .CLK (CLK), - .RESET (RESET), - .WRITE (WRITE), - .READ (READ), - .READ_OUT (READ_OUT), - .MATCH (MATCH), - .MATCH_OUT (MATCH_OUT), - .READ_MONITOR (READ_OUT), - .MATCH_MONITOR (MATCH_OUT) - ); - -endmodule diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/Modules.tcl b/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/Modules.tcl deleted file mode 100644 index 12a494c4b..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/Modules.tcl +++ /dev/null @@ -1,11 +0,0 @@ -# Modules.tcl: Local include tcl script -# Copyright (C) 2023 CESNET z. s. p. o. -# Author: Tomas Fukac -# -# SPDX-License-Identifier: BSD-3-Clause - -set SV_COMMON_BASE "$OFM_PATH/comp/ver" - -set COMPONENTS [list [list "SV_COMMON" $SV_COMMON_BASE "FULL"]] - -set MOD "$MOD $ENTITY_BASE/sv_wb_pkg.sv" diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/sv_wb_pkg.sv b/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/sv_wb_pkg.sv deleted file mode 100644 index 8efefe995..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/sv_wb_pkg.sv +++ /dev/null @@ -1,16 +0,0 @@ -// sv_wb_pkg.sv: SystemVerilog package with Write Bus -// Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac -// -// SPDX-License-Identifier: BSD-3-Clause - -`include "wb_ifc.sv" - -package sv_wb_pkg; - - import sv_common_pkg::*; - - `include "wb_transaction.sv" - `include "wb_driver.sv" - -endpackage diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_driver.sv b/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_driver.sv deleted file mode 100644 index b33d88fca..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_driver.sv +++ /dev/null @@ -1,79 +0,0 @@ -// wb_driver.sv: Write Bus interface Driver -// Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac -// -// SPDX-License-Identifier: BSD-3-Clause - -class WbDriver #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE) extends Driver; - - protected virtual iWbRx#(DATA_WIDTH,ADDR_WIDTH).tb vif; - protected bit [DATA_WIDTH-1 : 0] data; - protected bit [DATA_WIDTH-1 : 0] mask; - protected bit [ADDR_WIDTH-1 : 0] addr; - - protected bit src_rdy; - protected int unsigned word; - - rand bit wordDelayEn; - int wordDelayEnable_wt = 0; - int wordDelayDisable_wt = 1; - rand integer wordDelay; - int wordDelayLow = 0; - int wordDelayHigh = 0; - - constraint cDelays{ - wordDelayEn dist {1'b1 := wordDelayEnable_wt, 1'b0 := wordDelayDisable_wt}; - wordDelay inside { [wordDelayLow:wordDelayHigh] }; - } - - - function new(string i, tTransMbx t, virtual iWbRx#(DATA_WIDTH,ADDR_WIDTH).tb v); - super.new(i, t); - vif = v; - src_rdy = 0; - endfunction - - task moveWord(); - vif.cb.DATA <= data; - vif.cb.MASK <= mask; - vif.cb.ADDR <= addr; - vif.cb.SRC_RDY <= src_rdy; - if(src_rdy) begin - do - @(vif.cb); - while(!vif.cb.DST_RDY); - vif.cb.SRC_RDY <= 0; - IDLE_RANDOMIZE : assert(randomize()); - if(wordDelayEn) - repeat(wordDelay) - @(vif.cb); - end else begin - @(vif.cb); - end - src_rdy = 0; - endtask - - task run(); - Transaction transaction; - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM) tr; - @(vif.cb); // initial sync - while(enabled) begin - while(transMbx.try_get(transaction) == 0) begin // wait for transaction - moveWord(); - busy = 0; - if (!enabled) return; - end - busy = 1; - - foreach(cbs[i]) cbs[i].pre_tx(transaction, inst); // notify callbacks - $cast(tr, transaction); - data = tr.data; - mask = tr.mask; - addr = tr.addr; - src_rdy = 1; - foreach(cbs[i]) cbs[i].post_tx(transaction, inst); - moveWord(); - end - endtask - -endclass diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_ifc.sv b/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_ifc.sv deleted file mode 100644 index ffa586d0f..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_ifc.sv +++ /dev/null @@ -1,34 +0,0 @@ -// wb_ifc.sv: Write Bus interface -// Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac -// -// SPDX-License-Identifier: BSD-3-Clause - -// Write Bus RX (verification to DUT) interface -interface iWbRx #(DATA_WIDTH = 64, ADDR_WIDTH = 8) (input logic CLK, RESET); - initial VALID_PARAMETERS : assert(DATA_WIDTH > 0 && ADDR_WIDTH > 0); - - logic [DATA_WIDTH-1 : 0] DATA = 0; - logic [DATA_WIDTH-1 : 0] MASK = 0; - logic [ADDR_WIDTH-1 : 0] ADDR = 0; - logic SRC_RDY = 0; - logic DST_RDY; - - clocking cb @(posedge CLK); - default input #1step output #500ps; - output DATA, MASK, ADDR, SRC_RDY; - input DST_RDY; - endclocking; - - clocking monitor_cb @(posedge CLK); - default input #1step output #500ps; - input DATA, MASK, ADDR, SRC_RDY, DST_RDY; - endclocking: monitor_cb; - - modport dut (input DATA, MASK, ADDR, SRC_RDY, output DST_RDY); - - modport tb (clocking cb); - - modport monitor (clocking monitor_cb); - -endinterface diff --git a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_transaction.sv b/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_transaction.sv deleted file mode 100644 index 9d49a17d3..000000000 --- a/comp/mvb_tools/storage/tcam/ver/tbench/write_bus/wb_transaction.sv +++ /dev/null @@ -1,47 +0,0 @@ -// wb_transaction.sv: Write Bus transaction -// Copyright (C) 2023 CESNET z. s. p. o. -// Author: Tomas Fukac -// -// SPDX-License-Identifier: BSD-3-Clause - -class WbTransaction #(DATA_WIDTH = 64, ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE) extends Transaction; - - rand bit [DATA_WIDTH-1 : 0] data; - rand bit [DATA_WIDTH-1 : 0] mask; - rand bit [ADDR_WIDTH-1 : 0] addr; - - // in fragmented mode MLAB addresses 21-32 are not used - constraint frag_mem_constr { addr[4 : 0] < 20 || !FRAGMENTED_MEM; } - - virtual function void display(string prefix = ""); - if(prefix != "") begin - $write("---------------------------------------------------------\n"); - $write("-- %s\n",prefix); - $write("---------------------------------------------------------\n"); - end - $write("DATA: 0x%1h\n", data); - $write("MASK: 0x%1h\n", mask); - $write("ADDR: 0x%1h\n", addr); - endfunction - - virtual function Transaction copy(Transaction to = null); - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM) tr; - if(to == null) begin - tr = new(); - end else begin - $cast(tr, to); - end - tr.data = data; - tr.mask = mask; - tr.addr = addr; - copy = tr; - endfunction - - virtual function bit compare(input Transaction to, output string diff, input int kind = -1); - WbTransaction #(DATA_WIDTH, ADDR_WIDTH, FRAGMENTED_MEM) tr; - $cast(tr, to); - // TODO!!! - return data == tr.data; - endfunction - -endclass diff --git a/comp/mvb_tools/storage/tcam/ver/top_level.fdo b/comp/mvb_tools/storage/tcam/ver/top_level.fdo index b79bc2969..cb0f698ab 100644 --- a/comp/mvb_tools/storage/tcam/ver/top_level.fdo +++ b/comp/mvb_tools/storage/tcam/ver/top_level.fdo @@ -1,6 +1,7 @@ # top_level.fdo: Top Level Function simulation file # Copyright (C) 2023 CESNET z. s. p. o. -# Author: Tomas Fukac +# Author(s): Tomas Fukac +# Tomas Hak # # SPDX-License-Identifier: BSD-3-Clause @@ -9,16 +10,14 @@ set FIRMWARE_BASE "../../../../.." set DUT_BASE ".." set DUT_VER_BASE "." -set TB_FILE "./tbench/testbench.sv" +set TB_FILE "$FIRMWARE_BASE/comp/base/mem/tcam2/ver/tbench/testbench.sv" set SIG_FILE "./signals_sig.fdo" -set COMPONENTS [list \ - [list "DUT" $DUT_BASE "FULL"]\ - [list "DUT_VER" $DUT_VER_BASE "FULL"]\ -] +lappend COMPONENTS [list "DUT" $DUT_BASE "FULL" ] +lappend COMPONENTS [list "DUT_VER" $DUT_VER_BASE "FULL" ] -# Disable Code Coverage -set CODE_COVERAGE "false" +set SIM_FLAGS(CODE_COVERAGE) false +set SIM_FLAGS(DEBUG) false # Global include file for compilation source "$FIRMWARE_BASE/build/Modelsim.inc.fdo" diff --git a/comp/mvb_tools/storage/tcam/ver/ver_settings.py b/comp/mvb_tools/storage/tcam/ver/ver_settings.py index 3d43b214b..4863c2633 100644 --- a/comp/mvb_tools/storage/tcam/ver/ver_settings.py +++ b/comp/mvb_tools/storage/tcam/ver/ver_settings.py @@ -1,6 +1,7 @@ # ver_settings.py # Copyright (C) 2023 CESNET z. s. p. o. -# Author: Tomas Fukac +# Author(s): Tomas Fukac +# Tomas Hak # # SPDX-License-Identifier: BSD-3-Clause