231 lines
7.0 KiB
Systemverilog
231 lines
7.0 KiB
Systemverilog
//
|
|
// Copyright 2019 Ettus Research, A National Instruments Company
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
//
|
|
// Module: PkgRfnocItemUtils
|
|
//
|
|
// 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 and functions to convert to and from a CHDR vector.
|
|
//
|
|
// - ItemDataBuffQueue: A queue of ItemDataBuff buffers
|
|
//
|
|
|
|
package PkgRfnocItemUtils;
|
|
|
|
import rfnoc_chdr_utils_pkg::*;
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Item Data Buffer
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// This is a class of "items" of an arbitrary type
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
class ItemDataBuff #(type item_t = logic [31:0], int CHDR_W = 64);
|
|
|
|
localparam ITEM_W = $bits(item_t);
|
|
|
|
// Redefine these types from rfnoc_chdr_utils_pkg 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 item_t buff[$];
|
|
|
|
// Create a new empty buffer
|
|
function new();
|
|
buff.delete();
|
|
endfunction : new
|
|
|
|
// Get the bitwidth of a item in this buffer
|
|
function int item_w();
|
|
return ITEM_W;
|
|
endfunction : item_w
|
|
|
|
// Delete the contents of this buffer
|
|
function void delete();
|
|
buff.delete();
|
|
endfunction : delete
|
|
|
|
// Get the size (in number of words) of this buffer
|
|
function int size();
|
|
return buff.size();
|
|
endfunction : size
|
|
|
|
// Get the size (in number of bytes) of this buffer
|
|
function int get_bytes();
|
|
return size() * (item_w() / 8);
|
|
endfunction : get_bytes
|
|
|
|
// Get the i'th element in this buffer
|
|
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(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.
|
|
function chdr_word_queue_t to_chdr_payload();
|
|
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*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.
|
|
function void from_chdr_payload(chdr_word_queue_t chdr_w_vtr, int bytes);
|
|
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*ITEM_W +: ITEM_W]);
|
|
bytes_left -= (ITEM_W/8);
|
|
end
|
|
end
|
|
end
|
|
endfunction : from_chdr_payload
|
|
|
|
// Output a string representation of the contents of the buffer
|
|
function string sprint(string format = "%X", bit as_chdr = 0);
|
|
if (as_chdr) begin
|
|
string str = $sformatf("ItemDataBuff (64-bit CHDR, %0d bytes)\n", get_bytes());
|
|
chdr_word_queue_t chdr_q = this.to_chdr_payload();
|
|
foreach (chdr_q[i]) begin
|
|
str = { str, $sformatf({"%5d> ", format, "\n"}, i, chdr_q[i]) };
|
|
end
|
|
return str;
|
|
end else begin
|
|
string str = $sformatf("ItemDataBuff (%0d-bit)\n", ITEM_W);
|
|
foreach (buff[i]) begin
|
|
str = { str, $sformatf({"%5d> ", format, "\n"}, i, buff[i]) };
|
|
end
|
|
return str;
|
|
end
|
|
endfunction : sprint
|
|
|
|
// Print a string representation of the contents of the buffer
|
|
function void print(string format = "%X", bit as_chdr = 0);
|
|
$display(sprint(format, as_chdr));
|
|
endfunction : print
|
|
|
|
// Check if the contents of two buffers is equal
|
|
function bit equal(
|
|
ItemDataBuff #(item_t,CHDR_W) rhs
|
|
);
|
|
if (this.size() != rhs.size()) return 0;
|
|
for (int i = 0; i < this.size(); i++) begin
|
|
if (this.get(i) != rhs.get(i)) return 0;
|
|
end
|
|
return 1;
|
|
endfunction : equal
|
|
|
|
endclass
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// 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();
|
|
queue.delete();
|
|
endfunction : new
|
|
|
|
// Delete the contents of this queue
|
|
function void delete();
|
|
queue.delete();
|
|
endfunction : delete
|
|
|
|
// Get the size (in number of buffers) of this queue
|
|
function int size();
|
|
return queue.size();
|
|
endfunction : size
|
|
|
|
// Get the i'th element in this buffer
|
|
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 #(item_t) buff, int i = -1);
|
|
if (i < 0)
|
|
queue.push_back(buff);
|
|
else
|
|
queue.insert(i, buff);
|
|
endfunction : put
|
|
|
|
// Create a queue of buffers and fill them using the contents of the specified file.
|
|
function void from_hex_file(
|
|
int max_buff_size,
|
|
string filename
|
|
);
|
|
string line;
|
|
int word_i = 0;
|
|
int handle = $fopen(filename, "r");
|
|
queue.delete();
|
|
while ($fgets(line, handle) > 0) begin
|
|
item_t word = 'x;
|
|
int buff_i = word_i++ / max_buff_size;
|
|
if (queue.size() < buff_i + 1) begin
|
|
ItemDataBuff #(item_t) buff = new;
|
|
queue.push_back(buff);
|
|
end
|
|
if ($sscanf(line, "%x", word) > 0) begin
|
|
queue[buff_i].put(word);
|
|
end else begin
|
|
$error("File parse error");
|
|
end
|
|
end
|
|
$fclose(handle);
|
|
handle = 0;
|
|
endfunction : from_hex_file
|
|
|
|
// Write the contents of the queue of buffers to the specified file.
|
|
function void to_hex_file(
|
|
string filename
|
|
);
|
|
int handle = $fopen(filename, "w");
|
|
foreach (queue[i]) begin
|
|
for (int j = 0; j < queue[i].size(); j++) begin
|
|
$fdisplay(handle, $sformatf("%x", queue[i].get(j)));
|
|
end
|
|
end
|
|
$fclose(handle);
|
|
handle = 0;
|
|
endfunction : to_hex_file
|
|
|
|
endclass
|
|
endpackage : PkgRfnocItemUtils
|