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
.ValueVisitor
):
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
, val1
, val0
= value
.operands
433 val1_bits
, val1_sign
= val1
.shape()
434 val0_bits
, val0_sign
= val0
.shape()
435 res_bits
, res_sign
= value
.shape()
436 val1_bits
= val0_bits
= res_bits
= max(val1_bits
, val0_bits
, res_bits
)
437 val1_wire
= self
.match_shape(val1
, val1_bits
, val1_sign
)
438 val0_wire
= self
.match_shape(val0
, val0_bits
, val0_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
.StatementVisitor
):
524 def __init__(self
, state
, rhs_compiler
, lhs_compiler
):
526 self
.rhs_compiler
= rhs_compiler
527 self
.lhs_compiler
= lhs_compiler
532 self
._test
_cache
= {}
535 def case(self
, switch
, value
):
537 old_case
= self
._case
538 with switch
.case(value
) as self
._case
:
541 self
._case
= old_case
543 def on_Assign(self
, stmt
):
544 # The invariant provided by LHSGroupAnalyzer is that all signals that ever appear together
545 # on LHS are a part of the same group, so it is sufficient to check any of them.
546 any_lhs_signal
= next(iter(stmt
.lhs
._lhs
_signals
()))
547 if any_lhs_signal
not in self
._group
:
550 lhs_bits
, lhs_sign
= stmt
.lhs
.shape()
551 rhs_bits
, rhs_sign
= stmt
.rhs
.shape()
552 if lhs_bits
== rhs_bits
:
553 rhs_sigspec
= self
.rhs_compiler(stmt
.rhs
)
555 # In RTLIL, LHS and RHS of assignment must have exactly same width.
556 rhs_sigspec
= self
.rhs_compiler
.match_shape(
557 stmt
.rhs
, lhs_bits
, rhs_sign
)
558 self
._case
.assign(self
.lhs_compiler(stmt
.lhs
), rhs_sigspec
)
560 def on_Switch(self
, stmt
):
561 if stmt
not in self
._test
_cache
:
562 self
._test
_cache
[stmt
] = self
.rhs_compiler(stmt
.test
)
563 test_sigspec
= self
._test
_cache
[stmt
]
565 with self
._case
.switch(test_sigspec
) as switch
:
566 for value
, stmts
in stmt
.cases
.items():
567 with self
.case(switch
, value
):
568 self
.on_statements(stmts
)
570 def on_statement(self
, stmt
):
572 super().on_statement(stmt
)
573 except LegalizeValue
as legalize
:
574 with self
._case
.switch(self
.rhs_compiler(legalize
.value
)) as switch
:
575 bits
, sign
= legalize
.value
.shape()
576 tests
= ["{:0{}b}".format(v
, bits
) for v
in legalize
.branches
]
577 tests
[-1] = "-" * bits
578 for branch
, test
in zip(legalize
.branches
, tests
):
579 with self
.case(switch
, test
):
580 branch_value
= ast
.Const(branch
, (bits
, sign
))
581 with self
.state
.expand_to(legalize
.value
, branch_value
):
582 super().on_statement(stmt
)
584 def on_statements(self
, stmts
):
586 self
.on_statement(stmt
)
589 def convert_fragment(builder
, fragment
, name
, top
):
590 if isinstance(fragment
, ir
.Instance
):
591 port_map
= OrderedDict()
592 for port_name
, value
in fragment
.named_ports
.items():
593 port_map
["\\{}".format(port_name
)] = value
595 if fragment
.type[0] == "$":
596 return fragment
.type, port_map
598 return "\\{}".format(fragment
.type), port_map
600 with builder
.module(name
or "anonymous", attrs
={"top": 1} if top
else {}) as module
:
601 compiler_state
= _ValueCompilerState(module
)
602 rhs_compiler
= _RHSValueCompiler(compiler_state
)
603 lhs_compiler
= _LHSValueCompiler(compiler_state
)
604 stmt_compiler
= _StatementCompiler(compiler_state
, rhs_compiler
, lhs_compiler
)
606 # Register all signals driven in the current fragment. This must be done first, as it
607 # affects further codegen; e.g. whether sig$next signals will be generated and used.
608 for domain
, signal
in fragment
.iter_drivers():
609 compiler_state
.add_driven(signal
, sync
=domain
is not None)
611 # Transform all signals used as ports in the current fragment eagerly and outside of
612 # any hierarchy, to make sure they get sensible (non-prefixed) names.
613 for signal
in fragment
.ports
:
614 compiler_state
.add_port(signal
, fragment
.ports
[signal
])
615 compiler_state
.resolve_curr(signal
)
617 # Transform all clocks clocks and resets eagerly and outside of any hierarchy, to make
618 # sure they get sensible (non-prefixed) names. This does not affect semantics.
619 for domain
, _
in fragment
.iter_sync():
620 cd
= fragment
.domains
[domain
]
621 compiler_state
.resolve_curr(cd
.clk
)
622 if cd
.rst
is not None:
623 compiler_state
.resolve_curr(cd
.rst
)
625 # Transform all subfragments to their respective cells. Transforming signals connected
626 # to their ports into wires eagerly makes sure they get sensible (prefixed with submodule
628 memories
= OrderedDict()
629 for subfragment
, sub_name
in fragment
.subfragments
:
630 if not subfragment
.ports
:
633 sub_params
= OrderedDict()
634 if hasattr(subfragment
, "parameters"):
635 for param_name
, param_value
in subfragment
.parameters
.items():
636 if isinstance(param_value
, mem
.Memory
):
638 if memory
not in memories
:
639 memories
[memory
] = module
.memory(width
=memory
.width
, size
=memory
.depth
,
641 addr_bits
= bits_for(memory
.depth
)
642 for addr
in range(memory
.depth
):
643 if addr
< len(memory
.init
):
644 data
= memory
.init
[addr
]
647 module
.cell("$meminit", ports
={
648 "\\ADDR": rhs_compiler(ast
.Const(addr
, addr_bits
)),
649 "\\DATA": rhs_compiler(ast
.Const(data
, memory
.width
)),
651 "MEMID": memories
[memory
],
653 "WIDTH": memory
.width
,
658 param_value
= memories
[memory
]
660 sub_params
[param_name
] = param_value
662 sub_type
, sub_port_map
= \
663 convert_fragment(builder
, subfragment
, top
=False, name
=sub_name
)
665 sub_ports
= OrderedDict()
666 for port
, value
in sub_port_map
.items():
667 for signal
in value
._rhs
_signals
():
668 compiler_state
.resolve_curr(signal
, prefix
=sub_name
)
669 sub_ports
[port
] = rhs_compiler(value
)
671 module
.cell(sub_type
, name
=sub_name
, ports
=sub_ports
, params
=sub_params
)
673 lhs_grouper
= xfrm
.LHSGroupAnalyzer()
674 lhs_grouper
.on_statements(fragment
.statements
)
675 for group
, group_signals
in lhs_grouper
.groups().items():
676 with module
.process(name
="$group_{}".format(group
)) as process
:
677 with process
.case() as case
:
678 # For every signal in comb domain, assign \sig$next to the reset value.
679 # For every signal in sync domains, assign \sig$next to the current
681 for domain
, signal
in fragment
.iter_drivers():
682 if signal
not in group_signals
:
685 prev_value
= ast
.Const(signal
.reset
, signal
.nbits
)
688 case
.assign(lhs_compiler(signal
), rhs_compiler(prev_value
))
690 # Convert statements into decision trees.
691 stmt_compiler
._group
= group_signals
692 stmt_compiler
._case
= case
693 stmt_compiler(fragment
.statements
)
695 # For every signal in the sync domain, assign \sig's initial value (which will
696 # end up as the \init reg attribute) to the reset value.
697 with process
.sync("init") as sync
:
698 for domain
, signal
in fragment
.iter_sync():
699 if signal
not in group_signals
:
701 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
702 sync
.update(wire_curr
, rhs_compiler(ast
.Const(signal
.reset
, signal
.nbits
)))
704 # For every signal in every domain, assign \sig to \sig$next. The sensitivity list,
705 # however, differs between domains: for comb domains, it is `always`, for sync
706 # domains with sync reset, it is `posedge clk`, for sync domains with async reset
707 # it is `posedge clk or posedge rst`.
708 for domain
, signals
in fragment
.drivers
.items():
709 signals
= signals
& group_signals
715 triggers
.append(("always",))
717 cd
= fragment
.domains
[domain
]
718 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.clk
)))
720 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.rst
)))
722 for trigger
in triggers
:
723 with process
.sync(*trigger
) as sync
:
724 for signal
in signals
:
725 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
726 sync
.update(wire_curr
, wire_next
)
728 # Finally, collect the names we've given to our ports in RTLIL, and correlate these with
729 # the signals represented by these ports. If we are a submodule, this will be necessary
730 # to create a cell for us in the parent module.
731 port_map
= OrderedDict()
732 for signal
in fragment
.ports
:
733 port_map
[compiler_state
.resolve_curr(signal
)] = signal
735 return module
.name
, port_map
738 def convert(fragment
, name
="top", **kwargs
):
739 fragment
= fragment
.prepare(**kwargs
)
741 convert_fragment(builder
, fragment
, name
=name
, top
=True)