X-Git-Url: https://git.libre-soc.org/?p=sv2nmigen.git;a=blobdiff_plain;f=absyn.py;h=7d54d6e3e76092384e6c00ff19e03f6cb0b2ddc3;hp=6ccbb0529944f48fcc57d1578f573bfcd8cffd10;hb=HEAD;hpb=e2973c57aa90034c4fb3bff4a1de95b0fd1c9ccc diff --git a/absyn.py b/absyn.py index 6ccbb05..386e5d3 100644 --- a/absyn.py +++ b/absyn.py @@ -10,72 +10,122 @@ 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 + 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[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): + def __init__(self, comment, dt, name): self.comment = comment - self.dt=dt - self.name=name + self.dt = dt + self.name = name + def initNode(self): - return port_decl_do_not_use(self.comment,self.dt,self.name) + return port_decl_do_not_use(self.comment, self.dt, self.name) + class Assignment: - def __init__(self,left,op,right): + 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] + elif(type(x) == CondStatement): + return [x] + else: + return x.statements + + class Absyn: - def __init__(self,outputfn): - self.outputfile = open(outputfn,"w") - self.outputfile.write(preamble) + def __init__(self, outputfn): + self.outputfn = outputfn + self.outputfile = None self.assign = [] self.ports = [] - def printpy(self,p): + self.wires = [] + self.comb = [] + self.sync = [] + + 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 port_decl(self,comment, dt, name): - port = PortDecl(comment,dt,name) + + def port_decl(self, comment, dt, name): + port = PortDecl(comment, dt, name) self.ports += [port] return port - def initFunc(self,ports,params): - params = [Leaf(token.LPAR, '('),Leaf(token.NAME,"self")] + [Leaf(token.RPAR, ')')] + 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: @@ -84,75 +134,144 @@ class Absyn: 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.")) + stmts.children.append(Leaf(token.STRING, self.blocktype)) + stmts.children.append(Leaf(token.STRING, " += ")) + 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, ')')] + 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(Leaf(token.STRING, "m = Module()")) stmts.children.append(self.nl()) - - for a in self.assign: + for w in self.wires: + wirename = w[0] + hasdims = (len(w) >= 4) stmts.children.append(self.indent(2)) - # m.d.sync += self.left.eq(right) - stmts.children.append(Leaf(token.STRING,"m.d.comb += self.")) - stmts.children.append(Leaf(token.STRING,a.left)) - stmts.children.append(Leaf(token.STRING,".eq(self.")) - stmts.children.append(Leaf(token.STRING,a.right)) - stmts.children.append(Leaf(token.STRING,")")) + 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: - # - # - #ports = a[8] - # - - stmts.children.append(self.indent(2)) - stmts.children.append(Leaf(token.STRING,"return m")) + + self.blocktype = "comb" + for a in self.assign: + self.do_assign(a, stmts, 2) + + for c in self.comb: + if(type(c) == Assignment): + self.do_assign(c, stmts, 2) + else: + self.do_ifblock(c, stmts, 2) + + self.blocktype = "sync" + for c in self.sync: + 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.initFunc(ports,params), + 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)) - print("=====================") - print(str(clsdecl)) return clsdecl - def appendComments(self,data): - lines = data.split("\n") - for line in lines: - self.printpy("#"+line) + 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): - # print("#ASSIGN:BROKEN"+str(list(p))) - self.assign += [Assignment(p[1],p[2],p[3])] + 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): + slist = p3[6] + self.comb += slist.statements + + def always_ff(self, p3, p1): + slist = p3[1] + self.sync += slist.statements