diff --git a/comp/uvm/avst_crdt/Modules.tcl b/comp/uvm/avst_crdt/Modules.tcl new file mode 100644 index 000000000..d8dbd6d53 --- /dev/null +++ b/comp/uvm/avst_crdt/Modules.tcl @@ -0,0 +1,8 @@ +# Modules.tcl: Local include script +# Copyright (C) 2024 CESNET z. s. p. o. +# Author(s): Yaroslav Marushchenko + +# SPDX-License-Identifier: BSD-3-Clause + +lappend MOD "$ENTITY_BASE/interface.sv" +lappend MOD "$ENTITY_BASE/pkg.sv" diff --git a/comp/uvm/avst_crdt/agent.sv b/comp/uvm/avst_crdt/agent.sv new file mode 100644 index 000000000..c92be9c92 --- /dev/null +++ b/comp/uvm/avst_crdt/agent.sv @@ -0,0 +1,189 @@ +// agent.sv: AVST credit control agent +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +// ======= // +// RX side // +// ======= // + +class agent_rx #(int unsigned UPDATE_CNT_WIDTH) extends uvm_agent; + `uvm_component_param_utils(uvm_avst_crdt::agent_rx #(UPDATE_CNT_WIDTH)) + + // Analysis port + uvm_analysis_port #(sequence_item #(UPDATE_CNT_WIDTH)) analysis_port; + + // ------------------ // + // Agent's components // + // ------------------ // + + sequencer #(UPDATE_CNT_WIDTH) m_sequencer; + driver_rx #(UPDATE_CNT_WIDTH) m_driver; + monitor #(UPDATE_CNT_WIDTH) m_monitor; + config_item m_config; + + // Constructor + function new(string name = "agent_rx", uvm_component parent = null); + super.new(name, parent); + endfunction + + virtual function uvm_active_passive_enum get_is_active(); + return uvm_active_passive_enum'(m_config.active); + endfunction + + function void build_phase(uvm_phase phase); + super.build_phase(phase); + + // Get a configuration from the database + assert(uvm_config_db #(config_item)::get(this, "", "m_config", m_config)) + else begin + `uvm_fatal(this.get_full_name(), "Unable to get configuration object") + end + + // Create a sequencer and a driver if the agent is active + if(get_is_active() == UVM_ACTIVE) begin + m_sequencer = sequencer #(UPDATE_CNT_WIDTH)::type_id::create("m_sequencer", this); + m_driver = driver_rx #(UPDATE_CNT_WIDTH)::type_id::create("m_driver", this); + end + + // Create a monitor + m_monitor = monitor #(UPDATE_CNT_WIDTH)::type_id::create("m_monitor", this); + endfunction + + function void connect_phase(uvm_phase phase); + // Virtual interface + virtual avst_crdt_if #(UPDATE_CNT_WIDTH) vif; + + super.connect_phase(phase); + + // Get a virtual interface instance from the database + assert(uvm_config_db #(virtual avst_crdt_if #(UPDATE_CNT_WIDTH))::get(null, "", m_config.interface_name, vif)) + else begin + `uvm_fatal(this.get_full_name(), $sformatf("Cannot find an interface with name %s, probably not set!", m_config.interface_name)); + end + + // Connect the driver if the agent is active + if(get_is_active() == UVM_ACTIVE) begin + m_driver.vif = vif; + m_driver.seq_item_port.connect(m_sequencer.seq_item_export); + end + + // Connect the monitor + m_monitor.vif = vif; + analysis_port = m_monitor.analysis_port; + endfunction + +endclass + +class agent_rx_hdr extends agent_rx #(2); + `uvm_component_utils(uvm_avst_crdt::agent_rx_hdr) + + // Constructor + function new(string name = "agent_rx_hdr", uvm_component parent = null); + super.new(name, parent); + endfunction + +endclass + +class agent_rx_data extends agent_rx #(4); + `uvm_component_utils(uvm_avst_crdt::agent_rx_data) + + // Constructor + function new(string name = "agent_rx_data", uvm_component parent = null); + super.new(name, parent); + endfunction + +endclass + +// ======= // +// TX side // +// ======= // + +class agent_tx #(int unsigned UPDATE_CNT_WIDTH) extends uvm_agent; + `uvm_component_param_utils(uvm_avst_crdt::agent_tx #(UPDATE_CNT_WIDTH)) + + // Analysis port + uvm_analysis_port #(sequence_item #(UPDATE_CNT_WIDTH)) analysis_port; + + // ------------------ // + // Agent's components // + // ------------------ // + + sequencer #(UPDATE_CNT_WIDTH) m_sequencer; + driver_tx #(UPDATE_CNT_WIDTH) m_driver; + monitor #(UPDATE_CNT_WIDTH) m_monitor; + config_item m_config; + + // Constructor + function new(string name = "agent_tx", uvm_component parent = null); + super.new(name, parent); + endfunction + + virtual function uvm_active_passive_enum get_is_active(); + return uvm_active_passive_enum'(m_config.active); + endfunction + + function void build_phase(uvm_phase phase); + super.build_phase(phase); + + // Get a configuration from the database + assert(uvm_config_db #(config_item)::get(this, "", "m_config", m_config)) + else begin + `uvm_fatal(this.get_full_name(), "Unable to get configuration object") + end + + // Create a sequencer and a driver if the agent is active + if(get_is_active() == UVM_ACTIVE) begin + m_sequencer = sequencer #(UPDATE_CNT_WIDTH)::type_id::create("m_sequencer", this); + m_driver = driver_tx #(UPDATE_CNT_WIDTH)::type_id::create("m_driver", this); + end + + // Create a monitor + m_monitor = monitor #(UPDATE_CNT_WIDTH)::type_id::create("m_monitor", this); + endfunction + + function void connect_phase(uvm_phase phase); + // Virtual interface + virtual avst_crdt_if #(UPDATE_CNT_WIDTH) vif; + + super.connect_phase(phase); + + // Get a virtual interface instance from the database + assert(uvm_config_db #(virtual avst_crdt_if #(UPDATE_CNT_WIDTH))::get(null, "", m_config.interface_name, vif)) + else begin + `uvm_fatal(this.get_full_name(), $sformatf("Cannot find an interface with name %s, probably not set!", m_config.interface_name)); + end + + // Connect the driver if the agent is active + if(get_is_active() == UVM_ACTIVE) begin + m_driver.vif = vif; + m_driver.seq_item_port.connect(m_sequencer.seq_item_export); + end + + // Connect the monitor + m_monitor.vif = vif; + analysis_port = m_monitor.analysis_port; + endfunction + +endclass + +class agent_tx_hdr extends agent_tx #(2); + `uvm_component_utils(uvm_avst_crdt::agent_tx_hdr) + + // Constructor + function new(string name = "agent_tx_hdr", uvm_component parent = null); + super.new(name, parent); + endfunction + +endclass + +class agent_tx_data extends agent_tx #(4); + `uvm_component_utils(uvm_avst_crdt::agent_tx_data) + + // Constructor + function new(string name = "agent_tx_data", uvm_component parent = null); + super.new(name, parent); + endfunction + +endclass diff --git a/comp/uvm/avst_crdt/config.sv b/comp/uvm/avst_crdt/config.sv new file mode 100644 index 000000000..72372298a --- /dev/null +++ b/comp/uvm/avst_crdt/config.sv @@ -0,0 +1,27 @@ +// config.sv: Configuration object for AVST credit control agent +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +`ifndef AVST_CRDT_CONFIG_SV +`define AVST_CRDT_CONFIG_SV + +class config_item extends uvm_object; + `uvm_object_utils(uvm_avst_crdt::config_item) + + // ----------------------- // + // Configuration variables // + // ----------------------- // + + uvm_active_passive_enum active; + string interface_name; + + // Constructor + function new(string name = "config_item"); + super.new(name); + endfunction + +endclass + +`endif diff --git a/comp/uvm/avst_crdt/driver.sv b/comp/uvm/avst_crdt/driver.sv new file mode 100644 index 000000000..1850d1f4c --- /dev/null +++ b/comp/uvm/avst_crdt/driver.sv @@ -0,0 +1,103 @@ +// driver.sv: AVST credit control driver +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +// ======= // +// RX side // +// ======= // + +class driver_rx #(int unsigned UPDATE_CNT_WIDTH) extends uvm_driver #(sequence_item #(UPDATE_CNT_WIDTH)); + `uvm_component_param_utils(uvm_avst_crdt::driver_rx #(UPDATE_CNT_WIDTH)) + + // Virtual interface + virtual avst_crdt_if #(UPDATE_CNT_WIDTH).driver_rx vif; + + // Constructor + function new(string name = "driver_rx", uvm_component parent = null); + super.new(name, parent); + endfunction + + // Driving signals to interface + task run_phase(uvm_phase phase); + rsp = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("rsp"); + + forever begin + // Get new sequence item to drive to interface + seq_item_port.try_next_item(req); + + if (req != null) begin + vif.driver_rx_cb.INIT <= req.init; + vif.driver_rx_cb.UPDATE <= req.update; + vif.driver_rx_cb.UPDATE_CNT <= req.update_cnt; + seq_item_port.item_done(); + end else begin + vif.driver_rx_cb.INIT <= 1'b0; + vif.driver_rx_cb.UPDATE <= 1'b0; + vif.driver_rx_cb.UPDATE_CNT <= 1'bX; + end + + // Wait for the clocking block to write values + @(vif.driver_rx_cb); + + if (req != null) begin + // Set response data + rsp.copy(req); + rsp.init_ack = vif.driver_rx_cb.INIT_ACK; + + rsp.set_id_info(req); + seq_item_port.put_response(rsp); + end + end + endtask + +endclass + +// ======= // +// TX side // +// ======= // + +class driver_tx #(int unsigned UPDATE_CNT_WIDTH) extends uvm_driver #(sequence_item #(UPDATE_CNT_WIDTH)); + `uvm_component_param_utils(uvm_avst_crdt::driver_tx #(UPDATE_CNT_WIDTH)) + + // Virtual interface + virtual avst_crdt_if #(UPDATE_CNT_WIDTH).driver_tx vif; + + // Constructor + function new(string name = "driver_tx", uvm_component parent = null); + super.new(name, parent); + endfunction + + // Start driving signals to interface + task run_phase(uvm_phase phase); + rsp = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("rsp"); + + forever begin + // Get new sequence item to drive to interface + seq_item_port.try_next_item(req); + + if (req != null) begin + vif.driver_tx_cb.INIT_ACK <= req.init_ack; + seq_item_port.item_done(); + end else begin + vif.driver_tx_cb.INIT_ACK <= 1'b0; + end + + // Wait for the clocking block to write values + @(vif.driver_tx_cb); + + if (req != null) begin + // Set response data + rsp.copy(req); + rsp.init = vif.driver_tx_cb.INIT; + rsp.update = vif.driver_tx_cb.UPDATE; + rsp.update_cnt = vif.driver_tx_cb.UPDATE_CNT; + + rsp.set_id_info(req); + seq_item_port.put_response(rsp); + end + end + endtask + +endclass diff --git a/comp/uvm/avst_crdt/interface.sv b/comp/uvm/avst_crdt/interface.sv new file mode 100644 index 000000000..bdaf3e2cf --- /dev/null +++ b/comp/uvm/avst_crdt/interface.sv @@ -0,0 +1,54 @@ +// interface.sv: AVST credit control interface +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +interface avst_crdt_if #(int unsigned UPDATE_CNT_WIDTH) (input logic CLK); + // ------------------------------- // + // Bus structure of credit control // + // ------------------------------- // + + wire logic INIT; + wire logic INIT_ACK; + wire logic UPDATE; + wire logic [UPDATE_CNT_WIDTH-1 : 0] UPDATE_CNT; + + // RX driver clocking block + clocking driver_rx_cb @(posedge CLK); + input INIT_ACK; + output INIT, UPDATE, UPDATE_CNT; + endclocking + + // TX driver clocking block + clocking driver_tx_cb @(posedge CLK); + output INIT_ACK; + input INIT, UPDATE, UPDATE_CNT; + endclocking + + // Monitor clocking block + clocking monitor_cb @(posedge CLK); + input INIT, INIT_ACK, UPDATE, UPDATE_CNT; + endclocking + + // RX connection to DUT + modport dut_rx( + input INIT, UPDATE, UPDATE_CNT, + output INIT_ACK + ); + + // TX connection to DUT + modport dut_tx( + input INIT_ACK, + output INIT, UPDATE, UPDATE_CNT + ); + + // RX driver module port + modport driver_rx(clocking driver_rx_cb); + // TX driver module port + modport driver_tx(clocking driver_tx_cb); + + // Monitor module port + modport monitor(clocking monitor_cb); + +endinterface diff --git a/comp/uvm/avst_crdt/monitor.sv b/comp/uvm/avst_crdt/monitor.sv new file mode 100644 index 000000000..943271da0 --- /dev/null +++ b/comp/uvm/avst_crdt/monitor.sv @@ -0,0 +1,40 @@ +// monitor.sv: AVST credit control monitor +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +class monitor #(int unsigned UPDATE_CNT_WIDTH) extends uvm_monitor; + `uvm_component_param_utils(uvm_avst_crdt::monitor #(UPDATE_CNT_WIDTH)) + + // Virtual interface + virtual avst_crdt_if #(UPDATE_CNT_WIDTH).monitor vif; + + // Analysis port + uvm_analysis_port #(sequence_item #(UPDATE_CNT_WIDTH)) analysis_port; + + // Constructor + function new(string name = "monitor", uvm_component parent = null); + super.new(name, parent); + + analysis_port = new("analysis_port", this); + endfunction + + task run_phase(uvm_phase phase); + sequence_item #(UPDATE_CNT_WIDTH) item; + + forever begin + @(vif.monitor_cb); + + item = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("item"); + // Sampling + item.init = vif.monitor_cb.INIT; + item.init_ack = vif.monitor_cb.INIT_ACK; + item.update = vif.monitor_cb.UPDATE; + item.update_cnt = vif.monitor_cb.UPDATE_CNT; + // Write sequence item to analysis port + analysis_port.write(item); + end + endtask + +endclass diff --git a/comp/uvm/avst_crdt/pkg.sv b/comp/uvm/avst_crdt/pkg.sv new file mode 100644 index 000000000..6bed5a647 --- /dev/null +++ b/comp/uvm/avst_crdt/pkg.sv @@ -0,0 +1,25 @@ +// pkg.sv: Package for AVST credit control interface +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +`ifndef AVST_CRDT_PKG +`define AVST_CRDT_PKG + +package uvm_avst_crdt; + + `include "uvm_macros.svh" + import uvm_pkg::*; + + `include "config.sv" + `include "sequence_item.sv" + `include "sequencer.sv" + `include "sequence.sv" + `include "driver.sv" + `include "monitor.sv" + `include "agent.sv" + +endpackage + +`endif diff --git a/comp/uvm/avst_crdt/readme.rst b/comp/uvm/avst_crdt/readme.rst new file mode 100644 index 000000000..b7e7ecf98 --- /dev/null +++ b/comp/uvm/avst_crdt/readme.rst @@ -0,0 +1,48 @@ +.. readme.rst: Documentation of AVST CRDT agent +.. Copyright (C) 2024 CESNET z. s. p. o. +.. Author(s): Yaroslav Marushchenko + +.. SPDX-License-Identifier: BSD-3-Clause + +*************** +AVST CRDT Agent +*************** + +This agent is a low-level agent that is responsible for communication through the `Intel Credit Control interface `_. +This package, **uvm_avst_crdt**, contains 2 generic and 4 predefined agents. The RX agent sends credits to the DUT. The TX agent is responsible for the correct initialization. + +Agents +====== + +The package contains RX and TX agents that can be parameterized with the **UPDATE_CNT_WIDTH** parameter. +The generic agents are configured with one parameter: + +- UPDATE_CNT_WIDTH + +Moreover, the package contains 4 agents with predefined parameter values: + +- *agent_rx_hdr* with **UPDATE_CNT_WIDTH = 2**. +- *agent_rx_data* with **UPDATE_CNT_WIDTH = 4**. +- *agent_tx_hdr* with **UPDATE_CNT_WIDTH = 2**. +- *agent_tx_data* with **UPDATE_CNT_WIDTH = 4**. + +Sequence Item +============== + +The following table shows properties in the *sequence_item* class. + +.. code-block:: systemverilog + + rand logic init; + rand logic init_ack; + rand logic update; + rand logic [UPDATE_CNT_WIDTH-1 : 0] update_cnt; + +Sequences +========= + +- *sequence_rx* is a common credit-generating sequence. +- *sequence_rx_initializing* is responsible for correct initialization on the RX side. +- *sequence_tx_ack* is responsible for correct initialization on the TX side. + +All these sequences have predefined *_hdr* and *_data* variants, just like agents do. diff --git a/comp/uvm/avst_crdt/sequence.sv b/comp/uvm/avst_crdt/sequence.sv new file mode 100644 index 000000000..6d52d2819 --- /dev/null +++ b/comp/uvm/avst_crdt/sequence.sv @@ -0,0 +1,249 @@ +// sequence.sv: AVST credit control sequence +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +// ======= // +// RX side // +// ======= // + +virtual class sequence_rx_base #(int unsigned UPDATE_CNT_WIDTH) extends uvm_sequence #(sequence_item #(UPDATE_CNT_WIDTH)); + `uvm_object_param_utils(uvm_avst_crdt::sequence_rx_base #(UPDATE_CNT_WIDTH)) + + // --------- // + // Variables // + // --------- // + + sequence_item #(UPDATE_CNT_WIDTH) req; + + // Transaction count + int unsigned max_transaction_count = 100; + int unsigned min_transaction_count = 10; + rand int unsigned transaction_count; + constraint c_transaction_count {transaction_count inside {[min_transaction_count : max_transaction_count]};} + + // Constructor + function new(string name = "sequence_rx_base"); + super.new(name); + endfunction + + pure virtual task send_transaction(); + + // Generate transactions + virtual task body; + repeat (transaction_count) begin + req = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("req"); + send_transaction(); + end + endtask + +endclass + +class sequence_rx #(int unsigned UPDATE_CNT_WIDTH) extends sequence_rx_base #(UPDATE_CNT_WIDTH); + `uvm_object_param_utils(uvm_avst_crdt::sequence_rx #(UPDATE_CNT_WIDTH)) + + // Constructor + function new(string name = "sequence_rx"); + super.new(name); + endfunction + + virtual task send_transaction(); + int unsigned randomize_result; + + start_item(req); + + randomize_result = req.randomize() with { + init == 1'b0; + }; + assert(randomize_result) + else begin + `uvm_fatal(this.get_full_name(), "\n\tCannot randomize") + end + + finish_item(req); + get_response(rsp); + endtask + +endclass + +class sequence_rx_hdr extends sequence_rx #(2); + `uvm_object_utils(uvm_avst_crdt::sequence_rx_hdr) + + // Constructor + function new(string name = "sequence_rx_hdr"); + super.new(name); + endfunction + +endclass + +class sequence_rx_data extends sequence_rx #(4); + `uvm_object_utils(uvm_avst_crdt::sequence_rx_data) + + // Constructor + function new(string name = "sequence_rx_data"); + super.new(name); + endfunction + +endclass + +class sequence_rx_initializing #(int unsigned UPDATE_CNT_WIDTH) extends sequence_rx_base #(UPDATE_CNT_WIDTH); + `uvm_object_param_utils(uvm_avst_crdt::sequence_rx_initializing #(UPDATE_CNT_WIDTH)) + + // SEPARATION_LENGTH means length of clock cycle separation between the deassertion of the *update and *init signals. + // https://www.intel.com/content/www/us/en/docs/programmable/683501/24-2-11-3-0/credit-initialization.html + localparam int unsigned SEPARATION_LENGTH = 2; + + // Constructor + function new(string name = "sequence_rx_initializing"); + super.new(name); + endfunction + + virtual task send_transaction(); + int unsigned randomize_result; + + start_item(req); + + randomize_result = req.randomize() with { + init == 1'b1; + }; + assert(randomize_result) + else begin + `uvm_fatal(this.get_full_name(), "\n\tCannot randomize") + end + + finish_item(req); + get_response(rsp); + endtask + + virtual task send_separation_transaction(); + int unsigned randomize_result; + + start_item(req); + + randomize_result = req.randomize() with { + init == 1'b1; + update == 1'b0; + }; + assert(randomize_result) + else begin + `uvm_fatal(this.get_full_name(), "\n\tCannot randomize") + end + + finish_item(req); + get_response(rsp); + endtask + + // Generate transactions + virtual task body; + repeat (transaction_count-SEPARATION_LENGTH) begin + req = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("req"); + send_transaction(); + end + + repeat (SEPARATION_LENGTH) begin + req = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("req"); + send_separation_transaction(); + end + endtask + +endclass + +class sequence_rx_initializing_hdr extends sequence_rx_initializing #(2); + `uvm_object_utils(uvm_avst_crdt::sequence_rx_initializing_hdr) + + // Constructor + function new(string name = "sequence_rx_initializing_hdr"); + super.new(name); + endfunction + +endclass + +class sequence_rx_initializing_data extends sequence_rx_initializing #(4); + `uvm_object_utils(uvm_avst_crdt::sequence_rx_initializing_data) + + // Constructor + function new(string name = "sequence_rx_initializing_data"); + super.new(name); + endfunction + +endclass + +// ======= // +// TX side // +// ======= // + +class sequence_tx_ack #(int unsigned UPDATE_CNT_WIDTH) extends uvm_sequence #(sequence_item #(UPDATE_CNT_WIDTH)); + `uvm_object_param_utils(uvm_avst_crdt::sequence_tx_ack #(UPDATE_CNT_WIDTH)) + + // Constructor + function new(string name = "sequence_tx_ack"); + super.new(name); + endfunction + + virtual task send_empty_transaction(); + int unsigned randomize_result; + + start_item(req); + + randomize_result = req.randomize() with { + init_ack == 1'b0; + }; + assert(randomize_result) + else begin + `uvm_fatal(this.get_full_name(), "\n\tCannot randomize") + end + + finish_item(req); + get_response(rsp); + endtask + + virtual task send_transaction(); + int unsigned randomize_result; + + start_item(req); + + randomize_result = req.randomize() with { + init_ack == 1'b1; + }; + assert(randomize_result) + else begin + `uvm_fatal(this.get_full_name(), "\n\tCannot randomize") + end + + finish_item(req); + get_response(rsp); + endtask + + // Generate transactions + virtual task body; + do begin + req = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("req"); + send_empty_transaction(); + end while(rsp.init !== 1'b1); + + req = sequence_item #(UPDATE_CNT_WIDTH)::type_id::create("req"); + send_transaction(); + endtask + +endclass + +class sequence_tx_ack_hdr extends sequence_tx_ack #(2); + `uvm_object_utils(uvm_avst_crdt::sequence_tx_ack_hdr) + + // Constructor + function new(string name = "sequence_tx_ack_hdr"); + super.new(name); + endfunction + +endclass + +class sequence_tx_ack_data extends sequence_tx_ack #(4); + `uvm_object_utils(uvm_avst_crdt::sequence_tx_ack_data) + + // Constructor + function new(string name = "sequence_tx_ack_data"); + super.new(name); + endfunction + +endclass diff --git a/comp/uvm/avst_crdt/sequence_item.sv b/comp/uvm/avst_crdt/sequence_item.sv new file mode 100644 index 000000000..7076fe7f2 --- /dev/null +++ b/comp/uvm/avst_crdt/sequence_item.sv @@ -0,0 +1,77 @@ +// sequence_item.sv: Item for AVST credit control sequencer +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +class sequence_item #(int unsigned UPDATE_CNT_WIDTH) extends uvm_sequence_item; + `uvm_object_param_utils(uvm_avst_crdt::sequence_item #(UPDATE_CNT_WIDTH)) + + // ------------------------------- // + // Bus structure of credit control // + // ------------------------------- // + + rand logic init; + rand logic init_ack; + rand logic update; + rand logic [UPDATE_CNT_WIDTH-1 : 0] update_cnt; + + // Constructor + function new(string name = "sequence_item"); + super.new(name); + endfunction + + // -------------------- // + // Common UVM functions // + // -------------------- // + + function void do_copy(uvm_object rhs); + sequence_item #(UPDATE_CNT_WIDTH) rhs_; + + if(!$cast(rhs_, rhs)) begin + `uvm_fatal(this.get_full_name(), "Failed to cast transaction object.") + return; + end + + // Item copying + super.do_copy(rhs); + init = rhs_.init; + init_ack = rhs_.init_ack; + update = rhs_.update; + update_cnt = rhs_.update_cnt; + endfunction + + function bit do_compare(uvm_object rhs, uvm_comparer comparer); + sequence_item #(UPDATE_CNT_WIDTH) rhs_; + + if(!$cast(rhs_, rhs)) begin + `uvm_fatal("do_compare:", "Failed to cast transaction object.") + return 0; + end + + // Item comparison + return ( + super.do_compare(rhs, comparer ) && + (init === rhs_.init ) && + (init_ack === rhs_.init_ack ) && + (update === rhs_.update ) && + (update_cnt === rhs_.update_cnt) + ); + + endfunction + + function string convert2string(); + string output_string = ""; + + // Item stringifying + $sformat(output_string, {"\n\tINIT %0b\n\tINIT_ACK %0b\n\tUPDATE %0b\n\tUPDATE_CNT %0h\n"}, + init, + init_ack, + update, + update_cnt + ); + + return output_string; + endfunction + +endclass diff --git a/comp/uvm/avst_crdt/sequencer.sv b/comp/uvm/avst_crdt/sequencer.sv new file mode 100644 index 000000000..2d368254b --- /dev/null +++ b/comp/uvm/avst_crdt/sequencer.sv @@ -0,0 +1,15 @@ +// sequencer.sv: Sequencer for AVST credit control interface +// Copyright (C) 2024 CESNET z. s. p. o. +// Author(s): Yaroslav Marushchenko + +// SPDX-License-Identifier: BSD-3-Clause + +class sequencer #(int unsigned UPDATE_CNT_WIDTH) extends uvm_sequencer #(uvm_avst_crdt::sequence_item #(UPDATE_CNT_WIDTH)); + `uvm_component_param_utils(uvm_avst_crdt::sequencer #(UPDATE_CNT_WIDTH)) + + // Constructor + function new(string name = "sequencer", uvm_component parent = null); + super.new(name, parent); + endfunction + +endclass diff --git a/comp/uvm/componets.rst b/comp/uvm/componets.rst index 164e42a73..96d70424a 100644 --- a/comp/uvm/componets.rst +++ b/comp/uvm/componets.rst @@ -44,3 +44,4 @@ Library of commonly used agents and enviroments in UVM verification logic_vector_array_axi/readme packet_generators/flowtest/readme avmm/readme + avst_crdt/readme