103db533f0f049001cd2670f1f408c0500472e29
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
<< " \"version\": \"0.0.0\",\n";
84 f
<< " \"modules\": [\n";
87 for (auto mod
: _use_selection
? design
->selected_modules() : design
->modules()) {
101 void write_module(Module
* mod
)
103 log_assert(mod
!= nullptr);
108 f
<< stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(mod
->name
)).c_str());
109 f
<< " \"cell_sorts\": [\n";
111 bool first_sort
{true};
112 for (auto& sort
: _cells
) {
116 write_cell_sort(sort
);
123 f
<< " \"connections\": [\n";
130 void write_cell_sort(std::pair
<const std::string
, std::vector
<Cell
*>>& sort
)
132 const auto port_cell
= sort
.second
.front();
135 f
<< stringf(" \"type\": %s,\n", sort
.first
.c_str());
136 f
<< " \"ports\": [\n";
138 bool first_port
{true};
139 for (auto con
: port_cell
->connections()) {
144 f
<< stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(con
.first
)).c_str());
145 f
<< " \"direction\": \"";
146 if (port_cell
->input(con
.first
))
148 if (port_cell
->input(con
.first
))
151 if (con
.second
.size() == 1)
152 f
<< " \"range\": [0, 0]\n";
154 f
<< stringf(" \"range\": [%d, %d]\n", con
.second
.size(), 0);
161 f
<< " ],\n \"cells\": [\n";
162 bool first_cell
{true};
163 for (auto& cell
: sort
.second
) {
176 void write_param_val(const Const
& v
)
178 if ((v
.flags
& RTLIL::ConstFlags::CONST_FLAG_STRING
) == RTLIL::ConstFlags::CONST_FLAG_STRING
) {
179 const auto str
= v
.decode_string();
182 f
<< get_string(str
);
183 } else if ((v
.flags
& RTLIL::ConstFlags::CONST_FLAG_SIGNED
) == RTLIL::ConstFlags::CONST_FLAG_SIGNED
) {
184 f
<< stringf("\"%dsd %d\"", v
.size(), v
.as_int());
185 } else if ((v
.flags
& RTLIL::ConstFlags::CONST_FLAG_REAL
) == RTLIL::ConstFlags::CONST_FLAG_REAL
) {
188 f
<< get_string(v
.as_string());
192 void write_cell(Cell
* cell
)
194 log_assert(cell
!= nullptr);
197 f
<< stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(cell
->name
)).c_str());
198 f
<< " \"attributes\": {\n";
200 bool first_attr
{true};
201 for (auto& attr
: cell
->attributes
) {
204 const auto attr_val
= attr
.second
;
205 if (!attr_val
.empty()) {
206 f
<< stringf(" %s: ", get_string(RTLIL::unescape_id(attr
.first
)).c_str());
207 write_param_val(attr_val
);
209 f
<< stringf(" %s: true", get_string(RTLIL::unescape_id(attr
.first
)).c_str());
217 f
<< " \"parameters\": {\n";
219 bool first_param
{true};
220 for (auto& param
: cell
->parameters
) {
223 const auto param_val
= param
.second
;
224 if (!param_val
.empty()) {
225 f
<< stringf(" %s: ", get_string(RTLIL::unescape_id(param
.first
)).c_str());
226 write_param_val(param_val
);
228 f
<< stringf(" %s: true", get_string(RTLIL::unescape_id(param
.first
)).c_str());
240 struct MetadataBackend
: public Backend
{
241 MetadataBackend() : Backend("metadata", "generate design metadata") { }
244 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
246 log(" metadata [options] [selection]\n");
248 log("Write a JSON metadata for the current design\n");
253 void execute(std::ostream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
) override
256 extra_args(f
, filename
, args
, argidx
);
258 log_header(design
, "Executing metadata backend.\n");
260 MetadataWriter
metadata_writier(*f
, false);
261 metadata_writier
.write_metadata(design
);
267 struct MetadataPass
: public Pass
{
268 MetadataPass() : Pass("metadata", "write design metadata") { }
272 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
274 log(" metadata [options] [selection]\n");
276 log("Write a JSON metadata for the current design\n");
278 log(" -o <filename>\n");
279 log(" write to the specified file.\n");
281 log("See 'help write_metadata' for a description of the JSON format used.\n");
284 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
286 std::string filename
{};
289 for (argidx
= 1; argidx
< args
.size(); argidx
++)
291 if (args
[argidx
] == "-o" && argidx
+1 < args
.size()) {
292 filename
= args
[++argidx
];
297 extra_args(args
, argidx
, design
);
300 std::stringstream buf
;
302 if (!filename
.empty()) {
303 rewrite_filename(filename
);
304 std::ofstream
*ff
= new std::ofstream
;
305 ff
->open(filename
.c_str(), std::ofstream::trunc
);
308 log_error("Can't open file `%s' for writing: %s\n", filename
.c_str(), strerror(errno
));
316 MetadataWriter
metadata_writier(*f
, false);
317 metadata_writier
.write_metadata(design
);
319 if (!filename
.empty()) {
322 log("%s", buf
.str().c_str());
328 PRIVATE_NAMESPACE_END