X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=absyn.py;h=ecd3846516ddf89e773c7b3bdb20754cf52e5e8b;hb=10c1bd0020878f84ededfa7c47d0ed4fd43f50bf;hp=c59f8b6dc559fc6c04f626ccf80702c9da8615ba;hpb=8cf06d22508dc51c013b6dce81869db32d0bd4e3;p=sv2nmigen.git diff --git a/absyn.py b/absyn.py index c59f8b6..ecd3846 100644 --- a/absyn.py +++ b/absyn.py @@ -1,5 +1,206 @@ +from lib2to3.pytree import Node, Leaf +from lib2to3.pgen2 import token +from lib2to3.pygram import python_symbols as syms + +preamble = """# this file has been generated by sv2nmigen + +from nmigen import Signal, Module, Const, Cat, Elaboratable + + + +""" + + +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 + + class Absyn: - def __init__(self): - self.outputfile = open("output.py","w") - def printpy(self,p): + def __init__(self, outputfn): + self.outputfn = outputfn + self.outputfile = None + self.assign = [] + self.ports = [] + self.wires = [] + + 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): + p = list(p) + if(p[1] == "assign"): + self.printpy(p[4]) + + def assign3(self, left, op, right): + return Assignment(left, op, right) + + def indent(self, count): + if(indent_debug): + return Leaf(token.INDENT, '>>> '*count) + else: + return Leaf(token.INDENT, ' '*4*count) + + def dedent(self, count): + return Leaf(token.DEDENT, '') + + def nl(self): + 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.initNode()) + stmts.children.append(self.nl()) + return stmts + + 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()) + + for a in self.assign: + stmts.children.append(self.indent(2)) + # m.d.sync += self.left.eq(right) + 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()) + + 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): + params = p[7] + ports = p[8] + clsname = [Leaf(token.NAME, 'class'), + Leaf(token.NAME, p[4], prefix=' '), + Leaf(token.LPAR, '('), + Leaf(token.NAME, 'Elaboratable'), + Leaf(token.LPAR, ')'), + Leaf(token.COLON, ':'), + self.nl(), + ] + + suite = Node(syms.suite, [Leaf(token.NEWLINE, '\n'), + self.indent(1), + self.initFunc(ports, params), + self.indent(1), + self.elaborateFunc() + + ]) + clsdecl = Node(syms.classdef, clsname + [suite]) + clsdecl = Node(syms.compound_stmt, [clsdecl]) + + 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])] + + def always_comb(self, p3, p1): + print("always_comb") + slist = p3[6] + for s in slist.statements: + self.assign += [s]