Parameterize the issuer on the number of operands and results
authorCesar Strauss <cestrauss@gmail.com>
Mon, 23 Nov 2020 10:40:04 +0000 (07:40 -0300)
committerCesar Strauss <cestrauss@gmail.com>
Mon, 23 Nov 2020 10:50:07 +0000 (07:50 -0300)
This allows reuse for the DummyALU, which has three operands, but is
otherwise similar to the ALU in terms of operations.

Also, the issuer now creates the producers and consumers.

src/soc/experiment/test/test_compalu_multi.py

index 7c3d122ca6f9f4339d4ecfe076a211dd78e6d1fa..fb22a58a40b22404910fbeb7a995840e76f2106f 100644 (file)
@@ -292,29 +292,38 @@ class OpSim:
     """ALU Operation issuer
 
     Issues operations to the DUT"""
-    def __init__(self, dut, producers, consumers):
+    def __init__(self, dut, sim):
         self.op_count = 0
         self.zero_a_count = 0
         self.imm_ok_count = 0
         self.dut = dut
-        self.producers = producers
-        self.consumers = consumers
-
-    def issue(self, a, b, op, expected, delays,
+        # create one operand producer for each input port
+        self.producers = list()
+        for i in range(len(dut.src_i)):
+            self.producers.append(OperandProducer(sim, dut, i))
+        # create one result consumer for each output port
+        self.consumers = list()
+        for i in range(len(dut.dest)):
+            self.consumers.append(ResultConsumer(sim, dut, i))
+    def issue(self, src_i, op, expected, src_delays, dest_delays,
               inv_a=0, imm=0, imm_ok=0, zero_a=0):
         """Executes the issue operation"""
         dut = self.dut
         producers = self.producers
         consumers = self.consumers
-        print("issue", a, b, op, expected)
         yield dut.issue_i.eq(0)
         yield
         # forward data and delays to the producers and consumers
+        # first, send special cases (with zero_a and/or imm_ok)
         if not zero_a:
-            yield from producers[0].send(a, delays[0])
+            yield from producers[0].send(src_i[0], src_delays[0])
         if not imm_ok:
-            yield from producers[1].send(b, delays[1])
-        yield from consumers[0].receive(expected, delays[2])
+            yield from producers[1].send(src_i[1], src_delays[1])
+        # then, send the rest (if any)
+        for i in range(2, len(producers)):
+            yield from producers[i].send(src_i[i], src_delays[i])
+        for i in range(len(consumers)):
+            yield from consumers[i].receive(expected, dest_delays[i])
         # submit operation, and assert issue_i for one cycle
         yield dut.oper_i.insn_type.eq(op)
         yield dut.oper_i.invert_in.eq(inv_a)
@@ -340,36 +349,47 @@ class OpSim:
             self.imm_ok_count = self.imm_ok_count + 1
         # check that producers and consumers have the same count
         # this assures that no data was left unused or was lost
+        # first, check special cases (zero_a and imm_ok)
         assert (yield producers[0].count) + self.zero_a_count == self.op_count
         assert (yield producers[1].count) + self.imm_ok_count == self.op_count
-        assert (yield consumers[0].count) == self.op_count
+        # then, check the rest (if any)
+        for i in range(2, len(producers)):
+            assert (yield producers[i].count) == self.op_count
+        for i in range(len(consumers)):
+            assert (yield consumers[i].count) == self.op_count
 
 
 def scoreboard_sim(op):
     # zero (no) input operands test
     # 0 + 8 = 8
-    yield from op.issue(5, 2, MicrOp.OP_ADD,
+    yield from op.issue([5, 2], MicrOp.OP_ADD,
                         zero_a=1, imm=8, imm_ok=1,
-                        expected=8, delays=[0, 2, 0])
+                        expected=8,
+                        src_delays=[0, 2], dest_delays=[0])
     # 5 + 8 = 13
-    yield from op.issue(5, 2, MicrOp.OP_ADD,
+    yield from op.issue([5, 2], MicrOp.OP_ADD,
                         inv_a=0, imm=8, imm_ok=1,
-                        expected=13, delays=[2, 0, 2])
+                        expected=13,
+                        src_delays=[2, 0], dest_delays=[2])
     # 5 + 2 = 7
-    yield from op.issue(5, 2, MicrOp.OP_ADD,
-                        expected=7, delays=[1, 1, 1])
+    yield from op.issue([5, 2], MicrOp.OP_ADD,
+                        expected=7,
+                        src_delays=[1, 1], dest_delays=[1])
     # (-6) + 2 = (-4)
-    yield from op.issue(5, 2, MicrOp.OP_ADD, inv_a=1,
-                        expected=65532, delays=[1, 2, 0])
+    yield from op.issue([5, 2], MicrOp.OP_ADD, inv_a=1,
+                        expected=65532,
+                        src_delays=[1, 2], dest_delays=[0])
     # 0 + 2 = 2
-    yield from op.issue(5, 2, MicrOp.OP_ADD, zero_a=1,
-                        expected=2, delays=[2, 0, 1])
+    yield from op.issue([5, 2], MicrOp.OP_ADD, zero_a=1,
+                        expected=2,
+                        src_delays=[2, 0], dest_delays=[1])
 
     # test combinatorial zero-delay operation
     # In the test ALU, any operation other than ADD, MUL or SHR
     # is zero-delay, and do a subtraction.
-    yield from op.issue(5, 2, MicrOp.OP_NOP,
-                        expected=3, delays=[0, 1, 2])
+    yield from op.issue([5, 2], MicrOp.OP_NOP,
+                        expected=3,
+                        src_delays=[0, 1], dest_delays=[2])
 
 
 def test_compunit_fsm():
@@ -453,13 +473,8 @@ def test_compunit():
     sim = Simulator(m)
     sim.add_clock(1e-6)
 
-    # create one operand producer for each input port
-    prod_a = OperandProducer(sim, dut, 0)
-    prod_b = OperandProducer(sim, dut, 1)
-    # create an result consumer for the output port
-    cons = ResultConsumer(sim, dut, 0)
     # create an operation issuer
-    op = OpSim(dut, [prod_a, prod_b], [cons])
+    op = OpSim(dut, sim)
     sim.add_sync_process(wrap(scoreboard_sim(op)))
     sim_writer = sim.write_vcd('test_compunit1.vcd')
     with sim_writer:
@@ -794,18 +809,13 @@ def test_compunit_regspec1():
     sim = Simulator(m)
     sim.add_clock(1e-6)
 
-    # create one operand producer for each input port
-    prod_a = OperandProducer(sim, dut, 0)
-    prod_b = OperandProducer(sim, dut, 1)
-    # create an result consumer for the output port
-    cons = ResultConsumer(sim, dut, 0)
     # create an operation issuer
-    op = OpSim(dut, [prod_a, prod_b], [cons])
+    op = OpSim(dut, sim)
     sim.add_sync_process(wrap(scoreboard_sim(op)))
     sim_writer = sim.write_vcd('test_compunit_regspec1.vcd',
-                               traces=[prod_a.count,
-                                       prod_b.count,
-                                       cons.count])
+                               traces=[op.producers[0].count,
+                                       op.producers[1].count,
+                                       op.consumers[0].count])
     with sim_writer:
         sim.run()