mirror of https://github.com/YosysHQ/yosys.git
134 lines
3.9 KiB
C++
134 lines
3.9 KiB
C++
|
// This is free and unencumbered software released into the public domain.
|
||
|
//
|
||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||
|
// distribute this software, either in source code form or as a compiled
|
||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||
|
// means.
|
||
|
|
||
|
#include "kernel/rtlil.h"
|
||
|
#include "kernel/register.h"
|
||
|
#include "kernel/sigtools.h"
|
||
|
#include "kernel/log.h"
|
||
|
|
||
|
#include <string>
|
||
|
#include <map>
|
||
|
#include <set>
|
||
|
|
||
|
// this function is called for each module in the design
|
||
|
static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool report_bits)
|
||
|
{
|
||
|
// use a SigMap to convert nets to a unique representation
|
||
|
SigMap sigmap(module);
|
||
|
|
||
|
// count how many times a single-bit signal is used
|
||
|
std::map<RTLIL::SigSpec, int> bit_usage_count;
|
||
|
|
||
|
// count ouput lines for this module (needed only for summary output at the end)
|
||
|
int line_count = 0;
|
||
|
|
||
|
log("Looking for stub wires in module %s:\n", RTLIL::id2cstr(module->name));
|
||
|
|
||
|
// For all ports on all cells
|
||
|
for (auto &cell_iter : module->cells)
|
||
|
for (auto &conn : cell_iter.second->connections)
|
||
|
{
|
||
|
// Get the signals on the port
|
||
|
// (use sigmap to get a uniqe signal name)
|
||
|
RTLIL::SigSpec sig = sigmap(conn.second);
|
||
|
|
||
|
// split the signal up into single-bit chunks
|
||
|
sig.expand();
|
||
|
|
||
|
// add each chunk to bit_usage_count, unless it is a constant
|
||
|
for (auto &c : sig.chunks)
|
||
|
if (c.wire != NULL)
|
||
|
bit_usage_count[c]++;
|
||
|
}
|
||
|
|
||
|
// for each wire in the module
|
||
|
for (auto &wire_iter : module->wires)
|
||
|
{
|
||
|
RTLIL::Wire *wire = wire_iter.second;
|
||
|
|
||
|
// .. but only selected wires
|
||
|
if (!design->selected(module, wire))
|
||
|
continue;
|
||
|
|
||
|
// add +1 usage if this wire actually is a port
|
||
|
int usage_offset = wire->port_id > 0 ? 1 : 0;
|
||
|
|
||
|
// we will record which bits of the (possibly multi-bit) wire are stub signals
|
||
|
std::set<int> stub_bits;
|
||
|
|
||
|
// get a signal description for this wire and split it into seperate bits
|
||
|
RTLIL::SigSpec sig = sigmap(wire);
|
||
|
sig.expand();
|
||
|
|
||
|
// for each bit (unless it is a constant):
|
||
|
// check if it is used at least two times and add to stub_bits otherwise
|
||
|
for (size_t i = 0; i < sig.chunks.size(); i++)
|
||
|
if (sig.chunks[i].wire != NULL && (bit_usage_count[sig.chunks[i]] +
|
||
|
usage_offset) < 2)
|
||
|
stub_bits.insert(i);
|
||
|
|
||
|
// continue if no stub bits found
|
||
|
if (stub_bits.size() == 0)
|
||
|
continue;
|
||
|
|
||
|
// report stub bits and/or stub wires, don't report single bits
|
||
|
// if called with report_bits set to false.
|
||
|
if (int(stub_bits.size()) == sig.width) {
|
||
|
log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name));
|
||
|
} else {
|
||
|
if (!report_bits)
|
||
|
continue;
|
||
|
log(" found wire with stub bits: %s [", RTLIL::id2cstr(wire->name));
|
||
|
for (int bit : stub_bits)
|
||
|
log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit);
|
||
|
log("]\n");
|
||
|
}
|
||
|
|
||
|
// we have outputted a line, increment summary counter
|
||
|
line_count++;
|
||
|
}
|
||
|
|
||
|
// report summary
|
||
|
if (report_bits)
|
||
|
log(" found %d stub wires or wires with stub bits.\n", line_count);
|
||
|
else
|
||
|
log(" found %d stub wires.\n", line_count);
|
||
|
}
|
||
|
|
||
|
// each pass contains a singleton object that is derived from Pass
|
||
|
struct StubnetsPass : public Pass {
|
||
|
StubnetsPass() : Pass("stubnets") { }
|
||
|
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
|
||
|
{
|
||
|
// variables to mirror information from passed options
|
||
|
bool report_bits = 0;
|
||
|
|
||
|
log_header("Executing STUBNETS pass (find stub nets).\n");
|
||
|
|
||
|
// parse options
|
||
|
size_t argidx;
|
||
|
for (argidx = 1; argidx < args.size(); argidx++) {
|
||
|
std::string arg = args[argidx];
|
||
|
if (arg == "-report_bits") {
|
||
|
report_bits = true;
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// handle extra options (e.g. selection)
|
||
|
extra_args(args, argidx, design);
|
||
|
|
||
|
// call find_stub_nets() for each module that is either
|
||
|
// selected as a whole or contains selected objects.
|
||
|
for (auto &it : design->modules)
|
||
|
if (design->selected_module(it.first))
|
||
|
find_stub_nets(design, it.second, report_bits);
|
||
|
}
|
||
|
} StubnetsPass;
|
||
|
|