1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// 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::SigBit, 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);
// add each bit to bit_usage_count, unless it is a constant
for (auto &bit : sig)
if (bit.wire != NULL)
bit_usage_count[bit]++;
}
// 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);
// for each bit (unless it is a constant):
// check if it is used at least two times and add to stub_bits otherwise
for (int i = 0; i < SIZE(sig); i++)
if (sig[i].wire != NULL && (bit_usage_count[sig[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 (SIZE(stub_bits) == SIZE(sig)) {
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;
|