Skip to content

Commit

Permalink
Merge branch 'isa_frame_packer' into 'devel'
Browse files Browse the repository at this point in the history
Improve frame packer verification

See merge request ndk/ndk-fpga!142
  • Loading branch information
radek-isa committed Jan 21, 2025
2 parents 0f54daf + 622e747 commit f0908d6
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 83 deletions.
13 changes: 13 additions & 0 deletions comp/mfb_tools/flow/frame_packer/readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://www.vut.cz/www_base/zav_prace_soubor_verejne.php?file_id=267988>`_ (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.

113 changes: 75 additions & 38 deletions comp/mfb_tools/flow/frame_packer/uvm/tbench/env/model.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 7 additions & 19 deletions comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/speed.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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");

Expand All @@ -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
Expand Down
24 changes: 6 additions & 18 deletions comp/mfb_tools/flow/frame_packer/uvm/tbench/tests/test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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");

Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit f0908d6

Please sign in to comment.