From 1b9b594f52b603a0f354e8ea246d34ceafca122a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 21 Jul 2026 19:20:28 +0200 Subject: [PATCH] rtlil: resolve positional cell ports before giving up on a direction Until `hierarchy` runs, a connection made by position is named `$` rather than after the port it reaches, so looking it up by name in the instantiated module finds nothing and port_dir() reports PD_UNKNOWN. The signorm index reads that as "not an input", which makes the cell claim a driver on a net it only reads. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MQU5XCqDYY8MbivGkNRrDo --- kernel/rtlil.cc | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d053369a6..e77ad14fb 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -5213,13 +5213,32 @@ bool RTLIL::Cell::known() const return false; } +// Find the port a connection names in the module the cell instantiates. Until +// `hierarchy` runs, a connection made by position is named `$` instead +// of after the port it reaches, and looking that up by name finds nothing -- +// which would leave even a plain input port's direction unknown. +static RTLIL::Wire *find_port(RTLIL::Module *m, TwineRef portname) +{ + if (m == nullptr) + return nullptr; + if (RTLIL::Wire *w = m->wire(portname)) + return w; + + std::string name = m->design->twines.str(portname); + if (name.size() < 2 || name[0] != '$' || name[1] < '0' || name[1] > '9') + return nullptr; + int port_id = atoi(name.c_str() + 1); + if (port_id < 1 || port_id > GetSize(m->ports)) + return nullptr; + return m->wire(m->ports[port_id - 1]); +} + bool RTLIL::Cell::input(TwineRef portname) const { if (yosys_celltypes.cell_known(type_impl)) return yosys_celltypes.cell_input(type_impl, portname); if (module && module->design) { - RTLIL::Module *m = module->design->module(type_impl); - RTLIL::Wire *w = m ? m->wire(portname) : nullptr; + RTLIL::Wire *w = find_port(module->design->module(type_impl), portname); return w && w->port_input; } return false; @@ -5230,8 +5249,7 @@ bool RTLIL::Cell::output(TwineRef portname) const if (yosys_celltypes.cell_known(type_impl)) return yosys_celltypes.cell_output(type_impl, portname); if (module && module->design) { - RTLIL::Module *m = module->design->module(type_impl); - RTLIL::Wire *w = m ? m->wire(portname) : nullptr; + RTLIL::Wire *w = find_port(module->design->module(type_impl), portname); return w && w->port_output; } return false; @@ -5242,10 +5260,7 @@ RTLIL::PortDir RTLIL::Cell::port_dir(TwineRef portname) const if (yosys_celltypes.cell_known(type_impl)) return yosys_celltypes.cell_port_dir(type_impl, portname); if (module && module->design) { - RTLIL::Module *m = module->design->module(type_impl); - if (m == nullptr) - return PortDir::PD_UNKNOWN; - RTLIL::Wire *w = m->wire(portname); + RTLIL::Wire *w = find_port(module->design->module(type_impl), portname); if (w == nullptr) return PortDir::PD_UNKNOWN; return PortDir(w->port_input + w->port_output * 2);