Skip to content

Commit eb6824c

Browse files
committed
0.4.5
- (#93) Support slices/part selects on int/bit-type fields in procedural code. - (#83) Correct an issue with variable-bounds detetion that resulted in little randomization being applied to constrained nested fields Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
1 parent 7250e7c commit eb6824c

13 files changed

+191
-36
lines changed

doc/Changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11

2+
## 0.4.5
3+
- (#93) Support slices/part selects on int/bit-type fields in
4+
procedural code.
5+
- (#83) Correct an issue with variable-bounds detetion that
6+
resulted in little randomization being applied to
7+
constrained nested fields
28
## 0.4.4
39
- (#92) Corrected an issue where soft constraints were dropped while
410
combining solve sets

etc/ivpm.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

22
name=pyvsc
3-
version=0.4.4
3+
version=0.4.5
44

src/vsc/model/value_scalar.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@
66
from vsc.model.value import Value, ValueType
77
from vsc.model.value_bool import ValueBool
88

9-
# class ValueInt(int):
10-
#
11-
# def __getitem__(self, rng):
12-
# val = str.__int__()
13-
# if
14-
# print("int rng: " + str(self.__int__()))
15-
# for v in dir(self):
16-
# print(" v: " + str(v))
9+
class ValueInt(int):
10+
"""Wrapper for 'int' values. Permits operators"""
11+
12+
def __getitem__(self, rng):
13+
val = self.__int__()
14+
15+
if isinstance(rng, slice):
16+
if (rng.start < rng.stop):
17+
raise Exception("integer slice bounds are reversed. Expect [%d:%d]" % (
18+
rng.stop, rng.start))
19+
mask = ((1 << ((rng.start-rng.stop)+1)) - 1)
20+
return ((val >> rng.stop) & mask)
21+
else:
22+
# Single bit
23+
return ((val >> rng) & 1)
1724

1825
class ValueScalar(Value):
1926

@@ -29,10 +36,10 @@ def val(self):
2936
return self.v
3037

3138
def __int__(self):
32-
return self.v
39+
return ValueInt(self.v)
3340

34-
# def toInt(self):
35-
# return ValueInt(self.v)
41+
def toInt(self):
42+
return ValueInt(self.v)
3643

3744
def __bool__(self):
3845
return self.v != 0
@@ -65,6 +72,10 @@ def __add__(self, rhs):
6572
v = int(rhs)
6673
return ValueScalar(self.v + v)
6774

75+
def __and__(self, rhs):
76+
v = int(rhs)
77+
return ValueScalar(self.v & v)
78+
6879
def __sub__(self, rhs):
6980
v = int(rhs)
7081
return ValueScalar(self.v - v)

src/vsc/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ def val(self, v):
384384
self.get_model().set_val(ValueScalar(v))
385385

386386
def get_val(self):
387-
return int(self.get_model().get_val())
387+
return self.get_model().get_val().toInt()
388388

389389
def set_val(self, val):
390390
if self.is_signed:

src/vsc/visitors/expr2field_visitor.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,23 @@ def __init__(self):
1414
super().__init__()
1515
self.fm = None
1616

17-
def field(self, e : ExprModel):
17+
def field(self, e : ExprModel, fail_on_failure=True):
1818
e.accept(self)
1919

20-
if self.fm is None:
20+
if self.fm is None and fail_on_failure:
2121
from vsc.visitors.model_pretty_printer import ModelPrettyPrinter
2222
raise Exception("Failed to obtain field from expression %s" % (
2323
ModelPrettyPrinter.print(e)))
2424
return self.fm
25+
26+
def visit_expr_bin(self, e):
27+
self.fm = None
28+
29+
def visit_expr_unary(self, e):
30+
self.fm = None
31+
32+
def visit_expr_cond(self, e):
33+
self.fm = None
2534

2635
def visit_expr_fieldref(self, e):
2736
self.fm = e.fm

src/vsc/visitors/variable_bound_visitor.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from vsc.visitors.is_const_expr_visitor import IsConstExprVisitor
3939
from vsc.visitors.is_nonrand_expr_visitor import IsNonRandExprVisitor
4040
from vsc.visitors.model_pretty_printer import ModelPrettyPrinter
41+
from vsc.visitors.expr2field_visitor import Expr2FieldVisitor
4142

4243

4344
class VariableBoundVisitor(ModelVisitor):
@@ -147,29 +148,19 @@ def visit_expr_bin(self, e:ExprBinModel):
147148
isinstance(e.lhs, ExprArraySubscriptModel) or
148149
isinstance(e.rhs, ExprArraySubscriptModel)):
149150
return
150-
151+
152+
lhs_fm = Expr2FieldVisitor().field(e.lhs, fail_on_failure=False)
153+
rhs_fm = Expr2FieldVisitor().field(e.rhs, fail_on_failure=False)
154+
155+
# Check whether the expressions involve *any* random variables
151156
lhs_is_nonrand = IsNonRandExprVisitor().is_nonrand(e.lhs)
152157
rhs_is_nonrand = IsNonRandExprVisitor().is_nonrand(e.rhs)
153158

154-
if isinstance(e.lhs, ExprArraySubscriptModel):
155-
lhs_fm = e.lhs.subscript()
156-
elif isinstance(e.lhs, ExprFieldRefModel):
157-
lhs_fm = e.lhs.fm
158-
else:
159-
lhs_fm = None
160-
161159
if lhs_fm is not None and lhs_fm in self.bound_m.keys():
162160
lhs_bounds = self.bound_m[lhs_fm]
163161
else:
164162
lhs_bounds = None
165163

166-
if isinstance(e.rhs, ExprArraySubscriptModel):
167-
rhs_fm = e.rhs.subscript()
168-
elif isinstance(e.rhs, ExprFieldRefModel):
169-
rhs_fm = e.rhs.fm
170-
else:
171-
rhs_fm = None
172-
173164
if rhs_fm is not None and rhs_fm in self.bound_m.keys():
174165
rhs_bounds = self.bound_m[rhs_fm]
175166
else:

ve/unit/test_compound_obj.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ def test_c(self):
542542
self.x[0].value < self.x[1].value
543543

544544
inst=Parent()
545-
inst.randomize(debug=1)
545+
inst.randomize(debug=0)
546546
print(inst.c1[0].a[0].value)
547547
print(inst.c2[0].x[0].value)
548548

ve/unit/test_constraint_foreach.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def test_c(self):
6666
self.x[0].value < self.x[1].value
6767

6868
inst=Parent()
69-
inst.randomize(debug=1)
69+
inst.randomize(debug=0)
7070
print(inst.c1[0].a[0].value)
7171
print(inst.c2[0].x[0].value)
7272
self.assertEqual(inst.c1[0].a[0].value, inst.c2[0].x[0].value)
@@ -132,7 +132,7 @@ def test_c(self):
132132
pass
133133

134134
inst=Parent()
135-
inst.randomize(debug=1)
135+
inst.randomize(debug=0)
136136
print(inst.c1[0].a[0].value)
137137
print(inst.c2[0].x[0].value)
138138
self.assertEqual(inst.c1[0].a[0].value, inst.c2[0].x[0].value)

ve/unit/test_constraint_soft.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def dist_a(self):
6565

6666
item = my_item()
6767
for i in range(10):
68-
with item.randomize_with(debug=1) as it:
68+
with item.randomize_with(debug=0) as it:
6969
it.b > 10
7070
it.a == 1 #B
7171

ve/unit/test_field_standalone.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,14 @@ def test_distweight(self):
194194
# print("<== randomize")
195195
# print("PCID: %d" % int(PCID.get_val()))
196196

197+
def test_bit_partselect(self):
198+
199+
field = vsc.rand_uint32_t(0xFFEEAA55)
200+
201+
self.assertEqual(field.get_val(), 0xFFEEAA55)
202+
self.assertEqual(field.get_val()[7:0], 0x55)
203+
self.assertEqual(field.get_val()[11:4], 0xA5)
204+
self.assertEqual(field.get_val()[31], 1)
205+
self.assertEqual(field.get_val()[0], 1)
206+
self.assertEqual(field.get_val()[8], 0)
197207

0 commit comments

Comments
 (0)