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_Record(self
, value
):
309 return self(ast
.Cat(value
.fields
.values()))
311 def on_Cat(self
, value
):
312 return "{{ {} }}".format(" ".join(reversed([self(o
) for o
in value
.parts
])))
314 def _prepare_value_for_Slice(self
, value
):
315 raise NotImplementedError # :nocov:
317 def on_Slice(self
, value
):
318 if value
.start
== 0 and value
.end
== len(value
.value
):
319 return self(value
.value
)
321 sigspec
= self
._prepare
_value
_for
_Slice
(value
.value
)
322 if value
.start
+ 1 == value
.end
:
323 return "{} [{}]".format(sigspec
, value
.start
)
325 return "{} [{}:{}]".format(sigspec
, value
.end
- 1, value
.start
)
327 def on_ArrayProxy(self
, value
):
328 index
= self
.s
.expand(value
.index
)
329 if isinstance(index
, ast
.Const
):
330 if index
.value
< len(value
.elems
):
331 elem
= value
.elems
[index
.value
]
333 elem
= value
.elems
[-1]
334 return self
.match_shape(elem
, *value
.shape())
336 raise LegalizeValue(value
.index
, range(len(value
.elems
)))
339 class _RHSValueCompiler(_ValueCompiler
):
343 (1, "b"): "$reduce_bool",
364 def on_Const(self
, value
):
365 if isinstance(value
.value
, str):
366 return "{}'{}".format(value
.nbits
, value
.value
)
368 value_twos_compl
= value
.value
& ((1 << value
.nbits
) - 1)
369 return "{}'{:0{}b}".format(value
.nbits
, value_twos_compl
, value
.nbits
)
371 def on_Signal(self
, value
):
372 wire_curr
, wire_next
= self
.s
.resolve(value
)
375 def on_Operator_unary(self
, value
):
376 arg
, = value
.operands
377 arg_bits
, arg_sign
= arg
.shape()
378 res_bits
, res_sign
= value
.shape()
379 res
= self
.s
.rtlil
.wire(width
=res_bits
)
380 self
.s
.rtlil
.cell(self
.operator_map
[(1, value
.op
)], ports
={
384 "A_SIGNED": arg_sign
,
387 }, src
=src(value
.src_loc
))
390 def match_shape(self
, value
, new_bits
, new_sign
):
391 if isinstance(value
, ast
.Const
):
392 return self(ast
.Const(value
.value
, (new_bits
, new_sign
)))
394 value_bits
, value_sign
= value
.shape()
395 if new_bits
<= value_bits
:
396 return self(ast
.Slice(value
, 0, new_bits
))
398 res
= self
.s
.rtlil
.wire(width
=new_bits
)
399 self
.s
.rtlil
.cell("$pos", ports
={
403 "A_SIGNED": value_sign
,
404 "A_WIDTH": value_bits
,
406 }, src
=src(value
.src_loc
))
409 def on_Operator_binary(self
, value
):
410 lhs
, rhs
= value
.operands
411 lhs_bits
, lhs_sign
= lhs
.shape()
412 rhs_bits
, rhs_sign
= rhs
.shape()
413 if lhs_sign
== rhs_sign
:
417 lhs_sign
= rhs_sign
= True
418 lhs_bits
= rhs_bits
= max(lhs_bits
, rhs_bits
)
419 lhs_wire
= self
.match_shape(lhs
, lhs_bits
, lhs_sign
)
420 rhs_wire
= self
.match_shape(rhs
, rhs_bits
, rhs_sign
)
421 res_bits
, res_sign
= value
.shape()
422 res
= self
.s
.rtlil
.wire(width
=res_bits
)
423 self
.s
.rtlil
.cell(self
.operator_map
[(2, value
.op
)], ports
={
428 "A_SIGNED": lhs_sign
,
430 "B_SIGNED": rhs_sign
,
433 }, src
=src(value
.src_loc
))
436 def on_Operator_mux(self
, value
):
437 sel
, val1
, val0
= value
.operands
438 val1_bits
, val1_sign
= val1
.shape()
439 val0_bits
, val0_sign
= val0
.shape()
440 res_bits
, res_sign
= value
.shape()
441 val1_bits
= val0_bits
= res_bits
= max(val1_bits
, val0_bits
, res_bits
)
442 val1_wire
= self
.match_shape(val1
, val1_bits
, val1_sign
)
443 val0_wire
= self
.match_shape(val0
, val0_bits
, val0_sign
)
444 res
= self
.s
.rtlil
.wire(width
=res_bits
)
445 self
.s
.rtlil
.cell("$mux", ports
={
452 }, src
=src(value
.src_loc
))
455 def on_Operator(self
, value
):
456 if len(value
.operands
) == 1:
457 return self
.on_Operator_unary(value
)
458 elif len(value
.operands
) == 2:
459 return self
.on_Operator_binary(value
)
460 elif len(value
.operands
) == 3:
461 assert value
.op
== "m"
462 return self
.on_Operator_mux(value
)
464 raise TypeError # :nocov:
466 def _prepare_value_for_Slice(self
, value
):
467 if isinstance(value
, (ast
.Signal
, ast
.Slice
, ast
.Cat
)):
468 sigspec
= self(value
)
470 sigspec
= self
.s
.rtlil
.wire(len(value
))
471 self
.s
.rtlil
.connect(sigspec
, self(value
))
474 def on_Part(self
, value
):
475 lhs
, rhs
= value
.value
, value
.offset
476 lhs_bits
, lhs_sign
= lhs
.shape()
477 rhs_bits
, rhs_sign
= rhs
.shape()
478 res_bits
, res_sign
= value
.shape()
479 res
= self
.s
.rtlil
.wire(width
=res_bits
)
480 # Note: Verilog's x[o+:w] construct produces a $shiftx cell, not a $shift cell.
481 # However, Migen's semantics defines the out-of-range bits to be zero, so it is correct
482 # to use a $shift cell here instead, even though it produces less idiomatic Verilog.
483 self
.s
.rtlil
.cell("$shift", ports
={
488 "A_SIGNED": lhs_sign
,
490 "B_SIGNED": rhs_sign
,
493 }, src
=src(value
.src_loc
))
496 def on_Repl(self
, value
):
497 return "{{ {} }}".format(" ".join(self(value
.value
) for _
in range(value
.count
)))
500 class _LHSValueCompiler(_ValueCompiler
):
501 def on_Const(self
, value
):
502 raise TypeError # :nocov:
504 def on_Operator(self
, value
):
505 raise TypeError # :nocov:
507 def match_shape(self
, value
, new_bits
, new_sign
):
508 assert value
.shape() == (new_bits
, new_sign
)
511 def on_Signal(self
, value
):
512 wire_curr
, wire_next
= self
.s
.resolve(value
)
513 if wire_next
is None:
514 raise ValueError("No LHS wire for non-driven signal {}".format(repr(value
)))
517 def _prepare_value_for_Slice(self
, value
):
518 assert isinstance(value
, (ast
.Signal
, ast
.Slice
, ast
.Cat
))
521 def on_Part(self
, value
):
522 offset
= self
.s
.expand(value
.offset
)
523 if isinstance(offset
, ast
.Const
):
524 return self(ast
.Slice(value
.value
, offset
.value
, offset
.value
+ value
.width
))
526 raise LegalizeValue(value
.offset
, range((1 << len(value
.offset
)) - 1))
528 def on_Repl(self
, value
):
529 raise TypeError # :nocov:
532 class _StatementCompiler(xfrm
.StatementVisitor
):
533 def __init__(self
, state
, rhs_compiler
, lhs_compiler
):
535 self
.rhs_compiler
= rhs_compiler
536 self
.lhs_compiler
= lhs_compiler
539 self
._test
_cache
= {}
540 self
._has
_rhs
= False
543 def case(self
, switch
, value
):
545 old_case
= self
._case
546 with switch
.case(value
) as self
._case
:
549 self
._case
= old_case
551 def _check_rhs(self
, value
):
552 if self
._has
_rhs
or next(iter(value
._rhs
_signals
()), None) is not None:
555 def on_Assign(self
, stmt
):
556 self
._check
_rhs
(stmt
.rhs
)
558 lhs_bits
, lhs_sign
= stmt
.lhs
.shape()
559 rhs_bits
, rhs_sign
= stmt
.rhs
.shape()
560 if lhs_bits
== rhs_bits
:
561 rhs_sigspec
= self
.rhs_compiler(stmt
.rhs
)
563 # In RTLIL, LHS and RHS of assignment must have exactly same width.
564 rhs_sigspec
= self
.rhs_compiler
.match_shape(
565 stmt
.rhs
, lhs_bits
, lhs_sign
)
566 self
._case
.assign(self
.lhs_compiler(stmt
.lhs
), rhs_sigspec
)
568 def on_Switch(self
, stmt
):
569 self
._check
_rhs
(stmt
.test
)
571 if stmt
not in self
._test
_cache
:
572 self
._test
_cache
[stmt
] = self
.rhs_compiler(stmt
.test
)
573 test_sigspec
= self
._test
_cache
[stmt
]
575 with self
._case
.switch(test_sigspec
) as switch
:
576 for value
, stmts
in stmt
.cases
.items():
577 with self
.case(switch
, value
):
578 self
.on_statements(stmts
)
580 def on_statement(self
, stmt
):
582 super().on_statement(stmt
)
583 except LegalizeValue
as legalize
:
584 with self
._case
.switch(self
.rhs_compiler(legalize
.value
)) as switch
:
585 bits
, sign
= legalize
.value
.shape()
586 tests
= ["{:0{}b}".format(v
, bits
) for v
in legalize
.branches
]
587 tests
[-1] = "-" * bits
588 for branch
, test
in zip(legalize
.branches
, tests
):
589 with self
.case(switch
, test
):
590 branch_value
= ast
.Const(branch
, (bits
, sign
))
591 with self
.state
.expand_to(legalize
.value
, branch_value
):
592 super().on_statement(stmt
)
594 def on_statements(self
, stmts
):
596 self
.on_statement(stmt
)
599 def convert_fragment(builder
, fragment
, name
, top
):
600 if isinstance(fragment
, ir
.Instance
):
601 port_map
= OrderedDict()
602 for port_name
, value
in fragment
.named_ports
.items():
603 port_map
["\\{}".format(port_name
)] = value
605 if fragment
.type[0] == "$":
606 return fragment
.type, port_map
608 return "\\{}".format(fragment
.type), port_map
610 with builder
.module(name
or "anonymous", attrs
={"top": 1} if top
else {}) as module
:
611 compiler_state
= _ValueCompilerState(module
)
612 rhs_compiler
= _RHSValueCompiler(compiler_state
)
613 lhs_compiler
= _LHSValueCompiler(compiler_state
)
614 stmt_compiler
= _StatementCompiler(compiler_state
, rhs_compiler
, lhs_compiler
)
616 verilog_trigger
= None
617 verilog_trigger_sync_emitted
= False
619 # Register all signals driven in the current fragment. This must be done first, as it
620 # affects further codegen; e.g. whether sig$next signals will be generated and used.
621 for domain
, signal
in fragment
.iter_drivers():
622 compiler_state
.add_driven(signal
, sync
=domain
is not None)
624 # Transform all signals used as ports in the current fragment eagerly and outside of
625 # any hierarchy, to make sure they get sensible (non-prefixed) names.
626 for signal
in fragment
.ports
:
627 compiler_state
.add_port(signal
, fragment
.ports
[signal
])
628 compiler_state
.resolve_curr(signal
)
630 # Transform all clocks clocks and resets eagerly and outside of any hierarchy, to make
631 # sure they get sensible (non-prefixed) names. This does not affect semantics.
632 for domain
, _
in fragment
.iter_sync():
633 cd
= fragment
.domains
[domain
]
634 compiler_state
.resolve_curr(cd
.clk
)
635 if cd
.rst
is not None:
636 compiler_state
.resolve_curr(cd
.rst
)
638 # Transform all subfragments to their respective cells. Transforming signals connected
639 # to their ports into wires eagerly makes sure they get sensible (prefixed with submodule
641 memories
= OrderedDict()
642 for subfragment
, sub_name
in fragment
.subfragments
:
643 if not subfragment
.ports
:
646 sub_params
= OrderedDict()
647 if hasattr(subfragment
, "parameters"):
648 for param_name
, param_value
in subfragment
.parameters
.items():
649 if isinstance(param_value
, mem
.Memory
):
651 if memory
not in memories
:
652 memories
[memory
] = module
.memory(width
=memory
.width
, size
=memory
.depth
,
654 addr_bits
= bits_for(memory
.depth
)
656 for addr
in range(memory
.depth
):
657 if addr
< len(memory
.init
):
658 data
= memory
.init
[addr
]
661 data_parts
.append("{:0{}b}".format(data
, memory
.width
))
662 module
.cell("$meminit", ports
={
663 "\\ADDR": rhs_compiler(ast
.Const(0, addr_bits
)),
664 "\\DATA": "{}'".format(memory
.width
* memory
.depth
) +
665 "".join(reversed(data_parts
)),
667 "MEMID": memories
[memory
],
669 "WIDTH": memory
.width
,
670 "WORDS": memory
.depth
,
674 param_value
= memories
[memory
]
676 sub_params
[param_name
] = param_value
678 sub_type
, sub_port_map
= \
679 convert_fragment(builder
, subfragment
, top
=False, name
=sub_name
)
681 sub_ports
= OrderedDict()
682 for port
, value
in sub_port_map
.items():
683 for signal
in value
._rhs
_signals
():
684 compiler_state
.resolve_curr(signal
, prefix
=sub_name
)
685 sub_ports
[port
] = rhs_compiler(value
)
687 module
.cell(sub_type
, name
=sub_name
, ports
=sub_ports
, params
=sub_params
)
689 # If we emit all of our combinatorial logic into a single RTLIL process, Verilog
690 # simulators will break horribly, because Yosys write_verilog transforms RTLIL processes
691 # into always @* blocks with blocking assignment, and that does not create delta cycles.
693 # Therefore, we translate the fragment as many times as there are independent groups
694 # of signals (a group is a transitive closure of signals that appear together on LHS),
695 # splitting them into many RTLIL (and thus Verilog) processes.
696 lhs_grouper
= xfrm
.LHSGroupAnalyzer()
697 lhs_grouper
.on_statements(fragment
.statements
)
699 for group
, group_signals
in lhs_grouper
.groups().items():
700 lhs_group_filter
= xfrm
.LHSGroupFilter(group_signals
)
702 with module
.process(name
="$group_{}".format(group
)) as process
:
703 with process
.case() as case
:
704 # For every signal in comb domain, assign \sig$next to the reset value.
705 # For every signal in sync domains, assign \sig$next to the current
707 for domain
, signal
in fragment
.iter_drivers():
708 if signal
not in group_signals
:
711 prev_value
= ast
.Const(signal
.reset
, signal
.nbits
)
714 case
.assign(lhs_compiler(signal
), rhs_compiler(prev_value
))
716 # Convert statements into decision trees.
717 stmt_compiler
._case
= case
718 stmt_compiler
._has
_rhs
= False
719 stmt_compiler(lhs_group_filter(fragment
.statements
))
721 # Verilog `always @*` blocks will not run if `*` does not match anything, i.e.
722 # if the implicit sensitivity list is empty. We check this while translating,
723 # by looking for any signals on RHS. If there aren't any, we add some logic
724 # whose only purpose is to trigger Verilog simulators when it converts
725 # through RTLIL and to Verilog, by populating the sensitivity list.
726 if not stmt_compiler
._has
_rhs
:
727 if verilog_trigger
is None:
729 module
.wire(1, name
="$verilog_initial_trigger")
730 case
.assign(verilog_trigger
, verilog_trigger
)
732 # For every signal in the sync domain, assign \sig's initial value (which will
733 # end up as the \init reg attribute) to the reset value.
734 with process
.sync("init") as sync
:
735 for domain
, signal
in fragment
.iter_sync():
736 if signal
not in group_signals
:
738 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
739 sync
.update(wire_curr
, rhs_compiler(ast
.Const(signal
.reset
, signal
.nbits
)))
741 # The Verilog simulator trigger needs to change at time 0, so if we haven't
742 # yet done that in some process, do it.
743 if verilog_trigger
and not verilog_trigger_sync_emitted
:
744 sync
.update(verilog_trigger
, "1'0")
745 verilog_trigger_sync_emitted
= True
747 # For every signal in every domain, assign \sig to \sig$next. The sensitivity list,
748 # however, differs between domains: for comb domains, it is `always`, for sync
749 # domains with sync reset, it is `posedge clk`, for sync domains with async reset
750 # it is `posedge clk or posedge rst`.
751 for domain
, signals
in fragment
.drivers
.items():
752 signals
= signals
& group_signals
758 triggers
.append(("always",))
760 cd
= fragment
.domains
[domain
]
761 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.clk
)))
763 triggers
.append(("posedge", compiler_state
.resolve_curr(cd
.rst
)))
765 for trigger
in triggers
:
766 with process
.sync(*trigger
) as sync
:
767 for signal
in signals
:
768 wire_curr
, wire_next
= compiler_state
.resolve(signal
)
769 sync
.update(wire_curr
, wire_next
)
771 # Finally, collect the names we've given to our ports in RTLIL, and correlate these with
772 # the signals represented by these ports. If we are a submodule, this will be necessary
773 # to create a cell for us in the parent module.
774 port_map
= OrderedDict()
775 for signal
in fragment
.ports
:
776 port_map
[compiler_state
.resolve_curr(signal
)] = signal
778 return module
.name
, port_map
781 def convert(fragment
, name
="top", **kwargs
):
782 fragment
= fragment
.prepare(**kwargs
)
784 convert_fragment(builder
, fragment
, name
=name
, top
=True)