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/rtlil.h"
21 #include "kernel/register.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/celltypes.h"
24 #include "kernel/log.h"
28 PRIVATE_NAMESPACE_BEGIN
30 static std::string
netname(std::set
<std::string
> &conntypes_code
, std::set
<std::string
> &celltypes_code
, std::set
<std::string
> &constcells_code
, RTLIL::SigSpec sig
)
32 if (!sig
.is_fully_const() && !sig
.is_wire())
33 log_error("Can't export composite or non-word-wide signal %s.\n", log_signal(sig
));
35 conntypes_code
.insert(stringf("conntype b%d %d 2 %d\n", sig
.size(), sig
.size(), sig
.size()));
37 if (sig
.is_fully_const()) {
38 celltypes_code
.insert(stringf("celltype CONST_%d b%d *CONST cfg:%d VALUE\n", sig
.size(), sig
.size(), sig
.size()));
39 constcells_code
.insert(stringf("node CONST_%d_0x%x CONST_%d CONST CONST_%d_0x%x VALUE 0x%x\n",
40 sig
.size(), sig
.as_int(), sig
.size(), sig
.size(), sig
.as_int(), sig
.as_int()));
41 return stringf("CONST_%d_0x%x", sig
.size(), sig
.as_int());
44 return RTLIL::unescape_id(sig
.as_wire()->name
);
47 struct IntersynthBackend
: public Backend
{
48 IntersynthBackend() : Backend("intersynth", "write design to InterSynth netlist file") { }
49 void help() YS_OVERRIDE
51 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
53 log(" write_intersynth [options] [filename]\n");
55 log("Write the current design to an 'intersynth' netlist file. InterSynth is\n");
56 log("a tool for Coarse-Grain Example-Driven Interconnect Synthesis.\n");
59 log(" do not generate celltypes and conntypes commands. i.e. just output\n");
60 log(" the netlists. this is used for postsilicon synthesis.\n");
62 log(" -lib <verilog_or_ilang_file>\n");
63 log(" Use the specified library file for determining whether cell ports are\n");
64 log(" inputs or outputs. This option can be used multiple times to specify\n");
65 log(" more than one library.\n");
68 log(" only write selected modules. modules must be selected entirely or\n");
69 log(" not at all.\n");
71 log("http://www.clifford.at/intersynth/\n");
74 void execute(std::ostream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
76 log_header(design
, "Executing INTERSYNTH backend.\n");
79 std::vector
<std::string
> libfiles
;
80 std::vector
<RTLIL::Design
*> libs
;
81 bool flag_notypes
= false;
82 bool selected
= false;
85 for (argidx
= 1; argidx
< args
.size(); argidx
++)
87 if (args
[argidx
] == "-notypes") {
91 if (args
[argidx
] == "-lib" && argidx
+1 < args
.size()) {
92 libfiles
.push_back(args
[++argidx
]);
95 if (args
[argidx
] == "-selected") {
101 extra_args(f
, filename
, args
, argidx
);
103 log("Output filename: %s\n", filename
.c_str());
105 for (auto filename
: libfiles
) {
107 f
.open(filename
.c_str());
109 log_error("Can't open lib file `%s'.\n", filename
.c_str());
110 RTLIL::Design
*lib
= new RTLIL::Design
;
111 Frontend::frontend_call(lib
, &f
, filename
, (filename
.size() > 3 && filename
.substr(filename
.size()-3) == ".il") ? "ilang" : "verilog");
116 log_header(design
, "Continuing INTERSYNTH backend.\n");
118 std::set
<std::string
> conntypes_code
, celltypes_code
;
119 std::string netlists_code
;
120 CellTypes
ct(design
);
122 for (auto lib
: libs
)
123 ct
.setup_design(lib
);
125 for (auto module_it
: design
->modules_
)
127 RTLIL::Module
*module
= module_it
.second
;
128 SigMap
sigmap(module
);
130 if (module
->get_blackbox_attribute())
132 if (module
->memories
.size() == 0 && module
->processes
.size() == 0 && module
->cells_
.size() == 0)
135 if (selected
&& !design
->selected_whole_module(module
->name
)) {
136 if (design
->selected_module(module
->name
))
137 log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(module
->name
));
141 log("Generating netlist %s.\n", RTLIL::id2cstr(module
->name
));
143 if (module
->memories
.size() != 0 || module
->processes
.size() != 0)
144 log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n");
146 std::set
<std::string
> constcells_code
;
147 netlists_code
+= stringf("# Netlist of module %s\n", RTLIL::id2cstr(module
->name
));
148 netlists_code
+= stringf("netlist %s\n", RTLIL::id2cstr(module
->name
));
150 // Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports
151 for (auto wire_it
: module
->wires_
) {
152 RTLIL::Wire
*wire
= wire_it
.second
;
153 if (wire
->port_input
|| wire
->port_output
) {
154 celltypes_code
.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n",
155 RTLIL::id2cstr(wire
->name
), wire
->width
, wire
->port_input
? "*" : "",
156 wire
->port_input
? "input" : "output", RTLIL::id2cstr(wire
->name
), wire
->width
, RTLIL::id2cstr(wire
->name
)));
157 netlists_code
+= stringf("node %s %s PORT %s\n", RTLIL::id2cstr(wire
->name
), RTLIL::id2cstr(wire
->name
),
158 netname(conntypes_code
, celltypes_code
, constcells_code
, sigmap(wire
)).c_str());
162 // Submodules: "std::set<string> celltypes_code" prevents duplicate cell types
163 for (auto cell_it
: module
->cells_
)
165 RTLIL::Cell
*cell
= cell_it
.second
;
166 std::string celltype_code
, node_code
;
168 if (!ct
.cell_known(cell
->type
))
169 log_error("Found unknown cell type %s in module!\n", RTLIL::id2cstr(cell
->type
));
171 celltype_code
= stringf("celltype %s", RTLIL::id2cstr(cell
->type
));
172 node_code
= stringf("node %s %s", RTLIL::id2cstr(cell
->name
), RTLIL::id2cstr(cell
->type
));
173 for (auto &port
: cell
->connections()) {
174 RTLIL::SigSpec sig
= sigmap(port
.second
);
175 if (sig
.size() != 0) {
176 conntypes_code
.insert(stringf("conntype b%d %d 2 %d\n", sig
.size(), sig
.size(), sig
.size()));
177 celltype_code
+= stringf(" b%d %s%s", sig
.size(), ct
.cell_output(cell
->type
, port
.first
) ? "*" : "", RTLIL::id2cstr(port
.first
));
178 node_code
+= stringf(" %s %s", RTLIL::id2cstr(port
.first
), netname(conntypes_code
, celltypes_code
, constcells_code
, sig
).c_str());
181 for (auto ¶m
: cell
->parameters
) {
182 celltype_code
+= stringf(" cfg:%d %s", int(param
.second
.bits
.size()), RTLIL::id2cstr(param
.first
));
183 if (param
.second
.bits
.size() != 32) {
184 node_code
+= stringf(" %s '", RTLIL::id2cstr(param
.first
));
185 for (int i
= param
.second
.bits
.size()-1; i
>= 0; i
--)
186 node_code
+= param
.second
.bits
[i
] == State::S1
? "1" : "0";
188 node_code
+= stringf(" %s 0x%x", RTLIL::id2cstr(param
.first
), param
.second
.as_int());
191 celltypes_code
.insert(celltype_code
+ "\n");
192 netlists_code
+= node_code
+ "\n";
195 if (constcells_code
.size() > 0)
196 netlists_code
+= "# constant cells\n";
197 for (auto code
: constcells_code
)
198 netlists_code
+= code
;
199 netlists_code
+= "\n";
203 *f
<< stringf("### Connection Types\n");
204 for (auto code
: conntypes_code
)
205 *f
<< stringf("%s", code
.c_str());
206 *f
<< stringf("\n### Cell Types\n");
207 for (auto code
: celltypes_code
)
208 *f
<< stringf("%s", code
.c_str());
210 *f
<< stringf("\n### Netlists\n");
211 *f
<< stringf("%s", netlists_code
.c_str());
213 for (auto lib
: libs
)
220 PRIVATE_NAMESPACE_END