aboutsummaryrefslogtreecommitdiffstats
path: root/json
diff options
context:
space:
mode:
Diffstat (limited to 'json')
-rw-r--r--json/jsonparse.cc62
-rw-r--r--json/jsonwrite.cc78
2 files changed, 100 insertions, 40 deletions
diff --git a/json/jsonparse.cc b/json/jsonparse.cc
index caedbb5b..ad21daf2 100644
--- a/json/jsonparse.cc
+++ b/json/jsonparse.cc
@@ -230,6 +230,25 @@ struct JsonNode
}
};
+inline Property json_parse_attr_param_value(JsonNode *node)
+{
+ Property value;
+
+ if (node->type == 'S') {
+ value = Property::from_string(node->data_string);
+ } else if (node->type == 'N') {
+ value = Property(node->data_number, 32);
+ } else if (node->type == 'A') {
+ log_error("JSON attribute or parameter value is an array.\n");
+ } else if (node->type == 'D') {
+ log_error("JSON attribute or parameter value is a dict.\n");
+ } else {
+ log_abort();
+ }
+
+ return value;
+}
+
void ground_net(Context *ctx, NetInfo *net)
{
std::unique_ptr<CellInfo> cell = std::unique_ptr<CellInfo>(new CellInfo);
@@ -323,18 +342,12 @@ void json_import_cell_params(Context *ctx, string &modname, CellInfo *cell, Json
param = param_node->data_dict.at(param_node->data_dict_keys[param_id]);
pId = ctx->id(param_node->data_dict_keys[param_id]);
- if (param->type == 'N') {
- (*dest)[pId].setNumber(param->data_number);
- } else if (param->type == 'S')
- (*dest)[pId].setString(param->data_string);
- else
- log_error("JSON parameter type of \"%s\' of cell \'%s\' not supported\n", pId.c_str(ctx),
- cell->name.c_str(ctx));
+ (*dest)[pId] = json_parse_attr_param_value(param);
if (json_debug)
log_info(" Added parameter \'%s\'=%s to cell \'%s\' "
"of module \'%s\'\n",
- pId.c_str(ctx), cell->params[pId].c_str(), cell->name.c_str(ctx), modname.c_str());
+ pId.c_str(ctx), cell->params[pId].as_string().c_str(), cell->name.c_str(ctx), modname.c_str());
}
void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNode *param_node,
@@ -347,16 +360,12 @@ void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNod
param = param_node->data_dict.at(param_node->data_dict_keys[param_id]);
pId = ctx->id(param_node->data_dict_keys[param_id]);
- if (param->type == 'N') {
- (*dest)[pId].setNumber(param->data_number);
- } else if (param->type == 'S')
- (*dest)[pId].setString(param->data_string);
- else
- log_error("JSON parameter type of \"%s\' of net \'%s\' not supported\n", pId.c_str(ctx), net->name.c_str(ctx));
+ (*dest)[pId] = json_parse_attr_param_value(param);
+
if (json_debug)
log_info(" Added parameter \'%s\'=%s to net \'%s\' "
"of module \'%s\'\n",
- pId.c_str(ctx), net->attrs[pId].c_str(), net->name.c_str(ctx), modname.c_str());
+ pId.c_str(ctx), net->attrs[pId].as_string().c_str(), net->name.c_str(ctx), modname.c_str());
}
void json_import_top_attrib(Context *ctx, string &modname, JsonNode *param_node,
@@ -369,14 +378,10 @@ void json_import_top_attrib(Context *ctx, string &modname, JsonNode *param_node,
param = param_node->data_dict.at(param_node->data_dict_keys[param_id]);
pId = ctx->id(param_node->data_dict_keys[param_id]);
- if (param->type == 'N') {
- (*dest)[pId].setNumber(param->data_number);
- } else if (param->type == 'S')
- (*dest)[pId].setString(param->data_string);
- else
- log_error("JSON parameter type of \"%s\' of module not supported\n", pId.c_str(ctx));
+ (*dest)[pId] = json_parse_attr_param_value(param);
+
if (json_debug)
- log_info(" Added parameter \'%s\'=%s module \'%s\'\n", pId.c_str(ctx), (*dest)[pId].c_str(),
+ log_info(" Added parameter \'%s\'=%s module \'%s\'\n", pId.c_str(ctx), (*dest)[pId].as_string().c_str(),
modname.c_str());
}
@@ -728,10 +733,10 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string
}
PortInfo pinfo;
- pinfo.name = net->name;
+ pinfo.name = ctx->id(name);
pinfo.net = net;
pinfo.type = type;
- ctx->ports[net->name] = pinfo;
+ ctx->ports[pinfo.name] = pinfo;
}
void json_import_toplevel_port(Context *ctx, const string &modname, const std::vector<IdString> &netnames,
@@ -917,7 +922,7 @@ void json_import(Context *ctx, string modname, JsonNode *node)
}
}
check_all_nets_driven(ctx);
- ctx->settings[ctx->id("synth")] = "1";
+ ctx->settings[ctx->id("synth")] = 1;
}
}; // End Namespace JsonParser
@@ -986,12 +991,7 @@ bool load_json_settings(std::istream &f, std::string &filename, std::unordered_m
for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) {
JsonNode *param = attr_node->data_dict.at(attr_node->data_dict_keys[attrid]);
std::string pId = attr_node->data_dict_keys[attrid];
- if (param->type == 'N') {
- values[pId].setNumber(param->data_number);
- } else if (param->type == 'S')
- values[pId].setString(param->data_string);
- else
- log_error("JSON parameter type of \"%s\' of module not supported\n", pId.c_str());
+ values[pId] = json_parse_attr_param_value(param);
}
}
}
diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc
index 0b7a5b25..3d3b70e4 100644
--- a/json/jsonwrite.cc
+++ b/json/jsonwrite.cc
@@ -45,6 +45,15 @@ std::string get_string(std::string str)
std::string get_name(IdString name, Context *ctx) { return get_string(name.c_str(ctx)); }
+void write_parameter_value(std::ostream &f, const Property &value)
+{
+ if (value.size() == 32 && value.is_fully_def()) {
+ f << stringf("%d", value.as_int64());
+ } else {
+ f << get_string(value.to_string());
+ }
+}
+
void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map<IdString, Property> &parameters,
bool for_module = false)
{
@@ -52,19 +61,69 @@ void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map<Id
for (auto &param : parameters) {
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first, ctx).c_str());
- if (param.second.isString())
- f << get_string(param.second);
+ write_parameter_value(f, param.second);
+ first = false;
+ }
+}
+
+struct PortGroup
+{
+ std::string name;
+ std::vector<int> bits;
+ PortType dir;
+};
+
+std::vector<PortGroup> group_ports(Context *ctx)
+{
+ std::vector<PortGroup> groups;
+ std::unordered_map<std::string, size_t> base_to_group;
+ for (auto &pair : ctx->ports) {
+ std::string name = pair.second.name.str(ctx);
+ if ((name.back() != ']') || (name.find('[') == std::string::npos)) {
+ groups.push_back({name, {pair.first.index}, pair.second.type});
+ } else {
+ int off1 = int(name.find_last_of('['));
+ std::string basename = name.substr(0, off1);
+ int index = std::stoi(name.substr(off1 + 1, name.size() - (off1 + 2)));
+
+ if (!base_to_group.count(basename)) {
+ base_to_group[basename] = groups.size();
+ groups.push_back({basename, std::vector<int>(index + 1, -1), pair.second.type});
+ }
+
+ auto &grp = groups.at(base_to_group[basename]);
+ if (int(grp.bits.size()) <= index)
+ grp.bits.resize(index + 1, -1);
+ NPNR_ASSERT(grp.bits.at(index) == -1);
+ grp.bits.at(index) = pair.second.net ? pair.second.net->name.index : pair.first.index;
+ }
+ }
+ return groups;
+};
+
+std::string format_port_bits(const PortGroup &port)
+{
+ std::stringstream s;
+ s << "[ ";
+ bool first = true;
+ for (auto bit : port.bits) {
+ if (!first)
+ s << ", ";
+ if (bit == -1)
+ s << "\"x\"";
else
- f << param.second.num;
+ s << bit;
first = false;
}
+ s << " ]";
+ return s.str();
}
void write_module(std::ostream &f, Context *ctx)
{
auto val = ctx->attrs.find(ctx->id("module"));
if (val != ctx->attrs.end())
- f << stringf(" %s: {\n", get_string(val->second.str).c_str());
+ f << stringf(" %s: {\n", get_string(val->second.as_string()).c_str());
else
f << stringf(" %s: {\n", get_string("top").c_str());
f << stringf(" \"settings\": {");
@@ -74,14 +133,15 @@ void write_module(std::ostream &f, Context *ctx)
write_parameters(f, ctx, ctx->attrs, true);
f << stringf("\n },\n");
f << stringf(" \"ports\": {");
+
+ auto ports = group_ports(ctx);
bool first = true;
- for (auto &pair : ctx->ports) {
- auto &c = pair.second;
+ for (auto &port : ports) {
f << stringf("%s\n", first ? "" : ",");
- f << stringf(" %s: {\n", get_name(c.name, ctx).c_str());
+ f << stringf(" %s: {\n", get_string(port.name).c_str());
f << stringf(" \"direction\": \"%s\",\n",
- c.type == PORT_IN ? "input" : c.type == PORT_INOUT ? "inout" : "output");
- f << stringf(" \"bits\": [ %d ]\n", pair.first.index);
+ port.dir == PORT_IN ? "input" : port.dir == PORT_INOUT ? "inout" : "output");
+ f << stringf(" \"bits\": %s\n", format_port_bits(port).c_str());
f << stringf(" }");
first = false;
}