-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'marushchenko_feature_uvm-crdt_agent' into 'main'
UVM AVST_CRDT AGENT [FEATURE]: add agent See merge request ndk/ofm!389
- Loading branch information
Showing
12 changed files
with
836 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Modules.tcl: Local include script | ||
# Copyright (C) 2024 CESNET z. s. p. o. | ||
# Author(s): Yaroslav Marushchenko <[email protected]> | ||
|
||
# SPDX-License-Identifier: BSD-3-Clause | ||
|
||
lappend MOD "$ENTITY_BASE/interface.sv" | ||
lappend MOD "$ENTITY_BASE/pkg.sv" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
// agent.sv: AVST credit control agent | ||
// Copyright (C) 2024 CESNET z. s. p. o. | ||
// Author(s): Yaroslav Marushchenko <[email protected]> | ||
|
||
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <[email protected]> | ||
|
||
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// driver.sv: AVST credit control driver | ||
// Copyright (C) 2024 CESNET z. s. p. o. | ||
// Author(s): Yaroslav Marushchenko <[email protected]> | ||
|
||
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// interface.sv: AVST credit control interface | ||
// Copyright (C) 2024 CESNET z. s. p. o. | ||
// Author(s): Yaroslav Marushchenko <[email protected]> | ||
|
||
// 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 |
Oops, something went wrong.