Skip to content

Commit

Permalink
New testcase for the GPIO feature straps
Browse files Browse the repository at this point in the history
Removed the assumption StrapSampleOnce_A, that does not work
for cases that sample_trigger never fell or if we have more than one
reset operation happening during the simulation.

Signed-off-by: Marcelo Carvalho Faleiro de Almeida <[email protected]>
  • Loading branch information
marcelocarvalhoLowRisc committed Jan 20, 2025
1 parent 29d7b87 commit 49e465c
Show file tree
Hide file tree
Showing 18 changed files with 329 additions and 39 deletions.
10 changes: 9 additions & 1 deletion hw/ip/gpio/data/gpio.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
package: "",
desc: '''
This signal is pulsed high by the power manager after reset in order to sample the HW straps.
It can only be pulsed high one-time after reset. The following pulses will not be taken into consideration.
''',
default: "1'b0"
},
Expand Down Expand Up @@ -390,7 +391,14 @@
],
},
{ name: "HW_STRAPS_DATA_IN",
desc: "GPIO Input data sampled as straps during cold boot read value",
desc: '''
GPIO input data that was sampled as straps as the block came out of reset.

This register depends on the GpioAsHwStrapsEn parameter.
- If the parameter is false then the register reads as zero.
- If the parameter is true then GPIO input data is sampled on the first cycle after reset
where the strap_en_i input is high. That sampled data is stored in this register.
''',
swaccess: "ro",
hwaccess: "hrw",
tags: [// Value in the register is determined by GPIO pin values that are sampled
Expand Down
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"]
}
]
}
10 changes: 5 additions & 5 deletions hw/ip/gpio/doc/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ Referring to the [Comportable guideline for peripheral device functionality](htt

## [Inter-Module Signals](https://opentitan.org/book/doc/contributing/hw/comportability/index.html#inter-signal-handling)

| Port Name | Package::Struct | Type | Act | Width | Description |
|:---------------|:----------------------|:--------|:------|--------:|:----------------------------------------------------------------------------------------------|
| strap_en | logic | uni | rcv | 1 | This signal is pulsed high by the power manager after reset in order to sample the HW straps. |
| sampled_straps | gpio_pkg::gpio_straps | uni | req | 1 | This vector contains the sampled strap values. |
| tl | tlul_pkg::tl | req_rsp | rsp | 1 | |
| Port Name | Package::Struct | Type | Act | Width | Description |
|:---------------|:----------------------|:--------|:------|--------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| strap_en | logic | uni | rcv | 1 | This signal is pulsed high by the power manager after reset in order to sample the HW straps. It can only be pulsed high one-time after reset. The following pulses will not be taken into consideration. |
| sampled_straps | gpio_pkg::gpio_straps | uni | req | 1 | This vector contains the sampled strap values. |
| tl | tlul_pkg::tl | req_rsp | rsp | 1 | |

## Interrupts

Expand Down
47 changes: 26 additions & 21 deletions hw/ip/gpio/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
<!-- BEGIN CMDGEN util/regtool.py -d ./hw/ip/gpio/data/gpio.hjson -->
## Summary

| Name | Offset | Length | Description |
|:-----------------------------------------------------------|:---------|---------:|:--------------------------------------------------------------|
| gpio.[`INTR_STATE`](#intr_state) | 0x0 | 4 | Interrupt State Register |
| gpio.[`INTR_ENABLE`](#intr_enable) | 0x4 | 4 | Interrupt Enable Register |
| gpio.[`INTR_TEST`](#intr_test) | 0x8 | 4 | Interrupt Test Register |
| gpio.[`ALERT_TEST`](#alert_test) | 0xc | 4 | Alert Test Register |
| gpio.[`DATA_IN`](#data_in) | 0x10 | 4 | GPIO Input data read value |
| gpio.[`DIRECT_OUT`](#direct_out) | 0x14 | 4 | GPIO direct output data write value |
| gpio.[`MASKED_OUT_LOWER`](#masked_out_lower) | 0x18 | 4 | GPIO write data lower with mask. |
| gpio.[`MASKED_OUT_UPPER`](#masked_out_upper) | 0x1c | 4 | GPIO write data upper with mask. |
| gpio.[`DIRECT_OE`](#direct_oe) | 0x20 | 4 | GPIO Output Enable. |
| gpio.[`MASKED_OE_LOWER`](#masked_oe_lower) | 0x24 | 4 | GPIO write Output Enable lower with mask. |
| gpio.[`MASKED_OE_UPPER`](#masked_oe_upper) | 0x28 | 4 | GPIO write Output Enable upper with mask. |
| gpio.[`INTR_CTRL_EN_RISING`](#intr_ctrl_en_rising) | 0x2c | 4 | GPIO interrupt enable for GPIO, rising edge. |
| gpio.[`INTR_CTRL_EN_FALLING`](#intr_ctrl_en_falling) | 0x30 | 4 | GPIO interrupt enable for GPIO, falling edge. |
| gpio.[`INTR_CTRL_EN_LVLHIGH`](#intr_ctrl_en_lvlhigh) | 0x34 | 4 | GPIO interrupt enable for GPIO, level high. |
| gpio.[`INTR_CTRL_EN_LVLLOW`](#intr_ctrl_en_lvllow) | 0x38 | 4 | GPIO interrupt enable for GPIO, level low. |
| gpio.[`CTRL_EN_INPUT_FILTER`](#ctrl_en_input_filter) | 0x3c | 4 | filter enable for GPIO input bits. |
| gpio.[`HW_STRAPS_DATA_IN_VALID`](#hw_straps_data_in_valid) | 0x40 | 4 | Indicates whether the data in !!HW_STRAPS_DATA_IN is valid. |
| gpio.[`HW_STRAPS_DATA_IN`](#hw_straps_data_in) | 0x44 | 4 | GPIO Input data sampled as straps during cold boot read value |
| Name | Offset | Length | Description |
|:-----------------------------------------------------------|:---------|---------:|:---------------------------------------------------------------------------|
| gpio.[`INTR_STATE`](#intr_state) | 0x0 | 4 | Interrupt State Register |
| gpio.[`INTR_ENABLE`](#intr_enable) | 0x4 | 4 | Interrupt Enable Register |
| gpio.[`INTR_TEST`](#intr_test) | 0x8 | 4 | Interrupt Test Register |
| gpio.[`ALERT_TEST`](#alert_test) | 0xc | 4 | Alert Test Register |
| gpio.[`DATA_IN`](#data_in) | 0x10 | 4 | GPIO Input data read value |
| gpio.[`DIRECT_OUT`](#direct_out) | 0x14 | 4 | GPIO direct output data write value |
| gpio.[`MASKED_OUT_LOWER`](#masked_out_lower) | 0x18 | 4 | GPIO write data lower with mask. |
| gpio.[`MASKED_OUT_UPPER`](#masked_out_upper) | 0x1c | 4 | GPIO write data upper with mask. |
| gpio.[`DIRECT_OE`](#direct_oe) | 0x20 | 4 | GPIO Output Enable. |
| gpio.[`MASKED_OE_LOWER`](#masked_oe_lower) | 0x24 | 4 | GPIO write Output Enable lower with mask. |
| gpio.[`MASKED_OE_UPPER`](#masked_oe_upper) | 0x28 | 4 | GPIO write Output Enable upper with mask. |
| gpio.[`INTR_CTRL_EN_RISING`](#intr_ctrl_en_rising) | 0x2c | 4 | GPIO interrupt enable for GPIO, rising edge. |
| gpio.[`INTR_CTRL_EN_FALLING`](#intr_ctrl_en_falling) | 0x30 | 4 | GPIO interrupt enable for GPIO, falling edge. |
| gpio.[`INTR_CTRL_EN_LVLHIGH`](#intr_ctrl_en_lvlhigh) | 0x34 | 4 | GPIO interrupt enable for GPIO, level high. |
| gpio.[`INTR_CTRL_EN_LVLLOW`](#intr_ctrl_en_lvllow) | 0x38 | 4 | GPIO interrupt enable for GPIO, level low. |
| gpio.[`CTRL_EN_INPUT_FILTER`](#ctrl_en_input_filter) | 0x3c | 4 | filter enable for GPIO input bits. |
| gpio.[`HW_STRAPS_DATA_IN_VALID`](#hw_straps_data_in_valid) | 0x40 | 4 | Indicates whether the data in !!HW_STRAPS_DATA_IN is valid. |
| gpio.[`HW_STRAPS_DATA_IN`](#hw_straps_data_in) | 0x44 | 4 | GPIO input data that was sampled as straps as the block came out of reset. |

## INTR_STATE
Interrupt State Register
Expand Down Expand Up @@ -358,7 +358,12 @@ Indicates whether the data in [`HW_STRAPS_DATA_IN`](#hw_straps_data_in) is valid
| 0 | ro | 0x0 | HW_STRAPS_DATA_IN_VALID | |

## HW_STRAPS_DATA_IN
GPIO Input data sampled as straps during cold boot read value
GPIO input data that was sampled as straps as the block came out of reset.

This register depends on the GpioAsHwStrapsEn parameter.
- If the parameter is false then the register reads as zero.
- If the parameter is true then GPIO input data is sampled on the first cycle after reset
where the strap_en_i input is high. That sampled data is stored in this register.
- Offset: `0x44`
- Reset default: `0x0`
- Reset mask: `0xffffffff`
Expand Down
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
50 changes: 49 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,46 @@ class gpio_scoreboard extends cip_base_scoreboard #(.CFG_T (gpio_env_cfg),
end
endtask : monitor_gpio_interrupt_pins

// Task: monitor_gpio_straps
virtual task monitor_gpio_straps();
forever begin : monitor_gpio_intr
@(posedge cfg.clk_rst_vif.clk)
if(!cfg.under_reset) begin
if (|gpio_i_driven === 1'b1) begin
@(negedge cfg.straps_vif_inst.strap_en) begin
if (!first_strap_triggered) begin
// 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)));

// 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.sampled_straps.data)
// Check the register hw_straps_data_in_valid
`DV_CHECK_CASE_EQ('b1, cfg.straps_vif_inst.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 +607,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 +851,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
Loading

0 comments on commit 49e465c

Please sign in to comment.