Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gpio scoreboard imp #26098

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions hw/dv/sv/dv_lib/dv_base_sequencer.sv
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ class dv_base_sequencer #(type ITEM_T = uvm_sequence_item,

function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (cfg.has_req_fifo) req_analysis_fifo = new("req_analysis_fifo", this);
if (cfg.has_rsp_fifo) rsp_analysis_fifo = new("rsp_analysis_fifo", this);

if (cfg == null) begin
`uvm_fatal("dv_base_sequencer", "cfg handle is null. Ensure it's properly assigned before build_phase.")
end else begin
if (cfg.has_req_fifo) req_analysis_fifo = new("req_analysis_fifo", this);
if (cfg.has_rsp_fifo) rsp_analysis_fifo = new("rsp_analysis_fifo", this);
end
endfunction : build_phase

endclass
23 changes: 22 additions & 1 deletion hw/dv/sv/dv_lib/dv_base_virtual_sequencer.sv
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ class dv_base_virtual_sequencer #(type CFG_T = dv_base_env_cfg,
CFG_T cfg;
COV_T cov;

`uvm_component_new
function new(string name = "dv_base_virtual_sequencer", uvm_component parent);
super.new(name, parent);
endfunction

// Dynamic associative array to store sub-sequencers
uvm_sequencer_base sub_sequencers[string];

// Method to dynamically register a sub-sequencer
function void register_sequencer(string name, uvm_sequencer_base sequencer);
sub_sequencers[name] = sequencer;
`uvm_info(get_type_name(), $sformatf("Registered sequencer: %s", name), UVM_MEDIUM)
endfunction

// Method to retrieve a sequencer by name
function uvm_sequencer_base get_sequencer(string name);
if (sub_sequencers.exists(name))
return sub_sequencers[name];
else begin
`uvm_error(get_type_name(), $sformatf("Sequencer %s not found!", name))
return null;
end
endfunction

endclass
15 changes: 15 additions & 0 deletions hw/ip/gpio/data/gpio_testplan.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,20 @@
stage: V2
tests: ["gpio_stress_all"]
}
{
name: straps_data
desc: '''Verify the straps data/valid ouput expected values based on the strap_en and gpio_i inputs:
- Drives gpio_i input with random values.
- Set the strap_en high for at least one clock cycle.
- Read the registers hw_straps_data_in and hw_straps_data_in_valid.
- The data read and sampled_straps_o will be checked in the scoreboard.
- Drive the gpio_o to make sure that has no impact on straps registers.
- Read to make sure that if does not affect the straps registers after drive the gpio_o.
- Apply reset and make sure the strap registers are clean.
- Read straps registers after reset.
- Iterate again the same flow, with new random values.'''
stage: V3
tests: ["gpio_rand_straps"]
}
]
}
54 changes: 54 additions & 0 deletions hw/ip/gpio/dv/env/gpio_agent/gpio_strap_agent.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

`ifndef GPIO_STRAP_AGENT_SV
`define GPIO_STRAP_AGENT_SV
class gpio_strap_agent extends dv_base_agent #(.CFG_T(gpio_strap_agent_cfg),
.DRIVER_T(gpio_strap_driver),
.SEQUENCER_T(strap_sequencer),
.MONITOR_T(gpio_strap_monitor));

`uvm_component_utils(gpio_strap_agent)

gpio_strap_monitor strap_monitor;
gpio_strap_driver strap_driver;
strap_sequencer strap_sqr;
gpio_strap_agent_cfg cfg;

// Constructor
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new

// Build phase
function void build_phase(uvm_phase phase);

// Instantiate the monitor
strap_monitor = gpio_strap_monitor::type_id::create("strap_monitor", this);
// Instantiate the driver
strap_driver = gpio_strap_driver::type_id::create("strap_driver", this);
// Instantiate the sequencer
strap_sqr = strap_sequencer::type_id::create("strap_sqr", this);
// Set the sequencer in the config DB for the driver
uvm_config_db#(strap_sequencer)::set(this, "*", "strap_sqr", strap_sqr);

// Instantiate the strap agent config object
cfg = gpio_strap_agent_cfg::type_id::create("cfg", this);

// Set the agent cfg in the config DB
uvm_config_db#(gpio_strap_agent_cfg)::set(this, "", "cfg", cfg);
// Set the agent cfg in the config DB
uvm_config_db#(gpio_strap_agent_cfg)::set(this, "*", "monitor_cfg", cfg);

super.build_phase(phase);
endfunction : build_phase

// Connect phase
function void connect_phase(uvm_phase phase);
strap_driver.seq_item_port.connect(strap_sqr.seq_item_export);
super.connect_phase(phase);
endfunction : connect_phase

endclass : gpio_strap_agent
`endif // GPIO_STRAP_AGENT_SV
14 changes: 14 additions & 0 deletions hw/ip/gpio/dv/env/gpio_agent/gpio_strap_agent_cfg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`ifndef GPIO_STRAP_AGENT_CFG_SV
`define GPIO_STRAP_AGENT_CFG_SV
class gpio_strap_agent_cfg extends dv_base_agent_cfg;
`uvm_object_utils(gpio_strap_agent_cfg)

function new (string name = "gpio_strap_agent_cfg");
super.new(name);
endfunction : new

endclass
`endif // GPIO_STRAP_AGENT_SV
57 changes: 57 additions & 0 deletions hw/ip/gpio/dv/env/gpio_agent/gpio_strap_driver.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

`ifndef GPIO_STRAP_DRIVER_SV
`define GPIO_STRAP_DRIVER_SV

class gpio_strap_driver extends dv_base_driver #(.ITEM_T(uvm_sequence_item),
.CFG_T(gpio_strap_agent_cfg));

`uvm_component_utils(gpio_strap_driver)

straps_vif m_straps_vif;
virtual clk_rst_if clk_rst_vif;
strap_sequencer m_seqr;

// Constructor: Creates a new instance of the gpio_driver class
// @param name - The name of the component
// @param parent - The parent component
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(straps_vif)::get(this, "*.*", "straps_vif", m_straps_vif)) begin
`uvm_fatal("gpio_strap_driver", "Virtual interface m_straps_vif is not set in the uvm_config_db")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would help to use either gfn here or
$sformatf("%m") here in case we have multiple agents so it's easier to figure out the instance that's wrong

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix that! thnks

end
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "*.env", "clk_rst_vif", clk_rst_vif)) begin
`uvm_fatal("gpio_strap_driver", "Could not get clk_rst_vif")
end
if (!uvm_config_db#(strap_sequencer)::get(this, "", "strap_sqr", m_seqr)) begin
`uvm_fatal(get_type_name(), "Failed to get sequencer handle from config DB!")
end
endfunction

virtual task run_phase(uvm_phase phase);
forever begin
gpio_seq_item m_item;
seq_item_port.get_next_item(req);

if(!$cast(m_item , req)) begin
`uvm_error("gpio_strap_driver", "Failed to cast item to gpio_seq_item")
end
drive_item(m_item);
seq_item_port.item_done();
end
endtask

// Drive the stran_en_i pin
virtual task drive_item(gpio_seq_item req);
@(posedge clk_rst_vif.clk);
m_straps_vif.dut_if.strap_en <= req.strap_en_i;
endtask

endclass
`endif // GPIO_STRAP_DRIVER_SV
78 changes: 78 additions & 0 deletions hw/ip/gpio/dv/env/gpio_agent/gpio_strap_monitor.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`ifndef GPIO_STRAP_MONITOR_SV
`define GPIO_STRAP_MONITOR_SV
class gpio_strap_monitor extends dv_base_monitor #(.ITEM_T(uvm_sequence_item),
.CFG_T(gpio_strap_agent_cfg));

`uvm_component_utils(gpio_strap_monitor)

// Used to send the strap outputs to the scoreboard
uvm_analysis_port #(gpio_seq_item) mon_ap;
// straps virtual interface
straps_vif m_straps_vif;
// gpio virtual interface
gpio_vif m_gpio_vif;
// clk and rst virtual interface
virtual clk_rst_if clk_rst_vif;
// GPIO sequence item
gpio_seq_item item;
// strap agent configuration object
gpio_strap_agent_cfg cfg;

// Constructor
function new(string name = "gpio_strap_monitor", uvm_component parent = null);
super.new(name, parent);
mon_ap = new ("mon_ap", this);
item = new();
endfunction

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(straps_vif)::get(this, "*.*", "straps_vif", m_straps_vif)) begin
`uvm_fatal(`gfn, "Virtual interface m_straps_vif is not set")
end
if (!uvm_config_db#(gpio_vif)::get(this, "*.env", "gpio_vif", m_gpio_vif)) begin
`uvm_fatal("gpio_strap_driver", "Could not get m_gpio_vif")
end
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "*.env", "clk_rst_vif", clk_rst_vif)) begin
`uvm_fatal(`gfn, "Could not get clk_rst_vif")
end
if (!uvm_config_db#(gpio_strap_agent_cfg)::get(this, "", "monitor_cfg", cfg)) begin
`uvm_fatal(`gfn, "Could not get strap agent config")
end
// Required because the parent class use the agent configuration object.
super.cfg = cfg;
endfunction

// Task to monitor GPIO strap signals
virtual task run_phase(uvm_phase phase);
fork
monitor_gpio_straps();
join_none
endtask

// Task: monitor_gpio_straps
// The task monitor the gpio straps enable signal
// and send the strap ouput information to the scoreboard to be checked.
virtual task monitor_gpio_straps();
forever begin : monitor_gpio_straps
@(posedge clk_rst_vif.clk)
if(clk_rst_vif.rst_n) begin
if(m_straps_vif.tb_if.strap_en &&
!m_straps_vif.strap_en_q &&
!m_straps_vif.strap_en_qq) begin
// Wait for at least 1 clock cycle after strap_en is asserted.
clk_rst_vif.wait_clks(1);
// Sample the straps
item.sampled_straps_o.data = m_straps_vif.tb_if.sampled_straps.data;
item.sampled_straps_o.valid = m_straps_vif.tb_if.sampled_straps.valid;
// Send the sampled straps to the gpio scoreboard.
mon_ap.write(item);
end
end
end
endtask : monitor_gpio_straps
endclass : gpio_strap_monitor
`endif // GPIO_STRAP_MONITOR_SV
9 changes: 9 additions & 0 deletions hw/ip/gpio/dv/env/gpio_env.core
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ filesets:
depend:
- lowrisc:dv:ralgen
- lowrisc:dv:cip_lib
- lowrisc:ip:gpio:0.1
files:
- gpio_env_pkg.sv
- gpio_env_cfg.sv: {is_include_file: true}
- gpio_env_cov.sv: {is_include_file: true}
- gpio_virtual_sequencer.sv: {is_include_file: true}
- gpio_agent/gpio_strap_agent_cfg.sv: {is_include_file: true}
- gpio_agent/gpio_strap_driver.sv: {is_include_file: true}
- gpio_agent/gpio_strap_monitor.sv: {is_include_file: true}
- gpio_agent/gpio_strap_agent.sv: {is_include_file: true}
- gpio_scoreboard.sv: {is_include_file: true}
- gpio_env.sv: {is_include_file: true}
- seq_lib/gpio_vseq_list.sv: {is_include_file: true}
Expand All @@ -28,6 +34,9 @@ filesets:
- seq_lib/gpio_stress_all_vseq.sv: {is_include_file: true}
- seq_lib/gpio_intr_rand_pgm_vseq.sv: {is_include_file: true}
- seq_lib/gpio_intr_with_filter_rand_intr_event_vseq.sv: {is_include_file: true}
- seq_lib/gpio_rand_straps_vseq.sv : {is_include_file: true}
- seq_lib/gpio_seq_item.sv: {is_include_file: true}
- seq_lib/gpio_strap_en_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource

generate:
Expand Down
46 changes: 38 additions & 8 deletions hw/ip/gpio/dv/env/gpio_env.sv
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,50 @@
// SPDX-License-Identifier: Apache-2.0

class gpio_env extends cip_base_env #(
.CFG_T (gpio_env_cfg),
.COV_T (gpio_env_cov),
.VIRTUAL_SEQUENCER_T(gpio_virtual_sequencer),
.SCOREBOARD_T (gpio_scoreboard)
);
.CFG_T (gpio_env_cfg),
.COV_T (gpio_env_cov),
.VIRTUAL_SEQUENCER_T(gpio_virtual_sequencer),
.SCOREBOARD_T (gpio_scoreboard)
);
`uvm_component_utils(gpio_env)

`uvm_component_new
gpio_strap_agent strap_agent;
straps_vif m_straps_vif;
virtual clk_rst_if m_clk_rst_vif;
gpio_vif m_gpio_vif;

function new (string name, uvm_component parent = null);
super.new (name, parent);
endfunction

function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(gpio_vif)::get(this, "", "gpio_vif", cfg.gpio_vif)) begin
`uvm_fatal(get_full_name(), "failed to get gpio_vif from uvm_config_db")

// Create and configure the gpio_strap_agent
strap_agent = gpio_strap_agent::type_id::create("strap_agent", this);

if (!uvm_config_db#(straps_vif)::get(this, "*.*", "straps_vif", m_straps_vif)) begin
`uvm_fatal("gpio_strap_driver", "Could not get m_straps_vif from uvm_config_db ")
end
if (!uvm_config_db#(virtual clk_rst_if)::get(this, "", "clk_rst_vif", m_clk_rst_vif)) begin
`uvm_fatal("gpio_strap_driver", "Could not get m_clk_rst_vif from uvm_config_db")
end
if (!uvm_config_db#(gpio_vif)::get(this, "", "gpio_vif", m_gpio_vif)) begin
`uvm_fatal("gpio_strap_driver", "Could not get m_gpio_vif from uvm_config_db")
end
// Set these interfaces instances to the environment configuration object.
cfg.gpio_vif = m_gpio_vif;
cfg.straps_vif_inst = m_straps_vif;
cfg.clk_rst_vif = m_clk_rst_vif;

endfunction

virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// Connect the strap monitor to the gpio scoreboard
strap_agent.strap_monitor.mon_ap.connect(scoreboard.sb_exp);
// Register a strap agent’s sub-sequencer into the virtual sequencer.
// to be able to access it through the main sequence test.
virtual_sequencer.register_sequencer("strap_sequencer", strap_agent.strap_sqr);
endfunction
endclass
9 changes: 7 additions & 2 deletions hw/ip/gpio/dv/env/gpio_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ class gpio_env_cfg extends cip_base_env_cfg #(
rand bit pulldown_en;
// gpio virtual interface
gpio_vif gpio_vif;
// gpio strats virtual interface
straps_vif straps_vif_inst;

constraint pullup_pulldown_en_c {pullup_en ^ pulldown_en;}

`uvm_object_utils(gpio_env_cfg)
`uvm_object_new

function new (string name = "gpio_env_cfg");
super.new (name);
endfunction

virtual function void initialize(bit [TL_AW-1:0] csr_base_addr = '1);
list_of_alerts = gpio_env_pkg::LIST_OF_ALERTS;
Expand All @@ -27,6 +32,6 @@ class gpio_env_cfg extends cip_base_env_cfg #(

// only support 1 outstanding TL item
m_tl_agent_cfg.max_outstanding_req = 1;
endfunction : initialize

endfunction : initialize
endclass
Loading
Loading