[pattgen, dv] Parameterize pattgen_agent
Signed-off-by: Tung Hoang <hoang.tung@wdc.com>
diff --git a/hw/dv/sv/pattgen_agent/pattgen_agent.core b/hw/dv/sv/pattgen_agent/pattgen_agent.core
index 5e7edfa..968d806 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_agent.core
+++ b/hw/dv/sv/pattgen_agent/pattgen_agent.core
@@ -13,13 +13,10 @@
- pattgen_agent_pkg.sv
- pattgen_if.sv
- pattgen_item.sv: {is_include_file: true}
- - pattgen_host_driver.sv: {is_include_file: true}
- - pattgen_device_driver.sv: {is_include_file: true}
- pattgen_driver.sv: {is_include_file: true}
- pattgen_agent_cfg.sv: {is_include_file: true}
- pattgen_agent_cov.sv: {is_include_file: true}
- pattgen_monitor.sv: {is_include_file: true}
- - pattgen_sequencer.sv: {is_include_file: true}
- pattgen_agent.sv: {is_include_file: true}
file_type: systemVerilogSource
diff --git a/hw/dv/sv/pattgen_agent/pattgen_agent.sv b/hw/dv/sv/pattgen_agent/pattgen_agent.sv
index b929ee1..2528700 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_agent.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_agent.sv
@@ -5,15 +5,11 @@
class pattgen_agent extends dv_base_agent #(
.CFG_T (pattgen_agent_cfg),
.DRIVER_T (pattgen_driver),
- .HOST_DRIVER_T (pattgen_host_driver),
- .DEVICE_DRIVER_T (pattgen_device_driver),
.SEQUENCER_T (pattgen_sequencer),
.MONITOR_T (pattgen_monitor),
.COV_T (pattgen_agent_cov)
);
-
`uvm_component_utils(pattgen_agent)
-
`uvm_component_new
function void build_phase(uvm_phase phase);
@@ -22,15 +18,8 @@
if (!uvm_config_db#(virtual pattgen_if)::get(this, "", "vif", cfg.vif)) begin
`uvm_fatal(`gfn, "failed to get pattgen_if handle from uvm_config_db")
end
- endfunction
- function void connect_phase(uvm_phase phase);
- super.connect_phase(phase);
- if (cfg.if_mode == dv_utils_pkg::Device) begin
- `uvm_info(`gfn, "device_driver is used", UVM_DEBUG)
- end else begin
- `uvm_fatal(`gfn, "failed to connect driver to sequencer")
- end
- endfunction : connect_phase
+ `DV_CHECK_NE_FATAL(cfg.if_mode, dv_utils_pkg::Host, "Host mode not supported")
+ endfunction
endclass
diff --git a/hw/dv/sv/pattgen_agent/pattgen_agent_cfg.sv b/hw/dv/sv/pattgen_agent/pattgen_agent_cfg.sv
index 2765a7e..bc29421 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_agent_cfg.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_agent_cfg.sv
@@ -3,17 +3,19 @@
// SPDX-License-Identifier: Apache-2.0
class pattgen_agent_cfg extends dv_base_agent_cfg;
- bit en_monitor = 1'b1;
+ bit en_monitor = 1'b1; // enable monitor
// interface handle used by driver, monitor & the sequencer, via cfg handle
virtual pattgen_if vif;
- bit polarity_ch0;
- bit polarity_ch1;
+ bit reset_asserted;
+
+ bit [NUM_PATTGEN_CHANNELS-1:0] polarity;
+ int length[NUM_PATTGEN_CHANNELS-1:0];
`uvm_object_utils_begin(pattgen_agent_cfg)
- `uvm_field_int(polarity_ch0, UVM_DEFAULT)
- `uvm_field_int(polarity_ch1, UVM_DEFAULT)
+ `uvm_field_sarray_int(polarity, UVM_DEFAULT)
+ `uvm_field_sarray_int(length, UVM_DEFAULT)
`uvm_object_utils_end
`uvm_object_new
diff --git a/hw/dv/sv/pattgen_agent/pattgen_agent_cov.sv b/hw/dv/sv/pattgen_agent/pattgen_agent_cov.sv
index f0919a5..dbe366a 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_agent_cov.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_agent_cov.sv
@@ -5,11 +5,13 @@
class pattgen_agent_cov extends dv_base_agent_cov #(pattgen_agent_cfg);
`uvm_component_utils(pattgen_agent_cov)
+ // the base class provides the following handles for use:
+ // pattgen_agent_cfg: cfg
// TODO: covergroups
function new(string name, uvm_component parent);
super.new(name, parent);
- //TODO: instantiate all covergroups here
+ //TODO: instantiate all covergroups here
endfunction : new
-endclass : pattgen_agent_cov
+endclass
diff --git a/hw/dv/sv/pattgen_agent/pattgen_agent_pkg.sv b/hw/dv/sv/pattgen_agent/pattgen_agent_pkg.sv
index 377ca3e..6be7dd4 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_agent_pkg.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_agent_pkg.sv
@@ -12,6 +12,9 @@
`include "uvm_macros.svh"
`include "dv_macros.svh"
+ // TODO: consider to have a parameterized class
+ parameter uint NUM_PATTGEN_CHANNELS = 2;
+
// local types
// forward declare classes to allow typedefs below
typedef class pattgen_item;
@@ -27,8 +30,6 @@
`include "pattgen_agent_cov.sv"
`include "pattgen_monitor.sv"
`include "pattgen_driver.sv"
- `include "pattgen_host_driver.sv"
- `include "pattgen_device_driver.sv"
`include "pattgen_agent.sv"
endpackage: pattgen_agent_pkg
diff --git a/hw/dv/sv/pattgen_agent/pattgen_device_driver.sv b/hw/dv/sv/pattgen_agent/pattgen_device_driver.sv
deleted file mode 100644
index ed5fa99..0000000
--- a/hw/dv/sv/pattgen_agent/pattgen_device_driver.sv
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-class pattgen_device_driver extends pattgen_driver;
- `uvm_component_utils(pattgen_device_driver)
- `uvm_component_new
-
- virtual task get_and_drive();
- @(posedge cfg.vif.rst_ni);
- // keep this as very simple task since pattgen DUT
- // does not require responses from pattgen_agent
- endtask : get_and_drive
-
-endclass : pattgen_device_driver
\ No newline at end of file
diff --git a/hw/dv/sv/pattgen_agent/pattgen_driver.sv b/hw/dv/sv/pattgen_agent/pattgen_driver.sv
index a73e010..a96a0c7 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_driver.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_driver.sv
@@ -9,10 +9,15 @@
virtual task reset_signals();
forever begin
@(negedge cfg.vif.rst_ni);
- `uvm_info(`gfn, "\n driver in reset progress", UVM_DEBUG)
+ `uvm_info(`gfn, "\ndriver in reset progress", UVM_DEBUG)
@(posedge cfg.vif.rst_ni);
- `uvm_info(`gfn, "\n driver out of reset", UVM_DEBUG)
+ `uvm_info(`gfn, "\ndriver out of reset", UVM_DEBUG)
end
endtask : reset_signals
+ virtual task get_and_drive();
+ @(posedge cfg.vif.rst_ni);
+ // pattgen does not require responses from pattgen_agent thus this task is kept to a minimum
+ endtask : get_and_drive
+
endclass : pattgen_driver
diff --git a/hw/dv/sv/pattgen_agent/pattgen_host_driver.sv b/hw/dv/sv/pattgen_agent/pattgen_host_driver.sv
deleted file mode 100644
index 64be592..0000000
--- a/hw/dv/sv/pattgen_agent/pattgen_host_driver.sv
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-class pattgen_host_driver extends pattgen_driver;
- `uvm_component_utils(pattgen_host_driver)
- `uvm_component_new
-
- // pattgen_agent is only operating in device mode
-endclass : pattgen_host_driver
diff --git a/hw/dv/sv/pattgen_agent/pattgen_if.sv b/hw/dv/sv/pattgen_agent/pattgen_if.sv
index c169fc1..eba4971 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_if.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_if.sv
@@ -2,37 +2,14 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-import pattgen_agent_pkg::*;
-
-interface pattgen_if;
+interface pattgen_if #(
+ parameter int unsigned NumChannels = 2
+);
logic clk_i;
logic rst_ni;
// standard pattgen interface pins
- logic pda0_tx;
- logic pcl0_tx;
- logic pda1_tx;
- logic pcl1_tx;
-
- task automatic get_bit(string channel, bit polarity,
- output bit bit_o);
- if (channel == "Channel0") begin
- if (!polarity) begin
- @(posedge pcl0_tx);
- end else begin
- @(negedge pcl0_tx);
- end
- bit_o = pda0_tx;
- end else if (channel == "Channel1") begin
- if (!polarity) begin
- @(posedge pcl1_tx);
- end else begin
- @(negedge pcl1_tx);
- end
- bit_o = pda1_tx;
- end else begin
- bit_o = 1'bx;
- end
- endtask : get_bit
+ logic [NumChannels-1:0] pda_tx;
+ logic [NumChannels-1:0] pcl_tx;
endinterface : pattgen_if
diff --git a/hw/dv/sv/pattgen_agent/pattgen_item.sv b/hw/dv/sv/pattgen_agent/pattgen_item.sv
index 3060a85..75165fe 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_item.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_item.sv
@@ -3,10 +3,12 @@
// SPDX-License-Identifier: Apache-2.0
class pattgen_item extends uvm_sequence_item;
- bit data;
+ bit data_q[$];
+ //uint length;
`uvm_object_utils_begin(pattgen_item);
- `uvm_field_int(data, UVM_DEFAULT)
+ //`uvm_field_int(length, UVM_DEFAULT | UVM_NOCOMPARE)
+ `uvm_field_queue_int(data_q, UVM_DEFAULT)
`uvm_object_utils_end
`uvm_object_new
diff --git a/hw/dv/sv/pattgen_agent/pattgen_monitor.sv b/hw/dv/sv/pattgen_agent/pattgen_monitor.sv
index 9b97da0..9f4eeaa 100644
--- a/hw/dv/sv/pattgen_agent/pattgen_monitor.sv
+++ b/hw/dv/sv/pattgen_agent/pattgen_monitor.sv
@@ -11,68 +11,92 @@
`uvm_component_new
// analysis ports connected to scb
- uvm_analysis_port #(pattgen_item) ch0_item_port; // used to send items on ch0 to scb
- uvm_analysis_port #(pattgen_item) ch1_item_port; // used to send items on ch1 to scb
-
- local pattgen_item ch0_dut_item;
- local pattgen_item ch1_dut_item;
-
- // counters for generated bits on channels
- uint cnt_ch0 = 0;
- uint cnt_ch1 = 0;
+ uvm_analysis_port #(pattgen_item) item_port[NUM_PATTGEN_CHANNELS];
function void build_phase(uvm_phase phase);
super.build_phase(phase);
- ch0_item_port = new("ch0_item_port", this);
- ch1_item_port = new("ch1_item_port", this);
- ch0_dut_item = new("ch0_dut_item");
- ch1_dut_item = new("ch1_dut_item");
+ for (uint i = 0; i < NUM_PATTGEN_CHANNELS; i++) begin
+ item_port[i] = new($sformatf("item_port[%0d]", i), this);
+ end
endfunction : build_phase
virtual task run_phase(uvm_phase phase);
wait(cfg.vif.rst_ni);
collect_trans(phase);
endtask : run_phase
-
- // collect items forever
- virtual protected task collect_trans(uvm_phase phase);
- pattgen_item ch0_item, ch1_item;
- forever begin
- wait(cfg.en_monitor);
+ virtual protected task collect_trans(uvm_phase phase);
+ for (uint i = 0; i < NUM_PATTGEN_CHANNELS; i++) begin
fork
- begin // collect items on the channel 0
- cfg.vif.get_bit(.channel("Channel0"), .polarity(cfg.polarity_ch0),
- .bit_o(ch0_dut_item.data));
- `downcast(ch0_item, ch0_dut_item.clone());
- ch0_item_port.write(ch0_item);
- end
- begin // collect items on the channel 1
- cfg.vif.get_bit(.channel("Channel1"), .polarity(cfg.polarity_ch1),
- .bit_o(ch1_dut_item.data));
- `downcast(ch1_item, ch1_dut_item.clone());
- ch1_item_port.write(ch1_item);
- end
- begin // if (on-the-fly) reset is monitored, drop the item
- @(negedge cfg.vif.rst_ni);
- `uvm_info(`gfn, $sformatf("\nmonitor is reset, drop item on channel 0\n%s",
- ch0_dut_item.sprint()), UVM_DEBUG)
- `uvm_info(`gfn, $sformatf("\nmonitor is reset, drop item on channel 1\n%s",
- ch1_dut_item.sprint()), UVM_DEBUG)
- end
- join_any
- disable fork;
+ automatic uint channel = i;
+ collect_channel_trans(channel);
+ reset_thread();
+ join_none
end
endtask : collect_trans
+ virtual protected task collect_channel_trans(uint channel);
+ bit bit_data;
+ uint bit_cnt;
+
+ pattgen_item dut_item;
+ forever begin
+ dut_item = pattgen_item::type_id::create("dut_item");
+ bit_cnt = 0;
+ fork
+ begin : isolation_thread
+ fork
+ begin
+ do begin
+ get_pattgen_bit(channel, cfg.polarity[channel], bit_data);
+ dut_item.data_q.push_back(bit_data);
+ bit_cnt++;
+ `uvm_info(`gfn, $sformatf("\n--> monitor: channel %0d, polar %0b, data[%0d] %b",
+ channel, cfg.polarity[channel], bit_cnt, bit_data), UVM_DEBUG)
+ end while (bit_cnt < cfg.length[channel]);
+ // avoid race condition (counter is achieved and reset is issued at the same time)
+ if (!cfg.reset_asserted) begin
+ item_port[channel].write(dut_item);
+ `uvm_info(`gfn, $sformatf("\n--> monitor: send dut_item on channel %0d to scb\n%s",
+ channel, dut_item.sprint()), UVM_DEBUG)
+ end
+ end
+ @(posedge cfg.reset_asserted);
+ join_any
+ disable fork;
+ end : isolation_thread
+ join
+ end
+ endtask : collect_channel_trans
+
+ virtual task reset_thread();
+ forever begin
+ @(negedge cfg.vif.rst_ni);
+ cfg.reset_asserted = 1'b1;
+ // implement other clean-up actions under reset here
+ @(posedge cfg.vif.rst_ni);
+ cfg.reset_asserted = 1'b0;
+ end
+ endtask : reset_thread
+
// update of_to_end to prevent sim finished when there is any activity on the bus
// ok_to_end = 0 (bus busy) / 1 (bus idle)
virtual task monitor_ready_to_end();
forever begin
- @(cfg.vif.pcl0_tx or cfg.vif.pda0_tx or cfg.vif.pcl1_tx or cfg.vif.pda1_tx);
- ok_to_end = (cfg.vif.pcl0_tx == 1'b0) && (cfg.vif.pda0_tx == 1'b0) &&
- (cfg.vif.pcl1_tx == 1'b0) && (cfg.vif.pda1_tx == 1'b0);
+ @(cfg.vif.pcl_tx, cfg.vif.pda_tx);
+ ok_to_end = (cfg.vif.pcl_tx === {NUM_PATTGEN_CHANNELS{1'b0}}) &&
+ (cfg.vif.pda_tx === {NUM_PATTGEN_CHANNELS{1'b0}});
end
endtask : monitor_ready_to_end
+ virtual task get_pattgen_bit(uint channel, bit polarity, output bit bit_o);
+ `DV_CHECK_LT_FATAL(channel, NUM_PATTGEN_CHANNELS, "invalid channel index")
+ if (polarity) begin
+ @(negedge cfg.vif.pcl_tx[channel]);
+ end else begin
+ @(posedge cfg.vif.pcl_tx[channel]);
+ end
+ bit_o = cfg.vif.pda_tx[channel];
+ endtask : get_pattgen_bit
+
endclass : pattgen_monitor
diff --git a/hw/dv/sv/pattgen_agent/pattgen_sequencer.sv b/hw/dv/sv/pattgen_agent/pattgen_sequencer.sv
deleted file mode 100644
index e42a5a7..0000000
--- a/hw/dv/sv/pattgen_agent/pattgen_sequencer.sv
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-class pattgen_sequencer extends dv_base_sequencer#(pattgen_item, pattgen_agent_cfg);
- `uvm_component_utils(pattgen_sequencer)
- `uvm_component_new
-
- // pattgen DUT does not require reponses from pattgen_agent thus no need extension
-endclass : pattgen_sequencer