def lhsnre_rhsvar_propagator(self, lhs_e, op, rhs_bounds): propagator = None if op == BinExprType.Lt: # <expr> < <var> <-> <var> >= <expr>+1 # Sets the minimum bound for the variable propagator = VariableBoundExprMinPropagator( rhs_bounds, ExprBinModel(lhs_e, BinExprType.Add, ExprLiteralModel(1, False, 4))) elif op == BinExprType.Le: # <expr> <= <var> <-> <var> >= <expr> propagator = VariableBoundExprMinPropagator(rhs_bounds, lhs_e) elif op == BinExprType.Gt: # <expr> > <var> <-> <var> <= <expr>-1 propagator = VariableBoundExprMaxPropagator( rhs_bounds, ExprBinModel(lhs_e, BinExprType.Sub, ExprLiteralModel(1, False, 4))) elif op == BinExprType.Ge: # <expr> >= <var> <-> <var> <= <expr> propagator = VariableBoundExprMaxPropagator(rhs_bounds, lhs_e) elif op == BinExprType.Eq: propagator = VariableBoundEqPropagator(rhs_bounds, lhs_e, True) if propagator is not None: rhs_bounds.add_propagator(propagator) return propagator
def lhsvar_rhsnre_propagator(self, lhs_bounds, op, rhs_e): propagator = None if op == BinExprType.Lt: # The max bound is propagator = VariableBoundExprMaxPropagator( lhs_bounds, ExprBinModel(rhs_e, BinExprType.Sub, ExprLiteralModel(1, False, 4))) elif op == BinExprType.Le: # The max bound is propagator = VariableBoundExprMaxPropagator(lhs_bounds, rhs_e) elif op == BinExprType.Gt: # The minimum bound is 1+RHS propagator = VariableBoundExprMinPropagator( lhs_bounds, ExprBinModel(rhs_e, BinExprType.Add, ExprLiteralModel(1, False, 4))) elif op == BinExprType.Ge: # The minimum bound is 1+ RHS propagator = VariableBoundExprMinPropagator(lhs_bounds, rhs_e) elif op == BinExprType.Eq: # Know that the right-hand side is a non-rand quantity # This pins the left-hand variable to a single value propagator = VariableBoundEqPropagator(lhs_bounds, rhs_e, True) if propagator is not None: lhs_bounds.add_propagator(propagator) return propagator
def create_single_var_domain_constraint( self, f: FieldScalarModel, bound_m: VariableBoundModel) -> ExprModel: range_l = bound_m.domain.range_l if len(range_l) == 1: val = self.randint(range_l[0][0], range_l[0][1]) e = ExprBinModel(ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(val, f.is_signed, f.width)) return e else: # domain_bin_ratio = int(len(bound_m.domain.range_l)/len(bound_m.domain_offsets)) domain_bin_ratio = 1 if domain_bin_ratio <= 1: # Just pick a single value off_val = self.randint(0, bound_m.domain_sz - 1) target_val = bound_m.offset2value(off_val) e = ExprBinModel( ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(target_val, f.is_signed, f.width)) return e else: # TODO: For a variable with a small number of bins # relative to the domain the cover, it likely makes # sense to try to place a range within the bin instead # of selecting a single value # print("domain_bin_ratio=" + str(domain_bin_ratio)) pass return None
def test_incr(self): obj = FieldCompositeModel("obj") arr = obj.add_field( FieldArrayModel( "arr", None, # type_t True, # is_scalar None, # not an enum-type list 32, False, True, False)) for i in range(10): arr.add_field() obj.add_constraint( ConstraintBlockModel("XX", [ ConstraintExprModel( ExprBinModel(ExprFieldRefModel(arr.size), BinExprType.Eq, ExprLiteralModel(10, False, 32))) ])) foreach = ConstraintForeachModel(ExprFieldRefModel(arr)) foreach.addConstraint( ConstraintImpliesModel( ExprBinModel(ExprFieldRefModel(foreach.index), BinExprType.Gt, ExprLiteralModel(0, False, 32)), [ ConstraintExprModel( ExprBinModel( ExprArraySubscriptModel( ExprFieldRefModel(arr), ExprFieldRefModel(foreach.index)), BinExprType.Eq, ExprBinModel( ExprArraySubscriptModel( ExprFieldRefModel(arr), ExprBinModel( ExprFieldRefModel(foreach.index), BinExprType.Sub, ExprLiteralModel(1, False, 32))), BinExprType.Add, ExprLiteralModel( 1, False, 32)))) ])) obj.add_constraint(ConstraintBlockModel("c", [foreach])) # print("Object: " + ModelPrettyPrinter.print(obj)) # # constraints = ArrayConstraintBuilder.build(obj) # for c in constraints: # print("Constraint: " + ModelPrettyPrinter.print(c)) # print("Object(1): " + ModelPrettyPrinter.print(obj)) # # ConstraintOverrideRollbackVisitor.rollback(obj) # print("Object(2): " + ModelPrettyPrinter.print(obj)) Randomizer.do_randomize([obj]) for f in arr.field_l: print("" + f.name + ": " + str(int(f.get_val())))
def get_bin_expr(self, bin_idx): """Builds expressions to represent the values in this bin""" expr = ExprBinModel( ExprBinModel(self.cp.target, BinExprType.Ge, ExprLiteralModel(self.target_val_low, False, 32)), BinExprType.And, ExprBinModel(self.cp.target, BinExprType.Le, ExprLiteralModel(self.target_val_high, False, 32))) return expr
def get_sum_expr(self): if self.sum_expr is None: # Build # Compute clog2 of overflow term to # ensure that we properly size the result # to avoid overflow result_bits = self.type_t.width overflow_val = int(self.size.get_val())-1 while overflow_val > 0: result_bits += 1 overflow_val >>= 1 # Force the result to be 32-bit, in order to # match user expectation ret = ExprLiteralModel(0, self.is_signed, result_bits) for i in range(int(self.size.get_val())): f = self.field_l[i] ret = ExprBinModel( ret, BinExprType.Add, ExprFieldRefModel(f)) self.sum_expr = ret return self.sum_expr
def get_bin_expr(self, idx): """Builds expressions to represent a single bin""" return ExprBinModel( self.cp.target, BinExprType.Eq, ExprLiteralModel(self.low+idx, False, 32) )
def swizzle_field(self, f, rs, bound_m) -> ExprModel: ret = None if self.debug > 0: print("Swizzling field %s" % f.name) if f in rs.dist_field_m.keys(): if self.debug > 0: print("Note: field %s is in dist map" % f.name) for d in rs.dist_field_m[f]: print(" Target interval %d" % d.target_range) if len(rs.dist_field_m[f]) > 1: target_d = self.randstate.randint(0, len(rs.dist_field_m[f]) - 1) dist_scope_c = rs.dist_field_m[f][target_d] else: dist_scope_c = rs.dist_field_m[f][0] target_w = dist_scope_c.dist_c.weights[dist_scope_c.target_range] if target_w.rng_rhs is not None: # Dual-bound range val_l = target_w.rng_lhs.val() val_r = target_w.rng_rhs.val() val = self.randstate.randint(val_l, val_r) if self.debug > 0: print( "Select dist-weight range: %d..%d ; specific value %d" % (int(val_l), int(val_r), int(val))) ret = [ ExprBinModel(ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(val, f.is_signed, f.width)) ] else: # Single value val = target_w.rng_lhs.val() ret = [ ExprBinModel( ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(int(val), f.is_signed, f.width)) ] else: if f in bound_m.keys(): f_bound = bound_m[f] if not f_bound.isEmpty(): ret = self.create_rand_domain_constraint(f, f_bound) return ret
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 test_smoke(self): obj = FieldCompositeModel("obj") arr = obj.add_field( FieldArrayModel( "arr", None, # type_t True, None, # not an enum-type 32, False, True, True)) # for i in range(10): # arr.add_field() obj.add_constraint( ConstraintBlockModel("XX", [ ConstraintExprModel( ExprBinModel(ExprFieldRefModel(arr.size), BinExprType.Eq, ExprLiteralModel(10, False, 32))) ])) foreach = ConstraintForeachModel(ExprFieldRefModel(arr)) foreach.addConstraint( ConstraintExprModel( ExprBinModel( ExprArraySubscriptModel(ExprFieldRefModel(arr), ExprFieldRefModel(foreach.index)), BinExprType.Lt, ExprLiteralModel(10, False, 32)))) obj.add_constraint(ConstraintBlockModel("c", [foreach])) # print("Object: " + ModelPrettyPrinter.print(obj)) # # constraints = ArrayConstraintBuilder.build(obj) # for c in constraints: # print("Constraint: " + ModelPrettyPrinter.print(c)) # print("Object(1): " + ModelPrettyPrinter.print(obj)) # # ConstraintOverrideRollbackVisitor.rollback(obj) # print("Object(2): " + ModelPrettyPrinter.print(obj)) randstate = RandState(0) Randomizer.do_randomize(randstate, SourceInfo("", -1), [obj]) for f in arr.field_l: print("" + f.name + ": " + str(int(f.get_val())))
def visit_expr_fieldref(self, e : ExprFieldRefModel): if self.phase != 1: return if e.fm in self.index_set: # Replace the index with the appropriate literal value self._expr = ExprLiteralModel(int(e.fm.get_val()), False, 32) else: ConstraintCopyBuilder.visit_expr_fieldref(self, e)
def get_bin_expr(self, bin_idx): """Builds expressions to represent the values in this bin""" expr = None for r in self.binspec.range_l: if r[0] == r[1]: e = ExprBinModel(self.cp.target, BinExprType.Eq, ExprLiteralModel(r[0])) else: e = ExprBinModel( ExprBinModel(self.cp.target, BinExprType.Ge, ExprLiteralModel(r[0])), BinExprType.And, ExprBinModel(self.cp.target, BinExprType.Le, ExprLiteralModel(r[1]))) if expr is None: expr = e else: expr = ExprBinModel(expr, BinExprType.Or, e) return expr
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 to_expr(t): if isinstance(t, expr): return t elif type(t) == int: return expr(ExprLiteralModel(t, True, 32)) elif isinstance(type(t), (EnumMeta,IntEnum)): return expr(EnumInfo.get(type(t)).e2e(t)) elif hasattr(t, "to_expr"): return t.to_expr() elif callable(t): raise Exception("TODO: support lambda references") else: print("Type: " + str(t) + " " + str(type(t))) raise Exception("Element \"" + str(t) + "\" isn't recognized, and doesn't provide to_expr")
def get_sum_expr(self): if self.sum_expr is None: # Build ret = None for f in self.field_l: if ret is None: ret = ExprFieldRefModel(f) else: ret = ExprBinModel(ret, BinExprType.Add, ExprFieldRefModel(f)) if ret is None: ret = ExprLiteralModel(0, False, 32) self.sum_expr = ret return self.sum_expr
def test_simple(self): a = FieldScalarModel("a", 16, False, True) b = FieldScalarModel("b", 16, False, True) c = FieldScalarModel("c", 16, False, True) l = ExprLiteralModel(10, False, 8) ab_c = ConstraintBlockModel("ab_c", [ ConstraintImpliesModel( ExprBinModel(ExprFieldRefModel(a), BinExprType.Lt, ExprFieldRefModel(b)), [ ConstraintExprModel( ExprBinModel(ExprFieldRefModel(c), BinExprType.Eq, l)) ]) ]) copy = ConstraintCopyBuilder.copy(ab_c) self.assertEquals(1, len(copy)) self.assertIsNot(ab_c, copy[0])
def to_expr(t): if isinstance(t, expr): # This expression is already on the stack # push_expr(t.em) return t elif type(t) == int or type(t) == ValueInt: return expr(ExprLiteralModel(int(t), True, 32)) elif isinstance(type(t), (EnumMeta, IntEnum)): return expr(EnumInfo.get(type(t)).e2e(t)) elif hasattr(t, "to_expr"): return t.to_expr() elif callable(t): raise Exception("TODO: support lambda references") else: raise Exception( "Element \"" + str(t) + "\" isn't recognized, and doesn't provide to_expr (type=%s)" % str(type(t)))
def test_wide_var(self): obj = FieldCompositeModel("obj") a = obj.add_field(FieldScalarModel("a", 1024, False, True)) obj.add_constraint( ConstraintBlockModel("c", [ ConstraintExprModel( ExprBinModel( a.expr(), BinExprType.Gt, ExprLiteralModel(0x80000000000000000, False, 72))) ])) randstate = RandState(0) rand = Randomizer(randstate) rand.do_randomize(randstate, SourceInfo("", -1), [obj]) print("a=" + hex(int(a.val))) self.assertGreater(a.val, ValueScalar(0x80000000000000000))
def build(self, btor, ctx_width=-1): t = None expr = None for r in self.rhs.rl: if isinstance(r, ExprRangeModel): t = ExprBinModel(ExprBinModel(self.lhs, BinExprType.Ge, r.lhs), BinExprType.And, ExprBinModel(self.lhs, BinExprType.Le, r.rhs)) elif isinstance(r, ExprFieldRefModel): if isinstance(r.fm, FieldArrayModel): # Need to build out for each element # TODO: must handle case where size is random arr: FieldArrayModel = r.fm if arr.is_rand_sz: pass else: for i in range(int(arr.size.get_val())): t = ExprBinModel(self.lhs, BinExprType.Eq, ExprFieldRefModel(arr.field_l[i])) if expr is None: expr = t else: expr = ExprBinModel(expr, BinExprType.Or, t) # Clear the temporary term, so the combination code # below doesn't use it. t = None else: t = ExprBinModel(self.lhs, BinExprType.Eq, r) else: t = ExprBinModel(self.lhs, BinExprType.Eq, r) if t is not None: if expr is None: expr = t else: expr = ExprBinModel(expr, BinExprType.Or, t) if expr is None: expr = ExprLiteralModel(1, False, 1) from vsc.visitors.model_pretty_printer import ModelPrettyPrinter return expr.build(btor) if expr is not None else None
def visit_expr_fieldref(self, e): if ForeachRefExpander.EN_DEBUG > 0: print("--> ForeachRefExpander::visit_expr_fieldref %s" % e.fm.fullname) # Save a reference to the field self._field = e.fm # If the target is one of the index variables, then # note that and grab the actual value for use if e.fm in self.index_set: if ForeachRefExpander.EN_DEBUG > 0: print( "ForeachRefExpander: field is an index. Replacing with %d" % (int(e.fm.get_val()), )) self._refs_index_var = True self._expr = ExprLiteralModel(int(e.fm.get_val()), True, 32) if ForeachRefExpander.EN_DEBUG > 0: print("<-- ForeachRefExpander::visit_expr_fieldref")
def create_rand_domain_constraint( self, f: FieldScalarModel, bound_m: VariableBoundModel) -> ExprModel: e = None range_l = bound_m.domain.range_l # print("create_rand_domain_constraint: " + f.name + " " + str(range_l)) if len(range_l) == 1: domain = range_l[0][1] - range_l[0][0] if domain > 64: r_type = self.randint(0, 3) single_val = self.randint(range_l[0][0], range_l[0][1]) if r_type >= 0 and r_type <= 2: # range # Pretty simple. Partition and randomize bin_sz_h = 1 if int(domain / 128) == 0 else int(domain / 128) if r_type == 0: # Center value in bin if single_val + bin_sz_h > range_l[0][1]: max = range_l[0][1] min = range_l[0][1] - 2 * bin_sz_h elif single_val - bin_sz_h < range_l[0][0]: max = range_l[0][0] + 2 * bin_sz_h min = range_l[0][0] else: max = single_val + bin_sz_h min = single_val - bin_sz_h elif r_type == 1: # Bin starts at value if single_val + 2 * bin_sz_h > range_l[0][1]: max = range_l[0][1] min = range_l[0][1] - 2 * bin_sz_h elif single_val - 2 * bin_sz_h < range_l[0][0]: max = range_l[0][0] + 2 * bin_sz_h min = range_l[0][0] else: max = single_val + 2 * bin_sz_h min = single_val elif r_type == 2: # Bin ends at value if single_val + 2 * bin_sz_h > range_l[0][1]: max = range_l[0][1] min = range_l[0][1] - 2 * bin_sz_h elif single_val - 2 * bin_sz_h < range_l[0][0]: max = range_l[0][0] + 2 * bin_sz_h min = range_l[0][0] else: max = single_val min = single_val - 2 * bin_sz_h e = ExprBinModel( ExprBinModel( ExprFieldRefModel(f), BinExprType.Ge, ExprLiteralModel(min, f.is_signed, f.width)), BinExprType.And, ExprBinModel( ExprFieldRefModel(f), BinExprType.Le, ExprLiteralModel(max, f.is_signed, f.width))) elif r_type == 3: # Single value e = ExprBinModel( ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(single_val, f.is_signed, f.width)) else: val = self.randint(0, domain - 1) e = ExprBinModel(ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(val, f.is_signed, f.width)) else: # domain_bin_ratio = int(len(bound_m.domain.range_l)/len(bound_m.domain_offsets)) # # if domain_bin_ratio <= 1: # # Just pick a single value # print("Should pick single value") # else: # # # print("domain_bin_ratio=" + str(domain_bin_ratio)) # pass # # Multi-range domain pass return e
def signed(v, w=-1): if w == -1: w = 32 return expr(ExprLiteralModel(v, True, w))
def unsigned(v, w=-1): if w == -1: w = 32 return expr(ExprLiteralModel(v, False, w))
def visit_expr_bin(self, e: ExprBinModel): # TODO: We'll need to deal with expressions that involve variables # An alias is the simplest relationship. A == B means that there is # a single bound for both variables, and all relationships on A and B # contribute to this single bound # Don't attempt to deal with subscripts when we're # establishing array domains. if not self.process_subscript and ( isinstance(e.lhs, ExprArraySubscriptModel) or isinstance(e.rhs, ExprArraySubscriptModel)): return if self.phase == 1: # Traverse to pick up variable references super().visit_expr_bin(e) if isinstance(e.lhs, ExprArraySubscriptModel): fm = e.lhs.subscript() elif isinstance(e.lhs, ExprFieldRefModel): fm = e.lhs.fm else: fm = None if self.depth > 0: # Ignore processing if we're deep in an expression pass elif fm is not None and not isinstance(e.rhs, ExprFieldRefModel): bounds = self.bound_m[fm] if e.op == BinExprType.Lt: # TODO: # The max bound is self._propagator = VariableBoundMaxPropagator( bounds, ExprBinModel(e.rhs, BinExprType.Sub, ExprLiteralModel(1, False, 4))) bounds.add_propagator(self._propagator) # Apply propagator self._propagator.propagate() self._propagator = None elif e.op == BinExprType.Le: # TODO: # The max bound is self._propagator = VariableBoundMaxPropagator( bounds, e.rhs) bounds.add_propagator(self._propagator) # Apply propagator self._propagator.propagate() self._propagator = None elif e.op == BinExprType.Gt: # TODO: # The minimum bound is 1+ RHS self._propagator = VariableBoundMinPropagator( bounds, ExprBinModel(e.rhs, BinExprType.Add, ExprLiteralModel(1, False, 4))) bounds.add_propagator(self._propagator) # Apply propagator self._propagator.propagate() self._propagator = None elif e.op == BinExprType.Ge: # TODO: # The minimum bound is 1+ RHS self._propagator = VariableBoundMinPropagator( bounds, e.rhs) bounds.add_propagator(self._propagator) # Apply propagator self._propagator.propagate() self._propagator = None elif e.op == BinExprType.Eq: is_const_v = IsConstExprVisitor() is_const = is_const_v.is_const(e.rhs) if is_const: self._propagator = VariableBoundEqPropagator( bounds, e.rhs, True) elif isinstance(e.rhs, ExprFieldRefModel): # TODO: lhs is an alias # self._propagator = VariableBoundEqPropagator( # bounds, # self.bound_m[e.rhs.fm], # True) pass if self._propagator is not None: bounds.add_propagator(self._propagator) self._propagator.propagate() # # self._propagator = None elif isinstance(e.rhs, ExprFieldRefModel): # TODO: Need to do similar calculation for RHS pass
def get_bin_expr(self, bin_idx): """Builds expressions to represent the values in this bin""" expr = ExprBinModel(self.cp.target, BinExprType.Eq, ExprLiteralModel(self.target_val, False, 32)) return expr
def create_rand_domain_constraint(self, f : FieldScalarModel, bound_m : VariableBoundModel)->ExprModel: e = None range_l = bound_m.domain.range_l range_idx = self.randint(0, len(range_l)-1) range = range_l[range_idx] domain = range[1]-range[0] if self.debug > 0: print("create_rand_domain_constraint: " + f.name + " range_idx=" + str(range_idx) + " range=" + str(range)) if domain > 64: r_type = self.randint(0, 3) single_val = self.randint(range[0], range[1]) if r_type >= 0 and r_type <= 2: # range # Pretty simple. Partition and randomize bin_sz_h = 1 if int(domain/128) == 0 else int(domain/128) if r_type == 0: # Center value in bin if single_val+bin_sz_h > range[1]: max = range[1] min = range[1]-2*bin_sz_h elif single_val-bin_sz_h < range[0]: max = range[0]+2*bin_sz_h min = range[0] else: max = single_val+bin_sz_h min = single_val-bin_sz_h elif r_type == 1: # Bin starts at value if single_val+2*bin_sz_h > range[1]: max = range[1] min = range[1]-2*bin_sz_h elif single_val-2*bin_sz_h < range[0]: max = range[0]+2*bin_sz_h min = range[0] else: max = single_val+2*bin_sz_h min = single_val elif r_type == 2: # Bin ends at value if single_val+2*bin_sz_h > range[1]: max = range[1] min = range[1]-2*bin_sz_h elif single_val-2*bin_sz_h < range[0]: max = range[0]+2*bin_sz_h min = range[0] else: max = single_val min = single_val-2*bin_sz_h e = ExprBinModel( ExprBinModel( ExprFieldRefModel(f), BinExprType.Ge, ExprLiteralModel( min, f.is_signed, f.width) ), BinExprType.And, ExprBinModel( ExprFieldRefModel(f), BinExprType.Le, ExprLiteralModel( max, f.is_signed, f.width) ) ) elif r_type == 3: # Single value e = ExprBinModel( ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(single_val, f.is_signed, f.width)) else: val = self.randint(range[0], range[1]) e = ExprBinModel( ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(val, f.is_signed, f.width)) return e
def create_rand_domain_constraint( self, f: FieldScalarModel, bound_m: VariableBoundModel) -> ExprModel: e = None range_l = bound_m.domain.range_l range_idx = self.randint(0, len(range_l) - 1) range = range_l[range_idx] domain = range[1] - range[0] if self.debug > 0: print("create_rand_domain_constraint: " + f.name + " range_idx=" + str(range_idx) + " range=" + str(range)) if domain > 64: r_type = self.randint(0, 3) r_type = 3 # Note: hard-coded to selecting single value for single_val = self.randint(range[0], range[1]) if r_type >= 0 and r_type <= 2: # range # Pretty simple. Partition and randomize # bin_sz_h = 1 if int(domain/128) == 0 else int(domain/128) bin_sz_h = 1 if int(domain / 128) == 0 else int(domain / 128) if r_type == 0: # Center value in bin if single_val + bin_sz_h > range[1]: max = range[1] min = range[1] - 2 * bin_sz_h elif single_val - bin_sz_h < range[0]: max = range[0] + 2 * bin_sz_h min = range[0] else: max = single_val + bin_sz_h min = single_val - bin_sz_h if self.debug > 0: print( "rand_domain range-type is bin center value: center=%d => %d..%d" % (single_val, min, max)) elif r_type == 1: # Bin starts at value if single_val + 2 * bin_sz_h > range[1]: max = range[1] min = range[1] - 2 * bin_sz_h elif single_val - 2 * bin_sz_h < range[0]: max = range[0] + 2 * bin_sz_h min = range[0] else: max = single_val + 2 * bin_sz_h min = single_val if self.debug > 0: print( "rand_domain range-type is bin left-target value: left=%d %d..%d" % (single_val, min, max)) elif r_type == 2: # Bin ends at value if single_val + 2 * bin_sz_h > range[1]: max = range[1] min = range[1] - 2 * bin_sz_h elif single_val - 2 * bin_sz_h < range[0]: max = range[0] + 2 * bin_sz_h min = range[0] else: max = single_val min = single_val - 2 * bin_sz_h if self.debug > 0: print( "rand_domain range-type is bin right-target value: left=%d %d..%d" % (single_val, min, max)) e = ExprBinModel( ExprBinModel(ExprFieldRefModel(f), BinExprType.Ge, ExprLiteralModel(min, f.is_signed, f.width)), BinExprType.And, ExprBinModel(ExprFieldRefModel(f), BinExprType.Le, ExprLiteralModel(max, f.is_signed, f.width))) elif r_type == 3: # Single value if self.debug > 0: print("rand_domain range-type is single value: %d" % single_val) e = ExprBinModel( ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(single_val, f.is_signed, f.width)) else: val = self.randint(range[0], range[1]) if self.debug > 0: print("rand_domain on small domain [%d..%d] => %d" % (range[0], range[1], val)) e = ExprBinModel(ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(val, f.is_signed, f.width)) return e
def create_rand_domain_constraint( self, f: FieldScalarModel, bound_m: VariableBoundModel) -> ExprModel: e = [] range_l = bound_m.domain.range_l if self.debug: print("range_l: %d (%s)" % (len(range_l), str(range_l))) if len(range_l) > 1: # If we have a multi-part domain, select from one # of the slices range_idx = self.randstate.randint(0, len(range_l) - 1) t_range = range_l[range_idx] else: # Otherwise, if our domain is a single range, select # an appropriate value and slice it into selections t_range = range_l[0] if self.debug > 0: print("Domain: %d..%d" % (t_range[0], t_range[1])) if t_range[0] == t_range[1]: # Single value e.append( ExprBinModel(ExprFieldRefModel(f), BinExprType.Eq, ExprLiteralModel(t_range[0], False, 32))) else: # Multi-value range d_width = 0 maxval = t_range[1] while maxval > 0: d_width += 1 maxval >>= 1 if self.debug > 0: print("d_width: %d" % d_width) # bit_pattern = self.randstate.randint(0, (1 << width)-1) bit_pattern = self.randstate.randint(t_range[0], t_range[1]) max_intervals = 6 if self.debug > 0: print("bit_pattern: %s" % bin(bit_pattern)) if d_width > max_intervals: interval_w = int(d_width / max_intervals) for i in range(max_intervals): low = i * interval_w if i + 1 == max_intervals: high = d_width - 1 width = d_width - low else: high = (i + 1) * interval_w - 1 width = interval_w if self.debug > 0: print("%d..%d 0x%08x" % (low, high, ((bit_pattern >> low) & ((1 << width) - 1)))) e.append( ExprBinModel( ExprPartselectModel( ExprFieldRefModel(f), ExprLiteralModel(high, False, 32), ExprLiteralModel(low, False, 32)), BinExprType.Eq, ExprLiteralModel( (bit_pattern >> low) & ((1 << width) - 1), False, width))) else: # Create a per-bit constraint for i in range(d_width): e.append( ExprBinModel( ExprPartselectModel(ExprFieldRefModel(f), ExprLiteralModel(i, False, 32)), BinExprType.Eq, ExprLiteralModel((bit_pattern >> i) & 1, False, 1))) return e
def visit_expr_literal(self, e: ExprLiteralModel): self.is_x = False self.val = e.val()
def e2e(self, ev): v = self.e2v_m[ev] return ExprLiteralModel(v, True, 32)