mirror of https://github.com/YosysHQ/yosys.git
json: Add support for memories.
Previously, memories were silently discarded by the JSON backend, making round-tripping modules with them crash. Since there are already some users using JSON to implement custom external passes that use memories (and infer width/size from memory ports), let's fix this by just making JSON backend and frontend support memories as first-class objects. Processes are still not supported, and will now cause a hard error. Fixes #1908.
This commit is contained in:
parent
a55bf6375b
commit
3d9698153f
|
@ -135,6 +135,10 @@ struct JsonWriter
|
|||
// reserve 0 and 1 to avoid confusion with "0" and "1"
|
||||
sigidcounter = 2;
|
||||
|
||||
if (module->has_processes()) {
|
||||
log_error("Module %s contains processes, which are not supported by JSON backend.\n", log_id(module));
|
||||
}
|
||||
|
||||
f << stringf(" %s: {\n", get_name(module->name).c_str());
|
||||
|
||||
f << stringf(" \"attributes\": {");
|
||||
|
@ -216,6 +220,27 @@ struct JsonWriter
|
|||
}
|
||||
f << stringf("\n },\n");
|
||||
|
||||
if (!module->memories.empty()) {
|
||||
f << stringf(" \"memories\": {");
|
||||
first = true;
|
||||
for (auto &it : module->memories) {
|
||||
if (use_selection && !module->selected(it.second))
|
||||
continue;
|
||||
f << stringf("%s\n", first ? "" : ",");
|
||||
f << stringf(" %s: {\n", get_name(it.second->name).c_str());
|
||||
f << stringf(" \"hide_name\": %s,\n", it.second->name[0] == '$' ? "1" : "0");
|
||||
f << stringf(" \"attributes\": {");
|
||||
write_parameters(it.second->attributes);
|
||||
f << stringf("\n },\n");
|
||||
f << stringf(" \"width\": %d,\n", it.second->width);
|
||||
f << stringf(" \"start_offset\": %d,\n", it.second->start_offset);
|
||||
f << stringf(" \"size\": %d\n", it.second->size);
|
||||
f << stringf(" }");
|
||||
first = false;
|
||||
}
|
||||
f << stringf("\n },\n");
|
||||
}
|
||||
|
||||
f << stringf(" \"netnames\": {");
|
||||
first = true;
|
||||
for (auto w : module->wires()) {
|
||||
|
@ -332,6 +357,10 @@ struct JsonBackend : public Backend {
|
|||
log(" <cell_name>: <cell_details>,\n");
|
||||
log(" ...\n");
|
||||
log(" },\n");
|
||||
log(" \"memories\": {\n");
|
||||
log(" <memory_name>: <memory_details>,\n");
|
||||
log(" ...\n");
|
||||
log(" },\n");
|
||||
log(" \"netnames\": {\n");
|
||||
log(" <net_name>: <net_details>,\n");
|
||||
log(" ...\n");
|
||||
|
@ -379,6 +408,19 @@ struct JsonBackend : public Backend {
|
|||
log(" },\n");
|
||||
log(" }\n");
|
||||
log("\n");
|
||||
log("And <memory_details> is:\n");
|
||||
log("\n");
|
||||
log(" {\n");
|
||||
log(" \"hide_name\": <1 | 0>,\n");
|
||||
log(" \"attributes\": {\n");
|
||||
log(" <attribute_name>: <attribute_value>,\n");
|
||||
log(" ...\n");
|
||||
log(" },\n");
|
||||
log(" \"width\": <memory width>\n");
|
||||
log(" \"start_offset\": <the lowest valid memory address>\n");
|
||||
log(" \"size\": <memory size>\n");
|
||||
log(" }\n");
|
||||
log("\n");
|
||||
log("And <net_details> is:\n");
|
||||
log("\n");
|
||||
log(" {\n");
|
||||
|
|
|
@ -539,6 +539,52 @@ void json_import(Design *design, string &modname, JsonNode *node)
|
|||
json_parse_attr_param(cell->parameters, cell_node->data_dict.at("parameters"));
|
||||
}
|
||||
}
|
||||
|
||||
if (node->data_dict.count("memories"))
|
||||
{
|
||||
JsonNode *memories_node = node->data_dict.at("memories");
|
||||
|
||||
if (memories_node->type != 'D')
|
||||
log_error("JSON memories node is not a dictionary.\n");
|
||||
|
||||
for (auto &memory_node_it : memories_node->data_dict)
|
||||
{
|
||||
IdString memory_name = RTLIL::escape_id(memory_node_it.first.c_str());
|
||||
JsonNode *memory_node = memory_node_it.second;
|
||||
|
||||
RTLIL::Memory *mem = new RTLIL::Memory;
|
||||
mem->name = memory_name;
|
||||
|
||||
if (memory_node->type != 'D')
|
||||
log_error("JSON memory node '%s' is not a dictionary.\n", log_id(memory_name));
|
||||
|
||||
if (memory_node->data_dict.count("width") == 0)
|
||||
log_error("JSON memory node '%s' has no width attribute.\n", log_id(memory_name));
|
||||
JsonNode *width_node = memory_node->data_dict.at("width");
|
||||
if (width_node->type != 'N')
|
||||
log_error("JSON memory node '%s' has a non-number width.\n", log_id(memory_name));
|
||||
mem->width = width_node->data_number;
|
||||
|
||||
if (memory_node->data_dict.count("size") == 0)
|
||||
log_error("JSON memory node '%s' has no size attribute.\n", log_id(memory_name));
|
||||
JsonNode *size_node = memory_node->data_dict.at("size");
|
||||
if (size_node->type != 'N')
|
||||
log_error("JSON memory node '%s' has a non-number size.\n", log_id(memory_name));
|
||||
mem->size = size_node->data_number;
|
||||
|
||||
mem->start_offset = 0;
|
||||
if (memory_node->data_dict.count("start_offset") != 0) {
|
||||
JsonNode *val = memory_node->data_dict.at("start_offset");
|
||||
if (val->type == 'N')
|
||||
mem->start_offset = val->data_number;
|
||||
}
|
||||
|
||||
if (memory_node->data_dict.count("attributes"))
|
||||
json_parse_attr_param(mem->attributes, memory_node->data_dict.at("attributes"));
|
||||
|
||||
module->memories[mem->name] = mem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct JsonFrontend : public Frontend {
|
||||
|
|
Loading…
Reference in New Issue