diff options
Diffstat (limited to 'fpga/usrp3/sim/rfnoc/PkgAxisCtrlBfm.sv')
-rw-r--r-- | fpga/usrp3/sim/rfnoc/PkgAxisCtrlBfm.sv | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/fpga/usrp3/sim/rfnoc/PkgAxisCtrlBfm.sv b/fpga/usrp3/sim/rfnoc/PkgAxisCtrlBfm.sv new file mode 100644 index 000000000..8c88792c7 --- /dev/null +++ b/fpga/usrp3/sim/rfnoc/PkgAxisCtrlBfm.sv @@ -0,0 +1,232 @@ +// +// Copyright 2019 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: PkgAxisCtrlBfm +// +// Description: Package for an AXIS-Ctrl bus functional model (BFM), which +// consists primarily of the AxisCtrlPacket and AxisCtrlBfm classes. +// + + + +package PkgAxisCtrlBfm; + + import PkgChdrUtils::*; + import PkgAxiStreamBfm::*; + export PkgAxiStreamBfm::*; + + + //--------------------------------------------------------------------------- + // AXIS-Ctrl Packet Class + //--------------------------------------------------------------------------- + + class AxisCtrlPacket; + + //------------ + // Properties + //------------ + + axis_ctrl_header_t header; + chdr_word_t timestamp; + ctrl_op_word_t op_word; + ctrl_word_t data[$]; + + + //--------- + // Methods + //--------- + + // Return a handle to a copy of this transaction + function AxisCtrlPacket copy(); + AxisCtrlPacket temp; + temp = new(); + temp.header = this.header; + temp.timestamp = this.timestamp; + temp.op_word = this.op_word; + temp.data = this.data; + return temp; + endfunction + + // Return true if this packet equals that of the argument + function bit equal(AxisCtrlPacket packet); + if (header != packet.header) return 0; + if (op_word != packet.op_word) return 0; + if (data.size() != packet.data.size()) return 0; + if (header.has_time && timestamp != packet.timestamp) return 0; + foreach (data[i]) begin + if (data[i] != packet.data[i]) return 0; + end + return 1; + endfunction : equal + + // Format the contents of the packet into a string + function string sprint(); + string str; + str = {str, $sformatf("AxisCtrlPacket:\n")}; + str = {str, $sformatf("- header: %p\n", header) }; + if (header.has_time) + str = {str, $sformatf("- timestamp: %0d\n", timestamp) }; + str = {str, $sformatf("- op_word: '{status:%s,op_code:%s,byte_enable:0b%4b,address:0x%05x}\n", + op_word.status.name, op_word.op_code.name, op_word.byte_enable, op_word.address)}; + str = {str, $sformatf("- data:\n") }; + foreach (data[i]) begin + str = {str, $sformatf("%5d> 0x%08x\n", i, data[i]) }; + end + return str; + endfunction : sprint + + // Print the contents of the packet + function void print(); + $display(sprint()); + endfunction : print + + function void write_ctrl( + ref axis_ctrl_header_t header, + ref ctrl_op_word_t op_word, + ref ctrl_word_t data[$], + input chdr_word_t timestamp = 0 + ); + this.header = header; + this.data = data; + this.timestamp = timestamp; + this.op_word = op_word; + endfunction : write_ctrl + + endclass : AxisCtrlPacket; + + + + //--------------------------------------------------------------------------- + // AXIS-Ctrl Bus Functional Model Class + //--------------------------------------------------------------------------- + + class AxisCtrlBfm extends AxiStreamBfm #(32); + + extern function new ( + virtual AxiStreamIf #(32).master master, + virtual AxiStreamIf #(32).slave slave + ); + + extern task put_ctrl(AxisCtrlPacket ctrl_packet); + + extern task try_put_ctrl(AxisCtrlPacket ctrl_packet); + + extern task get_ctrl(output AxisCtrlPacket ctrl_packet); + + extern function bit try_get_ctrl(output AxisCtrlPacket ctrl_packet); + + extern function AxisPacket axis_ctrl_to_axis(AxisCtrlPacket ctrl_packet); + + extern function AxisCtrlPacket axis_to_axis_ctrl(AxisPacket axis_packet); + + endclass : AxisCtrlBfm + + + + //--------------------------------------------------------------------------- + // AXIS-Ctrl BFM Methods + //--------------------------------------------------------------------------- + + // Class constructor. This must be given an interface for the master + // connection and an interface for the slave connection. + function AxisCtrlBfm::new ( + virtual AxiStreamIf #(32).master master, + virtual AxiStreamIf #(32).slave slave + ); + super.new(master, slave); + endfunction : new + + + // Queue the provided packet for transmission + task AxisCtrlBfm::put_ctrl(AxisCtrlPacket ctrl_packet); + AxisPacket axis_packet; + axis_packet = axis_ctrl_to_axis(ctrl_packet); + super.put(axis_packet); + endtask : put_ctrl + + + // Attempt to queue the provided packet for transmission. Return 1 if + // successful, return 0 if the queue is full. + task AxisCtrlBfm::try_put_ctrl(AxisCtrlPacket ctrl_packet); + AxisPacket axis_packet; + axis_packet = axis_ctrl_to_axis(ctrl_packet); + super.put(axis_packet); + endtask : try_put_ctrl + + // Get the next packet when it becomes available (waits if necessary) + task AxisCtrlBfm::get_ctrl(output AxisCtrlPacket ctrl_packet); + AxisPacket axis_packet; + super.get(axis_packet); + ctrl_packet = axis_to_axis_ctrl(axis_packet); + endtask : get_ctrl + + + // Get the next packet if there's one available and return 1. Return 0 if + // there's no packet available. + function bit AxisCtrlBfm::try_get_ctrl(output AxisCtrlPacket ctrl_packet); + AxisPacket axis_packet; + if(!super.try_get(axis_packet)) return 0; + ctrl_packet = axis_to_axis_ctrl(axis_packet); + return 1; + endfunction : try_get_ctrl + + + // Convert an AXIS-Ctrl packet data structure to an AXI-Stream packet data + // structure. + function AxisCtrlBfm::AxisPacket AxisCtrlBfm::axis_ctrl_to_axis(AxisCtrlPacket ctrl_packet); + AxisPacket axis_packet = new(); + int index; + + // Insert words 0 and 1 (header) + axis_packet.data.push_back(ctrl_packet.header[31: 0]); + axis_packet.data.push_back(ctrl_packet.header[63:32]); + + // Insert timestamp if has_time is set (words 2 and 3) + if (ctrl_packet.header.has_time) begin + axis_packet.data.push_back(ctrl_packet.timestamp[31: 0]); + axis_packet.data.push_back(ctrl_packet.timestamp[63:32]); + end + + // Insert word 4 (operation word) + axis_packet.data.push_back(ctrl_packet.op_word[31: 0]); + + // Insert data + foreach (ctrl_packet.data[i]) begin + axis_packet.data.push_back(ctrl_packet.data[i]); + end + + return axis_packet; + endfunction : axis_ctrl_to_axis + + + // Convert an AXI-Stream packet data structure to an AXIS-Ctrl packet data + // structure. + function AxisCtrlPacket AxisCtrlBfm::axis_to_axis_ctrl(AxisPacket axis_packet); + AxisCtrlPacket ctrl_packet = new(); + int i; // Use an index instead of pop_front() to workaround a ModelSim bug + + // Grab words 0 and 1 (header) + ctrl_packet.header[31: 0] = axis_packet.data[0]; + ctrl_packet.header[63:32] = axis_packet.data[1]; + + // If has_time is set, grab timestamp (words 2 and 3) + i = 2; + if (ctrl_packet.header.has_time) begin + ctrl_packet.timestamp[31: 0] = axis_packet.data[2]; + ctrl_packet.timestamp[63:32] = axis_packet.data[3]; + i += 2; + end + + // Grab word 4 (operation word) + ctrl_packet.op_word[31: 0] = axis_packet.data[i]; + + // Grab data + ctrl_packet.data = axis_packet.data[(i+1):$]; + + return ctrl_packet; + endfunction : axis_to_axis_ctrl + + +endpackage : PkgAxisCtrlBfm |