Some myHDL libraries provide classes to generate @block
components. These are currently under scrutiny.
For the time being, factory classes have be decorated using the @factory
decorator in order to be translated to IRL.
Not that the following class makes sense in the real world, but as an example:
@block
factory¶from myirl.emulation.myhdl import *
@factory
class Bingo:
def __init__(self, parameter = 8):
self.n = parameter
T = Signal.Type(intbv, parameter)
@block
def my_unit(clk : ClkSignal, a : T, b : T.Output):
@always(clk.posedge)
def worker():
b.next = a
return instances()
self.my_unit = my_unit
def test():
b = Bingo(6)
u, v = [Signal(intbv()[6:]) for _ in range(2)]
c = ClkSignal()
u = b.my_unit(c, u, v)
f = u.elab(targets.VHDL)
test()
Creating process 'my_unit/worker' with sensitivity (clk'rising,) Writing 'my_unit' to file /tmp/myirl_top_my_unit_ey6bg8eu/my_unit.vhdl
!cat /tmp/my_unit.vhdl
cat: /tmp/my_unit.vhdl: No such file or directory
@block_component
member¶When specified as a static unit inside this class, the class will serve as its context and the unit requires a @block_component
decoration (without arguments), plus the self
argument, representing a component method describing hardware inference.
In this case, the factory class is derived from the DesignModule
(or minimum the BareModule
class). This construct helps to encapsulate common blocks that depend on a complex configuration.
from myirl.test import common_test
@factory
class Bongo(LibraryModule):
def __init__(self, parameter = 8, name = "Bongo"):
self.n = parameter
super().__init__(name)
self.files = []
self.inst = None
# Here, we use `@block_component` without arguments, as the context is 'self'
@block_component
def my_unit1(self, clk : ClkSignal, a : Signal, b : Signal.Output):
"A component somewhere in the hierarchy"
ls = Signal(intbv()[self.n:])
@always(clk.posedge)
def worker():
ls.next = a
b.next = ls
return instances()
@block_component
def my_tb(self):
"A built-in test bench"
u, v = [Signal(intbv()[self.n:]) for _ in range(2)]
c = ClkSignal()
@always(delay(4))
def clkgen():
c.next = ~c
@instance
def stim():
u.next = 2
yield c.posedge
yield c.posedge
yield c.posedge
print(v)
assert v == 2
raise StopSimulation
uut = self.my_unit1(c, u, v)
return instances()
def build(self):
t = self.my_tb()
self.files = t.elab(targets.VHDL, elab_all = True)
self.inst = t
print("Resulting files", self.files)
def simulate(self):
common_test.run_ghdl(self.files, self.inst, debug = True)
print(Bongo.unparse())
============================== Unparsing unit Bongo ============================== class Bongo(LibraryModule): def __init__(self, parameter=8, name='Bongo'): self.n = parameter super().__init__(name) self.files = [] self.inst = None @block_component def my_unit1(self, clk: ClkSignal, a: Signal, b: Signal.Output): 'A component somewhere in the hierarchy' ls = Signal(intbv()[self.n:]) @always_(clk.posedge) def worker(): (yield [ls.set(a), b.set(ls)]) return instances() @block_component def my_tb(self): 'A built-in test bench' (u, v) = [Signal(intbv()[self.n:]) for _ in range(2)] c = ClkSignal() @always_(delay(4)) def clkgen(): (yield [c.set((~ c))]) @sequential def stim(_sequence): _sequence += [u.set(2), wait(c.posedge), wait(c.posedge), wait(c.posedge), print_(v), assert_((v == 2), 'Failed in /tmp/ipykernel_41098/1829234184.py:Bongo():41'), raise_(StopSimulation)] uut = self.my_unit1(c, u, v) return instances() def build(self): t = self.my_tb() self.files = t.elab(targets.VHDL, elab_all=True) self.inst = t print('Resulting files', self.files) def simulate(self): common_test.run_ghdl(self.files, self.inst, debug=True)
Running this design component, OO style:
def test():
b = Bongo(6)
b.build()
b.simulate()
b = Bongo(7)
b.build()
test()
Using default for name: Bongo Declare obj 'my_tb' in context '(LIB: Bongo 'Bongo')' Creating process 'my_tb/clkgen' with sensitivity ([ DeltaT 4 ns ],) Creating sequential 'my_tb/stim' Declare obj 'my_unit1' in context '(LIB: Bongo 'Bongo')' Creating process 'my_unit1/worker' with sensitivity (clk'rising,) Elaborating component my_unit1__Bongo_s1_s6_s6 Writing 'my_unit1' to file /tmp/myirl_Bongo_b8y8be_6/my_unit1.vhdl Elaborating component my_tb__Bongo Writing 'my_tb' to file /tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl Creating library file /tmp/myirl_module_defs_rauris6_/module_defs.vhdl Resulting files ['/tmp/myirl_Bongo_b8y8be_6/my_unit1.vhdl', '/tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl', '/tmp/myirl_module_defs_rauris6_/module_defs.vhdl'] ==== COSIM stdout ==== ==== COSIM stderr ==== ==== COSIM stdout ==== analyze /home/testing/.local/lib/python3.9/site-packages/myirl-0.0.0-py3.9-linux-x86_64.egg/myirl/targets/../test/vhdl/txt_util.vhdl analyze /home/testing/.local/lib/python3.9/site-packages/myirl-0.0.0-py3.9-linux-x86_64.egg/myirl/targets/libmyirl.vhdl analyze /tmp/myirl_Bongo_b8y8be_6/my_unit1.vhdl analyze /tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl elaborate my_tb ==== COSIM stderr ==== ==== COSIM stdout ==== 0x02 /tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl:42:9:@20ns:(assertion failure): Stop Simulation /tmp/my_tb:error: assertion failed in process .my_tb(myirl).stim /tmp/my_tb:error: simulation failed ==== COSIM stderr ==== Using default for name: Bongo Declare obj 'my_tb' in context '(LIB: Bongo 'Bongo')' Creating process 'my_tb/clkgen' with sensitivity ([ DeltaT 4 ns ],) Creating sequential 'my_tb/stim' Declare obj 'my_unit1' in context '(LIB: Bongo 'Bongo')' Creating process 'my_unit1/worker' with sensitivity (clk'rising,) Elaborating component my_unit1__Bongo_s1_s7_s7 Writing 'my_unit1' to file /tmp/myirl_Bongo_jfhjnb75/my_unit1.vhdl Elaborating component my_tb__Bongo Writing 'my_tb' to file /tmp/myirl_Bongo_jfhjnb75/my_tb.vhdl Creating library file /tmp/myirl_module_defs_u116uelo/module_defs.vhdl Resulting files ['/tmp/myirl_Bongo_jfhjnb75/my_unit1.vhdl', '/tmp/myirl_Bongo_jfhjnb75/my_tb.vhdl', '/tmp/myirl_module_defs_u116uelo/module_defs.vhdl']