@@ -17,6 +17,11 @@ class dv_base_reg_field extends uvm_reg_field;
17
17
// This is used for get_field_by_name
18
18
string alias_name = " " ;
19
19
20
+ // If this field encodes a mubi, this field encodes special access modes such as W1C that cannot
21
+ // be captured with the regular access configuration, since UVM does not model such access modes
22
+ // correctly for mubis.
23
+ string mubi_access = " " ;
24
+
20
25
// Default mubi_width = 0 indicates this register field is not a mubi type.
21
26
protected int mubi_width;
22
27
@@ -58,6 +63,7 @@ class dv_base_reg_field extends uvm_reg_field;
58
63
int unsigned size,
59
64
int unsigned lsb_pos,
60
65
string access,
66
+ string mubi_access,
61
67
bit volatile,
62
68
uvm_reg_data_t reset,
63
69
bit has_reset,
@@ -73,7 +79,7 @@ class dv_base_reg_field extends uvm_reg_field;
73
79
.is_rand (is_rand),
74
80
.individually_accessible (individually_accessible));
75
81
value.rand_mode (is_rand);
76
-
82
+ this .mubi_access = mubi_access;
77
83
is_intr_test_fld = ! (uvm_re_match (" intr_test*" , get_parent ().get_name ()));
78
84
shadowed_val = ~ committed_val;
79
85
endfunction
@@ -83,10 +89,53 @@ class dv_base_reg_field extends uvm_reg_field;
83
89
`downcast (get_dv_base_reg_parent, csr)
84
90
endfunction
85
91
92
+ // Local helper function to reduce code in do_predict further below.
93
+ function uvm_reg_data_t mubi_or_hi (uvm_reg_data_t a, uvm_reg_data_t b);
94
+ import prim_mubi_pkg :: * ;
95
+ uvm_reg_data_t out;
96
+ case (mubi_width)
97
+ 4 : out = uvm_reg_data_t ' (mubi4_or_hi (mubi4_t ' (a), mubi4_t ' (b)));
98
+ 8 : out = uvm_reg_data_t ' (mubi8_or_hi (mubi8_t ' (a), mubi8_t ' (b)));
99
+ 12 : out = uvm_reg_data_t ' (mubi12_or_hi (mubi12_t ' (a), mubi12_t ' (b)));
100
+ 16 : out = uvm_reg_data_t ' (mubi16_or_hi (mubi16_t ' (a), mubi16_t ' (b)));
101
+ default : $error (" Unsupported mubi width %d ." , mubi_width);
102
+ endcase
103
+ return out;
104
+ endfunction : mubi_or_hi
105
+
106
+ // Local helper function to reduce code in do_predict further below.
107
+ function uvm_reg_data_t mubi_and_hi (uvm_reg_data_t a, uvm_reg_data_t b);
108
+ import prim_mubi_pkg :: * ;
109
+ uvm_reg_data_t out;
110
+ case (mubi_width)
111
+ 4 : out = uvm_reg_data_t ' (mubi4_and_hi (mubi4_t ' (a), mubi4_t ' (b)));
112
+ 8 : out = uvm_reg_data_t ' (mubi8_and_hi (mubi8_t ' (a), mubi8_t ' (b)));
113
+ 12 : out = uvm_reg_data_t ' (mubi12_and_hi (mubi12_t ' (a), mubi12_t ' (b)));
114
+ 16 : out = uvm_reg_data_t ' (mubi16_and_hi (mubi16_t ' (a), mubi16_t ' (b)));
115
+ default : $error (" Unsupported mubi width: %d ." , mubi_width);
116
+ endcase
117
+ return out;
118
+ endfunction : mubi_and_hi
119
+
120
+ // Local helper function to reduce code in do_predict further below.
121
+ function uvm_reg_data_t mubi_false ();
122
+ import prim_mubi_pkg :: * ;
123
+ uvm_reg_data_t out;
124
+ case (mubi_width)
125
+ 4 : out = uvm_reg_data_t ' (MuBi4False);
126
+ 8 : out = uvm_reg_data_t ' (MuBi8False);
127
+ 12 : out = uvm_reg_data_t ' (MuBi12False);
128
+ 16 : out = uvm_reg_data_t ' (MuBi16False);
129
+ default : $error (" Unsupported mubi width: %d ." , mubi_width);
130
+ endcase
131
+ return out;
132
+ endfunction : mubi_false
133
+
86
134
virtual function void do_predict (uvm_reg_item rw,
87
135
uvm_predict_e kind = UVM_PREDICT_DIRECT,
88
136
uvm_reg_byte_en_t be = - 1 );
89
137
uvm_reg_data_t field_val = rw.value[0 ] & ((1 << get_n_bits ())- 1 );
138
+ string access = get_access ();
90
139
91
140
// update intr_state mirrored value if this is an intr_test reg
92
141
// if kind is UVM_PREDICT_DIRECT or UVM_PREDICT_READ, super.do_predict can handle
@@ -101,8 +150,27 @@ class dv_base_reg_field extends uvm_reg_field;
101
150
end
102
151
// use UVM_PREDICT_READ to avoid uvm_warning due to UVM_PREDICT_DIRECT
103
152
void '(intr_state_fld.predict (predict_val, .kind (UVM_PREDICT_READ )));
104
- end
105
153
154
+ end else if (kind == UVM_PREDICT_WRITE && mubi_access inside { " W1S" , " W1C" , " W0C" } )
155
+ begin
156
+ // Some smoke checking of the byte enables. RTL does not latch anything if not all affected
157
+ // bytes of the field are enabled. Note that we still use UVM_PREDICT_WRITE further below
158
+ // since the underlying access is set to RW in the RAL model.
159
+ if (mubi_width <= 8 && be[0 ] || mubi_width > 8 && mubi_width <= 16 && & be[1 : 0 ]) begin
160
+ // In case this is a clearable MUBI field, we have to interpret the write value correctly.
161
+ // ICEBOX(#9273): Note that this just uses bitwise functions to update the value and does
162
+ // not rectify incorrect mubi values. At a later point, we should discuss if and how to
163
+ // tighten this up, as discussed on the linked issue.
164
+ case (mubi_access)
165
+ " W1S" : rw.value[0 ] = this .mubi_or_hi (rw.value[0 ], `gmv (this ));
166
+ " W1C" : rw.value[0 ] = this .mubi_and_hi (~ rw.value[0 ], `gmv (this ));
167
+ " W0C" : rw.value[0 ] = this .mubi_and_hi (rw.value[0 ], `gmv (this ));
168
+ default : ; // unreachable
169
+ endcase
170
+ end
171
+ end else if (kind == UVM_PREDICT_READ && mubi_access == " RC" ) begin
172
+ rw.value[0 ] = this .mubi_false ();
173
+ end
106
174
super .do_predict (rw, kind, be);
107
175
endfunction
108
176
0 commit comments