Skip to content

Commit f32402d

Browse files
authored
Fix returning unsigned on comparison #278 and swizzler dist issue (#279)
* Fix swizzler range max width on negative numbers The example I saw in #278 had rand ints with a range of -255 to 255, which resulted in only 8 bits of swizzling. This appears to leave the MSB or sign bit unconstrained. Added test with a similar range of -7 to 7 that triggers the same failure. * Return unsigned on comparison operators #278 The return value of comparision operators, or equality and relational operators, was inheriting the signed type of the input variables. The return values from these operators should be unsigned 1-bit values. See 1800-2017 11.8.2
1 parent 4b6a8c4 commit f32402d

4 files changed

Lines changed: 66 additions & 11 deletions

File tree

src/vsc/model/expr_bin_model.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ def __init__(self, lhs, op, rhs):
3636
self.is_composite = False
3737
self._width_valid = False
3838
self._width = -1
39+
self.equality_ops = [BinExprType.Eq, BinExprType.Ne]
40+
self.relational_ops = [BinExprType.Gt, BinExprType.Ge, BinExprType.Lt, BinExprType.Le]
3941

4042
def build_composite(self, btor, lhs, rhs):
4143
if isinstance(lhs, FieldCompositeModel):
@@ -160,12 +162,14 @@ def extend(e1, ctx_width, signed, btor):
160162
return ret
161163

162164
def is_signed(self):
163-
return (self.lhs.is_signed() and self.rhs.is_signed())
165+
if self.op in (self.equality_ops + self.relational_ops):
166+
return False
167+
else:
168+
return (self.lhs.is_signed() and self.rhs.is_signed())
164169

165170
def width(self):
166171
if not self._width_valid:
167-
if self.op in (BinExprType.Eq, BinExprType.Ge, BinExprType.Le,
168-
BinExprType.Gt, BinExprType.Lt, BinExprType.Ne):
172+
if self.op in (self.equality_ops + self.relational_ops):
169173
self._width = 1
170174
else:
171175
lhs_w = self.lhs.width()

src/vsc/model/solvegroup_swizzler_partsel.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ def sample_dist_weights(self,
176176
BinExprType.Eq,
177177
ExprLiteralModel(int(val), f.is_signed, f.width))
178178
return ret
179+
180+
def min_signed_bits(self, n):
181+
if n < 0:
182+
return (n+1).bit_length() + 1
183+
else:
184+
return n.bit_length()
179185

180186
def create_rand_domain_constraint(self,
181187
f : FieldScalarModel,
@@ -205,15 +211,9 @@ def create_rand_domain_constraint(self,
205211
ExprLiteralModel(t_range[0], False, 32)))
206212
else:
207213
# Determine the max width to use for swizzling.
208-
# max value of abs bounds
209214

210-
maxval = int(max(abs(t_range[0]), abs(t_range[1])))
211-
212-
d_width = 0
213-
214-
while maxval > 0:
215-
d_width += 1
216-
maxval >>= 1
215+
d_width = int(max(self.min_signed_bits(t_range[0]),
216+
self.min_signed_bits(t_range[1])))
217217

218218
if self.debug > 0:
219219
print("d_width: %d" % d_width)

ve/unit/test_constraint_expr.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,34 @@ def __init__(self):
8181
it.a <= it.b
8282
self.assertLessEqual(my_i.a, my_i.b)
8383

84+
def test_eq_rel_sign_ext(self):
85+
@vsc.randobj
86+
class my_c(object):
87+
def __init__(self):
88+
self.a = vsc.rand_int8_t()
89+
self.eq = vsc.rand_int8_t()
90+
self.ne = vsc.rand_int8_t()
91+
self.gt = vsc.rand_int8_t()
92+
self.ge = vsc.rand_int8_t()
93+
self.lt = vsc.rand_int8_t()
94+
self.le = vsc.rand_int8_t()
95+
96+
my_i = my_c()
97+
with my_i.randomize_with() as it:
98+
it.a == 5
99+
it.eq == (it.a == 5)
100+
it.ne == (it.a != 6)
101+
it.gt == (it.a > 4)
102+
it.ge == (it.a >= 4)
103+
it.lt == (it.a < 6)
104+
it.le == (it.a <= 6)
105+
self.assertEqual(my_i.eq, 1)
106+
self.assertEqual(my_i.ne, 1)
107+
self.assertEqual(my_i.gt, 1)
108+
self.assertEqual(my_i.ge, 1)
109+
self.assertEqual(my_i.lt, 1)
110+
self.assertEqual(my_i.le, 1)
111+
84112
def test_add(self):
85113
@vsc.randobj
86114
class my_c(object):

ve/unit/test_random_dist.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,29 @@ def ab_c(self):
691691
for e in a_hist:
692692
self.assertNotEqual(e, 0)
693693

694+
695+
def test_widevar_signed_small_range(self):
696+
@vsc.randobj
697+
class Selector:
698+
def __init__(self):
699+
self.a = vsc.rand_int64_t()
700+
701+
@vsc.constraint
702+
def ab_c(self):
703+
self.a.inside(vsc.rangelist(vsc.rng(-7, 7)))
704+
705+
selector = Selector()
706+
a_hist = {}
707+
for _ in range(20*20):
708+
selector.randomize()
709+
if selector.a in a_hist:
710+
a_hist[selector.a] += 1
711+
else:
712+
a_hist[selector.a] = 1
713+
714+
print("a_hist: %s" % len(a_hist))
715+
self.assertEqual(len(a_hist), 15)
716+
694717
def test_widevar_small_range_2(self):
695718

696719
@vsc.randobj

0 commit comments

Comments
 (0)