From 87b277d17faf91daee616f0c89eb0509b1e1f431 Mon Sep 17 00:00:00 2001 From: Marcelo Carvalho Faleiro de Almeida Date: Tue, 14 Jan 2025 15:56:15 +0000 Subject: [PATCH] Functional coverage for gpio straps - 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 --- hw/ip/gpio/data/gpio_testplan.hjson | 15 ++ hw/ip/gpio/dv/cov/gpio_cover.cfg | 6 + hw/ip/gpio/dv/env/gpio_env.core | 1 + hw/ip/gpio/dv/env/gpio_env.sv | 3 + hw/ip/gpio/dv/env/gpio_env_cfg.sv | 10 +- hw/ip/gpio/dv/env/gpio_env_pkg.sv | 1 + hw/ip/gpio/dv/env/gpio_scoreboard.sv | 60 ++++++- .../dv/env/seq_lib/gpio_rand_straps_vseq.sv | 153 ++++++++++++++++++ hw/ip/gpio/dv/env/seq_lib/gpio_vseq_list.sv | 1 + hw/ip/gpio/dv/gpio_sim.core | 1 + hw/ip/gpio/dv/gpio_sim_cfg.hjson | 13 +- hw/ip/gpio/dv/interfaces/gpio_if.core | 18 +++ hw/ip/gpio/dv/interfaces/gpio_straps_if.sv | 63 ++++++++ hw/ip/gpio/dv/tb/tb.sv | 14 +- hw/ip/gpio/dv/tests/gpio_base_test.sv | 17 +- hw/ip/gpio/rtl/gpio.sv | 1 - 16 files changed, 364 insertions(+), 13 deletions(-) create mode 100644 hw/ip/gpio/dv/cov/gpio_cover.cfg create mode 100644 hw/ip/gpio/dv/env/seq_lib/gpio_rand_straps_vseq.sv create mode 100644 hw/ip/gpio/dv/interfaces/gpio_if.core create mode 100644 hw/ip/gpio/dv/interfaces/gpio_straps_if.sv diff --git a/hw/ip/gpio/data/gpio_testplan.hjson b/hw/ip/gpio/data/gpio_testplan.hjson index c8588cb3854e63..e09ef17c3ea406 100644 --- a/hw/ip/gpio/data/gpio_testplan.hjson +++ b/hw/ip/gpio/data/gpio_testplan.hjson @@ -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"] + } ] } diff --git a/hw/ip/gpio/dv/cov/gpio_cover.cfg b/hw/ip/gpio/dv/cov/gpio_cover.cfg new file mode 100644 index 00000000000000..5cf610c2b8a167 --- /dev/null +++ b/hw/ip/gpio/dv/cov/gpio_cover.cfg @@ -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 diff --git a/hw/ip/gpio/dv/env/gpio_env.core b/hw/ip/gpio/dv/env/gpio_env.core index da4d4389683e1c..7e4c39ede54418 100644 --- a/hw/ip/gpio/dv/env/gpio_env.core +++ b/hw/ip/gpio/dv/env/gpio_env.core @@ -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: diff --git a/hw/ip/gpio/dv/env/gpio_env.sv b/hw/ip/gpio/dv/env/gpio_env.sv index 111ac6c7a7e161..ced2992614c1ac 100644 --- a/hw/ip/gpio/dv/env/gpio_env.sv +++ b/hw/ip/gpio/dv/env/gpio_env.sv @@ -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 diff --git a/hw/ip/gpio/dv/env/gpio_env_cfg.sv b/hw/ip/gpio/dv/env/gpio_env_cfg.sv index c8af480a21b311..e9e269c8d4cbe9 100644 --- a/hw/ip/gpio/dv/env/gpio_env_cfg.sv +++ b/hw/ip/gpio/dv/env/gpio_env_cfg.sv @@ -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; @@ -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 diff --git a/hw/ip/gpio/dv/env/gpio_env_pkg.sv b/hw/ip/gpio/dv/env/gpio_env_pkg.sv index 1c94585f248353..d6d8ecb371fd2d 100644 --- a/hw/ip/gpio/dv/env/gpio_env_pkg.sv +++ b/hw/ip/gpio/dv/env/gpio_env_pkg.sv @@ -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; diff --git a/hw/ip/gpio/dv/env/gpio_scoreboard.sv b/hw/ip/gpio/dv/env/gpio_scoreboard.sv index 26f53a7abbe946..8d841bb3fdcc75 100644 --- a/hw/ip/gpio/dv/env/gpio_scoreboard.sv +++ b/hw/ip/gpio/dv/env/gpio_scoreboard.sv @@ -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; @@ -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); @@ -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 @@ -360,6 +366,56 @@ 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_in.sampled_straps.data) + // Check the register hw_straps_data_in_valid + `DV_CHECK_CASE_EQ('b1, + cfg.straps_vif_inst.straps_port_in.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) && @@ -561,6 +617,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 @@ -804,6 +861,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 diff --git a/hw/ip/gpio/dv/env/seq_lib/gpio_rand_straps_vseq.sv b/hw/ip/gpio/dv/env/seq_lib/gpio_rand_straps_vseq.sv new file mode 100644 index 00000000000000..568c9244dc3bc6 --- /dev/null +++ b/hw/ip/gpio/dv/env/seq_lib/gpio_rand_straps_vseq.sv @@ -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 diff --git a/hw/ip/gpio/dv/env/seq_lib/gpio_vseq_list.sv b/hw/ip/gpio/dv/env/seq_lib/gpio_vseq_list.sv index fd508cad328b8f..ab7a840ca9d854 100644 --- a/hw/ip/gpio/dv/env/seq_lib/gpio_vseq_list.sv +++ b/hw/ip/gpio/dv/env/seq_lib/gpio_vseq_list.sv @@ -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" diff --git a/hw/ip/gpio/dv/gpio_sim.core b/hw/ip/gpio/dv/gpio_sim.core index a33d0dc74f66e4..325079ca43de6d 100644 --- a/hw/ip/gpio/dv/gpio_sim.core +++ b/hw/ip/gpio/dv/gpio_sim.core @@ -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 diff --git a/hw/ip/gpio/dv/gpio_sim_cfg.hjson b/hw/ip/gpio/dv/gpio_sim_cfg.hjson index 6a8910a7669541..ccb899ee65e262 100644 --- a/hw/ip/gpio/dv/gpio_sim_cfg.hjson +++ b/hw/ip/gpio/dv/gpio_sim_cfg.hjson @@ -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 @@ -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. diff --git a/hw/ip/gpio/dv/interfaces/gpio_if.core b/hw/ip/gpio/dv/interfaces/gpio_if.core new file mode 100644 index 00000000000000..c3d4a82ce3654f --- /dev/null +++ b/hw/ip/gpio/dv/interfaces/gpio_if.core @@ -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 diff --git a/hw/ip/gpio/dv/interfaces/gpio_straps_if.sv b/hw/ip/gpio/dv/interfaces/gpio_straps_if.sv new file mode 100644 index 00000000000000..7a86eb9521215b --- /dev/null +++ b/hw/ip/gpio/dv/interfaces/gpio_straps_if.sv @@ -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 diff --git a/hw/ip/gpio/dv/tb/tb.sv b/hw/ip/gpio/dv/tb/tb.sv index 94e8ebac0b7c09..df01b937be127c 100644 --- a/hw/ip/gpio/dv/tb/tb.sv +++ b/hw/ip/gpio/dv/tb/tb.sv @@ -11,8 +11,6 @@ module tb; import gpio_env_pkg::*; import gpio_test_pkg::*; import gpio_reg_pkg::*; - import gpio_pkg::*; - // macro includes `include "uvm_macros.svh" `include "dv_macros.svh" @@ -24,6 +22,8 @@ module tb; wire [NUM_GPIOS-1:0] gpio_oe; wire [NUM_GPIOS-1:0] gpio_intr; wire [NUM_MAX_INTERRUPTS-1:0] interrupts; + gpio_straps_t sampled_straps; + wire strap_en; `DV_ALERT_IF_CONNECT() @@ -33,6 +33,7 @@ module tb; .rst_n(rst_n) ); pins_if #(NUM_MAX_INTERRUPTS) intr_if (.pins(interrupts)); + gpio_straps_if straps_if_inst (); tl_if tl_if ( .clk (clk), .rst_n(rst_n) @@ -52,9 +53,8 @@ module tb; .clk_i (clk), .rst_ni(rst_n), - // TODO: need to test snapshot functionality - .strap_en_i(1'b0), - .sampled_straps_o(), + .strap_en_i(straps_if_inst.strap_en), + .sampled_straps_o(straps_if_inst.sampled_straps), .tl_i(tl_if.h2d), .tl_o(tl_if.d2h), @@ -69,6 +69,9 @@ module tb; .cio_gpio_en_o (gpio_oe) ); + assign straps_if_inst.clk = clk; + assign straps_if_inst.rst_n = rst_n; + assign interrupts[NUM_GPIOS-1:0] = gpio_intr; // gpio pins are represented by bi-directional gpio_if interface @@ -85,6 +88,7 @@ module tb; uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if); uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if); uvm_config_db#(virtual pins_if #(NUM_GPIOS))::set(null, "*.env", "gpio_vif", gpio_if); + uvm_config_db#(virtual gpio_straps_if)::set(null, "*.*", "straps_vif", straps_if_inst); $timeformat(-12, 0, " ps", 12); run_test(); end diff --git a/hw/ip/gpio/dv/tests/gpio_base_test.sv b/hw/ip/gpio/dv/tests/gpio_base_test.sv index e12c37d4c78eeb..b0484c7ec2f71c 100644 --- a/hw/ip/gpio/dv/tests/gpio_base_test.sv +++ b/hw/ip/gpio/dv/tests/gpio_base_test.sv @@ -1,16 +1,25 @@ // Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 - class gpio_base_test extends cip_base_test #( .ENV_T(gpio_env), .CFG_T(gpio_env_cfg) ); `uvm_component_utils(gpio_base_test) - `uvm_component_new - + straps_vif straps_vif_inst; // Virtual interface + function new(string name, uvm_component parent); + super.new(name, parent); + endfunction + task reset_phase(uvm_phase phase); + phase.raise_objection(this); + // Initialize inputs + straps_vif_inst.strap_en = 0; + phase.drop_objection(this); + endtask virtual function void build_phase(uvm_phase phase); super.build_phase(phase); + if (!uvm_config_db#(straps_vif)::get(this, "*.*", "straps_vif", straps_vif_inst)) begin + `uvm_fatal("SEQ", "Virtual interface straps_vif_inst is not set") + end endfunction : build_phase - endclass : gpio_base_test diff --git a/hw/ip/gpio/rtl/gpio.sv b/hw/ip/gpio/rtl/gpio.sv index d47f5fb4f4c1fc..e2598bcfb54e23 100644 --- a/hw/ip/gpio/rtl/gpio.sv +++ b/hw/ip/gpio/rtl/gpio.sv @@ -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;