From 5fc7ae9be74e87e5ad08f19a2a91c31094a8d474 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 26 Aug 2020 22:45:19 +0000 Subject: [PATCH] back.rtlil: do not squash empty modules. In commit 9faa1d37, the RTLIL backend was changed to ignore modules without ports completely, since Yosys would recognize empty modules as black boxes without explicit `write_verilog -noblackbox` and break the design. That change had many flaws: * It removed instances without ports, which are used in e.g. SoC FPGAs to instantiate a dummy CPU. * It removed fragments without ports, which can appear in e.g. SoC FPGAs in case the fabric is not connected to any I/O ports. * Finally, it was just conceptually unjustified. This commit changes the logic to actually check for empty fragments, and instead of removing them, it adds a dummy wire inside. It would be possible to use the Yosys-specific (*noblackbox*) attribute. However, it would be necessary to strip it for most targets right away, and also the wire doubles as documentation. Fixes #441. --- nmigen/back/rtlil.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 100df5a..05f219a 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -831,6 +831,11 @@ def _convert_fragment(builder, fragment, name_map, hierarchy): verilog_trigger = None verilog_trigger_sync_emitted = False + # If the fragment is completely empty, add a dummy wire to it, or Yosys will interpret + # it as a black box by default (when read as Verilog). + if not fragment.ports and not fragment.statements and not fragment.subfragments: + module.wire(1, name="$empty_module_filler") + # Register all signals driven in the current fragment. This must be done first, as it # affects further codegen; e.g. whether \sig$next signals will be generated and used. for domain, signal in fragment.iter_drivers(): @@ -855,9 +860,6 @@ def _convert_fragment(builder, fragment, name_map, hierarchy): # name) names. memories = OrderedDict() for subfragment, sub_name in fragment.subfragments: - if not subfragment.ports: - continue - if sub_name is None: sub_name = module.anonymous() -- 2.30.2