[gpio dv] GPIO Functional Coverage Updates

1. cip_base_env_cov.sv: Common covergroup for interrupt pins
2. gpio_env_cov.sv: Optimize covergroup creation part by
   enclosing covergroups definitions inside dedicated class,
   and having arrrays of each class type on per pin, per
   register name basis.
3. gpio_scoreboard.sv: Modified coverage sampling based on
   above changes.
4. gpio_base_vseq.sv: Specify function set_gpio_pulls() to be
   of void return type.
diff --git a/hw/dv/sv/cip_lib/cip_base_env_cov.sv b/hw/dv/sv/cip_lib/cip_base_env_cov.sv
index 8d3e16c..ca02b55 100644
--- a/hw/dv/sv/cip_lib/cip_base_env_cov.sv
+++ b/hw/dv/sv/cip_lib/cip_base_env_cov.sv
@@ -29,9 +29,22 @@
   cross cp_intr, cp_intr_test, cp_intr_en, cp_intr_state {
     illegal_bins test_0_state_1 = binsof(cp_intr_test) intersect {0} &&
                                   binsof(cp_intr_state) intersect {1};
+    illegal_bins test_1_state_0 = binsof(cp_intr_test) intersect {1} &&
+                                  binsof(cp_intr_state) intersect {0};
   }
 endgroup
 
+covergroup intr_pins_covergroup (uint num_interrupts) with function sample(uint intr_pin, bit intr_pin_value);
+  cp_intr_pin: coverpoint intr_pin {
+    bins all_pins[] = {[0:num_interrupts-1]};
+  }
+  cp_intr_pin_value: coverpoint intr_pin_value {
+    bins values[] = {0, 1};
+    bins transitions[] = (0 => 1), (1 => 0);
+  }
+  cp_intr_pins_all_values: cross cp_intr_pin, cp_intr_pin_value;
+endgroup
+
 covergroup alert_covergroup (uint num_alerts) with function sample(uint alert);
   cp_alert: coverpoint alert {
     bins all_values[] = {[0:num_alerts-1]};
@@ -43,6 +56,7 @@
 
   intr_covergroup      intr_cg;
   intr_test_covergroup intr_test_cg;
+  intr_pins_covergroup intr_pins_cg;
   alert_covergroup     alert_cg;
 
   `uvm_component_new
@@ -50,8 +64,9 @@
   virtual function void build_phase(uvm_phase phase);
     super.build_phase(phase);
     if (cfg.num_interrupts != 0) begin
-      intr_cg       = new(cfg.num_interrupts);
-      intr_test_cg  = new(cfg.num_interrupts);
+      intr_cg      = new(cfg.num_interrupts);
+      intr_test_cg = new(cfg.num_interrupts);
+      intr_pins_cg = new(cfg.num_interrupts);
     end
     if (cfg.num_alerts != 0) alert_cg = new(cfg.num_alerts);
   endfunction
diff --git a/hw/ip/gpio/dv/env/gpio_env_cov.sv b/hw/ip/gpio/dv/env/gpio_env_cov.sv
index 0db3496..4dff5c3 100644
--- a/hw/ip/gpio/dv/env/gpio_env_cov.sv
+++ b/hw/ip/gpio/dv/env/gpio_env_cov.sv
@@ -2,64 +2,139 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-// Generic covergroup definitions
-covergroup gpio_generic_cg(string name) with function sample(bit value);
-  option.per_instance = 1;
-  option.name = name;
-  cp_value: coverpoint value;
-  cp_transitions: coverpoint value {
-    bins rising  = (0 => 1);
-    bins falling = (1 => 0);
-  }
-endgroup : gpio_generic_cg
+class gpio_generic_cov_obj extends uvm_object;
+  `uvm_object_utils(gpio_generic_cov_obj)
 
-covergroup gpio_intr_type_en_state_cg(string name) with function sample(bit intr_type,
-                                                                        bit intr_en,
-                                                                        bit intr_state);
-  option.per_instance = 1;
-  option.name = name;
-  cp_cross_intr_type_en_state: cross intr_type, intr_en, intr_state {
-    ignore_bins intr_type_disabled = binsof(intr_type) intersect {0};
-  }
-endgroup : gpio_intr_type_en_state_cg
+  // Covergroup: generic_cg
+  // Generic covergroup definition
+  covergroup generic_cg(string name) with function sample(bit value);
+    option.per_instance = 1;
+    option.name = name;
+    cp_value: coverpoint value;
+    cp_transitions: coverpoint value {
+      bins rising  = (0 => 1);
+      bins falling = (1 => 0);
+    }
+  endgroup : generic_cg
+
+  // Function: new
+  function new(string name="gpio_generic_cov");
+    super.new(name);
+    generic_cg = new(name);
+  endfunction : new
+
+endclass : gpio_generic_cov_obj
+
+class gpio_intr_type_cov_obj extends uvm_object;
+  `uvm_object_utils(gpio_intr_type_cov_obj)
+
+  // Covergroup: intr_type_cg
+  // Covergroup for different interrupt types based on "Interrupt Control" registers in
+  // gpio. This group samples combination of interrupt type, interrupt enable and
+  // interrupt state, on per bit basis.
+  covergroup intr_type_cg(string name) with function sample(bit type_ctrl_en,
+                                                            bit intr_en,
+                                                            bit intr_state);
+    option.per_instance = 1;
+    option.name = name;
+    cp_cross_type_en_state: cross type_ctrl_en, intr_en, intr_state {
+      ignore_bins intr_type_disabled = binsof(type_ctrl_en) intersect {0};
+    }
+  endgroup : intr_type_cg
+
+  // Function: new
+  function new(string name="gpio_intr_type_cov_obj");
+    super.new(name);
+    intr_type_cg = new(name);
+  endfunction : new
+endclass : gpio_intr_type_cov_obj
+
+class gpio_two_vars_generic_cov_obj extends uvm_object;
+  `uvm_object_utils(gpio_two_vars_generic_cov_obj)
+
+  // Covergroup: var1_var2_cg
+  // Generic covergroup that samples two bit variables and
+  // looks for their individual coverage as well as cross coverage.
+  covergroup var1_var2_cg(string name) with function sample(bit var1, bit var2);
+    option.per_instance = 1;
+    option.name = name;
+    cp_var1: coverpoint var1;
+    cp_var2: coverpoint var2;
+    cp_var1_var2_cross: cross cp_var1, cp_var2;
+  endgroup : var1_var2_cg
+
+  // Function: new
+  function new(string name="gpio_two_vars_generic_cov_obj");
+    super.new(name);
+    var1_var2_cg = new(name);
+  endfunction : new
+endclass : gpio_two_vars_generic_cov_obj
 
 class gpio_env_cov extends cip_base_env_cov #(.CFG_T(gpio_env_cfg));
   `uvm_component_utils(gpio_env_cov)
 
-  // Per pin coverage for values '0' and '1' and transitions
-  gpio_generic_cg gpio_pin_values_cg[NUM_GPIOS];
+  // Array of coverage objects for per pin coverage for gpio pin values
+  gpio_generic_cov_obj gpio_pin_values_cov_obj[NUM_GPIOS];
   // Interrupt State (Interrupt bit getting set and cleared)
-  gpio_generic_cg intr_state_cg[TL_DW];
+  gpio_generic_cov_obj intr_state_cov_obj[NUM_GPIOS];
   // Interrupt Control Enable registers' values
-  gpio_generic_cg intr_ctrl_en_rising_cg[TL_DW];
-  gpio_generic_cg intr_ctrl_en_falling_cg[TL_DW];
-  gpio_generic_cg intr_ctrl_en_lvlhigh_cg[TL_DW];
-  gpio_generic_cg intr_ctrl_en_lvllow_cg[TL_DW];
+  gpio_generic_cov_obj intr_ctrl_en_cov_objs[NUM_GPIOS][string];
   // Different gpio interrupt types' occurrences
-  gpio_intr_type_en_state_cg rising_edge_intr_event_cg[TL_DW];
-  gpio_intr_type_en_state_cg falling_edge_intr_event_cg[TL_DW];
-  gpio_intr_type_en_state_cg lvlhigh_intr_event_cg[TL_DW];
-  gpio_intr_type_en_state_cg lvllow_intr_event_cg[TL_DW];
+  gpio_intr_type_cov_obj intr_event_type_cov_objs[NUM_GPIOS][string];
+  // Per bit coverage on *out* and *oe* registers
+  gpio_generic_cov_obj out_oe_cov_objs[NUM_GPIOS][string];
+
+  // Coverage on data and mask fields of masked* registers
+  gpio_two_vars_generic_cov_obj out_oe_mask_data_cov_objs[NUM_GPIOS/2][string];
+  // Coverage on effective values of DATA_OUT and DATA_OE
+  gpio_two_vars_generic_cov_obj data_out_data_oe_cov_obj[NUM_GPIOS];
+  // data_in register per bit value coverage
+  gpio_generic_cov_obj data_in_cov_obj[NUM_GPIOS];
 
   function new(string name, uvm_component parent);
     super.new(name, parent);
-    // Create coverage for each gpio pin value
-    foreach (gpio_pin_values_cg[each_pin]) begin
-      gpio_pin_values_cg [each_pin] = new($sformatf("gpio_pin-%0d", each_pin));
-    end
-    // Create coverage for interrupt control policies and state
-    for (uint each_bit = 0; each_bit < TL_DW; each_bit++) begin
-      intr_state_cg[each_bit] = new($sformatf("intr_state_cg%0d", each_bit));
-      intr_ctrl_en_rising_cg[each_bit] = new($sformatf("intr_ctrl_en_rising_cg%0d", each_bit));
-      intr_ctrl_en_falling_cg[each_bit] = new($sformatf("intr_ctrl_en_falling_cg%0d", each_bit));
-      intr_ctrl_en_lvlhigh_cg[each_bit] = new($sformatf("intr_ctrl_en_lvlhigh_cg%0d", each_bit));
-      intr_ctrl_en_lvllow_cg [each_bit] = new($sformatf("intr_ctrl_en_lvllow_cg%0d", each_bit));
-      rising_edge_intr_event_cg[each_bit] = new($sformatf("rising_edge_intr_event_cg%0d",
-                                                           each_bit));
-      falling_edge_intr_event_cg[each_bit] = new($sformatf("falling_edge_intr_event_cg%0d",
-                                                           each_bit));
-      lvlhigh_intr_event_cg[each_bit] = new($sformatf("lvlhigh_intr_event_cg%0d", each_bit));
-      lvllow_intr_event_cg[each_bit] = new($sformatf("lvllow_intr_event_cg%0d", each_bit));
+    begin
+      string intr_types[4] = '{"rising", "falling", "lvlhigh", "lvllow"};
+      string out_oe_reg_names[6] = '{"direct_out",
+                                     "direct_oe",
+                                     "masked_out_lower",
+                                     "masked_oe_lower",
+                                     "masked_out_upper",
+                                     "masked_oe_upper"};
+      foreach (intr_state_cov_obj[each_pin]) begin
+        // Create coverage for each gpio pin values and transitions
+        gpio_pin_values_cov_obj[each_pin] = new($sformatf("gpio_values_cov_obj_pin%0d", each_pin));
+        // Create per pin coverage for interrupt state values and transitions
+        intr_state_cov_obj[each_pin] = new($sformatf("intr_state_cov_obj_pin%0d", each_pin));
+        // Create per pin coverage interrupts
+        foreach(intr_types[each_type]) begin
+          // Per pin coverage for "Intrrupt Control Enable" values
+          // and transitions for each type of interrupt
+          intr_ctrl_en_cov_objs[each_pin][{"intr_ctrl_en_", intr_types[each_type]}] =
+              new({"intr_ctrl_en_", intr_types[each_type], $sformatf("_pin%0d_cov", each_pin)});
+          // Per pin coverage for different types of interrupt event occurrences
+          intr_event_type_cov_objs[each_pin][{"intr_event_", intr_types[each_type]}] =
+              new({"intr_event_", intr_types[each_type], $sformatf("_pin%0d", each_pin)});
+        end
+        // Per pin coverage for values of different *out* and *oe* registers
+        foreach (out_oe_reg_names[each_reg]) begin
+          out_oe_cov_objs[each_pin][out_oe_reg_names[each_reg]] =
+            new({out_oe_reg_names[each_reg], $sformatf("_cov_obj_pin%0d", each_pin)});
+        end
+        data_out_data_oe_cov_obj[each_pin] = new($sformatf("data_out_data_oe_cov_obj_pin%0d",
+                                                           each_pin));
+        data_in_cov_obj[each_pin] = new($sformatf("data_in_cov_obj_pin%0d", each_pin));
+      end
+      // Per pin coverage and cross coverage for mask and data
+      // fields within masked_* registers
+      foreach (out_oe_mask_data_cov_objs[each_pin]) begin
+        foreach (out_oe_reg_names[each_reg]) begin
+          if (!uvm_re_match("masked*", out_oe_reg_names[each_reg])) begin
+            out_oe_mask_data_cov_objs[each_pin][out_oe_reg_names[each_reg]] =
+                new({out_oe_reg_names[each_reg], $sformatf("_mask_data_cov_obj_pin%0d", each_pin)});
+          end
+        end
+      end
     end
   endfunction : new
 
diff --git a/hw/ip/gpio/dv/env/gpio_scoreboard.sv b/hw/ip/gpio/dv/env/gpio_scoreboard.sv
index 5fe1b23..7a83581 100644
--- a/hw/ip/gpio/dv/env/gpio_scoreboard.sv
+++ b/hw/ip/gpio/dv/env/gpio_scoreboard.sv
@@ -40,7 +40,10 @@
   // Task: run_phase
   task run_phase(uvm_phase phase);
     super.run_phase(phase);
-    monitor_gpio_i();
+    fork
+      monitor_gpio_i();
+      monitor_gpio_interrupt_pins();
+    join_none
   endtask
 
   // Task : process_tl_access
@@ -114,8 +117,9 @@
                   intr_state_write_to_clear_update.reg_value[each_bit] == 1'b1 &&
                   item.a_data[each_bit] == 1'b1) begin
                 intr_state_write_to_clear_update.reg_value[each_bit] = 1'b0;
+                // Coverage Sampling: gpio interrupt cleared
                 if (cfg.en_cov) begin
-                  cov.intr_state_cg[each_bit].sample(1'b0);
+                  cov.intr_state_cov_obj[each_bit].generic_cg.sample(1'b0);
                 end
               end
             end
@@ -140,6 +144,25 @@
           if (csr.get_name() == "intr_test") begin
             // Store the written value as it is WO register
             last_intr_test_event = item.a_data;
+          end else begin
+            // Coverage Sampling: coverage on *out* and *oe* register values
+            if (cfg.en_cov && (!uvm_re_match("*out*", csr.get_name()) ||
+                               !uvm_re_match("*oe*", csr.get_name()))) begin
+              for (uint each_pin = 0; each_pin < NUM_GPIOS; each_pin++) begin
+
+                cov.out_oe_cov_objs[each_pin][csr.get_name()].generic_cg.sample(
+                    item.a_data[each_pin]);
+              end
+              // Coverage Sampling: Cross coverage on mask and data within masked_* registers
+              if (!uvm_re_match("masked*", csr.get_name())) begin
+                bit [(NUM_GPIOS/2) - 1:0] mask, data;
+                {mask, data} = item.d_data;
+                for (uint each_pin = 0; each_pin < NUM_GPIOS/2; each_pin++) begin
+                  cov.out_oe_mask_data_cov_objs[each_pin][csr.get_name()].var1_var2_cg.sample(
+                      mask[each_pin], data[each_pin]);
+                end
+              end
+            end
           end
           csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), .be(item.a_mask));
         end
@@ -176,10 +199,10 @@
       `uvm_info(`gfn, $sformatf("cfg.gpio_vif.pins = %0h, under_reset = %0b",
                                 cfg.gpio_vif.pins, under_reset), UVM_HIGH)
       if (under_reset == 1'b0) begin
-        // Coverage Sampling-1: gpio pin values' coverage
+        // Coverage Sampling: gpio pin values' coverage
         if (cfg.en_cov) begin
-          foreach (cov.gpio_pin_values_cg[each_pin]) begin
-            cov.gpio_pin_values_cg[each_pin].sample(cfg.gpio_vif.pins[each_pin]);
+          foreach (cov.gpio_pin_values_cov_obj[each_pin]) begin
+            cov.gpio_pin_values_cov_obj[each_pin].generic_cg.sample(cfg.gpio_vif.pins[each_pin]);
           end
         end
         // evaluate gpio input driven to dut
@@ -271,6 +294,22 @@
 
   endtask : monitor_gpio_i
 
+  // Task: monitor_gpio_interrupt_pins
+  virtual task monitor_gpio_interrupt_pins();
+    forever begin : monitor_gpio_intr
+      @(cfg.intr_vif.pins or under_reset) begin
+        if (under_reset == 0) begin
+          if (cfg.en_cov) begin
+            // Coverage Sampling: gpio interrupt pin values and transitions
+            for (uint each_pin = 0; each_pin < NUM_GPIOS; each_pin++) begin
+              cov.intr_pins_cg.sample(each_pin, cfg.intr_vif.pins[each_pin]);
+            end
+          end
+        end
+      end
+    end
+  endtask : monitor_gpio_interrupt_pins
+
   // Function: actual_gpio_i_activity
   function bit actual_gpio_i_activity();
     return ~((prv_gpio_i_pins_o === cfg.gpio_vif.pins_o) &&
@@ -454,6 +493,12 @@
         current_data_in_update.reg_value = pred_val_gpio_pins;
         current_data_in_update.eval_time = $time;
         data_in_update_queue.push_back(current_data_in_update);
+        // Coverage Sampling: data_in register coverage
+        if (cfg.en_cov) begin
+          for (uint each_bit = 0; each_bit < NUM_GPIOS; each_bit++) begin
+            cov.data_in_cov_obj[each_bit].generic_cg.sample(pred_val_gpio_pins[each_bit]);
+          end
+        end
       end
       // If update was due to register write, we can call predict right away
       if (csr != null) begin
@@ -497,13 +542,17 @@
       end
     end
 
-    // Coverage Sampling-2: gpio interrupt types
+    // Coverage Sampling: gpio interrupt types
     if (cfg.en_cov) begin
       foreach (intr_ctrl_en_rising[each_bit]) begin
-        cov.intr_ctrl_en_rising_cg [each_bit].sample(intr_ctrl_en_rising[each_bit]);
-        cov.intr_ctrl_en_falling_cg[each_bit].sample(intr_ctrl_en_falling[each_bit]);
-        cov.intr_ctrl_en_lvlhigh_cg[each_bit].sample(intr_ctrl_en_lvlhigh[each_bit]);
-        cov.intr_ctrl_en_lvllow_cg [each_bit].sample(intr_ctrl_en_lvllow[each_bit]);
+        cov.intr_ctrl_en_cov_objs[each_bit]["intr_ctrl_en_rising"].generic_cg.sample(
+            intr_ctrl_en_rising[each_bit]);
+        cov.intr_ctrl_en_cov_objs[each_bit]["intr_ctrl_en_falling"].generic_cg.sample(
+            intr_ctrl_en_falling[each_bit]);
+        cov.intr_ctrl_en_cov_objs[each_bit]["intr_ctrl_en_lvlhigh"].generic_cg.sample(
+            intr_ctrl_en_lvlhigh[each_bit]);
+        cov.intr_ctrl_en_cov_objs[each_bit]["intr_ctrl_en_lvllow"].generic_cg.sample(
+            intr_ctrl_en_lvllow[each_bit]);
         // Interrupt Test coverage
         cov.intr_test_cg.sample(each_bit,
                                 last_intr_test_event[each_bit],
@@ -535,15 +584,18 @@
           end
         end
       end
-      // Cross coverage of (edge tiggered intr type)x(enable)x(state) when type is enabled
+      // Coverage Sampling: Cross coverage of (edge tiggered intr type)x(enable)x(state)
+      // when type is enabled
       if (cfg.en_cov) begin
         foreach (rising_edge_intr_events[each_bit]) begin
-          cov.rising_edge_intr_event_cg[each_bit].sample(intr_ctrl_en_rising[each_bit],
-                                                         intr_enable[each_bit],
-                                                         rising_edge_intr_events[each_bit]);
-          cov.falling_edge_intr_event_cg[each_bit].sample(intr_ctrl_en_falling[each_bit],
-                                                          intr_enable[each_bit],
-                                                          falling_edge_intr_events[each_bit]);
+          cov.intr_event_type_cov_objs[each_bit]["intr_event_rising"].intr_type_cg.sample(
+              intr_ctrl_en_rising[each_bit],
+              intr_enable[each_bit],
+              rising_edge_intr_events[each_bit]);
+          cov.intr_event_type_cov_objs[each_bit]["intr_event_falling"].intr_type_cg.sample(
+              intr_ctrl_en_falling[each_bit],
+              intr_enable[each_bit],
+              falling_edge_intr_events[each_bit]);
         end
       end
     end
@@ -565,24 +617,30 @@
           end
         end
       end
-      // Cross coverage of (edge tiggered intr type)x(enable)x(state) when type is enabled
+      // Coverage Sampling: Cross coverage of (edge tiggered intr type)x(enable)x(state)
+      // when type is enabled
       if (cfg.en_cov) begin
         foreach (lvlhigh_intr_events[each_bit]) begin
-          cov.lvlhigh_intr_event_cg[each_bit].sample(intr_ctrl_en_lvlhigh[each_bit],
-                                                     intr_enable[each_bit],
-                                                     lvlhigh_intr_events[each_bit]);
-          cov.lvllow_intr_event_cg[each_bit].sample(intr_ctrl_en_lvllow[each_bit],
-                                                    intr_enable[each_bit],
-                                                    lvllow_intr_events[each_bit]);
+          cov.intr_event_type_cov_objs[each_bit]["intr_event_lvlhigh"].intr_type_cg.sample(
+              intr_ctrl_en_lvlhigh[each_bit],
+              intr_enable[each_bit],
+              lvlhigh_intr_events[each_bit]);
+          cov.intr_event_type_cov_objs[each_bit]["intr_event_lvllow"].intr_type_cg.sample(
+              intr_ctrl_en_lvllow[each_bit],
+              intr_enable[each_bit],
+              lvllow_intr_events[each_bit]);
         end
       end
     end
     // 3. Apply effect of "Interrupt Test"
     exp_intr_status |= last_intr_test_event;
+    // Coverage Sampling: Coverage on Interrupt Index, Interrupt Enable,
+    // Interrupt Status and their cross coverage
     if (cfg.en_cov) begin
       foreach (exp_intr_status[each_bit]) begin
         cov.intr_cg.sample(each_bit, intr_enable[each_bit], exp_intr_status[each_bit]);
-        cov.intr_state_cg[each_bit].sample(last_intr_update_except_clearing[each_bit]);
+        cov.intr_state_cov_obj[each_bit].generic_cg.sample(
+            last_intr_update_except_clearing[each_bit]);
       end
     end
     // Clear last_intr_test_event
@@ -634,6 +692,8 @@
     end
     ral.masked_out_upper.mask.predict(.value(mask), .kind(UVM_PREDICT_WRITE));
     ral.masked_out_upper.data.predict(.value(data), .kind(UVM_PREDICT_WRITE));
+    // Coverage Sampling: Coverage on DATA_OUT values and its combinations with DATA_OE
+    sample_data_out_data_oe_coverage();
   endfunction : update_gpio_out_regs
 
   // Function : update_gpio_oe_regs
@@ -661,8 +721,20 @@
     end
     ral.masked_oe_upper.mask.predict(.value(mask), .kind(UVM_PREDICT_WRITE));
     ral.masked_oe_upper.data.predict(.value(data), .kind(UVM_PREDICT_WRITE));
+    // Coverage Sampling: Coverage on DATA_OUT values and its combinations with DATA_OE
+    sample_data_out_data_oe_coverage();
   endfunction : update_gpio_oe_regs
 
+  // Function: sample_data_out_data_oe_coverage
+  function void sample_data_out_data_oe_coverage();
+    if (cfg.en_cov) begin
+      for (uint each_bit = 0; each_bit < NUM_GPIOS; each_bit++) begin
+        cov.data_out_data_oe_cov_obj[each_bit].var1_var2_cg.sample(data_out[each_bit],
+                                                                   data_oe[each_bit]);
+      end
+    end
+  endfunction : sample_data_out_data_oe_coverage
+
   // Function: reset
   virtual function void reset(string kind = "HARD");
     super.reset(kind);
diff --git a/hw/ip/gpio/dv/env/seq_lib/gpio_base_vseq.sv b/hw/ip/gpio/dv/env/seq_lib/gpio_base_vseq.sv
index 69c5bcf..7db4e09 100644
--- a/hw/ip/gpio/dv/env/seq_lib/gpio_base_vseq.sv
+++ b/hw/ip/gpio/dv/env/seq_lib/gpio_base_vseq.sv
@@ -34,7 +34,7 @@
   // from extended sequence.
   // Note: This function does not check whether only one of 'pu' and 'pd' is passed 1.
   //       If we pass both pu and pd to be 1, gpio pullup will be used.
-  protected function set_gpio_pulls(bit pu = 1'b1, bit pd = 1'b0);
+  protected function void set_gpio_pulls(bit pu = 1'b1, bit pd = 1'b0);
     bit no_pullup_pulldown;
     cfg.pullup_en   = pu;
     cfg.pulldown_en = pd;