Skip to content

Commit 36aca2d

Browse files
committed
0.9.0
- (#219) - Add `unique_vec` constraint to support unique-vector constraints Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
1 parent 1df7609 commit 36aca2d

9 files changed

+156
-2
lines changed

doc/Changelog.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11

2+
## 0.9.0
3+
- (#219) - Add `unique_vec` constraint to support unique-vector constraints
4+
25
## 0.8.9
36
- (#205) - Ensure that recursive references between objects don't cause recursion
47

etc/ivpm.info

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

22
name=pyvsc
3-
version=0.8.9
3+
version=0.9.0
44

src/vsc/constraints.py

+19
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@
3131
from vsc.model.constraint_soft_model import ConstraintSoftModel
3232
from vsc.model.constraint_solve_order_model import ConstraintSolveOrderModel
3333
from vsc.model.constraint_unique_model import ConstraintUniqueModel
34+
from vsc.model.constraint_unique_vec_model import ConstraintUniqueVecModel
3435
from vsc.model.dist_weight_expr_model import DistWeightExprModel
3536
from vsc.model.expr_array_subscript_model import ExprArraySubscriptModel
3637
from vsc.model.expr_dynref_model import ExprDynRefModel
3738
from vsc.model.expr_fieldref_model import ExprFieldRefModel
39+
from vsc.model.field_array_model import FieldArrayModel
3840
from vsc.model.expr_indexed_field_ref_model import ExprIndexedFieldRefModel
3941
from vsc.model.field_scalar_model import FieldScalarModel
4042
from vsc.types import to_expr, expr, type_base, rng
@@ -271,6 +273,23 @@ def unique(*args):
271273
if in_srcinfo_mode():
272274
c.srcinfo = SourceInfo.mk()
273275
push_constraint_stmt(c)
276+
277+
def unique_vec(*args):
278+
expr_l = []
279+
for i in range(-1, -(len(args)+1), -1):
280+
to_expr(args[i])
281+
e = pop_expr()
282+
if not isinstance(e, ExprFieldRefModel) or not isinstance(e.fm, FieldArrayModel):
283+
raise Exception("All arguments to unique_vec must be lists")
284+
expr_l.insert(0, e)
285+
286+
if len(expr_l) < 2:
287+
raise Exception("Must specify at least two vectors to uniquify")
288+
289+
c = ConstraintUniqueVecModel(expr_l)
290+
if in_srcinfo_mode():
291+
c.srcinfo = SourceInfo.mk()
292+
push_constraint_stmt(c)
274293

275294
class forall(object):
276295

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
19+
# Created on Jul 28, 2019
20+
#
21+
# @author: ballance
22+
23+
from vsc.model.constraint_model import ConstraintModel
24+
from vsc.model.expr_bin_model import ExprBinModel
25+
from vsc.model.bin_expr_type import BinExprType
26+
from vsc.model.expr_fieldref_model import ExprFieldRefModel
27+
from vsc.model.field_array_model import FieldArrayModel
28+
29+
class ConstraintUniqueVecModel(ConstraintModel):
30+
31+
def __init__(self, unique_l):
32+
super().__init__()
33+
self.unique_l = unique_l
34+
self.expr = None
35+
36+
def build(self, btor, soft=False):
37+
ret = None
38+
39+
# Elements in the unique list might be arrays
40+
unique_l = []
41+
42+
sz = -1
43+
for i in self.unique_l:
44+
if sz == -1:
45+
sz = len(i.fm.field_l)
46+
elif sz != len(i.fm.field_l):
47+
raise Exception("All arguments to unique_vec must be of the same size")
48+
49+
# Form ORs of inequalities across the vector pairs
50+
and_e = None
51+
for i in range(len(self.unique_l)):
52+
for j in range(i+1, len(self.unique_l)):
53+
v_ne = self._mkVecNotEq(btor, self.unique_l[i], self.unique_l[j])
54+
55+
if and_e is None:
56+
and_e = v_ne
57+
else:
58+
and_e = btor.And(and_e, v_ne)
59+
60+
return and_e
61+
62+
def _mkVecNotEq(self, btor, v1, v2):
63+
ret = None
64+
for i in range(len(v1.fm.field_l)):
65+
ne = ExprBinModel(
66+
ExprFieldRefModel(v1.fm.field_l[i]),
67+
BinExprType.Ne,
68+
ExprFieldRefModel(v2.fm.field_l[i]))
69+
if ret is None:
70+
ret = ne.build(btor)
71+
else:
72+
ret = btor.Or(ne.build(btor), ret)
73+
return ret
74+
75+
def accept(self, visitor):
76+
visitor.visit_constraint_unique_vec(self)
77+
78+
def clone(self, deep=False)->'ConstraintModel':
79+
ret = ConstraintUniqueVecModel(self.unique_l)
80+
81+
return ret
82+

src/vsc/model/model_visitor.py

+7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from vsc.model.constraint_implies_model import ConstraintImpliesModel
3131
from vsc.model.constraint_scope_model import ConstraintScopeModel
3232
from vsc.model.constraint_unique_model import ConstraintUniqueModel
33+
from vsc.model.constraint_unique_vec_model import ConstraintUniqueVecModel
3334
from vsc.model.expr_bin_model import ExprBinModel
3435
from vsc.model.expr_cond_model import ExprCondModel
3536
from vsc.model.covergroup_model import CovergroupModel
@@ -158,6 +159,12 @@ def visit_constraint_unique(self, c : ConstraintUniqueModel):
158159
for e in c.unique_l:
159160
e.accept(self)
160161
self.visit_constraint_stmt_leave(c)
162+
163+
def visit_constraint_unique_vec(self, c : ConstraintUniqueVecModel):
164+
self.visit_constraint_stmt_enter(c)
165+
for e in c.unique_l:
166+
e.accept(self)
167+
self.visit_constraint_stmt_leave(c)
161168

162169
def visit_expr_array_product(self, s):
163170
self.visit_expr_dynamic(s)

src/vsc/types.py

+4
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,9 @@ def __init__(self, l):
983983
self.l = l
984984
self.model = l._int_field_info.model
985985
self.idx = 0
986+
987+
def __iter__(self):
988+
return self
986989

987990
def __next__(self):
988991
if self.idx >= int(self.model.size.get_val()):
@@ -997,6 +1000,7 @@ def __next__(self):
9971000

9981001
self.idx += 1
9991002
return int(v)
1003+
10001004
class list_object_it(object):
10011005
def __init__(self, l):
10021006
self.l = l

src/vsc/visitors/variable_bound_visitor.py

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from vsc.model.constraint_inline_scope_model import ConstraintInlineScopeModel
1515
from vsc.model.constraint_soft_model import ConstraintSoftModel
1616
from vsc.model.constraint_unique_model import ConstraintUniqueModel
17+
from vsc.model.constraint_unique_vec_model import ConstraintUniqueVecModel
1718
from vsc.model.enum_field_model import EnumFieldModel
1819
from vsc.model.expr_array_subscript_model import ExprArraySubscriptModel
1920
from vsc.model.expr_bin_model import ExprBinModel
@@ -134,6 +135,11 @@ def visit_constraint_unique(self, c:ConstraintUniqueModel):
134135
# Don't go into an unexpanded unique block. This
135136
# construct is a meta-constraint that will be expanded
136137
pass
138+
139+
def visit_constraint_unique_vec(self, c:ConstraintUniqueModel):
140+
# Don't go into an unexpanded unique block. This
141+
# construct is a meta-constraint that will be expanded
142+
pass
137143

138144
def visit_expr_bin(self, e:ExprBinModel):
139145
# TODO: We'll need to deal with expressions that involve variables

ve/unit/test_constraint_functions.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ def clog2_c(self):
3131
for i in range(256):
3232
with c.randomize_with():
3333
c.b == i
34-
print("a=%d b=%d" % (c.a, c.b))
34+
print("a=%d b=%d" % (c.a, c.b))
35+

ve/unit/test_unique.py

+32
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,37 @@ def a_c(self):
200200
for j in range(len(total_l)):
201201
for k in range(j+1, len(total_l)):
202202
self.assertNotEqual(total_l[j], total_l[k])
203+
204+
def test_unique_vec_smoke(self):
205+
@vsc.randobj
206+
class my_c(object):
207+
def __init__(self):
208+
self.a = vsc.rand_list_t(vsc.rand_uint16_t(1), 2)
209+
self.b = vsc.rand_list_t(vsc.rand_uint16_t(1), 2)
210+
self.c = vsc.rand_list_t(vsc.rand_uint16_t(1), 2)
211+
212+
@vsc.constraint
213+
def index_1_constraint(self):
214+
self.a[0] < 2
215+
self.b[0] < 2
216+
self.c[0] < 2
217+
self.a[1] < 2
218+
self.b[1] < 2
219+
self.c[1] < 2
220+
221+
@vsc.constraint
222+
def unique_list_constraint(self):
223+
vsc.unique_vec(self.a, self.b, self.c)
224+
225+
it = my_c()
226+
print("A:")
227+
for i in range(len(it.a)):
228+
print(" %d" % it.a[i])
229+
print("B:")
230+
for i in range(len(it.b)):
231+
print(" %d" % it.b[i])
232+
print("C:")
233+
for i in range(len(it.c)):
234+
print(" %d" % it.c[i])
203235

204236

0 commit comments

Comments
 (0)