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
|