[dv/clkmgr] Update docs and minor refactor

Add coverpoints in the testplan.
Remove extclk_sel_regwen from clkmgr_if.
Fix the type of extclk_sel in clkmgr_if.
Replace clkmgr_vif.wait_clks by clk_rst_vif.wait_clks.
Simplify the constraint for lc_tx_t variable.
Start monitor_ip_clk_en task in clkmgr_scoreboard.

Signed-off-by: Guillermo Maturana <maturana@google.com>
diff --git a/hw/ip/clkmgr/data/clkmgr_testplan.hjson b/hw/ip/clkmgr/data/clkmgr_testplan.hjson
index 479f465..c56a4a9 100644
--- a/hw/ip/clkmgr/data/clkmgr_testplan.hjson
+++ b/hw/ip/clkmgr/data/clkmgr_testplan.hjson
@@ -111,9 +111,33 @@
       tests: []
     }
   ]
-  // The covergroups are arrays, which are yet to be supported by the tools.
   covergroups: [
-    // peri_cg_wrap cover the dependencies of each peripheral clock.
-    // trans_cg_wrap  cover the dependencies of each transactional unit clock.
+    {
+      name: peri_cg
+      desc: '''
+            Collects coverage for each peripheral clock.
+
+            The peripheral clocks depend on a bit in the clk_enables CSR,
+            the ip_clk_en input from pwrmgr, and the scanmode input.
+            This collects the cross of them for each peripheral.
+
+            FIXME This is collected in an array, one instance for each clock,
+            but the dvsim coverage flow doesn't yet support arrays.
+            '''
+    }
+    {
+      name: trans_cg
+      desc: '''
+            Collects coverage for each transactional unit clock.
+
+            The transactional unit clocks depend on a bit in the clk_hints CSR,
+            the ip_clk_en input from pwrmgr, the respective idle input bit from
+            the unit, and the scanmode input.
+            This collects the cross of them for each transactional unit.
+
+            FIXME This is collected in an array, one instance for each clock,
+            but the dvsim coverage flow doesn't yet support arrays.
+            '''
+    }
   ]
 }
diff --git a/hw/ip/clkmgr/dv/env/clkmgr_env_pkg.sv b/hw/ip/clkmgr/dv/env/clkmgr_env_pkg.sv
index 7b6da06..6f0e788 100644
--- a/hw/ip/clkmgr/dv/env/clkmgr_env_pkg.sv
+++ b/hw/ip/clkmgr/dv/env/clkmgr_env_pkg.sv
@@ -14,6 +14,10 @@
   import csr_utils_pkg::*;
   import clkmgr_ral_pkg::*;
 
+  import lc_ctrl_pkg::lc_tx_t;
+  import lc_ctrl_pkg::On;
+  import lc_ctrl_pkg::Off;
+
   // macro includes
   `include "uvm_macros.svh"
   `include "dv_macros.svh"
diff --git a/hw/ip/clkmgr/dv/env/clkmgr_if.sv b/hw/ip/clkmgr/dv/env/clkmgr_if.sv
index 67af1a2..1a4d88f 100644
--- a/hw/ip/clkmgr/dv/env/clkmgr_if.sv
+++ b/hw/ip/clkmgr/dv/env/clkmgr_if.sv
@@ -52,31 +52,22 @@
   } clk_hints_t;
 
   // The CSR values from the testbench side.
-  clk_enables_t clk_enables;
-  clk_hints_t   clk_hints;
-  clk_hints_t   clk_hints_status;
-  logic         extclk_sel_regwen;
-  logic         extclk_sel;
-  logic         jitter_enable;
+  clk_enables_t        clk_enables;
+  clk_hints_t          clk_hints;
+  clk_hints_t          clk_hints_status;
+  lc_ctrl_pkg::lc_tx_t extclk_sel;
+  logic                jitter_enable;
 
-  task automatic wait_clks(int cycles);
-    repeat (cycles) @(posedge clk);
-  endtask
-
-  function automatic void update_extclk_sel_regwen(logic sel_regwen);
-    extclk_sel_regwen = sel_regwen;
+  function automatic void update_extclk_sel(lc_ctrl_pkg::lc_tx_t value);
+    extclk_sel = value;
   endfunction
 
-  function automatic void update_extclk_sel(logic sel);
-    extclk_sel = sel;
+  function automatic void update_clk_enables(clk_enables_t value);
+    clk_enables = value;
   endfunction
 
-  function automatic void update_clk_enables(clk_enables_t ens);
-    clk_enables = ens;
-  endfunction
-
-  function automatic void update_clk_hints(clk_hints_t hints);
-    clk_hints = hints;
+  function automatic void update_clk_hints(clk_hints_t value);
+    clk_hints = value;
   endfunction
 
   function automatic void update_idle(bit [NUM_TRANS-1:0] value);
@@ -87,8 +78,8 @@
     pwr_i.ip_clk_en = value;
   endfunction
 
-  function automatic void update_scanmode(lc_ctrl_pkg::lc_tx_t scm);
-    scanmode_i = scm;
+  function automatic void update_scanmode(lc_ctrl_pkg::lc_tx_t value);
+    scanmode_i = value;
   endfunction
 
   function automatic logic get_clk_status();
diff --git a/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv b/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv
index 9a7c5f9..b41ea1b 100644
--- a/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv
+++ b/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv
@@ -29,6 +29,7 @@
     super.run_phase(phase);
     fork
       monitor_idle();
+      monitor_ip_clk_en();
       monitor_scanmode();
       begin : post_reset
         fork
@@ -179,6 +180,8 @@
     string access_str = write ? "write" : "read";
     string channel_str = channel == AddrChannel ? "address" : "data";
 
+    logic  extclk_sel_regwen = ral.extclk_sel_regwen.get_reset();
+
     // if access was to a valid csr, get the csr handle
     if (csr_addr inside {cfg.csr_addrs[ral_name]}) begin
       csr = ral.default_map.get_reg_by_offset(csr_addr);
@@ -211,10 +214,10 @@
       end
       "extclk_sel_regwen":
         if (addr_phase_write) begin
-          cfg.clkmgr_vif.update_extclk_sel_regwen(item.a_data);
+          extclk_sel_regwen = item.a_data;
         end
       "extclk_sel":
-        if (addr_phase_write) begin
+        if (addr_phase_write && extclk_sel_regwen) begin
           cfg.clkmgr_vif.update_extclk_sel(item.a_data);
         end
       "jitter": begin
diff --git a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv
index 56867ee..179ad75 100644
--- a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv
+++ b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv
@@ -10,18 +10,30 @@
   );
   `uvm_object_utils(clkmgr_base_vseq)
 
+  typedef enum {LcTxTSelOn, LcTxTSelOff, LcTxTSelOther} lc_tx_t_sel_e;
+
+  // This simplifies the constraint blocks.
+  function lc_tx_t get_lc_tx_t_from_sel(lc_tx_t_sel_e sel, lc_tx_t other);
+    case (sel)
+      LcTxTSelOn: return On;
+      LcTxTSelOff: return Off;
+      LcTxTSelOther: return other;
+    endcase
+  endfunction
+
   rand bit ip_clk_en;
   rand bit [NUM_TRANS-1:0] idle;
 
-  // This selects scanmode according to scanmode_sel, which is randomized with weights.
-  rand bit [$bits(lc_ctrl_pkg::lc_tx_t)-1:0] scanmode;
-  typedef enum {SC_ON, SC_OFF, SC_OTHER}     scanmode_sel_e;
-  rand scanmode_sel_e                        scanmode_sel;
-  constraint scanmode_values {
-    (scanmode_sel == SC_ON)    -> scanmode == lc_ctrl_pkg::On;
-    (scanmode_sel == SC_OFF)   -> scanmode == lc_ctrl_pkg::Off;
-    (scanmode_sel == SC_OTHER) -> !(scanmode inside {lc_ctrl_pkg::On, lc_ctrl_pkg::Off});
-    scanmode_sel dist {SC_ON := 4, SC_OFF := 2, SC_OTHER := 2};
+  // This selects scanmode according to sel_scanmode, which is randomized with weights.
+  rand lc_tx_t       scanmode;
+  rand lc_tx_t       scanmode_other;
+  rand lc_tx_t_sel_e sel_scanmode;
+  int                scanmode_on_weight = 8;
+
+  constraint scanmode_c {
+    sel_scanmode dist {LcTxTSelOn := scanmode_on_weight, LcTxTSelOff := 4, LcTxTSelOther := 4};
+    !(scanmode_other inside {On, Off});
+    scanmode == get_lc_tx_t_from_sel(sel_scanmode, scanmode_other);
   }
 
   // various knobs to enable certain routines
@@ -96,7 +108,6 @@
   function void update_csrs_with_reset_values();
     cfg.clkmgr_vif.update_clk_enables(ral.clk_enables.get_reset());
     cfg.clkmgr_vif.update_clk_hints(ral.clk_hints.get_reset());
-    cfg.clkmgr_vif.update_extclk_sel_regwen(ral.extclk_sel_regwen.get_reset());
     cfg.clkmgr_vif.update_extclk_sel(ral.extclk_sel.get_reset());
   endfunction
 
diff --git a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_peri_vseq.sv b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_peri_vseq.sv
index 1cb0f8a..7347f16 100644
--- a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_peri_vseq.sv
+++ b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_peri_vseq.sv
@@ -18,7 +18,7 @@
     for (int i = 0; i < num_trans; ++i) begin
       logic [NUM_PERI-1:0] flipped_enables;
       `DV_CHECK_RANDOMIZE_FATAL(this)
-      cfg.clkmgr_vif.init(.idle(idle), .ip_clk_en(ip_clk_en), .scanmode(scanmode));      
+      cfg.clkmgr_vif.init(.idle(idle), .ip_clk_en(ip_clk_en), .scanmode(scanmode));
 
       csr_wr(.ptr(ral.clk_enables), .value(initial_enables));
 
diff --git a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv
index 1ff77c2..a3ad7ee 100644
--- a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv
+++ b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_smoke_vseq.sv
@@ -10,7 +10,7 @@
 
   constraint enable_ip_clk_en { ip_clk_en == 1'b1; }
   constraint all_busy { idle == '0; }
-  constraint scanmode_off { scanmode_sel == SC_OFF; }
+  constraint scanmode_off { sel_scanmode == LcTxTSelOff; }
 
   task body();
     update_csrs_with_reset_values();
@@ -63,7 +63,7 @@
                    $sformatf("%s hint value cannot drop while busy", descriptor.unit.name()))
 
       `uvm_info(`gfn, $sformatf("Setting %s idle bit", descriptor.unit.name), UVM_MEDIUM)
-      cfg.clkmgr_vif.wait_clks(1);
+      cfg.clk_rst_vif.wait_clks(1);
       idle[trans] = 1'b1;
       cfg.clkmgr_vif.update_idle(idle);
       // Some cycles for the logic to settle.
diff --git a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_trans_vseq.sv b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_trans_vseq.sv
index fa4c72d..e8e3bcb 100644
--- a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_trans_vseq.sv
+++ b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_trans_vseq.sv
@@ -27,20 +27,20 @@
       `uvm_info(`gfn, $sformatf("Updating hints to 0x%0x", initial_hints), UVM_MEDIUM)
       csr_wr(.ptr(ral.clk_hints), .value(initial_hints));
 
-      cfg.clkmgr_vif.wait_clks(5);
+      cfg.clk_rst_vif.wait_clks(5);
       // We expect the status to be determined by hints and idle.
       csr_rd(.ptr(ral.clk_hints_status), .value(value));
       `DV_CHECK_EQ(value, initial_hints | ~idle, "Busy units have status high")
 
       // Clearing idle should make hint_status match hints.
       cfg.clkmgr_vif.update_idle('1);
-      cfg.clkmgr_vif.wait_clks(2);
+      cfg.clk_rst_vif.wait_clks(2);
       csr_rd(.ptr(ral.clk_hints_status), .value(value));
       `DV_CHECK_EQ(value, initial_hints, "All idle: units status matches hints")
 
       // Now enable them all, and the status should also be all ones.
       csr_wr(.ptr(ral.clk_hints), .value('1));
-      cfg.clkmgr_vif.wait_clks(2);
+      cfg.clk_rst_vif.wait_clks(2);
       csr_rd(.ptr(ral.clk_hints_status), .value(value));
       // We expect all units to be on.
       `DV_CHECK_EQ(value, '1, "All idle and all hints high: units status should be high")