Skip to content

Commit

Permalink
Functional coverage for gpio straps
Browse files Browse the repository at this point in the history
- Included new file gpio_cover.cfg to add the gpio_straps_if cover
assertions in the database
- Added the configuration file above into the gpio_sim_cfg.hjson
- Included the commit from PR: 25868 about straps verification,
from this point, only needs to review these files:
        - new file:   hw/ip/gpio/dv/cov/gpio_cover.cfg
        - modified:   hw/ip/gpio/dv/gpio_sim_cfg.hjson (Inclusion about
          the gpio_cover.cfg)
        - modified:   hw/ip/gpio/dv/env/gpio_env_cov.sv
        - new file:   hw/ip/gpio/dv/interfaces/gpio_straps_if.sv (New
          cover properties included)

Signed-off-by: Marcelo Carvalho Faleiro de Almeida <[email protected]>
  • Loading branch information
marcelocarvalhoLowRisc committed Feb 3, 2025
1 parent 29d7b87 commit ad99314
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 2 deletions.
6 changes: 6 additions & 0 deletions hw/ip/gpio/dv/cov/gpio_cover.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// Enables the coverage for gpio_straps_if cover assertions.
+module gpio_straps_if
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
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.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.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
13 changes: 12 additions & 1 deletion hw/ip/gpio/dv/gpio_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@
// Add GPIO specific exclusion files.
vcs_cov_excl_files: ["{proj_root}/hw/ip/gpio/dv/cov/gpio_cov_excl.el"]

overrides: [
{
name: default_vcs_cov_cfg_file
value: "-cm_hier {dv_root}/tools/vcs/cover.cfg+{proj_root}/hw/ip/gpio/dv/cov/gpio_cover.cfg"
}
]

// Enable cdc instrumentation.
run_opts: ["+cdc_instrumentation_enabled=1"]
run_opts: ["+cdc_instrumentation_enabled=1", "+interface", "+vcs+dumpinterface", "+define+UVM_DUMP_INTERFACES", "+cover=all"]

// Add a second build mode to test the input synchronizers.
// Note that since the scoreboard has a cycle accurate model
Expand Down Expand Up @@ -180,6 +187,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
63 changes: 63 additions & 0 deletions hw/ip/gpio/dv/interfaces/gpio_straps_if.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// interface : gpio_straps_if
`ifndef GPIO_STRAPS_IF_SV
`define GPIO_STRAPS_IF_SV

import gpio_pkg::*;

// Interface definition
interface gpio_straps_if();

logic clk;
logic rst_n;
logic strap_en; // Signal to enable straps
gpio_straps_t sampled_straps; // Sampled gpio_i snapshot data from GPIO (DUT)

modport straps_port_in(input clk,
input rst_n,
input strap_en,
output sampled_straps);

modport straps_port_out(output clk,
output rst_n,
output strap_en,
input sampled_straps);

// Sequence to capture the timing relationship between strap_en and strap_data
sequence strap_data_timing_seq;
@(posedge clk) strap_en ##1 sampled_straps.data;
endsequence

// Property for the strap_data timing
property strap_data_timing_prop;
strap_data_timing_seq;
endproperty

// Cover the property
COV_STRAP_DATA_TIMING: cover property (strap_data_timing_prop);

// Sequence to capture the timing relationship between rst_n and strap_en
sequence reset_timing_seq;
@(posedge clk) rst_n ##1 strap_en;
endsequence

// Property for the reset timing
property reset_timing_prop;
reset_timing_seq;
endproperty

// Cover the property
COV_STRAP_RST_TIMING: cover property (reset_timing_prop);

// Additional checks for early strap_en
property strap_en_too_early_prop;
@(posedge clk) rst_n ##[1:$] strap_en;
endproperty

COV_STRAP_EN_TIMING: cover property (strap_en_too_early_prop);

endinterface : gpio_straps_if

`endif // GPIO_STRAPS_IF_SV
1 change: 0 additions & 1 deletion hw/ip/gpio/rtl/gpio.sv
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ module gpio
assign hw2reg.hw_straps_data_in.d = data_in_d;
assign sampled_straps_o.data = reg2hw.hw_straps_data_in.q;
assign sampled_straps_o.valid = reg2hw.hw_straps_data_in_valid.q;
`ASSUME(StrapSampleOnce_A, ##1 $fell(sample_trigger) |-> always !sample_trigger)
end else begin : gen_no_strap_sample
assign hw2reg.hw_straps_data_in_valid.de = 1'b0;
assign hw2reg.hw_straps_data_in_valid.d = 1'b0;
Expand Down

0 comments on commit ad99314

Please sign in to comment.