diff options
Diffstat (limited to 'json')
-rw-r--r-- | json/jsonparse.cc | 62 | ||||
-rw-r--r-- | json/jsonwrite.cc | 78 |
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> ¶meters, bool for_module = false) { @@ -52,19 +61,69 @@ void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map<Id for (auto ¶m : 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; } |