[dv] Add a macro to constrain Mubi type randomization

Simplify the code of writing constraint of MuBi type variable
Signed-off-by: Weicai Yang <weicai@google.com>
diff --git a/hw/dv/sv/cip_lib/cip_base_pkg.sv b/hw/dv/sv/cip_lib/cip_base_pkg.sv
index e2df222..3150601 100644
--- a/hw/dv/sv/cip_lib/cip_base_pkg.sv
+++ b/hw/dv/sv/cip_lib/cip_base_pkg.sv
@@ -72,6 +72,39 @@
     end
   endfunction
 
+  // Create functions that return a random value for the mubi type variable, based on weight
+  // settings
+  //
+  // The function is `get_rand_mubi4|8|16_val(t_weight, f_weight, other_weight)`
+  // t_weight: randomization weight of the value True
+  // f_weight: randomization weight of the value False
+  // other_weight: randomization weight of values other than True or False
+  `define _DV_MUBI_RAND_VAL(WIDTH_) \
+    function automatic mubi``WIDTH_``_e get_rand_mubi``WIDTH_``_val( \
+        int t_weight = 2, int f_weight = 2, int other_weight = 1); \
+      bit[WIDTH_-1:0] val; \
+      `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(val, \
+          `DV_MUBI``WIDTH_``_DIST(val, t_weight, f_weight, other_weight), , msg_id) \
+      return mubi``WIDTH_``_e'(val); \
+    endfunction
+
+  // Create function - get_rand_mubi4_val
+  `_DV_MUBI_RAND_VAL(4)
+  // Create function - get_rand_mubi8_val
+  `_DV_MUBI_RAND_VAL(8)
+  // Create function - get_rand_mubi16_val
+  `_DV_MUBI_RAND_VAL(16)
+
+  `undef _DV_MUBI_RAND_VAL
+
+  // Currently lc_tx_e is exactly the same as mubi4_e. create a separate function in case these
+  // 2 types are changed differently in the future
+  function automatic lc_ctrl_pkg::lc_tx_e get_rand_lc_tx_val(int t_weight = 2,
+                                                             int f_weight = 2,
+                                                             int other_weight = 1);
+    return lc_ctrl_pkg::lc_tx_e'(get_rand_mubi4_val(t_weight, f_weight, other_weight));
+  endfunction
+
   // package sources
   // base env
   `include "cip_base_env_cfg.sv"
diff --git a/hw/dv/sv/cip_lib/cip_macros.svh b/hw/dv/sv/cip_lib/cip_macros.svh
index d603469..fd5465f 100644
--- a/hw/dv/sv/cip_lib/cip_macros.svh
+++ b/hw/dv/sv/cip_lib/cip_macros.svh
@@ -47,4 +47,44 @@
   end
 `endif
 
+// A macro to simplify the distribution constraint of mubi type variable
+// Don't use this macro directly, use DV_MUBI4|8|16_DIST
+`ifndef _DV_MUBI_DIST
+`define _DV_MUBI_DIST(VAR_, TRUE_, FALSE_, T_WEIGHT_, F_WEIGHT_, OTHER_WEIGHT_) \
+  // OTHER_WEIGHT_ must be divisible by 3 as there are ranges for values other than true and false \
+  if (TRUE_ > FALSE_) { \
+    VAR_ dist {TRUE_  :/ T_WEIGHT_ * 3, \
+               FALSE_ :/ F_WEIGHT_ * 3, \
+               [0 : FALSE_ - 1]         :/ OTHER_WEIGHT_, \
+               [FALSE_ + 1 : TRUE_ - 1] :/ OTHER_WEIGHT_, \
+               [TRUE_ + 1 : $]          :/ OTHER_WEIGHT_}; \
+  } else { \
+    VAR_ dist {TRUE_  :/ T_WEIGHT_ * 3, \
+               FALSE_ :/ F_WEIGHT_ * 3, \
+               [0 : TRUE_ - 1]          :/ OTHER_WEIGHT_, \
+               [TRUE_ + 1 : FALSE_ - 1] :/ OTHER_WEIGHT_, \
+               [FALSE_+ 1 : $]          :/ OTHER_WEIGHT_}; \
+  }
+`endif
+
+// inputs of these macros
+// VAR: the mubi variable
+// T_WEIGHT_: randomization weight of the value True
+// F_WEIGHT_: randomization weight of the value False
+// OTHER_WEIGHT_: randomization weight of values other than True or False
+`ifndef DV_MUBI4_DIST
+`define DV_MUBI4_DIST(VAR_, T_WEIGHT_ = 2, F_WEIGHT_ = 2, OTHER_WEIGHT_ = 1) \
+  `_DV_MUBI_DIST(VAR_, MuBi4True, MuBi4False, T_WEIGHT_, F_WEIGHT_, OTHER_WEIGHT_)
+`endif
+
+`ifndef DV_MUBI8_DIST
+`define DV_MUBI8_DIST(VAR_, T_WEIGHT_ = 2, F_WEIGHT_ = 2, OTHER_WEIGHT_ = 1) \
+  `_DV_MUBI_DIST(VAR_, MuBi8True, MuBi8False, T_WEIGHT_, F_WEIGHT_, OTHER_WEIGHT_)
+`endif
+
+`ifndef DV_MUBI16_DIST
+`define DV_MUBI16_DIST(VAR_, T_WEIGHT_ = 2, F_WEIGHT_ = 2, OTHER_WEIGHT_ = 1) \
+  `_DV_MUBI_DIST(VAR_, MuBi16True, MuBi16False, T_WEIGHT_, F_WEIGHT_, OTHER_WEIGHT_)
+`endif
+
 `endif // __CIP_MACROS_SVH__