From 35d3e55ad39f6bb37d9be3fb7a855fd89dd30899 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Sun, 14 Jul 2024 20:46:26 -0600 Subject: [PATCH 1/2] Collect solve-order constraints from with statements With debug=True solve-order constraints would show up but would not be applied b/c with constraints are not explored during the first pass (pass=0). --- src/vsc/model/rand_info_builder.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vsc/model/rand_info_builder.py b/src/vsc/model/rand_info_builder.py index 8b49e36..b7beac7 100644 --- a/src/vsc/model/rand_info_builder.py +++ b/src/vsc/model/rand_info_builder.py @@ -98,11 +98,15 @@ def build( builder = RandInfoBuilder(rng) - # First, collect all the fields + # First, collect all fields and ordering from constraints builder._pass = 0 for fm in field_model_l: fm.accept(builder) - + + # Collect all fields and ordering from standalone constraints passed to the function + for c in constraint_l: + c.accept(builder) + builder._randset_m.clear() builder._randset_l.clear() builder._randset_field_m.clear() From 59c91c13bbda8ae47a31833991bd488cfd2558a4 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Sun, 14 Jul 2024 20:52:57 -0600 Subject: [PATCH 2/2] Fix solve_order's after argument when using lists Addresses #213 Adds a unit test for the various ways to call solve_order. Update the solve_order docs with a snippet using lists. --- doc/source/constraints.rst | 11 ++++++- src/vsc/constraints.py | 2 +- ve/unit/test_constraint_solve_order.py | 42 ++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/doc/source/constraints.rst b/doc/source/constraints.rst index 2e2cea9..d9b823f 100644 --- a/doc/source/constraints.rst +++ b/doc/source/constraints.rst @@ -488,10 +488,19 @@ statement corresponds to the SystemVerilog `solve a before b` statement. with vsc.else_then: self.b != 4 -In the example above, te `solve_order` statement causes `b` to +In the example above, the `solve_order` statement causes `b` to have values evenly distributed between the value sets [4] and [0..3,5..255]. +Use lists of variables to create multiple solve-order constraints. +The example below solves `a` and `b` before `c` and `d`. + +.. code-block:: python3 + + @vsc.constraint + def abcd_c(self): + vsc.solve_order([self.a, self.b], [self.c, self.d]) + unique ------ The `unique` constraint ensures that all variables in the specified list have diff --git a/src/vsc/constraints.py b/src/vsc/constraints.py index af934e0..4a28ed8 100644 --- a/src/vsc/constraints.py +++ b/src/vsc/constraints.py @@ -431,7 +431,7 @@ def solve_order(before, after): a_e = pop_expr() if not isinstance(a_e, ExprFieldRefModel): raise Exception("Parameter " + str(a) + " is not a field reference") - before_l.append(a_e.fm) + after_l.append(a_e.fm) else: to_expr(after) after_e = pop_expr() diff --git a/ve/unit/test_constraint_solve_order.py b/ve/unit/test_constraint_solve_order.py index 19b1d37..0dc8b02 100644 --- a/ve/unit/test_constraint_solve_order.py +++ b/ve/unit/test_constraint_solve_order.py @@ -362,3 +362,45 @@ def a_and_lists_c(self): 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") + + def test_before_and_after_lists(self): + + @vsc.randobj + class my_c(object): + + def __init__(self): + self.a = vsc.rand_bit_t(64) + self.b = vsc.rand_bit_t(64) + self.c = vsc.rand_bit_t(1) + + @vsc.constraint + def abc_c(self): + # If a or b is solved first then it's extremely likley + # that all variables will be non-zero + with vsc.implies(self.c == 0): + self.a == 0 + self.b == 0 + + def test_solve_order(order): + a_hist = [0]*2 + b_hist = [0]*2 + c_hist = [0]*2 + samples = 100 + + for _ in range(samples): + with i.randomize_with(): + order() + a_hist[i.a > 0] += 1 + b_hist[i.b > 0] += 1 + c_hist[i.c > 0] += 1 + self.assertEqual(a_hist[1], samples) + self.assertEqual(b_hist[1], samples) + self.assertEqual(c_hist[1], samples) + + i = my_c() + + # Test various combinations of before and after arguments + test_solve_order(lambda: vsc.solve_order( i.a , i.c )) + test_solve_order(lambda: vsc.solve_order( i.a , [i.c])) + test_solve_order(lambda: vsc.solve_order([i.a, i.b], i.c )) + test_solve_order(lambda: vsc.solve_order([i.a, i.b], [i.c]))