mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
Merge branch 'master' of https://github.com/jandecaluwe/myhdl
This commit is contained in:
commit
68302ecc6a
12
.travis.yml
12
.travis.yml
@ -9,13 +9,19 @@ python:
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
|
||||
# binary install as per travis instructions
|
||||
# used to install latest version of ghdl
|
||||
before_script:
|
||||
- ./scripts/install_ghdl.sh
|
||||
- export PATH=$PATH:$PWD/ghdl-0.33/bin/
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- pgavin-ghdl
|
||||
# sources:
|
||||
# - pgavin-ghdl
|
||||
packages:
|
||||
- iverilog
|
||||
- ghdl
|
||||
# - ghdl
|
||||
|
||||
install:
|
||||
- pip install .
|
||||
|
@ -41,6 +41,14 @@ A :class:`Simulation` object has the following method:
|
||||
Run the simulation forever (by default) or for a specified duration.
|
||||
|
||||
|
||||
.. method:: Simulation.quit()
|
||||
|
||||
Quit the simulation after it has run for a specified duration. The method should
|
||||
be called (the simulation instance must be quit) before another simulation
|
||||
instance is created. The method is called by default when the simulation is run
|
||||
forever.
|
||||
|
||||
|
||||
.. _ref-simsupport:
|
||||
|
||||
Simulation support functions
|
||||
@ -90,6 +98,11 @@ Waveform tracing
|
||||
This attribute is used to set the directory to which VCD files are written. By
|
||||
default, the current working directory is used.
|
||||
|
||||
.. attribute:: filename
|
||||
|
||||
This attribute is used to set the filename to which VCD files are written. By
|
||||
default, the name attribbute is used.
|
||||
|
||||
.. attribute:: timescale
|
||||
|
||||
This attribute is used to set the timescale corresponding to unit steps,
|
||||
|
@ -33,6 +33,7 @@ def simulate(timesteps):
|
||||
tb = traceSignals(test_dff)
|
||||
sim = Simulation(tb)
|
||||
sim.run(timesteps)
|
||||
sim.quit()
|
||||
|
||||
simulate(2000)
|
||||
|
||||
|
@ -44,6 +44,7 @@ def simulate(timesteps):
|
||||
tb = traceSignals(test_dffa)
|
||||
sim = Simulation(tb)
|
||||
sim.run(timesteps)
|
||||
sim.quit()
|
||||
|
||||
simulate(20000)
|
||||
|
||||
|
@ -33,6 +33,7 @@ def simulate(timesteps):
|
||||
tb = traceSignals(test_latch)
|
||||
sim = Simulation(tb)
|
||||
sim.run(timesteps)
|
||||
sim.quit()
|
||||
|
||||
simulate(20000)
|
||||
|
||||
|
@ -45,6 +45,7 @@ class _error:
|
||||
_error.ArgType = "Inappriopriate argument type"
|
||||
_error.MultipleCosim = "Only a single cosimulator argument allowed"
|
||||
_error.DuplicatedArg = "Duplicated argument"
|
||||
_error.MultipleSim = "Only a single Simulation instance is allowed"
|
||||
|
||||
class Simulation(object):
|
||||
|
||||
@ -54,6 +55,7 @@ class Simulation(object):
|
||||
run -- run a simulation for some duration
|
||||
|
||||
"""
|
||||
_no_of_instances = 0
|
||||
|
||||
def __init__(self, *args):
|
||||
""" Construct a simulation object.
|
||||
@ -65,13 +67,16 @@ class Simulation(object):
|
||||
_simulator._time = 0
|
||||
arglist = _flatten(*args)
|
||||
self._waiters, self._cosim = _makeWaiters(arglist)
|
||||
if Simulation._no_of_instances > 0:
|
||||
raise SimulationError(_error.MultipleSim)
|
||||
Simulation._no_of_instances += 1
|
||||
if not self._cosim and _simulator._cosim:
|
||||
warn("Cosimulation not registered as Simulation argument")
|
||||
self._finished = False
|
||||
del _futureEvents[:]
|
||||
del _siglist[:]
|
||||
|
||||
|
||||
|
||||
|
||||
def _finalize(self):
|
||||
cosim = self._cosim
|
||||
if cosim:
|
||||
@ -85,9 +90,12 @@ class Simulation(object):
|
||||
# clean up for potential new run with same signals
|
||||
for s in _signals:
|
||||
s._clear()
|
||||
Simulation._no_of_instances = 0
|
||||
self._finished = True
|
||||
|
||||
|
||||
|
||||
def quit(self):
|
||||
self._finalize()
|
||||
|
||||
def runc(self, duration=0, quiet=0):
|
||||
simrunc.run(sim=self, duration=duration, quiet=quiet)
|
||||
|
||||
@ -201,7 +209,7 @@ class Simulation(object):
|
||||
self._finalize()
|
||||
# now reraise the exepction
|
||||
raise
|
||||
|
||||
|
||||
|
||||
def _makeWaiters(arglist):
|
||||
waiters = []
|
||||
@ -231,4 +239,4 @@ def _makeWaiters(arglist):
|
||||
if hasattr(sig, '_waiter'):
|
||||
waiters.append(sig._waiter)
|
||||
return waiters, cosim
|
||||
|
||||
|
||||
|
@ -50,6 +50,7 @@ class _TraceSignalsClass(object):
|
||||
|
||||
__slot__ = ("name",
|
||||
"directory",
|
||||
"filename",
|
||||
"timescale",
|
||||
"tracelists"
|
||||
)
|
||||
@ -57,6 +58,7 @@ class _TraceSignalsClass(object):
|
||||
def __init__(self):
|
||||
self.name = None
|
||||
self.directory = None
|
||||
self.filename = None
|
||||
self.timescale = "1ns"
|
||||
self.tracelists = True
|
||||
|
||||
@ -89,8 +91,13 @@ class _TraceSignalsClass(object):
|
||||
else:
|
||||
directory = self.directory
|
||||
|
||||
if self.filename is None:
|
||||
filename = name
|
||||
else:
|
||||
filename = str(self.filename)
|
||||
|
||||
h = _HierExtr(name, dut, *args, **kwargs)
|
||||
vcdpath = os.path.join(directory, name + ".vcd")
|
||||
vcdpath = os.path.join(directory, filename + ".vcd")
|
||||
if path.exists(vcdpath):
|
||||
backup = vcdpath + '.' + str(path.getmtime(vcdpath))
|
||||
shutil.copyfile(vcdpath, backup)
|
||||
|
@ -578,10 +578,14 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
node.obj = int(0) # XXX
|
||||
elif f is bool:
|
||||
node.obj = bool()
|
||||
elif f in _flatten(integer_types, ord):
|
||||
elif f in _flatten(integer_types):
|
||||
node.obj = int(-1)
|
||||
## elif f in (posedge , negedge):
|
||||
## node.obj = _EdgeDetector()
|
||||
elif f is ord:
|
||||
node.obj = int(-1)
|
||||
if not (isinstance(node.args[0], ast.Str) and (len(node.args[0].s) == 1)):
|
||||
self.raiseError(node, _error.NotSupported, "ord: expect string argument with length 1")
|
||||
elif f is delay:
|
||||
node.obj = delay(0)
|
||||
### suprize: identity comparison on unbound methods doesn't work in python 2.5??
|
||||
@ -915,6 +919,8 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
s = s[m.end():]
|
||||
continue
|
||||
self.raiseError(node, _error.UnsupportedFormatString, "%s" % s)
|
||||
elif isinstance(n, ast.Str):
|
||||
f.append(n.s)
|
||||
else:
|
||||
f.append(defaultConvSpec)
|
||||
a.append(n)
|
||||
|
@ -602,9 +602,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
pre, suf = "", "(0)"
|
||||
else:
|
||||
pre, suf = "stdl(", ")"
|
||||
elif isinstance(vhd, vhd_string):
|
||||
if isinstance(ori, vhd_enum):
|
||||
pre, suf = "%s'image(" % ori._type._name, ")"
|
||||
# elif isinstance(vhd, vhd_string):
|
||||
# if isinstance(ori, vhd_enum):
|
||||
# pre, suf = "%s'image(" % ori._type._name, ")"
|
||||
|
||||
return pre, suf
|
||||
|
||||
@ -654,10 +654,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
self.shiftOp(node)
|
||||
elif isinstance(node.op, (ast.BitAnd, ast.BitOr, ast.BitXor)):
|
||||
self.BitOp(node)
|
||||
elif isinstance(node.op, ast.Mod) and (self.context == _context.PRINT):
|
||||
self.visit(node.left)
|
||||
self.write(", ")
|
||||
self.visit(node.right)
|
||||
else:
|
||||
self.BinOp(node)
|
||||
|
||||
@ -953,11 +949,10 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
return
|
||||
elif f is ord:
|
||||
opening, closing = '', ''
|
||||
if isinstance(node.args[0], ast.Str):
|
||||
if len(node.args[0].s) > 1:
|
||||
self.raiseError(node, _error.UnsupportedType, "Strings with length > 1" )
|
||||
else:
|
||||
node.args[0].s = ord(node.args[0].s)
|
||||
v = ord(node.args[0].s)
|
||||
node.args[0].s = v
|
||||
self.write(v)
|
||||
return
|
||||
elif f in integer_types:
|
||||
opening, closing = '', ''
|
||||
pre, suf = self.inferCast(node.vhd, node.vhdOri)
|
||||
@ -1361,15 +1356,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
a.vhd = vhd_boolean()
|
||||
elif isinstance(a.vhdOri, vhd_enum):
|
||||
a.vhd = vhd_string()
|
||||
self.write("write(L, ")
|
||||
self.context = _context.PRINT
|
||||
self.write("write(L, to_string(")
|
||||
self.visit(a)
|
||||
self.context = None
|
||||
if s.justified == 'LEFT':
|
||||
self.write(", justified=>LEFT")
|
||||
if s.width:
|
||||
self.write(", field=>%s" % s.width)
|
||||
self.write(")")
|
||||
self.write("))")
|
||||
self.write(';')
|
||||
self.writeline()
|
||||
self.write("writeline(output, L);")
|
||||
|
@ -151,7 +151,7 @@ class _ToVerilogConvertor(object):
|
||||
genlist = _analyzeGens(arglist, h.absnames)
|
||||
siglist, memlist = _analyzeSigs(h.hierarchy)
|
||||
_annotateTypes(genlist)
|
||||
|
||||
|
||||
intf = _analyzeTopFunc(func, *args, **kwargs)
|
||||
intf.name = name
|
||||
doc = _makeDoc(inspect.getdoc(func))
|
||||
@ -750,11 +750,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
return
|
||||
elif f is ord:
|
||||
opening, closing = '', ''
|
||||
if isinstance(node.args[0], ast.Str):
|
||||
if len(node.args[0].s) > 1:
|
||||
self.raiseError(node, _error.UnsupportedType, "Strings with length > 1")
|
||||
else:
|
||||
node.args[0].s = str(ord(node.args[0].s))
|
||||
node.args[0].s = str(ord(node.args[0].s))
|
||||
elif f in integer_types:
|
||||
opening, closing = '', ''
|
||||
# convert number argument to integer
|
||||
|
@ -22,7 +22,7 @@ _simulators = {}
|
||||
sim = namedtuple('sim', 'name hdl analyze elaborate simulate skiplines skipchars ignore')
|
||||
|
||||
|
||||
def registerSimulator(name=None, hdl=None, analyze=None, elaborate=None, simulate=None,
|
||||
def registerSimulator(name=None, hdl=None, analyze=None, elaborate=None, simulate=None,
|
||||
skiplines=None, skipchars=None, ignore=None):
|
||||
if not isinstance(name, str) or (name.strip() == ""):
|
||||
raise ValueError("Invalid simulator name")
|
||||
@ -41,8 +41,8 @@ def registerSimulator(name=None, hdl=None, analyze=None, elaborate=None, simulat
|
||||
registerSimulator(
|
||||
name="ghdl",
|
||||
hdl="VHDL",
|
||||
analyze="ghdl -a --workdir=work pck_myhdl_%(version)s.vhd %(topname)s.vhd",
|
||||
elaborate="ghdl -e --workdir=work -o %(unitname)s %(topname)s",
|
||||
analyze="ghdl -a --std=08 --workdir=work pck_myhdl_%(version)s.vhd %(topname)s.vhd",
|
||||
elaborate="ghdl -e --std=08 --workdir=work %(unitname)s",
|
||||
simulate="ghdl -r --workdir=work %(unitname)s"
|
||||
)
|
||||
|
||||
@ -96,7 +96,7 @@ class _VerificationClass(object):
|
||||
__slots__ = ("simulator", "_analyzeOnly")
|
||||
|
||||
def __init__(self, analyzeOnly=False):
|
||||
self.simulator = None
|
||||
self.simulator = None
|
||||
self._analyzeOnly = analyzeOnly
|
||||
|
||||
|
||||
@ -178,7 +178,7 @@ class _VerificationClass(object):
|
||||
if ret != 0:
|
||||
print("Elaboration failed", file=sys.stderr)
|
||||
return ret
|
||||
|
||||
|
||||
g = tempfile.TemporaryFile(mode='w+t')
|
||||
#print(simulate)
|
||||
ret = subprocess.call(simulate, stdout=g, shell=True)
|
||||
|
43
myhdl/test/bugs/test_issue_104.py
Normal file
43
myhdl/test/bugs/test_issue_104.py
Normal file
@ -0,0 +1,43 @@
|
||||
from __future__ import print_function
|
||||
import pytest
|
||||
from myhdl import Simulation, delay, SimulationError, instance, now
|
||||
from myhdl._Simulation import _error
|
||||
from helpers import raises_kind
|
||||
|
||||
def test():
|
||||
@instance
|
||||
def tbstim():
|
||||
yield delay(10)
|
||||
print("{0:<8d} ".format(now()))
|
||||
yield delay(1000)
|
||||
print("{0:<8d} ".format(now()))
|
||||
for _ in range(10):
|
||||
yield delay(1000)
|
||||
|
||||
return tbstim
|
||||
|
||||
|
||||
def issue_104_quit_method():
|
||||
sim = Simulation(test())
|
||||
sim.run(1000)
|
||||
sim.run(500)
|
||||
sim.quit()
|
||||
return sim._finished
|
||||
|
||||
def issue_104_multiple_instance():
|
||||
sim1 = Simulation(test())
|
||||
sim1.run(1000)
|
||||
# sim1 is "puased"
|
||||
|
||||
# try and create a second, third, forth simulation instance
|
||||
for ii in range(4):
|
||||
with raises_kind(SimulationError, _error.MultipleSim):
|
||||
another_sim = Simulation(test())
|
||||
# generating more sims should have failed
|
||||
sim1.run(1000)
|
||||
sim1.quit()
|
||||
|
||||
def test_issue_104():
|
||||
|
||||
assert issue_104_quit_method() == True
|
||||
issue_104_multiple_instance()
|
@ -155,12 +155,16 @@ class TestTraceSigs:
|
||||
assert not path.exists(psub)
|
||||
|
||||
def testTristateTrace(self, vcd_dir):
|
||||
Simulation(topTristate()).run(100, quiet=QUIET)
|
||||
sim = Simulation(topTristate())
|
||||
sim.run(100, quiet=QUIET)
|
||||
sim.quit()
|
||||
|
||||
def testBackupOutputFile(self, vcd_dir):
|
||||
p = "%s.vcd" % fun.__name__
|
||||
dut = traceSignals(fun)
|
||||
Simulation(dut).run(1000, quiet=QUIET)
|
||||
sim = Simulation(dut)
|
||||
sim.run(1000, quiet=QUIET)
|
||||
sim.quit()
|
||||
_simulator._tf.close()
|
||||
_simulator._tracing = 0
|
||||
size = path.getsize(p)
|
||||
|
5
scripts/install_ghdl.sh
Executable file
5
scripts/install_ghdl.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -evx
|
||||
wget https://sourceforge.net/projects/ghdl-updates/files/Builds/ghdl-0.33/ghdl-0.33-x86_64-linux.tgz -O /tmp/ghdl.tar.gz
|
||||
mkdir ghdl-0.33
|
||||
tar -C ghdl-0.33 -xvf /tmp/ghdl.tar.gz
|
Loading…
x
Reference in New Issue
Block a user