Re: please help with best way how to construct unittest testbench

Christopher Felton <[email protected]> Fri, 29 Jan 2016 10:26:24 -0600
Newsgroups gmane.comp.python.myhdl
Message-ID <[email protected]>
On 1/29/16 9:05 AM, David Belohrad wrote:
> Dear all,
>
> my question is simple: when using unittest/testcase, one can write
> more testbenches. I have wrote one, like the one below. As you can
> see, the 'testbench' is quite long, as one has to initialize all the
> signals, instantiate the DUT, provide reset and clock, and it does
> nothing (yet).
>
> I want to add a second test-bench, but I'd like to re-use the
> fraction of instantiation and initialization of the DUT.


This is where things get fun :)  Yes, use the power of
Python to create reusable things, the following are some
reusability items I have used in the past:

1) This is the testbench template I use (I am sure it
can be improved upon):
https://gist.github.com/cfelton/17bfc798550aa9ed8e04

2) Clock object with gen method

      clock = Clock(frequency=125e6)
      tbclk = clock.gen()

https://github.com/cfelton/rhea/blob/master/rhea/system/clock.py

3) Reset object with `pulse` method

      reset = Reset(0, active=0, async=True)
      ...
      @instance
      def tbstim():
          yield reset.pulse(10)

4) Interfaces with transactor methods!  This simplifies
a lot.

     class SomeInterface():
         ...

     bus = SomeInterface()

     tbdut = my_dut(clock, reset, bus)

     @instance
     def tbstim():
         yield bus.write()
         yield bus.read()
         # ...

5) portmap dicts, I create a dict with all the signals
in the module port arguments, the portmap can be reused.
Often I connect a portmap to a top-level (since top-level
ports a tied to the physical hardware and fixed)

     def my_top_level_module(clock, reset, sdi, sdo):
         ...
     my_top_level_module.portmap = {
         clock: Clock(),
         reset: Reset(),
         sdi: Signal(bool(0))
         sdo: Signal(bool(0))
     }


Use functions to wrap common tasks, use generators to
wrap common simulation sequences, etc.

     # another reset resuse
     def doreset(reset):
         reset.next = reset.active
         yield delay(30)
         reset.next = not reset.active

    @instance
    def tbstim():
        # reuse in various stimulus
        yield doreset(reset)


As others have pointed out, use the various features
of Python to make reusable objects.

Keerthan has some utilities to simplify some of these
task as well (setting up cosim, testbench generators, etc.)
https://github.com/jck/uhdl

You don't need to limit yourself to the above examples,
there is a lot you can do with Python and reusability.

Regards,
Chris



------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140