3 from collections
import defaultdict
, OrderedDict
4 from contextlib
import contextmanager
6 from ..tools
import bits_for
7 from ..hdl
import ast
, ir
, mem
, xfrm
16 def _make_name(self
, name
, local
):
19 name
= "${}".format(self
._index
)
20 elif not local
and name
[0] not in "\\$":
21 name
= "\\{}".format(name
)
22 while name
in self
._names
:
24 name
= "{}${}".format(name
, self
._index
)
30 _escape_map
= str.maketrans({
39 self
._buffer
= io
.StringIO()
42 return self
._buffer
.getvalue()
44 def _append(self
, fmt
, *args
, **kwargs
):
45 self
._buffer
.write(fmt
.format(*args
, **kwargs
))
47 def attribute(self
, name
, value
, indent
=0):
48 if isinstance(value
, str):
49 self
._append
("{}attribute \\{} \"{}\"\n",
50 " " * indent
, name
, value
.translate(self
._escape
_map
))
52 self
._append
("{}attribute \\{} {}\n",
53 " " * indent
, name
, int(value
))
57 self
.attribute("src", src
)
60 class _Builder(_Namer
, _Bufferer
):
61 def module(self
, name
=None, attrs
={}):
62 name
= self
._make
_name
(name
, local
=False)
63 return _ModuleBuilder(self
, name
, attrs
)
66 class _ModuleBuilder(_Namer
, _Bufferer
):
67 def __init__(self
, rtlil
, name
, attrs
):
71 self
.attrs
= {"generator": "nMigen"}
72 self
.attrs
.update(attrs
)
75 for name
, value
in self
.attrs
.items():
76 self
.attribute(name
, value
, indent
=0)
77 self
._append
("module {}\n", self
.name
)
80 def __exit__(self
, *args
):
82 self
.rtlil
._buffer
.write(str(self
))
84 def attribute(self
, name
, value
, indent
=1):
85 super().attribute(name
, value
, indent
)
87 def wire(self
, width
, port_id
=None, port_kind
=None, name
=None, src
=""):
89 name
= self
._make
_name
(name
, local
=False)
91 self
._append
(" wire width {} {}\n", width
, name
)
93 assert port_kind
in ("input", "output", "inout")
94 self
._append
(" wire width {} {} {} {}\n", width
, port_kind
, port_id
, name
)
97 def connect(self
, lhs
, rhs
):
98 self
._append
(" connect {} {}\n", lhs
, rhs
)
100 def memory(self
, width
, size
, name
=None, src
=""):
102 name
= self
._make
_name
(name
, local
=False)
103 self
._append
(" memory width {} size {} {}\n", width
, size
, name
)
106 def cell(self
, kind
, name
=None, params
={}, ports
={}, src
=""):
108 name
= self
._make
_name
(name
, local
=False)
109 self
._append
(" cell {} {}\n", kind
, name
)
110 for param
, value
in params
.items():
111 if isinstance(value
, str):
112 self
._append
(" parameter \\{} \"{}\"\n",
113 param
, value
.translate(self
._escape
_map
))
115 self
._append
(" parameter \\{} {:d}\n",
117 for port
, wire
in ports
.items():
118 self
._append
(" connect {} {}\n", port
, wire
)
119 self
._append
(" end\n")
122 def process(self
, name
=None, src
=""):
123 name
= self
._make
_name
(name
, local
=True)
124 return _ProcessBuilder(self
, name
, src
)
127 class _ProcessBuilder(_Bufferer
):
128 def __init__(self
, rtlil
, name
, src
):
136 self
._append
(" process {}\n", self
.name
)
139 def __exit__(self
, *args
):
140 self
._append
(" end\n")
141 self
.rtlil
._buffer
.write(str(self
))
144 return _CaseBuilder(self
, indent
=2)
146 def sync(self
, kind
, cond
=None):
147 return _SyncBuilder(self
, kind
, cond
)
151 def __init__(self
, rtlil
, indent
):
158 def __exit__(self
, *args
):
161 def assign(self
, lhs
, rhs
):
162 self
.rtlil
._append
("{}assign {} {}\n", " " * self
.indent
, lhs
, rhs
)
164 def switch(self
, cond
):
165 return _SwitchBuilder(self
.rtlil
, cond
, self
.indent
)
168 class _SwitchBuilder
:
169 def __init__(self
, rtlil
, cond
, indent
):
175 self
.rtlil
._append
("{}switch {}\n", " " * self
.indent
, self
.cond
)
178 def __exit__(self
, *args
):
179 self
.rtlil
._append
("{}end\n", " " * self
.indent
)
181 def case(self
, value
=None):
183 self
.rtlil
._append
("{}case\n", " " * (self
.indent
+ 1))
185 self
.rtlil
._append
("{}case {}'{}\n", " " * (self
.indent
+ 1),
187 return _CaseBuilder(self
.rtlil
, self
.indent
+ 2)
191 def __init__(self
, rtlil
, kind
, cond
):
197 if self
.cond
is None:
198 self
.rtlil
._append
(" sync {}\n", self
.kind
)
200 self
.rtlil
._append
(" sync {} {}\n", self
.kind
, self
.cond
)
203 def __exit__(self
, *args
):
206 def update(self
, lhs
, rhs
):
207 self
.rtlil
._append
(" update {} {}\n", lhs
, rhs
)
212 return "{}:{}".format(file, line
)
215 class LegalizeValue(Exception):
216 def __init__(self
, value
, branches
):
218 self
.branches
= list(branches
)
221 class _ValueCompilerState
:
222 def __init__(self
, rtlil
):
224 self
.wires
= ast
.SignalDict()
225 self
.driven
= ast
.SignalDict()
226 self
.ports
= ast
.SignalDict()
228 self
.expansions
= ast
.ValueDict()
230 def add_driven(self
, signal
, sync
):
231 self
.driven
[signal
] = sync
233 def add_port(self
, signal
, kind
):
234 assert kind
in ("i", "o", "io")
241 self
.ports
[signal
] = (len(self
.ports
), kind
)
243 def resolve(self
, signal
, prefix
=None):
244 if signal
in self
.wires
:
245 return self
.wires
[signal
]
247 if signal
in self
.ports
:
248 port_id
, port_kind
= self
.ports
[signal
]
250 port_id
= port_kind
= None
251 if prefix
is not None:
252 wire_name
= "{}_{}".format(prefix
, signal
.name
)
254 wire_name
= signal
.name
256 for attr_name
, attr_signal
in signal
.attrs
.items():
257 self
.rtlil
.attribute(attr_name
, attr_signal
)
258 wire_curr
= self
.rtlil
.wire(width
=signal
.nbits
, name
=wire_name
,
259 port_id
=port_id
, port_kind
=port_kind
,
260 src
=src(signal
.src_loc
))
261 if signal
in self
.driven
:
262 wire_next
= self
.rtlil
.wire(width
=signal
.nbits
, name
=wire_curr
+ "$next",
263 src
=src(signal
.src_loc
))
266 self
.wires
[signal
] = (wire_curr
, wire_next
)
268 return wire_curr
, wire_next
270 def resolve_curr(self
, signal
, prefix
=None):
271 wire_curr
, wire_next
= self
.resolve(signal
, prefix
)
274 def expand(self
, value
):
275 if not self
.expansions
:
277 return self
.expansions
.get(value
, value
)
280 def expand_to(self
, value
, expansion
):
282 assert value
not in self
.expansions
283 self
.expansions
[value
] = expansion
286 del self
.expansions
[value
]
289 class _ValueCompiler(xfrm
.AbstractValueTransformer
):
290 def __init__(self
, state
):
293 def on_value(self
, value
):
294 return super().on_value(self
.s
.expand(value
))
296 def on_unknown(self
, value
):
300 super().on_unknown(value
)
302 def on_ClockSignal(self
, value
):
303 raise NotImplementedError # :nocov:
305 def on_ResetSignal(self
, value
):
306 raise NotImplementedError # :nocov:
308 def on_Cat(self
, value
):
309 return "{{ {} }}".format(" ".join(reversed([self(o
) for o
in value
.parts
])))
311 def _prepare_value_for_Slice(self
, value
):
312 raise NotImplementedError # :nocov:
314 def on_Slice(self
, value
):
315 if value
.start
== 0 and value
.end
== len(value
.value
):
316 return self(value
.value
)
318 sigspec
= self
._prepare
_value
_for
_Slice
(value
.value
)
319 if value
.start
+ 1 == value
.end
:
320 return "{} [{}]".format(sigspec
, value
.start
)
322 return "{} [{}:{}]".format(sigspec
, value
.end
- 1, value
.start
)
324 def on_ArrayProxy(self
, value
):
325 index
= self
.s
.expand(value
.index
)
326 if isinstance(index
, ast
.Const
):
327 if index
.value
< len(value
.elems
):
328 return self(value
.elems
[index
.value
])
330 return self(value
.elems
[-1])
332 raise LegalizeValue(value
.index
, range(len(value
.elems
)))
335 class _RHSValueCompiler(_ValueCompiler
):
339 (1, "b"): "$reduce_bool",
360 def on_Const(self
, value
):
361 if isinstance(value
.value
, str):
362 return "{}'{}".format(value
.nbits
, value
.value
)
364 return "{}'{:0{}b}".format(value
.nbits
, value
.value
, value
.nbits
)
366 def on_Signal(self
, value
):
367 wire_curr
, wire_next
= self
.s
.resolve(value
)
370 def on_Operator_unary(self
, value
):
371 arg
, = value
.operands
372 arg_bits
, arg_sign
= arg
.shape()
373 res_bits
, res_sign
= value
.shape()
374 res
= self
.s
.rtlil
.wire(width
=res_bits
)
375 self
.s
.rtlil
.cell(self
.operator_map
[(1, value
.op
)], ports
={
379 "A_SIGNED": arg_sign
,
382 }, src
=src(value
.src_loc
))
385 def match_shape(self
, value
, new_bits
, new_sign
):
386 if isinstance(value
, ast
.Const
):
387 return self(ast
.Const(value
.value
, (new_bits
, new_sign
)))
389 value_bits
, value_sign
= value
.shape()
390 if new_bits
<= value_bits
:
391 return self(ast
.Slice(value
, 0, new_bits
))
393 res
= self
.s
.rtlil
.wire(width
=new_bits
)
394 self
.s
.rtlil
.cell("$pos", ports
={
398 "A_SIGNED": value_sign
,
399 "A_WIDTH": value_bits
,
401 }, src
=src(value
.src_loc
))
404 def on_Operator_binary(self
, value
):
405 lhs
, rhs
= value
.operands
406 lhs_bits
, lhs_sign
= lhs
.shape()
407 rhs_bits
, rhs_sign
= rhs
.shape()
408 if lhs_sign
== rhs_sign
:
412 lhs_sign
= rhs_sign
= True
413 lhs_bits
= rhs_bits
= max(lhs_bits
, rhs_bits
)
414 lhs_wire
= self
.match_shape(lhs
, lhs_bits
, lhs_sign
)
415 rhs_wire
= self
.match_shape(rhs
, rhs_bits
, rhs_sign
)
416 res_bits
, res_sign
= value
.shape()
417 res
= self
.s
.rtlil
.wire(width
=res_bits
)
418 self
.s
.rtlil
.cell(self
.operator_map
[(2, value
.op
)], ports
={
423 "A_SIGNED": lhs_sign
,
425 "B_SIGNED": rhs_sign
,
428 }, src
=src(value
.src_loc
))
431 def on_Operator_mux(self
, value
):
432 sel
, lhs
, rhs
= value
.operands
433 lhs_bits
, lhs_sign
= lhs
.shape()
434 rhs_bits
, rhs_sign
= rhs
.shape()
435 res_bits
, res_sign
= value
.shape()
436 lhs_bits
= rhs_bits
= res_bits
= max(lhs_bits
, rhs_bits
, res_bits
)
437 lhs_wire
= self
.match_shape(lhs
, lhs_bits
, lhs_sign
)
438 rhs_wire
= self
.match_shape(rhs
, rhs_bits
, rhs_sign
)
439 res
= self
.s
.rtlil
.wire(width
=res_bits
)
440 self
.s
.rtlil
.cell("$mux", ports
={
447 }, src
=src(value
.src_loc
))
450 def on_Operator(self
, value
):
451 if len(value
.operands
) == 1:
452 return self
.on_Operator_unary(value
)
453 elif len(value
.operands
) == 2:
454 return self
.on_Operator_binary(value
)
455 elif len(value
.operands
) == 3:
456 assert value
.op
== "m"
457 return self
.on_Operator_mux(value
)
459 raise TypeError # :nocov:
461 def _prepare_value_for_Slice(self
, value
):
462 if isinstance(value
, (ast
.Signal
, ast
.Slice
, ast
.Cat
)):
463 sigspec
= self(value
)
465 sigspec
= self
.s
.rtlil
.wire(len(value
))
466 self
.s
.rtlil
.connect(sigspec
, self(value
))
469 def on_Part(self
, value
):
470 lhs
, rhs
= value
.value
, value
.offset
471 lhs_bits
, lhs_sign
= lhs
.shape()
472 rhs_bits
, rhs_sign
= rhs
.shape()
473 res_bits
, res_sign
= value
.shape()
474 res
= self
.s
.rtlil
.wire(width
=res_bits
)
475 # Note: Verilog's x[o+:w] construct produces a $shiftx cell, not a $shift cell.
476 # However, Migen's semantics defines the out-of-range bits to be zero, so it is correct
477 # to use a $shift cell here instead, even though it produces less idiomatic Verilog.
478 self
.s
.rtlil
.cell("$shift", ports
={
483 "A_SIGNED": lhs_sign
,
485 "B_SIGNED": rhs_sign
,
488 }, src
=src(value
.src_loc
))
491 def on_Repl(self
, value
):
492 return "{{ {} }}".format(" ".join(self(value
.value
) for _
in range(value
.count
)))
495 class _LHSValueCompiler(_ValueCompiler
):
496 def on_Const(self
, value
):
497 raise TypeError # :nocov:
499 def on_Operator(self
, value
):
500 raise TypeError # :nocov:
502 def on_Signal(self
, value
):
503 wire_curr
, wire_next
= self
.s
.resolve(value
)
504 if wire_next
is None:
505 raise ValueError("No LHS wire for non-driven signal {}".format(repr(value
)))
508 def _prepare_value_for_Slice(self
, value
):
509 assert isinstance(value
, (ast
.Signal
, ast
.Slice
, ast
.Cat
))
512 def on_Part(self
, value
):
513 offset
= self
.s
.expand(value
.offset
)
514 if isinstance(offset
, ast
.Const
):
515 return self(ast
.Slice(value
.value
, offset
.value
, offset
.value
+ value
.width
))
517 raise LegalizeValue(value
.offset
, range((1 << len(value
.offset
)) - 1))
519 def on_Repl(self
, value
):
520 raise TypeError # :nocov:
523 class _StatementCompiler(xfrm
.AbstractStatementTransformer
):
524 def __init__(self
, state
, rhs_compiler
, lhs_compiler
):
526 self
.rhs_compiler
= rhs_compiler
527 self
.lhs_compiler
= lhs_compiler
532 def case(self
, switch
, value
):
534 old_case
= self
._case
535 with switch
.case(value
) as self
._case
:
538 self
._case
= old_case
540 def on_Assign(self
, stmt
):
541 if isinstance(stmt
, ast
.Assign
):
542 lhs_bits
, lhs_sign
= stmt
.lhs
.shape()
543 rhs_bits
, rhs_sign
= stmt
.rhs
.shape()
544 if lhs_bits
== rhs_bits
:
545 rhs_sigspec
= self
.rhs_compiler(stmt
.rhs
)
547 # In RTLIL, LHS and RHS of assignment must have exactly same width.
548 rhs_sigspec
= self
.rhs_compiler
.match_shape(
549 stmt
.rhs
, lhs_bits
, rhs_sign
)
550 self
._case
.assign(self
.lhs_compiler(stmt
.lhs
), rhs_sigspec
)
552 def on_Switch(self
, stmt
):
553 with self
._case
.switch(self
.rhs_compiler(stmt
.test
)) as switch
:
554 for value
, stmts
in stmt
.cases
.items():
555 with self
.case(switch
, value
):
556 self
.on_statements(stmts
)
558 def on_statement(self
, stmt
):
560 super().on_statement(stmt
)
561 except LegalizeValue
as legalize
:
562 with self
._case
.switch(self
.rhs_compiler(legalize
.value
)) as switch
:
563 bits
, sign
= legalize
.value
.shape()
564 tests
= ["{:0{}b}".format(v
, bits
) for v
in legalize
.branches
]
565 tests
[-1] = "-" * bits
566 for branch
, test
in zip(legalize
.branches
, tests
):
567 with self
.case(switch
, test
):
568 branch_value
= ast
.Const(branch
, (bits
, sign
))
569 with self
.state
.expand_to(legalize
.value
, branch_value
):
570 super().on_statement(stmt
)
572 def on_statements(self
, stmts
):
574 self
.on_statement(stmt
)
577 def convert_fragment(builder
, fragment
, name
, top
):
578 if isinstance(fragment
, ir
.Instance
):
579 port_map
= OrderedDict()
580 for port_name
, value
in fragment
.named_ports
.items():
581 port_map
["\\{}".format(port_name
)] = value
583 if fragment
.type[0] == "$":
584 return fragment
.type, port_map
586 return "\\{}".format(fragment
.type), port_map
588 with builder
.module(name
or "anonymous", attrs
={"top": 1} if top
else {}) as module
:
589 compiler_state
= _ValueCompilerState(module
)
590 rhs_compiler
= _RHSValueCompiler(compiler_state
)
591 lhs_compiler
= _LHSValueCompiler(compiler_state
)
592 stmt_compiler
= _StatementCompiler(compiler_state
, rhs_compiler
, lhs_compiler
)
594 # Register all signals driven in the current fragment. This must be done first, as it
595 # affects further codegen; e.g. whether sig$next signals will be generated and used.
596 for domain
, signal
in fragment
.iter_drivers():
597 compiler_state
.add_driven(signal
, sync
=domain
is not None)
599 # Transform all signals used as ports in the current fragment eagerly and outside of
600 # any hierarchy, to make sure they get sensible (non-prefixed) names.
601 for signal
in fragment
.ports
:
602 compiler_state
.add_port(signal
, fragment
.ports
[signal
])
603 compiler_state
.resolve_curr(signal
)
605 # Transform all clocks clocks and resets eagerly and outside of any hierarchy, to make
606 # sure they get sensible (non-prefixed) names. This does not affect semantics.
607 for domain
, _
in fragment
.iter_sync():
608 cd
= fragment
.domains
[domain
]
609 compiler_state
.resolve_curr(cd
.clk
)
610 if cd
.rst
is not None:
611 compiler_state
.resolve_curr(cd
.rst
)
613 # Transform all subfragments to their respective cells. Transforming signals connected
614 # to their ports into wires eagerly makes sure they get sensible (prefixed with submodule
616 memories
= OrderedDict()
617 for subfragment
, sub_name
in fragment
.subfragments
:
618 sub_params
= OrderedDict()
619 if hasattr(subfragment
, "parameters"):
620 for param_name
, param_value
in subfragment
.parameters
.items():
621 if isinstance(param_value
, mem
.Memory
):
623 if memory
not in memories
:
624 memories
[memory
] = module
.memory(width
=memory
.width
, size
=memory
.depth
,
626 addr_bits
= bits_for(memory
.depth
)
627 for addr
in range(memory
.depth
):
628 if addr
< len(memory
.init
):
629 data
= memory
.init
[addr
]
632 module
.cell("$meminit", ports
={
633 "\\ADDR": rhs_compiler(ast
.Const(addr
, addr_bits
)),
634 "\\DATA": rhs_compiler(ast
.Const(data
, memory
.width
)),
636 "MEMID": memories
[memory
],
638 "WIDTH": memory
.width
,
643 param_value
= memories
[memory
]
645 sub_params
[param_name
] = param_value
647 sub_type
, sub_port_map
= \
648 convert_fragment(builder
, subfragment
, top
=False, name
=sub_name
)
650 sub_ports
= OrderedDict()
651 for port
, value
in sub_port_map
.items():
652 for signal
in value
._rhs
_signals
():
653 compiler_state
.resolve_curr(signal
, prefix
=sub_name
)
654 sub_ports
[port
] = rhs_compiler(value
)
656 module
.cell(sub_type
, name
=sub_name
, ports
=sub_ports
, params
=sub_params
)
658 with module
.process() as process
:
659 with process
.case() as case
:
660 # For every signal in comb domain, assign \sig$next to the reset value.
661 # For every signal in sync domains, assign \sig$next to the current value (\sig).
662 for domain
, signal
in fragment
.iter_drivers():
664 prev_value
= ast
.Const(signal
.reset
, signal
.nbits
)
667 case
.assign(lhs_compiler(signal
), rhs_compiler(prev_value
))
669 # Convert statements into decision trees.
670 stmt_compiler
._case
= case
671 stmt_compiler(fragment
.statements
)
673 # For every signal in the sync domain, assign \sig's initial value (which will end up
674 # as the \init reg attribute) to the reset value.
675 with process
.sync("init") as sync
:
676 for domain
, signal
in fragment
.iter_sync():
677 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
678 sync
.update(wire_curr
, rhs_compiler(ast
.Const(signal
.reset
, signal
.nbits
)))
680 # For every signal in every domain, assign \sig to \sig$next. The sensitivity list,
681 # however, differs between domains: for comb domains, it is `always`, for sync domains
682 # with sync reset, it is `posedge clk`, for sync domains with async rest it is
683 # `posedge clk or posedge rst`.
684 for domain
, signals
in fragment
.drivers
.items():
687 triggers
.append(("always",))
689 cd
= fragment
.domains
[domain
]
690 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.clk
)))
692 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.rst
)))
694 for trigger
in triggers
:
695 with process
.sync(*trigger
) as sync
:
696 for signal
in signals
:
697 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
698 sync
.update(wire_curr
, wire_next
)
700 # Finally, collect the names we've given to our ports in RTLIL, and correlate these with
701 # the signals represented by these ports. If we are a submodule, this will be necessary
702 # to create a cell for us in the parent module.
703 port_map
= OrderedDict()
704 for signal
in fragment
.ports
:
705 port_map
[compiler_state
.resolve_curr(signal
)] = signal
707 return module
.name
, port_map
710 def convert(fragment
, name
="top", **kwargs
):
711 fragment
= fragment
.prepare(**kwargs
)
713 convert_fragment(builder
, fragment
, name
=name
, top
=True)