1
0
mirror of https://github.com/myhdl/myhdl.git synced 2024-12-14 07:44:38 +08:00
This commit is contained in:
jand 2003-10-22 13:01:06 +00:00
parent 418d9ec490
commit 3f6fb7d34d
5 changed files with 243 additions and 39 deletions

View File

@ -112,6 +112,8 @@ class Signal(object):
else:
self._type = type(val)
self._setNextVal = self._setNextType
if hasattr(val, '_nrbits'):
self._nrbits = val._nrbits
self._eventWaiters = _WaiterList()
self._posedgeWaiters = _WaiterList()
self._negedgeWaiters = _WaiterList()

View File

@ -27,6 +27,7 @@ __date__ = "$Date$"
from types import StringType
from myhdl._util import bin
def enum(*args):
@ -34,6 +35,7 @@ def enum(*args):
# only default encoding for now
argdict = {}
encoding = {}
nrbits = len(bin(len(args)))
i = 0
for arg in args:
if type(arg) is not StringType:
@ -41,20 +43,25 @@ def enum(*args):
if encoding.has_key(arg):
raise ValueError("enum literals should be unique")
argdict[i] = arg
encoding[arg] = i
encoding[arg] = bin(i, nrbits)
i += 1
class EnumItem(object):
def __init__(self, arg):
def __init__(self, index, arg):
self._index = index
self._val = encoding[arg]
self._nrbits = nrbits
def __repr__(self):
return argdict[self._val]
return argdict[self._index]
def __hex__(self):
return hex(int(self._val, 2))
__str__ = __repr__
class Enum(object):
def __init__(self):
for slot in args:
self.__dict__[slot] = EnumItem(slot)
for index, slot in enumerate(args):
self.__dict__[slot] = EnumItem(index, slot)
self.__dict__['_nrbits'] = nrbits
def __setattr__(self, attr, val):
raise AttributeError("Cannot assign to enum attributes")
def __len__(self):

View File

@ -30,6 +30,7 @@ from __future__ import generators
import sys
from inspect import currentframe, getframeinfo, getouterframes
import re
import string
from types import GeneratorType
import compiler
from compiler import ast
@ -123,9 +124,10 @@ class _HierExtr(object):
global _profileFunc
self.skipNames = ('always_comb', 'instances', 'processes')
self.skip = 0
self.names = [name]
self.names = []
self.instNamesStack = [Set()]
self.hierarchy = hierarchy = []
self.gennames = gennames = {}
self.level = 0
# handle special case of a top-level generator separately
if _isGenFunc(dut):
@ -165,6 +167,8 @@ class _HierExtr(object):
self.level += 1
self.instNamesStack.append(Set())
elif event == "return":
truenames = [n for n in self.names[1:] if n is not None]
prefix = '_'.join(truenames)
if not self.skip:
name = self.names.pop()
if name:
@ -189,6 +193,10 @@ class _HierExtr(object):
gsigdict[n] = v
inst = [self.level+1, gname, gsigdict]
self.hierarchy.append(inst)
absgname = gname
if prefix:
absgname = prefix + "_" + gname
self.gennames[id(g)] = absgname
inst = [self.level, name, sigdict]
self.hierarchy.append(inst)
self.level -= 1

View File

@ -30,9 +30,10 @@ import inspect
import compiler
from compiler import ast
from sets import Set
from types import GeneratorType
from types import GeneratorType, ClassType
from cStringIO import StringIO
from myhdl import Signal, intbv
from myhdl._extractHierarchy import _HierExtr, _findInstanceName
@ -99,13 +100,13 @@ def toVerilog(func, *args, **kwargs):
tbfile = open(tbpath, 'w')
siglist = _analyzeSigs(h.hierarchy)
astlist = _analyzeGens(_flatten(h.top))
genlist = _analyzeGens(_flatten(h.top), h.gennames)
intf = _analyzeTopFunc(func, *args, **kwargs)
intf.name = name
_writeModuleHeader(vfile, intf)
_writeSigDecls(vfile, intf, siglist)
_convertGens(astlist, vfile)
_convertGens(genlist, vfile)
_writeModuleFooter(vfile)
_writeTestBench(tbfile, intf)
@ -143,15 +144,21 @@ def _analyzeSigs(hierarchy):
return siglist
def _analyzeGens(top):
def LabelGenerator():
i = 1
while 1:
yield "_MYHDL_LABEL_%s" % i
i += 1
def _analyzeGens(top, gennames):
genLabel = LabelGenerator()
genlist = []
for g in top:
f = g.gi_frame
s = inspect.getsource(f)
s = s.lstrip()
ast = compiler.parse(s)
ast.locals = f.f_locals
ast.globals = f.f_globals
symdict = f.f_globals.copy()
symdict.update(f.f_locals)
sigdict = {}
@ -160,6 +167,10 @@ def _analyzeGens(top):
sigdict[n] = v
ast.sigdict = sigdict
ast.symdict = symdict
if gennames.has_key(id(g)):
ast.name = gennames[id(g)]
else:
ast.name = genLabel.next()
v = _AnalyzeGenVisitor(sigdict)
compiler.walk(ast, v)
genlist.append(ast)
@ -371,6 +382,8 @@ def _getRangeString(s):
return ''
elif s._type is intbv:
return "[%s:0] " % (s._nrbits-1)
elif s._nrbits is not None:
return "[%s:0] " % (s._nrbits-1)
else:
raise AssertionError
@ -379,8 +392,9 @@ def _getRangeString(s):
class _convertGenVisitor(object):
def __init__(self, f, sigdict, symdict):
def __init__(self, f, sigdict, symdict, name):
self.buf = self.fileBuf = f
self.name = name
self.declBuf = StringIO()
self.codeBuf = StringIO()
self.sigdict = sigdict
@ -388,13 +402,7 @@ class _convertGenVisitor(object):
self.ind = ''
self.inYield = False
self.isSigAss = False
self.genLabel = self.LabelGenerator()
def LabelGenerator(self):
i = 1
while 1:
yield "LABEL_%s" % i
i += 1
def write(self, arg):
self.buf.write("%s" % arg)
@ -442,17 +450,32 @@ class _convertGenVisitor(object):
def visitCallFunc(self, node):
self.visit(node.node)
self.write(' ')
self.visit(node.args[0])
f = node.node
assert isinstance(f, ast.Name)
self.visit(f)
if f.name in self.symdict:
obj = self.symdict[f.name]
elif f.name in __builtins__:
obj = __builtins__[f.name]
else:
raise AssertionError
if type(obj) in (ClassType, type) and issubclass(obj, Exception):
self.write(": ")
else:
self.write(' ')
if node.args:
self.visit(node.args[0])
# XXX
def visitCompare(self, node):
self.write("(")
self.visit(node.expr)
assert len(node.ops) == 1
op, code = node.ops[0]
self.write(" %s " % op)
self.visit(code)
self.write(")")
def visitConst(self, node):
self.write(node.value)
@ -497,7 +520,7 @@ class _convertGenVisitor(object):
self.write("always @(")
self.visit(sl)
self.inYield = False
self.write(") begin: %s" % self.genLabel.next())
self.write(") begin: %s" % self.name)
self.indent()
self.buf = self.codeBuf
for s in w.body.nodes[1:]:
@ -512,21 +535,31 @@ class _convertGenVisitor(object):
self.writeline()
def visitGetattr(self, node):
if node.attrname == 'next':
self.isSigAss = True
self.visit(node.expr)
assert isinstance(node.expr, ast.Name)
assert node.expr.name in self.symdict
obj = self.symdict[node.expr.name]
if type(obj) is Signal:
if node.attrname == 'next':
self.isSigAss = True
self.visit(node.expr)
elif str(type(obj)) == "<class 'myhdl._enum.Enum'>":
assert hasattr(obj, node.attrname)
e = getattr(obj, node.attrname)
self.write("%d'b%s" % (obj._nrbits, e._val))
def visitIf(self, node):
self.writeline()
self.write("if (")
test, suite = node.tests[0]
self.visit(test)
self.write(") begin")
self.indent()
self.visit(suite)
self.dedent()
self.writeline()
self.write("end")
ifstring = "if ("
for test, suite in node.tests:
self.writeline()
self.write(ifstring)
self.visit(test)
self.write(") begin")
self.indent()
self.visit(suite)
self.dedent()
self.writeline()
self.write("end")
ifstring = "else if ("
if node.else_:
self.writeline()
self.write("else begin")
@ -537,10 +570,12 @@ class _convertGenVisitor(object):
self.write("end")
def visitMod(self, node):
self.write("(")
self.visit(node.left)
self.write(" % ")
self.visit(node.right)
self.write(")")
def visitName(self, node):
if node.name in self.symdict:
obj = self.symdict[node.name]
@ -553,6 +588,27 @@ class _convertGenVisitor(object):
else:
self.write(node.name)
def visitNot(self, node):
self.write("(!")
self.visit(node.expr)
self.write(")")
def visitRaise(self, node):
self.writeline()
self.write('$display("')
self.visit(node.expr1)
self.write('");')
self.writeline()
self.write("$finish;")
def visitSub(self, node):
self.write("(")
self.visit(node.left)
self.write(" - ")
self.visit(node.right)
self.write(")")
def visitSubscript(self, node):
self.visit(node.expr)
self.write("[")
@ -580,7 +636,7 @@ class _convertGenVisitor(object):
def _convertGens(astlist, vfile):
for ast in astlist:
v = _convertGenVisitor(vfile, ast.sigdict, ast.symdict)
v = _convertGenVisitor(vfile, ast.sigdict, ast.symdict, ast.name)
compiler.walk(ast, v)

View File

@ -0,0 +1,131 @@
import os
path = os.path
import unittest
from unittest import TestCase
from myhdl import *
# SEARCH, CONFIRM, SYNC = range(3)
ACTIVE_LOW = 0
FRAME_SIZE = 8
t_State = enum('SEARCH', 'CONFIRM', 'SYNC')
def FramerCtrl(SOF, state, syncFlag, clk, reset_n):
""" Framing control FSM.
SOF -- start-of-frame output bit
state -- FramerState output
syncFlag -- sync pattern found indication input
clk -- clock input
reset_n -- active low reset
"""
index = Signal(intbv(0)[8:]) # position in frame
def FSM():
while 1:
yield posedge(clk), negedge(reset_n)
if reset_n == ACTIVE_LOW:
SOF.next = 0
index.next = 0
state.next = t_State.SEARCH
else:
index.next = (index + 1) % FRAME_SIZE
SOF.next = 0
if state == t_State.SEARCH:
index.next = 1
if syncFlag:
state.next = t_State.CONFIRM
elif state == t_State.CONFIRM:
if index == 0:
if syncFlag:
state.next = t_State.SYNC
else:
state.next = t_State.SEARCH
elif state == t_State.SYNC:
if index == 0:
if not syncFlag:
state.next = t_State.SEARCH
SOF.next = (index == FRAME_SIZE-1)
else:
raise ValueError("Undefined state")
FSM_1 = FSM()
return FSM_1
analyze_cmd = "iverilog -o framerctrl framerctrl.v tb_framerctrl.v"
simulate_cmd = "vvp -m ../../../cosimulation/icarus/myhdl.vpi framerctrl"
def FramerCtrl_v(SOF, state, syncFlag, clk, reset_n):
if path.exists("framectrl"):
os.remove("framectrl")
os.system(analyze_cmd)
return Cosimulation(simulate_cmd, **locals())
class FramerCtrlTest(TestCase):
def bench(self):
SOF = Signal(bool(0))
SOF_v = Signal(bool(0))
syncFlag = Signal(bool(0))
clk = Signal(bool(0))
reset_n = Signal(bool(1))
state = Signal(t_State.SEARCH)
state_v = Signal(intbv(0)[2:])
framerctrl = toVerilog(FramerCtrl, SOF, state, syncFlag, clk, reset_n)
framerctrl_v = FramerCtrl_v(SOF_v, state_v, syncFlag, clk, reset_n)
def clkgen():
reset_n.next = 1
yield delay(10)
reset_n.next = 0
yield delay(10)
reset_n.next = 1
yield delay(10)
while 1:
yield delay(10)
clk.next = not clk
def stimulus():
for i in range(3):
yield posedge(clk)
for n in (12, 8, 8, 4, 11, 8, 8, 7, 6, 8, 8):
syncFlag.next = 1
yield posedge(clk)
syncFlag.next = 0
for i in range(n-1):
yield posedge(clk)
raise StopSimulation
def check():
while 1:
yield negedge(clk)
self.assertEqual(SOF, SOF_v)
self.assertEqual(eval(hex(state)), eval(hex(state_v)))
# print "MyHDL: %s %s" % (SOF, hex(state))
# print "Verilog: %s %s" % (SOF_v, hex(state_v))
return framerctrl, framerctrl_v, clkgen(), stimulus(), check()
def test(self):
tb_fsm = self.bench()
sim = Simulation(tb_fsm)
sim.run()
if __name__ == '__main__':
unittest.main()