diff --git a/comp/mfb_tools/flow/frame_packer/readme.rst b/comp/mfb_tools/flow/frame_packer/readme.rst index c6561f87e..169ed63c5 100644 --- a/comp/mfb_tools/flow/frame_packer/readme.rst +++ b/comp/mfb_tools/flow/frame_packer/readme.rst @@ -78,3 +78,16 @@ The length and the channel ID are sent to the ``MVB_FIFO`` which is directly con References ~~~~~~~~~~ For more detailed description refer to `David Beneš's master thesis `_ (2023/2024) + +Known bugs +~~~~~~~~~~ + +There is a possible bug when sending the combination of small and large packets. In 400G +version this could result in sending a packet larger than USR_PKT_SIZE_MAX. + +Another bug considers incomplete resetting logic of a signal that blocks the activation of the Timeout counter in the FP_TIMEOUT_EXT component. +This bug occures in a verification when, at the end of the run, a Superpacket is sent due to a Timeout on a channel, and then one more packet +(smaller than the size of the MFB word) arrives on this channel. It gets stuck in the Assembly/Temporary register forever as the Timeout counter +gets unblocked only when the register "overflows" (i.e., a packet continues over this word). The solution should be to fix the reset logic for +the `timeout_block` signal. + diff --git a/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/model.sv b/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/model.sv index 9305d5e1b..b1b53d291 100644 --- a/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/model.sv +++ b/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/model.sv @@ -22,8 +22,11 @@ class model #(RX_CHANNELS, PKT_MTU, META_WIDTH, MFB_ITEM_WIDTH) extends uvm_com // FIFO to store SUPERPACKET + protected uvm_logic_vector_array::sequence_item #(MFB_ITEM_WIDTH) channel_fifo_data[RX_CHANNELS][$]; + protected uvm_logic_vector::sequence_item #($clog2(RX_CHANNELS) + $clog2(PKT_MTU+1)) channel_fifo_meta[RX_CHANNELS][$]; protected logic [MFB_ITEM_WIDTH-1 : 0] sp_fifo[RX_CHANNELS][$]; protected int unsigned pkt_num; + protected int unsigned sp_num_cnt; function new(string name = "model", uvm_component parent = null); super.new(name, parent); @@ -46,77 +49,68 @@ class model #(RX_CHANNELS, PKT_MTU, META_WIDTH, MFB_ITEM_WIDTH) extends uvm_com int unsigned ret = 0; ret |= (data_in.used() != 0); ret |= (meta_in.used() != 0); + for (int unsigned it = 0; it < RX_CHANNELS; it++) begin + ret |= (channel_fifo_data[it].size() != 0); + ret |= (channel_fifo_meta[it].size() != 0); + ret |= (sp_fifo[it].size() != 0); + end return ret; endfunction - task run_phase(uvm_phase phase); - - string msg = ""; - string dbg = ""; - - uvm_logic_vector_array::sequence_item #(MFB_ITEM_WIDTH) tr_mfb_in; - uvm_logic_vector::sequence_item #($clog2(RX_CHANNELS) + $clog2(PKT_MTU+1)) tr_mvb_in; - + task run_channel(int unsigned channel, uvm_phase phase); + const string tag = $sformatf("CHANNEL %0d", channel); // EOF of SUPERPACKET uvm_logic_vector::sequence_item #(2) tr_last; - - // SUPERPACKET counter - int unsigned sp_num_cnt = 0; - - //Channel - logic[$clog2(RX_CHANNELS)-1 : 0] rx_channel; - logic[$clog2(PKT_MTU+1 )-1 : 0] rx_length; logic[$clog2(PKT_MTU+1 )-1 : 0] tx_length; logic[$clog2(RX_CHANNELS)-1 : 0] tx_channel; logic[META_WIDTH-1 : 0] tx_meta; logic tx_discard; + string msg = ""; + int unsigned chan_pkt_num; + uvm_logic_vector_array::sequence_item #(MFB_ITEM_WIDTH) tr_mfb_in; + uvm_logic_vector::sequence_item #($clog2(RX_CHANNELS) + $clog2(PKT_MTU+1)) tr_mvb_in; + int unsigned it; forever begin - int unsigned it; - // Get input packet - data_in.get(tr_mfb_in); - meta_in.get(tr_mvb_in); - pkt_num++; - {rx_length, rx_channel} = tr_mvb_in.data; - assert (rx_length == tr_mfb_in.data.size()) else begin `uvm_fatal(this.get_full_name(), $sformatf("RX length %0d is different from mfb length %0d\n", rx_length, tr_mfb_in.data.size())); end + wait (channel_fifo_data[channel].size() != 0 && channel_fifo_meta[channel].size()); - analysis_export_flow_ctrl[rx_channel].get(tr_last); - msg = $sformatf("Received pakcet %0d\nCHANNEL %0d\n\nEOF: %0d\nLAST: %0d\nMODEL_IN: %0s\n", pkt_num, rx_channel, tr_last.data[0], tr_last.data[1], tr_mfb_in.convert2string()); - `uvm_info(this.get_full_name(), msg, UVM_MEDIUM); + tr_mfb_in = channel_fifo_data[channel].pop_front(); + tr_mvb_in = channel_fifo_meta[channel].pop_front(); + chan_pkt_num++; //SUPERPACKET assemble for (it = 0; it < tr_mfb_in.data.size(); it++) begin - sp_fifo[unsigned'(rx_channel)].push_back(tr_mfb_in.data[it]); + sp_fifo[channel].push_back(tr_mfb_in.data[it]); end //pealing it = it%8; if (it != 0) begin for (; it < 8; it++) begin - sp_fifo[unsigned'(rx_channel)].push_back('x); + sp_fifo[channel].push_back('x); end end - // // DEBUG - // debug_fifo_state.item.data = sp_fifo[int'(channel)]; - // $write(dbg, "FIFO_STATE \n %0s \n", debug_fifo_state.convert2string()); - // `uvm_info(this.get_full_name(), dbg, UVM_MEDIUM); + //GET if packet is last + analysis_export_flow_ctrl[channel].get(tr_last); + `uvm_info(this.get_full_name(), $sformatf("Received pakcet %0d\nCHANNEL %0d\n\nEOF: %0d\nLAST: %0d\nMODEL_IN: %0s\n", pkt_num, channel, tr_last.data[0], tr_last.data[1], tr_mfb_in.convert2string()), UVM_MEDIUM); if (tr_last.data[1] == 1) begin uvm_logic_vector_array::sequence_item #(MFB_ITEM_WIDTH) tr_mfb_out; uvm_logic_vector::sequence_item #($clog2(RX_CHANNELS) + $clog2(PKT_MTU+1) + META_WIDTH + 1) tr_mvb_out; tr_mfb_out = uvm_logic_vector_array::sequence_item #(MFB_ITEM_WIDTH)::type_id::create("tr_mfb_out", this); - tr_mfb_out.tag = $sformatf("CHANNEL %0d", rx_channel); + tr_mfb_out.tag = tag; sp_num_cnt++; - tr_mfb_out.data = sp_fifo[unsigned'(rx_channel)]; + tr_mfb_out.data = sp_fifo[channel]; + sp_fifo[channel].delete(); tr_mvb_out = uvm_logic_vector::sequence_item #($clog2(RX_CHANNELS) + $clog2(PKT_MTU+1) + META_WIDTH + 1)::type_id::create("tr_mvb_out", this); - tr_mvb_out.tag = $sformatf("CHANNEL %0d", rx_channel); + tr_mvb_out.tag = tag; tx_length = tr_mfb_out.data.size(); tx_meta = 'x; tx_discard = 'x; - tx_channel = rx_channel; + tx_channel = channel; tr_mvb_out.data = {tx_length, tx_meta, tx_discard, tx_channel}; //DEBUG @@ -126,13 +120,56 @@ class model #(RX_CHANNELS, PKT_MTU, META_WIDTH, MFB_ITEM_WIDTH) extends uvm_com "\nSUPERPACKET_NO: %0d", "\nSUPERPACKET_SIZE: %0d bytes", "\n**************************************************************************\n"} - , $time, rx_channel, sp_num_cnt, sp_fifo[unsigned'(rx_channel)].size()); + , $time, channel, sp_num_cnt, tr_mfb_out.data.size()); //`uvm_info(this.get_full_name(), msg, UVM_MEDIUM); - - sp_fifo[unsigned'(rx_channel)].delete(); data_out.write(tr_mfb_out); meta_out.write(tr_mvb_out); end end endtask + + + + task run_phase(uvm_phase phase); + uvm_logic_vector_array::sequence_item #(MFB_ITEM_WIDTH) tr_mfb_in; + uvm_logic_vector::sequence_item #($clog2(RX_CHANNELS) + $clog2(PKT_MTU+1)) tr_mvb_in; + logic[$clog2(PKT_MTU+1 )-1 : 0] rx_length; + + //Channel + logic[$clog2(RX_CHANNELS)-1 : 0] rx_channel; + sp_num_cnt = 0; + pkt_num = 0; + + for(int unsigned it = 0; it < RX_CHANNELS; it++) begin + fork + automatic int index = it; + run_channel(index, phase); + join_none; + end + + + forever begin + int unsigned it; + // Get input packet + data_in.get(tr_mfb_in); + meta_in.get(tr_mvb_in); + pkt_num++; + {rx_length, rx_channel} = tr_mvb_in.data; + assert (rx_length == tr_mfb_in.data.size()) else begin `uvm_fatal(this.get_full_name(), $sformatf("RX length %0d is different from mfb length %0d\n", rx_length, tr_mfb_in.data.size())); end + + channel_fifo_data[rx_channel].push_back(tr_mfb_in); + channel_fifo_meta[rx_channel].push_back(tr_mvb_in); + end + endtask + + function void report_phase(uvm_phase phase); + string msg = "\n"; + + msg = {msg, $sformatf("\tData (%0d) meta (%0d)\n", data_in.used(), meta_in.used())}; + msg = {msg, $sformatf("\tPacket processed %0d megapacket created %0d\n", pkt_num, sp_num_cnt)}; + for (int unsigned it = 0; it < RX_CHANNELS; it++) begin + msg = {msg, $sformatf("\t\tchannel %0d Data (%0d) meta (%0d) internal superpacket data (%0d)\n", it, channel_fifo_data[it].size(), channel_fifo_meta[it].size(), sp_fifo[it].size())}; + end + `uvm_info(this.get_full_name(), msg, UVM_NONE); + endfunction endclass diff --git a/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/scoreboard_cmp.sv b/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/scoreboard_cmp.sv index e332a01df..0d664b0ff 100644 --- a/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/scoreboard_cmp.sv +++ b/comp/mfb_tools/flow/frame_packer/uvm/tbench/env/scoreboard_cmp.sv @@ -13,14 +13,7 @@ class comparer_superpacket #(type CLASS_TYPE) extends uvm_common::comparer_taged endfunction virtual function int unsigned compare(MODEL_ITEM tr_model, DUT_ITEM tr_dut); - int unsigned ret = 1; - if (tr_model.data.size() < tr_dut.data.size()) return 0; - for (int unsigned it = 0; it < tr_model.size(); it++) begin - if (!$isunknown(tr_model.data[it]) && tr_model.data[it] !== tr_dut.data[it]) begin - return 0; - end - end - return ret; + return ((tr_dut.data ==? tr_model.data) === 1'b1); endfunction endclass diff --git a/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/speed.sv b/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/speed.sv index 1062cadf6..b72e17179 100644 --- a/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/speed.sv +++ b/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/speed.sv @@ -44,7 +44,6 @@ class speed extends uvm_test; // declare the Environment reference variable uvm_framepacker::env #(MFB_REGIONS, MFB_REGION_SIZE, MFB_BLOCK_SIZE, MFB_ITEM_WIDTH, SPACE_SIZE_MIN_RX, SPACE_SIZE_MAX_RX, SPACE_SIZE_MIN_TX, SPACE_SIZE_MAX_TX, RX_CHANNELS, USR_RX_PKT_SIZE_MAX, HDR_META_WIDTH) m_env; - int unsigned timeout; // ------------------------------------------------------------------------ // Functions @@ -75,6 +74,7 @@ class speed extends uvm_test; // ------------------------------------------------------------------------ // Create environment and Run sequences on their sequencers virtual task run_phase(uvm_phase phase); + time timeout; virt_seq_full_speed #(MFB_REGIONS, MFB_REGION_SIZE, MFB_BLOCK_SIZE, MFB_ITEM_WIDTH, RX_CHANNELS, USR_RX_PKT_SIZE_MAX) m_vseq; m_vseq = virt_seq_full_speed #(MFB_REGIONS, MFB_REGION_SIZE, MFB_BLOCK_SIZE, MFB_ITEM_WIDTH, RX_CHANNELS, USR_RX_PKT_SIZE_MAX)::type_id::create("m_vseq"); @@ -86,30 +86,18 @@ class speed extends uvm_test; m_vseq.randomize(); m_vseq.start(m_env.vscr); - timeout = 1; - fork - test_wait_timeout(1000); - test_wait_result(); - join_any; - phase.drop_objection(this); - - endtask - - task test_wait_timeout(int unsigned time_length); - #(time_length*1us); - endtask - - task test_wait_result(); - do begin + timeout = $time(); + while ((timeout + 0.5ms) > $time() && m_env.m_scoreboard.used() != 0) begin #(600ns); - end while (m_env.m_scoreboard.used() != 0); - timeout = 0; + end + + phase.drop_objection(this); endtask function void report_phase(uvm_phase phase); `uvm_info(this.get_full_name(), {"\n\tTEST : ", this.get_type_name(), " END\n"}, UVM_NONE); - if (timeout) begin + if (m_env.m_scoreboard.used()) begin `uvm_error(this.get_full_name(), "\n\t===================================================\n\tTIMEOUT SOME PACKET STUCK IN DESIGN\n\t===================================================\n\n"); end endfunction diff --git a/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/test.sv b/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/test.sv index 6aee13576..aa0847209 100644 --- a/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/test.sv +++ b/comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/test.sv @@ -10,7 +10,6 @@ class ex_test extends uvm_test; // declare the Environment reference variable uvm_framepacker::env #(MFB_REGIONS, MFB_REGION_SIZE, MFB_BLOCK_SIZE, MFB_ITEM_WIDTH, SPACE_SIZE_MIN_RX, SPACE_SIZE_MAX_RX, SPACE_SIZE_MIN_TX, SPACE_SIZE_MAX_TX, RX_CHANNELS, USR_RX_PKT_SIZE_MAX, HDR_META_WIDTH) m_env; - int unsigned timeout; // ------------------------------------------------------------------------ // Functions @@ -27,6 +26,7 @@ class ex_test extends uvm_test; // ------------------------------------------------------------------------ // Create environment and Run sequences o their sequencers task run_seq(uvm_phase phase); + time timeout; virt_sequence#(MFB_REGIONS, MFB_REGION_SIZE, MFB_BLOCK_SIZE, MFB_ITEM_WIDTH, RX_CHANNELS, USR_RX_PKT_SIZE_MAX) m_vseq; m_vseq = virt_sequence#(MFB_REGIONS, MFB_REGION_SIZE, MFB_BLOCK_SIZE, MFB_ITEM_WIDTH, RX_CHANNELS, USR_RX_PKT_SIZE_MAX)::type_id::create("m_vseq"); @@ -37,11 +37,10 @@ class ex_test extends uvm_test; m_vseq.randomize(); m_vseq.start(m_env.vscr); - timeout = 1; - fork - test_wait_timeout(1000); - test_wait_result(); - join_any; + timeout = $time(); + while ((timeout + 0.5ms) > $time() && m_env.m_scoreboard.used() != 0) begin + #(600ns); + end phase.drop_objection(this, "End of rx sequence"); endtask @@ -50,20 +49,9 @@ class ex_test extends uvm_test; run_seq(phase); endtask - task test_wait_timeout(int unsigned time_length); - #(time_length*1us); - endtask - - task test_wait_result(); - do begin - #(600ns); - end while (m_env.m_scoreboard.used() != 0); - timeout = 0; - endtask - function void report_phase(uvm_phase phase); `uvm_info(this.get_full_name(), {"\n\tTEST : ", this.get_type_name(), " END\n"}, UVM_NONE); - if (timeout) begin + if (m_env.m_scoreboard.used()) begin `uvm_error(this.get_full_name(), "\n\t===================================================\n\tTIMEOUT SOME PACKET STUCK IN DESIGN\n\t===================================================\n\n"); end endfunction