sim: Parameterize chdr_word_t data type

This replaces chdr_word_t, which was a statically defined 64-bit data
type, with a paramaterizable data type that matches the defined CHDR_W.
Code that formerly referenced the chdr_word_t data type can now define
the data type for their desired CHDR_W and ITEM_W as follows:

  // Define the CHDR word and item/sample data types
  typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
  typedef ChdrData #(CHDR_W, ITEM_W)::item_t      item_t;

ITEM_W is optional when defining chdr_word_t if items are not
needed. Static methods in the ChdrData class also provide the ability to
convert between CHDR words and data items. For example:

  // Convert CHDR data buffer to a buffer of samples
  samples = ChdrData#(CHDR_W, ITEM_W)::chdr_to_item(data);


Original-commit: fc895feacb8dde3b02c9a4eccb4b4f4a654f2881
This commit is contained in:
Wade Fife
2020-03-09 13:43:05 -05:00
parent 1db22ce4ec
commit 14dc3950cf
16 changed files with 411 additions and 216 deletions
@@ -83,6 +83,8 @@ module rfnoc_block_axi_ram_fifo_tb #(
// Bus Functional Models
//---------------------------------------------------------------------------
typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t;
RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_ctrl_clk);
AxiStreamIf #(32) m_ctrl (rfnoc_ctrl_clk, 1'b0);
AxiStreamIf #(32) s_ctrl (rfnoc_ctrl_clk, 1'b0);
@@ -35,6 +35,7 @@ module rfnoc_block_ddc_tb();
// Block configuration
localparam int CHDR_W = 64;
localparam int SAMP_W = 32;
localparam int THIS_PORTID = 'h123;
localparam int MTU = 8;
localparam int NUM_PORTS = 1;
@@ -60,6 +61,8 @@ module rfnoc_block_ddc_tb();
// Bus Functional Models
//---------------------------------------------------------------------------
typedef ChdrData #(CHDR_W, SAMP_W)::chdr_word_t chdr_word_t;
RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_ctrl_clk);
AxiStreamIf #(32) m_ctrl (rfnoc_ctrl_clk, 1'b0);
AxiStreamIf #(32) s_ctrl (rfnoc_ctrl_clk, 1'b0);
@@ -35,6 +35,7 @@ module rfnoc_block_duc_tb();
// Block configuration
localparam int CHDR_W = 64;
localparam int SAMP_W = 32;
localparam int THIS_PORTID = 'h123;
localparam int MTU = 8;
localparam int NUM_PORTS = 1;
@@ -49,6 +50,7 @@ module rfnoc_block_duc_tb();
bit rfnoc_chdr_clk;
bit rfnoc_ctrl_clk;
bit ce_clk;
sim_clock_gen #(CHDR_CLK_PER) rfnoc_chdr_clk_gen (.clk(rfnoc_chdr_clk), .rst());
sim_clock_gen #(CHDR_CLK_PER) rfnoc_ctrl_clk_gen (.clk(rfnoc_ctrl_clk), .rst());
@@ -59,6 +61,8 @@ module rfnoc_block_duc_tb();
// Bus Functional Models
//---------------------------------------------------------------------------
typedef ChdrData #(CHDR_W, SAMP_W)::chdr_word_t chdr_word_t;
RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_ctrl_clk);
AxiStreamIf #(32) m_ctrl (rfnoc_ctrl_clk, 1'b0);
AxiStreamIf #(32) s_ctrl (rfnoc_ctrl_clk, 1'b0);
@@ -30,6 +30,7 @@ module rfnoc_block_fft_tb();
// Block configuration
localparam int NOC_ID = 32'hFF70_0000;
localparam int CHDR_W = 64;
localparam int SAMP_W = 32;
localparam int THIS_PORTID = 'h123;
localparam int MTU = 10;
localparam int NUM_PORTS = 1;
@@ -60,6 +61,8 @@ module rfnoc_block_fft_tb();
// Bus Functional Models
//---------------------------------------------------------------------------
typedef ChdrData #(CHDR_W, SAMP_W)::chdr_word_t chdr_word_t;
RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_ctrl_clk);
AxiStreamIf #(32) m_ctrl (rfnoc_ctrl_clk, 1'b0);
AxiStreamIf #(32) s_ctrl (rfnoc_ctrl_clk, 1'b0);
@@ -36,6 +36,7 @@ module rfnoc_block_fir_filter_tb #(
// DUT parameters to test
localparam int CHDR_W = 64;
localparam int SAMP_W = 32;
localparam int THIS_PORTID = 'h123;
localparam int MTU = 8;
//
@@ -86,6 +87,8 @@ module rfnoc_block_fir_filter_tb #(
// Bus Functional Models
//---------------------------------------------------------------------------
typedef ChdrData #(CHDR_W, SAMP_W)::chdr_word_t chdr_word_t;
RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_ctrl_clk);
AxiStreamIf #(32) m_ctrl (rfnoc_ctrl_clk, 1'b0);
AxiStreamIf #(32) s_ctrl (rfnoc_ctrl_clk, 1'b0);
@@ -24,6 +24,7 @@ module rfnoc_block_null_src_sink_tb;
localparam [9:0] THIS_PORTID = 10'h17;
localparam [15:0] THIS_EPID = 16'hDEAD;
localparam int CHDR_W = 64;
localparam int ITEM_W = 32;
localparam int SPP = 201;
localparam int LPP = ((SPP+1)/2);
localparam int NUM_PKTS = 50;
@@ -48,6 +49,8 @@ module rfnoc_block_null_src_sink_tb;
AxiStreamIf #(CHDR_W) s0_chdr (rfnoc_chdr_clk); // Optional data iface
AxiStreamIf #(CHDR_W) s1_chdr (rfnoc_chdr_clk); // Optional data iface
typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
// Bus functional model for a software block controller
RfnocBlockCtrlBfm #(.CHDR_W(CHDR_W)) blk_ctrl;
@@ -128,7 +131,7 @@ module rfnoc_block_null_src_sink_tb;
// Read status register and validate it
blk_ctrl.reg_read(dut.REG_CTRL_STATUS, rvalue);
`ASSERT_ERROR(rvalue[31:24] == 2, "Incorrect NIPC Value");
`ASSERT_ERROR(rvalue[23:16] == 32, "Incorrect ITEM_W Value");
`ASSERT_ERROR(rvalue[23:16] == ITEM_W, "Incorrect ITEM_W Value");
test.end_timeout(timeout);
end
test.end_test();
@@ -139,7 +142,7 @@ module rfnoc_block_null_src_sink_tb;
repeat (NUM_PKTS) begin
chdr_word_t rx_data[$];
int rx_bytes;
automatic ItemDataBuff #(logic[31:0]) tx_dbuff = new, rx_dbuff = new;
automatic ItemDataBuff #(logic[ITEM_W-1:0]) tx_dbuff = new, rx_dbuff = new;
for (int i = 0; i < SPP; i++)
tx_dbuff.put($urandom());
test.start_timeout(timeout, 5us, "Waiting for pkt to loop back");
@@ -176,7 +179,7 @@ module rfnoc_block_null_src_sink_tb;
repeat (NUM_PKTS) begin
chdr_word_t rx_data[$];
int rx_bytes;
automatic ItemDataBuff #(logic[31:0]) tx_dbuff = new;
automatic ItemDataBuff #(logic[ITEM_W-1:0]) tx_dbuff = new;
for (int i = 0; i < SPP; i++)
tx_dbuff.put($urandom());
test.start_timeout(timeout, 5us, "Waiting for pkt to loop back");
@@ -27,7 +27,6 @@ module rfnoc_block_radio_tb #(
import PkgRfnocBlockCtrlBfm::*;
import PkgAxisCtrlBfm::*;
import PkgChdrBfm::*;
import PkgRfnocItemUtils::*;
// Pull in radio register offsets and constants
`include "rfnoc_block_radio_regs.vh"
@@ -87,6 +86,9 @@ module rfnoc_block_radio_tb #(
AxiStreamIf #(CHDR_W) m_chdr [NUM_PORTS] (rfnoc_chdr_clk, 1'b0);
AxiStreamIf #(CHDR_W) s_chdr [NUM_PORTS] (rfnoc_chdr_clk, 1'b0);
typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
typedef ChdrData #(CHDR_W, ITEM_W)::item_t sample_t;
// Bus functional model for a software block controller
RfnocBlockCtrlBfm #(.CHDR_W(CHDR_W)) blk_ctrl = new(backend, m_ctrl, s_ctrl);
@@ -370,13 +372,13 @@ module rfnoc_block_radio_tb #(
for (int i = 0; i < valid_words; i++) begin
// Check each sample of the next chdr_word_t value
for (int sub_sample = 0; sub_sample < $bits(chdr_word_t)/ITEM_W; sub_sample++) begin
chdr_word_t word;
word = data[i][ITEM_W*sub_sample +: ITEM_W]; // Work around Vivado 2018.3 issue
sample_t actual;
actual = data[i][ITEM_W*sub_sample +: ITEM_W]; // Work around Vivado 2018.3 issue
`ASSERT_ERROR(
word == sample_val,
actual == sample_val,
$sformatf(
"Sample %0d (0x%X) didn't match expected value (0x%X)",
sample_count, data[i][ITEM_W*sub_sample +: ITEM_W], sample_val
sample_count, actual, sample_val
)
);
sample_val++;
@@ -45,6 +45,8 @@ module chdr_stream_endpoint_tb;
localparam [9:0] PORT_A = 10'd1;
localparam [9:0] PORT_B = 10'd2;
typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t;
// ----------------------------------------
// DUT (and Crossbar) Instantiations
// ----------------------------------------
+1
View File
@@ -12,6 +12,7 @@ PkgTestExec.sv \
test_exec.svh \
sim_clock_gen.sv \
PkgAxiStreamBfm.sv \
PkgChdrData.sv \
PkgChdrUtils.sv \
PkgChdrBfm.sv \
PkgAxisCtrlBfm.sv \
+2 -2
View File
@@ -29,7 +29,7 @@ package PkgAxisCtrlBfm;
//------------
axis_ctrl_header_t header;
chdr_word_t timestamp;
chdr_timestamp_t timestamp;
ctrl_op_word_t op_word;
ctrl_word_t data[$];
@@ -86,7 +86,7 @@ package PkgAxisCtrlBfm;
ref axis_ctrl_header_t header,
ref ctrl_op_word_t op_word,
ref ctrl_word_t data[$],
input chdr_word_t timestamp = 0
input chdr_timestamp_t timestamp = 0
);
this.header = header;
this.data = data;
+150 -123
View File
@@ -21,14 +21,17 @@ package PkgChdrBfm;
// CHDR Packet Class
//---------------------------------------------------------------------------
class ChdrPacket #(int BUS_WIDTH = 64);
class ChdrPacket #(int CHDR_W = 64);
typedef ChdrPacket #(BUS_WIDTH) ChdrPacket;
typedef ChdrPacket #(CHDR_W) ChdrPacket;
typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t;
chdr_header_t header;
chdr_word_t timestamp;
chdr_word_t metadata[$];
chdr_word_t data[$];
const int BYTES_PER_CHDR_W = CHDR_W / 8;
chdr_header_t header;
chdr_timestamp_t timestamp;
chdr_word_t metadata[$];
chdr_word_t data[$];
extern function ChdrPacket copy();
extern function bit equal(ChdrPacket packet);
@@ -39,12 +42,12 @@ package PkgChdrBfm;
extern function void write_raw (ref chdr_header_t header,
ref chdr_word_t data[$],
input chdr_word_t metadata[$] = {},
input chdr_word_t timestamp = 0,
input chdr_timestamp_t timestamp = 0,
input int data_byte_length = -1);
extern function void read_raw (output chdr_header_t header,
output chdr_word_t data[$],
output chdr_word_t metadata[$],
output chdr_word_t timestamp,
output chdr_timestamp_t timestamp,
output int data_byte_length);
extern function void write_stream_status(ref chdr_header_t header,
ref chdr_str_status_t status);
@@ -62,12 +65,12 @@ package PkgChdrBfm;
ref chdr_ctrl_header_t ctrl_header,
ref ctrl_op_word_t ctrl_op_word,
ref ctrl_word_t ctrl_data[$],
input chdr_word_t ctrl_timestamp = 0);
input chdr_timestamp_t ctrl_timestamp = 0);
extern function void read_ctrl (output chdr_header_t header,
output chdr_ctrl_header_t ctrl_header,
output ctrl_op_word_t ctrl_op_word,
output ctrl_word_t ctrl_data[$],
output chdr_word_t ctrl_timestamp);
output chdr_timestamp_t ctrl_timestamp);
// Helper methods
@@ -79,6 +82,8 @@ package PkgChdrBfm;
extern function string sprint_raw();
extern function string sprint_pretty();
extern function bit chdr_word_queues_equal(ref chdr_word_t a[$], ref chdr_word_t b[$]);
endclass : ChdrPacket;
@@ -88,14 +93,14 @@ package PkgChdrBfm;
//---------------------------------------------------------------------------
class ChdrBfm #(
parameter int BUS_WIDTH = 64,
parameter int CHDR_W = 64,
parameter int USER_WIDTH = 1
) extends AxiStreamBfm #(BUS_WIDTH, USER_WIDTH);
) extends AxiStreamBfm #(CHDR_W, USER_WIDTH);
typedef ChdrPacket #(BUS_WIDTH) ChdrPacket;
typedef ChdrPacket #(CHDR_W) ChdrPacket;
typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t;
// Number of 64-bit CHDR words per AXI word
const int CHDR_PER_BUS = BUS_WIDTH / $bits(chdr_word_t);
const int BYTES_PER_CHDR_W = CHDR_W / 8;
// Default fields used by high-level transaction methods
chdr_epid_t dst_epid;
@@ -103,8 +108,8 @@ package PkgChdrBfm;
extern function new (
virtual AxiStreamIf #(BUS_WIDTH, USER_WIDTH).master master,
virtual AxiStreamIf #(BUS_WIDTH, USER_WIDTH).slave slave
virtual AxiStreamIf #(CHDR_W, USER_WIDTH).master master,
virtual AxiStreamIf #(CHDR_W, USER_WIDTH).slave slave
);
@@ -210,7 +215,7 @@ package PkgChdrBfm;
str = {str, $sformatf(" > chdr_str_command_t : %p\n", tmp_cmd)};
end else if (header.pkt_type == CHDR_CONTROL) begin
chdr_header_t tmp_hdr;
chdr_word_t tmp_ts;
chdr_timestamp_t tmp_ts;
chdr_ctrl_header_t tmp_ctrl_hdr;
ctrl_op_word_t tmp_op_word;
ctrl_word_t tmp_ctrl_data[$];
@@ -250,11 +255,11 @@ package PkgChdrBfm;
// method to calculate the payload length based on the size of the data
// array.
function void ChdrPacket::write_raw (
ref chdr_header_t header,
ref chdr_word_t data[$],
input chdr_word_t metadata[$] = {},
input chdr_word_t timestamp = 0,
input int data_byte_length = -1
ref chdr_header_t header,
ref chdr_word_t data[$],
input chdr_word_t metadata[$] = {},
input chdr_timestamp_t timestamp = 0,
input int data_byte_length = -1
);
this.header = header;
this.timestamp = timestamp;
@@ -267,11 +272,11 @@ package PkgChdrBfm;
int array_num_bytes;
// Make sure number of words for data_byte_length matches data length
assert((data_byte_length+7) / 8 == data.size()) else begin
assert((data_byte_length+(BYTES_PER_CHDR_W-1)) / BYTES_PER_CHDR_W == data.size()) else begin
$error("ChdrPacket::write_raw: data_byte_length doesn't correspond to number of words in data");
end
array_num_bytes = data.size() * $bits(chdr_word_t)/8;
array_num_bytes = data.size() * BYTES_PER_CHDR_W;
this.header.length -= (array_num_bytes - data_byte_length);
end
endfunction : write_raw
@@ -279,11 +284,11 @@ package PkgChdrBfm;
// Read the contents of this packet
function void ChdrPacket::read_raw (
output chdr_header_t header,
output chdr_word_t data[$],
output chdr_word_t metadata[$],
output chdr_word_t timestamp,
output int data_byte_length
output chdr_header_t header,
output chdr_word_t data[$],
output chdr_word_t metadata[$],
output chdr_timestamp_t timestamp,
output int data_byte_length
);
header = this.header;
data = this.data;
@@ -301,8 +306,8 @@ package PkgChdrBfm;
header.pkt_type = CHDR_STRM_STATUS; // Update packet type in header
this.header = header;
data = {};
for (int i = 0; i < $bits(status); i += $bits(chdr_word_t)) begin
data.push_back( status[i +: $bits(chdr_word_t)] );
for (int i = 0; i < $bits(status); i += CHDR_W) begin
data.push_back( status[i +: CHDR_W] );
end
update_lengths();
endfunction : write_stream_status
@@ -315,17 +320,17 @@ package PkgChdrBfm;
);
// Make sure it's a stream status packet
assert(this.header.pkt_type == CHDR_STRM_STATUS) else begin
$error("ChdrPacket::read_status: Packet type is not CHDR_STRM_STATUS");
$error("ChdrPacket::read_stream_status: Packet type is not CHDR_STRM_STATUS");
end
// Make sure we have enough payload
assert($bits(status) <= $bits(data)) else begin
$error("ChdrPacket::read_status: Not enough data for status payload");
$error("ChdrPacket::read_stream_status: Not enough data for status payload");
end
header = this.header;
for (int i = 0; i < $bits(status)/$bits(chdr_word_t); i++) begin
status[i*$bits(chdr_word_t) +: $bits(chdr_word_t)] = data[i];
for (int i = 0; i < $bits(status)/CHDR_W; i++) begin
status[i*CHDR_W +: CHDR_W] = data[i];
end
endfunction : read_stream_status
@@ -338,8 +343,8 @@ package PkgChdrBfm;
header.pkt_type = CHDR_STRM_CMD; // Update packet type in header
this.header = header;
data = {};
for (int i = 0; i < $bits(command); i += $bits(chdr_word_t)) begin
data.push_back( command[i +: $bits(chdr_word_t)] );
for (int i = 0; i < $bits(command); i += CHDR_W) begin
data.push_back( command[i +: CHDR_W] );
end
update_lengths();
endfunction : write_stream_cmd
@@ -352,17 +357,17 @@ package PkgChdrBfm;
);
// Make sure it's a stream command packet
assert(this.header.pkt_type == CHDR_STRM_CMD) else begin
$error("ChdrPacket::read_command: Packet type is not CHDR_STRM_CMD");
$error("ChdrPacket::read_stream_cmd: Packet type is not CHDR_STRM_CMD");
end
// Make sure we have enough payload
assert($bits(command) <= $bits(data)) else begin
$error("ChdrPacket::read_command: Not enough data for command payload");
$error("ChdrPacket::read_stream_cmd: Not enough data for command payload");
end
header = this.header;
for (int i = 0; i < $bits(command)/$bits(chdr_word_t); i++) begin
command[i*$bits(chdr_word_t) +: $bits(chdr_word_t)] = data[i];
for (int i = 0; i < $bits(command)/CHDR_W; i++) begin
command[i*CHDR_W +: CHDR_W] = data[i];
end
endfunction : read_stream_cmd
@@ -402,7 +407,7 @@ package PkgChdrBfm;
header = this.header;
num_ops = data_bytes()/8 - 1; // Num words, minus one for the header
num_ops = data_bytes()/BYTES_PER_CHDR_W - 1; // Num words, minus one for the header
// Make sure we have enough payload
assert(1 + num_ops <= data.size()) else begin
@@ -425,34 +430,49 @@ package PkgChdrBfm;
ref chdr_ctrl_header_t ctrl_header,
ref ctrl_op_word_t ctrl_op_word,
ref ctrl_word_t ctrl_data[$],
input chdr_word_t ctrl_timestamp = 0
input chdr_timestamp_t ctrl_timestamp = 0
);
bit partial_word;
ctrl_word_t mandatory_data;
ChdrData #(CHDR_W, 64)::item_queue_t data64;
header.pkt_type = CHDR_CONTROL; // Update packet type in header
this.header = header;
data = {};
data64 = {};
// Insert word 0 of control payload
data.push_back(ctrl_header[63:0]);
data64.push_back(ctrl_header);
// Insert word 1 of control payload, if timestamp is used
if (ctrl_header.has_time) begin
data.push_back(ctrl_timestamp);
data64.push_back(ctrl_timestamp);
end
// Make sure the amount of data passed matches the header
assert (ctrl_header.num_data == ctrl_data.size()) else begin
$error("ChdrPacket::write_ctrl: NumData doesn't match ctrl_data[] size");
end
// Insert word 2 of control payload, the operation word
// and first word of control data.
mandatory_data = (ctrl_header.num_data > 0) ? ctrl_data[0] : '0;
data.push_back({mandatory_data, ctrl_op_word[31:0]});
data64.push_back({mandatory_data, ctrl_op_word[31:0]});
// We have a half CHDR word if num_data is even
partial_word = (ctrl_header.num_data[0] == '0);
// Insert remaining data, if present
for (int i = 1; i < ctrl_data.size(); i+=2) begin
data.push_back({(partial_word ? '0 : ctrl_data[i+1]), ctrl_data[i]});
if (i == ctrl_data.size()-1) begin
// num_data must be even in this case, so last word is half filled
data64.push_back({ 32'b0, ctrl_data[i] });
end else begin
data64.push_back({ ctrl_data[i+1], ctrl_data[i] });
end
end
// Convert from 64-bit words to CHDR_W-bit words
data = ChdrData #(CHDR_W, 64)::item_to_chdr(data64);
update_lengths();
endfunction : write_ctrl
@@ -463,62 +483,71 @@ package PkgChdrBfm;
output chdr_ctrl_header_t ctrl_header,
output ctrl_op_word_t ctrl_op_word,
output ctrl_word_t ctrl_data[$],
output chdr_word_t ctrl_timestamp
output chdr_timestamp_t ctrl_timestamp
);
ChdrData #(CHDR_W, 32)::item_queue_t data32;
chdr_word_t chdr_op_word;
int ctrl_packet_size;
int dptr = 0;
// Make sure it's a stream status packet
assert(this.header.pkt_type == CHDR_CONTROL) else begin
$error("ChdrPacket::read_status: Packet type is not CHDR_CONTROL");
$error("ChdrPacket::read_ctrl: Packet type is not CHDR_CONTROL");
end
// Make sure we have enough payload
assert($bits(ctrl_header)+$bits(ctrl_op_word) <= $bits(data)) else begin
$error("ChdrPacket::read_status: Not enough data for status payload");
end
// Convert packet to 32-bit words for easier parsing
data32 = ChdrData #(CHDR_W, 32)::chdr_to_item(data, data_bytes());
// CHDR header
header = this.header;
// Word 0
ctrl_header[63:0] = data[dptr++];
// Ctrl header
ctrl_header = { data32[dptr+1], data32[dptr] };
dptr += 2;
// Word 1
if (ctrl_header.has_time) begin
ctrl_timestamp = data[dptr++];
// Make sure we have enough payload. Calculate expected size in 32-bit
// words.
ctrl_packet_size = 3 + ctrl_header.num_data; // header + op_word + data
if (ctrl_header.has_time) ctrl_packet_size += 2; // timestamp
assert(data32.size() < ctrl_packet_size) else begin
$error("ChdrPacket::read_ctrl: Not enough CHDR payload for control packet");
end
assert(data32.size() > ctrl_packet_size) else begin
$warning("ChdrPacket::read_ctrl: Excess CHDR payload for control packet");
end
// Word 2, last 32-bits of control header and first word of control data
chdr_op_word = data[dptr++];
ctrl_op_word = chdr_op_word[31:0];
ctrl_data.delete();
if (ctrl_header.num_data > 0) begin
ctrl_data[0] = chdr_op_word[63:32];
// Timestamp (optional)
if(ctrl_header.has_time) begin
ctrl_timestamp = { data32[dptr+1], data32[dptr] };
dptr += 2;
end
// Copy any remaining data words
for (int i = dptr; i < data.size(); i++) begin
ctrl_data.push_back(data[i][31:0]);
if (i != data.size()-1 || ctrl_header.num_data[0] != 0)
ctrl_data.push_back(data[i][63:32]);
// Operation word
ctrl_op_word = data32[dptr++];
// Data words
ctrl_data = {};
while (dptr < data32.size()) begin
ctrl_data.push_back(data32[dptr++]);
end
endfunction : read_ctrl
// Calculate the header size (including timestamp), in bytes, from the header
// information.
function int ChdrPacket::header_bytes();
if (BUS_WIDTH == $bits(chdr_word_t) && header.pkt_type == CHDR_DATA_WITH_TS) begin
header_bytes = 2 * (BUS_WIDTH / 8); // Two words (header + timestamp)
if (CHDR_W == 64 && header.pkt_type == CHDR_DATA_WITH_TS) begin
header_bytes = 2 * BYTES_PER_CHDR_W; // Two words (header + timestamp)
end else begin
header_bytes = (BUS_WIDTH / 8); // One word, regardless of timestamp
header_bytes = BYTES_PER_CHDR_W; // One word, regardless of timestamp
end
endfunction : header_bytes
// Calculate the metadata size from the header information.
function int ChdrPacket::mdata_bytes();
mdata_bytes = header.num_mdata * BUS_WIDTH/8;
mdata_bytes = header.num_mdata * BYTES_PER_CHDR_W;
endfunction : mdata_bytes
@@ -535,15 +564,12 @@ package PkgChdrBfm;
int num_mdata;
// Calculate NumMData based on the size of metadata queue
num_mdata = metadata.size() / (BUS_WIDTH / $bits(chdr_word_t));
if (metadata.size() % (BUS_WIDTH / $bits(chdr_word_t)) != 0) begin
num_mdata++;
end
num_mdata = metadata.size();
assert(num_mdata < 2**$bits(chdr_num_mdata_t)) else
$fatal(1, "ChdrPacket::update_lengths(): Calculated NumMData exceeds maximum size");
// Calculate the Length field
num_bytes = data.size() * $bits(chdr_word_t) / 8; // Payload length
num_bytes = data.size() * BYTES_PER_CHDR_W; // Payload length
num_bytes = num_bytes + header_bytes() + mdata_bytes(); // Payload + header length
assert(num_bytes < 2**$bits(chdr_length_t)) else
$fatal(1, "ChdrPacket::update_lengths(): Calculated Length exceeds maximum size");
@@ -554,6 +580,20 @@ package PkgChdrBfm;
endfunction : update_lengths
// Returns 1 if the queues have the same contents, otherwise returns 0. This
// function is equivalent to (a == b), but this doesn't work correctly yet in
// Vivado 2018.3.
function automatic bit ChdrPacket::chdr_word_queues_equal(ref chdr_word_t a[$], ref chdr_word_t b[$]);
chdr_word_t x, y;
if (a.size() != b.size()) return 0;
foreach (a[i]) begin
x = a[i];
y = b[i];
if (x !== y) return 0;
end
return 1;
endfunction : chdr_word_queues_equal
//---------------------------------------------------------------------------
@@ -564,11 +604,11 @@ package PkgChdrBfm;
// Class constructor. This must be given an interface for the master
// connection and an interface for the slave connection.
function ChdrBfm::new (
virtual AxiStreamIf #(BUS_WIDTH, USER_WIDTH).master master,
virtual AxiStreamIf #(BUS_WIDTH, USER_WIDTH).slave slave
virtual AxiStreamIf #(CHDR_W, USER_WIDTH).master master,
virtual AxiStreamIf #(CHDR_W, USER_WIDTH).slave slave
);
super.new(master, slave);
assert(BUS_WIDTH % 64 == 0) else begin
assert(CHDR_W % 64 == 0) else begin
$fatal(1, "ChdrBfm::new: CHDR bus width must be a multiple of 64 bits");
end
endfunction : new
@@ -637,6 +677,7 @@ package PkgChdrBfm;
enum int { ST_HEADER, ST_TIMESTAMP, ST_METADATA, ST_PAYLOAD } rx_state;
data_t word;
int num_rx_mdata;
int num_rx_bytes;
ChdrPacket chdr_packet = new();
rx_state = ST_HEADER;
@@ -646,12 +687,13 @@ package PkgChdrBfm;
case (rx_state)
ST_HEADER : begin
num_rx_bytes += BYTES_PER_CHDR_W;
chdr_packet.header = word[63:0];
// Depending on the size of the word, we could have just the header
// or both the header and the timestamp in this word.
if (chdr_packet.header.pkt_type == CHDR_DATA_WITH_TS) begin
if ($bits(word) >= 128) begin
if (CHDR_W >= 128) begin
chdr_packet.timestamp = word[127:64];
rx_state = ST_METADATA;
end else begin
@@ -667,33 +709,33 @@ package PkgChdrBfm;
end
end
ST_TIMESTAMP : begin
num_rx_bytes += BYTES_PER_CHDR_W;
chdr_packet.timestamp = word;
rx_state = (chdr_packet.header.num_mdata > 0) ? ST_METADATA : ST_PAYLOAD;
end
ST_METADATA : begin
for(int w = 0; w < CHDR_PER_BUS; w++) begin
// Grab the next chdr_word_t worth of bits
//$display("Grabbing meta word %d (%016X)", w, word[w*$bits(chdr_word_t) +: $bits(chdr_word_t)]);
chdr_packet.metadata.push_back(word[w*$bits(chdr_word_t) +: $bits(chdr_word_t)]);
end
chdr_packet.metadata.push_back(word);
num_rx_mdata++;
num_rx_bytes += BYTES_PER_CHDR_W;
if (num_rx_mdata == chdr_packet.header.num_mdata) rx_state = ST_PAYLOAD;
end
ST_PAYLOAD : begin
for(int w = 0; w < CHDR_PER_BUS; w++) begin
// Grab the next chdr_word_t worth of bits
//$display("Grabbing data word %d (%016X)", w, word[w*$bits(chdr_word_t) +: $bits(chdr_word_t)]);
chdr_packet.data.push_back(word[w*$bits(chdr_word_t) +: $bits(chdr_word_t)]);
end
chdr_packet.data.push_back(word);
num_rx_bytes += BYTES_PER_CHDR_W;
end
endcase
end
assert(rx_state == ST_PAYLOAD) else begin
assert (rx_state == ST_PAYLOAD) else begin
$error("ChdrBfm::axis_to_chdr: Malformed CHDR packet");
end
// Check length field, noting that the last word may be partially filled
assert (chdr_packet.header.length >= num_rx_bytes-(BYTES_PER_CHDR_W-1) &&
chdr_packet.header.length <= num_rx_bytes) else begin
$error("ChdrBfm::axis_to_chdr: Incorrect CHDR length");
end
return chdr_packet;
endfunction : axis_to_chdr
@@ -702,44 +744,37 @@ package PkgChdrBfm;
// Convert a CHDR packet data structure to a an AXI-Stream packet data
// structure.
function ChdrBfm::AxisPacket ChdrBfm::chdr_to_axis (ChdrPacket chdr_packet);
int num_bus_words, num_chdr_words, expected_bus_words;
int num_words, expected_words;
data_t bus_word = 0;
AxisPacket axis_packet = new();
// Check that we have the right number of metadata words
num_chdr_words = chdr_packet.metadata.size();
num_bus_words = num_chdr_words / CHDR_PER_BUS;
if (num_chdr_words % CHDR_PER_BUS != 0) num_bus_words++;
assert (num_bus_words == chdr_packet.header.num_mdata) else begin
assert (chdr_packet.metadata.size() == chdr_packet.header.num_mdata) else begin
$error("ChdrBfm::chdr_to_axis: Packet metadata size doesn't match header NumMData field");
end
// Calculate the number of words needed to represent this packet
num_bus_words = 0;
num_bus_words += chdr_packet.data.size() / CHDR_PER_BUS;
if (chdr_packet.data.size() % CHDR_PER_BUS != 0) num_bus_words++;
num_bus_words += chdr_packet.metadata.size() / CHDR_PER_BUS;
if (chdr_packet.metadata.size() % CHDR_PER_BUS != 0) num_bus_words++;
if (chdr_packet.header.pkt_type == CHDR_DATA_WITH_TS && CHDR_PER_BUS == 1) begin
num_words = chdr_packet.data.size() + chdr_packet.metadata.size();
if (chdr_packet.header.pkt_type == CHDR_DATA_WITH_TS && CHDR_W == 64) begin
// Add two words, one for header and one for timestamp
num_bus_words += 2;
num_words += 2;
end else begin
// Add one word only for header (which may or may not include a timestamp)
num_bus_words += 1;
num_words += 1;
end
// Calculate the number of words represented by the Length field
expected_bus_words = chdr_packet.header.length / (BUS_WIDTH/8);
if (chdr_packet.header.length % (BUS_WIDTH/8) != 0) expected_bus_words++;
expected_words = chdr_packet.header.length / BYTES_PER_CHDR_W;
if (chdr_packet.header.length % BYTES_PER_CHDR_W != 0) expected_words++;
// Make sure length field matches actual packet length
assert (num_bus_words == expected_bus_words) else begin
assert (num_words == expected_words) else begin
$error("ChdrBfm::chdr_to_axis: Packet size doesn't match header Length field");
end
// Insert header
bus_word[63:0] = chdr_packet.header;
if (BUS_WIDTH == 64) begin
if (CHDR_W == 64) begin
axis_packet.data.push_back(bus_word);
if (chdr_packet.header.pkt_type == CHDR_DATA_WITH_TS) begin
// Insert timestamp
@@ -754,21 +789,13 @@ package PkgChdrBfm;
// Insert metadata
while (chdr_packet.metadata.size() > 0) begin
bus_word = 0;
for (int w = 0; w < CHDR_PER_BUS; w++) begin
bus_word[w*$bits(chdr_word_t) +: $bits(chdr_word_t)] = chdr_packet.metadata.pop_front();
if (chdr_packet.metadata.size() == 0) break;
end
bus_word = chdr_packet.metadata.pop_front();
axis_packet.data.push_back(bus_word);
end
// Insert payload
while (chdr_packet.data.size() > 0) begin
bus_word = 0;
for (int word_count = 0; word_count < CHDR_PER_BUS; word_count++) begin
bus_word[word_count*64 +: 64] = chdr_packet.data.pop_front();
if (chdr_packet.data.size() == 0) break;
end
bus_word = chdr_packet.data.pop_front();
axis_packet.data.push_back(bus_word);
end
+155
View File
@@ -0,0 +1,155 @@
//
// Copyright 2020 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: PkgChdrData
//
// Description: This package defines the data types used to represent CHDR
// words and data samples in RFNoC as well as utilities for converting between
// them.
//
package PkgChdrData;
// Default value for ITEM_W needs to be 64 due to a bug in Vivado 2019.1.
class ChdrData #(int CHDR_W = 64, int ITEM_W = 64);
// CHDR bus word (CHDR_W bits)
typedef logic [CHDR_W-1:0] chdr_word_t ;
typedef chdr_word_t chdr_word_queue_t[$];
// The item/sample word type (user-defined width, a multiple of 8 bits)
typedef logic [ITEM_W-1:0] item_t ;
typedef item_t item_queue_t[$];
function new();
assert ((ITEM_W % 8 == 0) && (CHDR_W % ITEM_W == 0)) else begin
$fatal(1, "RfnocData::new: Invalid CHDR_W and/or ITEM_W");
end
endfunction
// Convert a queue of items to a queue of CHDR words
static function chdr_word_queue_t item_to_chdr(ref item_queue_t items);
int items_per_word = CHDR_W / ITEM_W;
int num_chdr_words = ((items.size() + items_per_word - 1) / items_per_word);
chdr_word_queue_t chdr_words;
chdr_word_t word;
for (int i = 0; i < num_chdr_words; i++) begin
for (int j = 0; j < items_per_word; j++) begin
word[j*ITEM_W +: ITEM_W] = items[i*items_per_word + j];
end
chdr_words.push_back(word);
end
return chdr_words;
endfunction : item_to_chdr
// Convert a queue of CHDR words to a queue of items. The optional
// num_bytes argument indicates how many bytes are in the item queue that
// you want to convert.
static function item_queue_t chdr_to_item(
ref chdr_word_queue_t chdr_words,
input int num_bytes = -1
);
int items_per_word = CHDR_W / ITEM_W;
int bytes_left;
item_queue_t item_words;
if (num_bytes < 0) bytes_left = chdr_words.size() * (CHDR_W / 8);
else bytes_left = num_bytes;
foreach (chdr_words[i]) begin
for (int j = 0; j < items_per_word; j++) begin
if (bytes_left > 0) begin
item_words.push_back(chdr_words[i][j*ITEM_W +: ITEM_W]);
bytes_left -= (ITEM_W/8);
end
end
end
assert (bytes_left == 0) else begin
$warning("ChdrData::chdr_to_item: num_bytes is not a multiple of items");
end
return item_words;
endfunction : chdr_to_item
// Return a string representation of the contents of the CHDR queue
static function string chdr_string(
ref chdr_word_queue_t chdr_words,
input string format = "%X"
);
string str = $sformatf("%0d-bit CHDR words (%0d words or %0d bytes):\n",
CHDR_W, chdr_words.size(), chdr_words.size() * (CHDR_W/8));
foreach (chdr_words[i]) begin
str = { str, $sformatf({"%5d> ", format, "\n"}, i, chdr_words[i]) };
end
return str;
endfunction : chdr_string
// Return a string representation of the contents of the item queue
static function string item_string(
ref item_queue_t items,
input string format = "%X"
);
string str = $sformatf("%0d-bit items (%0d items or %0d bytes)\n",
ITEM_W, items.size(), items.size() * (ITEM_W/8));
foreach (items[i]) begin
str = { str, $sformatf({"%5d> ", format, "\n"}, i, items[i]) };
end
return str;
endfunction : item_string
// Display a string representation of the contents of a CHDR word queue
static function void print_chdr(
ref chdr_word_queue_t chdr_words,
input string format = "%X"
);
$display(chdr_string(chdr_words, format));
endfunction : print_chdr
// Display a string representation of the contents of an item queue
static function void print_item(
ref item_queue_t items,
input string format = "%X"
);
$display(item_string(items, format));
endfunction : print_item
// Check if the contents of two CHDR queues is equal
static function bit chdr_equal(
ref chdr_word_queue_t left,
ref chdr_word_queue_t right
);
if (left.size() != right.size()) return 0;
for (int i = 0; i < left.size(); i++) begin
if (left[i] != right[i]) return 0;
end
return 1;
endfunction : chdr_equal
// Check if the contents of two item queues is equal
static function bit item_equal(
ref item_queue_t left,
ref item_queue_t right
);
if (left.size() != right.size()) return 0;
for (int i = 0; i < left.size(); i++) begin
if (left[i] != right[i]) return 0;
end
return 1;
endfunction : item_equal
endclass
endpackage : PkgChdrData
+5 -5
View File
@@ -16,11 +16,11 @@ package PkgChdrIfaceBfm;
typedef struct packed {
chdr_vc_t vc;
logic eob;
logic eov;
logic has_time;
chdr_word_t timestamp;
chdr_vc_t vc;
chdr_eob_t eob;
chdr_eov_t eov;
bit has_time;
chdr_timestamp_t timestamp;
} packet_info_t;
+18 -45
View File
@@ -13,16 +13,20 @@
package PkgChdrUtils;
import PkgChdrData::*;
//---------------------------------------------------------------------------
// Type Definitions
//---------------------------------------------------------------------------
// CHDR Definitions
// ----------------
//----------------------
// AXIS-CHDR Definitions
//----------------------
// The fundamental unit of the CHDR bus, which is always a multiple of 64-bits
typedef logic [63:0] chdr_word_t;
typedef chdr_word_t chdr_word_queue_t[$];
// Expose the CHDR word and item/sample data types and methods in the
// ChdrData class. The width of these types is a class parameter.
export PkgChdrData::ChdrData;
// CHDR header fields
typedef enum bit [2:0] {
@@ -37,10 +41,13 @@ package PkgChdrUtils;
} chdr_pkt_type_t; // CHDR Packet Type
typedef bit [ 5:0] chdr_vc_t; // CHDR Virtual Channel field
typedef bit [ 0:0] chdr_eob_t; // CHDR End of Burst field
typedef bit [ 0:0] chdr_eov_t; // CHDR End of Vector field
typedef bit [ 4:0] chdr_num_mdata_t; // CHDR Num Metadata field
typedef bit [15:0] chdr_seq_num_t; // CHDR SeqNum field
typedef bit [15:0] chdr_length_t; // CHDR Length field
typedef bit [15:0] chdr_epid_t; // CHDR EPID field
typedef bit [63:0] chdr_timestamp_t; // CHDR Timestamp field
// CHDR Context Field Identifiers
typedef enum bit [3:0] {
@@ -50,8 +57,9 @@ package PkgChdrUtils;
CONTEXT_FIELD_MDATA = 4'd3
} chdr_context_type_t;
//----------------------
// AXIS-Ctrl Definitions
// ---------------------
//----------------------
// The fundamental unit of the AXIS-Ctrl (control) bus, which is always 32 bits
typedef logic [31:0] ctrl_word_t;
@@ -82,9 +90,9 @@ package PkgChdrUtils;
typedef bit [3:0] ctrl_byte_en_t; // AXIS-Ctrl ByteEnable field
typedef bit [19:0] ctrl_address_t; // AXIS-Ctrl Address field
//-------------------------------
// CHDR Type-Specific Definitions
// ------------------------------
//-------------------------------
// CHDR Status packet fields
typedef enum bit [3:0] {
@@ -141,8 +149,8 @@ package PkgChdrUtils;
// CHDR packet header
typedef struct packed {
chdr_vc_t vc;
bit eob;
bit eov;
chdr_eob_t eob;
chdr_eov_t eov;
chdr_pkt_type_t pkt_type;
chdr_num_mdata_t num_mdata;
chdr_seq_num_t seq_num;
@@ -237,39 +245,4 @@ package PkgChdrUtils;
} chdr_mgmt_t;
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
// Returns 1 if the queues have the same contents, otherwise returns 0. This
// function is equivalent to (a == b), but this doesn't work correctly yet in
// Vivado 2018.3.
function automatic bit chdr_word_queues_equal(ref chdr_word_t a[$], ref chdr_word_t b[$]);
chdr_word_t x, y;
if (a.size() != b.size()) return 0;
foreach (a[i]) begin
x = a[i];
y = b[i];
if (x !== y) return 0;
end
return 1;
endfunction : chdr_word_queues_equal
// Returns 1 if the queues have the same contents, otherwise returns 0. This
// function is equivalent to (a == b), but this doesn't work correctly yet in
// Vivado 2018.3.
function automatic bit chdr_mgmt_op_queues_equal(ref chdr_mgmt_op_t a[$], ref chdr_mgmt_op_t b[$]);
chdr_mgmt_op_t x, y;
if (a.size() != b.size()) return 0;
foreach (a[i]) begin
x = a[i];
y = b[i];
if (x !== y) return 0;
end
return 1;
endfunction : chdr_mgmt_op_queues_equal
endpackage : PkgChdrUtils
+5 -3
View File
@@ -96,13 +96,15 @@ package PkgRfnocBlockCtrlBfm;
class RfnocBlockCtrlBfm #(CHDR_W = 64);
local virtual RfnocBackendIf.master backend;
local CtrlIfaceBfm ctrl;
local ChdrIfaceBfm #(CHDR_W) m_data[$];
local ChdrIfaceBfm #(CHDR_W) s_data[$];
local CtrlIfaceBfm ctrl;
local ChdrIfaceBfm #(CHDR_W) m_data[$];
local ChdrIfaceBfm #(CHDR_W) s_data[$];
local bit running;
localparam CMD_PROP_CYC = 5;
typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t;
// Class constructor to create a new BFM instance.
//
// backend: Interface for the backend signals of a block
+45 -30
View File
@@ -5,11 +5,14 @@
//
// Module: PkgRfnocItemUtils
//
// Description: This package contains utilities to handle and process items.
// Description: This package contains classes to handle and process CHDR items
// (e.g., samples) and to convert between CHDR words and items. It includes the
// following classes:
//
// - ItemDataBuff: A class that holds a collection of items of arbitrary width
// To can convert to and from a CHDR vector
// - ItemDataBuffQueue: A queue of ItemDataBuff buffers
// - ItemDataBuff: A class that holds a collection of items of arbitrary
// width and functions to convert to and from a CHDR vector.
//
// - ItemDataBuffQueue: A queue of ItemDataBuff buffers
//
package PkgRfnocItemUtils;
@@ -20,14 +23,20 @@ package PkgRfnocItemUtils;
// Item Data Buffer
//---------------------------------------------------------------------------
//
// This class items of an arbitrary type
// This is a class of "items" of an arbitrary type
//
//---------------------------------------------------------------------------
class ItemDataBuff #(type data_t);
typedef ItemDataBuff #(data_t) ItemDataBuffQueue[$];
class ItemDataBuff #(type item_t = logic [31:0], int CHDR_W = 64);
localparam ITEM_W = $bits(item_t);
// Redefine these types from PkgChdrUtils to workaround Vivado 2019.1 bug
typedef logic [CHDR_W-1:0] chdr_word_t;
typedef chdr_word_t chdr_word_queue_t[$];
// Store data in the user-specified format
local data_t buff[$];
local item_t buff[$];
// Create a new empty buffer
function new();
@@ -36,7 +45,7 @@ package PkgRfnocItemUtils;
// Get the bitwidth of a item in this buffer
function int item_w();
return $size(data_t);
return ITEM_W;
endfunction : item_w
// Delete the contents of this buffer
@@ -55,48 +64,46 @@ package PkgRfnocItemUtils;
endfunction : get_bytes
// Get the i'th element in this buffer
function data_t get(int i);
function item_t get(int i);
return buff[i];
endfunction : get
// Put and element in this buffer. If i is negative
// then put it at the end
function void put(data_t d, int i = -1);
function void put(item_t d, int i = -1);
if (i < 0)
buff.push_back(d);
else
buff.insert(i, d);
endfunction : put
// Convert the contents of this buffer to a CHDR payload
// A CHDR payload can be transmitted using the block controller
// BFM.
// Convert the contents of this buffer to a CHDR payload A CHDR payload can
// be transmitted using the block controller BFM.
function chdr_word_queue_t to_chdr_payload();
int samps_per_word = $size(chdr_word_t) / $size(data_t);
int samps_per_word = CHDR_W / ITEM_W;
int num_chdr_lines = ((buff.size() + samps_per_word - 1) / samps_per_word);
chdr_word_t chdr_w_vtr[$];
for (int i = 0; i < num_chdr_lines; i++) begin
chdr_word_t tmp = 'x;
for (int j = 0; j < samps_per_word; j++) begin
tmp[j*$size(data_t) +: $size(data_t)] = buff[i*samps_per_word + j];
tmp[j*ITEM_W +: ITEM_W] = buff[i*samps_per_word + j];
end
chdr_w_vtr.push_back(tmp);
end
return chdr_w_vtr;
endfunction : to_chdr_payload
// Populate this buffer using a CHDR payload
// A CHDR payload can be received using the block controller
// BFM.
// Populate this buffer using a CHDR payload A CHDR payload can be received
// using the block controller BFM.
function void from_chdr_payload(chdr_word_queue_t chdr_w_vtr, int bytes);
int samps_per_word = $size(chdr_word_t) / $size(data_t);
int samps_per_word = CHDR_W / ITEM_W;
int bytes_left = bytes;
buff.delete();
foreach (chdr_w_vtr[i]) begin
for (int j = 0; j < samps_per_word; j++) begin
if (bytes_left > 0) begin
buff.push_back(chdr_w_vtr[i][j*$size(data_t) +: $size(data_t)]);
bytes_left -= ($size(data_t)/8);
buff.push_back(chdr_w_vtr[i][j*ITEM_W +: ITEM_W]);
bytes_left -= (ITEM_W/8);
end
end
end
@@ -112,7 +119,7 @@ package PkgRfnocItemUtils;
end
return str;
end else begin
string str = $sformatf("ItemDataBuff (%0d-bit)\n", $size(data_t));
string str = $sformatf("ItemDataBuff (%0d-bit)\n", ITEM_W);
foreach (buff[i]) begin
str = { str, $sformatf({"%5d> ", format, "\n"}, i, buff[i]) };
end
@@ -127,7 +134,7 @@ package PkgRfnocItemUtils;
// Check if the contents of two buffers is equal
function bit equal(
ItemDataBuff #(data_t) rhs
ItemDataBuff #(item_t) rhs
);
if (this.size() != rhs.size()) return 0;
for (int i = 0; i < this.size(); i++) begin
@@ -139,8 +146,16 @@ package PkgRfnocItemUtils;
endclass
class ItemDataBuffQueue #(type data_t);
local ItemDataBuff #(data_t) queue[$];
//---------------------------------------------------------------------------
// Item Data Buffer Queue
//---------------------------------------------------------------------------
//
// This is a queue of item buffers
//
//---------------------------------------------------------------------------
class ItemDataBuffQueue #(type item_t = logic [31:0], int CHDR_W = 64);
local ItemDataBuff #(item_t, CHDR_W) queue[$];
// Create a new empty queue
function new();
@@ -158,13 +173,13 @@ package PkgRfnocItemUtils;
endfunction : size
// Get the i'th element in this buffer
function ItemDataBuff #(data_t) get(int i);
function ItemDataBuff #(item_t) get(int i);
return queue[i];
endfunction : get
// Put an element in this buffer. If i is negative
// then put it at the end
function void put(ItemDataBuff #(data_t) buff, int i = -1);
function void put(ItemDataBuff #(item_t) buff, int i = -1);
if (i < 0)
queue.push_back(buff);
else
@@ -181,10 +196,10 @@ package PkgRfnocItemUtils;
int handle = $fopen(filename, "r");
queue.delete();
while ($fgets(line, handle) > 0) begin
data_t word = 'x;
item_t word = 'x;
int buff_i = word_i++ / max_buff_size;
if (queue.size() < buff_i + 1) begin
ItemDataBuff #(data_t) buff = new;
ItemDataBuff #(item_t) buff = new;
queue.push_back(buff);
end
if ($sscanf(line, "%x", word) > 0) begin