Skip to content

Commit

Permalink
Included the gpio_straps_vseq in the gpio_stress_all_vseq list
Browse files Browse the repository at this point in the history
Merge the PR #25868 first.

Signed-off-by: Marcelo Carvalho Faleiro de Almeida <marcelo.carvalho@lowrisc.org>
  • Loading branch information
marcelocarvalhoLowRisc committed Feb 3, 2025
1 parent 29d7b87 commit 5af7d23
Show file tree
Hide file tree
Showing 16 changed files with 304 additions and 13 deletions.
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"]
}
]
}
1 change: 1 addition & 0 deletions hw/ip/gpio/dv/env/gpio_env.core
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ 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}
file_type: systemVerilogSource

generate:
Expand Down
3 changes: 3 additions & 0 deletions hw/ip/gpio/dv/env/gpio_env.sv
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ class gpio_env extends cip_base_env #(
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")
end
if (!uvm_config_db#(straps_vif)::get(this, "", "straps_vif", cfg.straps_vif_inst)) begin
`uvm_fatal(get_full_name(), "Virtual interface straps_vif_inst is not set")
end
endfunction

endclass
10 changes: 9 additions & 1 deletion 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 straps 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,9 @@ class gpio_env_cfg extends cip_base_env_cfg #(

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

// Used to allow reset operation during a stress all tests and check the CSR after that.
can_reset_with_csr_accesses = 1'b1;
endfunction : initialize

endclass
1 change: 1 addition & 0 deletions hw/ip/gpio/dv/env/gpio_env_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ package gpio_env_pkg;
parameter string LIST_OF_ALERTS[] = {"fatal_fault"};

typedef virtual pins_if #(NUM_GPIOS) gpio_vif;
typedef virtual gpio_straps_if straps_vif;
typedef class gpio_env_cfg;
typedef class gpio_env_cov;
typedef cip_base_virtual_sequencer #(gpio_env_cfg, gpio_env_cov) gpio_virtual_sequencer;
Expand Down
58 changes: 57 additions & 1 deletion hw/ip/gpio/dv/env/gpio_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class gpio_scoreboard extends cip_base_scoreboard #(.CFG_T (gpio_env_cfg),
// (i) indicate that write to INTR_STATE register just happened, and
// (ii) store information of which all interupt bits were cleared
bit [TL_DW-1:0] cleared_intr_bits;
// Flag to indicate that the strap was triggered
bit first_strap_triggered;

// mask are WO, store the values in scb
uvm_reg_data_t masked_out_lower_mask;
Expand All @@ -40,7 +42,9 @@ class gpio_scoreboard extends cip_base_scoreboard #(.CFG_T (gpio_env_cfg),

`uvm_component_utils(gpio_scoreboard)

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

// Function: build_phase
function void build_phase(uvm_phase phase);
Expand All @@ -54,6 +58,8 @@ class gpio_scoreboard extends cip_base_scoreboard #(.CFG_T (gpio_env_cfg),
fork
monitor_gpio_i();
monitor_gpio_interrupt_pins();
monitor_gpio_straps();
handle_reset();
join_none
endtask

Expand Down Expand Up @@ -360,6 +366,54 @@ class gpio_scoreboard extends cip_base_scoreboard #(.CFG_T (gpio_env_cfg),
end
endtask : monitor_gpio_interrupt_pins

virtual task update_gpio_straps_regs();
// Update data_in ral register value based on result of input
`DV_CHECK_FATAL(
ral.hw_straps_data_in.predict(.value(gpio_i_driven),
.kind(UVM_PREDICT_DIRECT)));
// Update data_in valid register value based on result of input
`DV_CHECK_FATAL(
ral.hw_straps_data_in_valid.predict(.value('b1),
.kind(UVM_PREDICT_DIRECT)));
endtask : update_gpio_straps_regs

// Task: monitor_gpio_straps
// The task monitors the gpio straps enable signal
// and checks the straps output signal after the first strap trigger
virtual task monitor_gpio_straps();
forever begin : monitor_gpio_straps
@(posedge cfg.clk_rst_vif.clk)
if(!cfg.under_reset) begin
if (|gpio_i_driven === 1'b1) begin
@(posedge cfg.straps_vif_inst.strap_en) begin
// Wait for at least 1 clock cycle after strap_en is asserted, to allow the straps to be
// ready for sampling.
cfg.clk_rst_vif.wait_clks(1);
update_gpio_straps_regs();
if (!first_strap_triggered) begin
// Checker: Compare actual values of gpio pins with straps register.
// Check the register hw_straps_data_in against gpio_i pins
`DV_CHECK_CASE_EQ(gpio_i_driven, cfg.straps_vif_inst.straps_port.sampled_straps.data)
// Check the register hw_straps_data_in_valid
`DV_CHECK_CASE_EQ('b1, cfg.straps_vif_inst.straps_port.sampled_straps.valid)
// Turn-off the checker after the first strap trigger.
first_strap_triggered = 1;
end
end
end
end
end
endtask : monitor_gpio_straps

virtual protected task handle_reset();
forever begin
@(negedge cfg.clk_rst_vif.rst_n);
cfg.under_reset = 1;
@(posedge cfg.clk_rst_vif.rst_n);
cfg.under_reset = 0;
end
endtask

// Function: actual_gpio_i_activity
function bit actual_gpio_i_activity();
return ~((prv_gpio_i_pins_o === cfg.gpio_vif.pins_o) &&
Expand Down Expand Up @@ -561,6 +615,7 @@ class gpio_scoreboard extends cip_base_scoreboard #(.CFG_T (gpio_env_cfg),
((|gpio_i_driven === 1'b1) && (actual_gpio_i_activity() == 1))) begin
`DV_CHECK_CASE_EQ(pred_val_gpio_pins, cfg.gpio_vif.pins)
end

end

endfunction : gpio_predict_and_compare
Expand Down Expand Up @@ -804,6 +859,7 @@ class gpio_scoreboard extends cip_base_scoreboard #(.CFG_T (gpio_env_cfg),
last_intr_update_except_clearing = '0;
last_intr_test_event = '0;
cleared_intr_bits = '0;
first_strap_triggered = 0;
endfunction

// Function: check_phase
Expand Down
153 changes: 153 additions & 0 deletions hw/ip/gpio/dv/env/seq_lib/gpio_rand_straps_vseq.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Verify the straps data/valid ouput expected values based on the strap_en and gpio_in inputs:
// - Drive gpio_in 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_out 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_out.
// - Apply reset and make sure the strap registers are clean.
// - Read straps registers after reset.
// - Iterate again the same flow, with new random values.
class gpio_rand_straps_vseq extends gpio_base_vseq;

`uvm_object_utils(gpio_rand_straps_vseq)

// gpio input to drive
rand bit [NUM_GPIOS-1:0] gpio_in;
// gpio output to program in register
rand bit [NUM_GPIOS-1:0] gpio_out;
// gpio output enable to program in register
rand bit [NUM_GPIOS-1:0] gpio_oe;

// Read straps_data_in
bit [NUM_GPIOS-1:0] rd_hw_straps_data_in;
// Read straps_data_in valid
bit rd_hw_straps_data_in_valid;

constraint num_trans_c {
num_trans inside {[20:200]};
}

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

task test_straps_gpio_in();

// Drive the gpio_in
drive_gpio_in(gpio_in);

// Wait at least one clock cycle to drive the strap_en
// Required because is required one clock cycle to update the gpio_in regsisters.
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(delay, delay >= 1;)
cfg.clk_rst_vif.wait_clks(delay);

// Trigger the snapshot of gpio_in to be stored in the straps registers
cfg.straps_vif_inst.straps_port.strap_en = 1;
cfg.clk_rst_vif.wait_clks(1);

// Wait at least two clock cycles to avoid race condition with the predict value updated
// in the scoreboard
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(delay, delay >= 1;)
cfg.clk_rst_vif.wait_clks(delay);

// Read the hw_straps_data_in and check the expected value in the scoreboard
csr_rd(.ptr(ral.hw_straps_data_in), .value(rd_hw_straps_data_in));
// Read the hw_straps_data_in_valid and check the expected value in the scoreboard
csr_rd(.ptr(ral.hw_straps_data_in_valid), .value(rd_hw_straps_data_in_valid));

// Random wait
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(delay, delay >= 0;)
cfg.clk_rst_vif.wait_clks(delay);

// Stop driving gpio_in
undrive_gpio_in();

// Random wait
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(delay, delay >= 0;)
cfg.clk_rst_vif.wait_clks(delay);

// Read to make sure that if does not affect the straps registers after undrive the gpio_in
csr_rd(.ptr(ral.hw_straps_data_in), .value(rd_hw_straps_data_in));
csr_rd(.ptr(ral.hw_straps_data_in_valid), .value(rd_hw_straps_data_in_valid));

endtask : test_straps_gpio_in

task test_straps_gpio_out();

// Additional verification
// Drive the gpio_out to make sure that has no impact on straps registers.
// then read the gpio strap registers again
cfg.gpio_vif.drive_en('0);

ral.direct_out.set(gpio_out);
ral.direct_oe.set(gpio_oe);
csr_update(.csr(ral.direct_out));
csr_update(.csr(ral.direct_oe));

// Random wait
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(delay, delay >= 0;)
cfg.clk_rst_vif.wait_clks(delay);

// Read to make sure that if does not affect the straps registers after drive the gpio_out
csr_rd(.ptr(ral.hw_straps_data_in), .value(rd_hw_straps_data_in));
csr_rd(.ptr(ral.hw_straps_data_in_valid), .value(rd_hw_straps_data_in_valid));

endtask : test_straps_gpio_out

task check_transaction(string txn_desc, bit is_first);
string msg_id = {`gfn, txn_desc};

`DV_CHECK_MEMBER_RANDOMIZE_FATAL(gpio_in)
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(gpio_out)
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(gpio_oe)

// User case to test the straps output, with gpio_in data randomised
test_straps_gpio_in();

// User case to test the straps output/registers, with gpio_out data randomised
// The gpio_out should not affect the straps output/registers.
//test_straps_gpio_out();

// Random wait
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(delay, delay >= 1;)
cfg.clk_rst_vif.wait_clks(delay);

// Disable the straps.
cfg.straps_vif_inst.straps_port.strap_en = 0;
// Apply reset and make sure the strap registers are clean
apply_reset();

// Random wait
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(delay, delay >= 2;)
cfg.clk_rst_vif.wait_clks(delay);

// Read the straps registers after reset
csr_rd(.ptr(ral.hw_straps_data_in), .value(rd_hw_straps_data_in));
csr_rd(.ptr(ral.hw_straps_data_in_valid), .value(rd_hw_straps_data_in_valid));

endtask : check_transaction

task body();
`uvm_info(`gfn, $sformatf("num_trans = %0d", num_trans), UVM_HIGH)

for (uint tr_num = 0; tr_num < num_trans; tr_num++) begin
string msg_id = {`gfn, $sformatf(" Transaction-%0d", tr_num)};
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(delay)

cfg.clk_rst_vif.wait_clks(delay);
`uvm_info(msg_id, $sformatf("delay = %0d", delay), UVM_HIGH)

check_transaction(msg_id, tr_num == 0);

`uvm_info(msg_id, "End of Transaction", UVM_HIGH)

end // end for

endtask : body

endclass : gpio_rand_straps_vseq
3 changes: 2 additions & 1 deletion hw/ip/gpio/dv/env/seq_lib/gpio_stress_all_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class gpio_stress_all_vseq extends gpio_base_vseq;
"gpio_dout_din_regs_random_rw_vseq",
"gpio_intr_rand_pgm_vseq",
"gpio_rand_intr_trigger_vseq",
"gpio_random_long_reg_writes_reg_reads_vseq"};
"gpio_random_long_reg_writes_reg_reads_vseq",
"gpio_rand_straps_vseq"};
for (int i = 1; i <= num_trans; i++) begin
uvm_sequence seq;
gpio_base_vseq gpio_vseq;
Expand Down
1 change: 1 addition & 0 deletions hw/ip/gpio/dv/env/seq_lib/gpio_vseq_list.sv
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
`include "gpio_random_long_reg_writes_reg_reads_vseq.sv"
`include "gpio_full_random_vseq.sv"
`include "gpio_stress_all_vseq.sv"
`include "gpio_rand_straps_vseq.sv"
1 change: 1 addition & 0 deletions hw/ip/gpio/dv/gpio_sim.core
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ filesets:
depend:
- lowrisc:dv:gpio_test
- lowrisc:dv:gpio_sva
- lowrisc:dv:gpio_if
files:
- tb/tb.sv
file_type: systemVerilogSource
Expand Down
4 changes: 4 additions & 0 deletions hw/ip/gpio/dv/gpio_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@
build_mode: en_cdc_prims
run_opts: ["+no_pullup_pulldown=1"]
}
{
name: gpio_rand_straps
uvm_test_seq: gpio_rand_straps_vseq
}
]

// List of regressions.
Expand Down
18 changes: 18 additions & 0 deletions hw/ip/gpio/dv/interfaces/gpio_if.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CAPI=2:
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:dv:gpio_if:0.1"
description: "GPIO Interfaces"
filesets:
files_dv:
depend:
- lowrisc:ip:gpio:0.1
files:
- gpio_straps_if.sv
file_type: systemVerilogSource

targets:
default:
filesets:
- files_dv
Loading

0 comments on commit 5af7d23

Please sign in to comment.