Skip to content

Commit

Permalink
Merge pull request #222 from alwilson/toposort_random_stability
Browse files Browse the repository at this point in the history
Make list solve_order predictable
  • Loading branch information
mballance authored Jul 13, 2024
2 parents 5f79289 + 46b44a8 commit c0b307f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
17 changes: 8 additions & 9 deletions src/vsc/model/rand_info_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,14 @@ def build(
if f in builder._order_m.keys():
rs_deps[f] = builder._order_m[f]

if len(rs_deps) > 0:
rs.rand_order_l = []
for fs in list(toposort(rs_deps)):
field_l = []
for fi in fs:
if fi in rs.fields():
field_l.append(fi)
if len(field_l) > 0:
rs.rand_order_l.append(field_l)
if len(rs_deps) > 0:
rs.rand_order_l = []
# Random stability warning: toposort uses sets and is unordered
for fs in list(toposort(rs_deps)):
# Add fields in predictable randset order
field_l = [fi for fi in rs.fields() if fi in fs]
if len(field_l) > 0:
rs.rand_order_l.append(field_l)

# It's important to maintain a fixed order for the
# unconstrained fields, since this affects their
Expand Down
39 changes: 39 additions & 0 deletions ve/unit/test_constraint_solve_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,42 @@ def loop_c(self):
self.assertNotEqual(0, num_of_nested_loop_hist[1])
self.assertNotEqual(0, num_of_nested_loop_hist[2])


def test_toposort_random_stability(self):
@vsc.randobj
class my_s(object):

def __init__(self):
self.a = vsc.rand_bit_t(8)
self.list_0 = vsc.rand_list_t(vsc.rand_bit_t(8), 10)
self.list_1 = vsc.rand_list_t(vsc.rand_bit_t(8), 10)

@vsc.constraint
def a_and_lists_c(self):
# Excercise rand_order/toposort on lists
vsc.solve_order(self.a, self.list_0)
vsc.solve_order(self.list_0, self.list_1)

# Make lists unique to better detect ordering differences
vsc.unique(self.list_0)
vsc.unique(self.list_1)

# Tie all variables into single randset
self.a > 10
self.a < 20
with vsc.foreach(self.list_0) as it:
it < self.a
with vsc.foreach(self.list_1) as it:
it < self.a

first = my_s()
first.set_randstate(vsc.RandState.mkFromSeed(0))
first.randomize()

for _ in range(20):
repeat = my_s()
repeat.set_randstate(vsc.RandState.mkFromSeed(0))
repeat.randomize()
self.assertEqual(first.a, repeat.a, "Mismatch on a")
self.assertListEqual(list(first.list_0), list(repeat.list_0), "Mismatch on list_0")
self.assertListEqual(list(first.list_1), list(repeat.list_1), "Mismatch on list_1")

0 comments on commit c0b307f

Please sign in to comment.