bd3e1bf5050f84caf9839fb7715a2b1ab64c95ac
1 from operator
import itemgetter
3 from migen
.fhdl
.structure
import *
4 from migen
.fhdl
.structure
import _Value
5 from migen
.fhdl
.bitcontainer
import bits_for
, value_bits_sign
6 from migen
.fhdl
.tools
import *
7 from migen
.fhdl
.tracer
import get_obj_var_name
8 from migen
.fhdl
.verilog
import _printexpr
as verilog_printexpr
11 __all__
= ["TSTriple", "Instance", "Memory",
12 "READ_FIRST", "WRITE_FIRST", "NO_CHANGE"]
16 def iter_expressions(self
):
20 def rename_clock_domain(self
, old
, new
):
21 for obj
, attr
, direction
in self
.iter_expressions():
22 rename_clock_domain_expr(getattr(obj
, attr
), old
, new
)
24 def list_clock_domains(self
):
26 for obj
, attr
, direction
in self
.iter_expressions():
27 r |
= list_clock_domains_expr(getattr(obj
, attr
))
30 def list_ios(self
, ins
, outs
, inouts
):
32 for obj
, attr
, direction
in self
.iter_expressions():
33 if (direction
== SPECIAL_INPUT
and ins
) \
34 or (direction
== SPECIAL_OUTPUT
and outs
) \
35 or (direction
== SPECIAL_INOUT
and inouts
):
36 signals
= list_signals(getattr(obj
, attr
))
41 class Tristate(Special
):
42 def __init__(self
, target
, o
, oe
, i
=None):
43 Special
.__init
__(self
)
44 self
.target
= wrap(target
)
47 self
.i
= wrap(i
) if i
is not None else None
49 def iter_expressions(self
):
50 for attr
, target_context
in [
51 ("target", SPECIAL_INOUT
),
53 ("oe", SPECIAL_INPUT
),
54 ("i", SPECIAL_OUTPUT
)]:
55 if getattr(self
, attr
) is not None:
56 yield self
, attr
, target_context
59 def emit_verilog(tristate
, ns
, add_data_file
):
61 return verilog_printexpr(ns
, e
)[0]
62 w
, s
= value_bits_sign(tristate
.target
)
63 r
= "assign " + pe(tristate
.target
) + " = " \
64 + pe(tristate
.oe
) + " ? " + pe(tristate
.o
) \
65 + " : " + str(w
) + "'bz;\n"
66 if tristate
.i
is not None:
67 r
+= "assign " + pe(tristate
.i
) + " = " + pe(tristate
.target
) + ";\n"
73 def __init__(self
, bits_sign
=None, min=None, max=None, reset_o
=0, reset_oe
=0):
74 self
.o
= Signal(bits_sign
, min=min, max=max, reset
=reset_o
)
75 self
.oe
= Signal(reset
=reset_oe
)
76 self
.i
= Signal(bits_sign
, min=min, max=max)
78 def get_tristate(self
, target
):
79 return Tristate(target
, self
.o
, self
.oe
, self
.i
)
82 class Instance(Special
):
84 def __init__(self
, name
, expr
=None):
88 self
.expr
= wrap(expr
)
96 def __init__(self
, name
, value
):
98 if isinstance(value
, (int, bool)):
99 value
= Constant(value
)
101 class PreformattedParam(str):
104 def __init__(self
, of
, *items
, name
="", synthesis_directive
=None, **kwargs
):
105 Special
.__init
__(self
)
108 self
.name_override
= name
110 self
.name_override
= of
111 self
.items
= list(items
)
112 self
.synthesis_directive
= synthesis_directive
113 for k
, v
in sorted(kwargs
.items(), key
=itemgetter(0)):
114 item_type
, item_name
= k
.split("_", maxsplit
=1)
117 "o": Instance
.Output
,
118 "io": Instance
.InOut
,
119 "p": Instance
.Parameter
121 self
.items
.append(item_class(item_name
, v
))
123 def get_io(self
, name
):
124 for item
in self
.items
:
125 if isinstance(item
, Instance
._IO
) and item
.name
== name
:
128 def iter_expressions(self
):
129 for item
in self
.items
:
130 if isinstance(item
, Instance
.Input
):
131 yield item
, "expr", SPECIAL_INPUT
132 elif isinstance(item
, Instance
.Output
):
133 yield item
, "expr", SPECIAL_OUTPUT
134 elif isinstance(item
, Instance
.InOut
):
135 yield item
, "expr", SPECIAL_INOUT
138 def emit_verilog(instance
, ns
, add_data_file
):
139 r
= instance
.of
+ " "
140 parameters
= list(filter(lambda i
: isinstance(i
, Instance
.Parameter
), instance
.items
))
148 r
+= "\t." + p
.name
+ "("
149 if isinstance(p
.value
, Constant
):
150 r
+= verilog_printexpr(ns
, p
.value
)[0]
151 elif isinstance(p
.value
, float):
153 elif isinstance(p
.value
, Instance
.PreformattedParam
):
155 elif isinstance(p
.value
, str):
156 r
+= "\"" + p
.value
+ "\""
161 r
+= ns
.get_name(instance
)
162 if parameters
: r
+= " "
165 for p
in instance
.items
:
166 if isinstance(p
, Instance
._IO
):
168 name_design
= verilog_printexpr(ns
, p
.expr
)[0]
172 r
+= "\t." + name_inst
+ "(" + name_design
+ ")"
175 if instance
.synthesis_directive
is not None:
176 synthesis_directive
= "/* synthesis {} */".format(instance
.synthesis_directive
)
177 r
+= ")" + synthesis_directive
+ ";\n\n"
183 (READ_FIRST
, WRITE_FIRST
, NO_CHANGE
) = range(3)
186 class _MemoryPort(Special
):
187 def __init__(self
, adr
, dat_r
, we
=None, dat_w
=None,
188 async_read
=False, re
=None, we_granularity
=0, mode
=WRITE_FIRST
,
190 Special
.__init
__(self
)
195 self
.async_read
= async_read
197 self
.we_granularity
= we_granularity
199 self
.clock
= ClockSignal(clock_domain
)
201 def iter_expressions(self
):
202 for attr
, target_context
in [
203 ("adr", SPECIAL_INPUT
),
204 ("we", SPECIAL_INPUT
),
205 ("dat_w", SPECIAL_INPUT
),
206 ("re", SPECIAL_INPUT
),
207 ("dat_r", SPECIAL_OUTPUT
),
208 ("clock", SPECIAL_INPUT
)]:
209 yield self
, attr
, target_context
212 def emit_verilog(port
, ns
, add_data_file
):
213 return "" # done by parent Memory object
216 class _MemoryLocation(_Value
):
217 def __init__(self
, memory
, index
):
218 _Value
.__init
__(self
)
220 self
.index
= wrap(index
)
223 class Memory(Special
):
224 def __init__(self
, width
, depth
, init
=None, name
=None):
225 Special
.__init
__(self
)
230 self
.name_override
= get_obj_var_name(name
, "mem")
232 def __getitem__(self
, index
):
234 return _MemoryLocation(self
, index
)
236 def get_port(self
, write_capable
=False, async_read
=False,
237 has_re
=False, we_granularity
=0, mode
=WRITE_FIRST
,
239 if we_granularity
>= self
.width
:
241 adr
= Signal(max=self
.depth
)
242 dat_r
= Signal(self
.width
)
245 we
= Signal(self
.width
//we_granularity
)
248 dat_w
= Signal(self
.width
)
256 mp
= _MemoryPort(adr
, dat_r
, we
, dat_w
,
257 async_read
, re
, we_granularity
, mode
,
259 self
.ports
.append(mp
)
263 def emit_verilog(memory
, ns
, add_data_file
):
266 if isinstance(e
, Memory
):
267 return ns
.get_name(e
)
269 return verilog_printexpr(ns
, e
)[0]
270 adrbits
= bits_for(memory
.depth
-1)
272 r
+= "reg [" + str(memory
.width
-1) + ":0] " \
274 + "[0:" + str(memory
.depth
-1) + "];\n"
278 for port
in memory
.ports
:
279 if not port
.async_read
:
280 if port
.mode
== WRITE_FIRST
and port
.we
is not None:
281 adr_reg
= Signal(name_override
="memadr")
282 r
+= "reg [" + str(adrbits
-1) + ":0] " \
283 + gn(adr_reg
) + ";\n"
284 adr_regs
[id(port
)] = adr_reg
286 data_reg
= Signal(name_override
="memdat")
287 r
+= "reg [" + str(memory
.width
-1) + ":0] " \
288 + gn(data_reg
) + ";\n"
289 data_regs
[id(port
)] = data_reg
291 for port
in memory
.ports
:
292 r
+= "always @(posedge " + gn(port
.clock
) + ") begin\n"
293 if port
.we
is not None:
294 if port
.we_granularity
:
295 n
= memory
.width
//port
.we_granularity
297 m
= i
*port
.we_granularity
298 M
= (i
+1)*port
.we_granularity
-1
299 sl
= "[" + str(M
) + ":" + str(m
) + "]"
300 r
+= "\tif (" + gn(port
.we
) + "[" + str(i
) + "])\n"
301 r
+= "\t\t" + gn(memory
) + "[" + gn(port
.adr
) + "]" + sl
+ " <= " + gn(port
.dat_w
) + sl
+ ";\n"
303 r
+= "\tif (" + gn(port
.we
) + ")\n"
304 r
+= "\t\t" + gn(memory
) + "[" + gn(port
.adr
) + "] <= " + gn(port
.dat_w
) + ";\n"
305 if not port
.async_read
:
306 if port
.mode
== WRITE_FIRST
and port
.we
is not None:
307 rd
= "\t" + gn(adr_regs
[id(port
)]) + " <= " + gn(port
.adr
) + ";\n"
309 bassign
= gn(data_regs
[id(port
)]) + " <= " + gn(memory
) + "[" + gn(port
.adr
) + "];\n"
310 if port
.mode
== READ_FIRST
or port
.we
is None:
312 elif port
.mode
== NO_CHANGE
:
313 rd
= "\tif (!" + gn(port
.we
) + ")\n" \
318 r
+= "\tif (" + gn(port
.re
) + ")\n"
319 r
+= "\t" + rd
.replace("\n\t", "\n\t\t")
322 for port
in memory
.ports
:
324 r
+= "assign " + gn(port
.dat_r
) + " = " + gn(memory
) + "[" + gn(port
.adr
) + "];\n"
326 if port
.mode
== WRITE_FIRST
and port
.we
is not None:
327 r
+= "assign " + gn(port
.dat_r
) + " = " + gn(memory
) + "[" + gn(adr_regs
[id(port
)]) + "];\n"
329 r
+= "assign " + gn(port
.dat_r
) + " = " + gn(data_regs
[id(port
)]) + ";\n"
332 if memory
.init
is not None:
334 for d
in memory
.init
:
335 content
+= "{:x}\n".format(d
)
336 memory_filename
= add_data_file(gn(memory
) + ".init", content
)
338 r
+= "initial begin\n"
339 r
+= "\t$readmemh(\"" + memory_filename
+ "\", " + gn(memory
) + ");\n"
345 class SynthesisDirective(Special
):
346 def __init__(self
, template
, **signals
):
347 Special
.__init
__(self
)
348 self
.template
= template
349 self
.signals
= signals
352 def emit_verilog(directive
, ns
, add_data_file
):
353 name_dict
= dict((k
, ns
.get_name(sig
)) for k
, sig
in directive
.signals
.items())
354 formatted
= directive
.template
.format(**name_dict
)
355 return "// synthesis " + formatted
+ "\n"
358 class Keep(SynthesisDirective
):
359 def __init__(self
, signal
):
360 SynthesisDirective
.__init
__(self
, "attribute keep of {s} is true", s
=signal
)