From 545068dec4a0433d17741b508965a391029e3283 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 31 May 2019 11:09:13 +0200 Subject: Initial work on jsonwrite --- common/command.cc | 8 +++ json/jsonwrite.cc | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ json/jsonwrite.h | 33 +++++++++++ 3 files changed, 208 insertions(+) create mode 100644 json/jsonwrite.cc create mode 100644 json/jsonwrite.h diff --git a/common/command.cc b/common/command.cc index 3eafdb17..242e5037 100644 --- a/common/command.cc +++ b/common/command.cc @@ -35,6 +35,7 @@ #include "command.h" #include "design_utils.h" #include "jsonparse.h" +#include "jsonwrite.h" #include "log.h" #include "timing.h" #include "util.h" @@ -120,6 +121,7 @@ po::options_description CommandHandler::getGeneralOptions() #endif general.add_options()("json", po::value(), "JSON design file to ingest"); + general.add_options()("write", po::value(), "JSON design file to write"); general.add_options()("seed", po::value(), "seed value for random number generator"); general.add_options()("randomize-seed,r", "randomize seed value for random number generator"); @@ -303,6 +305,12 @@ int CommandHandler::executeMain(std::unique_ptr ctx) customBitstream(ctx.get()); } + if (vm.count("write")) { + std::string filename = vm["write"].as(); + std::ofstream f(filename); + if (!write_json_file(f, filename, ctx.get())) + log_error("Loading design failed.\n"); + } if (vm.count("save")) { project.save(ctx.get(), vm["save"].as()); } diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc new file mode 100644 index 00000000..b35a61cf --- /dev/null +++ b/json/jsonwrite.cc @@ -0,0 +1,167 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "jsonwrite.h" +#include +#include +#include +#include +#include +#include +#include +#include "nextpnr.h" +#include "version.h" + +NEXTPNR_NAMESPACE_BEGIN + +namespace JsonWriter { + +std::string get_string(std::string str) +{ + std::string newstr = "\""; + for (char c : str) { + if (c == '\\') + newstr += c; + newstr += c; + } + return newstr + "\""; +} + +std::string get_name(IdString name, Context *ctx) +{ + return get_string(name.c_str(ctx)); +} + +void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) +{ + bool first = true; + for (auto ¶m : parameters) { + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first,ctx).c_str()); + f << get_string(param.second); + first = false; + } +} +void write_module(std::ostream &f, Context *ctx) +{ + f << stringf(" %s: {\n", get_string("top").c_str()); + // TODO: check if this is better to be separate + /*f << stringf(" \"settings\": {"); + write_parameters(f, ctx, ctx->settings, true); + f << stringf("\n },\n");*/ + f << stringf(" \"attributes\": {"); + // TODO: Top level attributes + f << stringf("\n },\n"); + f << stringf(" \"ports\": {"); + // TODO: Top level ports + f << stringf("\n },\n"); + + auto fn = ctx->nets.hash_function(); + + f << stringf(" \"cells\": {"); + bool first = true; + for (auto &pair : ctx->cells) { + auto &c = pair.second; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name, ctx).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name.c_str(ctx)[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type, ctx).c_str()); + f << stringf(" \"parameters\": {"); + write_parameters(f, ctx, c->params); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(f, ctx, c->attrs); + f << stringf("\n },\n"); + f << stringf(" \"port_directions\": {"); + bool first2 = true; + for (auto &conn : c->ports) { + auto &p = conn.second; + if (p.net) { + std::string direction = (p.type == PORT_IN) ? "input" : (p.type == PORT_OUT) ? "output" : "inout"; + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: \"%s\"", get_name(conn.first, ctx).c_str(), direction.c_str()); + first2 = false; + } + } + f << stringf("\n },\n"); + f << stringf(" \"connections\": {"); + first2 = true; + + for (auto &conn : c->ports) { + auto &p = conn.second; + if (p.net) { + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: %d", get_name(conn.first,ctx).c_str(), fn(p.net->name)); + first2 = false; + } + } + f << stringf("\n }\n"); + + f << stringf(" }"); + first = false; + } + + f << stringf("\n },\n"); + + f << stringf(" \"netnames\": {"); + first = true; + for (auto &pair : ctx->nets) { + auto &w = pair.second; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name, ctx).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name.c_str(ctx)[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": [ %d ] ,\n", fn(pair.first)); + f << stringf(" \"attributes\": {"); + write_parameters(f, ctx, w->attrs); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + + f << stringf("\n }\n"); + f << stringf(" }"); +} + +void write_context(std::ostream &f, Context *ctx) +{ + f << stringf("{\n"); + f << stringf(" \"creator\": %s,\n", get_string( "Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")").c_str()); + f << stringf(" \"modules\": {\n"); + write_module(f, ctx); + f << stringf("\n }"); + f << stringf("\n}\n"); +} + +}; // End Namespace JsonWriter + +bool write_json_file(std::ostream &f, std::string &filename, Context *ctx) +{ + try { + using namespace JsonWriter; + if (!f) + log_error("failed to open JSON file.\n"); + write_context(f, ctx); + log_break(); + return true; + } catch (log_execution_error_exception) { + return false; + } +} + +NEXTPNR_NAMESPACE_END diff --git a/json/jsonwrite.h b/json/jsonwrite.h new file mode 100644 index 00000000..9240bc96 --- /dev/null +++ b/json/jsonwrite.h @@ -0,0 +1,33 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef JSON_WRITER +#define JSON_WRITER + +#include +#include +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +extern bool write_json_file(std::ostream &, std::string &, Context *); + +NEXTPNR_NAMESPACE_END + +#endif -- cgit v1.2.3 From 1657479c8153199cbe008aad552ce07b8170293a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 31 May 2019 11:50:49 +0200 Subject: Solve some of connection issues --- json/jsonwrite.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index b35a61cf..f41fbebc 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -92,12 +92,10 @@ void write_module(std::ostream &f, Context *ctx) bool first2 = true; for (auto &conn : c->ports) { auto &p = conn.second; - if (p.net) { - std::string direction = (p.type == PORT_IN) ? "input" : (p.type == PORT_OUT) ? "output" : "inout"; - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: \"%s\"", get_name(conn.first, ctx).c_str(), direction.c_str()); - first2 = false; - } + std::string direction = (p.type == PORT_IN) ? "input" : (p.type == PORT_OUT) ? "output" : "inout"; + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: \"%s\"", get_name(conn.first, ctx).c_str(), direction.c_str()); + first2 = false; } f << stringf("\n },\n"); f << stringf(" \"connections\": {"); @@ -105,11 +103,13 @@ void write_module(std::ostream &f, Context *ctx) for (auto &conn : c->ports) { auto &p = conn.second; - if (p.net) { - f << stringf("%s\n", first2 ? "" : ","); - f << stringf(" %s: %d", get_name(conn.first,ctx).c_str(), fn(p.net->name)); - first2 = false; - } + f << stringf("%s\n", first2 ? "" : ","); + if (p.net) + f << stringf(" %s: [ %d ]", get_name(conn.first,ctx).c_str(), fn(p.net->name)); + else + f << stringf(" %s: [ ]", get_name(conn.first,ctx).c_str()); + + first2 = false; } f << stringf("\n }\n"); -- cgit v1.2.3 From f1b3a14bc23ccee6acaf6bbe27827523dc13c111 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 31 May 2019 13:38:18 +0200 Subject: Do not add VCC if not used, loading json works --- ice40/pack.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ice40/pack.cc b/ice40/pack.cc index 390cbf57..d8796ede 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -352,6 +352,7 @@ static void pack_constants(Context *ctx) std::vector dead_nets; bool gnd_used = false; + bool vcc_used = false; for (auto net : sorted(ctx->nets)) { NetInfo *ni = net.second; @@ -364,6 +365,7 @@ static void pack_constants(Context *ctx) } else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, vcc_net.get(), true); + vcc_used = true; dead_nets.push_back(net.first); ctx->cells.erase(drv_cell); } @@ -373,11 +375,10 @@ static void pack_constants(Context *ctx) ctx->cells[gnd_cell->name] = std::move(gnd_cell); ctx->nets[gnd_net->name] = std::move(gnd_net); } - // Vcc cell always inserted for now, as it may be needed during carry legalisation (TODO: trim later if actually - // never used?) - ctx->cells[vcc_cell->name] = std::move(vcc_cell); - ctx->nets[vcc_net->name] = std::move(vcc_net); - + if (vcc_used) { + ctx->cells[vcc_cell->name] = std::move(vcc_cell); + ctx->nets[vcc_net->name] = std::move(vcc_net); + } for (auto dn : dead_nets) { ctx->nets.erase(dn); } -- cgit v1.2.3 From 5013724c0a98833b50ece75b13a3eeab12178a7e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 1 Jun 2019 10:27:01 +0200 Subject: Solve issue with nets/cells not visible on load --- common/command.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/command.cc b/common/command.cc index 242e5037..3813a380 100644 --- a/common/command.cc +++ b/common/command.cc @@ -244,11 +244,11 @@ int CommandHandler::executeMain(std::unique_ptr ctx) if (vm.count("json")) { std::string filename = vm["json"].as(); std::ifstream f(filename); - w.notifyChangeContext(); if (!parse_json_file(f, filename, w.getContext())) log_error("Loading design failed.\n"); customAfterLoad(w.getContext()); + w.notifyChangeContext(); w.updateLoaded(); } else if (vm.count("load")) { w.projectLoad(vm["load"].as()); -- cgit v1.2.3 From aa0568628ffb373d07dcf01586ae643500509780 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 1 Jun 2019 11:41:34 +0200 Subject: Add writing routing data to json --- json/jsonwrite.cc | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index f41fbebc..bedb2449 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -48,7 +48,7 @@ std::string get_name(IdString name, Context *ctx) return get_string(name.c_str(ctx)); } -void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) +bool write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) { bool first = true; for (auto ¶m : parameters) { @@ -57,7 +57,27 @@ void write_parameters(std::ostream &f, Context *ctx, const std::unordered_mapwires) { + routing += first2 ? "" : ";"; + routing += ctx->getWireName(item.first).c_str(ctx); + routing += ","; + if (item.second.pip != PipId()) + routing += ctx->getPipName(item.second.pip).c_str(ctx); + first2 = false; + } + + f << stringf("%s\n", first ? "" : ","); + f << stringf(" \"NEXTPNR_ROUTING\": "); + f << get_string(routing); +} + void write_module(std::ostream &f, Context *ctx) { f << stringf(" %s: {\n", get_string("top").c_str()); @@ -128,7 +148,8 @@ void write_module(std::ostream &f, Context *ctx) f << stringf(" \"hide_name\": %s,\n", w->name.c_str(ctx)[0] == '$' ? "1" : "0"); f << stringf(" \"bits\": [ %d ] ,\n", fn(pair.first)); f << stringf(" \"attributes\": {"); - write_parameters(f, ctx, w->attrs); + bool first2 = write_parameters(f, ctx, w->attrs); + write_routing(f, ctx, w.get(), first2); f << stringf("\n }\n"); f << stringf(" }"); first = false; -- cgit v1.2.3 From ccbe2dd18d12d9d201afd5499e9e70ed8d2539de Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 1 Jun 2019 11:41:50 +0200 Subject: Add reading attributes to nets from json --- json/jsonparse.cc | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index eec7041c..a78affbe 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -332,6 +332,30 @@ void json_import_cell_params(Context *ctx, string &modname, CellInfo *cell, Json pId.c_str(ctx), cell->params[pId].c_str(), cell->name.c_str(ctx), modname.c_str()); } +void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNode *param_node, + std::unordered_map *dest, int param_id) +{ + // + JsonNode *param; + IdString pId; + // + 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] = std::to_string(param->data_number); + } else if (param->type == 'S') + (*dest)[pId] = 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)); + + 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()); +} + static int const_net_idx = 0; template @@ -790,6 +814,41 @@ void json_import(Context *ctx, string modname, JsonNode *node) json_import_toplevel_port(ctx, modname, netids, ports_parent->data_dict_keys[portid], here); } } + if (node->data_dict.count("netnames")) { + JsonNode *net_parent = node->data_dict.at("netnames"); + for (int nnid = 0; nnid < GetSize(net_parent->data_dict_keys); nnid++) { + JsonNode *here; + + here = net_parent->data_dict.at(net_parent->data_dict_keys[nnid]); + std::string basename = net_parent->data_dict_keys[nnid]; + if (here->data_dict.count("bits")) { + JsonNode *bits = here->data_dict.at("bits"); + assert(bits->type == 'A'); + size_t num_bits = bits->data_array.size(); + for (size_t i = 0; i < num_bits; i++) { + std::string name = + basename + (num_bits == 1 ? "" : std::string("[") + std::to_string(i) + std::string("]")); + IdString net_id = ctx->id(name); + if (here->data_dict.count("attributes") && ctx->nets.find(net_id)!=ctx->nets.end()) { + NetInfo *this_net = ctx->nets[net_id].get(); + + JsonNode *attr_node = here->data_dict.at("attributes"); + if (attr_node->type != 'D') + log_error("JSON attribute list of \'%s\' is not a data dictionary\n", this_net->name.c_str(ctx)); + + // + // Loop through all attributes, adding them into the + // design to annotate the cell + // + for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { + json_import_net_attrib(ctx, modname, this_net, attr_node, &this_net->attrs, attrid); + } + + } + } + } + } + } check_all_nets_driven(ctx); } }; // End Namespace JsonParser -- cgit v1.2.3 From d5d8213871d8cb68b2e4ef9b3557879c80ff5b51 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 1 Jun 2019 15:52:32 +0200 Subject: Added support for attributes/properties types --- common/nextpnr.h | 39 +++++++++++++++++++++++++++++++++++++-- common/pybindings.cc | 2 +- ecp5/pack.cc | 2 +- ice40/pack.cc | 2 +- json/jsonparse.cc | 12 ++++++------ json/jsonwrite.cc | 7 +++++-- 6 files changed, 51 insertions(+), 13 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index fc49300e..02201463 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -286,6 +286,41 @@ struct PipMap PlaceStrength strength = STRENGTH_NONE; }; +struct Property +{ + bool is_string; + + std::string str; + int num; + + std::string::iterator begin() { return str.begin(); } + std::string::iterator end() { return str.end(); } + + bool isString() const { return is_string; } + + void setNumber(int val) { is_string = false; num = val; str = std::to_string(val); } + void setString(std::string val) { is_string = true; str = val; } + + const char * c_str() const { return str.c_str(); } + operator std::string () const { return str; } + + bool operator==(const std::string other) const + { + return str == other; + } + bool operator!=(const std::string other) const + { + return str != other; + } + + Property& operator=(std::string other) + { + is_string = true; + str = other; + return *this; + } +}; + struct ClockConstraint; struct NetInfo : ArchNetInfo @@ -295,7 +330,7 @@ struct NetInfo : ArchNetInfo PortRef driver; std::vector users; - std::unordered_map attrs; + std::unordered_map attrs; // wire -> uphill_pip std::unordered_map wires; @@ -328,7 +363,7 @@ struct CellInfo : ArchCellInfo int32_t udata; std::unordered_map ports; - std::unordered_map attrs, params; + std::unordered_map attrs, params; BelId bel; PlaceStrength belStrength = STRENGTH_NONE; diff --git a/common/pybindings.cc b/common/pybindings.cc index 60f87e27..52dd9717 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -122,7 +122,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .value("PORT_INOUT", PORT_INOUT) .export_values(); - typedef std::unordered_map AttrMap; + typedef std::unordered_map AttrMap; typedef std::unordered_map PortMap; typedef std::unordered_map PinMap; typedef std::unordered_map> RegionMap; diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 7f00de1f..548c38d8 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -1896,7 +1896,7 @@ class Ecp5Packer iol->params[ctx->id("DELAY.DEL_VALUE")] = std::to_string(lookup_delay(str_or_default(ci->params, ctx->id("DEL_MODE"), "USER_DEFINED"))); if (ci->params.count(ctx->id("DEL_VALUE")) && - ci->params.at(ctx->id("DEL_VALUE")).substr(0, 5) != "DELAY") + std::string(ci->params.at(ctx->id("DEL_VALUE"))).substr(0, 5) != "DELAY") iol->params[ctx->id("DELAY.DEL_VALUE")] = ci->params.at(ctx->id("DEL_VALUE")); if (ci->ports.count(id_LOADN)) replace_port(ci, id_LOADN, iol, id_LOADN); diff --git a/ice40/pack.cc b/ice40/pack.cc index d8796ede..6c5dad39 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -1202,7 +1202,7 @@ static void pack_special(Context *ctx) ? "1" : feedback_path == "PHASE_AND_DELAY" ? "2" - : feedback_path == "EXTERNAL" ? "6" : feedback_path; + : feedback_path == "EXTERNAL" ? "6" : std::string(feedback_path); if (!std::all_of(fbp_value.begin(), fbp_value.end(), isdigit)) log_error("PLL '%s' has unsupported FEEDBACK_PATH value '%s'\n", ci->name.c_str(ctx), feedback_path.c_str()); diff --git a/json/jsonparse.cc b/json/jsonparse.cc index a78affbe..df21eb0f 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -309,7 +309,7 @@ bool is_blackbox(JsonNode *node) } void json_import_cell_params(Context *ctx, string &modname, CellInfo *cell, JsonNode *param_node, - std::unordered_map *dest, int param_id) + std::unordered_map *dest, int param_id) { // JsonNode *param; @@ -319,9 +319,9 @@ void json_import_cell_params(Context *ctx, string &modname, CellInfo *cell, Json pId = ctx->id(param_node->data_dict_keys[param_id]); if (param->type == 'N') { - (*dest)[pId] = std::to_string(param->data_number); + (*dest)[pId].setNumber(param->data_number); } else if (param->type == 'S') - (*dest)[pId] = param->data_string; + (*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)); @@ -333,7 +333,7 @@ void json_import_cell_params(Context *ctx, string &modname, CellInfo *cell, Json } void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNode *param_node, - std::unordered_map *dest, int param_id) + std::unordered_map *dest, int param_id) { // JsonNode *param; @@ -343,9 +343,9 @@ void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNod pId = ctx->id(param_node->data_dict_keys[param_id]); if (param->type == 'N') { - (*dest)[pId] = std::to_string(param->data_number); + (*dest)[pId].setNumber(param->data_number); } else if (param->type == 'S') - (*dest)[pId] = param->data_string; + (*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)); diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index bedb2449..8c1f914f 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -48,13 +48,16 @@ std::string get_name(IdString name, Context *ctx) return get_string(name.c_str(ctx)); } -bool write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) +bool write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) { bool first = true; for (auto ¶m : parameters) { f << stringf("%s\n", first ? "" : ","); f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first,ctx).c_str()); - f << get_string(param.second); + if (param.second.isString()) + f << get_string(param.second); + else + f << param.second.num; first = false; } return first; -- cgit v1.2.3 From bab6c9a09f9a5107267da70f5b2990975a1ce643 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 2 Jun 2019 08:50:48 +0200 Subject: Proper save message --- common/command.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/command.cc b/common/command.cc index 3813a380..e7ffef93 100644 --- a/common/command.cc +++ b/common/command.cc @@ -309,7 +309,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) std::string filename = vm["write"].as(); std::ofstream f(filename); if (!write_json_file(f, filename, ctx.get())) - log_error("Loading design failed.\n"); + log_error("Saving design failed.\n"); } if (vm.count("save")) { project.save(ctx.get(), vm["save"].as()); -- cgit v1.2.3 From eff1a1341a14c105ecf3bd8c559bf425915c3e01 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 2 Jun 2019 08:51:32 +0200 Subject: Revert "Do not add VCC if not used, loading json works" This reverts commit f1b3a14bc23ccee6acaf6bbe27827523dc13c111. --- ice40/pack.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ice40/pack.cc b/ice40/pack.cc index 6c5dad39..4cb76add 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -352,7 +352,6 @@ static void pack_constants(Context *ctx) std::vector dead_nets; bool gnd_used = false; - bool vcc_used = false; for (auto net : sorted(ctx->nets)) { NetInfo *ni = net.second; @@ -365,7 +364,6 @@ static void pack_constants(Context *ctx) } else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, vcc_net.get(), true); - vcc_used = true; dead_nets.push_back(net.first); ctx->cells.erase(drv_cell); } @@ -375,10 +373,11 @@ static void pack_constants(Context *ctx) ctx->cells[gnd_cell->name] = std::move(gnd_cell); ctx->nets[gnd_net->name] = std::move(gnd_net); } - if (vcc_used) { - ctx->cells[vcc_cell->name] = std::move(vcc_cell); - ctx->nets[vcc_net->name] = std::move(vcc_net); - } + // Vcc cell always inserted for now, as it may be needed during carry legalisation (TODO: trim later if actually + // never used?) + ctx->cells[vcc_cell->name] = std::move(vcc_cell); + ctx->nets[vcc_net->name] = std::move(vcc_net); + for (auto dn : dead_nets) { ctx->nets.erase(dn); } -- cgit v1.2.3 From 5c47b6034efd3898b666a18dd81cf4ae633a18c1 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 2 Jun 2019 09:13:19 +0200 Subject: added no-place and no-route options --- common/command.cc | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/common/command.cc b/common/command.cc index e7ffef93..dc83f84d 100644 --- a/common/command.cc +++ b/common/command.cc @@ -137,6 +137,8 @@ po::options_description CommandHandler::getGeneralOptions() general.add_options()("placer-budgets", "use budget rather than criticality in placer timing weights"); general.add_options()("pack-only", "pack design only without placement or routing"); + general.add_options()("no-route", "process design without routing"); + general.add_options()("no-place", "process design without placement"); general.add_options()("ignore-loops", "ignore combinational loops in timing analysis"); @@ -282,25 +284,33 @@ int CommandHandler::executeMain(std::unique_ptr ctx) execute_python_file(filename.c_str()); } else #endif - if (vm.count("json") || vm.count("load")) { - run_script_hook("pre-pack"); - if (!ctx->pack() && !ctx->force) - log_error("Packing design failed.\n"); - assign_budget(ctx.get()); - ctx->check(); - print_utilisation(ctx.get()); - run_script_hook("pre-place"); - - if (!vm.count("pack-only")) { + if (vm.count("json") || vm.count("load")) { + bool do_pack = true; + bool do_place = vm.count("pack-only")==0 && vm.count("no-place")==0; + bool do_route = vm.count("pack-only")==0 && vm.count("no-route")==0; + + if (do_pack) { + run_script_hook("pre-pack"); + if (!ctx->pack() && !ctx->force) + log_error("Packing design failed.\n"); + assign_budget(ctx.get()); + ctx->check(); + print_utilisation(ctx.get()); + } + + if (do_place) { + run_script_hook("pre-place"); if (!ctx->place() && !ctx->force) log_error("Placing design failed.\n"); ctx->check(); - run_script_hook("pre-route"); + } + if (do_route) { + run_script_hook("pre-route"); if (!ctx->route() && !ctx->force) log_error("Routing design failed.\n"); + run_script_hook("post-route"); } - run_script_hook("post-route"); customBitstream(ctx.get()); } -- cgit v1.2.3 From d0273f7faa9f7d75350f421966a7d5cbb4ccc9ba Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 2 Jun 2019 10:01:20 +0200 Subject: option to disable packing --- common/command.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/common/command.cc b/common/command.cc index dc83f84d..e81967b4 100644 --- a/common/command.cc +++ b/common/command.cc @@ -139,6 +139,7 @@ po::options_description CommandHandler::getGeneralOptions() general.add_options()("pack-only", "pack design only without placement or routing"); general.add_options()("no-route", "process design without routing"); general.add_options()("no-place", "process design without placement"); + general.add_options()("no-pack", "process design without packing"); general.add_options()("ignore-loops", "ignore combinational loops in timing analysis"); @@ -285,7 +286,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) } else #endif if (vm.count("json") || vm.count("load")) { - bool do_pack = true; + bool do_pack = vm.count("pack-only")!=0 || vm.count("no-pack")==0; bool do_place = vm.count("pack-only")==0 && vm.count("no-place")==0; bool do_route = vm.count("pack-only")==0 && vm.count("no-route")==0; @@ -293,11 +294,14 @@ int CommandHandler::executeMain(std::unique_ptr ctx) run_script_hook("pre-pack"); if (!ctx->pack() && !ctx->force) log_error("Packing design failed.\n"); - assign_budget(ctx.get()); - ctx->check(); - print_utilisation(ctx.get()); + } else { + ctx->assignArchInfo(); } + assign_budget(ctx.get()); + ctx->check(); + print_utilisation(ctx.get()); + if (do_place) { run_script_hook("pre-place"); if (!ctx->place() && !ctx->force) -- cgit v1.2.3 From 1894cb549c368ccd5c932535852d6d9367136865 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 2 Jun 2019 16:46:07 +0200 Subject: preserve constraints --- json/jsonwrite.cc | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 8c1f914f..7143bf93 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -81,6 +81,30 @@ void write_routing(std::ostream &f, Context *ctx, NetInfo *net, bool first) f << get_string(routing); } +void write_constraints(std::ostream &f, Context *ctx, CellInfo *cell, bool first) +{ + std::string constr; + constr += std::to_string(cell->constr_x) + ";"; + constr += std::to_string(cell->constr_y) + ";"; + constr += std::to_string(cell->constr_z) + ";"; + constr += std::to_string(cell->constr_abs_z ? 1:0) + ";"; + constr += cell->constr_parent!=nullptr ? cell->constr_parent->name.c_str(ctx) : ""; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" \"NEXTPNR_CONSTRAINT\": "); + f << get_string(constr); + + constr = ""; + for(auto &item : cell->constr_children) + { + if (!constr.empty()) constr += std::string(";"); + constr += item->name.c_str(ctx); + } + f << stringf(",\n"); + f << stringf(" \"NEXTPNR_CONSTR_CHILDREN\": "); + f << get_string(constr); + +} + void write_module(std::ostream &f, Context *ctx) { f << stringf(" %s: {\n", get_string("top").c_str()); @@ -109,7 +133,8 @@ void write_module(std::ostream &f, Context *ctx) write_parameters(f, ctx, c->params); f << stringf("\n },\n"); f << stringf(" \"attributes\": {"); - write_parameters(f, ctx, c->attrs); + bool first3 = write_parameters(f, ctx, c->attrs); + write_constraints(f, ctx, c.get(), first3); f << stringf("\n },\n"); f << stringf(" \"port_directions\": {"); bool first2 = true; @@ -123,7 +148,6 @@ void write_module(std::ostream &f, Context *ctx) f << stringf("\n },\n"); f << stringf(" \"connections\": {"); first2 = true; - for (auto &conn : c->ports) { auto &p = conn.second; f << stringf("%s\n", first2 ? "" : ","); -- cgit v1.2.3 From 7c65da417b5a222cc68a83e25c60c1f1326473f2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 2 Jun 2019 17:33:37 +0200 Subject: Read constraints and placing from file --- common/command.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/common/command.cc b/common/command.cc index e81967b4..7d4cd252 100644 --- a/common/command.cc +++ b/common/command.cc @@ -232,6 +232,22 @@ void CommandHandler::setupContext(Context *ctx) ctx->timing_driven = false; } +std::vector split(const std::string& str, const std::string& delim) +{ + std::vector tokens; + size_t prev = 0, pos = 0; + do + { + pos = str.find(delim, prev); + if (pos == std::string::npos) pos = str.length(); + std::string token = str.substr(prev, pos-prev); + if (!token.empty()) tokens.push_back(token); + prev = pos + delim.length(); + } + while (pos < str.length() && prev < str.length()); + return tokens; +} + int CommandHandler::executeMain(std::unique_ptr ctx) { if (vm.count("test")) { @@ -295,6 +311,30 @@ int CommandHandler::executeMain(std::unique_ptr ctx) if (!ctx->pack() && !ctx->force) log_error("Packing design failed.\n"); } else { + for (auto &pair : ctx->cells) { + auto &c = pair.second; + auto constr_main = c->attrs.find(ctx->id("NEXTPNR_CONSTRAINT")); + auto constr_child = c->attrs.find(ctx->id("NEXTPNR_CONSTR_CHILDREN")); + if (constr_main!=c->attrs.end()) + { + std::vector val = split(constr_main->second.str.c_str(),";"); + c->constr_x = std::stoi(val[0]); + c->constr_y = std::stoi(val[1]); + c->constr_z = std::stoi(val[2]); + c->constr_abs_z = val[3]=="1" ? true : false; + c->constr_parent = nullptr; + if (val.size()==5) + c->constr_parent = ctx->cells.find(ctx->id(val[4].c_str()))->second.get(); + + } + if (constr_child!=c->attrs.end()) + { + for(auto val : split(constr_child->second.str.c_str(),";")) + { + c->constr_children.push_back(ctx->cells.find(ctx->id(val.c_str()))->second.get()); + } + } + } ctx->assignArchInfo(); } @@ -307,6 +347,16 @@ int CommandHandler::executeMain(std::unique_ptr ctx) if (!ctx->place() && !ctx->force) log_error("Placing design failed.\n"); ctx->check(); + } else { + for (auto &pair : ctx->cells) { + auto &c = pair.second; + auto bel = c->attrs.find(ctx->id("BEL")); + if (bel!=c->attrs.end()) + { + BelId b = ctx->getBelByName(ctx->id(bel->second.c_str())); + ctx->bindBel(b, c.get(), STRENGTH_USER); + } + } } if (do_route) { -- cgit v1.2.3 From 82ed1803c726e912730c3053179f179b90c9b694 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 2 Jun 2019 18:38:20 +0200 Subject: use NEXTPNR_BEL, since BEL is initial placement --- common/command.cc | 2 +- json/jsonwrite.cc | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/command.cc b/common/command.cc index 7d4cd252..d0ef5174 100644 --- a/common/command.cc +++ b/common/command.cc @@ -350,7 +350,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) } else { for (auto &pair : ctx->cells) { auto &c = pair.second; - auto bel = c->attrs.find(ctx->id("BEL")); + auto bel = c->attrs.find(ctx->id("NEXTPNR_BEL")); if (bel!=c->attrs.end()) { BelId b = ctx->getBelByName(ctx->id(bel->second.c_str())); diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 7143bf93..e62a7d2a 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -102,6 +102,11 @@ void write_constraints(std::ostream &f, Context *ctx, CellInfo *cell, bool first f << stringf(",\n"); f << stringf(" \"NEXTPNR_CONSTR_CHILDREN\": "); f << get_string(constr); + if (cell->bel != BelId()) { + f << stringf(",\n"); + f << stringf(" \"NEXTPNR_BEL\": "); + f << get_string(ctx->getBelName(cell->bel).c_str(ctx)); + } } -- cgit v1.2.3 From 44d6f16b66e5f7b89e8cf5711744d6e5f6a40b4a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 3 Jun 2019 21:01:05 +0200 Subject: Support ecp5 read write additional cell info --- common/command.cc | 21 +++++++++++++++++---- json/jsonwrite.cc | 13 +++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/common/command.cc b/common/command.cc index d0ef5174..d700f4ee 100644 --- a/common/command.cc +++ b/common/command.cc @@ -28,6 +28,7 @@ #endif #include +#include #include #include #include @@ -317,15 +318,27 @@ int CommandHandler::executeMain(std::unique_ptr ctx) auto constr_child = c->attrs.find(ctx->id("NEXTPNR_CONSTR_CHILDREN")); if (constr_main!=c->attrs.end()) { - std::vector val = split(constr_main->second.str.c_str(),";"); + std::vector val; + boost::split(val,constr_main->second.str,boost::is_any_of(";")); c->constr_x = std::stoi(val[0]); c->constr_y = std::stoi(val[1]); c->constr_z = std::stoi(val[2]); - c->constr_abs_z = val[3]=="1" ? true : false; + c->constr_abs_z = val[3]=="1"; c->constr_parent = nullptr; - if (val.size()==5) + if (!val[4].empty()) c->constr_parent = ctx->cells.find(ctx->id(val[4].c_str()))->second.get(); - + #ifdef ARCH_ECP5 + c->sliceInfo.using_dff = val[5]=="1"; + c->sliceInfo.has_l6mux = val[6]=="1"; + c->sliceInfo.is_carry = val[7]=="1"; + c->sliceInfo.clk_sig = ctx->id(val[8]); + c->sliceInfo.lsr_sig = ctx->id(val[9]); + c->sliceInfo.clkmux = ctx->id(val[10]); + c->sliceInfo.lsrmux = ctx->id(val[11]); + c->sliceInfo.srmode = ctx->id(val[12]); + c->sliceInfo.sd0 = std::stoi(val[13]); + c->sliceInfo.sd1 = std::stoi(val[14]); + #endif } if (constr_child!=c->attrs.end()) { diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index e62a7d2a..9f29d510 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -89,6 +89,19 @@ void write_constraints(std::ostream &f, Context *ctx, CellInfo *cell, bool first constr += std::to_string(cell->constr_z) + ";"; constr += std::to_string(cell->constr_abs_z ? 1:0) + ";"; constr += cell->constr_parent!=nullptr ? cell->constr_parent->name.c_str(ctx) : ""; +#ifdef ARCH_ECP5 + constr += ";"; + constr += std::to_string(cell->sliceInfo.using_dff ? 1:0) + ";"; + constr += std::to_string(cell->sliceInfo.has_l6mux ? 1:0) + ";"; + constr += std::to_string(cell->sliceInfo.is_carry ? 1:0) + ";"; + constr += std::string(cell->sliceInfo.clk_sig.c_str(ctx)) + ";"; + constr += std::string(cell->sliceInfo.lsr_sig.c_str(ctx)) + ";"; + constr += std::string(cell->sliceInfo.clkmux.c_str(ctx)) + ";"; + constr += std::string(cell->sliceInfo.lsrmux.c_str(ctx)) + ";"; + constr += std::string(cell->sliceInfo.srmode.c_str(ctx)) + ";"; + constr += std::to_string(cell->sliceInfo.sd0) + ";"; + constr += std::to_string(cell->sliceInfo.sd1) + ";"; +#endif f << stringf("%s\n", first ? "" : ","); f << stringf(" \"NEXTPNR_CONSTRAINT\": "); f << get_string(constr); -- cgit v1.2.3 From d5f804832f1accf318e8f62a9989149f5bc0b34a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 3 Jun 2019 21:13:47 +0200 Subject: hacky way to support ECP5 for now --- json/jsonparse.cc | 6 +++++- json/jsonwrite.cc | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index df21eb0f..7d11cd03 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -349,7 +349,11 @@ void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNod else log_error("JSON parameter type of \"%s\' of net \'%s\' not supported\n", pId.c_str(ctx), net->name.c_str(ctx)); - +#ifdef ARCH_ECP5 + if (param_node->data_dict_keys[param_id]== "NEXTPNR_IS_GLOBAL") { + net->is_global = (*dest)[pId].num; + } +#endif if (json_debug) log_info(" Added parameter \'%s\'=%s to net \'%s\' " "of module \'%s\'\n", diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 9f29d510..eb1ed3a4 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -79,6 +79,11 @@ void write_routing(std::ostream &f, Context *ctx, NetInfo *net, bool first) f << stringf("%s\n", first ? "" : ","); f << stringf(" \"NEXTPNR_ROUTING\": "); f << get_string(routing); +#ifdef ARCH_ECP5 + f << stringf(",\n"); + f << stringf(" \"NEXTPNR_IS_GLOBAL\": "); + f << std::to_string(net->is_global ? 1:0); +#endif } void write_constraints(std::ostream &f, Context *ctx, CellInfo *cell, bool first) -- cgit v1.2.3 From 3ae50f85b15437b92b0ab3e6e9c243ea0556fdfc Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 4 Jun 2019 20:08:43 +0200 Subject: Use index as unique identifier for nets --- json/jsonwrite.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index eb1ed3a4..2aaba756 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -142,8 +142,6 @@ void write_module(std::ostream &f, Context *ctx) // TODO: Top level ports f << stringf("\n },\n"); - auto fn = ctx->nets.hash_function(); - f << stringf(" \"cells\": {"); bool first = true; for (auto &pair : ctx->cells) { @@ -175,7 +173,7 @@ void write_module(std::ostream &f, Context *ctx) auto &p = conn.second; f << stringf("%s\n", first2 ? "" : ","); if (p.net) - f << stringf(" %s: [ %d ]", get_name(conn.first,ctx).c_str(), fn(p.net->name)); + f << stringf(" %s: [ %d ]", get_name(conn.first,ctx).c_str(), p.net->name.index); else f << stringf(" %s: [ ]", get_name(conn.first,ctx).c_str()); @@ -196,7 +194,7 @@ void write_module(std::ostream &f, Context *ctx) f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(w->name, ctx).c_str()); f << stringf(" \"hide_name\": %s,\n", w->name.c_str(ctx)[0] == '$' ? "1" : "0"); - f << stringf(" \"bits\": [ %d ] ,\n", fn(pair.first)); + f << stringf(" \"bits\": [ %d ] ,\n", pair.first.index); f << stringf(" \"attributes\": {"); bool first2 = write_parameters(f, ctx, w->attrs); write_routing(f, ctx, w.get(), first2); -- cgit v1.2.3 From 1093d7e1228272ca73114bbc4415c48d6cba76ed Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 11:48:15 +0200 Subject: WIP saving/loading attributes --- common/command.cc | 51 +------------------------------------- common/nextpnr.cc | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ common/nextpnr.h | 3 +++ ecp5/arch.cc | 17 +++++++++++++ ecp5/arch.h | 2 ++ ecp5/pack.cc | 1 + generic/arch.cc | 11 +++++++++ generic/arch.h | 2 ++ ice40/arch.cc | 24 +++++++++++++++--- ice40/arch.h | 2 ++ ice40/pack.cc | 1 + json/jsonparse.cc | 6 +---- json/jsonwrite.cc | 74 +++---------------------------------------------------- 13 files changed, 130 insertions(+), 130 deletions(-) diff --git a/common/command.cc b/common/command.cc index d700f4ee..96008d2b 100644 --- a/common/command.cc +++ b/common/command.cc @@ -311,46 +311,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) run_script_hook("pre-pack"); if (!ctx->pack() && !ctx->force) log_error("Packing design failed.\n"); - } else { - for (auto &pair : ctx->cells) { - auto &c = pair.second; - auto constr_main = c->attrs.find(ctx->id("NEXTPNR_CONSTRAINT")); - auto constr_child = c->attrs.find(ctx->id("NEXTPNR_CONSTR_CHILDREN")); - if (constr_main!=c->attrs.end()) - { - std::vector val; - boost::split(val,constr_main->second.str,boost::is_any_of(";")); - c->constr_x = std::stoi(val[0]); - c->constr_y = std::stoi(val[1]); - c->constr_z = std::stoi(val[2]); - c->constr_abs_z = val[3]=="1"; - c->constr_parent = nullptr; - if (!val[4].empty()) - c->constr_parent = ctx->cells.find(ctx->id(val[4].c_str()))->second.get(); - #ifdef ARCH_ECP5 - c->sliceInfo.using_dff = val[5]=="1"; - c->sliceInfo.has_l6mux = val[6]=="1"; - c->sliceInfo.is_carry = val[7]=="1"; - c->sliceInfo.clk_sig = ctx->id(val[8]); - c->sliceInfo.lsr_sig = ctx->id(val[9]); - c->sliceInfo.clkmux = ctx->id(val[10]); - c->sliceInfo.lsrmux = ctx->id(val[11]); - c->sliceInfo.srmode = ctx->id(val[12]); - c->sliceInfo.sd0 = std::stoi(val[13]); - c->sliceInfo.sd1 = std::stoi(val[14]); - #endif - } - if (constr_child!=c->attrs.end()) - { - for(auto val : split(constr_child->second.str.c_str(),";")) - { - c->constr_children.push_back(ctx->cells.find(ctx->id(val.c_str()))->second.get()); - } - } - } - ctx->assignArchInfo(); - } - + } assign_budget(ctx.get()); ctx->check(); print_utilisation(ctx.get()); @@ -360,16 +321,6 @@ int CommandHandler::executeMain(std::unique_ptr ctx) if (!ctx->place() && !ctx->force) log_error("Placing design failed.\n"); ctx->check(); - } else { - for (auto &pair : ctx->cells) { - auto &c = pair.second; - auto bel = c->attrs.find(ctx->id("NEXTPNR_BEL")); - if (bel!=c->attrs.end()) - { - BelId b = ctx->getBelByName(ctx->id(bel->second.c_str())); - ctx->bindBel(b, c.get(), STRENGTH_USER); - } - } } if (do_route) { diff --git a/common/nextpnr.cc b/common/nextpnr.cc index daaadf28..89b6ed6c 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -453,4 +453,70 @@ DecalXY BaseCtx::constructDecalXY(DecalId decal, float x, float y) return dxy; } +void BaseCtx::commonInfoToAttributes() +{ + for (auto &cell : cells) { + auto ci = cell.second.get(); + if (ci->bel != BelId()) { + ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).c_str(this); + ci->attrs[id("BEL_STRENGTH")] = std::to_string((int)ci->belStrength); + } + if (ci->constr_x!= ci->UNCONSTR) + ci->attrs[id("CONSTR_X")] = std::to_string(ci->constr_x); + if (ci->constr_y!= ci->UNCONSTR) + ci->attrs[id("CONSTR_Y")] = std::to_string(ci->constr_y); + if (ci->constr_z!= ci->UNCONSTR) + ci->attrs[id("CONSTR_Z")] = std::to_string(ci->constr_z); + if (ci->constr_parent!= nullptr) + ci->attrs[id("CONSTR_PARENT")] = ci->constr_parent->name.c_str(this); + } + for (auto &net : getCtx()->nets) { + auto ni = net.second.get(); + std::string routing; + for (auto &item : ni->wires) { + routing += getCtx()->getWireName(item.first).c_str(this); + routing += ","; + if (item.second.pip != PipId()) + routing += getCtx()->getPipName(item.second.pip).c_str(this); + } + ni->attrs[id("ROUTING")] = routing; + } +} + +void BaseCtx::attributesToCommonInfo() +{ + for (auto &cell : cells) { + auto ci = cell.second.get(); + auto val = ci->attrs.find(id("NEXTPNR_BEL")); + if (val != ci->attrs.end()) { + auto str = ci->attrs.find(id("BEL_STRENGTH")); + PlaceStrength strength = PlaceStrength::STRENGTH_USER; + if (str != ci->attrs.end()) + strength = (PlaceStrength)std::stoi(str->second.str); + + BelId b = getCtx()->getBelByName(id(val->second.str)); + getCtx()->bindBel(b, ci, strength); + } + val = ci->attrs.find(id("CONSTR_X")); + if (val != ci->attrs.end()) + ci->constr_x = std::stoi(val->second.str); + + val = ci->attrs.find(id("CONSTR_Y")); + if (val != ci->attrs.end()) + ci->constr_y = std::stoi(val->second.str); + + val = ci->attrs.find(id("CONSTR_Z")); + if (val != ci->attrs.end()) { + ci->constr_z = std::stoi(val->second.str); + ci->constr_abs_z = (ci->constr_z == 0); + } + val = ci->attrs.find(id("CONSTR_PARENT")); + if (val != ci->attrs.end()) { + auto parent = cells.find(id(val->second.str)); + if (parent != cells.end()) + ci->constr_parent = parent->second.get(); + } + } +} + NEXTPNR_NAMESPACE_END diff --git a/common/nextpnr.h b/common/nextpnr.h index 02201463..f7f135fb 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -681,6 +681,9 @@ struct BaseCtx // Workaround for lack of wrappable constructors DecalXY constructDecalXY(DecalId decal, float x, float y); + + void commonInfoToAttributes(); + void attributesToCommonInfo(); }; NEXTPNR_NAMESPACE_END diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 9da8abdf..b5ffa5dc 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -524,6 +524,7 @@ bool Arch::place() } permute_luts(); + archInfoToAttributes(); return true; } @@ -558,6 +559,7 @@ bool Arch::route() log_info(" base %d adder %d\n", speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_base_delay, speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_fanout_adder); #endif + archInfoToAttributes(); return result; } @@ -986,6 +988,21 @@ WireId Arch::getBankECLK(int bank, int eclk) return getWireByLocAndBasename(Location(0, 0), "G_BANK" + std::to_string(bank) + "ECLK" + std::to_string(eclk)); } +void Arch::archInfoToAttributes() +{ + commonInfoToAttributes(); + for (auto &net : getCtx()->nets) { + auto ni = net.second.get(); + ni->attrs[id("IS_GLOBAL")] = ni->is_global ? "1" : "0"; + } +} + +void Arch::attributesToArchInfo() +{ + attributesToCommonInfo(); + assignArchInfo(); +} + #ifdef WITH_HEAP const std::string Arch::defaultPlacer = "heap"; #else diff --git a/ecp5/arch.h b/ecp5/arch.h index 3de06a42..23a264ec 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -994,6 +994,8 @@ struct Arch : BaseCtx bool slicesCompatible(const std::vector &cells) const; void assignArchInfo(); + void archInfoToAttributes(); + void attributesToArchInfo(); void permute_luts(); diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 548c38d8..5b924759 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -2428,6 +2428,7 @@ bool Arch::pack() Ecp5Packer(ctx).pack(); log_info("Checksum: 0x%08x\n", ctx->checksum()); assignArchInfo(); + archInfoToAttributes(); return true; } catch (log_execution_error_exception) { assignArchInfo(); diff --git a/generic/arch.cc b/generic/arch.cc index 5617fa63..674f7af7 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -604,6 +604,17 @@ void Arch::assignArchInfo() } } +void Arch::archInfoToAttributes() +{ + commonInfoToAttributes(); +} + +void Arch::attributesToArchInfo() +{ + attributesToCommonInfo(); + assignArchInfo(); +} + bool Arch::cellsCompatible(const CellInfo **cells, int count) const { const NetInfo *clk = nullptr; diff --git a/generic/arch.h b/generic/arch.h index e9d3593c..f553c613 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -288,6 +288,8 @@ struct Arch : BaseCtx // Internal usage void assignArchInfo(); bool cellsCompatible(const CellInfo **cells, int count) const; + void archInfoToAttributes(); + void attributesToArchInfo(); }; NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.cc b/ice40/arch.cc index d536ad35..659717f8 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -683,16 +683,21 @@ bool Arch::place() } else { log_error("iCE40 architecture does not support placer '%s'\n", placer.c_str()); } + bool retVal = true; if (bool_or_default(settings, id("opt_timing"), false)) { TimingOptCfg tocfg(getCtx()); tocfg.cellTypes.insert(id_ICESTORM_LC); - return timing_opt(getCtx(), tocfg); - } else { - return true; + retVal = timing_opt(getCtx(), tocfg); } + archInfoToAttributes(); + return retVal; } -bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } +bool Arch::route() { + bool retVal = router1(getCtx(), Router1Cfg(getCtx())); + archInfoToAttributes(); + return retVal; +} // ----------------------------------------------------------------------- @@ -1229,6 +1234,17 @@ void Arch::assignCellInfo(CellInfo *cell) } } +void Arch::archInfoToAttributes() +{ + commonInfoToAttributes(); +} + +void Arch::attributesToArchInfo() +{ + attributesToCommonInfo(); + assignArchInfo(); +} + const std::string Arch::defaultPlacer = "sa"; const std::vector Arch::availablePlacers = {"sa", diff --git a/ice40/arch.h b/ice40/arch.h index ea29f4f1..8b6942cb 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -878,6 +878,8 @@ struct Arch : BaseCtx // netlist modifications, and validity checks void assignArchInfo(); void assignCellInfo(CellInfo *cell); + void archInfoToAttributes(); + void attributesToArchInfo(); // ------------------------------------------------- BelPin getIOBSharingPLLPin(BelId pll, IdString pll_pin) const diff --git a/ice40/pack.cc b/ice40/pack.cc index 4cb76add..bc57e7d0 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -1406,6 +1406,7 @@ bool Arch::pack() ctx->assignArchInfo(); constrain_chains(ctx); ctx->assignArchInfo(); + archInfoToAttributes(); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; } catch (log_execution_error_exception) { diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 7d11cd03..41d54188 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -349,11 +349,6 @@ void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNod else log_error("JSON parameter type of \"%s\' of net \'%s\' not supported\n", pId.c_str(ctx), net->name.c_str(ctx)); -#ifdef ARCH_ECP5 - if (param_node->data_dict_keys[param_id]== "NEXTPNR_IS_GLOBAL") { - net->is_global = (*dest)[pId].num; - } -#endif if (json_debug) log_info(" Added parameter \'%s\'=%s to net \'%s\' " "of module \'%s\'\n", @@ -885,6 +880,7 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) log_info("Checksum: 0x%08x\n", ctx->checksum()); log_break(); ctx->settings.emplace(ctx->id("input/json"), filename); + ctx->attributesToCommonInfo(); return true; } catch (log_execution_error_exception) { return false; diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 2aaba756..811a2eec 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -48,7 +48,7 @@ std::string get_name(IdString name, Context *ctx) return get_string(name.c_str(ctx)); } -bool write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) +void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) { bool first = true; for (auto ¶m : parameters) { @@ -60,72 +60,6 @@ bool write_parameters(std::ostream &f, Context *ctx, const std::unordered_mapwires) { - routing += first2 ? "" : ";"; - routing += ctx->getWireName(item.first).c_str(ctx); - routing += ","; - if (item.second.pip != PipId()) - routing += ctx->getPipName(item.second.pip).c_str(ctx); - first2 = false; - } - - f << stringf("%s\n", first ? "" : ","); - f << stringf(" \"NEXTPNR_ROUTING\": "); - f << get_string(routing); -#ifdef ARCH_ECP5 - f << stringf(",\n"); - f << stringf(" \"NEXTPNR_IS_GLOBAL\": "); - f << std::to_string(net->is_global ? 1:0); -#endif -} - -void write_constraints(std::ostream &f, Context *ctx, CellInfo *cell, bool first) -{ - std::string constr; - constr += std::to_string(cell->constr_x) + ";"; - constr += std::to_string(cell->constr_y) + ";"; - constr += std::to_string(cell->constr_z) + ";"; - constr += std::to_string(cell->constr_abs_z ? 1:0) + ";"; - constr += cell->constr_parent!=nullptr ? cell->constr_parent->name.c_str(ctx) : ""; -#ifdef ARCH_ECP5 - constr += ";"; - constr += std::to_string(cell->sliceInfo.using_dff ? 1:0) + ";"; - constr += std::to_string(cell->sliceInfo.has_l6mux ? 1:0) + ";"; - constr += std::to_string(cell->sliceInfo.is_carry ? 1:0) + ";"; - constr += std::string(cell->sliceInfo.clk_sig.c_str(ctx)) + ";"; - constr += std::string(cell->sliceInfo.lsr_sig.c_str(ctx)) + ";"; - constr += std::string(cell->sliceInfo.clkmux.c_str(ctx)) + ";"; - constr += std::string(cell->sliceInfo.lsrmux.c_str(ctx)) + ";"; - constr += std::string(cell->sliceInfo.srmode.c_str(ctx)) + ";"; - constr += std::to_string(cell->sliceInfo.sd0) + ";"; - constr += std::to_string(cell->sliceInfo.sd1) + ";"; -#endif - f << stringf("%s\n", first ? "" : ","); - f << stringf(" \"NEXTPNR_CONSTRAINT\": "); - f << get_string(constr); - - constr = ""; - for(auto &item : cell->constr_children) - { - if (!constr.empty()) constr += std::string(";"); - constr += item->name.c_str(ctx); - } - f << stringf(",\n"); - f << stringf(" \"NEXTPNR_CONSTR_CHILDREN\": "); - f << get_string(constr); - if (cell->bel != BelId()) { - f << stringf(",\n"); - f << stringf(" \"NEXTPNR_BEL\": "); - f << get_string(ctx->getBelName(cell->bel).c_str(ctx)); - } - } void write_module(std::ostream &f, Context *ctx) @@ -154,8 +88,7 @@ void write_module(std::ostream &f, Context *ctx) write_parameters(f, ctx, c->params); f << stringf("\n },\n"); f << stringf(" \"attributes\": {"); - bool first3 = write_parameters(f, ctx, c->attrs); - write_constraints(f, ctx, c.get(), first3); + write_parameters(f, ctx, c->attrs); f << stringf("\n },\n"); f << stringf(" \"port_directions\": {"); bool first2 = true; @@ -196,8 +129,7 @@ void write_module(std::ostream &f, Context *ctx) f << stringf(" \"hide_name\": %s,\n", w->name.c_str(ctx)[0] == '$' ? "1" : "0"); f << stringf(" \"bits\": [ %d ] ,\n", pair.first.index); f << stringf(" \"attributes\": {"); - bool first2 = write_parameters(f, ctx, w->attrs); - write_routing(f, ctx, w.get(), first2); + write_parameters(f, ctx, w->attrs); f << stringf("\n }\n"); f << stringf(" }"); first = false; -- cgit v1.2.3 From 15a1d4f582e9d1706665fd862ade9ef3671ec8d6 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 7 Jun 2019 11:55:20 +0100 Subject: ecp5: Use an attribute to store is_global Signed-off-by: David Shah --- ecp5/arch.cc | 3 ++- ecp5/globals.cc | 2 +- ecp5/pack.cc | 8 ++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index b5ffa5dc..1abbd2aa 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -531,6 +531,7 @@ bool Arch::place() bool Arch::route() { route_ecp5_globals(getCtx()); + assignArchInfo(); assign_budget(getCtx(), true); bool result = router1(getCtx(), Router1Cfg(getCtx())); @@ -994,7 +995,7 @@ void Arch::archInfoToAttributes() for (auto &net : getCtx()->nets) { auto ni = net.second.get(); ni->attrs[id("IS_GLOBAL")] = ni->is_global ? "1" : "0"; - } + } } void Arch::attributesToArchInfo() diff --git a/ecp5/globals.cc b/ecp5/globals.cc index fae2c683..026f3a85 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -382,7 +382,7 @@ class Ecp5GlobalRouter glbnet->name = ctx->id("$glbnet$" + net->name.str(ctx)); glbnet->driver.cell = dcc.get(); glbnet->driver.port = id_CLKO; - glbnet->is_global = true; + glbnet->attrs[ctx->id("ECP5_IS_GLOBAL")] = "1"; dcc->ports[id_CLKO].net = glbnet.get(); std::vector keep_users; diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 5b924759..20130aad 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -1508,7 +1508,8 @@ class Ecp5Packer std::unique_ptr promoted_ecknet(new NetInfo); promoted_ecknet->name = eckname; - promoted_ecknet->is_global = true; // Prevents router etc touching this special net + promoted_ecknet->attrs[ctx->id("ECP5_IS_GLOBAL")] = + "1"; // Prevents router etc touching this special net eclk.buf = promoted_ecknet.get(); NPNR_ASSERT(!ctx->nets.count(eckname)); ctx->nets[eckname] = std::move(promoted_ecknet); @@ -1654,7 +1655,7 @@ class Ecp5Packer port.c_str(ctx), ci->name.c_str(ctx), usr.port.c_str(ctx), usr.cell->name.c_str(ctx)); } - pn->is_global = true; + pn->attrs[ctx->id("ECP5_IS_GLOBAL")] = "1"; } for (auto zport : @@ -2470,6 +2471,9 @@ void Arch::assignArchInfo() ci->sliceInfo.has_l6mux = true; } } + for (auto net : sorted(nets)) { + net.second->is_global = bool_or_default(net.second->attrs, id("ECP5_IS_GLOBAL")); + } } NEXTPNR_NAMESPACE_END -- cgit v1.2.3 From a8871ea8aa6e17b2fbc8f70ce0f96cca18bac928 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 13:18:43 +0200 Subject: Cleanup and fixes, flow works now --- common/command.cc | 16 ---------------- common/nextpnr.cc | 35 +++++++++++++++++++++++++++++++---- json/jsonparse.cc | 2 +- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/common/command.cc b/common/command.cc index 96008d2b..46d6d014 100644 --- a/common/command.cc +++ b/common/command.cc @@ -233,22 +233,6 @@ void CommandHandler::setupContext(Context *ctx) ctx->timing_driven = false; } -std::vector split(const std::string& str, const std::string& delim) -{ - std::vector tokens; - size_t prev = 0, pos = 0; - do - { - pos = str.find(delim, prev); - if (pos == std::string::npos) pos = str.length(); - std::string token = str.substr(prev, pos-prev); - if (!token.empty()) tokens.push_back(token); - prev = pos + delim.length(); - } - while (pos < str.length() && prev < str.length()); - return tokens; -} - int CommandHandler::executeMain(std::unique_ptr ctx) { if (vm.count("test")) { diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 89b6ed6c..09fff8d1 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -19,6 +19,7 @@ #include "nextpnr.h" #include "log.h" +#include NEXTPNR_NAMESPACE_BEGIN @@ -458,6 +459,9 @@ void BaseCtx::commonInfoToAttributes() for (auto &cell : cells) { auto ci = cell.second.get(); if (ci->bel != BelId()) { + if (ci->attrs.find(id("BEL")) != ci->attrs.end()) { + ci->attrs.erase(ci->attrs.find(id("BEL"))); + } ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).c_str(this); ci->attrs[id("BEL_STRENGTH")] = std::to_string((int)ci->belStrength); } @@ -465,10 +469,21 @@ void BaseCtx::commonInfoToAttributes() ci->attrs[id("CONSTR_X")] = std::to_string(ci->constr_x); if (ci->constr_y!= ci->UNCONSTR) ci->attrs[id("CONSTR_Y")] = std::to_string(ci->constr_y); - if (ci->constr_z!= ci->UNCONSTR) + if (ci->constr_z!= ci->UNCONSTR) { ci->attrs[id("CONSTR_Z")] = std::to_string(ci->constr_z); + ci->attrs[id("CONSTR_ABS_Z")] = std::to_string(ci->constr_abs_z ? 1 : 0); + } if (ci->constr_parent!= nullptr) ci->attrs[id("CONSTR_PARENT")] = ci->constr_parent->name.c_str(this); + if (!ci->constr_children.empty()) { + std::string constr = ""; + for(auto &item : ci->constr_children) + { + if (!constr.empty()) constr += std::string(";"); + constr += item->name.c_str(this); + } + ci->attrs[id("CONSTR_CHILDREN")] = constr; + } } for (auto &net : getCtx()->nets) { auto ni = net.second.get(); @@ -506,16 +521,28 @@ void BaseCtx::attributesToCommonInfo() ci->constr_y = std::stoi(val->second.str); val = ci->attrs.find(id("CONSTR_Z")); - if (val != ci->attrs.end()) { + if (val != ci->attrs.end()) ci->constr_z = std::stoi(val->second.str); - ci->constr_abs_z = (ci->constr_z == 0); - } + + val = ci->attrs.find(id("CONSTR_ABS_Z")); + if (val != ci->attrs.end()) + ci->constr_abs_z = std::stoi(val->second.str)==1; + val = ci->attrs.find(id("CONSTR_PARENT")); if (val != ci->attrs.end()) { auto parent = cells.find(id(val->second.str)); if (parent != cells.end()) ci->constr_parent = parent->second.get(); } + val = ci->attrs.find(id("CONSTR_CHILDREN")); + if (val != ci->attrs.end()) { + std::vector strs; + boost::split(strs,val->second.str,boost::is_any_of(";")); + for(auto val : strs) + { + ci->constr_children.push_back(cells.find(id(val.c_str()))->second.get()); + } + } } } diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 41d54188..1ff4f5af 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -880,7 +880,7 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) log_info("Checksum: 0x%08x\n", ctx->checksum()); log_break(); ctx->settings.emplace(ctx->id("input/json"), filename); - ctx->attributesToCommonInfo(); + ctx->attributesToArchInfo(); return true; } catch (log_execution_error_exception) { return false; -- cgit v1.2.3 From 54175f918760d3ee2a4d89f926f9e0652d223134 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 13:24:16 +0200 Subject: No need for this one --- ecp5/arch.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 1abbd2aa..044ff4d9 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -992,10 +992,6 @@ WireId Arch::getBankECLK(int bank, int eclk) void Arch::archInfoToAttributes() { commonInfoToAttributes(); - for (auto &net : getCtx()->nets) { - auto ni = net.second.get(); - ni->attrs[id("IS_GLOBAL")] = ni->is_global ? "1" : "0"; - } } void Arch::attributesToArchInfo() -- cgit v1.2.3 From 78e6631f766194c078b6cd32d520146e6ab257a4 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 13:49:19 +0200 Subject: Cleanup --- common/nextpnr.cc | 5 +++-- common/nextpnr.h | 4 ++-- ecp5/arch.cc | 11 ----------- ecp5/arch.h | 2 -- generic/arch.cc | 11 ----------- generic/arch.h | 2 -- ice40/arch.cc | 11 ----------- ice40/arch.h | 2 -- 8 files changed, 5 insertions(+), 43 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 09fff8d1..09d8349f 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -454,7 +454,7 @@ DecalXY BaseCtx::constructDecalXY(DecalId decal, float x, float y) return dxy; } -void BaseCtx::commonInfoToAttributes() +void BaseCtx::archInfoToAttributes() { for (auto &cell : cells) { auto ci = cell.second.get(); @@ -498,7 +498,7 @@ void BaseCtx::commonInfoToAttributes() } } -void BaseCtx::attributesToCommonInfo() +void BaseCtx::attributesToArchInfo() { for (auto &cell : cells) { auto ci = cell.second.get(); @@ -544,6 +544,7 @@ void BaseCtx::attributesToCommonInfo() } } } + getCtx()->assignArchInfo(); } NEXTPNR_NAMESPACE_END diff --git a/common/nextpnr.h b/common/nextpnr.h index f7f135fb..8e47dcda 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -682,8 +682,8 @@ struct BaseCtx // Workaround for lack of wrappable constructors DecalXY constructDecalXY(DecalId decal, float x, float y); - void commonInfoToAttributes(); - void attributesToCommonInfo(); + void archInfoToAttributes(); + void attributesToArchInfo(); }; NEXTPNR_NAMESPACE_END diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 044ff4d9..e796c9db 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -989,17 +989,6 @@ WireId Arch::getBankECLK(int bank, int eclk) return getWireByLocAndBasename(Location(0, 0), "G_BANK" + std::to_string(bank) + "ECLK" + std::to_string(eclk)); } -void Arch::archInfoToAttributes() -{ - commonInfoToAttributes(); -} - -void Arch::attributesToArchInfo() -{ - attributesToCommonInfo(); - assignArchInfo(); -} - #ifdef WITH_HEAP const std::string Arch::defaultPlacer = "heap"; #else diff --git a/ecp5/arch.h b/ecp5/arch.h index 23a264ec..3de06a42 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -994,8 +994,6 @@ struct Arch : BaseCtx bool slicesCompatible(const std::vector &cells) const; void assignArchInfo(); - void archInfoToAttributes(); - void attributesToArchInfo(); void permute_luts(); diff --git a/generic/arch.cc b/generic/arch.cc index 674f7af7..5617fa63 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -604,17 +604,6 @@ void Arch::assignArchInfo() } } -void Arch::archInfoToAttributes() -{ - commonInfoToAttributes(); -} - -void Arch::attributesToArchInfo() -{ - attributesToCommonInfo(); - assignArchInfo(); -} - bool Arch::cellsCompatible(const CellInfo **cells, int count) const { const NetInfo *clk = nullptr; diff --git a/generic/arch.h b/generic/arch.h index f553c613..e9d3593c 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -288,8 +288,6 @@ struct Arch : BaseCtx // Internal usage void assignArchInfo(); bool cellsCompatible(const CellInfo **cells, int count) const; - void archInfoToAttributes(); - void attributesToArchInfo(); }; NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.cc b/ice40/arch.cc index 659717f8..b7207ca9 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -1234,17 +1234,6 @@ void Arch::assignCellInfo(CellInfo *cell) } } -void Arch::archInfoToAttributes() -{ - commonInfoToAttributes(); -} - -void Arch::attributesToArchInfo() -{ - attributesToCommonInfo(); - assignArchInfo(); -} - const std::string Arch::defaultPlacer = "sa"; const std::vector Arch::availablePlacers = {"sa", diff --git a/ice40/arch.h b/ice40/arch.h index 8b6942cb..ea29f4f1 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -878,8 +878,6 @@ struct Arch : BaseCtx // netlist modifications, and validity checks void assignArchInfo(); void assignCellInfo(CellInfo *cell); - void archInfoToAttributes(); - void attributesToArchInfo(); // ------------------------------------------------- BelPin getIOBSharingPLLPin(BelId pll, IdString pll_pin) const -- cgit v1.2.3 From 07b21c51299d7ec38aca2a7994542e3c50f93aa3 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 13:58:21 +0200 Subject: Add vcc and gnd nets and cells only if needed --- ice40/pack.cc | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/ice40/pack.cc b/ice40/pack.cc index bc57e7d0..0a62a5ca 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -340,6 +340,12 @@ static void pack_constants(Context *ctx) gnd_net->driver.cell = gnd_cell.get(); gnd_net->driver.port = ctx->id("O"); gnd_cell->ports.at(ctx->id("O")).net = gnd_net.get(); + + NetInfo* gnd_net_info = gnd_net.get(); + if (ctx->nets.find(ctx->id("$PACKER_GND_NET"))!=ctx->nets.end()) + { + gnd_net_info = ctx->nets.find(ctx->id("$PACKER_GND_NET"))->second.get(); + } std::unique_ptr vcc_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_VCC"); vcc_cell->params[ctx->id("LUT_INIT")] = "1"; @@ -348,6 +354,12 @@ static void pack_constants(Context *ctx) vcc_net->driver.cell = vcc_cell.get(); vcc_net->driver.port = ctx->id("O"); vcc_cell->ports.at(ctx->id("O")).net = vcc_net.get(); + + NetInfo* vcc_net_info = vcc_net.get(); + if (ctx->nets.find(ctx->id("$PACKER_VCC_NET"))!=ctx->nets.end()) + { + vcc_net_info = ctx->nets.find(ctx->id("$PACKER_VCC_NET"))->second.get(); + } std::vector dead_nets; @@ -357,26 +369,29 @@ static void pack_constants(Context *ctx) NetInfo *ni = net.second; if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { IdString drv_cell = ni->driver.cell->name; - set_net_constant(ctx, ni, gnd_net.get(), false); + set_net_constant(ctx, ni, gnd_net_info, false); gnd_used = true; dead_nets.push_back(net.first); ctx->cells.erase(drv_cell); } else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) { IdString drv_cell = ni->driver.cell->name; - set_net_constant(ctx, ni, vcc_net.get(), true); + set_net_constant(ctx, ni, vcc_net_info, true); dead_nets.push_back(net.first); ctx->cells.erase(drv_cell); } } - if (gnd_used) { + if (gnd_used && (gnd_net_info == gnd_net.get())) { ctx->cells[gnd_cell->name] = std::move(gnd_cell); ctx->nets[gnd_net->name] = std::move(gnd_net); } // Vcc cell always inserted for now, as it may be needed during carry legalisation (TODO: trim later if actually // never used?) - ctx->cells[vcc_cell->name] = std::move(vcc_cell); - ctx->nets[vcc_net->name] = std::move(vcc_net); + if (vcc_net_info == vcc_net.get()) + { + ctx->cells[vcc_cell->name] = std::move(vcc_cell); + ctx->nets[vcc_net->name] = std::move(vcc_net); + } for (auto dn : dead_nets) { ctx->nets.erase(dn); -- cgit v1.2.3 From 5b62f33dd57ffd8df3aa4922f94d36ff3d288fbd Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 14:23:57 +0200 Subject: Restore routing from json --- common/nextpnr.cc | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 09d8349f..fd2efa22 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -488,11 +488,14 @@ void BaseCtx::archInfoToAttributes() for (auto &net : getCtx()->nets) { auto ni = net.second.get(); std::string routing; + bool first = true; for (auto &item : ni->wires) { + if (!first) routing += ";"; routing += getCtx()->getWireName(item.first).c_str(this); - routing += ","; + routing += ";"; if (item.second.pip != PipId()) routing += getCtx()->getPipName(item.second.pip).c_str(this); + first = false; } ni->attrs[id("ROUTING")] = routing; } @@ -544,6 +547,23 @@ void BaseCtx::attributesToArchInfo() } } } + for (auto &net : getCtx()->nets) { + auto ni = net.second.get(); + auto val = ni->attrs.find(id("ROUTING")); + if (val != ni->attrs.end()) { + std::vector strs; + boost::split(strs,val->second.str,boost::is_any_of(";")); + for(size_t i=0;ibindWire(getCtx()->getWireByName(id(wire)), ni, STRENGTH_WEAK); + else + getCtx()->bindPip(getCtx()->getPipByName(id(pip)), ni, STRENGTH_WEAK); + } + } + } getCtx()->assignArchInfo(); } -- cgit v1.2.3 From ef1a5fa60653a89fe008288aa4da00c481db2c46 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 14:31:13 +0200 Subject: Save/restore net strength --- common/nextpnr.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index fd2efa22..a026b60d 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -495,6 +495,7 @@ void BaseCtx::archInfoToAttributes() routing += ";"; if (item.second.pip != PipId()) routing += getCtx()->getPipName(item.second.pip).c_str(this); + routing += ";" + std::to_string(item.second.strength); first = false; } ni->attrs[id("ROUTING")] = routing; @@ -553,14 +554,15 @@ void BaseCtx::attributesToArchInfo() if (val != ni->attrs.end()) { std::vector strs; boost::split(strs,val->second.str,boost::is_any_of(";")); - for(size_t i=0;ibindWire(getCtx()->getWireByName(id(wire)), ni, STRENGTH_WEAK); + getCtx()->bindWire(getCtx()->getWireByName(id(wire)), ni, strength); else - getCtx()->bindPip(getCtx()->getPipByName(id(pip)), ni, STRENGTH_WEAK); + getCtx()->bindPip(getCtx()->getPipByName(id(pip)), ni, strength); } } } -- cgit v1.2.3 From d9b0bac248a12466cd2b62d02ec11b2e60d25019 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Jun 2019 16:11:11 +0200 Subject: Save top level attrs and store current step --- common/nextpnr.h | 3 +++ ecp5/arch.cc | 2 ++ ecp5/pack.cc | 1 + generic/arch.cc | 12 ++++++++++-- generic/pack.cc | 1 + ice40/arch.cc | 2 ++ ice40/pack.cc | 1 + json/jsonparse.cc | 30 +++++++++++++++++++++++++++++- json/jsonwrite.cc | 8 ++++++-- 9 files changed, 55 insertions(+), 5 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 8e47dcda..3b17920d 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -550,6 +550,9 @@ struct BaseCtx // Floorplanning regions std::unordered_map> region; + // Context meta data + std::unordered_map attrs; + BaseCtx() { idstring_str_to_idx = new std::unordered_map; diff --git a/ecp5/arch.cc b/ecp5/arch.cc index e796c9db..2061bf4a 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -524,6 +524,7 @@ bool Arch::place() } permute_luts(); + getCtx()->attrs[getCtx()->id("step")] = "place"; archInfoToAttributes(); return true; } @@ -560,6 +561,7 @@ bool Arch::route() log_info(" base %d adder %d\n", speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_base_delay, speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_fanout_adder); #endif + getCtx()->attrs[getCtx()->id("step")] = "route"; archInfoToAttributes(); return result; } diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 20130aad..4077bfed 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -2429,6 +2429,7 @@ bool Arch::pack() Ecp5Packer(ctx).pack(); log_info("Checksum: 0x%08x\n", ctx->checksum()); assignArchInfo(); + ctx->attrs[ctx->id("step")] = "pack"; archInfoToAttributes(); return true; } catch (log_execution_error_exception) { diff --git a/generic/arch.cc b/generic/arch.cc index 5617fa63..f6f7ff87 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -496,13 +496,21 @@ bool Arch::place() std::string placer = str_or_default(settings, id("placer"), defaultPlacer); // FIXME: No HeAP because it needs a list of IO buffers if (placer == "sa") { - return placer1(getCtx(), Placer1Cfg(getCtx())); + bool retVal = placer1(getCtx(), Placer1Cfg(getCtx())); + getCtx()->attrs[getCtx()->id("step")] = "place"; + archInfoToAttributes(); + return retVal; } else { log_error("Generic architecture does not support placer '%s'\n", placer.c_str()); } } -bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } +bool Arch::route() { + bool retVal = router1(getCtx(), Router1Cfg(getCtx())); + getCtx()->attrs[getCtx()->id("step")] = "route"; + archInfoToAttributes(); + return retVal; +} // --------------------------------------------------------------- diff --git a/generic/pack.cc b/generic/pack.cc index 26ae9182..0d47ea19 100644 --- a/generic/pack.cc +++ b/generic/pack.cc @@ -282,6 +282,7 @@ bool Arch::pack() pack_io(ctx); pack_lut_lutffs(ctx); pack_nonlut_ffs(ctx); + ctx->attrs[ctx->id("step")] = "pack"; ctx->assignArchInfo(); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; diff --git a/ice40/arch.cc b/ice40/arch.cc index b7207ca9..4945f5b3 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -689,12 +689,14 @@ bool Arch::place() tocfg.cellTypes.insert(id_ICESTORM_LC); retVal = timing_opt(getCtx(), tocfg); } + getCtx()->attrs[getCtx()->id("step")] = "place"; archInfoToAttributes(); return retVal; } bool Arch::route() { bool retVal = router1(getCtx(), Router1Cfg(getCtx())); + getCtx()->attrs[getCtx()->id("step")] = "route"; archInfoToAttributes(); return retVal; } diff --git a/ice40/pack.cc b/ice40/pack.cc index 0a62a5ca..ce39c903 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -1421,6 +1421,7 @@ bool Arch::pack() ctx->assignArchInfo(); constrain_chains(ctx); ctx->assignArchInfo(); + ctx->attrs[ctx->id("step")] = "pack"; archInfoToAttributes(); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 1ff4f5af..a36f891d 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -355,6 +355,27 @@ void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNod pId.c_str(ctx), net->attrs[pId].c_str(), net->name.c_str(ctx), modname.c_str()); } +void json_import_top_attrib(Context *ctx, string &modname, JsonNode *param_node, + std::unordered_map *dest, int param_id) +{ + // + JsonNode *param; + IdString pId; + // + 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)); + if (json_debug) + log_info(" Added parameter \'%s\'=%s module \'%s\'\n", + pId.c_str(ctx), (*dest)[pId].c_str(), modname.c_str()); +} + static int const_net_idx = 0; template @@ -714,7 +735,14 @@ void json_import(Context *ctx, string modname, JsonNode *node) return; log_info("Importing module %s\n", modname.c_str()); - + ctx->attrs[ctx->id("module")] = modname; + JsonNode *attr_node = node->data_dict.at("attributes"); + for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { + json_import_top_attrib(ctx, modname, attr_node, &ctx->attrs, attrid); + } + if (ctx->attrs.find(ctx->id("step")) == ctx->attrs.end()) + ctx->attrs[ctx->id("step")] = "synth"; + JsonNode *ports_parent = nullptr; if (node->data_dict.count("ports") > 0) ports_parent = node->data_dict.at("ports"); diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 811a2eec..19c43d7c 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -64,13 +64,17 @@ void write_parameters(std::ostream &f, Context *ctx, const std::unordered_mapattrs.find(ctx->id("module")); + if (val != ctx->attrs.end()) + f << stringf(" %s: {\n", get_string(val->second.str).c_str()); + else + f << stringf(" %s: {\n", get_string("top").c_str()); // TODO: check if this is better to be separate /*f << stringf(" \"settings\": {"); write_parameters(f, ctx, ctx->settings, true); f << stringf("\n },\n");*/ f << stringf(" \"attributes\": {"); - // TODO: Top level attributes + write_parameters(f, ctx, ctx->attrs, true); f << stringf("\n },\n"); f << stringf(" \"ports\": {"); // TODO: Top level ports -- cgit v1.2.3 From 856760599e51bd4c6da34112c993dc8bfb995f36 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 12 Jun 2019 18:34:34 +0200 Subject: Use properties for settings and save in json --- common/nextpnr.h | 2 +- common/project.cc | 6 ++++-- common/settings.h | 20 ++++++-------------- ecp5/lpf.cc | 2 +- ice40/pcf.cc | 2 +- json/jsonparse.cc | 2 +- json/jsonwrite.cc | 5 ++--- 7 files changed, 16 insertions(+), 23 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 3b17920d..66134456 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -541,7 +541,7 @@ struct BaseCtx mutable std::vector *idstring_idx_to_str; // Project settings and config switches - std::unordered_map settings; + std::unordered_map settings; // Placed nets and cells. std::unordered_map> nets; diff --git a/common/project.cc b/common/project.cc index b0ebe961..3b4e67e4 100644 --- a/common/project.cc +++ b/common/project.cc @@ -74,7 +74,7 @@ void ProjectHandler::save(Context *ctx, std::string filename) std::string path = "project.settings."; path += item.first.c_str(ctx); std::replace(path.begin(), path.end(), '/', '.'); - root.put(path, item.second); + root.put(path, item.second.str); } pt::write_json(f, root); } catch (...) { @@ -88,7 +88,9 @@ void addSettings(Context *ctx, std::string path, pt::ptree sub) const std::string &key = v.first; const boost::property_tree::ptree &subtree = v.second; if (subtree.empty()) { - ctx->settings.emplace(ctx->id(path + key), subtree.get_value().c_str()); + Property p; + p.setString(subtree.get_value().c_str()); + ctx->settings.emplace(ctx->id(path + key), p); } else { addSettings(ctx, path + key + "/", subtree); } diff --git a/common/settings.h b/common/settings.h index b57947c9..9d43c774 100644 --- a/common/settings.h +++ b/common/settings.h @@ -34,10 +34,10 @@ class Settings { try { IdString id = ctx->id(name); - auto pair = ctx->settings.emplace(id, std::to_string(defaultValue)); - if (!pair.second) { - return boost::lexical_cast(pair.first->second); - } + if (ctx->settings.find(id) != ctx->settings.end()) + return boost::lexical_cast(ctx->settings.find(id)->second.str); + else + ctx->settings[ctx->id(name)] = std::to_string(defaultValue); } catch (boost::bad_lexical_cast &) { log_error("Problem reading setting %s, using default value\n", name); @@ -53,20 +53,12 @@ class Settings template inline void Settings::set(const char *name, T value) { - IdString id = ctx->id(name); - auto pair = ctx->settings.emplace(id, std::to_string(value)); - if (!pair.second) { - ctx->settings[pair.first->first] = value; - } + ctx->settings[ctx->id(name)] = std::to_string(value); } template <> inline void Settings::set(const char *name, std::string value) { - IdString id = ctx->id(name); - auto pair = ctx->settings.emplace(id, value); - if (!pair.second) { - ctx->settings[pair.first->first] = value; - } + ctx->settings[ctx->id(name)] = value; } NEXTPNR_NAMESPACE_END diff --git a/ecp5/lpf.cc b/ecp5/lpf.cc index 4ac70fc9..ceb1d7ae 100644 --- a/ecp5/lpf.cc +++ b/ecp5/lpf.cc @@ -133,7 +133,7 @@ bool Arch::applyLPF(std::string filename, std::istream &in) } if (!isempty(linebuf)) log_error("unexpected end of LPF file\n"); - settings.emplace(id("input/lpf"), filename); + settings[id("input/lpf")] = filename; return true; } catch (log_execution_error_exception) { return false; diff --git a/ice40/pcf.cc b/ice40/pcf.cc index a8273dd6..91935bee 100644 --- a/ice40/pcf.cc +++ b/ice40/pcf.cc @@ -116,7 +116,7 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in) } } } - ctx->settings.emplace(ctx->id("input/pcf"), filename); + ctx->settings[ctx->id("input/pcf")] = filename; return true; } catch (log_execution_error_exception) { return false; diff --git a/json/jsonparse.cc b/json/jsonparse.cc index a36f891d..f0d0069a 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -907,7 +907,7 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) log_info("Checksum: 0x%08x\n", ctx->checksum()); log_break(); - ctx->settings.emplace(ctx->id("input/json"), filename); + ctx->settings[ctx->id("input/json")] = filename; ctx->attributesToArchInfo(); return true; } catch (log_execution_error_exception) { diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 19c43d7c..ac54bc4e 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -69,10 +69,9 @@ void write_module(std::ostream &f, Context *ctx) f << stringf(" %s: {\n", get_string(val->second.str).c_str()); else f << stringf(" %s: {\n", get_string("top").c_str()); - // TODO: check if this is better to be separate - /*f << stringf(" \"settings\": {"); + f << stringf(" \"settings\": {"); write_parameters(f, ctx, ctx->settings, true); - f << stringf("\n },\n");*/ + f << stringf("\n },\n"); f << stringf(" \"attributes\": {"); write_parameters(f, ctx, ctx->attrs, true); f << stringf("\n },\n"); -- cgit v1.2.3 From 1cd4a4d17aeaab26664add714c8a02f76f6a6a90 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 13 Jun 2019 17:42:41 +0200 Subject: Remove concept of project and code connected --- common/command.cc | 16 +----- common/command.h | 4 +- common/project.cc | 146 ----------------------------------------------------- common/project.h | 45 ----------------- ecp5/project.cc | 55 -------------------- generic/project.cc | 37 -------------- gui/basewindow.cc | 76 ---------------------------- gui/basewindow.h | 8 --- ice40/project.cc | 76 ---------------------------- 9 files changed, 4 insertions(+), 459 deletions(-) delete mode 100644 common/project.cc delete mode 100644 common/project.h delete mode 100644 ecp5/project.cc delete mode 100644 generic/project.cc delete mode 100644 ice40/project.cc diff --git a/common/command.cc b/common/command.cc index 46d6d014..43707c83 100644 --- a/common/command.cc +++ b/common/command.cc @@ -149,8 +149,6 @@ po::options_description CommandHandler::getGeneralOptions() general.add_options()("freq", po::value(), "set target frequency for design in MHz"); general.add_options()("timing-allow-fail", "allow timing to fail in design"); general.add_options()("no-tmdriv", "disable timing-driven placement"); - general.add_options()("save", po::value(), "project file to write"); - general.add_options()("load", po::value(), "project file to read"); return general; } @@ -254,8 +252,6 @@ int CommandHandler::executeMain(std::unique_ptr ctx) customAfterLoad(w.getContext()); w.notifyChangeContext(); w.updateLoaded(); - } else if (vm.count("load")) { - w.projectLoad(vm["load"].as()); } else w.notifyChangeContext(); } catch (log_execution_error_exception) { @@ -286,7 +282,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) execute_python_file(filename.c_str()); } else #endif - if (vm.count("json") || vm.count("load")) { + if (vm.count("json")) { bool do_pack = vm.count("pack-only")!=0 || vm.count("no-pack")==0; bool do_place = vm.count("pack-only")==0 && vm.count("no-place")==0; bool do_route = vm.count("pack-only")==0 && vm.count("no-route")==0; @@ -323,9 +319,6 @@ int CommandHandler::executeMain(std::unique_ptr ctx) if (!write_json_file(f, filename, ctx.get())) log_error("Saving design failed.\n"); } - if (vm.count("save")) { - project.save(ctx.get(), vm["save"].as()); - } #ifndef NO_PYTHON deinit_python(); @@ -361,12 +354,7 @@ int CommandHandler::exec() if (executeBeforeContext()) return 0; - std::unique_ptr ctx; - if (vm.count("load") && vm.count("gui") == 0) { - ctx = project.load(vm["load"].as()); - } else { - ctx = createContext(); - } + std::unique_ptr ctx = createContext(); settings = std::unique_ptr(new Settings(ctx.get())); setupContext(ctx.get()); setupArchContext(ctx.get()); diff --git a/common/command.h b/common/command.h index d0f1d328..c3274197 100644 --- a/common/command.h +++ b/common/command.h @@ -23,7 +23,7 @@ #include #include "nextpnr.h" -#include "project.h" +//#include "project.h" #include "settings.h" NEXTPNR_NAMESPACE_BEGIN @@ -66,7 +66,7 @@ class CommandHandler po::positional_options_description pos; int argc; char **argv; - ProjectHandler project; + //ProjectHandler project; std::ofstream logfile; }; diff --git a/common/project.cc b/common/project.cc deleted file mode 100644 index 3b4e67e4..00000000 --- a/common/project.cc +++ /dev/null @@ -1,146 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Miodrag Milanovic - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "project.h" -#include -#include -#include -#include -#include "jsonparse.h" -#include "log.h" - -NEXTPNR_NAMESPACE_BEGIN - -boost::filesystem::path make_relative(boost::filesystem::path child, boost::filesystem::path parent) -{ - boost::filesystem::path::const_iterator parentIter = parent.begin(); - boost::filesystem::path::const_iterator childIter = child.begin(); - - while (parentIter != parent.end() && childIter != child.end() && (*childIter) == (*parentIter)) { - ++childIter; - ++parentIter; - } - - boost::filesystem::path finalPath; - while (parentIter != parent.end()) { - finalPath /= ".."; - ++parentIter; - } - - while (childIter != child.end()) { - finalPath /= *childIter; - ++childIter; - } - - return finalPath; -} - -void ProjectHandler::save(Context *ctx, std::string filename) -{ - try { - boost::filesystem::path proj(filename); - std::ofstream f(filename); - pt::ptree root; - - log_info("Saving project %s...\n", filename.c_str()); - log_break(); - - root.put("project.version", 1); - root.put("project.name", boost::filesystem::basename(filename)); - root.put("project.arch.name", ctx->archId().c_str(ctx)); - root.put("project.arch.type", ctx->archArgsToId(ctx->archArgs()).c_str(ctx)); - std::string fn = ctx->settings[ctx->id("input/json")]; - root.put("project.input.json", make_relative(fn, proj.parent_path()).string()); - root.put("project.params.freq", int(ctx->target_freq / 1e6)); - root.put("project.params.seed", ctx->rngstate); - saveArch(ctx, root, proj.parent_path().string()); - for (auto const &item : ctx->settings) { - std::string path = "project.settings."; - path += item.first.c_str(ctx); - std::replace(path.begin(), path.end(), '/', '.'); - root.put(path, item.second.str); - } - pt::write_json(f, root); - } catch (...) { - log_error("Error saving project file.\n"); - } -} - -void addSettings(Context *ctx, std::string path, pt::ptree sub) -{ - for (pt::ptree::value_type &v : sub) { - const std::string &key = v.first; - const boost::property_tree::ptree &subtree = v.second; - if (subtree.empty()) { - Property p; - p.setString(subtree.get_value().c_str()); - ctx->settings.emplace(ctx->id(path + key), p); - } else { - addSettings(ctx, path + key + "/", subtree); - } - } -} - -std::unique_ptr ProjectHandler::load(std::string filename) -{ - std::unique_ptr ctx; - try { - pt::ptree root; - boost::filesystem::path proj(filename); - pt::read_json(filename, root); - log_info("Loading project %s...\n", filename.c_str()); - log_break(); - - int version = root.get("project.version"); - if (version != 1) - log_error("Wrong project format version.\n"); - - ctx = createContext(root); - - std::string arch_name = root.get("project.arch.name"); - if (arch_name != ctx->archId().c_str(ctx.get())) - log_error("Unsuported project architecture.\n"); - - auto project = root.get_child("project"); - auto input = project.get_child("input"); - std::string fn = input.get("json"); - boost::filesystem::path json = proj.parent_path() / fn; - std::ifstream f(json.string()); - if (!parse_json_file(f, fn, ctx.get())) - log_error("Loading design failed.\n"); - - if (project.count("params")) { - auto params = project.get_child("params"); - if (params.count("freq")) - ctx->target_freq = params.get("freq") * 1e6; - if (params.count("seed")) - ctx->rngseed(params.get("seed")); - } - if (project.count("settings")) { - addSettings(ctx.get(), "", project.get_child("settings")); - } - - loadArch(ctx.get(), root, proj.parent_path().string()); - } catch (...) { - log_error("Error loading project file.\n"); - } - return ctx; -} - -NEXTPNR_NAMESPACE_END diff --git a/common/project.h b/common/project.h deleted file mode 100644 index 03b4b7b5..00000000 --- a/common/project.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Miodrag Milanovic - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifndef PROJECT_H -#define PROJECT_H - -#include -#include -#include "nextpnr.h" - -NEXTPNR_NAMESPACE_BEGIN - -namespace pt = boost::property_tree; - -struct ProjectHandler -{ - void save(Context *ctx, std::string filename); - std::unique_ptr load(std::string filename); - // implemented per arch - void saveArch(Context *ctx, pt::ptree &root, std::string path); - std::unique_ptr createContext(pt::ptree &root); - void loadArch(Context *ctx, pt::ptree &root, std::string path); -}; - -boost::filesystem::path make_relative(boost::filesystem::path child, boost::filesystem::path parent); - -NEXTPNR_NAMESPACE_END - -#endif // PROJECT_H diff --git a/ecp5/project.cc b/ecp5/project.cc deleted file mode 100644 index 43318b1c..00000000 --- a/ecp5/project.cc +++ /dev/null @@ -1,55 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Miodrag Milanovic - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "project.h" -#include -#include -#include -#include "log.h" - -NEXTPNR_NAMESPACE_BEGIN - -void ProjectHandler::saveArch(Context *ctx, pt::ptree &root, std::string path) -{ - root.put("project.arch.package", ctx->archArgs().package); - root.put("project.arch.speed", ctx->archArgs().speed); -} - -std::unique_ptr ProjectHandler::createContext(pt::ptree &root) -{ - ArchArgs chipArgs; - std::string arch_type = root.get("project.arch.type"); - if (arch_type == "25k") { - chipArgs.type = ArchArgs::LFE5U_25F; - } - if (arch_type == "45k") { - chipArgs.type = ArchArgs::LFE5U_45F; - } - if (arch_type == "85k") { - chipArgs.type = ArchArgs::LFE5U_85F; - } - chipArgs.package = root.get("project.arch.package"); - chipArgs.speed = ArchArgs::SpeedGrade(root.get("project.arch.speed")); - - return std::unique_ptr(new Context(chipArgs)); -} - -void ProjectHandler::loadArch(Context *ctx, pt::ptree &root, std::string path) {} - -NEXTPNR_NAMESPACE_END diff --git a/generic/project.cc b/generic/project.cc deleted file mode 100644 index 342fcac3..00000000 --- a/generic/project.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Miodrag Milanovic - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "project.h" -#include -#include -#include "log.h" - -NEXTPNR_NAMESPACE_BEGIN - -void ProjectHandler::saveArch(Context *ctx, pt::ptree &root, std::string path) {} - -std::unique_ptr ProjectHandler::createContext(pt::ptree &root) -{ - ArchArgs chipArgs; - return std::unique_ptr(new Context(chipArgs)); -} - -void ProjectHandler::loadArch(Context *ctx, pt::ptree &root, std::string path) {} - -NEXTPNR_NAMESPACE_END diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 346efb88..afc80694 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -31,7 +31,6 @@ #include "jsonparse.h" #include "log.h" #include "mainwindow.h" -#include "project.h" #include "pythontab.h" static void initBasenameResource() { Q_INIT_RESOURCE(base); } @@ -130,25 +129,6 @@ void BaseMainWindow::writeInfo(std::string text) { console->info(text); } void BaseMainWindow::createMenusAndBars() { // File menu / project toolbar actions - actionNew = new QAction("New", this); - actionNew->setIcon(QIcon(":/icons/resources/new.png")); - actionNew->setShortcuts(QKeySequence::New); - actionNew->setStatusTip("New project file"); - connect(actionNew, &QAction::triggered, this, &BaseMainWindow::new_proj); - - actionOpen = new QAction("Open", this); - actionOpen->setIcon(QIcon(":/icons/resources/open.png")); - actionOpen->setShortcuts(QKeySequence::Open); - actionOpen->setStatusTip("Open an existing project file"); - connect(actionOpen, &QAction::triggered, this, &BaseMainWindow::open_proj); - - actionSave = new QAction("Save", this); - actionSave->setIcon(QIcon(":/icons/resources/save.png")); - actionSave->setShortcuts(QKeySequence::Save); - actionSave->setStatusTip("Save existing project to disk"); - actionSave->setEnabled(false); - connect(actionSave, &QAction::triggered, this, &BaseMainWindow::save_proj); - QAction *actionExit = new QAction("Exit", this); actionExit->setIcon(QIcon(":/icons/resources/exit.png")); actionExit->setShortcuts(QKeySequence::Quit); @@ -243,10 +223,6 @@ void BaseMainWindow::createMenusAndBars() menuBar->addAction(menuHelp->menuAction()); // Add File menu actions - menuFile->addAction(actionNew); - menuFile->addAction(actionOpen); - menuFile->addAction(actionSave); - menuFile->addSeparator(); menuFile->addAction(actionExit); // Add Design menu actions @@ -261,13 +237,6 @@ void BaseMainWindow::createMenusAndBars() // Add Help menu actions menuHelp->addAction(actionAbout); - // Project toolbar - QToolBar *projectToolBar = new QToolBar("Project"); - addToolBar(Qt::TopToolBarArea, projectToolBar); - projectToolBar->addAction(actionNew); - projectToolBar->addAction(actionOpen); - projectToolBar->addAction(actionSave); - // Main action bar mainActionBar = new QToolBar("Main"); addToolBar(Qt::TopToolBarArea, mainActionBar); @@ -386,9 +355,6 @@ void BaseMainWindow::taskStarted() disableActions(); actionPause->setEnabled(true); actionStop->setEnabled(true); - - actionNew->setEnabled(false); - actionOpen->setEnabled(false); } void BaseMainWindow::taskPaused() @@ -396,9 +362,6 @@ void BaseMainWindow::taskPaused() disableActions(); actionPlay->setEnabled(true); actionStop->setEnabled(true); - - actionNew->setEnabled(false); - actionOpen->setEnabled(false); } void BaseMainWindow::budget() @@ -427,14 +390,6 @@ void BaseMainWindow::disableActions() actionPause->setEnabled(false); actionStop->setEnabled(false); - actionNew->setEnabled(true); - actionOpen->setEnabled(true); - - if (ctx->settings.find(ctx->id("input/json")) != ctx->settings.end()) - actionSave->setEnabled(true); - else - actionSave->setEnabled(false); - onDisableActions(); } @@ -446,24 +401,6 @@ void BaseMainWindow::updateLoaded() onProjectLoaded(); } -void BaseMainWindow::projectLoad(std::string filename) -{ - ProjectHandler proj; - disableActions(); - ctx = proj.load(filename); - Q_EMIT contextChanged(ctx.get()); - log_info("Loaded project %s...\n", filename.c_str()); - updateLoaded(); -} - -void BaseMainWindow::open_proj() -{ - QString fileName = QFileDialog::getOpenFileName(this, QString("Open Project"), QString(), QString("*.proj")); - if (!fileName.isEmpty()) { - projectLoad(fileName.toStdString()); - } -} - void BaseMainWindow::execute_python() { QString fileName = QFileDialog::getOpenFileName(this, QString("Execute Python"), QString(), QString("*.py")); @@ -473,18 +410,5 @@ void BaseMainWindow::execute_python() } void BaseMainWindow::notifyChangeContext() { Q_EMIT contextChanged(ctx.get()); } -void BaseMainWindow::save_proj() -{ - if (currentProj.empty()) { - QString fileName = QFileDialog::getSaveFileName(this, QString("Save Project"), QString(), QString("*.proj")); - if (fileName.isEmpty()) - return; - currentProj = fileName.toStdString(); - } - if (!currentProj.empty()) { - ProjectHandler proj; - proj.save(ctx.get(), currentProj); - } -} NEXTPNR_NAMESPACE_END diff --git a/gui/basewindow.h b/gui/basewindow.h index 0b2d3fbc..e165851f 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -49,7 +49,6 @@ class BaseMainWindow : public QMainWindow virtual ~BaseMainWindow(); Context *getContext() { return ctx.get(); } void updateLoaded(); - void projectLoad(std::string filename); void notifyChangeContext(); protected: @@ -71,9 +70,6 @@ class BaseMainWindow : public QMainWindow virtual void new_proj() = 0; - void open_proj(); - void save_proj(); - void open_json(); void budget(); void place(); @@ -115,10 +111,6 @@ class BaseMainWindow : public QMainWindow QToolBar *mainActionBar; QProgressBar *progressBar; - QAction *actionNew; - QAction *actionOpen; - QAction *actionSave; - QAction *actionLoadJSON; QAction *actionPack; QAction *actionAssignBudget; diff --git a/ice40/project.cc b/ice40/project.cc deleted file mode 100644 index bbd82fd7..00000000 --- a/ice40/project.cc +++ /dev/null @@ -1,76 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Miodrag Milanovic - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "project.h" -#include -#include -#include "log.h" -#include "pcf.h" - -NEXTPNR_NAMESPACE_BEGIN - -void ProjectHandler::saveArch(Context *ctx, pt::ptree &root, std::string path) -{ - root.put("project.arch.package", ctx->archArgs().package); - if (ctx->settings.find(ctx->id("input/pcf")) != ctx->settings.end()) { - std::string fn = ctx->settings[ctx->id("input/pcf")]; - root.put("project.input.pcf", make_relative(fn, path).string()); - } -} - -std::unique_ptr ProjectHandler::createContext(pt::ptree &root) -{ - ArchArgs chipArgs; - std::string arch_type = root.get("project.arch.type"); - if (arch_type == "lp384") { - chipArgs.type = ArchArgs::LP384; - } - if (arch_type == "lp1k") { - chipArgs.type = ArchArgs::LP1K; - } - if (arch_type == "lp8k") { - chipArgs.type = ArchArgs::LP8K; - } - if (arch_type == "hx1k") { - chipArgs.type = ArchArgs::HX1K; - } - if (arch_type == "hx8k") { - chipArgs.type = ArchArgs::HX8K; - } - if (arch_type == "up5k") { - chipArgs.type = ArchArgs::UP5K; - } - if (arch_type == "u4k") { - chipArgs.type = ArchArgs::U4K; - } - chipArgs.package = root.get("project.arch.package"); - - return std::unique_ptr(new Context(chipArgs)); -} - -void ProjectHandler::loadArch(Context *ctx, pt::ptree &root, std::string path) -{ - auto input = root.get_child("project").get_child("input"); - boost::filesystem::path pcf = boost::filesystem::path(path) / input.get("pcf"); - std::ifstream f(pcf.string()); - if (!apply_pcf(ctx, input.get("pcf"), f)) - log_error("Loading PCF failed.\n"); -} - -NEXTPNR_NAMESPACE_END -- cgit v1.2.3 From c760b0326182c3779373fba1f77aad200c9b1b89 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 13 Jun 2019 18:18:16 +0200 Subject: Cleanup --- common/command.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/command.h b/common/command.h index c3274197..d4f9a12e 100644 --- a/common/command.h +++ b/common/command.h @@ -23,7 +23,6 @@ #include #include "nextpnr.h" -//#include "project.h" #include "settings.h" NEXTPNR_NAMESPACE_BEGIN @@ -66,7 +65,6 @@ class CommandHandler po::positional_options_description pos; int argc; char **argv; - //ProjectHandler project; std::ofstream logfile; }; -- cgit v1.2.3 From 4de147d9e42d7c932773544011a36e4550530a9e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 13 Jun 2019 18:39:16 +0200 Subject: Save settings that we saved in project --- common/command.cc | 4 ++++ ecp5/main.cc | 2 ++ ice40/main.cc | 2 +- json/jsonparse.cc | 1 - 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/common/command.cc b/common/command.cc index 43707c83..4822585c 100644 --- a/common/command.cc +++ b/common/command.cc @@ -229,6 +229,10 @@ void CommandHandler::setupContext(Context *ctx) ctx->timing_driven = true; if (vm.count("no-tmdriv")) ctx->timing_driven = false; + + settings->set("arch.name", std::string(ctx->archId().c_str(ctx))); + settings->set("arch.type", std::string(ctx->archArgsToId(ctx->archArgs()).c_str(ctx))); + settings->set("seed", ctx->rngstate); } int CommandHandler::executeMain(std::unique_ptr ctx) diff --git a/ecp5/main.cc b/ecp5/main.cc index bb18aa58..9d0241e9 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -150,6 +150,8 @@ std::unique_ptr ECP5CommandHandler::createContext() } } auto ctx = std::unique_ptr(new Context(chipArgs)); + ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; + ctx->settings[ctx->id("arch.speed")] = std::to_string(ctx->archArgs().speed); return ctx; } diff --git a/ice40/main.cc b/ice40/main.cc index 9b79a08c..4cbca2d4 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -167,7 +167,7 @@ std::unique_ptr Ice40CommandHandler::createContext() chipArgs.package = vm["package"].as(); auto ctx = std::unique_ptr(new Context(chipArgs)); - + ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; if (vm.count("promote-logic")) ctx->settings[ctx->id("promote_logic")] = "1"; if (vm.count("no-promote-globals")) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index f0d0069a..df8f45db 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -907,7 +907,6 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) log_info("Checksum: 0x%08x\n", ctx->checksum()); log_break(); - ctx->settings[ctx->id("input/json")] = filename; ctx->attributesToArchInfo(); return true; } catch (log_execution_error_exception) { -- cgit v1.2.3 From 03dff10cbde4c55e4ac9b53a01ba84f4bdac169b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 13 Jun 2019 20:42:11 +0200 Subject: Load properties from json and propagate to context create --- common/command.cc | 9 ++++++++- common/command.h | 2 +- ecp5/main.cc | 4 ++-- generic/main.cc | 4 ++-- ice40/main.cc | 4 ++-- json/jsonparse.cc | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ json/jsonparse.h | 2 +- 7 files changed, 65 insertions(+), 9 deletions(-) diff --git a/common/command.cc b/common/command.cc index 4822585c..209f8cab 100644 --- a/common/command.cc +++ b/common/command.cc @@ -358,7 +358,14 @@ int CommandHandler::exec() if (executeBeforeContext()) return 0; - std::unique_ptr ctx = createContext(); + std::unordered_map values; + if (vm.count("json")) { + std::string filename = vm["json"].as(); + std::ifstream f(filename); + if (!load_json_settings(f, filename, values)) + log_error("Loading design failed.\n"); + } + std::unique_ptr ctx = createContext(values); settings = std::unique_ptr(new Settings(ctx.get())); setupContext(ctx.get()); setupArchContext(ctx.get()); diff --git a/common/command.h b/common/command.h index d4f9a12e..5c5ceb9a 100644 --- a/common/command.h +++ b/common/command.h @@ -39,7 +39,7 @@ class CommandHandler protected: virtual void setupArchContext(Context *ctx) = 0; - virtual std::unique_ptr createContext() = 0; + virtual std::unique_ptr createContext(std::unordered_map &values) = 0; virtual po::options_description getArchOptions() = 0; virtual void validate(){}; virtual void customAfterLoad(Context *ctx){}; diff --git a/ecp5/main.cc b/ecp5/main.cc index 9d0241e9..355e346d 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -34,7 +34,7 @@ class ECP5CommandHandler : public CommandHandler public: ECP5CommandHandler(int argc, char **argv); virtual ~ECP5CommandHandler(){}; - std::unique_ptr createContext() override; + std::unique_ptr createContext(std::unordered_map &values) override; void setupArchContext(Context *ctx) override{}; void customAfterLoad(Context *ctx) override; void validate() override; @@ -98,7 +98,7 @@ void ECP5CommandHandler::customBitstream(Context *ctx) write_bitstream(ctx, basecfg, textcfg); } -std::unique_ptr ECP5CommandHandler::createContext() +std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map &values) { chipArgs.type = ArchArgs::LFE5U_45F; diff --git a/generic/main.cc b/generic/main.cc index c203f35c..8ab3b0e8 100644 --- a/generic/main.cc +++ b/generic/main.cc @@ -32,7 +32,7 @@ class GenericCommandHandler : public CommandHandler public: GenericCommandHandler(int argc, char **argv); virtual ~GenericCommandHandler(){}; - std::unique_ptr createContext() override; + std::unique_ptr createContext(std::unordered_map &values) override; void setupArchContext(Context *ctx) override{}; void customBitstream(Context *ctx) override; @@ -51,7 +51,7 @@ po::options_description GenericCommandHandler::getArchOptions() void GenericCommandHandler::customBitstream(Context *ctx) {} -std::unique_ptr GenericCommandHandler::createContext() +std::unique_ptr GenericCommandHandler::createContext(std::unordered_map &values) { return std::unique_ptr(new Context(chipArgs)); } diff --git a/ice40/main.cc b/ice40/main.cc index 4cbca2d4..00d7fe3e 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -36,7 +36,7 @@ class Ice40CommandHandler : public CommandHandler public: Ice40CommandHandler(int argc, char **argv); virtual ~Ice40CommandHandler(){}; - std::unique_ptr createContext() override; + std::unique_ptr createContext(std::unordered_map &values) override; void setupArchContext(Context *ctx) override; void validate() override; void customAfterLoad(Context *ctx) override; @@ -116,7 +116,7 @@ void Ice40CommandHandler::setupArchContext(Context *ctx) } } -std::unique_ptr Ice40CommandHandler::createContext() +std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map &values) { if (vm.count("lp384")) { chipArgs.type = ArchArgs::LP384; diff --git a/json/jsonparse.cc b/json/jsonparse.cc index df8f45db..a6b45282 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -914,4 +914,53 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) } } +bool load_json_settings(std::istream &f, std::string &filename, std::unordered_map &values) +{ + try { + using namespace JsonParser; + + if (!f) + log_error("failed to open JSON file.\n"); + + int lineno = 1; + + JsonNode root(f, lineno); + + if (root.type != 'D') + log_error("JSON root node is not a dictionary.\n"); + + if (root.data_dict.count("modules") != 0) { + JsonNode *modules = root.data_dict.at("modules"); + + if (modules->type != 'D') + log_error("JSON modules node is not a dictionary.\n"); + + for (auto &it : modules->data_dict) { + JsonNode *node = it.second; + if (is_blackbox(node)) + continue; + + if (node->data_dict.count("settings")) { + JsonNode *attr_node = node->data_dict.at("settings"); + 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()); + + } + } + } + } + + return true; + } catch (log_execution_error_exception) { + return false; + } +} + NEXTPNR_NAMESPACE_END diff --git a/json/jsonparse.h b/json/jsonparse.h index fe71444f..ca971e5f 100644 --- a/json/jsonparse.h +++ b/json/jsonparse.h @@ -27,7 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN extern bool parse_json_file(std::istream &, std::string &, Context *); - +extern bool load_json_settings(std::istream &f, std::string &filename, std::unordered_map &values); NEXTPNR_NAMESPACE_END #endif -- cgit v1.2.3 From c6057abd00fc4d1538f066324188bd04d6b4cfc7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 08:13:59 +0200 Subject: restore context from json --- ice40/main.cc | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/ice40/main.cc b/ice40/main.cc index 00d7fe3e..ce4b5532 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -153,6 +153,49 @@ std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map(); + + if (values.find("arch.name")!=values.end()) { + std::string arch_name = values["arch.name"].str; + if (arch_name != "ice40") + log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); + } + if (values.find("arch.type")!=values.end()) { + std::string arch_type = values["arch.type"].str; + if (chipArgs.type != ArchArgs::NONE) + log_error("Overriding architecture is unsuported.\n"); + + if (arch_type == "lp384") { + chipArgs.type = ArchArgs::LP384; + } + if (arch_type == "lp1k") { + chipArgs.type = ArchArgs::LP1K; + } + if (arch_type == "lp8k") { + chipArgs.type = ArchArgs::LP8K; + } + if (arch_type == "hx1k") { + chipArgs.type = ArchArgs::HX1K; + } + if (arch_type == "hx8k") { + chipArgs.type = ArchArgs::HX8K; + } + if (arch_type == "up5k") { + chipArgs.type = ArchArgs::UP5K; + } + if (arch_type == "u4k") { + chipArgs.type = ArchArgs::U4K; + } + if (chipArgs.type == ArchArgs::NONE) + log_error("Unsuported FPGA type '%s'.\n",arch_type.c_str()); + } + if (values.find("arch.package")!=values.end()) { + if (vm.count("package")) + log_error("Overriding architecture is unsuported.\n"); + chipArgs.package = values["arch.package"].str; + } + if (chipArgs.type == ArchArgs::NONE) { chipArgs.type = ArchArgs::HX1K; chipArgs.package = "tq144"; @@ -163,9 +206,6 @@ std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map(); - auto ctx = std::unique_ptr(new Context(chipArgs)); ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; if (vm.count("promote-logic")) -- cgit v1.2.3 From ca7e944d7a58bc305f0efce4da757520a6a86041 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 08:55:11 +0200 Subject: restore arch info for ecp5 --- ecp5/main.cc | 115 ++++++++++++++++++++++++++++++++++++++++++++------------ generic/main.cc | 5 +++ ice40/main.cc | 3 ++ 3 files changed, 99 insertions(+), 24 deletions(-) diff --git a/ecp5/main.cc b/ecp5/main.cc index 355e346d..0620b8b7 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -98,9 +98,20 @@ void ECP5CommandHandler::customBitstream(Context *ctx) write_bitstream(ctx, basecfg, textcfg); } +static std::string speedString(ArchArgs::SpeedGrade speed) +{ + switch(speed){ + case ArchArgs::SPEED_6: return "6"; + case ArchArgs::SPEED_7: return "7"; + case ArchArgs::SPEED_8: return "8"; + case ArchArgs::SPEED_8_5G: return "8"; + } + return ""; +} + std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map &values) { - chipArgs.type = ArchArgs::LFE5U_45F; + chipArgs.type = ArchArgs::NONE; if (vm.count("25k")) chipArgs.type = ArchArgs::LFE5U_25F; @@ -122,36 +133,92 @@ std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map(); - else + + if (vm.count("speed")) { + int speed = vm["speed"].as(); + switch (speed) { + case 6: + chipArgs.speed = ArchArgs::SPEED_6; + break; + case 7: + chipArgs.speed = ArchArgs::SPEED_7; + break; + case 8: + chipArgs.speed = ArchArgs::SPEED_8; + break; + default: + log_error("Unsupported speed grade '%d'\n", speed); + } + } else { + chipArgs.speed = ArchArgs::SPEED_6; + } + if (values.find("arch.name")!=values.end()) { + std::string arch_name = values["arch.name"].str; + if (arch_name != "ecp5") + log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); + } + if (values.find("arch.type")!=values.end()) { + std::string arch_type = values["arch.type"].str; + if (chipArgs.type != ArchArgs::NONE) + log_error("Overriding architecture is unsuported.\n"); + + if (arch_type == "lfe5u_25f") + chipArgs.type = ArchArgs::LFE5U_25F; + if (arch_type == "lfe5u_45f") + chipArgs.type = ArchArgs::LFE5U_45F; + if (arch_type == "lfe5u_85f") + chipArgs.type = ArchArgs::LFE5U_85F; + if (arch_type == "lfe5um_25f") + chipArgs.type = ArchArgs::LFE5UM_25F; + if (arch_type == "lfe5um_45f") + chipArgs.type = ArchArgs::LFE5UM_45F; + if (arch_type == "lfe5um_85f") + chipArgs.type = ArchArgs::LFE5UM_85F; + if (arch_type == "lfe5um5g_25f") + chipArgs.type = ArchArgs::LFE5UM5G_25F; + if (arch_type == "lfe5um5g_45f") + chipArgs.type = ArchArgs::LFE5UM5G_45F; + if (arch_type == "lfe5um5g_85f") + chipArgs.type = ArchArgs::LFE5UM5G_85F; + + if (chipArgs.type == ArchArgs::NONE) + log_error("Unsuported FPGA type '%s'.\n",arch_type.c_str()); + } + if (values.find("arch.package")!=values.end()) { + if (vm.count("package")) + log_error("Overriding architecture is unsuported.\n"); + chipArgs.package = values["arch.package"].str; + } + if (values.find("arch.speed")!=values.end()) { + std::string arch_speed = values["arch.speed"].str; + if (arch_speed == "6") + chipArgs.speed = ArchArgs::SPEED_6; + else if (arch_speed == "7") + chipArgs.speed = ArchArgs::SPEED_7; + else if (arch_speed == "8") + chipArgs.speed = ArchArgs::SPEED_8; + else + log_error("Unsuported speed '%s'.\n",arch_speed.c_str()); + } + if (chipArgs.type == ArchArgs::NONE) + chipArgs.type = ArchArgs::LFE5U_45F; + + if (chipArgs.package.empty()) chipArgs.package = "CABGA381"; + if (chipArgs.type == ArchArgs::LFE5UM5G_25F || chipArgs.type == ArchArgs::LFE5UM5G_45F || chipArgs.type == ArchArgs::LFE5UM5G_85F) { - if (vm.count("speed") && vm["speed"].as() != 8) + if (chipArgs.speed != ArchArgs::SPEED_8) log_error("Only speed grade 8 is available for 5G parts\n"); - chipArgs.speed = ArchArgs::SPEED_8_5G; - } else { - if (vm.count("speed")) { - int speed = vm["speed"].as(); - switch (speed) { - case 6: - chipArgs.speed = ArchArgs::SPEED_6; - break; - case 7: - chipArgs.speed = ArchArgs::SPEED_7; - break; - case 8: - chipArgs.speed = ArchArgs::SPEED_8; - break; - default: - log_error("Unsupported speed grade '%d'\n", speed); - } - } else { - chipArgs.speed = ArchArgs::SPEED_6; - } + else + chipArgs.speed = ArchArgs::SPEED_8_5G; } + auto ctx = std::unique_ptr(new Context(chipArgs)); + for(auto &val : values) + ctx->settings[ctx->id(val.first)] = val.second; ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; - ctx->settings[ctx->id("arch.speed")] = std::to_string(ctx->archArgs().speed); + ctx->settings[ctx->id("arch.speed")] = speedString(ctx->archArgs().speed); return ctx; } diff --git a/generic/main.cc b/generic/main.cc index 8ab3b0e8..f0070e92 100644 --- a/generic/main.cc +++ b/generic/main.cc @@ -53,6 +53,11 @@ void GenericCommandHandler::customBitstream(Context *ctx) {} std::unique_ptr GenericCommandHandler::createContext(std::unordered_map &values) { + if (values.find("arch.name")!=values.end()) { + std::string arch_name = values["arch.name"].str; + if (arch_name != "generic") + log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); + } return std::unique_ptr(new Context(chipArgs)); } diff --git a/ice40/main.cc b/ice40/main.cc index ce4b5532..f3885f29 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -207,6 +207,9 @@ std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map(new Context(chipArgs)); + for(auto &val : values) + ctx->settings[ctx->id(val.first)] = val.second; + ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; if (vm.count("promote-logic")) ctx->settings[ctx->id("promote_logic")] = "1"; -- cgit v1.2.3 From 36ccc22fc93eddd9b6ed867782668b0057ec67e2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 09:59:04 +0200 Subject: Use flags for each step --- ecp5/arch.cc | 4 ++-- ecp5/pack.cc | 2 +- generic/arch.cc | 4 ++-- generic/pack.cc | 2 +- ice40/arch.cc | 4 ++-- ice40/pack.cc | 2 +- json/jsonparse.cc | 2 -- 7 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 2061bf4a..02f73ca2 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -524,7 +524,7 @@ bool Arch::place() } permute_luts(); - getCtx()->attrs[getCtx()->id("step")] = "place"; + getCtx()->settings[getCtx()->id("place")] = "1"; archInfoToAttributes(); return true; } @@ -561,7 +561,7 @@ bool Arch::route() log_info(" base %d adder %d\n", speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_base_delay, speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_fanout_adder); #endif - getCtx()->attrs[getCtx()->id("step")] = "route"; + getCtx()->settings[getCtx()->id("route")] = "1"; archInfoToAttributes(); return result; } diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 4077bfed..9e2bc326 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -2429,7 +2429,7 @@ bool Arch::pack() Ecp5Packer(ctx).pack(); log_info("Checksum: 0x%08x\n", ctx->checksum()); assignArchInfo(); - ctx->attrs[ctx->id("step")] = "pack"; + ctx->settings[ctx->id("pack")] = "1"; archInfoToAttributes(); return true; } catch (log_execution_error_exception) { diff --git a/generic/arch.cc b/generic/arch.cc index f6f7ff87..2db9e547 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -497,7 +497,7 @@ bool Arch::place() // FIXME: No HeAP because it needs a list of IO buffers if (placer == "sa") { bool retVal = placer1(getCtx(), Placer1Cfg(getCtx())); - getCtx()->attrs[getCtx()->id("step")] = "place"; + getCtx()->settings[getCtx()->id("place")] = "1"; archInfoToAttributes(); return retVal; } else { @@ -507,7 +507,7 @@ bool Arch::place() bool Arch::route() { bool retVal = router1(getCtx(), Router1Cfg(getCtx())); - getCtx()->attrs[getCtx()->id("step")] = "route"; + getCtx()->settings[getCtx()->id("route")] = "1"; archInfoToAttributes(); return retVal; } diff --git a/generic/pack.cc b/generic/pack.cc index 0d47ea19..558eca7c 100644 --- a/generic/pack.cc +++ b/generic/pack.cc @@ -282,7 +282,7 @@ bool Arch::pack() pack_io(ctx); pack_lut_lutffs(ctx); pack_nonlut_ffs(ctx); - ctx->attrs[ctx->id("step")] = "pack"; + ctx->settings[ctx->id("pack")] = "1"; ctx->assignArchInfo(); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; diff --git a/ice40/arch.cc b/ice40/arch.cc index 4945f5b3..a0c64bb8 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -689,14 +689,14 @@ bool Arch::place() tocfg.cellTypes.insert(id_ICESTORM_LC); retVal = timing_opt(getCtx(), tocfg); } - getCtx()->attrs[getCtx()->id("step")] = "place"; + getCtx()->settings[getCtx()->id("place")] = "1"; archInfoToAttributes(); return retVal; } bool Arch::route() { bool retVal = router1(getCtx(), Router1Cfg(getCtx())); - getCtx()->attrs[getCtx()->id("step")] = "route"; + getCtx()->settings[getCtx()->id("route")] = "1"; archInfoToAttributes(); return retVal; } diff --git a/ice40/pack.cc b/ice40/pack.cc index ce39c903..a8f8c76e 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -1421,7 +1421,7 @@ bool Arch::pack() ctx->assignArchInfo(); constrain_chains(ctx); ctx->assignArchInfo(); - ctx->attrs[ctx->id("step")] = "pack"; + ctx->settings[ctx->id("pack")] = "1"; archInfoToAttributes(); log_info("Checksum: 0x%08x\n", ctx->checksum()); return true; diff --git a/json/jsonparse.cc b/json/jsonparse.cc index a6b45282..b2597828 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -740,8 +740,6 @@ void json_import(Context *ctx, string modname, JsonNode *node) for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { json_import_top_attrib(ctx, modname, attr_node, &ctx->attrs, attrid); } - if (ctx->attrs.find(ctx->id("step")) == ctx->attrs.end()) - ctx->attrs[ctx->id("step")] = "synth"; JsonNode *ports_parent = nullptr; if (node->data_dict.count("ports") > 0) -- cgit v1.2.3 From 053bd48bef73668e5c7bdf84e826a996a519c5bb Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 10:07:59 +0200 Subject: Cleanup --- gui/basewindow.cc | 1 - gui/basewindow.h | 1 - gui/ecp5/mainwindow.cc | 6 ------ gui/ecp5/mainwindow.h | 1 - gui/generic/mainwindow.cc | 1 + gui/ice40/mainwindow.cc | 6 ------ gui/ice40/mainwindow.h | 1 - 7 files changed, 1 insertion(+), 16 deletions(-) diff --git a/gui/basewindow.cc b/gui/basewindow.cc index afc80694..63e30f27 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -398,7 +398,6 @@ void BaseMainWindow::updateLoaded() disableActions(); actionPack->setEnabled(true); onJsonLoaded(); - onProjectLoaded(); } void BaseMainWindow::execute_python() diff --git a/gui/basewindow.h b/gui/basewindow.h index e165851f..91389978 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -58,7 +58,6 @@ class BaseMainWindow : public QMainWindow virtual void onDisableActions(){}; virtual void onJsonLoaded(){}; - virtual void onProjectLoaded(){}; virtual void onPackFinished(){}; virtual void onBudgetFinished(){}; virtual void onPlaceFinished(){}; diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index c6c7bc97..a54ab8b5 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -192,10 +192,4 @@ void MainWindow::onJsonLoaded() { actionLoadLPF->setEnabled(true); } void MainWindow::onRouteFinished() { actionLoadBase->setEnabled(true); } -void MainWindow::onProjectLoaded() -{ - if (ctx->settings.find(ctx->id("input/lpf")) != ctx->settings.end()) - actionLoadLPF->setEnabled(false); -} - NEXTPNR_NAMESPACE_END diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index 721c6c0b..186a7974 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -40,7 +40,6 @@ class MainWindow : public BaseMainWindow void onDisableActions() override; void onJsonLoaded() override; void onRouteFinished() override; - void onProjectLoaded() override; protected Q_SLOTS: void new_proj() override; diff --git a/gui/generic/mainwindow.cc b/gui/generic/mainwindow.cc index 54d1f2c8..eefff39c 100644 --- a/gui/generic/mainwindow.cc +++ b/gui/generic/mainwindow.cc @@ -29,6 +29,7 @@ NEXTPNR_NAMESPACE_BEGIN MainWindow::MainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent) : BaseMainWindow(std::move(context), args, parent) { + initMainResource(); QMessageBox::critical(0, "Error - FIXME", "No GUI support for nextpnr-generic"); std::exit(1); } diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index f270b112..b766734f 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -189,10 +189,4 @@ void MainWindow::onDisableActions() void MainWindow::onJsonLoaded() { actionLoadPCF->setEnabled(true); } void MainWindow::onRouteFinished() { actionSaveAsc->setEnabled(true); } -void MainWindow::onProjectLoaded() -{ - if (ctx->settings.find(ctx->id("input/pcf")) != ctx->settings.end()) - actionLoadPCF->setEnabled(false); -} - NEXTPNR_NAMESPACE_END diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h index 4a9a7d8e..de160174 100644 --- a/gui/ice40/mainwindow.h +++ b/gui/ice40/mainwindow.h @@ -41,7 +41,6 @@ class MainWindow : public BaseMainWindow void onDisableActions() override; void onJsonLoaded() override; void onRouteFinished() override; - void onProjectLoaded() override; protected Q_SLOTS: void new_proj() override; -- cgit v1.2.3 From 0d8c80ad5daafc02030385da90c5a57182a5d4e5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 11:14:18 +0200 Subject: gui for json write and proper statuses --- common/command.cc | 2 +- gui/base.qrc | 1 + gui/basewindow.cc | 71 +++++++++++++++++++++++++++++++++----------- gui/basewindow.h | 13 ++++---- gui/create_img.sh | 5 ++-- gui/ecp5/mainwindow.cc | 11 +++++-- gui/ecp5/mainwindow.h | 3 +- gui/ice40/mainwindow.cc | 8 +++-- gui/ice40/mainwindow.h | 3 +- gui/resources/save_json.png | Bin 0 -> 1546 bytes json/jsonparse.cc | 3 +- 11 files changed, 84 insertions(+), 36 deletions(-) create mode 100644 gui/resources/save_json.png diff --git a/common/command.cc b/common/command.cc index 209f8cab..7b0b2caa 100644 --- a/common/command.cc +++ b/common/command.cc @@ -255,7 +255,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) customAfterLoad(w.getContext()); w.notifyChangeContext(); - w.updateLoaded(); + w.updateActions(); } else w.notifyChangeContext(); } catch (log_execution_error_exception) { diff --git a/gui/base.qrc b/gui/base.qrc index 644b16a6..85d1432a 100644 --- a/gui/base.qrc +++ b/gui/base.qrc @@ -22,6 +22,7 @@ resources/route.png resources/time_add.png resources/open_json.png + resources/save_json.png resources/py.png diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 63e30f27..59dd6f7b 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -29,6 +29,7 @@ #include "designwidget.h" #include "fpgaviewwidget.h" #include "jsonparse.h" +#include "jsonwrite.h" #include "log.h" #include "mainwindow.h" #include "pythontab.h" @@ -138,13 +139,26 @@ void BaseMainWindow::createMenusAndBars() // Help menu actions QAction *actionAbout = new QAction("About", this); - // Design menu options + // Gile menu options + actionNew = new QAction("New", this); + actionNew->setIcon(QIcon(":/icons/resources/new.png")); + actionNew->setShortcuts(QKeySequence::New); + actionNew->setStatusTip("New project"); + connect(actionNew, &QAction::triggered, this, &BaseMainWindow::new_proj); + actionLoadJSON = new QAction("Open JSON", this); actionLoadJSON->setIcon(QIcon(":/icons/resources/open_json.png")); actionLoadJSON->setStatusTip("Open an existing JSON file"); actionLoadJSON->setEnabled(true); connect(actionLoadJSON, &QAction::triggered, this, &BaseMainWindow::open_json); + actionSaveJSON = new QAction("Save JSON", this); + actionSaveJSON->setIcon(QIcon(":/icons/resources/save_json.png")); + actionSaveJSON->setStatusTip("Write to JSON file"); + actionSaveJSON->setEnabled(true); + connect(actionSaveJSON, &QAction::triggered, this, &BaseMainWindow::save_json); + + // Design menu options actionPack = new QAction("Pack", this); actionPack->setIcon(QIcon(":/icons/resources/pack.png")); actionPack->setStatusTip("Pack current design"); @@ -223,10 +237,13 @@ void BaseMainWindow::createMenusAndBars() menuBar->addAction(menuHelp->menuAction()); // Add File menu actions + menuFile->addAction(actionNew); + menuFile->addAction(actionLoadJSON); + menuFile->addAction(actionSaveJSON); + menuFile->addSeparator(); menuFile->addAction(actionExit); // Add Design menu actions - menuDesign->addAction(actionLoadJSON); menuDesign->addAction(actionPack); menuDesign->addAction(actionAssignBudget); menuDesign->addAction(actionPlace); @@ -240,7 +257,10 @@ void BaseMainWindow::createMenusAndBars() // Main action bar mainActionBar = new QToolBar("Main"); addToolBar(Qt::TopToolBarArea, mainActionBar); + mainActionBar->addAction(actionNew); mainActionBar->addAction(actionLoadJSON); + mainActionBar->addAction(actionSaveJSON); + mainActionBar->addSeparator(); mainActionBar->addAction(actionPack); mainActionBar->addAction(actionAssignBudget); mainActionBar->addAction(actionPlace); @@ -280,7 +300,7 @@ void BaseMainWindow::load_json(std::string filename) if (parse_json_file(f, filename, ctx.get())) { log("Loading design successful.\n"); Q_EMIT updateTreeView(); - updateLoaded(); + updateActions(); } else { actionLoadJSON->setEnabled(true); log("Loading design failed.\n"); @@ -295,15 +315,26 @@ void BaseMainWindow::open_json() } } +void BaseMainWindow::save_json() +{ + QString fileName = QFileDialog::getSaveFileName(this, QString("Save JSON"), QString(), QString("*.json")); + if (!fileName.isEmpty()) { + std::string fn = fileName.toStdString(); + std::ofstream f(fn); + if (write_json_file(f, fn, ctx.get())) + log("Saving JSON successful.\n"); + else + log("Saving JSON failed.\n"); + } +} + void BaseMainWindow::pack_finished(bool status) { disableActions(); if (status) { log("Packing design successful.\n"); Q_EMIT updateTreeView(); - actionPlace->setEnabled(true); - actionAssignBudget->setEnabled(true); - onPackFinished(); + updateActions(); } else { log("Packing design failed.\n"); } @@ -313,9 +344,8 @@ void BaseMainWindow::budget_finish(bool status) { disableActions(); if (status) { - log("Assigning timing budget successful.\n"); - actionPlace->setEnabled(true); - onBudgetFinished(); + log("Assigning timing budget successful.\n"); + updateActions(); } else { log("Assigning timing budget failed.\n"); } @@ -327,8 +357,7 @@ void BaseMainWindow::place_finished(bool status) if (status) { log("Placing design successful.\n"); Q_EMIT updateTreeView(); - actionRoute->setEnabled(true); - onPlaceFinished(); + updateActions(); } else { log("Placing design failed.\n"); } @@ -339,7 +368,7 @@ void BaseMainWindow::route_finished(bool status) if (status) { log("Routing design successful.\n"); Q_EMIT updateTreeView(); - onRouteFinished(); + updateActions(); } else log("Routing design failed.\n"); } @@ -379,11 +408,12 @@ void BaseMainWindow::place() { Q_EMIT task->place(timing_driven); } void BaseMainWindow::disableActions() { - actionLoadJSON->setEnabled(false); + actionLoadJSON->setEnabled(true); actionPack->setEnabled(false); actionAssignBudget->setEnabled(false); actionPlace->setEnabled(false); actionRoute->setEnabled(false); + actionExecutePy->setEnabled(true); actionPlay->setEnabled(false); @@ -393,11 +423,18 @@ void BaseMainWindow::disableActions() onDisableActions(); } -void BaseMainWindow::updateLoaded() +void BaseMainWindow::updateActions() { - disableActions(); - actionPack->setEnabled(true); - onJsonLoaded(); + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionPack->setEnabled(true); + else if (ctx->settings.find(ctx->id("place"))==ctx->settings.end()) { + actionAssignBudget->setEnabled(true); + actionPlace->setEnabled(true); + } + else if (ctx->settings.find(ctx->id("route"))==ctx->settings.end()) + actionRoute->setEnabled(true); + + onUpdateActions(); } void BaseMainWindow::execute_python() diff --git a/gui/basewindow.h b/gui/basewindow.h index 91389978..d2640813 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -48,7 +48,8 @@ class BaseMainWindow : public QMainWindow explicit BaseMainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent = 0); virtual ~BaseMainWindow(); Context *getContext() { return ctx.get(); } - void updateLoaded(); + void updateActions(); + void notifyChangeContext(); protected: @@ -57,11 +58,7 @@ class BaseMainWindow : public QMainWindow void load_json(std::string filename); virtual void onDisableActions(){}; - virtual void onJsonLoaded(){}; - virtual void onPackFinished(){}; - virtual void onBudgetFinished(){}; - virtual void onPlaceFinished(){}; - virtual void onRouteFinished(){}; + virtual void onUpdateActions(){}; protected Q_SLOTS: void writeInfo(std::string text); @@ -70,6 +67,7 @@ class BaseMainWindow : public QMainWindow virtual void new_proj() = 0; void open_json(); + void save_json(); void budget(); void place(); @@ -110,7 +108,10 @@ class BaseMainWindow : public QMainWindow QToolBar *mainActionBar; QProgressBar *progressBar; + QAction *actionNew; QAction *actionLoadJSON; + QAction *actionSaveJSON; + QAction *actionPack; QAction *actionAssignBudget; QAction *actionPlace; diff --git a/gui/create_img.sh b/gui/create_img.sh index 1508d023..fcce4e88 100755 --- a/gui/create_img.sh +++ b/gui/create_img.sh @@ -2,5 +2,6 @@ convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 ' convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'PCF'" resources/open.png ice40/resources/open_pcf.png convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'BASE'" resources/open.png ecp5/resources/open_base.png convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'LPF'" resources/open.png ecp5/resources/open_lpf.png -convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'ASC'" resources/save.png ice40/resources/save_asc.png -convert -font helvetica -fill red -pointsize 7 -gravity center -draw "text 2,8 'CONFIG'" resources/save.png ecp5/resources/save_config.png \ No newline at end of file +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'ASC'" resources/save.png ice40/resources/save_asc.png +convert -font helvetica -fill red -pointsize 7 -gravity center -draw "text 2,8 'CONFIG'" resources/save.png ecp5/resources/save_config.png +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'JSON'" resources/save.png resources/save_json.png \ No newline at end of file diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index a54ab8b5..43b31f4c 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -188,8 +188,13 @@ void MainWindow::onDisableActions() actionSaveConfig->setEnabled(false); } -void MainWindow::onJsonLoaded() { actionLoadLPF->setEnabled(true); } - -void MainWindow::onRouteFinished() { actionLoadBase->setEnabled(true); } +void MainWindow::onUpdateActions() { + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionLoadLPF->setEnabled(true); + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionLoadBase->setEnabled(true); + if (ctx->settings.find(ctx->id("route"))!=ctx->settings.end()) + actionSaveConfig->setEnabled(true); +} NEXTPNR_NAMESPACE_END diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index 186a7974..b47e7ec7 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -38,8 +38,7 @@ class MainWindow : public BaseMainWindow protected: void onDisableActions() override; - void onJsonLoaded() override; - void onRouteFinished() override; + void onUpdateActions() override; protected Q_SLOTS: void new_proj() override; diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index b766734f..7c8effac 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -186,7 +186,11 @@ void MainWindow::onDisableActions() actionSaveAsc->setEnabled(false); } -void MainWindow::onJsonLoaded() { actionLoadPCF->setEnabled(true); } -void MainWindow::onRouteFinished() { actionSaveAsc->setEnabled(true); } +void MainWindow::onUpdateActions() { + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionLoadPCF->setEnabled(true); + if (ctx->settings.find(ctx->id("route"))!=ctx->settings.end()) + actionSaveAsc->setEnabled(true); +} NEXTPNR_NAMESPACE_END diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h index de160174..ed1b6aaf 100644 --- a/gui/ice40/mainwindow.h +++ b/gui/ice40/mainwindow.h @@ -39,8 +39,7 @@ class MainWindow : public BaseMainWindow void load_pcf(std::string filename); void onDisableActions() override; - void onJsonLoaded() override; - void onRouteFinished() override; + void onUpdateActions() override; protected Q_SLOTS: void new_proj() override; diff --git a/gui/resources/save_json.png b/gui/resources/save_json.png new file mode 100644 index 00000000..cbeb3243 Binary files /dev/null and b/gui/resources/save_json.png differ diff --git a/json/jsonparse.cc b/json/jsonparse.cc index b2597828..92bbf92f 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -740,7 +740,8 @@ void json_import(Context *ctx, string modname, JsonNode *node) for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { json_import_top_attrib(ctx, modname, attr_node, &ctx->attrs, attrid); } - + ctx->settings[ctx->id("synth")] = "1"; + JsonNode *ports_parent = nullptr; if (node->data_dict.count("ports") > 0) ports_parent = node->data_dict.at("ports"); -- cgit v1.2.3 From 903391a9e43cf5e27c4707b9b456c310e9d60524 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 13:02:15 +0200 Subject: Remove base config, since deprecated --- gui/ecp5/mainwindow.cc | 28 +--------------------------- gui/ecp5/mainwindow.h | 5 ----- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index 43b31f4c..043a6b86 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -60,12 +60,6 @@ void MainWindow::createMenu() actionLoadLPF->setEnabled(false); connect(actionLoadLPF, &QAction::triggered, this, &MainWindow::open_lpf); - actionLoadBase = new QAction("Open Base Config", this); - actionLoadBase->setIcon(QIcon(":/icons/resources/open_base.png")); - actionLoadBase->setStatusTip("Open Base Config file"); - actionLoadBase->setEnabled(false); - connect(actionLoadBase, &QAction::triggered, this, &MainWindow::open_base); - actionSaveConfig = new QAction("Save Bitstream", this); actionSaveConfig->setIcon(QIcon(":/icons/resources/save_config.png")); actionSaveConfig->setStatusTip("Save Bitstream config file"); @@ -75,12 +69,10 @@ void MainWindow::createMenu() // Add actions in menus mainActionBar->addSeparator(); mainActionBar->addAction(actionLoadLPF); - mainActionBar->addAction(actionLoadBase); mainActionBar->addAction(actionSaveConfig); menuDesign->addSeparator(); menuDesign->addAction(actionLoadLPF); - menuDesign->addAction(actionLoadBase); menuDesign->addAction(actionSaveConfig); } @@ -139,13 +131,6 @@ void MainWindow::new_proj() } } -void MainWindow::load_base_config(std::string filename) -{ - disableActions(); - currentBaseConfig = filename; - actionSaveConfig->setEnabled(true); -} - void MainWindow::open_lpf() { QString fileName = QFileDialog::getOpenFileName(this, QString("Open LPF"), QString(), QString("*.lpf")); @@ -162,21 +147,13 @@ void MainWindow::open_lpf() } } -void MainWindow::open_base() -{ - QString fileName = QFileDialog::getOpenFileName(this, QString("Open Base Config"), QString(), QString("*.config")); - if (!fileName.isEmpty()) { - load_base_config(fileName.toStdString()); - } -} - void MainWindow::save_config() { QString fileName = QFileDialog::getSaveFileName(this, QString("Save Bitstream"), QString(), QString("*.config")); if (!fileName.isEmpty()) { std::string fn = fileName.toStdString(); disableActions(); - write_bitstream(ctx.get(), currentBaseConfig, fileName.toStdString()); + write_bitstream(ctx.get(), "", fileName.toStdString()); log("Saving Bitstream successful.\n"); } } @@ -184,15 +161,12 @@ void MainWindow::save_config() void MainWindow::onDisableActions() { actionLoadLPF->setEnabled(false); - actionLoadBase->setEnabled(false); actionSaveConfig->setEnabled(false); } void MainWindow::onUpdateActions() { if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) actionLoadLPF->setEnabled(true); - if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) - actionLoadBase->setEnabled(true); if (ctx->settings.find(ctx->id("route"))!=ctx->settings.end()) actionSaveConfig->setEnabled(true); } diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index b47e7ec7..dc283cc7 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -34,7 +34,6 @@ class MainWindow : public BaseMainWindow public: void createMenu(); - void load_base_config(std::string filename); protected: void onDisableActions() override; @@ -44,17 +43,13 @@ class MainWindow : public BaseMainWindow void new_proj() override; void newContext(Context *ctx); void open_lpf(); - void open_base(); void save_config(); private: QAction *actionLoadLPF; - QAction *actionLoadBase; QAction *actionSaveConfig; ArchArgs chipArgs; - - std::string currentBaseConfig; }; NEXTPNR_NAMESPACE_END -- cgit v1.2.3 From aca372de99b960ca808e49fec27d2aaf890574d3 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 13:33:20 +0200 Subject: fix title --- gui/ecp5/mainwindow.cc | 2 +- gui/ecp5/mainwindow.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index 043a6b86..913c2520 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -47,7 +47,7 @@ MainWindow::~MainWindow() {} void MainWindow::newContext(Context *ctx) { - std::string title = "nextpnr-generic - " + ctx->getChipName() + " ( " + chipArgs.package + " )"; + std::string title = "nextpnr-ecp5 - " + ctx->getChipName() + " ( " + chipArgs.package + " )"; setWindowTitle(title.c_str()); } diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index dc283cc7..65493fbc 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -48,8 +48,6 @@ class MainWindow : public BaseMainWindow private: QAction *actionLoadLPF; QAction *actionSaveConfig; - - ArchArgs chipArgs; }; NEXTPNR_NAMESPACE_END -- cgit v1.2.3 From 66ea9f39f7f5d6e1152105328f9a48a367bd8ce0 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 15:18:35 +0200 Subject: enable lading of jsons and setting up context --- common/command.cc | 24 +++++++++++++++++++++++- common/command.h | 3 ++- ecp5/main.cc | 1 + generic/main.cc | 1 + gui/basewindow.cc | 25 ++++++++----------------- gui/basewindow.h | 6 +++--- gui/ecp5/mainwindow.cc | 8 ++++---- gui/ecp5/mainwindow.h | 2 +- gui/generic/mainwindow.cc | 4 ++-- gui/generic/mainwindow.h | 2 +- gui/ice40/mainwindow.cc | 8 ++++---- gui/ice40/mainwindow.h | 2 +- ice40/main.cc | 2 ++ 13 files changed, 53 insertions(+), 35 deletions(-) diff --git a/common/command.cc b/common/command.cc index 7b0b2caa..1a8f810e 100644 --- a/common/command.cc +++ b/common/command.cc @@ -245,7 +245,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) #ifndef NO_GUI if (vm.count("gui")) { Application a(argc, argv, (vm.count("gui-no-aa") > 0)); - MainWindow w(std::move(ctx), chipArgs); + MainWindow w(std::move(ctx), this); try { if (vm.count("json")) { std::string filename = vm["json"].as(); @@ -378,6 +378,28 @@ int CommandHandler::exec() } } +std::unique_ptr CommandHandler::load_json(std::string filename) +{ + vm.clear(); + std::unordered_map values; + { + std::ifstream f(filename); + if (!load_json_settings(f, filename, values)) + log_error("Loading design failed.\n"); + } + std::unique_ptr ctx = createContext(values); + settings = std::unique_ptr(new Settings(ctx.get())); + setupContext(ctx.get()); + setupArchContext(ctx.get()); + { + std::ifstream f(filename); + if (!parse_json_file(f, filename, ctx.get())) + log_error("Loading design failed.\n"); + } + customAfterLoad(ctx.get()); + return ctx; +} + void CommandHandler::run_script_hook(const std::string &name) { #ifndef NO_PYTHON diff --git a/common/command.h b/common/command.h index 5c5ceb9a..c7b58517 100644 --- a/common/command.h +++ b/common/command.h @@ -22,6 +22,7 @@ #define COMMAND_H #include +#include #include "nextpnr.h" #include "settings.h" @@ -36,6 +37,7 @@ class CommandHandler virtual ~CommandHandler(){}; int exec(); + std::unique_ptr load_json(std::string filename); protected: virtual void setupArchContext(Context *ctx) = 0; @@ -57,7 +59,6 @@ class CommandHandler protected: po::variables_map vm; - ArchArgs chipArgs; std::unique_ptr settings; private: diff --git a/ecp5/main.cc b/ecp5/main.cc index 0620b8b7..9917e217 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -111,6 +111,7 @@ static std::string speedString(ArchArgs::SpeedGrade speed) std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map &values) { + ArchArgs chipArgs; chipArgs.type = ArchArgs::NONE; if (vm.count("25k")) diff --git a/generic/main.cc b/generic/main.cc index f0070e92..1f0ee22d 100644 --- a/generic/main.cc +++ b/generic/main.cc @@ -53,6 +53,7 @@ void GenericCommandHandler::customBitstream(Context *ctx) {} std::unique_ptr GenericCommandHandler::createContext(std::unordered_map &values) { + ArchArgs chipArgs; if (values.find("arch.name")!=values.end()) { std::string arch_name = values["arch.name"].str; if (arch_name != "generic") diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 59dd6f7b..5b03b667 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -38,8 +38,8 @@ static void initBasenameResource() { Q_INIT_RESOURCE(base); } NEXTPNR_NAMESPACE_BEGIN -BaseMainWindow::BaseMainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent) - : QMainWindow(parent), chipArgs(args), ctx(std::move(context)), timing_driven(false) +BaseMainWindow::BaseMainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent) + : QMainWindow(parent), handler(handler), ctx(std::move(context)), timing_driven(false) { initBasenameResource(); qRegisterMetaType(); @@ -293,25 +293,16 @@ void BaseMainWindow::createMenusAndBars() setStatusBar(statusBar); } -void BaseMainWindow::load_json(std::string filename) -{ - disableActions(); - std::ifstream f(filename); - if (parse_json_file(f, filename, ctx.get())) { - log("Loading design successful.\n"); - Q_EMIT updateTreeView(); - updateActions(); - } else { - actionLoadJSON->setEnabled(true); - log("Loading design failed.\n"); - } -} - void BaseMainWindow::open_json() { QString fileName = QFileDialog::getOpenFileName(this, QString("Open JSON"), QString(), QString("*.json")); if (!fileName.isEmpty()) { - load_json(fileName.toStdString()); + disableActions(); + ctx = handler->load_json(fileName.toStdString()); + Q_EMIT contextChanged(ctx.get()); + Q_EMIT updateTreeView(); + log("Loading design successful.\n"); + updateActions(); } } diff --git a/gui/basewindow.h b/gui/basewindow.h index d2640813..4276c401 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -22,6 +22,7 @@ #include "nextpnr.h" #include "worker.h" +#include "command.h" #include #include @@ -45,7 +46,7 @@ class BaseMainWindow : public QMainWindow Q_OBJECT public: - explicit BaseMainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent = 0); + explicit BaseMainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent = 0); virtual ~BaseMainWindow(); Context *getContext() { return ctx.get(); } void updateActions(); @@ -55,7 +56,6 @@ class BaseMainWindow : public QMainWindow protected: void createMenusAndBars(); void disableActions(); - void load_json(std::string filename); virtual void onDisableActions(){}; virtual void onUpdateActions(){}; @@ -88,7 +88,7 @@ class BaseMainWindow : public QMainWindow protected: // state variables - ArchArgs chipArgs; + CommandHandler *handler; std::unique_ptr ctx; TaskManager *task; bool timing_driven; diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index 913c2520..b06e10e9 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -30,8 +30,8 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } NEXTPNR_NAMESPACE_BEGIN -MainWindow::MainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent) - : BaseMainWindow(std::move(context), args, parent) +MainWindow::MainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent) + : BaseMainWindow(std::move(context), handler, parent) { initMainResource(); @@ -47,7 +47,7 @@ MainWindow::~MainWindow() {} void MainWindow::newContext(Context *ctx) { - std::string title = "nextpnr-ecp5 - " + ctx->getChipName() + " ( " + chipArgs.package + " )"; + std::string title = "nextpnr-ecp5 - " + ctx->getChipName() + " ( " + ctx->archArgs().package + " )"; setWindowTitle(title.c_str()); } @@ -113,7 +113,7 @@ void MainWindow::new_proj() bool ok; QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok); if (ok && !item.isEmpty()) { - + ArchArgs chipArgs; chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item); QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type), diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index 65493fbc..e60fc5b0 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -29,7 +29,7 @@ class MainWindow : public BaseMainWindow Q_OBJECT public: - explicit MainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent = 0); + explicit MainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent = 0); virtual ~MainWindow(); public: diff --git a/gui/generic/mainwindow.cc b/gui/generic/mainwindow.cc index eefff39c..f616ca1a 100644 --- a/gui/generic/mainwindow.cc +++ b/gui/generic/mainwindow.cc @@ -26,8 +26,8 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } NEXTPNR_NAMESPACE_BEGIN -MainWindow::MainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent) - : BaseMainWindow(std::move(context), args, parent) +MainWindow::MainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent) + : BaseMainWindow(std::move(context), handler, parent) { initMainResource(); QMessageBox::critical(0, "Error - FIXME", "No GUI support for nextpnr-generic"); diff --git a/gui/generic/mainwindow.h b/gui/generic/mainwindow.h index bb6a4cf1..4d1cf598 100644 --- a/gui/generic/mainwindow.h +++ b/gui/generic/mainwindow.h @@ -29,7 +29,7 @@ class MainWindow : public BaseMainWindow Q_OBJECT public: - explicit MainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent = 0); + explicit MainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent = 0); virtual ~MainWindow(); public: diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index 7c8effac..c2ac264f 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -35,8 +35,8 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } NEXTPNR_NAMESPACE_BEGIN -MainWindow::MainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent) - : BaseMainWindow(std::move(context), args, parent) +MainWindow::MainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent) + : BaseMainWindow(std::move(context), handler, parent) { initMainResource(); @@ -123,7 +123,7 @@ void MainWindow::new_proj() bool ok; QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok); if (ok && !item.isEmpty()) { - + ArchArgs chipArgs; chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item); QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type), @@ -156,7 +156,7 @@ void MainWindow::load_pcf(std::string filename) void MainWindow::newContext(Context *ctx) { - std::string title = "nextpnr-ice40 - " + ctx->getChipName() + " ( " + chipArgs.package + " )"; + std::string title = "nextpnr-ice40 - " + ctx->getChipName() + " ( " + ctx->archArgs().package + " )"; setWindowTitle(title.c_str()); } diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h index ed1b6aaf..6e725a16 100644 --- a/gui/ice40/mainwindow.h +++ b/gui/ice40/mainwindow.h @@ -29,7 +29,7 @@ class MainWindow : public BaseMainWindow Q_OBJECT public: - explicit MainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent = 0); + explicit MainWindow(std::unique_ptr context, CommandHandler *handler, QWidget *parent = 0); virtual ~MainWindow(); public: diff --git a/ice40/main.cc b/ice40/main.cc index f3885f29..de618cbf 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -118,6 +118,8 @@ void Ice40CommandHandler::setupArchContext(Context *ctx) std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map &values) { + ArchArgs chipArgs; + chipArgs.type = ArchArgs::NONE; if (vm.count("lp384")) { chipArgs.type = ArchArgs::LP384; chipArgs.package = "qn32"; -- cgit v1.2.3 From 95280060b869f266beaff023dd63d74905c39ef4 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 15 Jun 2019 13:09:49 +0200 Subject: No need for settings class --- common/command.cc | 22 ++++++++--------- common/command.h | 3 +-- common/nextpnr.h | 13 ++++++++++ common/placer1.cc | 10 ++++---- common/placer1.h | 4 ++-- common/placer_heap.cc | 10 ++++---- common/placer_heap.h | 4 ++-- common/router1.cc | 10 ++++---- common/router1.h | 5 ++-- common/settings.h | 66 --------------------------------------------------- common/timing_opt.h | 6 ++--- 11 files changed, 48 insertions(+), 105 deletions(-) delete mode 100644 common/settings.h diff --git a/common/command.cc b/common/command.cc index 1a8f810e..ca054532 100644 --- a/common/command.cc +++ b/common/command.cc @@ -192,11 +192,11 @@ void CommandHandler::setupContext(Context *ctx) } if (vm.count("ignore-loops")) { - settings->set("timing/ignoreLoops", true); + ctx->settings[ctx->id("timing/ignoreLoops")] = std::to_string(true); } if (vm.count("timing-allow-fail")) { - settings->set("timing/allowFail", true); + ctx->settings[ctx->id("timing/allowFail")] = std::to_string(true); } if (vm.count("placer")) { @@ -205,20 +205,20 @@ void CommandHandler::setupContext(Context *ctx) Arch::availablePlacers.end()) log_error("Placer algorithm '%s' is not supported (available options: %s)\n", placer.c_str(), boost::algorithm::join(Arch::availablePlacers, ", ").c_str()); - settings->set("placer", placer); + ctx->settings[ctx->id("placer")] = placer; } else { - settings->set("placer", Arch::defaultPlacer); + ctx->settings[ctx->id("placer")] = Arch::defaultPlacer; } if (vm.count("cstrweight")) { - settings->set("placer1/constraintWeight", vm["cstrweight"].as()); + ctx->settings[ctx->id("placer1/constraintWeight")] = std::to_string(vm["cstrweight"].as()); } if (vm.count("starttemp")) { - settings->set("placer1/startTemp", vm["starttemp"].as()); + ctx->settings[ctx->id("placer1/startTemp")] = std::to_string(vm["starttemp"].as()); } if (vm.count("placer-budgets")) { - settings->set("placer1/budgetBased", true); + ctx->settings[ctx->id("placer1/budgetBased")] = std::to_string(true); } if (vm.count("freq")) { auto freq = vm["freq"].as(); @@ -230,9 +230,9 @@ void CommandHandler::setupContext(Context *ctx) if (vm.count("no-tmdriv")) ctx->timing_driven = false; - settings->set("arch.name", std::string(ctx->archId().c_str(ctx))); - settings->set("arch.type", std::string(ctx->archArgsToId(ctx->archArgs()).c_str(ctx))); - settings->set("seed", ctx->rngstate); + ctx->settings[ctx->id("arch.name")] = std::string(ctx->archId().c_str(ctx)); + ctx->settings[ctx->id("arch.type")] = std::string(ctx->archArgsToId(ctx->archArgs()).c_str(ctx)); + ctx->settings[ctx->id("seed")] = std::to_string(ctx->rngstate); } int CommandHandler::executeMain(std::unique_ptr ctx) @@ -366,7 +366,6 @@ int CommandHandler::exec() log_error("Loading design failed.\n"); } std::unique_ptr ctx = createContext(values); - settings = std::unique_ptr(new Settings(ctx.get())); setupContext(ctx.get()); setupArchContext(ctx.get()); int rc = executeMain(std::move(ctx)); @@ -388,7 +387,6 @@ std::unique_ptr CommandHandler::load_json(std::string filename) log_error("Loading design failed.\n"); } std::unique_ptr ctx = createContext(values); - settings = std::unique_ptr(new Settings(ctx.get())); setupContext(ctx.get()); setupArchContext(ctx.get()); { diff --git a/common/command.h b/common/command.h index c7b58517..b5908e3f 100644 --- a/common/command.h +++ b/common/command.h @@ -24,7 +24,7 @@ #include #include #include "nextpnr.h" -#include "settings.h" +#include "log.h" NEXTPNR_NAMESPACE_BEGIN @@ -59,7 +59,6 @@ class CommandHandler protected: po::variables_map vm; - std::unique_ptr settings; private: po::options_description options; diff --git a/common/nextpnr.h b/common/nextpnr.h index 66134456..b796b8aa 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -32,6 +32,7 @@ #include #include +#include #ifndef NEXTPNR_H #define NEXTPNR_H @@ -724,6 +725,18 @@ struct Context : Arch, DeterministicRNG void check() const; void archcheck() const; + + template T setting(const char *name, T defaultValue) + { + IdString new_id = id(name); + if (settings.find(new_id) != settings.end()) + return boost::lexical_cast(settings.find(new_id)->second.str); + else + settings[id(name)] = std::to_string(defaultValue); + + return defaultValue; + } + }; NEXTPNR_NAMESPACE_END diff --git a/common/placer1.cc b/common/placer1.cc index a8ddd8a6..89e4f919 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -1131,12 +1131,12 @@ class SAPlacer Placer1Cfg cfg; }; -Placer1Cfg::Placer1Cfg(Context *ctx) : Settings(ctx) +Placer1Cfg::Placer1Cfg(Context *ctx) { - constraintWeight = get("placer1/constraintWeight", 10); - minBelsForGridPick = get("placer1/minBelsForGridPick", 64); - budgetBased = get("placer1/budgetBased", false); - startTemp = get("placer1/startTemp", 1); + constraintWeight = ctx->setting("placer1/constraintWeight", 10); + minBelsForGridPick = ctx->setting("placer1/minBelsForGridPick", 64); + budgetBased = ctx->setting("placer1/budgetBased", false); + startTemp = ctx->setting("placer1/startTemp", 1); timingFanoutThresh = std::numeric_limits::max(); } diff --git a/common/placer1.h b/common/placer1.h index 4c7c7339..0f2e2894 100644 --- a/common/placer1.h +++ b/common/placer1.h @@ -20,11 +20,11 @@ #define PLACE_H #include "nextpnr.h" -#include "settings.h" +#include "log.h" NEXTPNR_NAMESPACE_BEGIN -struct Placer1Cfg : public Settings +struct Placer1Cfg { Placer1Cfg(Context *ctx); float constraintWeight; diff --git a/common/placer_heap.cc b/common/placer_heap.cc index f9b639f8..4d1f4863 100644 --- a/common/placer_heap.cc +++ b/common/placer_heap.cc @@ -1516,11 +1516,11 @@ int HeAPPlacer::CutSpreader::seq = 0; bool placer_heap(Context *ctx, PlacerHeapCfg cfg) { return HeAPPlacer(ctx, cfg).place(); } -PlacerHeapCfg::PlacerHeapCfg(Context *ctx) : Settings(ctx) +PlacerHeapCfg::PlacerHeapCfg(Context *ctx) { - alpha = get("placerHeap/alpha", 0.1); - criticalityExponent = get("placerHeap/criticalityExponent", 2); - timingWeight = get("placerHeap/timingWeight", 10); + alpha = ctx->setting("placerHeap/alpha", 0.1); + criticalityExponent = ctx->setting("placerHeap/criticalityExponent", 2); + timingWeight = ctx->setting("placerHeap/timingWeight", 10); } NEXTPNR_NAMESPACE_END @@ -1538,7 +1538,7 @@ bool placer_heap(Context *ctx, PlacerHeapCfg cfg) return false; } -PlacerHeapCfg::PlacerHeapCfg(Context *ctx) : Settings(ctx) {} +PlacerHeapCfg::PlacerHeapCfg(Context *ctx) {} NEXTPNR_NAMESPACE_END diff --git a/common/placer_heap.h b/common/placer_heap.h index 841aa0d9..2def5e75 100644 --- a/common/placer_heap.h +++ b/common/placer_heap.h @@ -27,11 +27,11 @@ #ifndef PLACER_HEAP_H #define PLACER_HEAP_H #include "nextpnr.h" -#include "settings.h" +#include "log.h" NEXTPNR_NAMESPACE_BEGIN -struct PlacerHeapCfg : public Settings +struct PlacerHeapCfg { PlacerHeapCfg(Context *ctx); diff --git a/common/router1.cc b/common/router1.cc index 28a422c8..02c817c7 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -733,12 +733,12 @@ struct Router1 NEXTPNR_NAMESPACE_BEGIN -Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx) +Router1Cfg::Router1Cfg(Context *ctx) { - maxIterCnt = get("router1/maxIterCnt", 200); - cleanupReroute = get("router1/cleanupReroute", true); - fullCleanupReroute = get("router1/fullCleanupReroute", true); - useEstimate = get("router1/useEstimate", true); + maxIterCnt = ctx->setting("router1/maxIterCnt", 200); + cleanupReroute = ctx->setting("router1/cleanupReroute", true); + fullCleanupReroute = ctx->setting("router1/fullCleanupReroute", true); + useEstimate = ctx->setting("router1/useEstimate", true); wireRipupPenalty = ctx->getRipupDelayPenalty(); netRipupPenalty = 10 * ctx->getRipupDelayPenalty(); diff --git a/common/router1.h b/common/router1.h index 80d7aa96..f3d325ad 100644 --- a/common/router1.h +++ b/common/router1.h @@ -21,11 +21,10 @@ #define ROUTER1_H #include "nextpnr.h" -#include "settings.h" - +#include "log.h" NEXTPNR_NAMESPACE_BEGIN -struct Router1Cfg : Settings +struct Router1Cfg { Router1Cfg(Context *ctx); diff --git a/common/settings.h b/common/settings.h deleted file mode 100644 index 9d43c774..00000000 --- a/common/settings.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * nextpnr -- Next Generation Place and Route - * - * Copyright (C) 2018 Miodrag Milanovic - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ -#ifndef SETTINGS_H -#define SETTINGS_H - -#include -#include "log.h" -#include "nextpnr.h" - -NEXTPNR_NAMESPACE_BEGIN - -class Settings -{ - public: - explicit Settings(Context *ctx) : ctx(ctx) {} - - template T get(const char *name, T defaultValue) - { - try { - IdString id = ctx->id(name); - if (ctx->settings.find(id) != ctx->settings.end()) - return boost::lexical_cast(ctx->settings.find(id)->second.str); - else - ctx->settings[ctx->id(name)] = std::to_string(defaultValue); - - } catch (boost::bad_lexical_cast &) { - log_error("Problem reading setting %s, using default value\n", name); - } - return defaultValue; - } - - template void set(const char *name, T value); - - private: - Context *ctx; -}; - -template inline void Settings::set(const char *name, T value) -{ - ctx->settings[ctx->id(name)] = std::to_string(value); -} - -template <> inline void Settings::set(const char *name, std::string value) -{ - ctx->settings[ctx->id(name)] = value; -} - -NEXTPNR_NAMESPACE_END - -#endif // SETTINGS_H diff --git a/common/timing_opt.h b/common/timing_opt.h index ceb35c71..cdc02406 100644 --- a/common/timing_opt.h +++ b/common/timing_opt.h @@ -18,13 +18,13 @@ */ #include "nextpnr.h" -#include "settings.h" +#include "log.h" NEXTPNR_NAMESPACE_BEGIN -struct TimingOptCfg : public Settings +struct TimingOptCfg { - TimingOptCfg(Context *ctx) : Settings(ctx) {} + TimingOptCfg(Context *ctx) {} // The timing optimiser will *only* optimise cells of these types // Normally these would only be logic cells (or tiles if applicable), the algorithm makes little sense -- cgit v1.2.3 From 8d5724f4fd8e384ac59b8a94ec6979593239976c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 15 Jun 2019 15:23:51 +0200 Subject: moved some context variables to settings --- common/command.cc | 21 +++++++++++++++------ common/nextpnr.h | 18 +++++++++++------- common/place_common.cc | 2 +- common/placer1.cc | 14 +++++++------- common/placer_heap.cc | 2 +- common/timing.cc | 20 ++++++++++---------- gui/worker.cc | 4 ++-- 7 files changed, 47 insertions(+), 34 deletions(-) diff --git a/common/command.cc b/common/command.cc index ca054532..89e05b4d 100644 --- a/common/command.cc +++ b/common/command.cc @@ -181,9 +181,9 @@ void CommandHandler::setupContext(Context *ctx) } if (vm.count("slack_redist_iter")) { - ctx->slack_redist_iter = vm["slack_redist_iter"].as(); + ctx->settings[ctx->id("slack_redist_iter")] = vm["slack_redist_iter"].as(); if (vm.count("freq") && vm["freq"].as() == 0) { - ctx->auto_freq = true; + ctx->settings[ctx->id("auto_freq")] = std::to_string(true); #ifndef NO_GUI if (!vm.count("gui")) #endif @@ -223,13 +223,22 @@ void CommandHandler::setupContext(Context *ctx) if (vm.count("freq")) { auto freq = vm["freq"].as(); if (freq > 0) - ctx->target_freq = freq * 1e6; + ctx->settings[ctx->id("target_freq")] = std::to_string(freq * 1e6); } - ctx->timing_driven = true; if (vm.count("no-tmdriv")) - ctx->timing_driven = false; - + ctx->settings[ctx->id("timing_driven")] = std::to_string(false); + + // Setting default values + if (ctx->settings.find(ctx->id("target_freq")) == ctx->settings.end()) + ctx->settings[ctx->id("target_freq")] = std::to_string(12e6); + if (ctx->settings.find(ctx->id("timing_driven")) == ctx->settings.end()) + ctx->settings[ctx->id("timing_driven")] = std::to_string(true); + if (ctx->settings.find(ctx->id("slack_redist_iter")) == ctx->settings.end()) + ctx->settings[ctx->id("slack_redist_iter")] = "0"; + if (ctx->settings.find(ctx->id("auto_freq")) == ctx->settings.end()) + ctx->settings[ctx->id("auto_freq")] = std::to_string(false); + ctx->settings[ctx->id("arch.name")] = std::string(ctx->archId().c_str(ctx)); ctx->settings[ctx->id("arch.type")] = std::string(ctx->archArgsToId(ctx->archArgs()).c_str(ctx)); ctx->settings[ctx->id("seed")] = std::to_string(ctx->rngstate); diff --git a/common/nextpnr.h b/common/nextpnr.h index b796b8aa..e4461cb4 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -701,10 +701,6 @@ struct Context : Arch, DeterministicRNG bool verbose = false; bool debug = false; bool force = false; - bool timing_driven = true; - float target_freq = 12e6; - bool auto_freq = false; - int slack_redist_iter = 0; Context(ArchArgs args) : Arch(args) {} @@ -733,10 +729,18 @@ struct Context : Arch, DeterministicRNG return boost::lexical_cast(settings.find(new_id)->second.str); else settings[id(name)] = std::to_string(defaultValue); - - return defaultValue; + + return defaultValue; + } + + template T setting(const char *name) const + { + IdString new_id = id(name); + if (settings.find(new_id) != settings.end()) + return boost::lexical_cast(settings.find(new_id)->second.str); + else + throw std::runtime_error("settings does not exists"); } - }; NEXTPNR_NAMESPACE_END diff --git a/common/place_common.cc b/common/place_common.cc index 73a320d0..cb9799b5 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -37,7 +37,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type if (driver_gb) return 0; int clock_count; - bool timing_driven = ctx->timing_driven && type == MetricType::COST && + bool timing_driven = ctx->setting("timing_driven") && type == MetricType::COST && ctx->getPortTimingClass(driver_cell, net->driver.port, clock_count) != TMG_IGNORE; delay_t negative_slack = 0; delay_t worst_slack = std::numeric_limits::max(); diff --git a/common/placer1.cc b/common/placer1.cc index 89e4f919..a2272b83 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -219,7 +219,7 @@ class SAPlacer if ((placed_cells - constr_placed_cells) % 500 != 0) log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells), int(autoplaced.size())); - if (cfg.budgetBased && ctx->slack_redist_iter > 0) + if (cfg.budgetBased && ctx->setting("slack_redist_iter") > 0) assign_budget(ctx); ctx->yield(); auto iplace_end = std::chrono::high_resolution_clock::now(); @@ -370,16 +370,16 @@ class SAPlacer ctx->shuffle(autoplaced); // Legalisation is a big change so force a slack redistribution here - if (ctx->slack_redist_iter > 0 && cfg.budgetBased) + if (ctx->setting("slack_redist_iter") > 0 && cfg.budgetBased) assign_budget(ctx, true /* quiet */); } require_legal = false; - } else if (cfg.budgetBased && ctx->slack_redist_iter > 0 && iter % ctx->slack_redist_iter == 0) { + } else if (cfg.budgetBased && ctx->setting("slack_redist_iter") > 0 && iter % ctx->setting("slack_redist_iter") == 0) { assign_budget(ctx, true /* quiet */); } // Invoke timing analysis to obtain criticalities - if (!cfg.budgetBased && ctx->timing_driven) + if (!cfg.budgetBased && ctx->setting("timing_driven")) get_criticalities(ctx, &net_crit); // Need to rebuild costs after criticalities change setup_costs(); @@ -804,7 +804,7 @@ class SAPlacer if (ignore_net(ni)) continue; net_bounds[ni->udata] = get_net_bounds(ni); - if (ctx->timing_driven && int(ni->users.size()) < cfg.timingFanoutThresh) + if (ctx->setting("timing_driven") && int(ni->users.size()) < cfg.timingFanoutThresh) for (size_t i = 0; i < ni->users.size(); i++) net_arc_tcost[ni->udata][i] = get_timing_cost(ni, i); } @@ -1021,7 +1021,7 @@ class SAPlacer } } - if (ctx->timing_driven && int(pn->users.size()) < cfg.timingFanoutThresh) { + if (ctx->setting("timing_driven") && int(pn->users.size()) < cfg.timingFanoutThresh) { // Output ports - all arcs change timing if (port.second.type == PORT_OUT) { int cc; @@ -1061,7 +1061,7 @@ class SAPlacer if (md.already_bounds_changed_x[bc] == MoveChangeData::NO_CHANGE) md.wirelen_delta += md.new_net_bounds[bc].hpwl() - net_bounds[bc].hpwl(); - if (ctx->timing_driven) { + if (ctx->setting("timing_driven")) { for (const auto &tc : md.changed_arcs) { double old_cost = net_arc_tcost.at(tc.first).at(tc.second); double new_cost = get_timing_cost(net_by_udata.at(tc.first), tc.second); diff --git a/common/placer_heap.cc b/common/placer_heap.cc index 4d1f4863..7b72200a 100644 --- a/common/placer_heap.cc +++ b/common/placer_heap.cc @@ -234,7 +234,7 @@ class HeAPPlacer std::chrono::duration(run_stopt - run_startt).count()); } - if (ctx->timing_driven) + if (ctx->setting("timing_driven")) get_criticalities(ctx, &net_crit); if (legal_hpwl < best_hpwl) { diff --git a/common/timing.cc b/common/timing.cc index 2ce9eea3..582c347f 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -113,7 +113,7 @@ struct Timing Timing(Context *ctx, bool net_delays, bool update, CriticalPathMap *crit_path = nullptr, DelayFrequency *slack_histogram = nullptr, NetCriticalityMap *net_crit = nullptr) - : ctx(ctx), net_delays(net_delays), update(update), min_slack(1.0e12 / ctx->target_freq), + : ctx(ctx), net_delays(net_delays), update(update), min_slack(1.0e12 / ctx->setting("target_freq")), crit_path(crit_path), slack_histogram(slack_histogram), net_crit(net_crit), async_clock(ctx->id("$async$")) { @@ -121,7 +121,7 @@ struct Timing delay_t walk_paths() { - const auto clk_period = ctx->getDelayFromNS(1.0e9 / ctx->target_freq).maxDelay(); + const auto clk_period = ctx->getDelayFromNS(1.0e9 / ctx->setting("target_freq")).maxDelay(); // First, compute the topographical order of nets to walk through the circuit, assuming it is a _acyclic_ graph // TODO(eddieh): Handle the case where it is cyclic, e.g. combinatorial loops @@ -657,17 +657,17 @@ void assign_budget(Context *ctx, bool quiet) { if (!quiet) { log_break(); - log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", ctx->target_freq / 1e6); + log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", ctx->setting("target_freq") / 1e6); } - Timing timing(ctx, ctx->slack_redist_iter > 0 /* net_delays */, true /* update */); + Timing timing(ctx, ctx->setting("slack_redist_iter")> 0 /* net_delays */, true /* update */); timing.assign_budget(); if (!quiet || ctx->verbose) { for (auto &net : ctx->nets) { for (auto &user : net.second->users) { // Post-update check - if (!ctx->auto_freq && user.budget < 0) + if (!ctx->setting("auto_freq") && user.budget < 0) log_info("port %s.%s, connected to net '%s', has negative " "timing budget of %fns\n", user.cell->name.c_str(ctx), user.port.c_str(ctx), net.first.c_str(ctx), @@ -683,13 +683,13 @@ void assign_budget(Context *ctx, bool quiet) // For slack redistribution, if user has not specified a frequency dynamically adjust the target frequency to be the // currently achieved maximum - if (ctx->auto_freq && ctx->slack_redist_iter > 0) { - delay_t default_slack = delay_t((1.0e9 / ctx->getDelayNS(1)) / ctx->target_freq); - ctx->target_freq = 1.0e9 / ctx->getDelayNS(default_slack - timing.min_slack); + if (ctx->setting("auto_freq") && ctx->setting("slack_redist_iter") > 0) { + delay_t default_slack = delay_t((1.0e9 / ctx->getDelayNS(1)) / ctx->setting("target_freq")); + ctx->settings[ctx->id("target_freq")] = std::to_string(1.0e9 / ctx->getDelayNS(default_slack - timing.min_slack)); if (ctx->verbose) log_info("minimum slack for this assign = %.2f ns, target Fmax for next " "update = %.2f MHz\n", - ctx->getDelayNS(timing.min_slack), ctx->target_freq / 1e6); + ctx->getDelayNS(timing.min_slack),ctx->setting("target_freq") / 1e6); } if (!quiet) @@ -896,7 +896,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p for (auto &clock : clock_reports) { const auto &clock_name = clock.first.str(ctx); const int width = max_width - clock_name.size(); - float target = ctx->target_freq / 1e6; + float target = ctx->setting("target_freq") / 1e6; if (ctx->nets.at(clock.first)->clkconstr) target = 1000 / ctx->getDelayNS(ctx->nets.at(clock.first)->clkconstr->period.minDelay()); diff --git a/gui/worker.cc b/gui/worker.cc index 900883d4..bd14771b 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -68,7 +68,7 @@ void Worker::budget(double freq) { Q_EMIT taskStarted(); try { - ctx->target_freq = freq; + ctx->settings[ctx->id("target_freq")] = std::to_string(freq); assign_budget(ctx); Q_EMIT budget_finish(true); } catch (WorkerInterruptionRequested) { @@ -80,7 +80,7 @@ void Worker::place(bool timing_driven) { Q_EMIT taskStarted(); try { - ctx->timing_driven = timing_driven; + ctx->settings[ctx->id("timing_driven")] = std::to_string(timing_driven); Q_EMIT place_finished(ctx->place()); } catch (WorkerInterruptionRequested) { Q_EMIT taskCanceled(); -- cgit v1.2.3 From 226885a58f67d81fb05e13bde91be8b654479210 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 15 Jun 2019 15:31:18 +0200 Subject: use save seed --- common/command.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/command.cc b/common/command.cc index 89e05b4d..09e75fdf 100644 --- a/common/command.cc +++ b/common/command.cc @@ -154,6 +154,9 @@ po::options_description CommandHandler::getGeneralOptions() void CommandHandler::setupContext(Context *ctx) { + if (ctx->settings.find(ctx->id("seed")) != ctx->settings.end()) + ctx->rngstate = ctx->setting("seed"); + if (vm.count("verbose")) { ctx->verbose = true; } -- cgit v1.2.3 From ff257a092930492a1260cf0c1f79d76c3d098612 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 15 Jun 2019 15:35:23 +0200 Subject: default placement only if not set --- common/command.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/command.cc b/common/command.cc index 09e75fdf..dc98d032 100644 --- a/common/command.cc +++ b/common/command.cc @@ -209,8 +209,6 @@ void CommandHandler::setupContext(Context *ctx) log_error("Placer algorithm '%s' is not supported (available options: %s)\n", placer.c_str(), boost::algorithm::join(Arch::availablePlacers, ", ").c_str()); ctx->settings[ctx->id("placer")] = placer; - } else { - ctx->settings[ctx->id("placer")] = Arch::defaultPlacer; } if (vm.count("cstrweight")) { @@ -241,7 +239,9 @@ void CommandHandler::setupContext(Context *ctx) ctx->settings[ctx->id("slack_redist_iter")] = "0"; if (ctx->settings.find(ctx->id("auto_freq")) == ctx->settings.end()) ctx->settings[ctx->id("auto_freq")] = std::to_string(false); - + if (ctx->settings.find(ctx->id("placer")) == ctx->settings.end()) + ctx->settings[ctx->id("placer")] = Arch::defaultPlacer; + ctx->settings[ctx->id("arch.name")] = std::string(ctx->archId().c_str(ctx)); ctx->settings[ctx->id("arch.type")] = std::string(ctx->archArgsToId(ctx->archArgs()).c_str(ctx)); ctx->settings[ctx->id("seed")] = std::to_string(ctx->rngstate); -- cgit v1.2.3 From 92da4a91de0b602b0414754bd3ae05fdd70acbe7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 09:43:47 +0200 Subject: Preserve ports --- common/nextpnr.h | 3 +++ json/jsonparse.cc | 8 +++++++- json/jsonwrite.cc | 13 +++++++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index e4461cb4..6950ac76 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -548,6 +548,9 @@ struct BaseCtx std::unordered_map> nets; std::unordered_map> cells; + // Top-level ports + std::unordered_map ports; + // Floorplanning regions std::unordered_map> region; diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 92bbf92f..76854bf9 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -717,6 +717,12 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string assert(false); } ctx->cells[iobuf->name] = std::move(iobuf); + + PortInfo pinfo; + pinfo.name = net->name; + pinfo.net = net; + pinfo.type = type; + ctx->ports[net->name] = pinfo; } void json_import_toplevel_port(Context *ctx, const string &modname, const std::vector &netnames, @@ -726,7 +732,7 @@ void json_import_toplevel_port(Context *ctx, const string &modname, const std::v JsonNode *nets_node = node->data_dict.at("bits"); json_import_ports( ctx, modname, netnames, "Top Level IO", portname, dir_node, nets_node, - [ctx](PortType type, const std::string &name, NetInfo *net) { insert_iobuf(ctx, net, type, name); }); + [ctx](PortType type, const std::string &name, NetInfo *net) { insert_iobuf(ctx, net, type, name); }); } void json_import(Context *ctx, string modname, JsonNode *node) diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index ac54bc4e..552cd398 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -76,11 +76,20 @@ void write_module(std::ostream &f, Context *ctx) write_parameters(f, ctx, ctx->attrs, true); f << stringf("\n },\n"); f << stringf(" \"ports\": {"); - // TODO: Top level ports + bool first = true; + for (auto &pair : ctx->ports) { + auto &c = pair.second; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c.name, ctx).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); + f << stringf(" }"); + first = false; + } f << stringf("\n },\n"); f << stringf(" \"cells\": {"); - bool first = true; + first = true; for (auto &pair : ctx->cells) { auto &c = pair.second; f << stringf("%s\n", first ? "" : ","); -- cgit v1.2.3 From 87ecd492957af9871db60155d3dddf121ef15714 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 11:31:59 +0200 Subject: Fix loading json --- json/jsonparse.cc | 110 +++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 76854bf9..5c5c1bcd 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -661,62 +661,64 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string // During packing, this generic IO buffer will be converted to an // architecure primitive. // - std::unique_ptr iobuf = std::unique_ptr(new CellInfo()); - iobuf->name = ctx->id(name); - std::copy(net->attrs.begin(), net->attrs.end(), std::inserter(iobuf->attrs, iobuf->attrs.begin())); - if (type == PORT_IN) { - if (ctx->verbose) - log_info("processing input port %s\n", name.c_str()); - iobuf->type = ctx->id("$nextpnr_ibuf"); - iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT}; - // Special case: input, etc, directly drives inout - if (net->driver.cell != nullptr) { - if (net->driver.cell->type != ctx->id("$nextpnr_iobuf")) - log_error("Top-level input '%s' also driven by %s.%s.\n", name.c_str(), - net->driver.cell->name.c_str(ctx), net->driver.port.c_str(ctx)); - net = net->driver.cell->ports.at(ctx->id("I")).net; - } - assert(net->driver.cell == nullptr); - net->driver.port = ctx->id("O"); - net->driver.cell = iobuf.get(); - } else if (type == PORT_OUT) { - if (ctx->verbose) - log_info("processing output port %s\n", name.c_str()); - iobuf->type = ctx->id("$nextpnr_obuf"); - iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), net, PORT_IN}; - PortRef ref; - ref.cell = iobuf.get(); - ref.port = ctx->id("I"); - net->users.push_back(ref); - } else if (type == PORT_INOUT) { - if (ctx->verbose) - log_info("processing inout port %s\n", name.c_str()); - iobuf->type = ctx->id("$nextpnr_iobuf"); - iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), nullptr, PORT_IN}; - - // Split the input and output nets for bidir ports - std::unique_ptr net2 = std::unique_ptr(new NetInfo()); - net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i"); - net2->driver = net->driver; - if (net->driver.cell != nullptr) { - net2->driver.cell->ports[net2->driver.port].net = net2.get(); - net->driver.cell = nullptr; + if (ctx->settings.find(ctx->id("synth"))==ctx->settings.end()) { + std::unique_ptr iobuf = std::unique_ptr(new CellInfo()); + iobuf->name = ctx->id(name); + std::copy(net->attrs.begin(), net->attrs.end(), std::inserter(iobuf->attrs, iobuf->attrs.begin())); + if (type == PORT_IN) { + if (ctx->verbose) + log_info("processing input port %s\n", name.c_str()); + iobuf->type = ctx->id("$nextpnr_ibuf"); + iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT}; + // Special case: input, etc, directly drives inout + if (net->driver.cell != nullptr) { + if (net->driver.cell->type != ctx->id("$nextpnr_iobuf")) + log_error("Top-level input '%s' also driven by %s.%s.\n", name.c_str(), + net->driver.cell->name.c_str(ctx), net->driver.port.c_str(ctx)); + net = net->driver.cell->ports.at(ctx->id("I")).net; + } + assert(net->driver.cell == nullptr); + net->driver.port = ctx->id("O"); + net->driver.cell = iobuf.get(); + } else if (type == PORT_OUT) { + if (ctx->verbose) + log_info("processing output port %s\n", name.c_str()); + iobuf->type = ctx->id("$nextpnr_obuf"); + iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), net, PORT_IN}; + PortRef ref; + ref.cell = iobuf.get(); + ref.port = ctx->id("I"); + net->users.push_back(ref); + } else if (type == PORT_INOUT) { + if (ctx->verbose) + log_info("processing inout port %s\n", name.c_str()); + iobuf->type = ctx->id("$nextpnr_iobuf"); + iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), nullptr, PORT_IN}; + + // Split the input and output nets for bidir ports + std::unique_ptr net2 = std::unique_ptr(new NetInfo()); + net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i"); + net2->driver = net->driver; + if (net->driver.cell != nullptr) { + net2->driver.cell->ports[net2->driver.port].net = net2.get(); + net->driver.cell = nullptr; + } + iobuf->ports[ctx->id("I")].net = net2.get(); + PortRef ref; + ref.cell = iobuf.get(); + ref.port = ctx->id("I"); + net2->users.push_back(ref); + ctx->nets[net2->name] = std::move(net2); + + iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT}; + assert(net->driver.cell == nullptr); + net->driver.port = ctx->id("O"); + net->driver.cell = iobuf.get(); + } else { + assert(false); } - iobuf->ports[ctx->id("I")].net = net2.get(); - PortRef ref; - ref.cell = iobuf.get(); - ref.port = ctx->id("I"); - net2->users.push_back(ref); - ctx->nets[net2->name] = std::move(net2); - - iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT}; - assert(net->driver.cell == nullptr); - net->driver.port = ctx->id("O"); - net->driver.cell = iobuf.get(); - } else { - assert(false); + ctx->cells[iobuf->name] = std::move(iobuf); } - ctx->cells[iobuf->name] = std::move(iobuf); PortInfo pinfo; pinfo.name = net->name; -- cgit v1.2.3 From 0c3093fe49d9ba14577b38bd5032081699e05680 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 17:45:53 +0200 Subject: fix regression --- json/jsonparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 5c5c1bcd..81b0c3be 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -748,7 +748,6 @@ void json_import(Context *ctx, string modname, JsonNode *node) for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { json_import_top_attrib(ctx, modname, attr_node, &ctx->attrs, attrid); } - ctx->settings[ctx->id("synth")] = "1"; JsonNode *ports_parent = nullptr; if (node->data_dict.count("ports") > 0) @@ -884,6 +883,7 @@ void json_import(Context *ctx, string modname, JsonNode *node) } } check_all_nets_driven(ctx); + ctx->settings[ctx->id("synth")] = "1"; } }; // End Namespace JsonParser -- cgit v1.2.3 From 9affcf82d969bf34aae449a28391451a4f4fdfd8 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Jun 2019 18:06:01 +0200 Subject: default for 5G is speed 8 --- ecp5/main.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ecp5/main.cc b/ecp5/main.cc index 9917e217..fa0783e1 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -151,7 +151,11 @@ std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map Date: Tue, 25 Jun 2019 18:19:25 +0200 Subject: clangformat run --- common/command.cc | 22 +++++++++++----------- common/command.h | 4 ++-- common/nextpnr.cc | 47 +++++++++++++++++++++++------------------------ common/nextpnr.h | 37 ++++++++++++++++++++----------------- common/placer1.cc | 3 ++- common/placer1.h | 2 +- common/placer_heap.h | 2 +- common/router1.h | 2 +- common/timing.cc | 10 ++++++---- common/timing_opt.h | 2 +- ecp5/main.cc | 36 ++++++++++++++++++++---------------- generic/arch.cc | 3 ++- generic/main.cc | 8 ++++---- gui/basewindow.cc | 17 ++++++++--------- gui/basewindow.h | 2 +- gui/ecp5/mainwindow.cc | 9 +++++---- gui/ice40/mainwindow.cc | 7 ++++--- ice40/arch.cc | 5 +++-- ice40/main.cc | 16 ++++++++-------- ice40/pack.cc | 32 +++++++++++++++----------------- json/jsonparse.cc | 32 +++++++++++++++----------------- json/jsonparse.h | 3 ++- json/jsonwrite.cc | 32 ++++++++++++++++---------------- 23 files changed, 171 insertions(+), 162 deletions(-) diff --git a/common/command.cc b/common/command.cc index dc98d032..8acbafd2 100644 --- a/common/command.cc +++ b/common/command.cc @@ -27,8 +27,8 @@ #include "pybindings.h" #endif -#include #include +#include #include #include #include @@ -156,7 +156,7 @@ void CommandHandler::setupContext(Context *ctx) { if (ctx->settings.find(ctx->id("seed")) != ctx->settings.end()) ctx->rngstate = ctx->setting("seed"); - + if (vm.count("verbose")) { ctx->verbose = true; } @@ -239,7 +239,7 @@ void CommandHandler::setupContext(Context *ctx) ctx->settings[ctx->id("slack_redist_iter")] = "0"; if (ctx->settings.find(ctx->id("auto_freq")) == ctx->settings.end()) ctx->settings[ctx->id("auto_freq")] = std::to_string(false); - if (ctx->settings.find(ctx->id("placer")) == ctx->settings.end()) + if (ctx->settings.find(ctx->id("placer")) == ctx->settings.end()) ctx->settings[ctx->id("placer")] = Arch::defaultPlacer; ctx->settings[ctx->id("arch.name")] = std::string(ctx->archId().c_str(ctx)); @@ -298,16 +298,16 @@ int CommandHandler::executeMain(std::unique_ptr ctx) execute_python_file(filename.c_str()); } else #endif - if (vm.count("json")) { - bool do_pack = vm.count("pack-only")!=0 || vm.count("no-pack")==0; - bool do_place = vm.count("pack-only")==0 && vm.count("no-place")==0; - bool do_route = vm.count("pack-only")==0 && vm.count("no-route")==0; + if (vm.count("json")) { + bool do_pack = vm.count("pack-only") != 0 || vm.count("no-pack") == 0; + bool do_place = vm.count("pack-only") == 0 && vm.count("no-place") == 0; + bool do_route = vm.count("pack-only") == 0 && vm.count("no-route") == 0; if (do_pack) { run_script_hook("pre-pack"); if (!ctx->pack() && !ctx->force) log_error("Packing design failed.\n"); - } + } assign_budget(ctx.get()); ctx->check(); print_utilisation(ctx.get()); @@ -329,7 +329,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) customBitstream(ctx.get()); } - if (vm.count("write")) { + if (vm.count("write")) { std::string filename = vm["write"].as(); std::ofstream f(filename); if (!write_json_file(f, filename, ctx.get())) @@ -370,7 +370,7 @@ int CommandHandler::exec() if (executeBeforeContext()) return 0; - std::unordered_map values; + std::unordered_map values; if (vm.count("json")) { std::string filename = vm["json"].as(); std::ifstream f(filename); @@ -392,7 +392,7 @@ int CommandHandler::exec() std::unique_ptr CommandHandler::load_json(std::string filename) { vm.clear(); - std::unordered_map values; + std::unordered_map values; { std::ifstream f(filename); if (!load_json_settings(f, filename, values)) diff --git a/common/command.h b/common/command.h index b5908e3f..e52b5a48 100644 --- a/common/command.h +++ b/common/command.h @@ -23,8 +23,8 @@ #include #include -#include "nextpnr.h" #include "log.h" +#include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN @@ -41,7 +41,7 @@ class CommandHandler protected: virtual void setupArchContext(Context *ctx) = 0; - virtual std::unique_ptr createContext(std::unordered_map &values) = 0; + virtual std::unique_ptr createContext(std::unordered_map &values) = 0; virtual po::options_description getArchOptions() = 0; virtual void validate(){}; virtual void customAfterLoad(Context *ctx){}; diff --git a/common/nextpnr.cc b/common/nextpnr.cc index a026b60d..d4cc4917 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -18,8 +18,8 @@ */ #include "nextpnr.h" -#include "log.h" #include +#include "log.h" NEXTPNR_NAMESPACE_BEGIN @@ -465,23 +465,23 @@ void BaseCtx::archInfoToAttributes() ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).c_str(this); ci->attrs[id("BEL_STRENGTH")] = std::to_string((int)ci->belStrength); } - if (ci->constr_x!= ci->UNCONSTR) + if (ci->constr_x != ci->UNCONSTR) ci->attrs[id("CONSTR_X")] = std::to_string(ci->constr_x); - if (ci->constr_y!= ci->UNCONSTR) + if (ci->constr_y != ci->UNCONSTR) ci->attrs[id("CONSTR_Y")] = std::to_string(ci->constr_y); - if (ci->constr_z!= ci->UNCONSTR) { + if (ci->constr_z != ci->UNCONSTR) { ci->attrs[id("CONSTR_Z")] = std::to_string(ci->constr_z); ci->attrs[id("CONSTR_ABS_Z")] = std::to_string(ci->constr_abs_z ? 1 : 0); } - if (ci->constr_parent!= nullptr) + if (ci->constr_parent != nullptr) ci->attrs[id("CONSTR_PARENT")] = ci->constr_parent->name.c_str(this); if (!ci->constr_children.empty()) { std::string constr = ""; - for(auto &item : ci->constr_children) - { - if (!constr.empty()) constr += std::string(";"); + for (auto &item : ci->constr_children) { + if (!constr.empty()) + constr += std::string(";"); constr += item->name.c_str(this); - } + } ci->attrs[id("CONSTR_CHILDREN")] = constr; } } @@ -490,7 +490,8 @@ void BaseCtx::archInfoToAttributes() std::string routing; bool first = true; for (auto &item : ni->wires) { - if (!first) routing += ";"; + if (!first) + routing += ";"; routing += getCtx()->getWireName(item.first).c_str(this); routing += ";"; if (item.second.pip != PipId()) @@ -501,7 +502,7 @@ void BaseCtx::archInfoToAttributes() ni->attrs[id("ROUTING")] = routing; } } - + void BaseCtx::attributesToArchInfo() { for (auto &cell : cells) { @@ -512,7 +513,7 @@ void BaseCtx::attributesToArchInfo() PlaceStrength strength = PlaceStrength::STRENGTH_USER; if (str != ci->attrs.end()) strength = (PlaceStrength)std::stoi(str->second.str); - + BelId b = getCtx()->getBelByName(id(val->second.str)); getCtx()->bindBel(b, ci, strength); } @@ -525,12 +526,12 @@ void BaseCtx::attributesToArchInfo() ci->constr_y = std::stoi(val->second.str); val = ci->attrs.find(id("CONSTR_Z")); - if (val != ci->attrs.end()) + if (val != ci->attrs.end()) ci->constr_z = std::stoi(val->second.str); val = ci->attrs.find(id("CONSTR_ABS_Z")); if (val != ci->attrs.end()) - ci->constr_abs_z = std::stoi(val->second.str)==1; + ci->constr_abs_z = std::stoi(val->second.str) == 1; val = ci->attrs.find(id("CONSTR_PARENT")); if (val != ci->attrs.end()) { @@ -541,11 +542,10 @@ void BaseCtx::attributesToArchInfo() val = ci->attrs.find(id("CONSTR_CHILDREN")); if (val != ci->attrs.end()) { std::vector strs; - boost::split(strs,val->second.str,boost::is_any_of(";")); - for(auto val : strs) - { + boost::split(strs, val->second.str, boost::is_any_of(";")); + for (auto val : strs) { ci->constr_children.push_back(cells.find(id(val.c_str()))->second.get()); - } + } } } for (auto &net : getCtx()->nets) { @@ -553,12 +553,11 @@ void BaseCtx::attributesToArchInfo() auto val = ni->attrs.find(id("ROUTING")); if (val != ni->attrs.end()) { std::vector strs; - boost::split(strs,val->second.str,boost::is_any_of(";")); - for(size_t i=0;isecond.str, boost::is_any_of(";")); + for (size_t i = 0; i < strs.size() / 3; i++) { + std::string wire = strs[i * 3]; + std::string pip = strs[i * 3 + 1]; + PlaceStrength strength = (PlaceStrength)std::stoi(strs[i * 3 + 2]); if (pip.empty()) getCtx()->bindWire(getCtx()->getWireByName(id(wire)), ni, strength); else diff --git a/common/nextpnr.h b/common/nextpnr.h index 6950ac76..3f434580 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -290,7 +290,7 @@ struct PipMap struct Property { bool is_string; - + std::string str; int num; @@ -299,22 +299,25 @@ struct Property bool isString() const { return is_string; } - void setNumber(int val) { is_string = false; num = val; str = std::to_string(val); } - void setString(std::string val) { is_string = true; str = val; } - - const char * c_str() const { return str.c_str(); } - operator std::string () const { return str; } - - bool operator==(const std::string other) const + void setNumber(int val) { - return str == other; - } - bool operator!=(const std::string other) const + is_string = false; + num = val; + str = std::to_string(val); + } + void setString(std::string val) { - return str != other; - } + is_string = true; + str = val; + } + + const char *c_str() const { return str.c_str(); } + operator std::string() const { return str; } + + bool operator==(const std::string other) const { return str == other; } + bool operator!=(const std::string other) const { return str != other; } - Property& operator=(std::string other) + Property &operator=(std::string other) { is_string = true; str = other; @@ -732,10 +735,10 @@ struct Context : Arch, DeterministicRNG return boost::lexical_cast(settings.find(new_id)->second.str); else settings[id(name)] = std::to_string(defaultValue); - - return defaultValue; + + return defaultValue; } - + template T setting(const char *name) const { IdString new_id = id(name); diff --git a/common/placer1.cc b/common/placer1.cc index a2272b83..7ab454c7 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -374,7 +374,8 @@ class SAPlacer assign_budget(ctx, true /* quiet */); } require_legal = false; - } else if (cfg.budgetBased && ctx->setting("slack_redist_iter") > 0 && iter % ctx->setting("slack_redist_iter") == 0) { + } else if (cfg.budgetBased && ctx->setting("slack_redist_iter") > 0 && + iter % ctx->setting("slack_redist_iter") == 0) { assign_budget(ctx, true /* quiet */); } diff --git a/common/placer1.h b/common/placer1.h index 0f2e2894..08edb2c4 100644 --- a/common/placer1.h +++ b/common/placer1.h @@ -19,8 +19,8 @@ #ifndef PLACE_H #define PLACE_H -#include "nextpnr.h" #include "log.h" +#include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN diff --git a/common/placer_heap.h b/common/placer_heap.h index 2def5e75..9b1c52cb 100644 --- a/common/placer_heap.h +++ b/common/placer_heap.h @@ -26,8 +26,8 @@ #ifndef PLACER_HEAP_H #define PLACER_HEAP_H -#include "nextpnr.h" #include "log.h" +#include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN diff --git a/common/router1.h b/common/router1.h index f3d325ad..a37784f4 100644 --- a/common/router1.h +++ b/common/router1.h @@ -20,8 +20,8 @@ #ifndef ROUTER1_H #define ROUTER1_H -#include "nextpnr.h" #include "log.h" +#include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN struct Router1Cfg diff --git a/common/timing.cc b/common/timing.cc index 60aef3fa..599d6dbd 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -658,10 +658,11 @@ void assign_budget(Context *ctx, bool quiet) { if (!quiet) { log_break(); - log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", ctx->setting("target_freq") / 1e6); + log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", + ctx->setting("target_freq") / 1e6); } - Timing timing(ctx, ctx->setting("slack_redist_iter")> 0 /* net_delays */, true /* update */); + Timing timing(ctx, ctx->setting("slack_redist_iter") > 0 /* net_delays */, true /* update */); timing.assign_budget(); if (!quiet || ctx->verbose) { @@ -686,11 +687,12 @@ void assign_budget(Context *ctx, bool quiet) // currently achieved maximum if (ctx->setting("auto_freq") && ctx->setting("slack_redist_iter") > 0) { delay_t default_slack = delay_t((1.0e9 / ctx->getDelayNS(1)) / ctx->setting("target_freq")); - ctx->settings[ctx->id("target_freq")] = std::to_string(1.0e9 / ctx->getDelayNS(default_slack - timing.min_slack)); + ctx->settings[ctx->id("target_freq")] = + std::to_string(1.0e9 / ctx->getDelayNS(default_slack - timing.min_slack)); if (ctx->verbose) log_info("minimum slack for this assign = %.2f ns, target Fmax for next " "update = %.2f MHz\n", - ctx->getDelayNS(timing.min_slack),ctx->setting("target_freq") / 1e6); + ctx->getDelayNS(timing.min_slack), ctx->setting("target_freq") / 1e6); } if (!quiet) diff --git a/common/timing_opt.h b/common/timing_opt.h index cdc02406..775d9596 100644 --- a/common/timing_opt.h +++ b/common/timing_opt.h @@ -17,8 +17,8 @@ * */ -#include "nextpnr.h" #include "log.h" +#include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN diff --git a/ecp5/main.cc b/ecp5/main.cc index fa0783e1..75126cea 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -34,7 +34,7 @@ class ECP5CommandHandler : public CommandHandler public: ECP5CommandHandler(int argc, char **argv); virtual ~ECP5CommandHandler(){}; - std::unique_ptr createContext(std::unordered_map &values) override; + std::unique_ptr createContext(std::unordered_map &values) override; void setupArchContext(Context *ctx) override{}; void customAfterLoad(Context *ctx) override; void validate() override; @@ -100,16 +100,20 @@ void ECP5CommandHandler::customBitstream(Context *ctx) static std::string speedString(ArchArgs::SpeedGrade speed) { - switch(speed){ - case ArchArgs::SPEED_6: return "6"; - case ArchArgs::SPEED_7: return "7"; - case ArchArgs::SPEED_8: return "8"; - case ArchArgs::SPEED_8_5G: return "8"; + switch (speed) { + case ArchArgs::SPEED_6: + return "6"; + case ArchArgs::SPEED_7: + return "7"; + case ArchArgs::SPEED_8: + return "8"; + case ArchArgs::SPEED_8_5G: + return "8"; } return ""; } -std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map &values) +std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map &values) { ArchArgs chipArgs; chipArgs.type = ArchArgs::NONE; @@ -154,15 +158,15 @@ std::unique_ptr ECP5CommandHandler::createContext(std::unordered_map ECP5CommandHandler::createContext(std::unordered_map ECP5CommandHandler::createContext(std::unordered_map ECP5CommandHandler::createContext(std::unordered_map(new Context(chipArgs)); - for(auto &val : values) + for (auto &val : values) ctx->settings[ctx->id(val.first)] = val.second; ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; ctx->settings[ctx->id("arch.speed")] = speedString(ctx->archArgs().speed); diff --git a/generic/arch.cc b/generic/arch.cc index 2db9e547..fa3c825d 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -505,7 +505,8 @@ bool Arch::place() } } -bool Arch::route() { +bool Arch::route() +{ bool retVal = router1(getCtx(), Router1Cfg(getCtx())); getCtx()->settings[getCtx()->id("route")] = "1"; archInfoToAttributes(); diff --git a/generic/main.cc b/generic/main.cc index 1f0ee22d..ce1a51c7 100644 --- a/generic/main.cc +++ b/generic/main.cc @@ -32,7 +32,7 @@ class GenericCommandHandler : public CommandHandler public: GenericCommandHandler(int argc, char **argv); virtual ~GenericCommandHandler(){}; - std::unique_ptr createContext(std::unordered_map &values) override; + std::unique_ptr createContext(std::unordered_map &values) override; void setupArchContext(Context *ctx) override{}; void customBitstream(Context *ctx) override; @@ -51,14 +51,14 @@ po::options_description GenericCommandHandler::getArchOptions() void GenericCommandHandler::customBitstream(Context *ctx) {} -std::unique_ptr GenericCommandHandler::createContext(std::unordered_map &values) +std::unique_ptr GenericCommandHandler::createContext(std::unordered_map &values) { ArchArgs chipArgs; - if (values.find("arch.name")!=values.end()) { + if (values.find("arch.name") != values.end()) { std::string arch_name = values["arch.name"].str; if (arch_name != "generic") log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); - } + } return std::unique_ptr(new Context(chipArgs)); } diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 5b03b667..550a4b93 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -310,11 +310,11 @@ void BaseMainWindow::save_json() { QString fileName = QFileDialog::getSaveFileName(this, QString("Save JSON"), QString(), QString("*.json")); if (!fileName.isEmpty()) { - std::string fn = fileName.toStdString(); + std::string fn = fileName.toStdString(); std::ofstream f(fn); if (write_json_file(f, fn, ctx.get())) log("Saving JSON successful.\n"); - else + else log("Saving JSON failed.\n"); } } @@ -335,7 +335,7 @@ void BaseMainWindow::budget_finish(bool status) { disableActions(); if (status) { - log("Assigning timing budget successful.\n"); + log("Assigning timing budget successful.\n"); updateActions(); } else { log("Assigning timing budget failed.\n"); @@ -399,7 +399,7 @@ void BaseMainWindow::place() { Q_EMIT task->place(timing_driven); } void BaseMainWindow::disableActions() { - actionLoadJSON->setEnabled(true); + actionLoadJSON->setEnabled(true); actionPack->setEnabled(false); actionAssignBudget->setEnabled(false); actionPlace->setEnabled(false); @@ -416,13 +416,12 @@ void BaseMainWindow::disableActions() void BaseMainWindow::updateActions() { - if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + if (ctx->settings.find(ctx->id("pack")) == ctx->settings.end()) actionPack->setEnabled(true); - else if (ctx->settings.find(ctx->id("place"))==ctx->settings.end()) { + else if (ctx->settings.find(ctx->id("place")) == ctx->settings.end()) { actionAssignBudget->setEnabled(true); - actionPlace->setEnabled(true); - } - else if (ctx->settings.find(ctx->id("route"))==ctx->settings.end()) + actionPlace->setEnabled(true); + } else if (ctx->settings.find(ctx->id("route")) == ctx->settings.end()) actionRoute->setEnabled(true); onUpdateActions(); diff --git a/gui/basewindow.h b/gui/basewindow.h index 4276c401..305cb6c9 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -20,9 +20,9 @@ #ifndef BASEMAINWINDOW_H #define BASEMAINWINDOW_H +#include "command.h" #include "nextpnr.h" #include "worker.h" -#include "command.h" #include #include diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index b06e10e9..880af047 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -164,10 +164,11 @@ void MainWindow::onDisableActions() actionSaveConfig->setEnabled(false); } -void MainWindow::onUpdateActions() { - if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) - actionLoadLPF->setEnabled(true); - if (ctx->settings.find(ctx->id("route"))!=ctx->settings.end()) +void MainWindow::onUpdateActions() +{ + if (ctx->settings.find(ctx->id("pack")) == ctx->settings.end()) + actionLoadLPF->setEnabled(true); + if (ctx->settings.find(ctx->id("route")) != ctx->settings.end()) actionSaveConfig->setEnabled(true); } diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index c2ac264f..ccff2117 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -186,10 +186,11 @@ void MainWindow::onDisableActions() actionSaveAsc->setEnabled(false); } -void MainWindow::onUpdateActions() { - if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) +void MainWindow::onUpdateActions() +{ + if (ctx->settings.find(ctx->id("pack")) == ctx->settings.end()) actionLoadPCF->setEnabled(true); - if (ctx->settings.find(ctx->id("route"))!=ctx->settings.end()) + if (ctx->settings.find(ctx->id("route")) != ctx->settings.end()) actionSaveAsc->setEnabled(true); } diff --git a/ice40/arch.cc b/ice40/arch.cc index d58951dd..0b1d280c 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -694,8 +694,9 @@ bool Arch::place() return retVal; } -bool Arch::route() { - bool retVal = router1(getCtx(), Router1Cfg(getCtx())); +bool Arch::route() +{ + bool retVal = router1(getCtx(), Router1Cfg(getCtx())); getCtx()->settings[getCtx()->id("route")] = "1"; archInfoToAttributes(); return retVal; diff --git a/ice40/main.cc b/ice40/main.cc index de618cbf..83cb04b0 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -36,7 +36,7 @@ class Ice40CommandHandler : public CommandHandler public: Ice40CommandHandler(int argc, char **argv); virtual ~Ice40CommandHandler(){}; - std::unique_ptr createContext(std::unordered_map &values) override; + std::unique_ptr createContext(std::unordered_map &values) override; void setupArchContext(Context *ctx) override; void validate() override; void customAfterLoad(Context *ctx) override; @@ -116,7 +116,7 @@ void Ice40CommandHandler::setupArchContext(Context *ctx) } } -std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map &values) +std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map &values) { ArchArgs chipArgs; chipArgs.type = ArchArgs::NONE; @@ -158,12 +158,12 @@ std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map(); - if (values.find("arch.name")!=values.end()) { + if (values.find("arch.name") != values.end()) { std::string arch_name = values["arch.name"].str; if (arch_name != "ice40") log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); } - if (values.find("arch.type")!=values.end()) { + if (values.find("arch.type") != values.end()) { std::string arch_type = values["arch.type"].str; if (chipArgs.type != ArchArgs::NONE) log_error("Overriding architecture is unsuported.\n"); @@ -190,14 +190,14 @@ std::unique_ptr Ice40CommandHandler::createContext(std::unordered_map Ice40CommandHandler::createContext(std::unordered_map(new Context(chipArgs)); - for(auto &val : values) + for (auto &val : values) ctx->settings[ctx->id(val.first)] = val.second; ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; diff --git a/ice40/pack.cc b/ice40/pack.cc index 66c5c0e8..d1366c9c 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -340,10 +340,9 @@ static void pack_constants(Context *ctx) gnd_net->driver.cell = gnd_cell.get(); gnd_net->driver.port = ctx->id("O"); gnd_cell->ports.at(ctx->id("O")).net = gnd_net.get(); - - NetInfo* gnd_net_info = gnd_net.get(); - if (ctx->nets.find(ctx->id("$PACKER_GND_NET"))!=ctx->nets.end()) - { + + NetInfo *gnd_net_info = gnd_net.get(); + if (ctx->nets.find(ctx->id("$PACKER_GND_NET")) != ctx->nets.end()) { gnd_net_info = ctx->nets.find(ctx->id("$PACKER_GND_NET"))->second.get(); } @@ -354,10 +353,9 @@ static void pack_constants(Context *ctx) vcc_net->driver.cell = vcc_cell.get(); vcc_net->driver.port = ctx->id("O"); vcc_cell->ports.at(ctx->id("O")).net = vcc_net.get(); - - NetInfo* vcc_net_info = vcc_net.get(); - if (ctx->nets.find(ctx->id("$PACKER_VCC_NET"))!=ctx->nets.end()) - { + + NetInfo *vcc_net_info = vcc_net.get(); + if (ctx->nets.find(ctx->id("$PACKER_VCC_NET")) != ctx->nets.end()) { vcc_net_info = ctx->nets.find(ctx->id("$PACKER_VCC_NET"))->second.get(); } @@ -387,8 +385,7 @@ static void pack_constants(Context *ctx) } // Vcc cell always inserted for now, as it may be needed during carry legalisation (TODO: trim later if actually // never used?) - if (vcc_net_info == vcc_net.get()) - { + if (vcc_net_info == vcc_net.get()) { ctx->cells[vcc_cell->name] = std::move(vcc_cell); ctx->nets[vcc_net->name] = std::move(vcc_net); } @@ -1239,13 +1236,14 @@ static void pack_special(Context *ctx) } auto feedback_path = packed->params[ctx->id("FEEDBACK_PATH")]; - std::string fbp_value = feedback_path == "DELAY" - ? "0" - : feedback_path == "SIMPLE" - ? "1" - : feedback_path == "PHASE_AND_DELAY" - ? "2" - : feedback_path == "EXTERNAL" ? "6" : std::string(feedback_path); + std::string fbp_value = + feedback_path == "DELAY" + ? "0" + : feedback_path == "SIMPLE" + ? "1" + : feedback_path == "PHASE_AND_DELAY" + ? "2" + : feedback_path == "EXTERNAL" ? "6" : std::string(feedback_path); if (!std::all_of(fbp_value.begin(), fbp_value.end(), isdigit)) log_error("PLL '%s' has unsupported FEEDBACK_PATH value '%s'\n", ci->name.c_str(ctx), feedback_path.c_str()); diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 29dcac0a..caedbb5b 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -338,7 +338,7 @@ void json_import_cell_params(Context *ctx, string &modname, CellInfo *cell, Json } void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNode *param_node, - std::unordered_map *dest, int param_id) + std::unordered_map *dest, int param_id) { // JsonNode *param; @@ -352,8 +352,7 @@ void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNod } 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)); + log_error("JSON parameter type of \"%s\' of net \'%s\' not supported\n", pId.c_str(ctx), net->name.c_str(ctx)); if (json_debug) log_info(" Added parameter \'%s\'=%s to net \'%s\' " "of module \'%s\'\n", @@ -361,7 +360,7 @@ void json_import_net_attrib(Context *ctx, string &modname, NetInfo *net, JsonNod } void json_import_top_attrib(Context *ctx, string &modname, JsonNode *param_node, - std::unordered_map *dest, int param_id) + std::unordered_map *dest, int param_id) { // JsonNode *param; @@ -377,8 +376,8 @@ void json_import_top_attrib(Context *ctx, string &modname, JsonNode *param_node, else log_error("JSON parameter type of \"%s\' of module not supported\n", pId.c_str(ctx)); if (json_debug) - log_info(" Added parameter \'%s\'=%s module \'%s\'\n", - pId.c_str(ctx), (*dest)[pId].c_str(), modname.c_str()); + log_info(" Added parameter \'%s\'=%s module \'%s\'\n", pId.c_str(ctx), (*dest)[pId].c_str(), + modname.c_str()); } static int const_net_idx = 0; @@ -669,7 +668,7 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string // During packing, this generic IO buffer will be converted to an // architecure primitive. // - if (ctx->settings.find(ctx->id("synth"))==ctx->settings.end()) { + if (ctx->settings.find(ctx->id("synth")) == ctx->settings.end()) { std::unique_ptr iobuf = std::unique_ptr(new CellInfo()); iobuf->name = ctx->id(name); std::copy(net->attrs.begin(), net->attrs.end(), std::inserter(iobuf->attrs, iobuf->attrs.begin())); @@ -682,7 +681,7 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string if (net->driver.cell != nullptr) { if (net->driver.cell->type != ctx->id("$nextpnr_iobuf")) log_error("Top-level input '%s' also driven by %s.%s.\n", name.c_str(), - net->driver.cell->name.c_str(ctx), net->driver.port.c_str(ctx)); + net->driver.cell->name.c_str(ctx), net->driver.port.c_str(ctx)); net = net->driver.cell->ports.at(ctx->id("I")).net; } assert(net->driver.cell == nullptr); @@ -897,12 +896,13 @@ void json_import(Context *ctx, string modname, JsonNode *node) std::string name = basename + (num_bits == 1 ? "" : std::string("[") + std::to_string(i) + std::string("]")); IdString net_id = ctx->id(name); - if (here->data_dict.count("attributes") && ctx->nets.find(net_id)!=ctx->nets.end()) { - NetInfo *this_net = ctx->nets[net_id].get(); - + if (here->data_dict.count("attributes") && ctx->nets.find(net_id) != ctx->nets.end()) { + NetInfo *this_net = ctx->nets[net_id].get(); + JsonNode *attr_node = here->data_dict.at("attributes"); if (attr_node->type != 'D') - log_error("JSON attribute list of \'%s\' is not a data dictionary\n", this_net->name.c_str(ctx)); + log_error("JSON attribute list of \'%s\' is not a data dictionary\n", + this_net->name.c_str(ctx)); // // Loop through all attributes, adding them into the @@ -911,12 +911,11 @@ void json_import(Context *ctx, string modname, JsonNode *node) for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { json_import_net_attrib(ctx, modname, this_net, attr_node, &this_net->attrs, attrid); } - } } - } + } } - } + } check_all_nets_driven(ctx); ctx->settings[ctx->id("synth")] = "1"; } @@ -956,7 +955,7 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) } } -bool load_json_settings(std::istream &f, std::string &filename, std::unordered_map &values) +bool load_json_settings(std::istream &f, std::string &filename, std::unordered_map &values) { try { using namespace JsonParser; @@ -993,7 +992,6 @@ bool load_json_settings(std::istream &f, std::string &filename, std::unordered_m values[pId].setString(param->data_string); else log_error("JSON parameter type of \"%s\' of module not supported\n", pId.c_str()); - } } } diff --git a/json/jsonparse.h b/json/jsonparse.h index ca971e5f..65e3f02e 100644 --- a/json/jsonparse.h +++ b/json/jsonparse.h @@ -27,7 +27,8 @@ NEXTPNR_NAMESPACE_BEGIN extern bool parse_json_file(std::istream &, std::string &, Context *); -extern bool load_json_settings(std::istream &f, std::string &filename, std::unordered_map &values); +extern bool load_json_settings(std::istream &f, std::string &filename, + std::unordered_map &values); NEXTPNR_NAMESPACE_END #endif diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index 552cd398..0b7a5b25 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -43,17 +43,15 @@ std::string get_string(std::string str) return newstr + "\""; } -std::string get_name(IdString name, Context *ctx) -{ - return get_string(name.c_str(ctx)); -} +std::string get_name(IdString name, Context *ctx) { return get_string(name.c_str(ctx)); } -void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) +void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, + bool for_module = false) { bool first = true; for (auto ¶m : parameters) { f << stringf("%s\n", first ? "" : ","); - f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first,ctx).c_str()); + f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first, ctx).c_str()); if (param.second.isString()) f << get_string(param.second); else @@ -65,7 +63,7 @@ void write_parameters(std::ostream &f, Context *ctx, const std::unordered_mapattrs.find(ctx->id("module")); - if (val != ctx->attrs.end()) + if (val != ctx->attrs.end()) f << stringf(" %s: {\n", get_string(val->second.str).c_str()); else f << stringf(" %s: {\n", get_string("top").c_str()); @@ -81,16 +79,17 @@ void write_module(std::ostream &f, Context *ctx) auto &c = pair.second; f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(c.name, ctx).c_str()); - f << stringf(" \"direction\": \"%s\",\n", c.type == PORT_IN ? "input" : c.type == PORT_INOUT ? "inout" : "output"); + f << stringf(" \"direction\": \"%s\",\n", + c.type == PORT_IN ? "input" : c.type == PORT_INOUT ? "inout" : "output"); f << stringf(" \"bits\": [ %d ]\n", pair.first.index); f << stringf(" }"); first = false; - } + } f << stringf("\n },\n"); f << stringf(" \"cells\": {"); first = true; - for (auto &pair : ctx->cells) { + for (auto &pair : ctx->cells) { auto &c = pair.second; f << stringf("%s\n", first ? "" : ","); f << stringf(" %s: {\n", get_name(c->name, ctx).c_str()); @@ -118,9 +117,9 @@ void write_module(std::ostream &f, Context *ctx) auto &p = conn.second; f << stringf("%s\n", first2 ? "" : ","); if (p.net) - f << stringf(" %s: [ %d ]", get_name(conn.first,ctx).c_str(), p.net->name.index); - else - f << stringf(" %s: [ ]", get_name(conn.first,ctx).c_str()); + f << stringf(" %s: [ %d ]", get_name(conn.first, ctx).c_str(), p.net->name.index); + else + f << stringf(" %s: [ ]", get_name(conn.first, ctx).c_str()); first2 = false; } @@ -146,7 +145,7 @@ void write_module(std::ostream &f, Context *ctx) f << stringf(" }"); first = false; } - + f << stringf("\n }\n"); f << stringf(" }"); } @@ -154,7 +153,8 @@ void write_module(std::ostream &f, Context *ctx) void write_context(std::ostream &f, Context *ctx) { f << stringf("{\n"); - f << stringf(" \"creator\": %s,\n", get_string( "Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")").c_str()); + f << stringf(" \"creator\": %s,\n", + get_string("Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")").c_str()); f << stringf(" \"modules\": {\n"); write_module(f, ctx); f << stringf("\n }"); @@ -166,7 +166,7 @@ void write_context(std::ostream &f, Context *ctx) bool write_json_file(std::ostream &f, std::string &filename, Context *ctx) { try { - using namespace JsonWriter; + using namespace JsonWriter; if (!f) log_error("failed to open JSON file.\n"); write_context(f, ctx); -- cgit v1.2.3 From 831c7f2ef1dce44e31f986ee591e9aa6441d9a6e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 28 Jun 2019 13:43:55 +0200 Subject: Speedup critical path --- common/placer1.cc | 17 +++++++++-------- common/placer1.h | 2 ++ common/placer_heap.cc | 3 ++- common/placer_heap.h | 1 + 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/common/placer1.cc b/common/placer1.cc index 7ab454c7..cb7ae847 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -219,7 +219,7 @@ class SAPlacer if ((placed_cells - constr_placed_cells) % 500 != 0) log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells), int(autoplaced.size())); - if (cfg.budgetBased && ctx->setting("slack_redist_iter") > 0) + if (cfg.budgetBased && cfg.slack_redist_iter > 0) assign_budget(ctx); ctx->yield(); auto iplace_end = std::chrono::high_resolution_clock::now(); @@ -370,17 +370,16 @@ class SAPlacer ctx->shuffle(autoplaced); // Legalisation is a big change so force a slack redistribution here - if (ctx->setting("slack_redist_iter") > 0 && cfg.budgetBased) + if (cfg.slack_redist_iter > 0 && cfg.budgetBased) assign_budget(ctx, true /* quiet */); } require_legal = false; - } else if (cfg.budgetBased && ctx->setting("slack_redist_iter") > 0 && - iter % ctx->setting("slack_redist_iter") == 0) { + } else if (cfg.budgetBased && cfg.slack_redist_iter > 0 && iter % cfg.slack_redist_iter == 0) { assign_budget(ctx, true /* quiet */); } // Invoke timing analysis to obtain criticalities - if (!cfg.budgetBased && ctx->setting("timing_driven")) + if (!cfg.budgetBased && cfg.timing_driven) get_criticalities(ctx, &net_crit); // Need to rebuild costs after criticalities change setup_costs(); @@ -805,7 +804,7 @@ class SAPlacer if (ignore_net(ni)) continue; net_bounds[ni->udata] = get_net_bounds(ni); - if (ctx->setting("timing_driven") && int(ni->users.size()) < cfg.timingFanoutThresh) + if (cfg.timing_driven && int(ni->users.size()) < cfg.timingFanoutThresh) for (size_t i = 0; i < ni->users.size(); i++) net_arc_tcost[ni->udata][i] = get_timing_cost(ni, i); } @@ -1022,7 +1021,7 @@ class SAPlacer } } - if (ctx->setting("timing_driven") && int(pn->users.size()) < cfg.timingFanoutThresh) { + if (cfg.timing_driven && int(pn->users.size()) < cfg.timingFanoutThresh) { // Output ports - all arcs change timing if (port.second.type == PORT_OUT) { int cc; @@ -1062,7 +1061,7 @@ class SAPlacer if (md.already_bounds_changed_x[bc] == MoveChangeData::NO_CHANGE) md.wirelen_delta += md.new_net_bounds[bc].hpwl() - net_bounds[bc].hpwl(); - if (ctx->setting("timing_driven")) { + if (cfg.timing_driven) { for (const auto &tc : md.changed_arcs) { double old_cost = net_arc_tcost.at(tc.first).at(tc.second); double new_cost = get_timing_cost(net_by_udata.at(tc.first), tc.second); @@ -1139,6 +1138,8 @@ Placer1Cfg::Placer1Cfg(Context *ctx) budgetBased = ctx->setting("placer1/budgetBased", false); startTemp = ctx->setting("placer1/startTemp", 1); timingFanoutThresh = std::numeric_limits::max(); + timing_driven = ctx->setting("timing_driven"); + slack_redist_iter = ctx->setting("slack_redist_iter"); } bool placer1(Context *ctx, Placer1Cfg cfg) diff --git a/common/placer1.h b/common/placer1.h index 08edb2c4..1356db3e 100644 --- a/common/placer1.h +++ b/common/placer1.h @@ -32,6 +32,8 @@ struct Placer1Cfg bool budgetBased; float startTemp; int timingFanoutThresh; + bool timing_driven; + int slack_redist_iter; }; extern bool placer1(Context *ctx, Placer1Cfg cfg); diff --git a/common/placer_heap.cc b/common/placer_heap.cc index 7b72200a..cd800085 100644 --- a/common/placer_heap.cc +++ b/common/placer_heap.cc @@ -234,7 +234,7 @@ class HeAPPlacer std::chrono::duration(run_stopt - run_startt).count()); } - if (ctx->setting("timing_driven")) + if (cfg.timing_driven) get_criticalities(ctx, &net_crit); if (legal_hpwl < best_hpwl) { @@ -1521,6 +1521,7 @@ PlacerHeapCfg::PlacerHeapCfg(Context *ctx) alpha = ctx->setting("placerHeap/alpha", 0.1); criticalityExponent = ctx->setting("placerHeap/criticalityExponent", 2); timingWeight = ctx->setting("placerHeap/timingWeight", 10); + timing_driven = ctx->setting("timing_driven"); } NEXTPNR_NAMESPACE_END diff --git a/common/placer_heap.h b/common/placer_heap.h index 9b1c52cb..a018aef8 100644 --- a/common/placer_heap.h +++ b/common/placer_heap.h @@ -38,6 +38,7 @@ struct PlacerHeapCfg float alpha; float criticalityExponent; float timingWeight; + bool timing_driven; std::unordered_set ioBufTypes; }; -- cgit v1.2.3 From e27dc41a7646fd3377d2400059c916fbcc35119c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 28 Jun 2019 13:44:01 +0200 Subject: add newline --- gui/create_img.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/create_img.sh b/gui/create_img.sh index fcce4e88..2e7b1f87 100755 --- a/gui/create_img.sh +++ b/gui/create_img.sh @@ -4,4 +4,4 @@ convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 ' convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'LPF'" resources/open.png ecp5/resources/open_lpf.png convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'ASC'" resources/save.png ice40/resources/save_asc.png convert -font helvetica -fill red -pointsize 7 -gravity center -draw "text 2,8 'CONFIG'" resources/save.png ecp5/resources/save_config.png -convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'JSON'" resources/save.png resources/save_json.png \ No newline at end of file +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'JSON'" resources/save.png resources/save_json.png -- cgit v1.2.3