2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
26 struct CutpointPass
: public Pass
{
27 CutpointPass() : Pass("cutpoint", "add hi/lo cover cells for each wire bit") { }
28 void help() YS_OVERRIDE
30 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
32 log(" cutpoint [options] [selection]\n");
34 log("This command adds formal cut points to the design.\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");
41 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
43 bool flag_undef
= false;
45 log_header(design
, "Executing CUTPOINT pass.\n");
48 for (argidx
= 1; argidx
< args
.size(); argidx
++)
50 if (args
[argidx
] == "-undef") {
56 extra_args(args
, argidx
, design
);
58 for (auto module
: design
->selected_modules())
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()))
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
)));
74 SigMap
sigmap(module
);
75 pool
<SigBit
> cutpoint_bits
;
77 for (auto cell
: module
->selected_cells()) {
78 if (cell
->type
== "$anyseq")
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
)));
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
)));
95 wire
->port_input
= false;
96 wire
->port_output
= false;
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
);
104 if (!cutpoint_bits
.empty())
106 for (auto cell
: module
->cells()) {
107 for (auto &conn
: cell
->connections()) {
108 if (!cell
->output(conn
.first
))
110 SigSpec sig
= sigmap(conn
.second
);
112 for (auto &bit
: sig
) {
113 if (cutpoint_bits
.count(bit
))
118 SigSpec dummy
= module
->addWire(NEW_ID
, bit_count
);
120 for (auto &bit
: sig
) {
121 if (cutpoint_bits
.count(bit
))
122 bit
= dummy
[bit_count
++];
124 cell
->setPort(conn
.first
, sig
);
128 vector
<Wire
*> rewrite_wires
;
129 for (auto wire
: module
->wires()) {
130 if (!wire
->port_input
)
133 for (auto &bit
: sigmap(wire
))
134 if (cutpoint_bits
.count(bit
))
137 rewrite_wires
.push_back(wire
);
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
));
149 module
->connect(lhs
, rhs
);
150 module
->swap_names(wire
, new_wire
);
152 wire
->port_input
= false;
153 wire
->port_output
= false;
156 SigSpec
sig(cutpoint_bits
);
157 sig
.sort_and_unify();
159 for (auto chunk
: sig
.chunks()) {
161 module
->connect(s
, flag_undef
? Const(State::Sx
, GetSize(s
)) : module
->Anyseq(NEW_ID
, GetSize(s
)));
168 PRIVATE_NAMESPACE_END