Re: [myhdl-list] difficulty using itertools with MyHDL
Brought to you by:
jandecaluwe
From: George P. <ge...@ga...> - 2006-10-20 11:12:37
|
I agree, I think I could have done a better job explaining what I wanted to do. I want to run multi-stage simulations for automated unit testing. For example, I have a ring buffer that I want to unit test. For some tests I want to check the border case where its full and read or writes are done to it. The first stage of the test involves filling it to capacity. The second stage involves driving signals and checking outputs. There could be multiple tests that start off by filling it up, so in practice I'd want to reuse the filler function. Stage 1: Fill ring buffer. Stage 2: Simultaneously drive signals and check outputs If I just return instances() then all the generators will be run together by the Simulation class, which is not what I want. Thus, I use chain() to impose an ordering. For Stage 2 I use izip() to ensure that the driver and monitor are run in lockstep. It goes something like this: stage1 = filler() stage2 = izip(driver, monitor) complete_sequence = chain(stage1, stage2) Right now I just copied and pasted the itertools functions from the Python docs into my code. In this way they are generators, and not itertools objects. Perhaps this is because in the Python library they inherit from a superclass and I don't? I've left out the definition of the Driver and Monitor, but they are ordinary generators like the ones found in the test benches in your cookbooks. def bench(): # I've deliberately glossed over the dut setup dut = RingBuffer(clk, rst, dat_i, we) clk = Signal(bool(0)) clkgen = ClkGen(clk) def filler(): # Fill up the Ring Buffer for i in range(depth): # Set up a write dat_i.next = i+10 we.next = True yield clk.posedge yield clk.negedge # De-assert the write enable we.next = False yield clk.posedge yield clk.negedge # Itertools can't directly be used. # Seems that the _Simulation.py checks for GeneratorType, but itertools object are not of that # type. See one idea for a solution here: # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/439359 # duplicate of Python's built-in izip(), except this one is of type 'generator' def izip(*iterables): iterables = map(iter, iterables) while iterables: result = [it.next() for it in iterables] yield tuple(result) # Same goes for chain: def chain(*iterables): for it in iterables: for element in it: yield element # Stage 1 - Fill the ring buffer stage1 = filler() # Stage 2 - Perform border-case testing # Simultaneously drive signals and monitor them stage2 = izip(driver, monitor) # Make this look like a generator def stopsim(): raise StopSimulation() yield None # Chain the generators so they run sequentially ordered_tests = chain(stage1, stage2, stopsim()) return clkgen, dut, ordered_tests # For py.test def test_1(): tb = traceSignals(bench()) sim = Simulation(tb) sim.run() Sorry for the confusion earlier. Does this help you understand what I want to accomplish? This is already working for me, except that I have to redefine izip() and ichain() myself. Perhaps you know of a better way to do this? Thanks, George |