convert numbers to python format
[sv2nmigen.git] / absyn.py
1 from lib2to3.pytree import Node, Leaf
2 from lib2to3.pgen2 import token
3 from lib2to3.pygram import python_symbols as syms
4
5 preamble = """# this file has been generated by sv2nmigen
6
7 from nmigen import Signal, Module, Const, Cat, Elaboratable
8
9
10
11 """
12
13 def port_decl_do_not_use(comment, dt, name):
14 if dt is None or dt.dims is None:
15 width = '' # width: 1
16 else:
17 width = dt.dims
18 # XXX TODO, better checking, should be using data structure... *sigh*
19 width = width[1:-1] # strip brackets
20 width = width.split(':')
21 assert width[0] == '0'
22 width = width[1]
23 return 'self.%s = Signal(%s) # %s' % (name, width, comment)
24
25 indent_debug = 0
26
27 class PortDecl:
28 def __init__(self,comment,dt,name):
29 self.comment = comment
30 self.dt=dt
31 self.name=name
32 def initNode(self):
33 return port_decl_do_not_use(self.comment,self.dt,self.name)
34
35 class Assignment:
36 def __init__(self,left,op,right):
37 self.left = left
38 self.op = op
39 self.right = right
40
41 class Absyn:
42 def __init__(self,outputfn):
43 self.outputfile = open(outputfn,"w")
44 self.outputfile.write(preamble)
45 self.assign = []
46 self.ports = []
47 def printpy(self,p):
48 self.outputfile.write(str(p)+"\n")
49 def assign(self,p):
50 p = list(p)
51 if(p[1]=="assign"):
52 self.printpy(p[4])
53 # m.d.comb += [l.eq(r)]
54 def indent(self,count):
55 if(indent_debug):
56 return Leaf(token.INDENT, '>>> '*count)
57 else:
58 return Leaf(token.INDENT, ' '*4*count)
59
60 def dedent(self,count):
61 return Leaf(token.DEDENT, '')
62 def nl(self):
63 return Leaf(token.NEWLINE, '\n')
64
65 def port_decl(self,comment, dt, name):
66 port = PortDecl(comment,dt,name)
67 self.ports += [port]
68 return port
69
70 def initFunc(self,ports,params):
71 params = [Leaf(token.LPAR, '('),Leaf(token.NAME,"self")] + [Leaf(token.RPAR, ')')]
72 # TODO handle sv params
73 fn = [Leaf(token.NAME, 'def'),
74 Leaf(token.NAME, '__init__', prefix=' '),
75 Node(syms.parameters, params),
76 Leaf(token.COLON, ':'),
77 self.nl()
78 ]
79 fndef = Node(syms.funcdef, fn)
80 stmts = Node(syms.stmt, [fndef])
81 for port in ports:
82 stmts.children.append(self.indent(2))
83 stmts.children.append(port.initNode())
84 stmts.children.append(self.nl())
85 return stmts
86
87 def elaborateFunc(self):
88 params = [Leaf(token.LPAR, '('),Leaf(token.NAME,"self, platform=None"),Leaf(token.RPAR, ')')]
89 fn = [Leaf(token.NAME, 'def'),
90 Leaf(token.NAME, 'elaborate', prefix=' '),
91 Node(syms.parameters, params),
92 Leaf(token.COLON, ':'),
93 self.nl()
94 ]
95 fndef = Node(syms.funcdef, fn)
96 stmts = Node(syms.stmt, [fndef])
97 stmts.children.append(self.indent(2))
98 stmts.children.append(Leaf(token.STRING,"m = Module()"))
99 stmts.children.append(self.nl())
100
101
102 for a in self.assign:
103 stmts.children.append(self.indent(2))
104 # m.d.sync += self.left.eq(right)
105 stmts.children.append(Leaf(token.STRING,"m.d.comb += self."))
106 stmts.children.append(Leaf(token.STRING,a.left))
107 stmts.children.append(Leaf(token.STRING,".eq(self."))
108 stmts.children.append(Leaf(token.STRING,a.right))
109 stmts.children.append(Leaf(token.STRING,")"))
110 stmts.children.append(self.nl())
111
112 #for a in self.assign:
113 #
114 #
115 #ports = a[8]
116 #
117
118 stmts.children.append(self.indent(2))
119 stmts.children.append(Leaf(token.STRING,"return m"))
120 stmts.children.append(self.nl())
121 return stmts
122
123 def module_1(self,p):
124 params = p[7]
125 ports = p[8]
126 clsname = [Leaf(token.NAME, 'class'),
127 Leaf(token.NAME, p[4], prefix=' '),
128 Leaf(token.LPAR,'('),
129 Leaf(token.NAME, 'Elaboratable'),
130 Leaf(token.LPAR,')'),
131 Leaf(token.COLON, ':'),
132 self.nl(),
133 ]
134
135 suite = Node(syms.suite, [Leaf(token.NEWLINE, '\n'),
136 self.indent(1),
137 self.initFunc(ports,params),
138 self.indent(1),
139 self.elaborateFunc()
140
141 ])
142 clsdecl = Node(syms.classdef, clsname + [suite])
143 clsdecl = Node(syms.compound_stmt, [clsdecl])
144
145 self.printpy(str(clsdecl))
146 print("=====================")
147 print(str(clsdecl))
148 return clsdecl
149
150 def appendComments(self,data):
151 self.outputfile.write(data)
152 #lines = data.split("\n")
153 #for line in lines:
154 # self.printpy("#"+line)
155
156 # combinatorical assign
157 def cont_assign_1(self,p):
158 # print("#ASSIGN:BROKEN"+str(list(p)))
159 self.assign += [Assignment(p[1],p[2],p[3])]