1 from functools
import partial
2 from operator
import itemgetter
5 from litex
.gen
.fhdl
.structure
import *
6 from litex
.gen
.fhdl
.structure
import _Operator
, _Slice
, _Assign
, _Fragment
7 from litex
.gen
.fhdl
.tools
import *
8 from litex
.gen
.fhdl
.namer
import build_namespace
9 from litex
.gen
.fhdl
.conv_output
import ConvOutput
12 _reserved_keywords
= {
13 "always", "and", "assign", "automatic", "begin", "buf", "bufif0", "bufif1",
14 "case", "casex", "casez", "cell", "cmos", "config", "deassign", "default",
15 "defparam", "design", "disable", "edge", "else", "end", "endcase",
16 "endconfig", "endfunction", "endgenerate", "endmodule", "endprimitive",
17 "endspecify", "endtable", "endtask", "event", "for", "force", "forever",
18 "fork", "function", "generate", "genvar", "highz0", "highz1", "if",
19 "ifnone", "incdir", "include", "initial", "inout", "input",
20 "instance", "integer", "join", "large", "liblist", "library", "localparam",
21 "macromodule", "medium", "module", "nand", "negedge", "nmos", "nor",
22 "noshowcancelled", "not", "notif0", "notif1", "or", "output", "parameter",
23 "pmos", "posedge", "primitive", "pull0", "pull1" "pulldown",
24 "pullup", "pulsestyle_onevent", "pulsestyle_ondetect", "remos", "real",
25 "realtime", "reg", "release", "repeat", "rnmos", "rpmos", "rtran",
26 "rtranif0", "rtranif1", "scalared", "showcancelled", "signed", "small",
27 "specify", "specparam", "strong0", "strong1", "supply0", "supply1",
28 "table", "task", "time", "tran", "tranif0", "tranif1", "tri", "tri0",
29 "tri1", "triand", "trior", "trireg", "unsigned", "use", "vectored", "wait",
30 "wand", "weak0", "weak1", "while", "wire", "wor","xnor", "xor"
40 n
+= "[" + str(len(s
)-1) + ":0] "
45 def _printconstant(node
):
47 return (str(node
.nbits
) + "'sd" + str(2**node
.nbits
+ node
.value
),
50 return str(node
.nbits
) + "'d" + str(node
.value
), False
53 def _printexpr(ns
, node
):
54 if isinstance(node
, Constant
):
55 return _printconstant(node
)
56 elif isinstance(node
, Signal
):
57 return ns
.get_name(node
), node
.signed
58 elif isinstance(node
, _Operator
):
59 arity
= len(node
.operands
)
60 r1
, s1
= _printexpr(ns
, node
.operands
[0])
66 r
= "-$signed({1'd0, " + r1
+ "})"
72 r2
, s2
= _printexpr(ns
, node
.operands
[1])
73 if node
.op
not in ["<<<", ">>>"]:
75 r1
= "$signed({1'd0, " + r1
+ "})"
77 r2
= "$signed({1'd0, " + r2
+ "})"
78 r
= r1
+ " " + node
.op
+ " " + r2
82 r2
, s2
= _printexpr(ns
, node
.operands
[1])
83 r3
, s3
= _printexpr(ns
, node
.operands
[2])
85 r3
= "$signed({1'd0, " + r3
+ "})"
87 r2
= "$signed({1'd0, " + r2
+ "})"
88 r
= r1
+ " ? " + r2
+ " : " + r3
92 return "(" + r
+ ")", s
93 elif isinstance(node
, _Slice
):
94 # Verilog does not like us slicing non-array signals...
95 if isinstance(node
.value
, Signal
) \
96 and len(node
.value
) == 1 \
97 and node
.start
== 0 and node
.stop
== 1:
98 return _printexpr(ns
, node
.value
)
100 if node
.start
+ 1 == node
.stop
:
101 sr
= "[" + str(node
.start
) + "]"
103 sr
= "[" + str(node
.stop
-1) + ":" + str(node
.start
) + "]"
104 r
, s
= _printexpr(ns
, node
.value
)
106 elif isinstance(node
, Cat
):
107 l
= [_printexpr(ns
, v
)[0] for v
in reversed(node
.l
)]
108 return "{" + ", ".join(l
) + "}", False
109 elif isinstance(node
, Replicate
):
110 return "{" + str(node
.n
) + "{" + _printexpr(ns
, node
.v
)[0] + "}}", False
112 raise TypeError("Expression of unrecognized type: '{}'".format(type(node
).__name
__))
115 (_AT_BLOCKING
, _AT_NONBLOCKING
, _AT_SIGNAL
) = range(3)
118 def _printnode(ns
, at
, level
, node
):
121 elif isinstance(node
, _Assign
):
122 if at
== _AT_BLOCKING
:
124 elif at
== _AT_NONBLOCKING
:
126 elif is_variable(node
.l
):
130 return "\t"*level
+ _printexpr(ns
, node
.l
)[0] + assignment
+ _printexpr(ns
, node
.r
)[0] + ";\n"
131 elif isinstance(node
, collections
.Iterable
):
132 return "".join(list(map(partial(_printnode
, ns
, at
, level
), node
)))
133 elif isinstance(node
, If
):
134 r
= "\t"*level
+ "if (" + _printexpr(ns
, node
.cond
)[0] + ") begin\n"
135 r
+= _printnode(ns
, at
, level
+ 1, node
.t
)
137 r
+= "\t"*level
+ "end else begin\n"
138 r
+= _printnode(ns
, at
, level
+ 1, node
.f
)
139 r
+= "\t"*level
+ "end\n"
141 elif isinstance(node
, Case
):
143 r
= "\t"*level
+ "case (" + _printexpr(ns
, node
.test
)[0] + ")\n"
144 css
= [(k
, v
) for k
, v
in node
.cases
.items() if isinstance(k
, Constant
)]
145 css
= sorted(css
, key
=lambda x
: x
[0].value
)
146 for choice
, statements
in css
:
147 r
+= "\t"*(level
+ 1) + _printexpr(ns
, choice
)[0] + ": begin\n"
148 r
+= _printnode(ns
, at
, level
+ 2, statements
)
149 r
+= "\t"*(level
+ 1) + "end\n"
150 if "default" in node
.cases
:
151 r
+= "\t"*(level
+ 1) + "default: begin\n"
152 r
+= _printnode(ns
, at
, level
+ 2, node
.cases
["default"])
153 r
+= "\t"*(level
+ 1) + "end\n"
154 r
+= "\t"*level
+ "endcase\n"
159 raise TypeError("Node of unrecognized type: "+str(type(node
)))
162 def _list_comb_wires(f
):
164 groups
= group_by_targets(f
.comb
)
166 if len(g
[1]) == 1 and isinstance(g
[1][0], _Assign
):
171 def _printheader(f
, ios
, name
, ns
,
173 sigs
= list_signals(f
) |
list_special_ios(f
, True, True, True)
174 special_outs
= list_special_ios(f
, False, True, True)
175 inouts
= list_special_ios(f
, False, False, True)
176 targets
= list_targets(f
) | special_outs
177 wires
= _list_comb_wires(f
) | special_outs
178 r
= "module " + name
+ "(\n"
180 for sig
in sorted(ios
, key
=lambda x
: x
.duid
):
185 r
+= "\tinout " + _printsig(ns
, sig
)
188 r
+= "\toutput " + _printsig(ns
, sig
)
190 r
+= "\toutput reg " + _printsig(ns
, sig
)
192 r
+= "\tinput " + _printsig(ns
, sig
)
194 for sig
in sorted(sigs
- ios
, key
=lambda x
: x
.duid
):
196 r
+= "wire " + _printsig(ns
, sig
) + ";\n"
198 if reg_initialization
:
199 r
+= "reg " + _printsig(ns
, sig
) + " = " + _printexpr(ns
, sig
.reset
)[0] + ";\n"
201 r
+= "reg " + _printsig(ns
, sig
) + ";\n"
206 def _printcomb(f
, ns
,
213 # Generate a dummy event to get the simulator
214 # to run the combinatorial process once at the beginning.
215 syn_off
= "// synthesis translate_off\n"
216 syn_on
= "// synthesis translate_on\n"
217 dummy_s
= Signal(name_override
="dummy_s")
219 r
+= "reg " + _printsig(ns
, dummy_s
) + ";\n"
220 r
+= "initial " + ns
.get_name(dummy_s
) + " <= 1'd0;\n"
223 groups
= group_by_targets(f
.comb
)
225 for n
, g
in enumerate(groups
):
226 if len(g
[1]) == 1 and isinstance(g
[1][0], _Assign
):
227 r
+= "assign " + _printnode(ns
, _AT_BLOCKING
, 0, g
[1][0])
230 dummy_d
= Signal(name_override
="dummy_d")
232 r
+= "reg " + _printsig(ns
, dummy_d
) + ";\n"
235 r
+= "always @(*) begin\n"
237 r
+= "\t$display(\"Running comb block #" + str(n
) + "\");\n"
240 r
+= "\t" + ns
.get_name(t
) + " = " + _printexpr(ns
, t
.reset
)[0] + ";\n"
241 r
+= _printnode(ns
, _AT_BLOCKING
, 1, g
[1])
244 r
+= "\t" + ns
.get_name(t
) + " <= " + _printexpr(ns
, t
.reset
)[0] + ";\n"
245 r
+= _printnode(ns
, _AT_NONBLOCKING
, 1, g
[1])
248 r
+= "\t" + ns
.get_name(dummy_d
) + " <= " + ns
.get_name(dummy_s
) + ";\n"
255 def _printsync(f
, ns
):
257 for k
, v
in sorted(f
.sync
.items(), key
=itemgetter(0)):
258 r
+= "always @(posedge " + ns
.get_name(f
.clock_domains
[k
].clk
) + ") begin\n"
259 r
+= _printnode(ns
, _AT_SIGNAL
, 1, v
)
264 def _printspecials(overrides
, specials
, ns
, add_data_file
):
266 for special
in sorted(specials
, key
=lambda x
: x
.duid
):
267 pr
= call_special_classmethod(overrides
, special
, "emit_verilog", ns
, add_data_file
)
269 raise NotImplementedError("Special " + str(special
) + " failed to implement emit_verilog")
274 def convert(f
, ios
=None, name
="top",
275 special_overrides
=dict(),
276 create_clock_domains
=True,
278 reg_initialization
=True,
280 blocking_assign
=False,
283 if not isinstance(f
, _Fragment
):
288 for cd_name
in sorted(list_clock_domains(f
)):
290 f
.clock_domains
[cd_name
]
292 if create_clock_domains
:
293 cd
= ClockDomain(cd_name
)
294 f
.clock_domains
.append(cd
)
295 ios |
= {cd
.clk
, cd
.rst
}
297 raise KeyError("Unresolved clock domain: '"+cd_name
+"'")
299 f
= lower_complex_slices(f
)
302 fs
, lowered_specials
= lower_specials(special_overrides
, f
.specials
)
303 f
+= lower_basics(fs
)
305 for io
in sorted(ios
, key
=lambda x
: x
.duid
):
306 if io
.name_override
is None:
307 io_name
= io
.backtrace
[-1][0]
309 io
.name_override
= io_name
310 ns
= build_namespace(list_signals(f
) \
311 |
list_special_ios(f
, True, True, True) \
312 | ios
, _reserved_keywords
)
313 ns
.clock_domains
= f
.clock_domains
316 src
= "/* Machine-generated using LiteX gen */\n"
317 src
+= _printheader(f
, ios
, name
, ns
,
318 reg_initialization
=reg_initialization
)
319 src
+= _printcomb(f
, ns
,
320 display_run
=display_run
,
321 dummy_signal
=dummy_signal
,
322 blocking_assign
=blocking_assign
)
323 src
+= _printsync(f
, ns
)
324 src
+= _printspecials(special_overrides
, f
.specials
- lowered_specials
, ns
, r
.add_data_file
)
326 r
.set_main_source(src
)