mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-06 01:24:10 +00:00
cellref: Add json dump
New `help -dump-cells-json <file>` to dump cells list. Add 'group' field to SimHelper class/struct with defaults to gate_other and word_other depending on source (simcells or simlib). Add 'unary' group to unary operator cells for testing (based on internal cell library docs page).
This commit is contained in:
parent
7eb33f1933
commit
7c5b10fe50
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
#include "kernel/satgen.h"
|
#include "kernel/satgen.h"
|
||||||
|
#include "kernel/json.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -763,6 +764,7 @@ struct SimHelper {
|
||||||
string source;
|
string source;
|
||||||
string desc;
|
string desc;
|
||||||
string code;
|
string code;
|
||||||
|
string group;
|
||||||
string ver;
|
string ver;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -950,6 +952,77 @@ struct HelpPass : public Pass {
|
||||||
// close
|
// close
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
bool dump_cells_json(PrettyJson &json) {
|
||||||
|
// init json
|
||||||
|
json.begin_object();
|
||||||
|
json.entry("version", "Yosys internal cells");
|
||||||
|
json.entry("generator", yosys_version_str);
|
||||||
|
|
||||||
|
dict<string, dict<string, pair<SimHelper, CellType>>> groups;
|
||||||
|
|
||||||
|
// iterate over cells
|
||||||
|
bool raise_error = false;
|
||||||
|
for (auto &it : yosys_celltypes.cell_types) {
|
||||||
|
auto name = it.first.str();
|
||||||
|
if (cell_help_messages.contains(name)) {
|
||||||
|
auto cell_help = cell_help_messages.get(name);
|
||||||
|
dict<string, pair<SimHelper, CellType>> *cell_group;
|
||||||
|
if (groups.count(cell_help.group) != 0) {
|
||||||
|
cell_group = &groups.at(cell_help.group);
|
||||||
|
} else {
|
||||||
|
cell_group = new dict<string, pair<SimHelper, CellType>>();
|
||||||
|
groups.emplace(cell_help.group, *cell_group);
|
||||||
|
}
|
||||||
|
auto cell_pair = pair<SimHelper, CellType>(cell_help, it.second);
|
||||||
|
cell_group->emplace(name, cell_pair);
|
||||||
|
} else {
|
||||||
|
log("ERROR: Missing cell help for cell '%s'.\n", name.c_str());
|
||||||
|
raise_error |= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write to json
|
||||||
|
json.name("groups");
|
||||||
|
json.begin_array();
|
||||||
|
groups.sort();
|
||||||
|
for (auto &it : groups) {
|
||||||
|
json.begin_object();
|
||||||
|
json.name("group"); json.value(it.first.c_str());
|
||||||
|
json.name("cells"); json.begin_array();
|
||||||
|
for (auto &it2 : it.second) {
|
||||||
|
auto ch = it2.second.first;
|
||||||
|
auto ct = it2.second.second;
|
||||||
|
json.begin_object();
|
||||||
|
json.name("cell"); json.value(ch.name);
|
||||||
|
json.name("title"); json.value(ch.title);
|
||||||
|
json.name("ports"); json.value(ch.ports);
|
||||||
|
json.name("source"); json.value(ch.source);
|
||||||
|
json.name("desc"); json.value(ch.desc);
|
||||||
|
json.name("code"); json.value(ch.code);
|
||||||
|
json.name("inputs"); json.begin_array();
|
||||||
|
for (auto &input : ct.inputs)
|
||||||
|
json.value(input.c_str());
|
||||||
|
json.end_array();
|
||||||
|
json.name("outputs"); json.begin_array();
|
||||||
|
for (auto &output : ct.outputs)
|
||||||
|
json.value(output.c_str());
|
||||||
|
json.end_array();
|
||||||
|
dict<string, bool> prop_dict = {
|
||||||
|
{"is_evaluable", ct.is_evaluable},
|
||||||
|
{"is_combinatorial", ct.is_combinatorial},
|
||||||
|
{"is_synthesizable", ct.is_synthesizable},
|
||||||
|
};
|
||||||
|
json.name("properties"); json.value(prop_dict);
|
||||||
|
json.end_object();
|
||||||
|
}
|
||||||
|
json.end_array();
|
||||||
|
json.end_object();
|
||||||
|
}
|
||||||
|
json.end_array();
|
||||||
|
|
||||||
|
json.end_object();
|
||||||
|
return raise_error;
|
||||||
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design*) override
|
void execute(std::vector<std::string> args, RTLIL::Design*) override
|
||||||
{
|
{
|
||||||
if (args.size() == 1) {
|
if (args.size() == 1) {
|
||||||
|
@ -1053,6 +1126,16 @@ struct HelpPass : public Pass {
|
||||||
else
|
else
|
||||||
log("No such command or cell type: %s\n", args[1].c_str());
|
log("No such command or cell type: %s\n", args[1].c_str());
|
||||||
return;
|
return;
|
||||||
|
} else if (args.size() == 3) {
|
||||||
|
if (args[1] == "-dump-cells-json") {
|
||||||
|
PrettyJson json;
|
||||||
|
if (!json.write_to_file(args[2]))
|
||||||
|
log_error("Can't open file `%s' for writing: %s\n", args[2].c_str(), strerror(errno));
|
||||||
|
if (dump_cells_json(json)) {
|
||||||
|
log_error("One or more cells defined in celltypes.h are missing help documentation.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
help();
|
help();
|
||||||
|
|
|
@ -12,6 +12,7 @@ class SimHelper:
|
||||||
source: str = ""
|
source: str = ""
|
||||||
desc: list[str]
|
desc: list[str]
|
||||||
code: list[str]
|
code: list[str]
|
||||||
|
group: str = ""
|
||||||
ver: str = "1"
|
ver: str = "1"
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
@ -19,7 +20,7 @@ class SimHelper:
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
printed_fields = [
|
printed_fields = [
|
||||||
"name", "title", "ports", "source", "desc", "code", "ver",
|
"name", "title", "ports", "source", "desc", "code", "group", "ver",
|
||||||
]
|
]
|
||||||
# generate C++ struct
|
# generate C++ struct
|
||||||
val = f"cell_help[{json.dumps(self.name)}] = "
|
val = f"cell_help[{json.dumps(self.name)}] = "
|
||||||
|
@ -28,6 +29,7 @@ class SimHelper:
|
||||||
field_val = getattr(self, field)
|
field_val = getattr(self, field)
|
||||||
if isinstance(field_val, list):
|
if isinstance(field_val, list):
|
||||||
field_val = "\n".join(field_val)
|
field_val = "\n".join(field_val)
|
||||||
|
field_val = field_val.strip()
|
||||||
val += f' {json.dumps(field_val)},\n'
|
val += f' {json.dumps(field_val)},\n'
|
||||||
val += "};\n"
|
val += "};\n"
|
||||||
return val
|
return val
|
||||||
|
@ -80,9 +82,23 @@ for line in fileinput.input():
|
||||||
if simHelper.ver == "1" and short_filename == "simcells.v":
|
if simHelper.ver == "1" and short_filename == "simcells.v":
|
||||||
# default simcells parsing
|
# default simcells parsing
|
||||||
simcells_reparse(simHelper)
|
simcells_reparse(simHelper)
|
||||||
|
|
||||||
|
# check help
|
||||||
if not simHelper.desc:
|
if not simHelper.desc:
|
||||||
# no help
|
|
||||||
simHelper.desc.append("No help message for this cell type found.\n")
|
simHelper.desc.append("No help message for this cell type found.\n")
|
||||||
|
elif simHelper.ver == "1" and short_filename == "simlib.v" and simHelper.desc[1].startswith(' '):
|
||||||
|
simHelper.desc.pop(1)
|
||||||
|
|
||||||
|
# check group
|
||||||
|
if not simHelper.group:
|
||||||
|
if short_filename == 'simcells.v':
|
||||||
|
simHelper.group = "gate_"
|
||||||
|
elif short_filename == 'simlib.v':
|
||||||
|
simHelper.group = "word_"
|
||||||
|
simHelper.group += "other"
|
||||||
|
|
||||||
|
# dump
|
||||||
print(simHelper)
|
print(simHelper)
|
||||||
|
# new
|
||||||
simHelper = SimHelper()
|
simHelper = SimHelper()
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,10 @@
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
//* ver 2
|
||||||
//-
|
//* title Bit-wise inverter
|
||||||
//- $not (A, Y)
|
//* group unary
|
||||||
//-
|
//- This corresponds to the Verilog unary prefix '~' operator.
|
||||||
//- A bit-wise inverter. This corresponds to the Verilog unary prefix '~' operator.
|
|
||||||
//-
|
//-
|
||||||
module \$not (A, Y);
|
module \$not (A, Y);
|
||||||
|
|
||||||
|
@ -63,6 +62,7 @@ endmodule
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
//-
|
//-
|
||||||
//- $pos (A, Y)
|
//- $pos (A, Y)
|
||||||
|
//* group unary
|
||||||
//-
|
//-
|
||||||
//- A buffer. This corresponds to the Verilog unary prefix '+' operator.
|
//- A buffer. This corresponds to the Verilog unary prefix '+' operator.
|
||||||
//-
|
//-
|
||||||
|
@ -111,6 +111,7 @@ endmodule
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
//-
|
//-
|
||||||
//- $neg (A, Y)
|
//- $neg (A, Y)
|
||||||
|
//* group unary
|
||||||
//-
|
//-
|
||||||
//- An arithmetic inverter. This corresponds to the Verilog unary prefix '-' operator.
|
//- An arithmetic inverter. This corresponds to the Verilog unary prefix '-' operator.
|
||||||
//-
|
//-
|
||||||
|
@ -258,6 +259,7 @@ endmodule
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
//-
|
//-
|
||||||
//- $reduce_and (A, Y)
|
//- $reduce_and (A, Y)
|
||||||
|
//* group unary
|
||||||
//-
|
//-
|
||||||
//- An AND reduction. This corresponds to the Verilog unary prefix '&' operator.
|
//- An AND reduction. This corresponds to the Verilog unary prefix '&' operator.
|
||||||
//-
|
//-
|
||||||
|
@ -285,6 +287,7 @@ endmodule
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
//-
|
//-
|
||||||
//- $reduce_or (A, Y)
|
//- $reduce_or (A, Y)
|
||||||
|
//* group unary
|
||||||
//-
|
//-
|
||||||
//- An OR reduction. This corresponds to the Verilog unary prefix '|' operator.
|
//- An OR reduction. This corresponds to the Verilog unary prefix '|' operator.
|
||||||
//-
|
//-
|
||||||
|
@ -312,6 +315,7 @@ endmodule
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
//-
|
//-
|
||||||
//- $reduce_xor (A, Y)
|
//- $reduce_xor (A, Y)
|
||||||
|
//* group unary
|
||||||
//-
|
//-
|
||||||
//- A XOR reduction. This corresponds to the Verilog unary prefix '^' operator.
|
//- A XOR reduction. This corresponds to the Verilog unary prefix '^' operator.
|
||||||
//-
|
//-
|
||||||
|
@ -339,6 +343,7 @@ endmodule
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
//-
|
//-
|
||||||
//- $reduce_xnor (A, Y)
|
//- $reduce_xnor (A, Y)
|
||||||
|
//* group unary
|
||||||
//-
|
//-
|
||||||
//- A XNOR reduction. This corresponds to the Verilog unary prefix '~^' operator.
|
//- A XNOR reduction. This corresponds to the Verilog unary prefix '~^' operator.
|
||||||
//-
|
//-
|
||||||
|
@ -366,6 +371,7 @@ endmodule
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
//-
|
//-
|
||||||
//- $reduce_bool (A, Y)
|
//- $reduce_bool (A, Y)
|
||||||
|
//* group unary
|
||||||
//-
|
//-
|
||||||
//- An OR reduction. This cell type is used instead of $reduce_or when a signal is
|
//- An OR reduction. This cell type is used instead of $reduce_or when a signal is
|
||||||
//- implicitly converted to a boolean signal, e.g. for operands of '&&' and '||'.
|
//- implicitly converted to a boolean signal, e.g. for operands of '&&' and '||'.
|
||||||
|
@ -1359,6 +1365,7 @@ endmodule
|
||||||
//-
|
//-
|
||||||
//- A logical inverter. This corresponds to the Verilog unary prefix '!' operator.
|
//- A logical inverter. This corresponds to the Verilog unary prefix '!' operator.
|
||||||
//-
|
//-
|
||||||
|
//* group unary
|
||||||
module \$logic_not (A, Y);
|
module \$logic_not (A, Y);
|
||||||
|
|
||||||
parameter A_SIGNED = 0;
|
parameter A_SIGNED = 0;
|
||||||
|
|
Loading…
Reference in a new issue