Added "yosys -D" feature
[yosys.git] / manual / CHAPTER_Prog / stubnets.cc
1 // This is free and unencumbered software released into the public domain.
2 //
3 // Anyone is free to copy, modify, publish, use, compile, sell, or
4 // distribute this software, either in source code form or as a compiled
5 // binary, for any purpose, commercial or non-commercial, and by any
6 // means.
7
8 #include "kernel/yosys.h"
9 #include "kernel/sigtools.h"
10
11 #include <string>
12 #include <map>
13 #include <set>
14
15 USING_YOSYS_NAMESPACE
16 PRIVATE_NAMESPACE_BEGIN
17
18 // this function is called for each module in the design
19 static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool report_bits)
20 {
21 // use a SigMap to convert nets to a unique representation
22 SigMap sigmap(module);
23
24 // count how many times a single-bit signal is used
25 std::map<RTLIL::SigBit, int> bit_usage_count;
26
27 // count output lines for this module (needed only for summary output at the end)
28 int line_count = 0;
29
30 log("Looking for stub wires in module %s:\n", RTLIL::id2cstr(module->name));
31
32 // For all ports on all cells
33 for (auto &cell_iter : module->cells_)
34 for (auto &conn : cell_iter.second->connections())
35 {
36 // Get the signals on the port
37 // (use sigmap to get a uniqe signal name)
38 RTLIL::SigSpec sig = sigmap(conn.second);
39
40 // add each bit to bit_usage_count, unless it is a constant
41 for (auto &bit : sig)
42 if (bit.wire != NULL)
43 bit_usage_count[bit]++;
44 }
45
46 // for each wire in the module
47 for (auto &wire_iter : module->wires_)
48 {
49 RTLIL::Wire *wire = wire_iter.second;
50
51 // .. but only selected wires
52 if (!design->selected(module, wire))
53 continue;
54
55 // add +1 usage if this wire actually is a port
56 int usage_offset = wire->port_id > 0 ? 1 : 0;
57
58 // we will record which bits of the (possibly multi-bit) wire are stub signals
59 std::set<int> stub_bits;
60
61 // get a signal description for this wire and split it into separate bits
62 RTLIL::SigSpec sig = sigmap(wire);
63
64 // for each bit (unless it is a constant):
65 // check if it is used at least two times and add to stub_bits otherwise
66 for (int i = 0; i < GetSize(sig); i++)
67 if (sig[i].wire != NULL && (bit_usage_count[sig[i]] + usage_offset) < 2)
68 stub_bits.insert(i);
69
70 // continue if no stub bits found
71 if (stub_bits.size() == 0)
72 continue;
73
74 // report stub bits and/or stub wires, don't report single bits
75 // if called with report_bits set to false.
76 if (GetSize(stub_bits) == GetSize(sig)) {
77 log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name));
78 } else {
79 if (!report_bits)
80 continue;
81 log(" found wire with stub bits: %s [", RTLIL::id2cstr(wire->name));
82 for (int bit : stub_bits)
83 log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit);
84 log("]\n");
85 }
86
87 // we have outputted a line, increment summary counter
88 line_count++;
89 }
90
91 // report summary
92 if (report_bits)
93 log(" found %d stub wires or wires with stub bits.\n", line_count);
94 else
95 log(" found %d stub wires.\n", line_count);
96 }
97
98 // each pass contains a singleton object that is derived from Pass
99 struct StubnetsPass : public Pass {
100 StubnetsPass() : Pass("stubnets") { }
101 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
102 {
103 // variables to mirror information from passed options
104 bool report_bits = 0;
105
106 log_header(design, "Executing STUBNETS pass (find stub nets).\n");
107
108 // parse options
109 size_t argidx;
110 for (argidx = 1; argidx < args.size(); argidx++) {
111 std::string arg = args[argidx];
112 if (arg == "-report_bits") {
113 report_bits = true;
114 continue;
115 }
116 break;
117 }
118
119 // handle extra options (e.g. selection)
120 extra_args(args, argidx, design);
121
122 // call find_stub_nets() for each module that is either
123 // selected as a whole or contains selected objects.
124 for (auto &it : design->modules_)
125 if (design->selected_module(it.first))
126 find_stub_nets(design, it.second, report_bits);
127 }
128 } StubnetsPass;
129
130 PRIVATE_NAMESPACE_END