Initial adaptation of muxpack from shregmap
[yosys.git] / passes / sat / cutpoint.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 struct CutpointPass : public Pass {
27 CutpointPass() : Pass("cutpoint", "add hi/lo cover cells for each wire bit") { }
28 void help() YS_OVERRIDE
29 {
30 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
31 log("\n");
32 log(" cutpoint [options] [selection]\n");
33 log("\n");
34 log("This command adds formal cut points to the design.\n");
35 log("\n");
36 log(" -undef\n");
37 log(" set cupoint nets to undef (x). the default behavior is to create a\n");
38 log(" $anyseq cell and drive the cutpoint net from that\n");
39 log("\n");
40 }
41 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
42 {
43 bool flag_undef = false;
44
45 log_header(design, "Executing CUTPOINT pass.\n");
46
47 size_t argidx;
48 for (argidx = 1; argidx < args.size(); argidx++)
49 {
50 if (args[argidx] == "-undef") {
51 flag_undef = true;
52 continue;
53 }
54 break;
55 }
56 extra_args(args, argidx, design);
57
58 for (auto module : design->selected_modules())
59 {
60 if (design->selected_whole_module(module->name)) {
61 log("Making all outputs of module %s cut points, removing module contents.\n", log_id(module));
62 module->new_connections(std::vector<RTLIL::SigSig>());
63 for (auto cell : vector<Cell*>(module->cells()))
64 module->remove(cell);
65 vector<Wire*> output_wires;
66 for (auto wire : module->wires())
67 if (wire->port_output)
68 output_wires.push_back(wire);
69 for (auto wire : output_wires)
70 module->connect(wire, flag_undef ? Const(State::Sx, GetSize(wire)) : module->Anyseq(NEW_ID, GetSize(wire)));
71 continue;
72 }
73
74 SigMap sigmap(module);
75 pool<SigBit> cutpoint_bits;
76
77 for (auto cell : module->selected_cells()) {
78 if (cell->type == "$anyseq")
79 continue;
80 log("Removing cell %s.%s, making all cell outputs cutpoints.\n", log_id(module), log_id(cell));
81 for (auto &conn : cell->connections()) {
82 if (cell->output(conn.first))
83 module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second)));
84 }
85 module->remove(cell);
86 }
87
88 for (auto wire : module->selected_wires()) {
89 if (wire->port_output) {
90 log("Making output wire %s.%s a cutpoint.\n", log_id(module), log_id(wire));
91 Wire *new_wire = module->addWire(NEW_ID, wire);
92 module->swap_names(wire, new_wire);
93 module->connect(new_wire, flag_undef ? Const(State::Sx, GetSize(new_wire)) : module->Anyseq(NEW_ID, GetSize(new_wire)));
94 wire->port_id = 0;
95 wire->port_input = false;
96 wire->port_output = false;
97 continue;
98 }
99 log("Making wire %s.%s a cutpoint.\n", log_id(module), log_id(wire));
100 for (auto bit : sigmap(wire))
101 cutpoint_bits.insert(bit);
102 }
103
104 if (!cutpoint_bits.empty())
105 {
106 for (auto cell : module->cells()) {
107 for (auto &conn : cell->connections()) {
108 if (!cell->output(conn.first))
109 continue;
110 SigSpec sig = sigmap(conn.second);
111 int bit_count = 0;
112 for (auto &bit : sig) {
113 if (cutpoint_bits.count(bit))
114 bit_count++;
115 }
116 if (bit_count == 0)
117 continue;
118 SigSpec dummy = module->addWire(NEW_ID, bit_count);
119 bit_count = 0;
120 for (auto &bit : sig) {
121 if (cutpoint_bits.count(bit))
122 bit = dummy[bit_count++];
123 }
124 cell->setPort(conn.first, sig);
125 }
126 }
127
128 vector<Wire*> rewrite_wires;
129 for (auto wire : module->wires()) {
130 if (!wire->port_input)
131 continue;
132 int bit_count = 0;
133 for (auto &bit : sigmap(wire))
134 if (cutpoint_bits.count(bit))
135 bit_count++;
136 if (bit_count)
137 rewrite_wires.push_back(wire);
138 }
139
140 for (auto wire : rewrite_wires) {
141 Wire *new_wire = module->addWire(NEW_ID, wire);
142 SigSpec lhs, rhs, sig = sigmap(wire);
143 for (int i = 0; i < GetSize(sig); i++)
144 if (!cutpoint_bits.count(sig[i])) {
145 lhs.append(SigBit(wire, i));
146 rhs.append(SigBit(new_wire, i));
147 }
148 if (GetSize(lhs))
149 module->connect(lhs, rhs);
150 module->swap_names(wire, new_wire);
151 wire->port_id = 0;
152 wire->port_input = false;
153 wire->port_output = false;
154 }
155
156 SigSpec sig(cutpoint_bits);
157 sig.sort_and_unify();
158
159 for (auto chunk : sig.chunks()) {
160 SigSpec s(chunk);
161 module->connect(s, flag_undef ? Const(State::Sx, GetSize(s)) : module->Anyseq(NEW_ID, GetSize(s)));
162 }
163 }
164 }
165 }
166 } CutpointPass;
167
168 PRIVATE_NAMESPACE_END