def visit_scalar_field(self, f: FieldScalarModel): if f.is_used_rand: self.is_x = True self.val = None else: self.is_x = False self.val = f.get_val()
class FieldArrayModel(FieldCompositeModel): """All arrays are processed as if they were variable size.""" def __init__(self, name, is_scalar, enums, width, is_signed, is_rand, is_rand_sz): super().__init__(name, is_rand) # width and is_signed only needed for scalar fields self.is_enum = (enums is not None) self.enums = enums self.is_scalar = is_scalar self.width = width self.is_signed = is_signed self.is_rand_sz = is_rand_sz # Holds a cached version of the sum constraint self.sum_expr_btor = None self.sum_expr = None # Holds a cached version of the sum constraint self.product_expr_btor = None self.product_expr = None self.size = FieldScalarModel("size", 32, False, is_rand_sz) self._set_size(0) def append(self, fm): super().add_field(fm) self._set_size(len(self.field_l)) fm.is_declared_rand = self.is_declared_rand fm.rand_mode = self.is_declared_rand self.name_elems() def clear(self): self.field_l.clear() self._set_size(0) def pop(self, idx=0): self.field_l.pop(idx) self._set_size(len(self.field_l)) self.name_elems() def _set_size(self, sz): if sz != int(self.size.get_val()): self.size.set_val(sz) self.sum_expr = None self.sum_expr_btor = None self.product_expr = None self.product_expr_btor = None def name_elems(self): """Apply an index-based name to all fields""" for i, f in enumerate(self.field_l): f.name = self.name + "[" + str(i) + "]" def pre_randomize(self): # Set the size field for arrays that don't # have a random size if not self.is_rand_sz: self._set_size(len(self.field_l)) FieldCompositeModel.pre_randomize(self) def post_randomize(self): FieldCompositeModel.post_randomize(self) self.sum_expr = None self.sum_expr_btor = None def add_field(self) -> FieldScalarModel: fid = len(self.field_l) if self.is_enum: ret = super().add_field( EnumFieldModel(self.name + "[" + str(fid) + "]", self.enums, self.is_declared_rand)) else: ret = super().add_field( FieldScalarModel(self.name + "[" + str(fid) + "]", self.width, self.is_signed, self.is_declared_rand)) # Update the size self._set_size(len(self.field_l)) return ret def build(self, builder): # Called before randomization self._set_size(len(self.field_l)) super().build(builder) def get_sum_expr(self): if self.sum_expr is None: # Build # Force the result to be 32-bit, in order to # match user expectation ret = ExprLiteralModel(0, self.is_signed, 32) for i in range(int(self.size.get_val())): f = self.field_l[i] if ret is None: ret = ExprFieldRefModel(f) else: ret = ExprBinModel(ret, BinExprType.Add, ExprFieldRefModel(f)) if ret is None: ret = ExprLiteralModel(0, self.is_signed, 32) self.sum_expr = ret return self.sum_expr def build_sum_expr(self, btor): if self.sum_expr_btor is None: self.sum_expr_btor = self.get_sum_expr().build(btor) return self.sum_expr_btor def get_product_expr(self): if self.product_expr is None: # Build # Force the result to be 32-bit, in order to # match user expectation if int(self.size.get_val()) == 0: ret = ExprLiteralModel(0, self.is_signed, 64) else: ret = ExprLiteralModel(1, self.is_signed, 64) for i in range(int(self.size.get_val())): f = self.field_l[i] ret = ExprBinModel(ret, BinExprType.Mul, ExprFieldRefModel(f)) self.product_expr = ret return self.product_expr def build_product_expr(self, btor): if self.product_expr_btor is None: self.product_expr_btor = self.get_product_expr().build(btor) return self.product_expr_btor def accept(self, v): v.visit_field_scalar_array(self)