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/register.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/rtlil.h"
23 #include "kernel/log.h"
26 PRIVATE_NAMESPACE_BEGIN
28 struct ConnwrappersWorker
31 // key: celltype, portname;
32 std::string widthparam
, signparam
;
36 std::set
<RTLIL::IdString
> decl_celltypes
;
37 std::map
<std::pair
<RTLIL::IdString
, RTLIL::IdString
>, portdecl_t
> decls
;
39 void add_port(std::string celltype
, std::string portname
, std::string widthparam
, std::string signparam
)
41 std::pair
<std::string
, std::string
> key(RTLIL::escape_id(celltype
), RTLIL::escape_id(portname
));
42 decl_celltypes
.insert(key
.first
);
45 log_cmd_error("Duplicate port decl: %s %s\n", celltype
.c_str(), portname
.c_str());
48 decl
.widthparam
= RTLIL::escape_id(widthparam
);
49 decl
.signparam
= RTLIL::escape_id(signparam
);
50 decl
.is_signed
= false;
54 void add_port(std::string celltype
, std::string portname
, std::string widthparam
, bool is_signed
)
56 std::pair
<std::string
, std::string
> key(RTLIL::escape_id(celltype
), RTLIL::escape_id(portname
));
57 decl_celltypes
.insert(key
.first
);
60 log_cmd_error("Duplicate port decl: %s %s\n", celltype
.c_str(), portname
.c_str());
63 decl
.widthparam
= RTLIL::escape_id(widthparam
);
64 decl
.is_signed
= is_signed
;
68 void work(RTLIL::Module
*module
)
70 std::map
<RTLIL::SigBit
, std::pair
<bool, RTLIL::SigSpec
>> extend_map
;
71 SigMap
sigmap(module
);
73 for (auto cell
: module
->cells())
75 if (!decl_celltypes
.count(cell
->type
))
78 for (auto &conn
: cell
->connections())
80 std::pair
<RTLIL::IdString
, RTLIL::IdString
> key(cell
->type
, conn
.first
);
82 if (!decls
.count(key
))
85 portdecl_t
&decl
= decls
.at(key
);
87 if (!cell
->parameters
.count(decl
.widthparam
))
90 if (!decl
.signparam
.empty() && !cell
->parameters
.count(decl
.signparam
))
93 int inner_width
= cell
->parameters
.at(decl
.widthparam
).as_int();
94 int outer_width
= conn
.second
.size();
95 bool is_signed
= decl
.signparam
.empty() ? decl
.is_signed
: cell
->parameters
.at(decl
.signparam
).as_bool();
97 if (inner_width
>= outer_width
)
100 RTLIL::SigSpec sig
= sigmap(conn
.second
);
101 extend_map
[sig
.extract(inner_width
- 1, 1)] = std::pair
<bool, RTLIL::SigSpec
>(is_signed
,
102 sig
.extract(inner_width
, outer_width
- inner_width
));
106 for (auto cell
: module
->selected_cells())
108 for (auto &conn
: cell
->connections_
)
110 std::vector
<RTLIL::SigBit
> sigbits
= sigmap(conn
.second
).to_sigbit_vector();
111 RTLIL::SigSpec old_sig
;
113 for (size_t i
= 0; i
< sigbits
.size(); i
++)
115 if (!extend_map
.count(sigbits
[i
]))
118 bool is_signed
= extend_map
.at(sigbits
[i
]).first
;
119 RTLIL::SigSpec extend_sig
= extend_map
.at(sigbits
[i
]).second
;
121 int extend_width
= 0;
122 RTLIL::SigBit extend_bit
= is_signed
? sigbits
[i
] : RTLIL::SigBit(RTLIL::State::S0
);
123 while (extend_width
< extend_sig
.size() && i
+ extend_width
+ 1 < sigbits
.size() &&
124 sigbits
[i
+ extend_width
+ 1] == extend_bit
) extend_width
++;
126 if (extend_width
== 0)
129 if (old_sig
.size() == 0)
130 old_sig
= conn
.second
;
132 conn
.second
.replace(i
+1, extend_sig
.extract(0, extend_width
));
137 log("Connected extended bits of %s.%s:%s: %s -> %s\n", log_id(module
->name
), log_id(cell
->name
),
138 log_id(conn
.first
), log_signal(old_sig
), log_signal(conn
.second
));
144 struct ConnwrappersPass
: public Pass
{
145 ConnwrappersPass() : Pass("connwrappers", "match width of input-output port pairs") { }
146 void help() YS_OVERRIDE
148 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
150 log(" connwrappers [options] [selection]\n");
152 log("Wrappers are used in coarse-grain synthesis to wrap cells with smaller ports\n");
153 log("in wrapper cells with a (larger) constant port size. I.e. the upper bits\n");
154 log("of the wrapper output are signed/unsigned bit extended. This command uses this\n");
155 log("knowledge to rewire the inputs of the driven cells to match the output of\n");
156 log("the driving cell.\n");
158 log(" -signed <cell_type> <port_name> <width_param>\n");
159 log(" -unsigned <cell_type> <port_name> <width_param>\n");
160 log(" consider the specified signed/unsigned wrapper output\n");
162 log(" -port <cell_type> <port_name> <width_param> <sign_param>\n");
163 log(" use the specified parameter to decide if signed or unsigned\n");
165 log("The options -signed, -unsigned, and -port can be specified multiple times.\n");
168 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
170 ConnwrappersWorker worker
;
173 for (argidx
= 1; argidx
< args
.size(); argidx
++)
175 if (args
[argidx
] == "-signed" && argidx
+3 < args
.size()) {
176 worker
.add_port(args
[argidx
+1], args
[argidx
+2], args
[argidx
+3], true);
180 if (args
[argidx
] == "-unsigned" && argidx
+3 < args
.size()) {
181 worker
.add_port(args
[argidx
+1], args
[argidx
+2], args
[argidx
+3], false);
185 if (args
[argidx
] == "-port" && argidx
+4 < args
.size()) {
186 worker
.add_port(args
[argidx
+1], args
[argidx
+2], args
[argidx
+3], args
[argidx
+4]);
192 extra_args(args
, argidx
, design
);
194 log_header(design
, "Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n");
196 for (auto module
: design
->selected_modules())
201 PRIVATE_NAMESPACE_END