1
0
mirror of https://github.com/myhdl/myhdl.git synced 2024-12-14 07:44:38 +08:00

_toVerilog.py: expanding initial_values kwarg to add 'skip_zero_mem_init' choice to skip generating initial block when all values are zero (#431)

This commit is contained in:
Josy Boelen 2024-06-11 13:48:35 +02:00 committed by GitHub
parent e356d8a589
commit 6520f32194
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 82 additions and 28 deletions

View File

@ -49,7 +49,7 @@ traceSignals -- function that enables signal tracing in a VCD file
toVerilog -- function that converts a design to Verilog
"""
__version__ = "0.11.46"
__version__ = "0.11.47"
class StopSimulation(Exception):

View File

@ -20,7 +20,7 @@
""" Block with the @block decorator function. """
import inspect
#from functools import wraps
# from functools import wraps
import functools
import myhdl
@ -34,8 +34,11 @@ from myhdl._Signal import _Signal, _isListOfSigs
from weakref import WeakValueDictionary
class _error:
pass
_error.ArgType = "%s: A block should return block or instantiator objects"
_error.InstanceError = "%s: subblock %s should be encapsulated in a block decorator"
@ -87,15 +90,16 @@ def _getCallInfo():
return _CallInfo(name, modctxt, symdict)
### I don't think this is the right place for uniqueifying the name.
### This seems to me to be a conversion concern, not a block concern, and
### there should not be the corresponding global state to be maintained here.
### The name should be whatever it is, which is then uniqueified at
### conversion time. Perhaps this happens already (FIXME - check and fix)
### ~ H Gomersall 24/11/2017
# ## I don't think this is the right place for uniqueifying the name.
# ## This seems to me to be a conversion concern, not a block concern, and
# ## there should not be the corresponding global state to be maintained here.
# ## The name should be whatever it is, which is then uniqueified at
# ## conversion time. Perhaps this happens already (FIXME - check and fix)
# ## ~ H Gomersall 24/11/2017
_inst_name_set = set()
_name_set = set()
def _uniqueify_name(proposed_name):
'''Creates a unique block name from the proposed name by appending
a suitable number to the end. Every name this function returns is
@ -140,6 +144,7 @@ class _bound_function_wrapper(object):
return _Block(self.bound_func, self, name, self.srcfile,
self.srcline, *args, **kwargs)
class block(object):
def __init__(self, func):
@ -304,14 +309,27 @@ class _Block(object):
Args:
hdl (Optional[str]): Target HDL. Defaults to Verilog
path (Optional[str]): Destination folder. Defaults to current
working dir.
name (Optional[str]): Module and output file name. Defaults to
`self.mod.__name__`
initial_vales(Optional[bool(), str]):
Verilog: False: no initial values
True: all initial values, using initial blocks for memories
'skip_zero_mem_init': same as for `True` except no initial blocks are
generated for memories where all values are zero,
which is the default at start-up of (most or all) FPGAs
VHDL: True or False only ('skip_zero_mem_init' will be treated as `True` ...)
trace(Optional[bool]): Verilog only. Whether the testbench should
dump all signal waveforms. Defaults to False.
testbench (Optional[bool]): Verilog only. Specifies whether a
testbench should be created. Defaults to True.
timescale(Optional[str]): Verilog only. Defaults to '1ns/10ps'
"""
@ -337,17 +355,17 @@ class _Block(object):
setattr(converter, k, v)
return converter(self)
def config_sim(self, trace=False, **kwargs) :
def config_sim(self, trace=False, **kwargs):
self._config_sim['trace'] = trace
if trace:
for k, v in kwargs.items() :
for k, v in kwargs.items():
setattr(myhdl.traceSignals, k, v)
myhdl.traceSignals(self)
def run_sim(self, duration=None, quiet=0):
if self.sim is None:
sim = self
#if self._config_sim['trace']:
# if self._config_sim['trace']:
# sim = myhdl.traceSignals(self)
self.sim = myhdl._Simulation.Simulation(sim)
self.sim.run(duration, quiet)

View File

@ -359,13 +359,19 @@ def _writeSigDecls(f, intf, siglist, memlist):
if not m._used:
continue
# infer attributes for the case of named signals in a list
for i, s in enumerate(m.mem):
for s in m.mem:
if not m._driven and s._driven:
m._driven = s._driven
# once suffices
break
if not m._read and s._read:
m._read = s._read
# once suffices
break
if not m._driven and not m._read:
continue
r = _getRangeString(m.elObj)
p = _getSignString(m.elObj)
k = 'wire'
@ -375,21 +381,23 @@ def _writeSigDecls(f, intf, siglist, memlist):
if toVerilog.initial_values and not k == 'wire':
if all([each._init == m.mem[0]._init for each in m.mem]):
initialize_block_name = ('INITIALIZE_' + m.name).upper()
_initial_assignments = (
'''
initial begin: %s
integer i;
for(i=0; i<%d; i=i+1) begin
%s[i] = %s;
if toVerilog.initial_values == 'skip_zero_mem_init':
pass
else:
initialize_block_name = ('INITIALIZE_' + m.name).upper()
_initial_assignments = (
'''
initial begin: %s
integer i;
for(i=0; i<%d; i=i+1) begin
%s[i] = %s;
end
end
end
''' % (initialize_block_name, len(m.mem), m.name,
_intRepr(m.mem[0]._init)))
''' % (initialize_block_name, len(m.mem), m.name,
_intRepr(m.mem[0]._init)))
initial_assignments = (
textwrap.dedent(_initial_assignments))
initial_assignments = (
textwrap.dedent(_initial_assignments))
else:
val_assignments = '\n'.join(

View File

@ -115,7 +115,8 @@ class _VerificationClass(object):
name = func.func.__name__
else:
warnings.warn(
"\n analyze()/verify(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html",
"\n analyze()/verify(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html"
f"\n Found hdl = {hdl} - func is: {func}",
stacklevel=2,
category=DeprecationWarning,
)

View File

@ -40,6 +40,22 @@ def ForLoopError2(a, out):
return logic
@block
def ForLoopError3(a, out):
@instance
def logic():
while 1:
yield a
var = 0
for i in range(1, 4, -1):
if a[i] == 1:
var += 1
out.next = var
return logic
@block
def ForLoop1(a, out):
@ -386,6 +402,15 @@ def testForLoopError2():
assert False
def testForLoopError3():
try:
analyze(LoopBench(ForLoopError3))
except ConversionError as e:
assert e.kind == _error.Requirement
else:
assert False
def testForLoop1():
assert verify(LoopBench(ForLoop1)) == 0

View File

@ -2,12 +2,13 @@ import os
path = os.path
from random import randrange
from myhdl import (Signal, intbv, delay, instance)
from myhdl import (block, Signal, intbv, delay, instance)
from myhdl.conversion import analyze
from myhdl import ConversionError
from myhdl.conversion._misc import _error
@block
def ForLoopError1(a, out):
@instance
@ -23,6 +24,7 @@ def ForLoopError1(a, out):
return logic
@block
def LoopBench(LoopTest):
a = Signal(intbv(-1)[16:])
@ -43,7 +45,7 @@ def LoopBench(LoopTest):
def testForLoopError1():
try:
analyze(LoopBench, ForLoopError1)
analyze(LoopBench(ForLoopError1))
except ConversionError as e:
assert e.kind == _error.Requirement
else: