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
19 def _make_name(self
, name
, local
):
22 name
= "${}".format(self
._index
)
23 elif not local
and name
[0] not in "\\$":
24 name
= "\\{}".format(name
)
25 while name
in self
._names
:
27 name
= "{}${}".format(name
, self
._index
)
33 _escape_map
= str.maketrans({
42 self
._buffer
= io
.StringIO()
45 return self
._buffer
.getvalue()
47 def _append(self
, fmt
, *args
, **kwargs
):
48 self
._buffer
.write(fmt
.format(*args
, **kwargs
))
50 def attribute(self
, name
, value
, indent
=0):
51 if isinstance(value
, str):
52 self
._append
("{}attribute \\{} \"{}\"\n",
53 " " * indent
, name
, value
.translate(self
._escape
_map
))
55 self
._append
("{}attribute \\{} {}\n",
56 " " * indent
, name
, int(value
))
60 self
.attribute("src", src
)
63 class _Builder(_Namer
, _Bufferer
):
64 def module(self
, name
=None, attrs
={}):
65 name
= self
._make
_name
(name
, local
=False)
66 return _ModuleBuilder(self
, name
, attrs
)
69 class _ModuleBuilder(_Namer
, _Bufferer
):
70 def __init__(self
, rtlil
, name
, attrs
):
74 self
.attrs
= {"generator": "nMigen"}
75 self
.attrs
.update(attrs
)
78 for name
, value
in self
.attrs
.items():
79 self
.attribute(name
, value
, indent
=0)
80 self
._append
("module {}\n", self
.name
)
83 def __exit__(self
, *args
):
85 self
.rtlil
._buffer
.write(str(self
))
87 def attribute(self
, name
, value
, indent
=1):
88 super().attribute(name
, value
, indent
)
90 def wire(self
, width
, port_id
=None, port_kind
=None, name
=None, src
=""):
92 name
= self
._make
_name
(name
, local
=False)
94 self
._append
(" wire width {} {}\n", width
, name
)
96 assert port_kind
in ("input", "output", "inout")
97 self
._append
(" wire width {} {} {} {}\n", width
, port_kind
, port_id
, name
)
100 def connect(self
, lhs
, rhs
):
101 self
._append
(" connect {} {}\n", lhs
, rhs
)
103 def memory(self
, width
, size
, name
=None, src
=""):
105 name
= self
._make
_name
(name
, local
=False)
106 self
._append
(" memory width {} size {} {}\n", width
, size
, name
)
109 def cell(self
, kind
, name
=None, params
={}, ports
={}, src
=""):
111 name
= self
._make
_name
(name
, local
=False)
112 self
._append
(" cell {} {}\n", kind
, name
)
113 for param
, value
in params
.items():
114 if isinstance(value
, str):
115 self
._append
(" parameter \\{} \"{}\"\n",
116 param
, value
.translate(self
._escape
_map
))
118 self
._append
(" parameter \\{} {:d}\n",
120 for port
, wire
in ports
.items():
121 self
._append
(" connect {} {}\n", port
, wire
)
122 self
._append
(" end\n")
125 def process(self
, name
=None, src
=""):
126 name
= self
._make
_name
(name
, local
=True)
127 return _ProcessBuilder(self
, name
, src
)
130 class _ProcessBuilder(_Bufferer
):
131 def __init__(self
, rtlil
, name
, src
):
139 self
._append
(" process {}\n", self
.name
)
142 def __exit__(self
, *args
):
143 self
._append
(" end\n")
144 self
.rtlil
._buffer
.write(str(self
))
147 return _CaseBuilder(self
, indent
=2)
149 def sync(self
, kind
, cond
=None):
150 return _SyncBuilder(self
, kind
, cond
)
154 def __init__(self
, rtlil
, indent
):
161 def __exit__(self
, *args
):
164 def assign(self
, lhs
, rhs
):
165 self
.rtlil
._append
("{}assign {} {}\n", " " * self
.indent
, lhs
, rhs
)
167 def switch(self
, cond
):
168 return _SwitchBuilder(self
.rtlil
, cond
, self
.indent
)
171 class _SwitchBuilder
:
172 def __init__(self
, rtlil
, cond
, indent
):
178 self
.rtlil
._append
("{}switch {}\n", " " * self
.indent
, self
.cond
)
181 def __exit__(self
, *args
):
182 self
.rtlil
._append
("{}end\n", " " * self
.indent
)
184 def case(self
, value
=None):
186 self
.rtlil
._append
("{}case\n", " " * (self
.indent
+ 1))
188 self
.rtlil
._append
("{}case {}'{}\n", " " * (self
.indent
+ 1),
190 return _CaseBuilder(self
.rtlil
, self
.indent
+ 2)
194 def __init__(self
, rtlil
, kind
, cond
):
200 if self
.cond
is None:
201 self
.rtlil
._append
(" sync {}\n", self
.kind
)
203 self
.rtlil
._append
(" sync {} {}\n", self
.kind
, self
.cond
)
206 def __exit__(self
, *args
):
209 def update(self
, lhs
, rhs
):
210 self
.rtlil
._append
(" update {} {}\n", lhs
, rhs
)
215 return "{}:{}".format(file, line
)
218 class LegalizeValue(Exception):
219 def __init__(self
, value
, branches
):
221 self
.branches
= list(branches
)
224 class _ValueCompilerState
:
225 def __init__(self
, rtlil
):
227 self
.wires
= ast
.SignalDict()
228 self
.driven
= ast
.SignalDict()
229 self
.ports
= ast
.SignalDict()
230 self
.anys
= ast
.ValueDict()
232 self
.expansions
= ast
.ValueDict()
234 def add_driven(self
, signal
, sync
):
235 self
.driven
[signal
] = sync
237 def add_port(self
, signal
, kind
):
238 assert kind
in ("i", "o", "io")
245 self
.ports
[signal
] = (len(self
.ports
), kind
)
247 def resolve(self
, signal
, prefix
=None):
248 if signal
in self
.wires
:
249 return self
.wires
[signal
]
251 if signal
in self
.ports
:
252 port_id
, port_kind
= self
.ports
[signal
]
254 port_id
= port_kind
= None
255 if prefix
is not None:
256 wire_name
= "{}_{}".format(prefix
, signal
.name
)
258 wire_name
= signal
.name
260 for attr_name
, attr_signal
in signal
.attrs
.items():
261 self
.rtlil
.attribute(attr_name
, attr_signal
)
262 wire_curr
= self
.rtlil
.wire(width
=signal
.nbits
, name
=wire_name
,
263 port_id
=port_id
, port_kind
=port_kind
,
264 src
=src(signal
.src_loc
))
265 if signal
in self
.driven
:
266 wire_next
= self
.rtlil
.wire(width
=signal
.nbits
, name
="$next" + wire_curr
,
267 src
=src(signal
.src_loc
))
270 self
.wires
[signal
] = (wire_curr
, wire_next
)
272 return wire_curr
, wire_next
274 def resolve_curr(self
, signal
, prefix
=None):
275 wire_curr
, wire_next
= self
.resolve(signal
, prefix
)
278 def expand(self
, value
):
279 if not self
.expansions
:
281 return self
.expansions
.get(value
, value
)
284 def expand_to(self
, value
, expansion
):
286 assert value
not in self
.expansions
287 self
.expansions
[value
] = expansion
290 del self
.expansions
[value
]
293 class _ValueCompiler(xfrm
.ValueVisitor
):
294 def __init__(self
, state
):
297 def on_value(self
, value
):
298 return super().on_value(self
.s
.expand(value
))
300 def on_unknown(self
, value
):
304 super().on_unknown(value
)
306 def on_ClockSignal(self
, value
):
307 raise NotImplementedError # :nocov:
309 def on_ResetSignal(self
, value
):
310 raise NotImplementedError # :nocov:
312 def on_Sample(self
, value
):
313 raise NotImplementedError # :nocov:
315 def on_Record(self
, value
):
316 return self(ast
.Cat(value
.fields
.values()))
318 def on_Cat(self
, value
):
319 return "{{ {} }}".format(" ".join(reversed([self(o
) for o
in value
.parts
])))
321 def _prepare_value_for_Slice(self
, value
):
322 raise NotImplementedError # :nocov:
324 def on_Slice(self
, value
):
325 if value
.start
== 0 and value
.end
== len(value
.value
):
326 return self(value
.value
)
328 sigspec
= self
._prepare
_value
_for
_Slice
(value
.value
)
329 if value
.start
== value
.end
:
331 elif value
.start
+ 1 == value
.end
:
332 return "{} [{}]".format(sigspec
, value
.start
)
334 return "{} [{}:{}]".format(sigspec
, value
.end
- 1, value
.start
)
336 def on_ArrayProxy(self
, value
):
337 index
= self
.s
.expand(value
.index
)
338 if isinstance(index
, ast
.Const
):
339 if index
.value
< len(value
.elems
):
340 elem
= value
.elems
[index
.value
]
342 elem
= value
.elems
[-1]
343 return self
.match_shape(elem
, *value
.shape())
345 raise LegalizeValue(value
.index
, range(len(value
.elems
)))
348 class _RHSValueCompiler(_ValueCompiler
):
352 (1, "b"): "$reduce_bool",
373 def on_Const(self
, value
):
374 if isinstance(value
.value
, str):
375 return "{}'{}".format(value
.nbits
, value
.value
)
377 value_twos_compl
= value
.value
& ((1 << value
.nbits
) - 1)
378 return "{}'{:0{}b}".format(value
.nbits
, value_twos_compl
, value
.nbits
)
380 def on_AnyConst(self
, value
):
381 if value
in self
.s
.anys
:
382 return self
.s
.anys
[value
]
384 res_bits
, res_sign
= value
.shape()
385 res
= self
.s
.rtlil
.wire(width
=res_bits
)
386 self
.s
.rtlil
.cell("$anyconst", ports
={
390 }, src
=src(value
.src_loc
))
391 self
.s
.anys
[value
] = res
394 def on_AnySeq(self
, value
):
395 if value
in self
.s
.anys
:
396 return self
.s
.anys
[value
]
398 res_bits
, res_sign
= value
.shape()
399 res
= self
.s
.rtlil
.wire(width
=res_bits
)
400 self
.s
.rtlil
.cell("$anyseq", ports
={
404 }, src
=src(value
.src_loc
))
405 self
.s
.anys
[value
] = res
408 def on_Signal(self
, value
):
409 wire_curr
, wire_next
= self
.s
.resolve(value
)
412 def on_Operator_unary(self
, value
):
413 arg
, = value
.operands
414 arg_bits
, arg_sign
= arg
.shape()
415 res_bits
, res_sign
= value
.shape()
416 res
= self
.s
.rtlil
.wire(width
=res_bits
)
417 self
.s
.rtlil
.cell(self
.operator_map
[(1, value
.op
)], ports
={
421 "A_SIGNED": arg_sign
,
424 }, src
=src(value
.src_loc
))
427 def match_shape(self
, value
, new_bits
, new_sign
):
428 if isinstance(value
, ast
.Const
):
429 return self(ast
.Const(value
.value
, (new_bits
, new_sign
)))
431 value_bits
, value_sign
= value
.shape()
432 if new_bits
<= value_bits
:
433 return self(ast
.Slice(value
, 0, new_bits
))
435 res
= self
.s
.rtlil
.wire(width
=new_bits
)
436 self
.s
.rtlil
.cell("$pos", ports
={
440 "A_SIGNED": value_sign
,
441 "A_WIDTH": value_bits
,
443 }, src
=src(value
.src_loc
))
446 def on_Operator_binary(self
, value
):
447 lhs
, rhs
= value
.operands
448 lhs_bits
, lhs_sign
= lhs
.shape()
449 rhs_bits
, rhs_sign
= rhs
.shape()
450 if lhs_sign
== rhs_sign
:
454 lhs_sign
= rhs_sign
= True
455 lhs_bits
= rhs_bits
= max(lhs_bits
, rhs_bits
)
456 lhs_wire
= self
.match_shape(lhs
, lhs_bits
, lhs_sign
)
457 rhs_wire
= self
.match_shape(rhs
, rhs_bits
, rhs_sign
)
458 res_bits
, res_sign
= value
.shape()
459 res
= self
.s
.rtlil
.wire(width
=res_bits
)
460 self
.s
.rtlil
.cell(self
.operator_map
[(2, value
.op
)], ports
={
465 "A_SIGNED": lhs_sign
,
467 "B_SIGNED": rhs_sign
,
470 }, src
=src(value
.src_loc
))
473 def on_Operator_mux(self
, value
):
474 sel
, val1
, val0
= value
.operands
475 val1_bits
, val1_sign
= val1
.shape()
476 val0_bits
, val0_sign
= val0
.shape()
477 res_bits
, res_sign
= value
.shape()
478 val1_bits
= val0_bits
= res_bits
= max(val1_bits
, val0_bits
, res_bits
)
479 val1_wire
= self
.match_shape(val1
, val1_bits
, val1_sign
)
480 val0_wire
= self
.match_shape(val0
, val0_bits
, val0_sign
)
481 res
= self
.s
.rtlil
.wire(width
=res_bits
)
482 self
.s
.rtlil
.cell("$mux", ports
={
489 }, src
=src(value
.src_loc
))
492 def on_Operator(self
, value
):
493 if len(value
.operands
) == 1:
494 return self
.on_Operator_unary(value
)
495 elif len(value
.operands
) == 2:
496 return self
.on_Operator_binary(value
)
497 elif len(value
.operands
) == 3:
498 assert value
.op
== "m"
499 return self
.on_Operator_mux(value
)
501 raise TypeError # :nocov:
503 def _prepare_value_for_Slice(self
, value
):
504 if isinstance(value
, (ast
.Signal
, ast
.Slice
, ast
.Cat
)):
505 sigspec
= self(value
)
507 sigspec
= self
.s
.rtlil
.wire(len(value
))
508 self
.s
.rtlil
.connect(sigspec
, self(value
))
511 def on_Part(self
, value
):
512 lhs
, rhs
= value
.value
, value
.offset
513 lhs_bits
, lhs_sign
= lhs
.shape()
514 rhs_bits
, rhs_sign
= rhs
.shape()
515 res_bits
, res_sign
= value
.shape()
516 res
= self
.s
.rtlil
.wire(width
=res_bits
)
517 # Note: Verilog's x[o+:w] construct produces a $shiftx cell, not a $shift cell.
518 # However, Migen's semantics defines the out-of-range bits to be zero, so it is correct
519 # to use a $shift cell here instead, even though it produces less idiomatic Verilog.
520 self
.s
.rtlil
.cell("$shift", ports
={
525 "A_SIGNED": lhs_sign
,
527 "B_SIGNED": rhs_sign
,
530 }, src
=src(value
.src_loc
))
533 def on_Repl(self
, value
):
534 return "{{ {} }}".format(" ".join(self(value
.value
) for _
in range(value
.count
)))
537 class _LHSValueCompiler(_ValueCompiler
):
538 def on_Const(self
, value
):
539 raise TypeError # :nocov:
541 def on_AnyConst(self
, value
):
542 raise TypeError # :nocov:
544 def on_AnySeq(self
, value
):
545 raise TypeError # :nocov:
547 def on_Operator(self
, value
):
548 raise TypeError # :nocov:
550 def match_shape(self
, value
, new_bits
, new_sign
):
551 assert value
.shape() == (new_bits
, new_sign
)
554 def on_Signal(self
, value
):
555 wire_curr
, wire_next
= self
.s
.resolve(value
)
556 if wire_next
is None:
557 raise ValueError("No LHS wire for non-driven signal {}".format(repr(value
)))
560 def _prepare_value_for_Slice(self
, value
):
561 assert isinstance(value
, (ast
.Signal
, ast
.Slice
, ast
.Cat
))
564 def on_Part(self
, value
):
565 offset
= self
.s
.expand(value
.offset
)
566 if isinstance(offset
, ast
.Const
):
567 return self(ast
.Slice(value
.value
, offset
.value
, offset
.value
+ value
.width
))
569 raise LegalizeValue(value
.offset
, range((1 << len(value
.offset
)) - 1))
571 def on_Repl(self
, value
):
572 raise TypeError # :nocov:
575 class _StatementCompiler(xfrm
.StatementVisitor
):
576 def __init__(self
, state
, rhs_compiler
, lhs_compiler
):
578 self
.rhs_compiler
= rhs_compiler
579 self
.lhs_compiler
= lhs_compiler
582 self
._test
_cache
= {}
583 self
._has
_rhs
= False
586 def case(self
, switch
, value
):
588 old_case
= self
._case
589 with switch
.case(value
) as self
._case
:
592 self
._case
= old_case
594 def _check_rhs(self
, value
):
595 if self
._has
_rhs
or next(iter(value
._rhs
_signals
()), None) is not None:
598 def on_Assign(self
, stmt
):
599 self
._check
_rhs
(stmt
.rhs
)
601 lhs_bits
, lhs_sign
= stmt
.lhs
.shape()
602 rhs_bits
, rhs_sign
= stmt
.rhs
.shape()
603 if lhs_bits
== rhs_bits
:
604 rhs_sigspec
= self
.rhs_compiler(stmt
.rhs
)
606 # In RTLIL, LHS and RHS of assignment must have exactly same width.
607 rhs_sigspec
= self
.rhs_compiler
.match_shape(
608 stmt
.rhs
, lhs_bits
, lhs_sign
)
609 self
._case
.assign(self
.lhs_compiler(stmt
.lhs
), rhs_sigspec
)
611 def on_Assert(self
, stmt
):
612 self(stmt
._check
.eq(stmt
.test
))
615 en_wire
= self
.rhs_compiler(stmt
._en
)
616 check_wire
= self
.rhs_compiler(stmt
._check
)
617 self
.state
.rtlil
.cell("$assert", ports
={
620 }, src
=src(stmt
.src_loc
))
622 def on_Assume(self
, stmt
):
623 self(stmt
._check
.eq(stmt
.test
))
626 en_wire
= self
.rhs_compiler(stmt
._en
)
627 check_wire
= self
.rhs_compiler(stmt
._check
)
628 self
.state
.rtlil
.cell("$assume", ports
={
631 }, src
=src(stmt
.src_loc
))
633 def on_Switch(self
, stmt
):
634 self
._check
_rhs
(stmt
.test
)
636 if stmt
not in self
._test
_cache
:
637 self
._test
_cache
[stmt
] = self
.rhs_compiler(stmt
.test
)
638 test_sigspec
= self
._test
_cache
[stmt
]
640 with self
._case
.switch(test_sigspec
) as switch
:
641 for value
, stmts
in stmt
.cases
.items():
642 with self
.case(switch
, value
):
643 self
.on_statements(stmts
)
645 def on_statement(self
, stmt
):
647 super().on_statement(stmt
)
648 except LegalizeValue
as legalize
:
649 with self
._case
.switch(self
.rhs_compiler(legalize
.value
)) as switch
:
650 bits
, sign
= legalize
.value
.shape()
651 tests
= ["{:0{}b}".format(v
, bits
) for v
in legalize
.branches
]
652 tests
[-1] = "-" * bits
653 for branch
, test
in zip(legalize
.branches
, tests
):
654 with self
.case(switch
, test
):
655 branch_value
= ast
.Const(branch
, (bits
, sign
))
656 with self
.state
.expand_to(legalize
.value
, branch_value
):
657 super().on_statement(stmt
)
659 def on_statements(self
, stmts
):
661 self
.on_statement(stmt
)
664 def convert_fragment(builder
, fragment
, name
, top
):
665 if isinstance(fragment
, ir
.Instance
):
666 port_map
= OrderedDict()
667 for port_name
, value
in fragment
.named_ports
.items():
668 port_map
["\\{}".format(port_name
)] = value
670 if fragment
.type[0] == "$":
671 return fragment
.type, port_map
673 return "\\{}".format(fragment
.type), port_map
675 with builder
.module(name
or "anonymous", attrs
={"top": 1} if top
else {}) as module
:
676 compiler_state
= _ValueCompilerState(module
)
677 rhs_compiler
= _RHSValueCompiler(compiler_state
)
678 lhs_compiler
= _LHSValueCompiler(compiler_state
)
679 stmt_compiler
= _StatementCompiler(compiler_state
, rhs_compiler
, lhs_compiler
)
681 verilog_trigger
= None
682 verilog_trigger_sync_emitted
= False
684 # Register all signals driven in the current fragment. This must be done first, as it
685 # affects further codegen; e.g. whether $next\sig signals will be generated and used.
686 for domain
, signal
in fragment
.iter_drivers():
687 compiler_state
.add_driven(signal
, sync
=domain
is not None)
689 # Transform all signals used as ports in the current fragment eagerly and outside of
690 # any hierarchy, to make sure they get sensible (non-prefixed) names.
691 for signal
in fragment
.ports
:
692 compiler_state
.add_port(signal
, fragment
.ports
[signal
])
693 compiler_state
.resolve_curr(signal
)
695 # Transform all clocks clocks and resets eagerly and outside of any hierarchy, to make
696 # sure they get sensible (non-prefixed) names. This does not affect semantics.
697 for domain
, _
in fragment
.iter_sync():
698 cd
= fragment
.domains
[domain
]
699 compiler_state
.resolve_curr(cd
.clk
)
700 if cd
.rst
is not None:
701 compiler_state
.resolve_curr(cd
.rst
)
703 # Transform all subfragments to their respective cells. Transforming signals connected
704 # to their ports into wires eagerly makes sure they get sensible (prefixed with submodule
706 memories
= OrderedDict()
707 for subfragment
, sub_name
in fragment
.subfragments
:
708 if not subfragment
.ports
:
711 sub_params
= OrderedDict()
712 if hasattr(subfragment
, "parameters"):
713 for param_name
, param_value
in subfragment
.parameters
.items():
714 if isinstance(param_value
, mem
.Memory
):
716 if memory
not in memories
:
717 memories
[memory
] = module
.memory(width
=memory
.width
, size
=memory
.depth
,
719 addr_bits
= bits_for(memory
.depth
)
721 for addr
in range(memory
.depth
):
722 if addr
< len(memory
.init
):
723 data
= memory
.init
[addr
]
726 data_parts
.append("{:0{}b}".format(data
, memory
.width
))
727 module
.cell("$meminit", ports
={
728 "\\ADDR": rhs_compiler(ast
.Const(0, addr_bits
)),
729 "\\DATA": "{}'".format(memory
.width
* memory
.depth
) +
730 "".join(reversed(data_parts
)),
732 "MEMID": memories
[memory
],
734 "WIDTH": memory
.width
,
735 "WORDS": memory
.depth
,
739 param_value
= memories
[memory
]
741 sub_params
[param_name
] = param_value
743 sub_type
, sub_port_map
= \
744 convert_fragment(builder
, subfragment
, top
=False, name
=sub_name
)
746 sub_ports
= OrderedDict()
747 for port
, value
in sub_port_map
.items():
748 for signal
in value
._rhs
_signals
():
749 compiler_state
.resolve_curr(signal
, prefix
=sub_name
)
750 sub_ports
[port
] = rhs_compiler(value
)
752 module
.cell(sub_type
, name
=sub_name
, ports
=sub_ports
, params
=sub_params
)
754 # If we emit all of our combinatorial logic into a single RTLIL process, Verilog
755 # simulators will break horribly, because Yosys write_verilog transforms RTLIL processes
756 # into always @* blocks with blocking assignment, and that does not create delta cycles.
758 # Therefore, we translate the fragment as many times as there are independent groups
759 # of signals (a group is a transitive closure of signals that appear together on LHS),
760 # splitting them into many RTLIL (and thus Verilog) processes.
761 lhs_grouper
= xfrm
.LHSGroupAnalyzer()
762 lhs_grouper
.on_statements(fragment
.statements
)
764 for group
, group_signals
in lhs_grouper
.groups().items():
765 lhs_group_filter
= xfrm
.LHSGroupFilter(group_signals
)
767 with module
.process(name
="$group_{}".format(group
)) as process
:
768 with process
.case() as case
:
769 # For every signal in comb domain, assign $next\sig to the reset value.
770 # For every signal in sync domains, assign $next\sig to the current
772 for domain
, signal
in fragment
.iter_drivers():
773 if signal
not in group_signals
:
776 prev_value
= ast
.Const(signal
.reset
, signal
.nbits
)
779 case
.assign(lhs_compiler(signal
), rhs_compiler(prev_value
))
781 # Convert statements into decision trees.
782 stmt_compiler
._case
= case
783 stmt_compiler
._has
_rhs
= False
784 stmt_compiler(lhs_group_filter(fragment
.statements
))
786 # Verilog `always @*` blocks will not run if `*` does not match anything, i.e.
787 # if the implicit sensitivity list is empty. We check this while translating,
788 # by looking for any signals on RHS. If there aren't any, we add some logic
789 # whose only purpose is to trigger Verilog simulators when it converts
790 # through RTLIL and to Verilog, by populating the sensitivity list.
791 if not stmt_compiler
._has
_rhs
:
792 if verilog_trigger
is None:
794 module
.wire(1, name
="$verilog_initial_trigger")
795 case
.assign(verilog_trigger
, verilog_trigger
)
797 # For every signal in the sync domain, assign \sig's initial value (which will
798 # end up as the \init reg attribute) to the reset value.
799 with process
.sync("init") as sync
:
800 for domain
, signal
in fragment
.iter_sync():
801 if signal
not in group_signals
:
803 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
804 sync
.update(wire_curr
, rhs_compiler(ast
.Const(signal
.reset
, signal
.nbits
)))
806 # The Verilog simulator trigger needs to change at time 0, so if we haven't
807 # yet done that in some process, do it.
808 if verilog_trigger
and not verilog_trigger_sync_emitted
:
809 sync
.update(verilog_trigger
, "1'0")
810 verilog_trigger_sync_emitted
= True
812 # For every signal in every domain, assign \sig to $next\sig. The sensitivity list,
813 # however, differs between domains: for comb domains, it is `always`, for sync
814 # domains with sync reset, it is `posedge clk`, for sync domains with async reset
815 # it is `posedge clk or posedge rst`.
816 for domain
, signals
in fragment
.drivers
.items():
817 signals
= signals
& group_signals
823 triggers
.append(("always",))
825 cd
= fragment
.domains
[domain
]
826 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.clk
)))
828 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.rst
)))
830 for trigger
in triggers
:
831 with process
.sync(*trigger
) as sync
:
832 for signal
in signals
:
833 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
834 sync
.update(wire_curr
, wire_next
)
836 # Finally, collect the names we've given to our ports in RTLIL, and correlate these with
837 # the signals represented by these ports. If we are a submodule, this will be necessary
838 # to create a cell for us in the parent module.
839 port_map
= OrderedDict()
840 for signal
in fragment
.ports
:
841 port_map
[compiler_state
.resolve_curr(signal
)] = signal
843 return module
.name
, port_map
846 def convert(fragment
, name
="top", **kwargs
):
847 fragment
= fragment
.prepare(**kwargs
)
849 convert_fragment(builder
, fragment
, name
=name
, top
=True)