From: Andrew Zonenberg Date: Fri, 11 Aug 2017 20:40:37 +0000 (-0700) Subject: Added opt_rmports pass (remove unconnected ports from top-level modules) X-Git-Tag: yosys-0.8~345^2~1^2~9 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cca3cb5fbbe5ba127b620be5435697fb0ee66736;p=yosys.git Added opt_rmports pass (remove unconnected ports from top-level modules) --- diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index a8b1537bb..7d54adf0f 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -6,6 +6,7 @@ OBJS += passes/opt/opt_reduce.o OBJS += passes/opt/opt_rmdff.o OBJS += passes/opt/opt_clean.o OBJS += passes/opt/opt_expr.o +OBJS += passes/opt/opt_rmports.o ifneq ($(SMALL),1) OBJS += passes/opt/share.o diff --git a/passes/opt/opt_rmports.cc b/passes/opt/opt_rmports.cc new file mode 100644 index 000000000..2fd73fff2 --- /dev/null +++ b/passes/opt/opt_rmports.cc @@ -0,0 +1,132 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/log.h" +#include +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct OptRmportsPass : public Pass { + OptRmportsPass() : Pass("opt_rmports", "remove top-level ports with no connections") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" opt_rmports\n"); + log("\n"); + log("This pass identifies ports in the top-level design which are not used or driven\n"); + log("and removes them\n"); + log("\n"); + } + + virtual void execute(std::vector /*args*/, RTLIL::Design *design) + { + log_header(design, "Executing OPT_RMPORTS pass (remove top level ports with no connections).\n"); + + //vector mods = design->modules(); + //for(auto mod : mods) + // ProcessModule(mod); + ProcessModule(design->top_module()); + } + + virtual void ProcessModule(RTLIL::Module* module) + { + log("Finding unconnected ports in module %s\n", module->name.c_str()); + + std::set used_ports; + + //See what wires are used. + //Start by checking connections between named wires + auto& conns = module->connections(); + for(auto sigsig : conns) + { + auto s1 = sigsig.first.as_wire(); + auto s2 = sigsig.second.as_wire(); + + if( (s1->port_input || s1->port_output) && (used_ports.find(s1->name) == used_ports.end()) ) + used_ports.emplace(s1->name); + + if( (s2->port_input || s2->port_output) && (used_ports.find(s2->name) == used_ports.end()) ) + used_ports.emplace(s2->name); + } + + //Then check connections to cells + auto cells = module->cells(); + for(auto cell : cells) + { + auto& cconns = cell->connections(); + for(auto conn : cconns) + { + if(!conn.second.is_wire()) + continue; + auto sig = conn.second.as_wire(); + + if( (sig->port_input || sig->port_output) && (used_ports.find(sig->name) == used_ports.end()) ) + used_ports.emplace(sig->name); + } + } + + //Now that we know what IS used, get rid of anything that isn't in that list + std::set unused_ports; + for(auto port : module->ports) + { + if(used_ports.find(port) != used_ports.end()) + continue; + unused_ports.emplace(port); + } + + //Print the ports out as we go through them + for(auto port : unused_ports) + { + log(" removing unused top-level port %s\n", port.c_str()); + + //Remove from ports list + for(size_t i=0; iports.size(); i++) + { + if(module->ports[i] == port) + { + module->ports.erase(module->ports.begin() + i); + break; + } + } + + //Mark the wire as no longer a port + auto wire = module->wire(port); + wire->port_input = false; + wire->port_output = false; + wire->port_id = 0; + } + log("Removed %zu unused top-level ports.\n", unused_ports.size()); + + //Re-number all of the wires that DO have ports still on them + for(size_t i=0; iports.size(); i++) + { + auto port = module->ports[i]; + auto wire = module->wire(port); + wire->port_id = i+1; + } + } + +} OptRmportsPass; + +PRIVATE_NAMESPACE_END