diff options
author | Andrew Zonenberg <azonenberg@drawersteak.com> | 2017-08-11 13:40:37 -0700 |
---|---|---|
committer | Andrew Zonenberg <azonenberg@drawersteak.com> | 2017-08-14 10:27:59 -0700 |
commit | cca3cb5fbbe5ba127b620be5435697fb0ee66736 (patch) | |
tree | 30736ee459096beb96c502a767a1bd2cf586680f /passes | |
parent | 007f29b9c221ab1a8931de863517d6990218970d (diff) | |
download | yosys-cca3cb5fbbe5ba127b620be5435697fb0ee66736.tar.gz yosys-cca3cb5fbbe5ba127b620be5435697fb0ee66736.tar.bz2 yosys-cca3cb5fbbe5ba127b620be5435697fb0ee66736.zip |
Added opt_rmports pass (remove unconnected ports from top-level modules)
Diffstat (limited to 'passes')
-rw-r--r-- | passes/opt/Makefile.inc | 1 | ||||
-rw-r--r-- | passes/opt/opt_rmports.cc | 132 |
2 files changed, 133 insertions, 0 deletions
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 <clifford@clifford.at> + * + * 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 <stdlib.h> +#include <stdio.h> + +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<std::string> /*args*/, RTLIL::Design *design) + { + log_header(design, "Executing OPT_RMPORTS pass (remove top level ports with no connections).\n"); + + //vector<RTLIL::Module*> 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<RTLIL::IdString> 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<RTLIL::IdString> 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; i<module->ports.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; i<module->ports.size(); i++) + { + auto port = module->ports[i]; + auto wire = module->wire(port); + wire->port_id = i+1; + } + } + +} OptRmportsPass; + +PRIVATE_NAMESPACE_END |