2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Aki "lethalbit" Van Ness <aki@yosyshq.com> <aki@lethalbit.net>
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 // MYAU - Metadata for Yosys-Assisted Utilities
22 #include "kernel/rtlil.h"
23 #include "kernel/register.h"
24 #include "kernel/sigtools.h"
25 #include "kernel/celltypes.h"
26 #include "kernel/cellaigs.h"
27 #include "kernel/log.h"
29 #include <unordered_map>
33 PRIVATE_NAMESPACE_BEGIN
41 std::unordered_map
<std::string
, std::vector
<Cell
*>> _cells
{};
43 // XXX(aki): this was pulled from the json backend, needs to be pulled
44 // out possibly into some sort of utilities file, or integrated into rtlil.h
46 string
get_string(string str
)
57 // XXX(aki): I know this is far from ideal but i'm out of spoons and cant focus so
58 // it'll have to do for now,
59 void coalesce_cells(Module
* mod
)
61 for (auto cell
: mod
->cells()) {
62 const auto cell_type
= get_string(RTLIL::unescape_id(cell
->type
));
64 if (_cells
.find(cell_type
) == _cells
.end())
65 _cells
.emplace(cell_type
, std::vector
<Cell
*>());
67 _cells
.at(cell_type
).push_back(cell
);
72 MetadataWriter(std::ostream
&f
, bool use_selection
) noexcept
: f(f
), _use_selection(use_selection
) { }
74 void write_metadata(Design
*design
)
76 log_assert(design
!= nullptr);
81 f
<< stringf(" \"generator\": %s,\n", get_string(yosys_version_str
).c_str());
82 // XXX(aki): Replace this with a proper version info eventually:tm:
83 f
<< stringf(" \"version\": \"0.0.0\",\n");
84 f
<< stringf(" \"modules\": [\n");
87 for (auto mod
: _use_selection
? design
->selected_modules() : design
->modules()) {
101 void write_module(Module
* mod
)
103 log_assert(mod
!= nullptr);
107 f
<< stringf(" {\n");
108 f
<< stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(mod
->name
)).c_str());
109 f
<< stringf(" \"cell_sorts\": [\n");
111 bool first_sort
{true};
112 for (auto& sort
: _cells
) {
116 write_cell_sort(sort
);
122 f
<< stringf(" ],\n");
123 f
<< stringf(" \"connections\": [\n");
125 f
<< stringf(" ]\n");
130 void write_cell_sort(std::pair
<const std::string
, std::vector
<Cell
*>>& sort
)
132 const auto port_cell
= sort
.second
.front();
134 f
<< stringf(" {\n");
135 f
<< stringf(" \"type\": %s,\n", sort
.first
.c_str());
136 f
<< stringf(" \"ports\": [\n");
138 bool first_port
{true};
139 for (auto con
: port_cell
->connections()) {
143 f
<< stringf(" {\n");
144 f
<< stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(con
.first
)).c_str());
145 f
<< stringf(" \"direction\": \"");
146 if (port_cell
->input(con
.first
))
148 if (port_cell
->input(con
.first
))
150 f
<< stringf("\",\n");
151 if (con
.second
.size() == 1)
152 f
<< stringf(" \"range\": [0, 0]\n");
154 f
<< stringf(" \"range\": [%d, %d]\n", con
.second
.size(), 0);
161 f
<< stringf(" ],\n \"cells\": [\n");
162 bool first_cell
{true};
163 for (auto& cell
: sort
.second
) {
172 f
<< stringf(" ]\n");
176 void write_cell(Cell
* cell
)
178 log_assert(cell
!= nullptr);
180 f
<< stringf(" {\n");
181 f
<< stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(cell
->name
)).c_str());
182 f
<< stringf(" \"attributes\": {\n");
184 bool first_attr
{true};
185 for (auto& attr
: cell
->attributes
) {
188 const auto attr_val
= attr
.second
.decode_string();
189 if (attr_val
.size() > 0)
190 f
<< stringf(" %s: \"%s\"\n", get_string(RTLIL::unescape_id(attr
.first
)).c_str(), attr_val
.c_str());
192 f
<< stringf(" %s: true\n", get_string(RTLIL::unescape_id(attr
.first
)).c_str());
197 f
<< stringf(" },\n");
198 f
<< stringf(" \"parameters\": {\n");
200 bool first_param
{true};
201 for (auto& param
: cell
->parameters
) {
204 const auto param_val
= param
.second
.decode_string();
205 if (param_val
.size() > 0)
206 f
<< stringf(" %s: \"%s\"\n", get_string(RTLIL::unescape_id(param
.first
)).c_str(), param_val
.c_str());
208 f
<< stringf(" %s: true\n", get_string(RTLIL::unescape_id(param
.first
)).c_str());
213 f
<< stringf(" },\n");
218 struct MetadataBackend
: public Backend
{
219 MetadataBackend() : Backend("metadata", "generate design metadata") { }
222 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
224 log(" metadata [options] [selection]\n");
226 log("Write a JSON metadata for the current design\n");
231 void execute(std::ostream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
) override
234 extra_args(f
, filename
, args
, argidx
);
236 log_header(design
, "Executing metadata backend.\n");
238 MetadataWriter
metadata_writier(*f
, false);
239 metadata_writier
.write_metadata(design
);
245 struct MetadataPass
: public Pass
{
246 MetadataPass() : Pass("metadata", "write design metadata") { }
250 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
252 log(" metadata [options] [selection]\n");
254 log("Write a JSON metadata for the current design\n");
256 log(" -o <filename>\n");
257 log(" write to the specified file.\n");
259 log("See 'help write_metadata' for a description of the JSON format used.\n");
262 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
264 std::string filename
{};
267 for (argidx
= 1; argidx
< args
.size(); argidx
++)
269 if (args
[argidx
] == "-o" && argidx
+1 < args
.size()) {
270 filename
= args
[++argidx
];
275 extra_args(args
, argidx
, design
);
278 std::stringstream buf
;
280 if (!filename
.empty()) {
281 rewrite_filename(filename
);
282 std::ofstream
*ff
= new std::ofstream
;
283 ff
->open(filename
.c_str(), std::ofstream::trunc
);
286 log_error("Can't open file `%s' for writing: %s\n", filename
.c_str(), strerror(errno
));
294 MetadataWriter
metadata_writier(*f
, false);
295 metadata_writier
.write_metadata(design
);
297 if (!filename
.empty()) {
300 log("%s", buf
.str().c_str());
306 PRIVATE_NAMESPACE_END