diff --git a/myhdl/_module.py b/myhdl/_module.py index e20bfc6b..572043f8 100644 --- a/myhdl/_module.py +++ b/myhdl/_module.py @@ -26,7 +26,8 @@ import inspect from myhdl import ModuleError from myhdl._instance import _Instantiator from myhdl._util import _flatten -from myhdl._extractHierarchy import _MemInfo, _makeMemInfo +from myhdl._extractHierarchy import (_MemInfo, _makeMemInfo, + _UserVerilogCode, _UserVhdlCode) from myhdl._Signal import _Signal, _isListOfSigs @@ -75,6 +76,8 @@ class _Module(object): def __init__(self, modfunc): self.modfunc = modfunc self.__name__ = self.name = modfunc.__name__ + self.sourcefile = inspect.getsourcefile(modfunc) + self.sourceline = inspect.getsourcelines(modfunc)[0] self.count = 0 def __call__(self, *args, **kwargs): @@ -101,6 +104,13 @@ class _ModuleInstance(object): self.update() # self.inferInterface(*args, **kwargs) self.name = self.__name__ = mod.__name__ + '_' + str(mod.count) + self.verilog_code = self.vhdl_code = None + if hasattr(mod, 'verilog_code'): + self.verilog_code = _UserVerilogCode(mod.verilog_code, self.symdict, mod.name, + mod.modfunc, mod.sourcefile, mod.sourceline) + if hasattr(mod, 'vhdl_code'): + self.vhdl_code = _UserVhdlCode(mod.vhdl_code, self.symdict, mod.name, + mod.modfunc, mod.sourcefile, mod.sourceline) def verify(self): for inst in self.subs: @@ -122,6 +132,8 @@ class _ModuleInstance(object): if isinstance(inst, _Instantiator): usedsigdict.update(inst.sigdict) usedlosdict.update(inst.losdict) + if self.symdict is None: + self.symdict = {} # Special case: due to attribute reference transformation, the # sigdict and losdict from Instantiator objects may contain new # references. Therefore, update the symdict with them. diff --git a/myhdl/_resolverefs.py b/myhdl/_resolverefs.py index d77ab06f..606ddc90 100644 --- a/myhdl/_resolverefs.py +++ b/myhdl/_resolverefs.py @@ -40,7 +40,8 @@ class _AttrRefTransformer(ast.NodeTransformer): def visit_Attribute(self, node): self.generic_visit(node) - reserved = ('next', 'posedge', 'negedge', 'max', 'min', 'val', 'signed') + reserved = ('next', 'posedge', 'negedge', 'max', 'min', 'val', 'signed', + 'verilog_code', 'vhdl_code') if node.attr in reserved: return node diff --git a/myhdl/conversion/_toVHDL.py b/myhdl/conversion/_toVHDL.py index 658b1062..c6543af3 100644 --- a/myhdl/conversion/_toVHDL.py +++ b/myhdl/conversion/_toVHDL.py @@ -73,7 +73,11 @@ def _flatten(*args): arglist = [] for arg in args: if isinstance(arg, _ModuleInstance): - arg = arg.subs + if arg.vhdl_code is not None: + arglist.append(arg.vhdl_code) + continue + else: + arg = arg.subs if id(arg) in _userCodeMap['vhdl']: arglist.append(_userCodeMap['vhdl'][id(arg)]) elif isinstance(arg, (list, tuple, set)): diff --git a/myhdl/conversion/_toVerilog.py b/myhdl/conversion/_toVerilog.py index bfa4f501..a18ce5cf 100644 --- a/myhdl/conversion/_toVerilog.py +++ b/myhdl/conversion/_toVerilog.py @@ -67,7 +67,11 @@ def _flatten(*args): arglist = [] for arg in args: if isinstance(arg, _ModuleInstance): - arg = arg.subs + if arg.verilog_code is not None: + arglist.append(arg.verilog_code) + continue + else: + arg = arg.subs if id(arg) in _userCodeMap['verilog']: arglist.append(_userCodeMap['verilog'][id(arg)]) elif isinstance(arg, (list, tuple, set)): diff --git a/myhdl/test/conversion/toVHDL/test_custom.py b/myhdl/test/conversion/toVHDL/test_custom.py index 23bcb98a..c753e97b 100644 --- a/myhdl/test/conversion/toVHDL/test_custom.py +++ b/myhdl/test/conversion/toVHDL/test_custom.py @@ -14,6 +14,7 @@ from myhdl.conversion._misc import _error ACTIVE_LOW, INACTIVE_HIGH = 0, 1 +@module def incRef(count, enable, clock, reset, n): """ Incrementer with enable. @@ -35,11 +36,12 @@ def incRef(count, enable, clock, reset, n): return logic +@module def incGen(count, enable, clock, reset, n): - """ Generator with __vhdl__ is not permitted """ + """ Generator with vhdl_code is not permitted """ @instance def logic(): - __vhdl__ = "Template string" + incGen.vhdl_code = "Template string" while 1: yield clock.posedge, reset.negedge if reset == ACTIVE_LOW: @@ -50,6 +52,7 @@ def incGen(count, enable, clock, reset, n): return logic +@module def inc(count, enable, clock, reset, n): """ Incrementer with enable. @@ -71,14 +74,14 @@ def inc(count, enable, clock, reset, n): count.driven = "reg" - __vhdl__ = \ + inc.vhdl_code = \ """ -process (%(clock)s, %(reset)s) begin - if (%(reset)s = '0') then - %(count)s <= (others => '0'); - elsif rising_edge(%(clock)s) then - if (%(enable)s = '1') then - %(count)s <= (%(count)s + 1) mod %(n)s; +process ($clock, $reset) begin + if ($reset = '0') then + $count <= (others => '0'); + elsif rising_edge($clock) then + if ($enable = '1') then + $count <= ($count + 1) mod $n; end if; end if; end process; @@ -87,6 +90,8 @@ end process; return incProcess + +@module def incErr(count, enable, clock, reset, n): @always(clock.posedge, reset.negedge) @@ -101,15 +106,15 @@ def incErr(count, enable, clock, reset, n): count.driven = "reg" - __vhdl__ = \ + incErr.vhdl_code = \ """ -always @(posedge %(clock)s, negedge %(reset)s) begin - if (%(reset)s == 0) begin - %(count)s <= 0; +always @(posedge $clock, negedge $reset) begin + if ($reset == 0) begin + $count <= 0; end else begin - if (%(enable)s) begin - %(count)s <= (%(countq)s + 1) %% %(n)s; + if ($enable) begin + $count <= ($countq + 1) %% $n; end end end @@ -119,6 +124,7 @@ end +@module def inc_comb(nextCount, count, n): @always_comb @@ -129,17 +135,20 @@ def inc_comb(nextCount, count, n): nextCount.driven = "wire" - __vhdl__ =\ + inc_comb.vhdl_code =\ """ -%(nextCount)s <= (%(count)s + 1) mod %(n)s; +$nextCount <= ($count + 1) mod $n; """ return logic +@module def inc_seq(count, nextCount, enable, clock, reset): @always(clock.posedge, reset.negedge) def logic(): + # make if fail in conversion + import types if reset == ACTIVE_LOW: count.next = 0 else: @@ -148,14 +157,14 @@ def inc_seq(count, nextCount, enable, clock, reset): count.driven = True - __vhdl__ = \ + inc_seq.vhdl_code = \ """ -process (%(clock)s, %(reset)s) begin - if (%(reset)s = '0') then - %(count)s <= (others => '0'); - elsif rising_edge(%(clock)s) then - if (%(enable)s = '1') then - %(count)s <= %(nextCount)s; +process ($clock, $reset) begin + if ($reset = '0') then + $count <= (others => '0'); + elsif rising_edge($clock) then + if ($enable = '1') then + $count <= $nextCount; end if; end if; end process; @@ -163,6 +172,7 @@ end process; return logic +@module def inc2(count, enable, clock, reset, n): nextCount = Signal(intbv(0, min=0, max=n)) @@ -173,11 +183,13 @@ def inc2(count, enable, clock, reset, n): return comb, seq +@module def inc3(count, enable, clock, reset, n): inc2_inst = inc2(count, enable, clock, reset, n) return inc2_inst +@module def clockGen(clock): @instance def logic(): @@ -191,6 +203,7 @@ NRTESTS = 1000 ENABLES = tuple([min(1, randrange(5)) for i in range(NRTESTS)]) +@module def stimulus(enable, clock, reset): @instance def logic(): @@ -209,6 +222,7 @@ def stimulus(enable, clock, reset): return logic +@module def check(count, enable, clock, reset, n): @instance def logic(): @@ -226,7 +240,7 @@ def check(count, enable, clock, reset, n): print(count) return logic - +@module def customBench(inc): m = 8 @@ -246,20 +260,20 @@ def customBench(inc): def testIncRef(): - assert conversion.verify(customBench, incRef) == 0 + assert conversion.verify(customBench(incRef)) == 0 def testInc(): - assert conversion.verify(customBench, inc) == 0 + assert conversion.verify(customBench(inc)) == 0 def testInc2(): - assert conversion.verify(customBench, inc2) == 0 + assert conversion.verify(customBench(inc2)) == 0 def testInc3(): - assert conversion.verify(customBench, inc3) == 0 + assert conversion.verify(customBench(inc3)) == 0 def testIncGen(): try: - assert conversion.verify(customBench, incGen) == 0 + assert conversion.verify(customBench(incGen)) == 0 except ConversionError as e: pass else: @@ -267,7 +281,7 @@ def testIncGen(): def testIncErr(): try: - assert conversion.verify(customBench, incErr) == 0 + assert conversion.verify(customBench(incErr)) == 0 except ConversionError as e: pass else: diff --git a/myhdl/test/conversion/toVerilog/test_custom.py b/myhdl/test/conversion/toVerilog/test_custom.py index 51e0d871..1c8ad84b 100644 --- a/myhdl/test/conversion/toVerilog/test_custom.py +++ b/myhdl/test/conversion/toVerilog/test_custom.py @@ -17,6 +17,7 @@ from myhdl.conversion._misc import _error ACTIVE_LOW, INACTIVE_HIGH = 0, 1 +@module def incRef(count, enable, clock, reset, n): """ Incrementer with enable. @@ -38,21 +39,23 @@ def incRef(count, enable, clock, reset, n): return logic +@module def incGen(count, enable, clock, reset, n): - """ Generator with __verilog__ is not permitted """ + """ Generator with verilog_code is not permitted """ @instance def logic(): - __verilog__ = "Template string" + incGen.verilog_code = "Template string" while 1: - yield clock.posedge, reset.negedge - if reset == ACTIVE_LOW: - count.next = 0 - else: - if enable: - count.next = (count + 1) % n + yield clock.posedge, reset.negedge + if reset == ACTIVE_LOW: + count.next = 0 + else: + if enable: + count.next = (count + 1) % n return logic +@module def inc(count, enable, clock, reset, n): """ Incrementer with enable. @@ -74,15 +77,15 @@ def inc(count, enable, clock, reset, n): count.driven = "reg" - __verilog__ = \ + inc.verilog_code = \ """ -always @(posedge %(clock)s, negedge %(reset)s) begin +always @(posedge $clock, negedge $reset) begin if (reset == 0) begin - %(count)s <= 0; + $count <= 0; end else begin if (enable) begin - %(count)s <= (%(count)s + 1) %% %(n)s; + $count <= ($count + 1) % $n; end end end @@ -91,6 +94,7 @@ end return incProcess +@module def incErr(count, enable, clock, reset, n): @always(clock.posedge, reset.negedge) @@ -105,15 +109,15 @@ def incErr(count, enable, clock, reset, n): count.driven = "reg" - __verilog__ = \ + incErr.verilog_code = \ """ -always @(posedge %(clock)s, negedge %(reset)s) begin +always @(posedge $clock, negedge $reset) begin if (reset == 0) begin - %(count)s <= 0; + $count <= 0; end else begin if (enable) begin - %(count)s <= (%(countq)s + 1) %% %(n)s; + $count <= ($countq + 1) % $n; end end end @@ -123,6 +127,7 @@ end +@module def inc_comb(nextCount, count, n): @always_comb @@ -133,17 +138,20 @@ def inc_comb(nextCount, count, n): nextCount.driven = "wire" - __verilog__ =\ + inc_comb.verilog_code =\ """ -assign %(nextCount)s = (%(count)s + 1) %% %(n)s; +assign $nextCount = ($count + 1) % $n; """ return logic +@module def inc_seq(count, nextCount, enable, clock, reset): @always(clock.posedge, reset.negedge) def logic(): + # make it fail in conversion + import types if reset == ACTIVE_LOW: count.next = 0 else: @@ -152,22 +160,22 @@ def inc_seq(count, nextCount, enable, clock, reset): count.driven = "reg" - __verilog__ = \ + inc_seq.verilog_code = \ """ -always @(posedge %(clock)s, negedge %(reset)s) begin +always @(posedge $clock, negedge $reset) begin if (reset == 0) begin - %(count)s <= 0; + $count <= 0; end else begin if (enable) begin - %(count)s <= %(nextCount)s; + $count <= $nextCount; end end end """ - # return nothing - cannot be simulated - return [] + return logic +@module def inc2(count, enable, clock, reset, n): nextCount = Signal(intbv(0, min=0, max=n)) @@ -178,6 +186,7 @@ def inc2(count, enable, clock, reset, n): return comb, seq +@module def inc3(count, enable, clock, reset, n): inc2_inst = inc2(count, enable, clock, reset, n) return inc2_inst @@ -233,7 +242,7 @@ class TestInc(TestCase): clock, reset = [Signal(bool()) for i in range(2)] inc_inst_ref = incRef(count, enable, clock, reset, n=n) - inc_inst = toVerilog(incVer, count, enable, clock, reset, n=n) + inc_inst = toVerilog(incVer(count, enable, clock, reset, n=n)) # inc_inst = inc(count, enable, clock, reset, n=n) inc_inst_v = inc_v(incVer.__name__, count_v, enable, clock, reset) clk_1 = self.clockGen(clock) @@ -271,7 +280,7 @@ class TestInc(TestCase): enable = Signal(bool(0)) clock, reset = [Signal(bool()) for i in range(2)] try: - inc_inst = toVerilog(incGen, count_v, enable, clock, reset, n=n) + inc_inst = toVerilog(incGen(count_v, enable, clock, reset, n=n)) except ConversionError as e: self.assertEqual(e.kind, _error.NotSupported) else: @@ -284,7 +293,7 @@ class TestInc(TestCase): enable = Signal(bool(0)) clock, reset = [Signal(bool()) for i in range(2)] try: - inc_inst = toVerilog(incErr, count_v, enable, clock, reset, n=n) + inc_inst = toVerilog(incErr(count_v, enable, clock, reset, n=n)) except ConversionError as e: pass else: