"""
+
+def port_decl_do_not_use(comment, dt, name):
+ if dt is None or dt.dims is None:
+ width = '' # width: 1
+ else:
+ width = dt.dims
+ # XXX TODO, better checking, should be using data structure... *sigh*
+ width = width[1:-1] # strip brackets
+ width = width.split(':')
+ assert width[0] == '0'
+ width = width[1]
+ return 'self.%s = Signal(%s) # %s' % (name, width, comment)
+
+
indent_debug = 0
+
+class PortDecl:
+ def __init__(self, comment, dt, name):
+ self.comment = comment
+ self.dt = dt
+ self.name = name
+
+ def initNode(self):
+ return port_decl_do_not_use(self.comment, self.dt, self.name)
+
+
+class Assignment:
+ def __init__(self, left, op, right):
+ self.left = left
+ self.op = op
+ self.right = right
+
+ def debugInfo(self):
+ return "Assignment:"+str(self.left) + " "+str(self.op)+" "+str(self.right)
+
+
+class CondStatement:
+ def __init__(self, cond, ifpart, elsepart):
+ self.cond = cond
+ self.ifpart = ifpart
+ self.elsepart = elsepart
+
+
+def makeBlock(x):
+ if(type(x) == Assignment):
+ return [x]
+ else:
+ return x.statements
+
+
class Absyn:
- def __init__(self):
- self.outputfile = open("output.py","w")
- self.outputfile.write(preamble)
- def printpy(self,p):
+ def __init__(self, outputfn):
+ self.outputfn = outputfn
+ self.outputfile = None
+ self.assign = []
+ self.ports = []
+ self.wires = []
+ self.comb = []
+
+ def open(self):
+ if(self.outputfile is None):
+ self.outputfile = open(self.outputfn, "w")
+ self.outputfile.write(preamble)
+
+ def printpy(self, p):
+ self.open()
self.outputfile.write(str(p)+"\n")
- def assign(self,p):
+
+ def assign(self, p):
p = list(p)
- if(p[1]=="assign"):
+ if(p[1] == "assign"):
self.printpy(p[4])
- # m.d.comb += [l.eq(r)]
- def indent(self,count):
+
+ def assign3(self, left, op, right):
+ return Assignment(left, op, right)
+
+ def cond_statement3(self, cond, ifpart, elsepart):
+ return CondStatement(cond, ifpart, elsepart)
+
+ def indent(self, count):
if(indent_debug):
return Leaf(token.INDENT, '>>> '*count)
else:
return Leaf(token.INDENT, ' '*4*count)
-
- def dedent(self,count):
+
+ def dedent(self, count):
return Leaf(token.DEDENT, '')
+
def nl(self):
- return Leaf(token.NEWLINE, '#\n')
-
- def initPorts(self,params,ports):
- pass_stmt = Node(syms.pass_stmt ,[Leaf(token.NAME, "def __init__(self):")])
- if params:
- params = [Leaf(token.LPAR, '(')] + params + [Leaf(token.RPAR, ')')]
- fn = [Leaf(token.NAME, 'def'),
- Leaf(token.NAME, '__initXXX__', prefix=' '),
- Node(syms.parameters, params),
- Leaf(token.COLON, ':')]
- fndef = Node(syms.funcdef, fn)
- stmts = Node(syms.stmt, [fndef])
- else:
- stmts = Node(syms.small_stmt, [pass_stmt, Leaf(token.NEWLINE, '\n')])
- stmts = Node(syms.stmt, [stmts])
-
+ return Leaf(token.NEWLINE, '\n')
+
+ def port_decl(self, comment, dt, name):
+ port = PortDecl(comment, dt, name)
+ self.ports += [port]
+ return port
+
+ def isPort(self, name):
+ for p in self.ports:
+ if(str(p.name) == str(name)):
+ return True
+ return False
+
+ def initFunc(self, ports, params):
+ params = [Leaf(token.LPAR, '('), Leaf(
+ token.NAME, "self")] + [Leaf(token.RPAR, ')')]
+ # TODO handle sv params
+ fn = [Leaf(token.NAME, 'def'),
+ Leaf(token.NAME, '__init__', prefix=' '),
+ Node(syms.parameters, params),
+ Leaf(token.COLON, ':'),
+ self.nl()
+ ]
+ fndef = Node(syms.funcdef, fn)
+ stmts = Node(syms.stmt, [fndef])
for port in ports:
stmts.children.append(self.indent(2))
- stmts.children.append(port)
+ stmts.children.append(port.initNode())
+ stmts.children.append(self.nl())
+ return stmts
+
+ def do_assign(self, a, stmts, indent):
+ stmts.children.append(self.indent(indent))
+ stmts.children.append(Leaf(token.STRING, "m.d.comb += "))
+ if(self.isPort(a.left)):
+ stmts.children.append(Leaf(token.STRING, "self."))
+ stmts.children.append(Leaf(token.STRING, a.left))
+ stmts.children.append(Leaf(token.STRING, ".eq("))
+ if(self.isPort(a.right)):
+ stmts.children.append(Leaf(token.STRING, "self."))
+ stmts.children.append(Leaf(token.STRING, a.right))
+ stmts.children.append(Leaf(token.STRING, ")"))
+ stmts.children.append(self.nl())
+
+ def do_ifblock(self, c, stmts, indent):
+ stmts.children.append(self.indent(indent))
+ stmts.children.append(Leaf(token.STRING, "with m.If("))
+ if(self.isPort(c.cond)):
+ stmts.children.append(Leaf(token.STRING, "self."))
+ stmts.children.append(Leaf(token.STRING, c.cond))
+ stmts.children.append(Leaf(token.STRING, "):"))
+ stmts.children.append(self.nl())
+
+ for c1 in makeBlock(c.ifpart):
+ if(type(c1) == Assignment):
+ self.do_assign(c1, stmts, indent+1)
+ else:
+ self.do_ifblock(c1, stmts, indent+1)
+
+ if(c.elsepart):
+ stmts.children.append(self.indent(indent))
+ stmts.children.append(Leaf(token.STRING, "with m.Else():"))
stmts.children.append(self.nl())
+ for c1 in makeBlock(c.elsepart):
+ if(type(c1) == Assignment):
+ self.do_assign(c1, stmts, indent+1)
+ else:
+ self.do_ifblock(c1, stmts, indent+1)
+
+ def elaborateFunc(self):
+ params = [Leaf(token.LPAR, '('), Leaf(
+ token.NAME, "self, platform=None"), Leaf(token.RPAR, ')')]
+ fn = [Leaf(token.NAME, 'def'),
+ Leaf(token.NAME, 'elaborate', prefix=' '),
+ Node(syms.parameters, params),
+ Leaf(token.COLON, ':'),
+ self.nl()
+ ]
+ fndef = Node(syms.funcdef, fn)
+ stmts = Node(syms.stmt, [fndef])
+ stmts.children.append(self.indent(2))
+ stmts.children.append(Leaf(token.STRING, "m = Module()"))
+ stmts.children.append(self.nl())
+
+ for w in self.wires:
+ wirename = w[0]
+ hasdims = (len(w) >= 4)
+ stmts.children.append(self.indent(2))
+ stmts.children.append(Leaf(token.STRING, wirename))
+ stmts.children.append(Leaf(token.STRING, " = Signal("))
+ if(hasdims):
+ stmts.children.append(Leaf(token.STRING, str(w[3])))
+ stmts.children.append(Leaf(token.STRING, ")"))
+ stmts.children.append(self.nl())
+
+ # refactor: assignments non cond
+ for a in self.assign:
+ self.do_assign(a, stmts)
+
+ for c in self.comb:
+ print("comb", c)
+ if(type(c) == Assignment):
+ self.do_assign(c, stmts, 2)
+ else:
+ self.do_ifblock(c, stmts, 2)
+
+ stmts.children.append(self.indent(2))
+ stmts.children.append(Leaf(token.STRING, "return m"))
+ stmts.children.append(self.nl())
return stmts
-
-
- def module_1(self,p):
+
+ def module_1(self, p):
params = p[7]
ports = p[8]
clsname = [Leaf(token.NAME, 'class'),
Leaf(token.NAME, p[4], prefix=' '),
- Leaf(token.LPAR,'('),
+ Leaf(token.LPAR, '('),
Leaf(token.NAME, 'Elaboratable'),
- Leaf(token.LPAR,')'),
+ Leaf(token.LPAR, ')'),
Leaf(token.COLON, ':'),
- ]
+ self.nl(),
+ ]
suite = Node(syms.suite, [Leaf(token.NEWLINE, '\n'),
self.indent(1),
- self.initPorts(params,ports),
- self.dedent(1)
- ])
+ self.initFunc(ports, params),
+ self.indent(1),
+ self.elaborateFunc()
+
+ ])
clsdecl = Node(syms.classdef, clsname + [suite])
clsdecl = Node(syms.compound_stmt, [clsdecl])
- #.printpy("#clsdecl"+ repr(clsdecl))
- #absyn.printpy("#clsstr:")
+
self.printpy(str(clsdecl))
return clsdecl
+
+ def module_item_2(self, signaltype, dims, mlist):
+ if(signaltype == "wire"):
+ for m in mlist:
+ if(dims):
+ self.wires.append(m+dims)
+ else:
+ self.wires.append(m)
+
+ def appendComments(self, data):
+ self.open()
+ self.outputfile.write(data)
+ #lines = data.split("\n")
+ # for line in lines:
+ # self.printpy("#"+line)
+
+ # combinatorical assign
+ def cont_assign_1(self, p):
+ self.assign += [Assignment(p[1], p[2], p[3])]
+
+ # cond assigmments and other nested blocks
+ def always_comb(self, p3, p1):
+ print("always_comb")
+ slist = p3[6]
+ self.comb += slist.statements