mirror of https://github.com/YosysHQ/yosys.git
pass jny: large chunk of refactoring to make the JSON output more pretty and the internals less of a spaghetti nightmare
This commit is contained in:
parent
0e20619189
commit
587f31b9a3
|
@ -66,10 +66,21 @@ struct JnyWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX(aki): this is a lazy way to do this i know,,,
|
||||||
|
std::string gen_indent(const uint16_t level)
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
for (uint16_t i = 0; i <= level; ++i)
|
||||||
|
{
|
||||||
|
s << " ";
|
||||||
|
}
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JnyWriter(std::ostream &f, bool use_selection) noexcept: f(f), _use_selection(use_selection) { }
|
JnyWriter(std::ostream &f, bool use_selection) noexcept: f(f), _use_selection(use_selection) { }
|
||||||
|
|
||||||
void write_metadata(Design *design)
|
void write_metadata(Design *design, uint16_t indent_level = 0)
|
||||||
{
|
{
|
||||||
log_assert(design != nullptr);
|
log_assert(design != nullptr);
|
||||||
|
|
||||||
|
@ -85,97 +96,109 @@ struct JnyWriter
|
||||||
for (auto mod : _use_selection ? design->selected_modules() : design->modules()) {
|
for (auto mod : _use_selection ? design->selected_modules() : design->modules()) {
|
||||||
if (!first)
|
if (!first)
|
||||||
f << ",\n";
|
f << ",\n";
|
||||||
write_module(mod);
|
write_module(mod, indent_level + 2);
|
||||||
|
|
||||||
f << "\n";
|
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f << "\n";
|
||||||
f << " ]\n";
|
f << " ]\n";
|
||||||
f << "}\n";
|
f << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_module(Module* mod)
|
void write_module(Module* mod, uint16_t indent_level = 0) {
|
||||||
{
|
|
||||||
log_assert(mod != nullptr);
|
log_assert(mod != nullptr);
|
||||||
|
|
||||||
coalesce_cells(mod);
|
coalesce_cells(mod);
|
||||||
|
|
||||||
f << " {\n";
|
const auto _indent = gen_indent(indent_level);
|
||||||
f << stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(mod->name)).c_str());
|
|
||||||
f << " \"cell_sorts\": [\n";
|
f << _indent << "{\n";
|
||||||
|
f << stringf(" %s\"name\": %s,\n", _indent.c_str(), get_string(RTLIL::unescape_id(mod->name)).c_str());
|
||||||
|
f << _indent << " \"cell_sorts\": [\n";
|
||||||
|
|
||||||
bool first_sort{true};
|
bool first_sort{true};
|
||||||
for (auto& sort : _cells) {
|
for (auto& sort : _cells) {
|
||||||
if (!first_sort)
|
if (!first_sort)
|
||||||
f << ",\n";
|
f << ",\n";
|
||||||
|
write_cell_sort(sort, indent_level + 2);
|
||||||
write_cell_sort(sort);
|
|
||||||
|
|
||||||
first_sort = false;
|
first_sort = false;
|
||||||
}
|
}
|
||||||
f << "\n";
|
f << "\n";
|
||||||
|
|
||||||
f << " ],\n";
|
f << _indent << " ],\n";
|
||||||
f << " \"connections\": [\n";
|
f << _indent << " \"connections\": [\n";
|
||||||
|
|
||||||
f << " ]\n";
|
f << _indent << " ],\n";
|
||||||
f << " }";
|
f << _indent << " \"attributes\": {\n";
|
||||||
|
|
||||||
|
write_prams(mod->attributes, indent_level + 2);
|
||||||
|
|
||||||
|
f << "\n";
|
||||||
|
|
||||||
|
f << _indent << " }\n";
|
||||||
|
f << _indent << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_cell_ports(RTLIL::Cell* port_cell, uint64_t indent_level = 0) {
|
||||||
void write_cell_sort(std::pair<const std::string, std::vector<Cell*>>& sort)
|
const auto _indent = gen_indent(indent_level);
|
||||||
{
|
|
||||||
const auto port_cell = sort.second.front();
|
|
||||||
|
|
||||||
f << " {\n";
|
|
||||||
f << stringf(" \"type\": %s,\n", sort.first.c_str());
|
|
||||||
f << " \"ports\": [\n";
|
|
||||||
|
|
||||||
bool first_port{true};
|
bool first_port{true};
|
||||||
for (auto con : port_cell->connections()) {
|
for (auto con : port_cell->connections()) {
|
||||||
if (!first_port)
|
if (!first_port)
|
||||||
f << ",\n";
|
f << ",\n";
|
||||||
|
|
||||||
f << " {\n";
|
f << _indent << " {\n";
|
||||||
f << stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(con.first)).c_str());
|
f << stringf(" %s\"name\": %s,\n", _indent.c_str(), get_string(RTLIL::unescape_id(con.first)).c_str());
|
||||||
f << " \"direction\": \"";
|
f << _indent << " \"direction\": \"";
|
||||||
if (port_cell->input(con.first))
|
if (port_cell->input(con.first))
|
||||||
f << "i";
|
f << "i";
|
||||||
if (port_cell->input(con.first))
|
if (port_cell->input(con.first))
|
||||||
f << "o";
|
f << "o";
|
||||||
f << "\",\n";
|
f << "\",\n";
|
||||||
if (con.second.size() == 1)
|
if (con.second.size() == 1)
|
||||||
f << " \"range\": [0, 0]\n";
|
f << _indent << " \"range\": [0, 0]\n";
|
||||||
else
|
else
|
||||||
f << stringf(" \"range\": [%d, %d]\n", con.second.size(), 0);
|
f << stringf(" %s\"range\": [%d, %d]\n", _indent.c_str(), con.second.size(), 0);
|
||||||
f << " }";
|
f << _indent << " }";
|
||||||
|
|
||||||
first_port = false;
|
first_port = false;
|
||||||
}
|
}
|
||||||
f << "\n";
|
f << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_cell_sort(std::pair<const std::string, std::vector<Cell*>>& sort, uint16_t indent_level = 0) {
|
||||||
|
const auto port_cell = sort.second.front();
|
||||||
|
const auto _indent = gen_indent(indent_level);
|
||||||
|
|
||||||
|
f << _indent << "{\n";
|
||||||
|
f << stringf(" %s\"type\": %s,\n", _indent.c_str(), sort.first.c_str());
|
||||||
|
f << _indent << " \"ports\": [\n";
|
||||||
|
|
||||||
|
write_cell_ports(port_cell, indent_level + 2);
|
||||||
|
|
||||||
|
f << _indent << " ],\n" << _indent << " \"cells\": [\n";
|
||||||
|
|
||||||
f << " ],\n \"cells\": [\n";
|
|
||||||
bool first_cell{true};
|
bool first_cell{true};
|
||||||
for (auto& cell : sort.second) {
|
for (auto& cell : sort.second) {
|
||||||
if (!first_cell)
|
if (!first_cell)
|
||||||
f << ",\n";
|
f << ",\n";
|
||||||
|
|
||||||
write_cell(cell);
|
write_cell(cell, indent_level + 2);
|
||||||
|
|
||||||
first_cell = false;
|
first_cell = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
f << "\n";
|
f << "\n";
|
||||||
f << " ]\n";
|
f << _indent << " ]\n";
|
||||||
f << " }";
|
f << _indent << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_param_val(const Const& v)
|
void write_param_val(const Const& v) {
|
||||||
{
|
|
||||||
if ((v.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) == RTLIL::ConstFlags::CONST_FLAG_STRING) {
|
if ((v.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) == RTLIL::ConstFlags::CONST_FLAG_STRING) {
|
||||||
const auto str = v.decode_string();
|
const auto str = v.decode_string();
|
||||||
|
|
||||||
|
// XXX(aki): TODO, uh, yeah
|
||||||
|
|
||||||
f << get_string(str);
|
f << get_string(str);
|
||||||
} else if ((v.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) == RTLIL::ConstFlags::CONST_FLAG_SIGNED) {
|
} else if ((v.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) == RTLIL::ConstFlags::CONST_FLAG_SIGNED) {
|
||||||
|
@ -187,58 +210,52 @@ struct JnyWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_cell(Cell* cell)
|
void write_prams(dict<RTLIL::IdString, RTLIL::Const>& params, uint16_t indent_level = 0) {
|
||||||
{
|
const auto _indent = gen_indent(indent_level);
|
||||||
log_assert(cell != nullptr);
|
|
||||||
|
|
||||||
f << " {\n";
|
|
||||||
f << stringf(" \"name\": %s,\n", get_string(RTLIL::unescape_id(cell->name)).c_str());
|
|
||||||
f << " \"attributes\": {\n";
|
|
||||||
|
|
||||||
bool first_attr{true};
|
|
||||||
for (auto& attr : cell->attributes) {
|
|
||||||
if (!first_attr)
|
|
||||||
f << stringf(",\n");
|
|
||||||
const auto attr_val = attr.second;
|
|
||||||
if (!attr_val.empty()) {
|
|
||||||
f << stringf(" %s: ", get_string(RTLIL::unescape_id(attr.first)).c_str());
|
|
||||||
write_param_val(attr_val);
|
|
||||||
} else {
|
|
||||||
f << stringf(" %s: true", get_string(RTLIL::unescape_id(attr.first)).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
first_attr = false;
|
|
||||||
}
|
|
||||||
f << "\n";
|
|
||||||
|
|
||||||
f << " },\n";
|
|
||||||
f << " \"parameters\": {\n";
|
|
||||||
|
|
||||||
bool first_param{true};
|
bool first_param{true};
|
||||||
for (auto& param : cell->parameters) {
|
for (auto& param : params) {
|
||||||
if (!first_param)
|
if (!first_param)
|
||||||
f << stringf(",\n");
|
f << stringf(",\n");
|
||||||
const auto param_val = param.second;
|
const auto param_val = param.second;
|
||||||
if (!param_val.empty()) {
|
if (!param_val.empty()) {
|
||||||
f << stringf(" %s: ", get_string(RTLIL::unescape_id(param.first)).c_str());
|
f << stringf(" %s%s: ", _indent.c_str(), get_string(RTLIL::unescape_id(param.first)).c_str());
|
||||||
write_param_val(param_val);
|
write_param_val(param_val);
|
||||||
} else {
|
} else {
|
||||||
f << stringf(" %s: true", get_string(RTLIL::unescape_id(param.first)).c_str());
|
f << stringf(" %s%s: true", _indent.c_str(), get_string(RTLIL::unescape_id(param.first)).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
first_param = false;
|
first_param = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_cell(Cell* cell, uint16_t indent_level = 0) {
|
||||||
|
const auto _indent = gen_indent(indent_level);
|
||||||
|
log_assert(cell != nullptr);
|
||||||
|
|
||||||
|
f << _indent << " {\n";
|
||||||
|
f << stringf(" %s\"name\": %s,\n", _indent.c_str(), get_string(RTLIL::unescape_id(cell->name)).c_str());
|
||||||
|
f << _indent << " \"attributes\": {\n";
|
||||||
|
|
||||||
|
write_prams(cell->attributes, indent_level + 2);
|
||||||
|
|
||||||
f << "\n";
|
f << "\n";
|
||||||
|
|
||||||
f << " },\n";
|
f << _indent << " },\n";
|
||||||
f << " }";
|
f << _indent << " \"parameters\": {\n";
|
||||||
|
|
||||||
|
write_prams(cell->parameters, indent_level + 2);
|
||||||
|
|
||||||
|
f << "\n";
|
||||||
|
|
||||||
|
f << _indent << " }\n";
|
||||||
|
f << _indent << " }";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JnyBackend : public Backend {
|
struct JnyBackend : public Backend {
|
||||||
JnyBackend() : Backend("jny", "generate design metadata") { }
|
JnyBackend() : Backend("jny", "generate design metadata") { }
|
||||||
void help() override
|
void help() override {
|
||||||
{
|
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" jny [options] [selection]\n");
|
log(" jny [options] [selection]\n");
|
||||||
|
@ -248,8 +265,7 @@ struct JnyBackend : public Backend {
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override {
|
||||||
{
|
|
||||||
size_t argidx{1};
|
size_t argidx{1};
|
||||||
extra_args(f, filename, args, argidx);
|
extra_args(f, filename, args, argidx);
|
||||||
|
|
||||||
|
@ -265,8 +281,7 @@ struct JnyBackend : public Backend {
|
||||||
struct JnyPass : public Pass {
|
struct JnyPass : public Pass {
|
||||||
JnyPass() : Pass("jny", "write design and metadata") { }
|
JnyPass() : Pass("jny", "write design and metadata") { }
|
||||||
|
|
||||||
void help() override
|
void help() override {
|
||||||
{
|
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" jny [options] [selection]\n");
|
log(" jny [options] [selection]\n");
|
||||||
|
@ -279,8 +294,7 @@ struct JnyPass : public Pass {
|
||||||
log("See 'help write_jny' for a description of the JSON format used.\n");
|
log("See 'help write_jny' for a description of the JSON format used.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override {
|
||||||
{
|
|
||||||
std::string filename{};
|
std::string filename{};
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
|
|
Loading…
Reference in New Issue