4444from vsc .model .rand_set import RandSet
4545from vsc .model .constraint_dist_scope_model import ConstraintDistScopeModel
4646from vsc .visitors .expand_solve_order_visitor import ExpandSolveOrderVisitor
47+ from vsc .visitors .expr2field_visitor import Expr2FieldVisitor
4748
4849
4950class RandInfoBuilder (ModelVisitor ,RandIF ):
5051
52+ EN_DEBUG = 0
53+
5154 def __init__ (self , rng ):
5255 # TODO: need access to the random state
5356 super ().__init__ ()
@@ -69,9 +72,9 @@ def __init__(self, rng):
6972 self .active_cp = None
7073 self ._rng = rng
7174 self ._order_l = []
72- self ._order_s = set ()
7375
7476 self ._order_m = {}
77+ self ._expr2fm = Expr2FieldVisitor ()
7578
7679 @staticmethod
7780 def build (
@@ -167,30 +170,6 @@ def visit_constraint_solve_order(self, c : ConstraintSolveOrderModel):
167170 for b in c .before_l :
168171 for a in c .after_l :
169172 ExpandSolveOrderVisitor (self ._order_m ).expand (a , b )
170-
171- # b_i = -1
172- # a_i = -1
173- # if b in self._order_s:
174- # b_i = self._order_l.index(b)
175- # if a in self._order_s:
176- # a_i = self._order_l.index(a)
177- #
178- # if b_i == -1 and a_i == -1:
179- # # Just add the elements to the list
180- # self._order_l.append(b)
181- # self._order_l.append(a)
182- # self._order_s.add(a)
183- # self._order_s.add(b)
184- # elif b_i != -1:
185- # self._order_l.insert(b_i+1, a)
186- # self._order_s.add(a)
187- # elif a_i != -1:
188- # self._order_l.insert(a_i, b)
189- # self._order_s.add(b)
190- # else:
191- # # Found both in the list already.
192- # # They might be in the list for good reasons or bad
193- # pass
194173
195174 def visit_constraint_stmt_enter (self , c ):
196175 if self ._pass == 1 and len (self ._constraint_s ) == 1 :
@@ -219,27 +198,39 @@ def visit_constraint_dynref(self, c):
219198 c_stmt .accept (self )
220199
221200 def visit_constraint_expr (self , c ):
201+ if RandInfoBuilder .EN_DEBUG :
202+ print ("--> RandInfoBuilder::visit_constraint_expr" )
203+
222204 super ().visit_constraint_expr (c )
223205
206+ if RandInfoBuilder .EN_DEBUG :
207+ print ("<-- RandInfoBuilder::visit_constraint_expr" )
208+
224209 def visit_constraint_dist_scope (self , s : ConstraintDistScopeModel ):
225210 super ().visit_constraint_dist_scope (s )
226211
227212 # Save information on dist constraints to the
228213 # appropriate randset
229214 if self ._active_randset is not None :
230- f = s .dist_c .lhs . fm
215+ f = self . _expr2fm . field ( s .dist_c .lhs )
231216 if f in self ._active_randset .dist_field_m .keys ():
232217 self ._active_randset .dist_field_m [f ].append (s )
233218 else :
234219 self ._active_randset .dist_field_m [f ] = [s ]
235220
236221 def visit_constraint_soft (self , c :ConstraintSoftModel ):
222+ if RandInfoBuilder .EN_DEBUG :
223+ print ("--> RandInfoBuilder::visit_constraint_soft" )
224+
237225 # Update the priority of this constraint
238226 c .priority += self ._soft_priority
239227 self ._soft_priority += 1
240228
241229 super ().visit_constraint_soft (c )
242230
231+ if RandInfoBuilder .EN_DEBUG :
232+ print ("<-- RandInfoBuilder::visit_constraint_soft" )
233+
243234 def visit_expr_array_subscript (self , s : ExprArraySubscriptModel ):
244235 fm = s .getFieldModel ()
245236 if self ._pass == 1 :
@@ -281,53 +272,64 @@ def visit_expr_array_subscript(self, s : ExprArraySubscriptModel):
281272 self ._field_s .remove (fm )
282273
283274 def visit_expr_fieldref (self , e ):
284- if self ._pass == 1 :
275+ # If the field is already referenced by an existing randset
276+ # that is not this one, we need to merge the sets
277+ fm = self ._expr2fm .field (e )
278+
279+ if self ._pass == 0 :
280+ fm .accept (self )
281+ elif self ._pass == 1 :
285282 # During pass 1, build out randsets based on constraint
286283 # relationships
287284
288- # If the field is already referenced by an existing randset
289- # that is not this one, we need to merge the sets
290- if isinstance (e .fm , FieldArrayModel ):
285+
286+ if isinstance (fm , FieldArrayModel ):
287+ # Note: this is important for unique constraints on an
288+ # entire (possibly variable-size) scalar array
291289 for f in e .fm .field_l :
292290 self .process_fieldref (f )
293291 else :
294- self .process_fieldref (e . fm )
292+ self .process_fieldref (fm )
295293
296-
297- super ().visit_expr_fieldref (e )
294+ # super().visit_expr_fieldref(e)
298295
299296 def visit_expr_indexed_fieldref (self , e ):
300297 self .process_fieldref (e .get_target ())
301298
302299 def process_fieldref (self , fm ):
300+ if RandInfoBuilder .EN_DEBUG > 0 :
301+ print ("--> RandInfoBuilder::process_fieldref %s" % fm .fullname )
303302 if fm in self ._randset_field_m .keys ():
304303 # There's an existing randset that holds this field
305304 ex_randset = self ._randset_field_m [fm ]
306305 if self ._active_randset is None :
307306 self ._active_randset = ex_randset
308307 elif ex_randset is not self ._active_randset :
309- if fm in self ._order_s :
310- # This field is part of the ordering constraint set.
311- if self ._active_randset .order != - 1 and self ._active_randset .order < ex_randset .order :
312- # If the active randset is also ordered, and comes before
313- # the one containing this field as primary, then we must
314- # save the constraints
315- self ._active_order_randset_s .add (ex_randset )
316- self ._active_randset .add_nontarget (fm )
317- else :
318- # This field isn't being ordered, so go ahead and
319- for f in self ._active_randset .fields ():
320- # Relink to the new consolidated randset
321- self ._randset_field_m [f ] = ex_randset
322- ex_randset .add_field (f )
308+ if RandInfoBuilder .EN_DEBUG > 0 :
309+ print ("RandInfoBuilder: combine two randsets" )
310+
311+ # This field isn't being ordered, so go ahead and
312+ for f in self ._active_randset .fields ():
313+ # Relink to the new consolidated randset
314+ self ._randset_field_m [f ] = ex_randset
315+ ex_randset .add_field (f )
323316
324- for c in self ._active_randset .constraints ():
325- ex_randset .add_constraint (c )
317+ for c in self ._active_randset .constraints ():
318+ ex_randset .add_constraint (c )
319+
320+ for c in self ._active_randset .soft_constraints ():
321+ ex_randset .add_constraint (c )
326322
327- # Remove the previous randset
328- self ._randset_s .remove (self ._active_randset )
329- self ._active_randset = ex_randset
323+ # Remove the previous randset
324+ self ._randset_s .remove (self ._active_randset )
325+ self ._active_randset = ex_randset
326+ else :
327+ # Field is handled by a randset that is the active one
328+ pass
330329 else :
330+ if RandInfoBuilder .EN_DEBUG > 0 :
331+ print ("RandInfoBuilder: create new randset" )
332+
331333 # No existing randset holds this field
332334 if self ._active_randset is None :
333335 self ._active_randset = RandSet ()
@@ -339,6 +341,9 @@ def process_fieldref(self, fm):
339341
340342 if fm in self ._field_s :
341343 self ._field_s .remove (fm )
344+
345+ if RandInfoBuilder .EN_DEBUG > 0 :
346+ print ("<-- RandInfoBuilder::process_fieldref %s" % fm .fullname )
342347
343348
344349 def visit_composite_field (self , f ):
0 commit comments