Thread: [myhdl-list] yield before the end of a simulation
Brought to you by:
jandecaluwe
From: Oscar D. <osc...@gm...> - 2011-12-20 11:35:47
|
Hi I have a testbench that needs to do some asserts at the end of a simulation. However, I couldn't find an elegant way to do it. Right now I'm passing to the testbench generator the same duration as in "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" and do the final asserts (by the way, in my case all my simulations have a defined duration). I tried to catch the StopSimulation exception, but it doesn't work inside a generator. Any ideas? Thanks! Best regards -- Oscar Díaz Key Fingerprint = 904B 306C C3C2 7487 650B BFAC EDA2 B702 90E9 9964 gpg --keyserver subkeys.pgp.net --recv-keys 90E99964 I recommend using OpenDocument Format for daily use and exchange of documents. http://www.fsf.org/campaigns/opendocument |
From: Christopher F. <chr...@gm...> - 2011-12-20 13:17:28
|
On 12/20/2011 5:35 AM, Oscar Diaz wrote: > Hi > > I have a testbench that needs to do some asserts at the end of a > simulation. However, I couldn't find an elegant way to do it. Right > now I'm passing to the testbench generator the same duration as in > "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" > and do the final asserts (by the way, in my case all my simulations > have a defined duration). I tried to catch the StopSimulation > exception, but it doesn't work inside a generator. Any ideas? Thanks! > > Best regards > I believe you can catch exceptions in generators. At least the generator PEP says so and the following works. ~~~ [Code Snip] ~~~ from myhdl import * def test(): @instance def ex_in_g(): try: for ii in xrange(10): yield delay(7) raise StopSimulation except Exception, e: print("Caught exception %s" % (str(e))) raise StopSimulation return ex_in_g if __name__ == '__main__': Simulation(test()).run() ~~~~~~~~~~~~~~~~~~~~~~~ Regards, Chris |
From: Oscar D. <osc...@gm...> - 2011-12-20 13:55:12
|
2011/12/20 Christopher Felton <chr...@gm...>: > On 12/20/2011 5:35 AM, Oscar Diaz wrote: >> Hi >> >> I have a testbench that needs to do some asserts at the end of a >> simulation. However, I couldn't find an elegant way to do it. Right >> now I'm passing to the testbench generator the same duration as in >> "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" >> and do the final asserts (by the way, in my case all my simulations >> have a defined duration). I tried to catch the StopSimulation >> exception, but it doesn't work inside a generator. Any ideas? Thanks! >> >> Best regards >> > > I believe you can catch exceptions in generators. At least the > generator PEP says so and the following works. > > ~~~ [Code Snip] ~~~ > from myhdl import * > def test(): > @instance > def ex_in_g(): > try: > for ii in xrange(10): > yield delay(7) > raise StopSimulation > > except Exception, e: > print("Caught exception %s" % (str(e))) > raise StopSimulation > > return ex_in_g > > if __name__ == '__main__': > Simulation(test()).run() > ~~~~~~~~~~~~~~~~~~~~~~~ That's the case when the exception is raised inside the generator, which is not my case. I'm trying to something like this: ~~~ [Code Snip] ~~~ from myhdl import * def test(): @instance def ex_in_g(): try: for ii in xrange(10): yield delay(7) # ideally it shouldn't got here return except Exception, e: # or maybe better "except StopSimulation" ? print("Caught exception %s" % (str(e))) raise StopSimulation return ex_in_g if __name__ == '__main__': # fixed simulation time Simulation(test()).run(50) ~~~~~~~~~~~~~~~~~~~~~~~ It doesn't work because the exception is raised inside the run() method. Right now my project store the simulation duration to yield before raising StopSimulation, like this: ~~~ [Code Snip] ~~~ from myhdl import * sim_duration = 100 def test(): @instance def main_block(): # do some stuff return @instance def last_check(): yield delay(sim_duration - 1) print "do some final asserts..." return return instances() if __name__ == '__main__': Simulation(test()).run(sim_duration) ~~~~~~~~~~~~~~~~~~~~~~~ Any ideas to improve this issue? Best regards > > Regards, > Chris > > > ------------------------------------------------------------------------------ > Write once. Port to many. > Get the SDK and tools to simplify cross-platform app development. Create > new or port existing apps to sell to consumers worldwide. Explore the > Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join > http://p.sf.net/sfu/intel-appdev > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list -- Oscar Díaz Key Fingerprint = 904B 306C C3C2 7487 650B BFAC EDA2 B702 90E9 9964 gpg --keyserver subkeys.pgp.net --recv-keys 90E99964 I recommend using OpenDocument Format for daily use and exchange of documents. http://www.fsf.org/campaigns/opendocument |
From: Christopher F. <chr...@gm...> - 2011-12-23 14:49:02
|
On Tuesday, December 20, 2011, Oscar Diaz <osc...@gm...> wrote: > 2011/12/20 Christopher Felton <chr...@gm...>: >> On 12/20/2011 5:35 AM, Oscar Diaz wrote: >>> Hi >>> >>> I have a testbench that needs to do some asserts at the end of a >>> simulation. However, I couldn't find an elegant way to do it. Right >>> now I'm passing to the testbench generator the same duration as in >>> "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" >>> and do the final asserts (by the way, in my case all my simulations >>> have a defined duration). I tried to catch the StopSimulation >>> exception, but it doesn't work inside a generator. Any ideas? Thanks! >>> >>> Best regards >>> >> >> I believe you can catch exceptions in generators. At least the >> generator PEP says so and the following works. >> >> ~~~ [Code Snip] ~~~ >> from myhdl import * >> def test(): >> @instance >> def ex_in_g(): >> try: >> for ii in xrange(10): >> yield delay(7) >> raise StopSimulation >> >> except Exception, e: >> print("Caught exception %s" % (str(e))) >> raise StopSimulation >> >> return ex_in_g >> >> if __name__ == '__main__': >> Simulation(test()).run() >> ~~~~~~~~~~~~~~~~~~~~~~~ > > That's the case when the exception is raised inside the generator, > which is not my case. I'm trying to something like this: > > ~~~ [Code Snip] ~~~ > from myhdl import * > def test(): > @instance > def ex_in_g(): > try: > for ii in xrange(10): > yield delay(7) > # ideally it shouldn't got here > return > > except Exception, e: > # or maybe better "except StopSimulation" ? > print("Caught exception %s" % (str(e))) > raise StopSimulation > > return ex_in_g > > if __name__ == '__main__': > # fixed simulation time > Simulation(test()).run(50) > ~~~~~~~~~~~~~~~~~~~~~~~ > > It doesn't work because the exception is raised inside the run() > method. Right now my project store the simulation duration to yield > before raising StopSimulation, like this: > ~~~ [Code Snip] ~~~ > from myhdl import * > sim_duration = 100 > def test(): > @instance > def main_block(): > # do some stuff > return > > @instance > def last_check(): > yield delay(sim_duration - 1) > print "do some final asserts..." > return > > return instances() > > if __name__ == '__main__': > Simulation(test()).run(sim_duration) > ~~~~~~~~~~~~~~~~~~~~~~~ > > Any ideas to improve this issue? > > Best regards > >> >> Regards, >> Chris >> >> Another option you could try is to run the simulation from the test function. After the simulation completes the final state is preserved and you can do the final checks. I haven't tried it. In the above example, the test function you could do the following. Def test(): ... Simulation((ex_in_g)).run() #checks # nothing to return Regards, Chris |
From: Uri N. <ur...@gm...> - 2011-12-26 19:32:35
|
On 23 December 2011 16:48, Christopher Felton <chr...@gm...>wrote: > > > On Tuesday, December 20, 2011, Oscar Diaz <osc...@gm...> wrote: > > 2011/12/20 Christopher Felton <chr...@gm...>: > >> On 12/20/2011 5:35 AM, Oscar Diaz wrote: > >>> Hi > >>> > >>> I have a testbench that needs to do some asserts at the end of a > >>> simulation. However, I couldn't find an elegant way to do it. Right > >>> now I'm passing to the testbench generator the same duration as in > >>> "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" > >>> and do the final asserts (by the way, in my case all my simulations > >>> have a defined duration). I tried to catch the StopSimulation > >>> exception, but it doesn't work inside a generator. Any ideas? Thanks! > >>> > >>> Best regards > >>> > >> > >> I believe you can catch exceptions in generators. At least the > >> generator PEP says so and the following works. > >> > >> ~~~ [Code Snip] ~~~ > >> from myhdl import * > >> def test(): > >> @instance > >> def ex_in_g(): > >> try: > >> for ii in xrange(10): > >> yield delay(7) > >> raise StopSimulation > >> > >> except Exception, e: > >> print("Caught exception %s" % (str(e))) > >> raise StopSimulation > >> > >> return ex_in_g > >> > >> if __name__ == '__main__': > >> Simulation(test()).run() > >> ~~~~~~~~~~~~~~~~~~~~~~~ > > > > That's the case when the exception is raised inside the generator, > > which is not my case. I'm trying to something like this: > > > > ~~~ [Code Snip] ~~~ > > from myhdl import * > > def test(): > > @instance > > def ex_in_g(): > > try: > > for ii in xrange(10): > > yield delay(7) > > # ideally it shouldn't got here > > return > > > > except Exception, e: > > # or maybe better "except StopSimulation" ? > > print("Caught exception %s" % (str(e))) > > raise StopSimulation > > > > return ex_in_g > > > > if __name__ == '__main__': > > # fixed simulation time > > Simulation(test()).run(50) > > ~~~~~~~~~~~~~~~~~~~~~~~ > > > > It doesn't work because the exception is raised inside the run() > > method. Right now my project store the simulation duration to yield > > before raising StopSimulation, like this: > > ~~~ [Code Snip] ~~~ > > from myhdl import * > > sim_duration = 100 > > def test(): > > @instance > > def main_block(): > > # do some stuff > > return > > > > @instance > > def last_check(): > > yield delay(sim_duration - 1) > > print "do some final asserts..." > > return > > > > return instances() > > > > if __name__ == '__main__': > > Simulation(test()).run(sim_duration) > > ~~~~~~~~~~~~~~~~~~~~~~~ > > > > Any ideas to improve this issue? > > > > Best regards > > > >> > >> Regards, > >> Chris > >> > >> > > Another option you could try is to run the simulation from the test > function. After the simulation completes the final state is preserved and > you can do the final checks. > > I haven't tried it. In the above example, the test function you could do > the following. > > Def test(): > ... > Simulation((ex_in_g)).run() > #checks > # nothing to return > > Regards, > Chris > > ------------------------------------------------------------------------------ > Write once. Port to many. > Get the SDK and tools to simplify cross-platform app development. Create > new or port existing apps to sell to consumers worldwide. Explore the > Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join > http://p.sf.net/sfu/intel-appdev > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list > > Hi, Perhaps something like the following is suitable: the stimulus generator halts the simulation once the vector is exhausted. No need to catch anything. I did need to use an object to store the result, since the Signals go dead at the end of the simulation. Cheers, Uri ~~~ [Code Snip] ~~~ #! /usr/bin/python import unittest import myhdl from myhdl import Signal, always, instance, delay def Clock(clk): @always(delay(1)) def logic(): clk.next ^= 1 return logic def DUT(clk, din, dout): @always(clk.posedge) def logic(): dout.next = din.val + 1 return logic class Monitor(): def __init__(self): self.sample = 0 def update(self, clk, din): @always(clk.posedge) def logic(): self.sample = din.val return logic class TestDUT(unittest.TestCase): # unittest methods def setUp(self): self.clk = Signal(0) self.din = Signal(0) self.dout = Signal(0) self.clk_inst = Clock(self.clk) self.dut_inst = DUT(self.clk, self.din, self.dout) self.monitor = Monitor() self.monitor_inst = self.monitor.update(self.clk, self.dout) def tearDown(self): pass # specific test methods (scenarios) def test_3(self): def stimulus(stimVector): @instance def logic(): for data in stimVector: self.din.next = data yield self.clk.posedge raise myhdl.StopSimulation return logic stimulus_inst = stimulus(range(1,7)) sim = myhdl.Simulation(self.dut_inst, self.clk_inst, self.monitor_inst, stimulus_inst) sim.run() self.assert_(self.monitor.sample == 5) if __name__ == '__main__': mytests = unittest.TestLoader().loadTestsFromTestCase(TestDUT) unittest.TextTestRunner(verbosity=2).run(mytests) |
From: Christopher F. <chr...@gm...> - 2011-12-27 13:20:54
|
On 12/23/2011 8:48 AM, Christopher Felton wrote: > On Tuesday, December 20, 2011, Oscar Diaz<osc...@gm...> wrote: >> 2011/12/20 Christopher Felton<chr...@gm...>: >>> On 12/20/2011 5:35 AM, Oscar Diaz wrote: >>>> Hi >>>> >>>> I have a testbench that needs to do some asserts at the end of a >>>> simulation. However, I couldn't find an elegant way to do it. Right >>>> now I'm passing to the testbench generator the same duration as in >>>> "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" >>>> and do the final asserts (by the way, in my case all my simulations >>>> have a defined duration). I tried to catch the StopSimulation >>>> exception, but it doesn't work inside a generator. Any ideas? Thanks! >>>> >>>> Best regards >>>> >>> >>> I believe you can catch exceptions in generators. At least the >>> generator PEP says so and the following works. >>> >>> ~~~ [Code Snip] ~~~ >>> from myhdl import * >>> def test(): >>> @instance >>> def ex_in_g(): >>> try: >>> for ii in xrange(10): >>> yield delay(7) >>> raise StopSimulation >>> >>> except Exception, e: >>> print("Caught exception %s" % (str(e))) >>> raise StopSimulation >>> >>> return ex_in_g >>> >>> if __name__ == '__main__': >>> Simulation(test()).run() >>> ~~~~~~~~~~~~~~~~~~~~~~~ >> >> That's the case when the exception is raised inside the generator, >> which is not my case. I'm trying to something like this: >> >> ~~~ [Code Snip] ~~~ >> from myhdl import * >> def test(): >> @instance >> def ex_in_g(): >> try: >> for ii in xrange(10): >> yield delay(7) >> # ideally it shouldn't got here >> return >> >> except Exception, e: >> # or maybe better "except StopSimulation" ? >> print("Caught exception %s" % (str(e))) >> raise StopSimulation >> >> return ex_in_g >> >> if __name__ == '__main__': >> # fixed simulation time >> Simulation(test()).run(50) >> ~~~~~~~~~~~~~~~~~~~~~~~ >> >> It doesn't work because the exception is raised inside the run() >> method. Right now my project store the simulation duration to yield >> before raising StopSimulation, like this: >> ~~~ [Code Snip] ~~~ >> from myhdl import * >> sim_duration = 100 >> def test(): >> @instance >> def main_block(): >> # do some stuff >> return >> >> @instance >> def last_check(): >> yield delay(sim_duration - 1) >> print "do some final asserts..." >> return >> >> return instances() >> >> if __name__ == '__main__': >> Simulation(test()).run(sim_duration) >> ~~~~~~~~~~~~~~~~~~~~~~~ >> >> Any ideas to improve this issue? >> >> Best regards >> >>> >>> Regards, >>> Chris >>> >>> > > Another option you could try is to run the simulation from the test > function. After the simulation completes the final state is preserved and > you can do the final checks. > > I haven't tried it. In the above example, the test function you could do > the following. > > Def test(): > ... > Simulation((ex_in_g)).run() > #checks > # nothing to return > > Regards, > Chris > > > > Here is a complete example that I briefly mentioned previously. The following, there is a simple module that will stop counting at some value. The simulation is run for some period of steps and the state is maintained for variables/objects that are active (? don't know the correct programming lingo for variables/objects that are in scope and have not been discarded). ~~~[Code Snip]~~~ from myhdl import * def incr(clk, rst, x): @always(clk.posedge) def hdlg_incr(): if rst: x.next = 0 else: if x < 12: x.next = x + 1 return hdlg_incr def test(): clk = Signal(False) rst = Signal(False) x = Signal(intbv(0, min=0, max=20)) dut = incr(clk, rst, x) @always(delay(1)) def tb_clk_gen(): clk.next = not clk @instance def tb_stim(): rst.next = True yield delay(3) rst.next = False # Run the simulation Simulation((dut, tb_clk_gen, tb_stim)).run(44) # Check final state assert x == 12, "Final state incorrect" assert x != 12, "Final state correct" if __name__ == '__main__': test() ~~~[End Code Snip]~~~ ~~~[CLI exec]~~~ In [2]: run end_state.py <class 'myhdl._SuspendSimulation'>: Simulated 44 timesteps --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) end_state.py in <module>() 40 41 if __name__ == '__main__': ---> 42 test() 43 \\sppdgfs\users\felton\misc\test\end_state.py in test() 36 37 assert x == 12, "Final state incorrect" ---> 38 assert x != 12, "Final state correct" 39 40 AssertionError: Final state correct ~~~[End CLI exec]~~~ Now, I don't think you can dig down and check internal variables this way (at least I do not know how to). Regards, Chris |