From c5325abca0a32d5d462d11bc0ccb0d6cc77fd267 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 20 Mar 2019 09:13:44 +0000 Subject: [PATCH] add a class-based unit test, found bug in eq function as a result: eq function from Example2OpClass was returning a list of assignment statements, which was resulting in a list-of-lists being created. flattening to a single 1D list was required --- src/add/example_buf_pipe.py | 9 +++-- src/add/test_buf_pipe.py | 70 ++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py index 0574ff35..c399570a 100644 --- a/src/add/example_buf_pipe.py +++ b/src/add/example_buf_pipe.py @@ -112,8 +112,8 @@ class NextControl: def eq(o, i): """ makes signals equal: a helper routine which identifies if it is being - passsed a list (or tuple) of objects, and calls the objects' eq - function. + passed a list (or tuple) of objects, or signals, or Records, and calls + the objects' eq function. complex objects (classes) can be used: they must follow the convention of having an eq member function, which takes the @@ -138,7 +138,10 @@ def eq(o, i): rres = eq(ao.fields[field_name], ai[field_name]) res += rres else: - res.append(ao.eq(ai)) + rres = ao.eq(ai) + if not isinstance(rres, Sequence): + rres = [rres] + res += rres return res diff --git a/src/add/test_buf_pipe.py b/src/add/test_buf_pipe.py index 55307cd3..546e6ad7 100644 --- a/src/add/test_buf_pipe.py +++ b/src/add/test_buf_pipe.py @@ -5,7 +5,7 @@ from nmigen.cli import verilog, rtlil from example_buf_pipe import ExampleBufPipe, ExampleBufPipeAdd from example_buf_pipe import ExampleCombPipe, CombPipe -from example_buf_pipe import PrevControl, NextControl +from example_buf_pipe import PrevControl, NextControl, BufferedPipeline from random import randint @@ -367,6 +367,68 @@ def test7_resultfn(o_data, expected, i, o): % (i, o, repr(o_data), repr(expected)) +class Example2OpClass: + """ an example of a class used to store 2 operands. + requires an eq function, to conform with the pipeline stage API + """ + + def __init__(self): + self.op1 = Signal(16) + self.op2 = Signal(16) + + def eq(self, i): + return [self.op1.eq(i.op1), self.op2.eq(i.op2)] + + +class ExampleAddClassStage: + """ an example of how to use the buffered pipeline, as a class instance + """ + + def ispec(self): + """ returns an instance of an Example2OpClass. + """ + return Example2OpClass() + + def ospec(self): + """ returns an output signal which will happen to contain the sum + of the two inputs + """ + return Signal(16) + + def process(self, i): + """ process the input data (sums the values in the tuple) and returns it + """ + return i.op1 + i.op2 + + +class ExampleBufPipeAddClass(BufferedPipeline): + """ an example of how to use the buffered pipeline, using a class instance + """ + + def __init__(self): + addstage = ExampleAddClassStage() + BufferedPipeline.__init__(self, addstage) + + +class TestInputAdd: + def __init__(self, op1, op2): + self.op1 = op1 + self.op2 = op2 + + +def test8_resultfn(o_data, expected, i, o): + res = expected.op1 + expected.op2 + assert o_data == res, \ + "%d-%d data %x not match %s\n" \ + % (i, o, o_data, repr(expected)) + +def data_2op(): + data = [] + for i in range(num_tests): + data.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1))) + return data + + num_tests = 100 if __name__ == '__main__': @@ -423,3 +485,9 @@ if __name__ == '__main__': with open("test_recordcomb_pipe.il", "w") as f: f.write(vl) + print ("test 8") + dut = ExampleBufPipeAddClass() + data=data_2op() + test = Test5(dut, test8_resultfn, data=data) + run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe8.vcd") + -- 2.30.2