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

Merge pull request #63 from jck/cosim-experiments

Various cosimulation and testing improvements.
This commit is contained in:
jandecaluwe 2015-04-26 14:48:44 +02:00
commit f4706661bc
19 changed files with 108 additions and 232 deletions

View File

@ -23,11 +23,13 @@ env:
- CI_TARGET=core
- CI_TARGET=icarus
- CI_TARGET=ghdl
- CI_TARGET=bugs
matrix:
allow_failures:
- python: "3.4"
env: CI_TARGET=icarus
- python: "3.4"
env: CI_TARGET=ghdl
script: ./ci.sh

4
ci.sh
View File

@ -23,16 +23,14 @@ echo -e "Running $CI_TARGET tests\n"
CI_TARGET=${CI_TARGET:-core}
if [ "$CI_TARGET" == "core" ]; then
run_test make -C myhdl/test/core
run_test make -C myhdl/test/core2
elif [ "$CI_TARGET" == "icarus" ]; then
run_test make -C "myhdl/test/conversion/general" icarus
run_test make -C cosimulation/icarus test
run_test make -C myhdl/test/conversion/toVerilog
run_test make -C "myhdl/test/bugs" icarus
elif [ "$CI_TARGET" == "ghdl" ]; then
run_test make -C "myhdl/test/conversion/general" GHDL
run_test make -C myhdl/test/conversion/toVHDL GHDL
elif [ "$CI_TARGET" == "bugs" ]; then
run_test make -C "myhdl/test/bugs" icarus
run_test make -C "myhdl/test/bugs" GHDL
fi

View File

@ -5,7 +5,7 @@ myhdl.vpi: myhdl.c myhdl_table.c
.PHONY: test
test: myhdl.vpi
make -C test
cd test && python test_all.py
clean:
-rm *.o *.vpi

View File

@ -1,2 +0,0 @@
all:
python test_all.py

View File

@ -31,4 +31,5 @@ clean:
.PHONY: test
test: myhdl_vpi.so
make -C test
rm -rf test/work
cd test && vlib work && python test_all.py

View File

@ -1,2 +0,0 @@
all:
python test_all.py

View File

@ -2,7 +2,7 @@ import os
from myhdl import Cosimulation
cmd = 'vsim -c -quiet -pli myhdl_vpi.so -do cosim.do dut_bin2gray'
cmd = 'vsim -c -quiet -pli ../myhdl_vpi.so -do cosim.do dut_bin2gray'
def bin2gray(B, G, width):
os.system('vlog -quiet +define+width=%s ../../test/verilog/bin2gray.v' % (width))

View File

@ -2,7 +2,7 @@ import os
from myhdl import Cosimulation
cmd = 'vsim -c -quiet -pli myhdl_vpi.so -do cosim.do dut_dff'
cmd = 'vsim -c -quiet -pli ../myhdl_vpi.so -do cosim.do dut_dff'
def dff(q, d, clk, reset):
os.system('vlog -quiet ../../test/verilog/dff.v')

View File

@ -3,7 +3,7 @@ import os.path as path
from myhdl import Cosimulation
cmd = 'vsim -c -quiet -pli myhdl_vpi.so -do cosim.do dut_dff_clkout'
cmd = 'vsim -c -quiet -pli ../myhdl_vpi.so -do cosim.do dut_dff_clkout'
def dff_clkout(clkout, q, d, clk, reset):
os.system('vlog -quiet ../../test/verilog/dff_clkout.v')

View File

@ -2,7 +2,7 @@ import os
from myhdl import Cosimulation
cmd = 'vsim -c -quiet -pli myhdl_vpi.so -do cosim.do dut_inc'
cmd = 'vsim -c -quiet -pli ../myhdl_vpi.so -do cosim.do dut_inc'
def inc(count, enable, clock, reset, n):
os.system('vlog -quiet +define+n=%s ../../test/verilog/inc.v' % (n))

View File

@ -21,12 +21,13 @@
from __future__ import absolute_import
import sys
import os
import shlex
import subprocess
from myhdl._intbv import intbv
from myhdl import _simulator, CosimulationError
from myhdl._compat import PY2, to_bytes, to_str
from myhdl._compat import PY2, string_types, to_bytes, to_str
_MAXLINE = 4096
@ -67,67 +68,69 @@ class Cosimulation(object):
self._toSizes = toSizes = []
self._toSigs = toSigs = []
self._toSigDict = toSigDict = {}
self._hasChange = 0
self._getMode = 1
child_pid = self._child_pid = os.fork()
if child_pid == 0:
def close_rt_wf():
os.close(rt)
os.close(wf)
os.environ['MYHDL_TO_PIPE'] = str(wt)
os.environ['MYHDL_FROM_PIPE'] = str(rf)
if isinstance(exe, list): arglist = exe
else: arglist = exe.split()
p = arglist[0]
arglist[0] = os.path.basename(p)
try:
os.execvp(p, arglist)
except OSError as e:
raise CosimulationError(_error.OSError, str(e))
else:
os.close(wt)
os.close(rf)
while 1:
s = to_str(os.read(rt, _MAXLINE))
if not s:
raise CosimulationError(_error.SimulationEnd)
e = s.split()
if e[0] == "FROM":
if int(e[1]) != 0:
raise CosimulationError(_error.TimeZero, "$from_myhdl")
for i in range(2, len(e)-1, 2):
n = e[i]
if n in fromSignames:
raise CosimulationError(_error.DuplicateSigNames, n)
if not n in kwargs:
raise CosimulationError(_error.SigNotFound, n)
fromSignames.append(n)
fromSigs.append(kwargs[n])
fromSizes.append(int(e[i+1]))
os.write(wf, b"OK")
elif e[0] == "TO":
if int(e[1]) != 0:
raise CosimulationError(_error.TimeZero, "$to_myhdl")
for i in range(2, len(e)-1, 2):
n = e[i]
if n in toSignames:
raise CosimulationError(_error.DuplicateSigNames, n)
if not n in kwargs:
raise CosimulationError(_error.SigNotFound, n)
toSignames.append(n)
toSigs.append(kwargs[n])
toSigDict[n] = kwargs[n]
toSizes.append(int(e[i+1]))
os.write(wf, b"OK")
elif e[0] == "START":
if not toSignames:
raise CosimulationError(_error.NoCommunication)
os.write(wf, b"OK")
break
else:
raise CosimulationError("Unexpected cosim input")
env = os.environ.copy()
env['MYHDL_TO_PIPE'] = str(wt)
env['MYHDL_FROM_PIPE'] = str(rf)
if isinstance(exe, string_types):
exe = shlex.split(exe)
try:
sp = subprocess.Popen(exe, env=env, close_fds=False,
preexec_fn=close_rt_wf)
except OSError as e:
raise CosimulationError(_error.OSError, str(e))
self._child = sp
os.close(wt)
os.close(rf)
while 1:
s = to_str(os.read(rt, _MAXLINE))
if not s:
raise CosimulationError(_error.SimulationEnd)
e = s.split()
if e[0] == "FROM":
if int(e[1]) != 0:
raise CosimulationError(_error.TimeZero, "$from_myhdl")
for i in range(2, len(e)-1, 2):
n = e[i]
if n in fromSignames:
raise CosimulationError(_error.DuplicateSigNames, n)
if not n in kwargs:
raise CosimulationError(_error.SigNotFound, n)
fromSignames.append(n)
fromSigs.append(kwargs[n])
fromSizes.append(int(e[i+1]))
os.write(wf, b"OK")
elif e[0] == "TO":
if int(e[1]) != 0:
raise CosimulationError(_error.TimeZero, "$to_myhdl")
for i in range(2, len(e)-1, 2):
n = e[i]
if n in toSignames:
raise CosimulationError(_error.DuplicateSigNames, n)
if not n in kwargs:
raise CosimulationError(_error.SigNotFound, n)
toSignames.append(n)
toSigs.append(kwargs[n])
toSigDict[n] = kwargs[n]
toSizes.append(int(e[i+1]))
os.write(wf, b"OK")
elif e[0] == "START":
if not toSignames:
raise CosimulationError(_error.NoCommunication)
os.write(wf, b"OK")
break
else:
raise CosimulationError("Unexpected cosim input")
def _get(self):
if not self._getMode:

View File

@ -78,7 +78,7 @@ class Simulation(object):
_simulator._cosim = 0
os.close(cosim._rt)
os.close(cosim._wf)
os.waitpid(cosim._child_pid, 0)
cosim._child.wait()
if _simulator._tracing:
_simulator._tracing = 0
_simulator._tf.close()

View File

@ -2,6 +2,7 @@ import sys
import types
PY2 = sys.version_info[0] == 2
PYPY = hasattr(sys, 'pypy_translation_info')
_identity = lambda x: x

View File

@ -1,5 +1,5 @@
all:
python test_all.py
py.test
clean:
- rm *.pyc *~

View File

@ -32,9 +32,11 @@ random.seed(1) # random, but deterministic
MAXLINE = 4096
import pytest
from myhdl import Signal
from myhdl._Cosimulation import Cosimulation, CosimulationError, _error
from myhdl._compat import to_bytes, PYPY
exe = "python test_Cosimulation.py CosimulationTest"
@ -54,13 +56,14 @@ toXVals = ["X00", "FZ3", "34XZ", "56U"]
allSigs = fromSigs.copy()
allSigs.update(toSigs)
@pytest.mark.xfail(PYPY, reason="This test does not work on pypy")
class CosimulationTest(TestCase):
def testWrongExe(self):
try:
Cosimulation("bla -x 45")
except CosimulationError as e:
self.assertTrue(e.kind in(_error.OSError, _error.SimulationEnd))
self.assertEqual(e.kind, _error.OSError)
else:
self.fail()
@ -76,11 +79,11 @@ class CosimulationTest(TestCase):
def cosimNotUnique(self):
wt = int(os.environ['MYHDL_TO_PIPE'])
rf = int(os.environ['MYHDL_FROM_PIPE'])
os.write(wt, "TO 00 a 1")
os.write(wt, b"TO 00 a 1")
os.read(rf, MAXLINE)
os.write(wt, "FROM 00 d 1")
os.write(wt, b"FROM 00 d 1")
os.read(rf, MAXLINE)
os.write(wt, "START")
os.write(wt, b"START")
os.read(rf, MAXLINE)
def testFromSignals(self):
@ -94,11 +97,11 @@ class CosimulationTest(TestCase):
buf = "FROM 00 "
for s, w in zip(fromSignames, fromSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
os.write(wt, "TO 0000 a 1")
os.write(wt, b"TO 0000 a 1")
os.read(rf, MAXLINE)
os.write(wt, "START")
os.write(wt, b"START")
os.read(rf, MAXLINE)
def testToSignals(self):
@ -114,11 +117,11 @@ class CosimulationTest(TestCase):
buf = "TO 00 "
for s, w in zip(toSignames, toSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
os.write(wt, "FROM 0000")
os.write(wt, b"FROM 0000")
os.read(rf, MAXLINE)
os.write(wt, "START")
os.write(wt, b"START")
os.read(rf, MAXLINE)
def testFromToSignals(self):
@ -134,14 +137,14 @@ class CosimulationTest(TestCase):
buf = "FROM 00 "
for s, w in zip(fromSignames, fromSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
buf = "TO 00 "
for s, w in zip(toSignames, toSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
os.write(wt, "START")
os.write(wt, b"START")
os.read(rf, MAXLINE)
def testTimeZero(self):
@ -158,7 +161,7 @@ class CosimulationTest(TestCase):
buf = "TO 01 "
for s, w in zip(fromSignames, fromSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
def testNoComm(self):
try:
@ -171,11 +174,11 @@ class CosimulationTest(TestCase):
def cosimNoComm(self):
wt = int(os.environ['MYHDL_TO_PIPE'])
rf = int(os.environ['MYHDL_FROM_PIPE'])
os.write(wt, "FROM 0000")
os.write(wt, b"FROM 0000")
os.read(rf, MAXLINE)
os.write(wt, "TO 0000")
os.write(wt, b"TO 0000")
os.read(rf, MAXLINE)
os.write(wt, "START ")
os.write(wt, b"START ")
os.read(rf, MAXLINE)
def testFromSignalsDupl(self):
@ -193,7 +196,7 @@ class CosimulationTest(TestCase):
for s, w in zip(fromSignames, fromSizes):
buf += "%s %s " % (s, w)
buf += "bb 5"
os.write(wt, buf)
os.write(wt, to_bytes(buf))
def testToSignalsDupl(self):
try:
@ -210,7 +213,7 @@ class CosimulationTest(TestCase):
for s, w in zip(toSignames, toSizes):
buf += "%s %s " % (s, w)
buf += "fff 6"
os.write(wt, buf)
os.write(wt, to_bytes(buf))
def testFromSignalVals(self):
cosim = Cosimulation(exe + ".cosimFromSignalVals", **allSigs)
@ -224,15 +227,15 @@ class CosimulationTest(TestCase):
buf = "FROM 00 "
for s, w in zip(fromSignames, fromSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
os.write(wt, "TO 0000 a 1")
os.write(wt, b"TO 0000 a 1")
os.read(rf, MAXLINE)
os.write(wt, "START")
os.write(wt, b"START")
os.read(rf, MAXLINE)
os.write(wt, "DUMMY")
os.write(wt, b"DUMMY")
s = os.read(rf, MAXLINE)
vals = [long(e, 16) for e in s.split()[1:]]
vals = [int(e, 16) for e in s.split()[1:]]
self.assertEqual(vals, fromVals)
def testToSignalVals(self):
@ -242,7 +245,7 @@ class CosimulationTest(TestCase):
cosim._get()
for n, v in zip(toSignames, toVals):
self.assertEqual(toSigs[n].next, v)
os.write(cosim._wf, "DUMMY")
os.write(cosim._wf, b"DUMMY")
cosim._getMode = 1
cosim._get()
for n in toSignames:
@ -255,14 +258,14 @@ class CosimulationTest(TestCase):
buf = "FROM 00 "
for s, w in zip(fromSignames, fromSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
buf = "TO 00 "
for s, w in zip(toSignames, toSizes):
buf += "%s %s " % (s, w)
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
os.write(wt, "START")
os.write(wt, b"START")
os.read(rf, MAXLINE)
buf = "0 "
for s, v in zip(toSignames, toVals):
@ -270,7 +273,7 @@ class CosimulationTest(TestCase):
buf += " "
buf += hex(v)[2:]
buf += " "
os.write(wt, buf)
os.write(wt, to_bytes(buf))
os.read(rf, MAXLINE)
buf = "0 "
for s, v in zip(toSignames, toXVals):
@ -278,7 +281,7 @@ class CosimulationTest(TestCase):
buf += " "
buf += v
buf += " "
os.write(wt, buf)
os.write(wt, to_bytes(buf))
def suite():
return unittest.makeSuite(CosimulationTest, 'test')

View File

@ -1,50 +0,0 @@
# This file is part of the myhdl library, a Python package for using
# Python as a Hardware Description Language.
#
# Copyright (C) 2003-2008 Jan Decaluwe
#
# The myhdl library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" Run all myhdl unit tests. """
from __future__ import absolute_import
import test_Simulation, test_Signal, test_intbv, test_Cosimulation, test_misc, \
test_always_comb, test_bin, test_traceSignals, test_enum, test_concat, \
test_inferWaiter, test_always, test_instance, test_signed, \
test_modbv
modules = (test_Simulation, test_Signal, test_intbv, test_misc, test_always_comb,
test_bin, test_traceSignals, test_enum, test_concat,
test_inferWaiter, test_always, test_instance, test_signed,
test_modbv
)
import unittest
tl = unittest.defaultTestLoader
def suite():
alltests = unittest.TestSuite()
for m in modules:
alltests.addTest(tl.loadTestsFromModule(m))
return alltests
def main():
unittest.main(defaultTest='suite',
testRunner=unittest.TextTestRunner(verbosity=2))
if __name__ == '__main__':
main()

View File

@ -1,76 +0,0 @@
# This file is part of the myhdl library, a Python package for using
# Python as a Hardware Description Language.
#
# Copyright (C) 2003-2008 Jan Decaluwe
#
# The myhdl library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" Run the unit tests for _unparse """
from __future__ import absolute_import
import unittest
from unittest import TestCase
import compiler
from myhdl._unparse import _unparse
class UnparseTest(TestCase):
expressions = [ "a + b",
"a - b",
"(a + b)",
"(a - b) - ( c + d) + 1",
"a & b",
"a | b",
"a ^ b",
"a < b",
"a < c > 1",
"a == b <= c >= d != e",
"a // b",
"~c",
"a << b",
"c % d",
"e * f + c",
"not e",
"d or a",
"a and b or c and d",
"a ** b",
"a >> b",
"a[m:n]",
"a[m+1:m-2]",
"a[n]",
"+e",
"-f",
"a(b)",
"f(g, h, i)",
"f(g, h, *args)",
"f(g, h, **kwargs)",
"f(g, h, *args, **kwargs)",
"f.attr",
"f.attr + 1 * h(g[k//2:3] & b[m])"
]
def testUnparse(self):
for expr in self.expressions:
ast = compiler.parse(expr)
s = _unparse(ast )
ast_unparse = compiler.parse(s)
self.assertEqual(str(ast), str(ast_unparse))
if __name__ == "__main__":
unittest.main()

View File

@ -1,2 +0,0 @@
all:
py.test