aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2018-06-21 19:31:50 +0200
committerClifford Wolf <clifford@clifford.at>2018-06-21 19:31:50 +0200
commitbfae4663fcb6028e8c20f28d5ffa15fd20d8e1fa (patch)
treeb5dd0075a7a75ef9c24e0f758b80b5da5ee18b3f
parent38dc1cc5504961f666da32d7249532a23d5876ad (diff)
parentc33a039ac388bfcb5e068a04a7cb1b05ebec7d7f (diff)
downloadnextpnr-bfae4663fcb6028e8c20f28d5ffa15fd20d8e1fa.tar.gz
nextpnr-bfae4663fcb6028e8c20f28d5ffa15fd20d8e1fa.tar.bz2
nextpnr-bfae4663fcb6028e8c20f28d5ffa15fd20d8e1fa.zip
Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr
# Conflicts: # common/route.cc
-rw-r--r--common/log.cc6
-rw-r--r--common/log.h4
-rw-r--r--common/place_sa.cc12
-rw-r--r--common/route.cc335
-rw-r--r--dummy/main.cc165
-rw-r--r--frontend/json/jsonparse.cc33
-rw-r--r--frontend/json/jsonparse.h2
-rw-r--r--gui/basewindow.cc1
-rw-r--r--gui/basewindow.h2
-rw-r--r--gui/dummy/mainwindow.cc9
-rw-r--r--gui/dummy/mainwindow.h2
-rw-r--r--gui/ice40/mainwindow.cc8
-rw-r--r--gui/ice40/worker.cc46
-rw-r--r--gui/ice40/worker.h18
-rw-r--r--ice40/main.cc474
-rw-r--r--ice40/pack.cc22
-rw-r--r--ice40/pcf.cc75
-rw-r--r--ice40/pcf.h2
18 files changed, 628 insertions, 588 deletions
diff --git a/common/log.cc b/common/log.cc
index b0cd802a..495f83b1 100644
--- a/common/log.cc
+++ b/common/log.cc
@@ -150,12 +150,8 @@ void logv_error(const char *format, va_list ap)
#ifdef EMSCRIPTEN
log_files = backup_log_files;
- throw 0;
-#elif defined(_MSC_VER)
- _exit(EXIT_FAILURE);
-#else
- _Exit(EXIT_FAILURE);
#endif
+ throw log_execution_error_exception();
}
void log(const char *format, ...)
diff --git a/common/log.h b/common/log.h
index 381843b3..65b3f178 100644
--- a/common/log.h
+++ b/common/log.h
@@ -43,6 +43,10 @@ struct log_cmd_error_exception
{
};
+struct log_execution_error_exception
+{
+};
+
extern std::vector<FILE *> log_files;
extern std::vector<std::ostream *> log_streams;
extern FILE *log_errfile;
diff --git a/common/place_sa.cc b/common/place_sa.cc
index 4d0d5d08..69ba968f 100644
--- a/common/place_sa.cc
+++ b/common/place_sa.cc
@@ -478,10 +478,14 @@ class SAPlacer
bool place_design_sa(Context *ctx)
{
- SAPlacer placer(ctx);
- placer.place();
- log_info("Checksum: 0x%08x\n", ctx->checksum());
- return true;
+ try {
+ SAPlacer placer(ctx);
+ placer.place();
+ log_info("Checksum: 0x%08x\n", ctx->checksum());
+ return true;
+ } catch (log_execution_error_exception) {
+ return false;
+ }
}
NEXTPNR_NAMESPACE_END
diff --git a/common/route.cc b/common/route.cc
index 0c072c3a..e6697349 100644
--- a/common/route.cc
+++ b/common/route.cc
@@ -406,233 +406,242 @@ NEXTPNR_NAMESPACE_BEGIN
bool route_design(Context *ctx)
{
- delay_t ripup_penalty = ctx->getRipupDelayPenalty();
- RipupScoreboard scores;
-
- log_break();
- log_info("Routing..\n");
-
- std::unordered_set<IdString> netsQueue;
-
- for (auto &net_it : ctx->nets) {
- auto net_name = net_it.first;
- auto net_info = net_it.second;
-
- if (net_info->driver.cell == nullptr)
- continue;
+ try {
+ delay_t ripup_penalty = ctx->getRipupDelayPenalty();
+ RipupScoreboard scores;
- if (!net_info->wires.empty())
- continue;
-
- netsQueue.insert(net_name);
- }
-
- if (netsQueue.empty()) {
- log_info("found no unrouted nets. no routing necessary.\n");
- return true;
- }
+ log_break();
+ log_info("Routing..\n");
- log_info("found %d unrouted nets. starting routing procedure.\n",
- int(netsQueue.size()));
+ std::unordered_set<IdString> netsQueue;
- delay_t estimatedTotalDelay = 0.0;
- int estimatedTotalDelayCnt = 0;
+ for (auto &net_it : ctx->nets) {
+ auto net_name = net_it.first;
+ auto net_info = net_it.second;
- for (auto net_name : netsQueue) {
- auto net_info = ctx->nets.at(net_name);
+ if (net_info->driver.cell == nullptr)
+ continue;
- auto src_bel = net_info->driver.cell->bel;
+ if (!net_info->wires.empty())
+ continue;
- if (src_bel == BelId())
- continue;
+ netsQueue.insert(net_name);
+ }
- IdString driver_port = net_info->driver.port;
+ if (netsQueue.empty()) {
+ log_info("found no unrouted nets. no routing necessary.\n");
+ return true;
+ }
- auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
- if (driver_port_it != net_info->driver.cell->pins.end())
- driver_port = driver_port_it->second;
+ log_info("found %d unrouted nets. starting routing procedure.\n",
+ int(netsQueue.size()));
- auto src_wire =
- ctx->getWireBelPin(src_bel, ctx->portPinFromId(driver_port));
+ delay_t estimatedTotalDelay = 0.0;
+ int estimatedTotalDelayCnt = 0;
- if (src_wire == WireId())
- continue;
+ for (auto net_name : netsQueue) {
+ auto net_info = ctx->nets.at(net_name);
- for (auto &user_it : net_info->users) {
- auto dst_bel = user_it.cell->bel;
+ auto src_bel = net_info->driver.cell->bel;
- if (dst_bel == BelId())
+ if (src_bel == BelId())
continue;
- IdString user_port = user_it.port;
-
- auto user_port_it = user_it.cell->pins.find(user_port);
+ IdString driver_port = net_info->driver.port;
- if (user_port_it != user_it.cell->pins.end())
- user_port = user_port_it->second;
+ auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
+ if (driver_port_it != net_info->driver.cell->pins.end())
+ driver_port = driver_port_it->second;
- auto dst_wire =
- ctx->getWireBelPin(dst_bel, ctx->portPinFromId(user_port));
+ auto src_wire = ctx->getWireBelPin(src_bel,
+ ctx->portPinFromId(driver_port));
- if (dst_wire == WireId())
+ if (src_wire == WireId())
continue;
- estimatedTotalDelay += ctx->estimateDelay(src_wire, dst_wire);
- estimatedTotalDelayCnt++;
- }
- }
+ for (auto &user_it : net_info->users) {
+ auto dst_bel = user_it.cell->bel;
- log_info("estimated total wire delay: %.2f (avg %.2f)\n",
- float(estimatedTotalDelay),
- float(estimatedTotalDelay) / estimatedTotalDelayCnt);
+ if (dst_bel == BelId())
+ continue;
- int iterCnt = 0;
+ IdString user_port = user_it.port;
- while (!netsQueue.empty()) {
- if (iterCnt == 200) {
- log_warning("giving up after %d iterations.\n", iterCnt);
- log_info("Checksum: 0x%08x\n", ctx->checksum());
- return false;
- }
-
- iterCnt++;
- if (ctx->verbose)
- log_info("-- %d --\n", iterCnt);
-
- int visitCnt = 0, revisitCnt = 0, overtimeRevisitCnt = 0, netCnt = 0;
+ auto user_port_it = user_it.cell->pins.find(user_port);
- std::unordered_set<IdString> ripupQueue;
+ if (user_port_it != user_it.cell->pins.end())
+ user_port = user_port_it->second;
- if (ctx->verbose || iterCnt == 1)
- log_info("routing queue contains %d nets.\n",
- int(netsQueue.size()));
+ auto dst_wire = ctx->getWireBelPin(
+ dst_bel, ctx->portPinFromId(user_port));
- bool printNets = ctx->verbose && (netsQueue.size() < 10);
+ if (dst_wire == WireId())
+ continue;
- std::vector<IdString> netsArray(netsQueue.begin(), netsQueue.end());
- ctx->sorted_shuffle(netsArray);
- netsQueue.clear();
-
- for (auto net_name : netsArray) {
- if (printNets)
- log_info(" routing net %s. (%d users)\n", net_name.c_str(ctx),
- int(ctx->nets.at(net_name)->users.size()));
+ estimatedTotalDelay += ctx->estimateDelay(src_wire, dst_wire);
+ estimatedTotalDelayCnt++;
+ }
+ }
- Router router(ctx, scores, net_name, false);
+ log_info("estimated total wire delay: %.2f (avg %.2f)\n",
+ float(estimatedTotalDelay),
+ float(estimatedTotalDelay) / estimatedTotalDelayCnt);
- netCnt++;
- visitCnt += router.visitCnt;
- revisitCnt += router.revisitCnt;
- overtimeRevisitCnt += router.overtimeRevisitCnt;
+ int iterCnt = 0;
- if (!router.routedOkay) {
- if (printNets)
- log_info(" failed to route to %s.\n",
- ctx->getWireName(router.failedDest).c_str(ctx));
- ripupQueue.insert(net_name);
+ while (!netsQueue.empty()) {
+ if (iterCnt == 200) {
+ log_warning("giving up after %d iterations.\n", iterCnt);
+ log_info("Checksum: 0x%08x\n", ctx->checksum());
+ return false;
}
- if ((ctx->verbose || iterCnt == 1) && !printNets &&
- (netCnt % 100 == 0))
- log_info(" processed %d nets. (%d routed, %d failed)\n",
- netCnt, netCnt - int(ripupQueue.size()),
- int(ripupQueue.size()));
- }
-
- int normalRouteCnt = netCnt - int(ripupQueue.size());
+ iterCnt++;
+ if (ctx->verbose)
+ log_info("-- %d --\n", iterCnt);
- if ((ctx->verbose || iterCnt == 1) && (netCnt % 100 != 0))
- log_info(" processed %d nets. (%d routed, %d failed)\n", netCnt,
- normalRouteCnt, int(ripupQueue.size()));
+ int visitCnt = 0, revisitCnt = 0, overtimeRevisitCnt = 0, netCnt = 0;
- if (ctx->verbose)
- log_info(" visited %d PIPs (%.2f%% revisits, %.2f%% overtime revisits).\n",
- visitCnt, (100.0 * revisitCnt) / visitCnt, (100.0 * overtimeRevisitCnt) / visitCnt);
+ std::unordered_set<IdString> ripupQueue;
- if (!ripupQueue.empty()) {
if (ctx->verbose || iterCnt == 1)
- log_info("failed to route %d nets. re-routing in ripup mode.\n",
- int(ripupQueue.size()));
-
- printNets = ctx->verbose && (ripupQueue.size() < 10);
+ log_info("routing queue contains %d nets.\n",
+ int(netsQueue.size()));
- visitCnt = 0;
- revisitCnt = 0;
- overtimeRevisitCnt = 0;
- netCnt = 0;
- int ripCnt = 0;
+ bool printNets = ctx->verbose && (netsQueue.size() < 10);
- std::vector<IdString> ripupArray(ripupQueue.begin(),
- ripupQueue.end());
- ctx->sorted_shuffle(ripupArray);
+ std::vector<IdString> netsArray(netsQueue.begin(), netsQueue.end());
+ ctx->sorted_shuffle(netsArray);
+ netsQueue.clear();
- for (auto net_name : ripupArray) {
+ for (auto net_name : netsArray) {
if (printNets)
log_info(" routing net %s. (%d users)\n",
net_name.c_str(ctx),
int(ctx->nets.at(net_name)->users.size()));
- Router router(ctx, scores, net_name, true, ripup_penalty);
+ Router router(ctx, scores, net_name, false);
netCnt++;
visitCnt += router.visitCnt;
revisitCnt += router.revisitCnt;
overtimeRevisitCnt += router.overtimeRevisitCnt;
- if (!router.routedOkay)
- log_error("Net %s is impossible to route.\n",
- net_name.c_str(ctx));
-
- for (auto it : router.rippedNets)
- netsQueue.insert(it);
-
- if (printNets) {
- if (router.rippedNets.size() < 10) {
- log_info(" ripped up %d other nets:\n",
- int(router.rippedNets.size()));
- for (auto n : router.rippedNets)
- log_info(" %s (%d users)\n", n.c_str(ctx),
- int(ctx->nets.at(n)->users.size()));
- } else {
- log_info(" ripped up %d other nets.\n",
- int(router.rippedNets.size()));
- }
+ if (!router.routedOkay) {
+ if (printNets)
+ log_info(
+ " failed to route to %s.\n",
+ ctx->getWireName(router.failedDest).c_str(ctx));
+ ripupQueue.insert(net_name);
}
- ripCnt += router.rippedNets.size();
-
if ((ctx->verbose || iterCnt == 1) && !printNets &&
(netCnt % 100 == 0))
- log_info(" routed %d nets, ripped %d nets.\n", netCnt,
- ripCnt);
+ log_info(" processed %d nets. (%d routed, %d failed)\n",
+ netCnt, netCnt - int(ripupQueue.size()),
+ int(ripupQueue.size()));
}
+ int normalRouteCnt = netCnt - int(ripupQueue.size());
+
if ((ctx->verbose || iterCnt == 1) && (netCnt % 100 != 0))
- log_info(" routed %d nets, ripped %d nets.\n", netCnt, ripCnt);
+ log_info(" processed %d nets. (%d routed, %d failed)\n",
+ netCnt, normalRouteCnt, int(ripupQueue.size()));
if (ctx->verbose)
log_info(" visited %d PIPs (%.2f%% revisits, %.2f%% overtime revisits).\n",
visitCnt, (100.0 * revisitCnt) / visitCnt, (100.0 * overtimeRevisitCnt) / visitCnt);
- if (ctx->verbose && !netsQueue.empty())
- log_info(" ripped up %d previously routed nets. continue "
- "routing.\n",
- int(netsQueue.size()));
- }
+ if (!ripupQueue.empty()) {
+ if (ctx->verbose || iterCnt == 1)
+ log_info("failed to route %d nets. re-routing in ripup "
+ "mode.\n",
+ int(ripupQueue.size()));
+
+ printNets = ctx->verbose && (ripupQueue.size() < 10);
+
+ visitCnt = 0;
+ revisitCnt = 0;
+ overtimeRevisitCnt = 0;
+ netCnt = 0;
+ int ripCnt = 0;
+
+ std::vector<IdString> ripupArray(ripupQueue.begin(),
+ ripupQueue.end());
+ ctx->sorted_shuffle(ripupArray);
+
+ for (auto net_name : ripupArray) {
+ if (printNets)
+ log_info(" routing net %s. (%d users)\n",
+ net_name.c_str(ctx),
+ int(ctx->nets.at(net_name)->users.size()));
+
+ Router router(ctx, scores, net_name, true, ripup_penalty);
+
+ netCnt++;
+ visitCnt += router.visitCnt;
+ revisitCnt += router.revisitCnt;
+ overtimeRevisitCnt += router.overtimeRevisitCnt;
+
+ if (!router.routedOkay)
+ log_error("Net %s is impossible to route.\n",
+ net_name.c_str(ctx));
+
+ for (auto it : router.rippedNets)
+ netsQueue.insert(it);
+
+ if (printNets) {
+ if (router.rippedNets.size() < 10) {
+ log_info(" ripped up %d other nets:\n",
+ int(router.rippedNets.size()));
+ for (auto n : router.rippedNets)
+ log_info(" %s (%d users)\n", n.c_str(ctx),
+ int(ctx->nets.at(n)->users.size()));
+ } else {
+ log_info(" ripped up %d other nets.\n",
+ int(router.rippedNets.size()));
+ }
+ }
- if (!ctx->verbose)
- log_info("iteration %d: routed %d nets without ripup, routed %d "
- "nets with ripup.\n",
- iterCnt, normalRouteCnt, int(ripupQueue.size()));
+ ripCnt += router.rippedNets.size();
- if (iterCnt == 8 || iterCnt == 16 || iterCnt == 32 || iterCnt == 64 ||
- iterCnt == 128)
- ripup_penalty += ctx->getRipupDelayPenalty();
- }
+ if ((ctx->verbose || iterCnt == 1) && !printNets &&
+ (netCnt % 100 == 0))
+ log_info(" routed %d nets, ripped %d nets.\n", netCnt,
+ ripCnt);
+ }
+
+ if ((ctx->verbose || iterCnt == 1) && (netCnt % 100 != 0))
+ log_info(" routed %d nets, ripped %d nets.\n", netCnt,
+ ripCnt);
- log_info("routing complete after %d iterations.\n", iterCnt);
- log_info("Checksum: 0x%08x\n", ctx->checksum());
- return true;
+ if (ctx->verbose)
+ log_info(" visited %d PIPs (%.2f%% revisits, %.2f%% overtime revisits).\n",
+ visitCnt, (100.0 * revisitCnt) / visitCnt, (100.0 * overtimeRevisitCnt) / visitCnt);
+
+ if (ctx->verbose && !netsQueue.empty())
+ log_info(" ripped up %d previously routed nets. continue "
+ "routing.\n",
+ int(netsQueue.size()));
+ }
+
+ if (!ctx->verbose)
+ log_info(
+ "iteration %d: routed %d nets without ripup, routed %d "
+ "nets with ripup.\n",
+ iterCnt, normalRouteCnt, int(ripupQueue.size()));
+
+ if (iterCnt == 8 || iterCnt == 16 || iterCnt == 32 ||
+ iterCnt == 64 || iterCnt == 128)
+ ripup_penalty += ctx->getRipupDelayPenalty();
+ }
+
+ log_info("routing complete after %d iterations.\n", iterCnt);
+ log_info("Checksum: 0x%08x\n", ctx->checksum());
+ return true;
+ } catch (log_execution_error_exception) {
+ return false;
+ }
}
bool get_actual_route_delay(Context *ctx, WireId src_wire, WireId dst_wire,
diff --git a/dummy/main.cc b/dummy/main.cc
index cef70235..110c5b6c 100644
--- a/dummy/main.cc
+++ b/dummy/main.cc
@@ -32,87 +32,96 @@ USING_NEXTPNR_NAMESPACE
int main(int argc, char *argv[])
{
- namespace po = boost::program_options;
- int rc = 0;
-
- log_files.push_back(stdout);
-
- po::options_description options("Allowed options");
- options.add_options()("help,h", "show help");
- options.add_options()("verbose,v", "verbose output");
- options.add_options()("force,f", "keep running after errors");
- options.add_options()("gui", "start gui");
- options.add_options()("run", po::value<std::vector<std::string>>(),
- "python file to execute");
- options.add_options()("version,V", "show version");
- po::positional_options_description pos;
- pos.add("run", -1);
-
- po::variables_map vm;
try {
- po::parsed_options parsed = po::command_line_parser(argc, argv)
- .options(options)
- .positional(pos)
- .run();
- po::store(parsed, vm);
-
- po::notify(vm);
- }
-
- catch (std::exception &e) {
- std::cout << e.what() << "\n";
- return 1;
- }
-
- if (vm.count("help") || argc == 1) {
- std::cout << boost::filesystem::basename(argv[0])
- << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
- std::cout << "\n";
- std::cout << options << "\n";
- return argc != 1;
- }
-
- if (vm.count("version")) {
- std::cout << boost::filesystem::basename(argv[0])
- << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
- return 1;
- }
-
- Context ctx(ArchArgs{});
- init_python(argv[0]);
- python_export_global("ctx", ctx);
-
- if (vm.count("verbose")) {
- ctx.verbose = true;
- }
-
- if (vm.count("force")) {
- ctx.force = true;
- }
-
- if (vm.count("seed")) {
- ctx.rngseed(vm["seed"].as<int>());
- }
-
- if (vm.count("run")) {
- std::vector<std::string> files =
- vm["run"].as<std::vector<std::string>>();
- for (auto filename : files)
- execute_python_file(filename.c_str());
- }
-
- if (vm.count("gui")) {
- QApplication a(argc, argv);
- MainWindow w(&ctx);
- w.show();
-
- rc = a.exec();
+ namespace po = boost::program_options;
+ int rc = 0;
+
+ log_files.push_back(stdout);
+
+ po::options_description options("Allowed options");
+ options.add_options()("help,h", "show help");
+ options.add_options()("verbose,v", "verbose output");
+ options.add_options()("force,f", "keep running after errors");
+ options.add_options()("gui", "start gui");
+ options.add_options()("run", po::value<std::vector<std::string>>(),
+ "python file to execute");
+ options.add_options()("version,V", "show version");
+ po::positional_options_description pos;
+ pos.add("run", -1);
+
+ po::variables_map vm;
+ try {
+ po::parsed_options parsed = po::command_line_parser(argc, argv)
+ .options(options)
+ .positional(pos)
+ .run();
+
+ po::store(parsed, vm);
+
+ po::notify(vm);
+ }
+
+ catch (std::exception &e) {
+ std::cout << e.what() << "\n";
+ return 1;
+ }
+
+ if (vm.count("help") || argc == 1) {
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ std::cout << "\n";
+ std::cout << options << "\n";
+ return argc != 1;
+ }
+
+ if (vm.count("version")) {
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ return 1;
+ }
+
+ Context ctx(ArchArgs{});
+ init_python(argv[0]);
+ python_export_global("ctx", ctx);
+
+ if (vm.count("verbose")) {
+ ctx.verbose = true;
+ }
+
+ if (vm.count("force")) {
+ ctx.force = true;
+ }
+
+ if (vm.count("seed")) {
+ ctx.rngseed(vm["seed"].as<int>());
+ }
+
+ if (vm.count("run")) {
+ std::vector<std::string> files =
+ vm["run"].as<std::vector<std::string>>();
+ for (auto filename : files)
+ execute_python_file(filename.c_str());
+ }
+
+ if (vm.count("gui")) {
+ QApplication a(argc, argv);
+ MainWindow w(&ctx);
+ w.show();
+
+ rc = a.exec();
+ }
+ deinit_python();
+ return rc;
+ } catch (log_execution_error_exception) {
+#if defined(_MSC_VER)
+ _exit(EXIT_FAILURE);
+#else
+ _Exit(EXIT_FAILURE);
+#endif
}
- deinit_python();
- return rc;
}
#endif
diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc
index 7d9e9dcf..a832e9e5 100644
--- a/frontend/json/jsonparse.cc
+++ b/frontend/json/jsonparse.cc
@@ -797,27 +797,32 @@ void json_import(Context *ctx, string modname, JsonNode *node)
}
}; // End Namespace JsonParser
-void parse_json_file(std::istream &f, std::string &filename, Context *ctx)
+bool parse_json_file(std::istream &f, std::string &filename, Context *ctx)
{
- using namespace JsonParser;
+ try {
+ using namespace JsonParser;
- JsonNode root(f);
+ JsonNode root(f);
- if (root.type != 'D')
- log_error("JSON root node is not a dictionary.\n");
+ 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 (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");
+ if (modules->type != 'D')
+ log_error("JSON modules node is not a dictionary.\n");
- for (auto &it : modules->data_dict)
- json_import(ctx, it.first, it.second);
- }
+ for (auto &it : modules->data_dict)
+ json_import(ctx, it.first, it.second);
+ }
- log_info("Checksum: 0x%08x\n", ctx->checksum());
- log_break();
+ log_info("Checksum: 0x%08x\n", ctx->checksum());
+ log_break();
+ return true;
+ } catch (log_execution_error_exception) {
+ return false;
+ }
}
NEXTPNR_NAMESPACE_END
diff --git a/frontend/json/jsonparse.h b/frontend/json/jsonparse.h
index 351b6558..fe71444f 100644
--- a/frontend/json/jsonparse.h
+++ b/frontend/json/jsonparse.h
@@ -26,7 +26,7 @@
NEXTPNR_NAMESPACE_BEGIN
-extern void parse_json_file(std::istream &, std::string &, Context *);
+extern bool parse_json_file(std::istream &, std::string &, Context *);
NEXTPNR_NAMESPACE_END
diff --git a/gui/basewindow.cc b/gui/basewindow.cc
index 1e6b171f..9020a719 100644
--- a/gui/basewindow.cc
+++ b/gui/basewindow.cc
@@ -10,7 +10,6 @@
#include "mainwindow.h"
#include "pythontab.h"
-
BaseMainWindow::BaseMainWindow(Context *_ctx, QWidget *parent)
: QMainWindow(parent), ctx(_ctx)
{
diff --git a/gui/basewindow.h b/gui/basewindow.h
index d6915ae9..b20d4621 100644
--- a/gui/basewindow.h
+++ b/gui/basewindow.h
@@ -30,7 +30,7 @@ class BaseMainWindow : public QMainWindow
protected Q_SLOTS:
void writeInfo(std::string text);
-
+
virtual void open() = 0;
virtual bool save() = 0;
diff --git a/gui/dummy/mainwindow.cc b/gui/dummy/mainwindow.cc
index f714e30e..7982c5f5 100644
--- a/gui/dummy/mainwindow.cc
+++ b/gui/dummy/mainwindow.cc
@@ -17,11 +17,6 @@ void MainWindow::createMenu()
menuBar->addAction(menu_Custom->menuAction());
}
-void MainWindow::open()
-{
-}
+void MainWindow::open() {}
-bool MainWindow::save()
-{
- return false;
-} \ No newline at end of file
+bool MainWindow::save() { return false; } \ No newline at end of file
diff --git a/gui/dummy/mainwindow.h b/gui/dummy/mainwindow.h
index ea4480fb..c9690f2c 100644
--- a/gui/dummy/mainwindow.h
+++ b/gui/dummy/mainwindow.h
@@ -19,7 +19,7 @@ class MainWindow : public BaseMainWindow
protected Q_SLOTS:
virtual void open();
- virtual bool save();
+ virtual bool save();
};
#endif // MAINWINDOW_H
diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc
index dafd92e9..934798bb 100644
--- a/gui/ice40/mainwindow.cc
+++ b/gui/ice40/mainwindow.cc
@@ -20,8 +20,7 @@ MainWindow::MainWindow(Context *_ctx, QWidget *parent)
createMenu();
task = new TaskManager(_ctx);
- connect(task, SIGNAL(log(std::string)), this,
- SLOT(writeInfo(std::string)));
+ connect(task, SIGNAL(log(std::string)), this, SLOT(writeInfo(std::string)));
}
MainWindow::~MainWindow() {}
@@ -43,7 +42,4 @@ void MainWindow::open()
task->parsejson(fn);
}
}
-bool MainWindow::save()
-{
- return false;
-} \ No newline at end of file
+bool MainWindow::save() { return false; } \ No newline at end of file
diff --git a/gui/ice40/worker.cc b/gui/ice40/worker.cc
index bd22f552..5702137b 100644
--- a/gui/ice40/worker.cc
+++ b/gui/ice40/worker.cc
@@ -1,13 +1,13 @@
#include "worker.h"
#include <fstream>
+#include "bitstream.h"
+#include "design_utils.h"
#include "jsonparse.h"
#include "log.h"
#include "pack.h"
#include "pcf.h"
#include "place_sa.h"
#include "route.h"
-#include "bitstream.h"
-#include "design_utils.h"
#include "timing.h"
Worker::Worker(Context *_ctx) : ctx(_ctx)
@@ -15,28 +15,29 @@ Worker::Worker(Context *_ctx) : ctx(_ctx)
log_write_function = [this](std::string text) { Q_EMIT log(text); };
}
-void Worker::parsejson(const std::string &filename)
+void Worker::parsejson(const std::string &filename)
{
std::string fn = filename;
std::ifstream f(fn);
-
- parse_json_file(f, fn, ctx);
- if (!pack_design(ctx))
- log_error("Packing design failed.\n");
- double freq = 50e6;
- assign_budget(ctx, freq);
- print_utilisation(ctx);
-
- if (!place_design_sa(ctx))
- log_error("Placing design failed.\n");
- if (!route_design(ctx))
- log_error("Routing design failed.\n");
- print_utilisation(ctx);
- Q_EMIT log("done");
+ try {
+ if (!parse_json_file(f, fn, ctx))
+ log_error("Loading design failed.\n");
+ if (!pack_design(ctx))
+ log_error("Packing design failed.\n");
+ double freq = 50e6;
+ assign_budget(ctx, freq);
+ print_utilisation(ctx);
+
+ if (!place_design_sa(ctx))
+ log_error("Placing design failed.\n");
+ if (!route_design(ctx))
+ log_error("Routing design failed.\n");
+ Q_EMIT log("done");
+ } catch (log_execution_error_exception) {
+ }
}
-
-TaskManager::TaskManager(Context *ctx)
+TaskManager::TaskManager(Context *ctx)
{
Worker *worker = new Worker(ctx);
worker->moveToThread(&workerThread);
@@ -46,13 +47,10 @@ TaskManager::TaskManager(Context *ctx)
workerThread.start();
}
-TaskManager::~TaskManager()
+TaskManager::~TaskManager()
{
workerThread.quit();
workerThread.wait();
}
-void TaskManager::info(const std::string &result)
-{
- Q_EMIT log(result);
-} \ No newline at end of file
+void TaskManager::info(const std::string &result) { Q_EMIT log(result); } \ No newline at end of file
diff --git a/gui/ice40/worker.h b/gui/ice40/worker.h
index 5dc25d89..12d740dd 100644
--- a/gui/ice40/worker.h
+++ b/gui/ice40/worker.h
@@ -1,8 +1,8 @@
#ifndef WORKER_H
#define WORKER_H
-#include "nextpnr.h"
#include <QThread>
+#include "nextpnr.h"
// FIXME
USING_NEXTPNR_NAMESPACE
@@ -10,13 +10,14 @@ USING_NEXTPNR_NAMESPACE
class Worker : public QObject
{
Q_OBJECT
-public:
+ public:
Worker(Context *ctx);
-public Q_SLOTS:
+ public Q_SLOTS:
void parsejson(const std::string &filename);
-Q_SIGNALS:
+ Q_SIGNALS:
void log(const std::string &text);
-private:
+
+ private:
Context *ctx;
};
@@ -24,12 +25,13 @@ class TaskManager : public QObject
{
Q_OBJECT
QThread workerThread;
-public:
+
+ public:
TaskManager(Context *ctx);
~TaskManager();
-public Q_SLOTS:
+ public Q_SLOTS:
void info(const std::string &text);
-Q_SIGNALS:
+ Q_SIGNALS:
void parsejson(const std::string &);
void log(const std::string &text);
};
diff --git a/ice40/main.cc b/ice40/main.cc
index 76c059b8..067637e8 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -60,276 +60,288 @@ void svg_dump_el(const GraphicElement &el)
int main(int argc, char *argv[])
{
- namespace po = boost::program_options;
- int rc = 0;
- std::string str;
-
- log_files.push_back(stdout);
-
- po::options_description options("Allowed options");
- options.add_options()("help,h", "show help");
- options.add_options()("verbose,v", "verbose output");
- options.add_options()("debug", "debug output");
- options.add_options()("force,f", "keep running after errors");
- options.add_options()("gui", "start gui");
- options.add_options()("svg", "dump SVG file");
- options.add_options()("pack-only",
- "pack design only without placement or routing");
-
- options.add_options()("run", po::value<std::vector<std::string>>(),
- "python file to execute");
- options.add_options()("json", po::value<std::string>(),
- "JSON design file to ingest");
- options.add_options()("pcf", po::value<std::string>(),
- "PCF constraints file to ingest");
- options.add_options()("asc", po::value<std::string>(),
- "asc bitstream file to write");
- options.add_options()("seed", po::value<int>(),
- "seed value for random number generator");
- options.add_options()("version,V", "show version");
- options.add_options()("tmfuzz", "run path delay estimate fuzzer");
- options.add_options()("lp384", "set device type to iCE40LP384");
- options.add_options()("lp1k", "set device type to iCE40LP1K");
- options.add_options()("lp8k", "set device type to iCE40LP8K");
- options.add_options()("hx1k", "set device type to iCE40HX1K");
- options.add_options()("hx8k", "set device type to iCE40HX8K");
- options.add_options()("up5k", "set device type to iCE40UP5K");
- options.add_options()("freq", po::value<double>(),
- "set target frequency for design in MHz");
- options.add_options()("package", po::value<std::string>(),
- "set device package");
- po::positional_options_description pos;
- pos.add("run", -1);
-
- po::variables_map vm;
try {
- po::parsed_options parsed = po::command_line_parser(argc, argv)
- .options(options)
- .positional(pos)
- .run();
-
- po::store(parsed, vm);
-
- po::notify(vm);
- }
+ namespace po = boost::program_options;
+ int rc = 0;
+ std::string str;
+
+ log_files.push_back(stdout);
+
+ po::options_description options("Allowed options");
+ options.add_options()("help,h", "show help");
+ options.add_options()("verbose,v", "verbose output");
+ options.add_options()("debug", "debug output");
+ options.add_options()("force,f", "keep running after errors");
+ options.add_options()("gui", "start gui");
+ options.add_options()("svg", "dump SVG file");
+ options.add_options()("pack-only",
+ "pack design only without placement or routing");
+
+ options.add_options()("run", po::value<std::vector<std::string>>(),
+ "python file to execute");
+ options.add_options()("json", po::value<std::string>(),
+ "JSON design file to ingest");
+ options.add_options()("pcf", po::value<std::string>(),
+ "PCF constraints file to ingest");
+ options.add_options()("asc", po::value<std::string>(),
+ "asc bitstream file to write");
+ options.add_options()("seed", po::value<int>(),
+ "seed value for random number generator");
+ options.add_options()("version,V", "show version");
+ options.add_options()("tmfuzz", "run path delay estimate fuzzer");
+ options.add_options()("lp384", "set device type to iCE40LP384");
+ options.add_options()("lp1k", "set device type to iCE40LP1K");
+ options.add_options()("lp8k", "set device type to iCE40LP8K");
+ options.add_options()("hx1k", "set device type to iCE40HX1K");
+ options.add_options()("hx8k", "set device type to iCE40HX8K");
+ options.add_options()("up5k", "set device type to iCE40UP5K");
+ options.add_options()("freq", po::value<double>(),
+ "set target frequency for design in MHz");
+ options.add_options()("package", po::value<std::string>(),
+ "set device package");
+ po::positional_options_description pos;
+ pos.add("run", -1);
+
+ po::variables_map vm;
+ try {
+ po::parsed_options parsed = po::command_line_parser(argc, argv)
+ .options(options)
+ .positional(pos)
+ .run();
+
+ po::store(parsed, vm);
+
+ po::notify(vm);
+ }
- catch (std::exception &e) {
- std::cout << e.what() << "\n";
- return 1;
- }
+ catch (std::exception &e) {
+ std::cout << e.what() << "\n";
+ return 1;
+ }
- if (vm.count("help") || argc == 1) {
- help:
- std::cout << boost::filesystem::basename(argv[0])
- << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
- std::cout << "\n";
- std::cout << options << "\n";
- return argc != 1;
- }
+ if (vm.count("help") || argc == 1) {
+ help:
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ std::cout << "\n";
+ std::cout << options << "\n";
+ return argc != 1;
+ }
- if (vm.count("version")) {
- std::cout << boost::filesystem::basename(argv[0])
- << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
- return 1;
- }
+ if (vm.count("version")) {
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ return 1;
+ }
- ArchArgs chipArgs;
+ ArchArgs chipArgs;
- if (vm.count("lp384")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::LP384;
- chipArgs.package = "qn32";
- }
+ if (vm.count("lp384")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::LP384;
+ chipArgs.package = "qn32";
+ }
- if (vm.count("lp1k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::LP1K;
- chipArgs.package = "tq144";
- }
+ if (vm.count("lp1k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::LP1K;
+ chipArgs.package = "tq144";
+ }
- if (vm.count("lp8k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::LP8K;
- chipArgs.package = "ct256";
- }
+ if (vm.count("lp8k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::LP8K;
+ chipArgs.package = "ct256";
+ }
- if (vm.count("hx1k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::HX1K;
- chipArgs.package = "tq144";
- }
+ if (vm.count("hx1k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::HX1K;
+ chipArgs.package = "tq144";
+ }
- if (vm.count("hx8k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::HX8K;
- chipArgs.package = "ct256";
- }
+ if (vm.count("hx8k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::HX8K;
+ chipArgs.package = "ct256";
+ }
- if (vm.count("up5k")) {
- if (chipArgs.type != ArchArgs::NONE)
- goto help;
- chipArgs.type = ArchArgs::UP5K;
- chipArgs.package = "sg48";
- }
+ if (vm.count("up5k")) {
+ if (chipArgs.type != ArchArgs::NONE)
+ goto help;
+ chipArgs.type = ArchArgs::UP5K;
+ chipArgs.package = "sg48";
+ }
- if (chipArgs.type == ArchArgs::NONE) {
- chipArgs.type = ArchArgs::HX1K;
- chipArgs.package = "tq144";
- }
+ if (chipArgs.type == ArchArgs::NONE) {
+ chipArgs.type = ArchArgs::HX1K;
+ chipArgs.package = "tq144";
+ }
#ifdef ICE40_HX1K_ONLY
- if (chipArgs.type != ArchArgs::HX1K) {
- std::cout << "This version of nextpnr-ice40 is built with HX1K-support "
- "only.\n";
- return 1;
- }
+ if (chipArgs.type != ArchArgs::HX1K) {
+ std::cout << "This version of nextpnr-ice40 is built with "
+ "HX1K-support "
+ "only.\n";
+ return 1;
+ }
#endif
- if (vm.count("package"))
- chipArgs.package = vm["package"].as<std::string>();
+ if (vm.count("package"))
+ chipArgs.package = vm["package"].as<std::string>();
- Context ctx(chipArgs);
- init_python(argv[0]);
- python_export_global("ctx", ctx);
+ Context ctx(chipArgs);
+ init_python(argv[0]);
+ python_export_global("ctx", ctx);
- if (vm.count("verbose")) {
- ctx.verbose = true;
- }
-
- if (vm.count("debug")) {
- ctx.verbose = true;
- ctx.debug = true;
- }
-
- if (vm.count("force")) {
- ctx.force = true;
- }
+ if (vm.count("verbose")) {
+ ctx.verbose = true;
+ }
- if (vm.count("seed")) {
- ctx.rngseed(vm["seed"].as<int>());
- }
+ if (vm.count("debug")) {
+ ctx.verbose = true;
+ ctx.debug = true;
+ }
- if (vm.count("svg")) {
- std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
- "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
- for (auto bel : ctx.getBels()) {
- std::cout << "<!-- " << ctx.getBelName(bel).str(&ctx) << " -->\n";
- for (auto &el : ctx.getBelGraphics(bel))
- svg_dump_el(el);
+ if (vm.count("force")) {
+ ctx.force = true;
}
- std::cout << "<!-- Frame -->\n";
- for (auto &el : ctx.getFrameGraphics())
- svg_dump_el(el);
- std::cout << "</svg>\n";
- }
- if (vm.count("tmfuzz")) {
- std::vector<WireId> src_wires, dst_wires;
+ if (vm.count("seed")) {
+ ctx.rngseed(vm["seed"].as<int>());
+ }
- /*for (auto w : ctx.getWires())
- src_wires.push_back(w);*/
- for (auto b : ctx.getBels()) {
- if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
- src_wires.push_back(ctx.getWireBelPin(b, PIN_O));
- }
- if (ctx.getBelType(b) == TYPE_SB_IO) {
- src_wires.push_back(ctx.getWireBelPin(b, PIN_D_IN_0));
+ if (vm.count("svg")) {
+ std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
+ "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
+ for (auto bel : ctx.getBels()) {
+ std::cout << "<!-- " << ctx.getBelName(bel).str(&ctx)
+ << " -->\n";
+ for (auto &el : ctx.getBelGraphics(bel))
+ svg_dump_el(el);
}
+ std::cout << "<!-- Frame -->\n";
+ for (auto &el : ctx.getFrameGraphics())
+ svg_dump_el(el);
+ std::cout << "</svg>\n";
}
- for (auto b : ctx.getBels()) {
- if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I0));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I1));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I2));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_I3));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_CEN));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_CIN));
+ if (vm.count("tmfuzz")) {
+ std::vector<WireId> src_wires, dst_wires;
+
+ /*for (auto w : ctx.getWires())
+ src_wires.push_back(w);*/
+ for (auto b : ctx.getBels()) {
+ if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
+ src_wires.push_back(ctx.getWireBelPin(b, PIN_O));
+ }
+ if (ctx.getBelType(b) == TYPE_SB_IO) {
+ src_wires.push_back(ctx.getWireBelPin(b, PIN_D_IN_0));
+ }
}
- if (ctx.getBelType(b) == TYPE_SB_IO) {
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_D_OUT_0));
- dst_wires.push_back(ctx.getWireBelPin(b, PIN_OUTPUT_ENABLE));
+
+ for (auto b : ctx.getBels()) {
+ if (ctx.getBelType(b) == TYPE_ICESTORM_LC) {
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I0));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I1));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I2));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_I3));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_CEN));
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_CIN));
+ }
+ if (ctx.getBelType(b) == TYPE_SB_IO) {
+ dst_wires.push_back(ctx.getWireBelPin(b, PIN_D_OUT_0));
+ dst_wires.push_back(
+ ctx.getWireBelPin(b, PIN_OUTPUT_ENABLE));
+ }
}
- }
- ctx.shuffle(src_wires);
- ctx.shuffle(dst_wires);
-
- for (int i = 0; i < int(src_wires.size()) && i < int(dst_wires.size());
- i++) {
- delay_t actual_delay;
- WireId src = src_wires[i], dst = dst_wires[i];
- if (!get_actual_route_delay(&ctx, src, dst, actual_delay))
- continue;
- printf("%s %s %.3f %.3f %d %d %d %d %d %d\n",
- ctx.getWireName(src).c_str(&ctx),
- ctx.getWireName(dst).c_str(&ctx),
- ctx.getDelayNS(actual_delay),
- ctx.getDelayNS(ctx.estimateDelay(src, dst)),
- ctx.chip_info->wire_data[src.index].x,
- ctx.chip_info->wire_data[src.index].y,
- ctx.chip_info->wire_data[src.index].type,
- ctx.chip_info->wire_data[dst.index].x,
- ctx.chip_info->wire_data[dst.index].y,
- ctx.chip_info->wire_data[dst.index].type);
+ ctx.shuffle(src_wires);
+ ctx.shuffle(dst_wires);
+
+ for (int i = 0;
+ i < int(src_wires.size()) && i < int(dst_wires.size()); i++) {
+ delay_t actual_delay;
+ WireId src = src_wires[i], dst = dst_wires[i];
+ if (!get_actual_route_delay(&ctx, src, dst, actual_delay))
+ continue;
+ printf("%s %s %.3f %.3f %d %d %d %d %d %d\n",
+ ctx.getWireName(src).c_str(&ctx),
+ ctx.getWireName(dst).c_str(&ctx),
+ ctx.getDelayNS(actual_delay),
+ ctx.getDelayNS(ctx.estimateDelay(src, dst)),
+ ctx.chip_info->wire_data[src.index].x,
+ ctx.chip_info->wire_data[src.index].y,
+ ctx.chip_info->wire_data[src.index].type,
+ ctx.chip_info->wire_data[dst.index].x,
+ ctx.chip_info->wire_data[dst.index].y,
+ ctx.chip_info->wire_data[dst.index].type);
+ }
}
- }
- if (vm.count("json")) {
- std::string filename = vm["json"].as<std::string>();
- std::ifstream f(filename);
+ if (vm.count("json")) {
+ std::string filename = vm["json"].as<std::string>();
+ std::ifstream f(filename);
+ if (!parse_json_file(f, filename, &ctx))
+ log_error("Loading design failed.\n");
- parse_json_file(f, filename, &ctx);
+ if (vm.count("pcf")) {
+ std::ifstream pcf(vm["pcf"].as<std::string>());
+ if (!apply_pcf(&ctx, pcf))
+ log_error("Loading PCF failed.\n");
+ }
- if (vm.count("pcf")) {
- std::ifstream pcf(vm["pcf"].as<std::string>());
- apply_pcf(&ctx, pcf);
+ if (!pack_design(&ctx) && !ctx.force)
+ log_error("Packing design failed.\n");
+ double freq = 50e6;
+ if (vm.count("freq"))
+ freq = vm["freq"].as<double>() * 1e6;
+ assign_budget(&ctx, freq);
+ print_utilisation(&ctx);
+
+ if (!vm.count("pack-only")) {
+ if (!place_design_sa(&ctx) && !ctx.force)
+ log_error("Placing design failed.\n");
+ if (!route_design(&ctx) && !ctx.force)
+ log_error("Routing design failed.\n");
+ }
}
- if (!pack_design(&ctx) && !ctx.force)
- log_error("Packing design failed.\n");
- double freq = 50e6;
- if (vm.count("freq"))
- freq = vm["freq"].as<double>() * 1e6;
- assign_budget(&ctx, freq);
- print_utilisation(&ctx);
-
- if (!vm.count("pack-only")) {
- if (!place_design_sa(&ctx) && !ctx.force)
- log_error("Placing design failed.\n");
- if (!route_design(&ctx) && !ctx.force)
- log_error("Routing design failed.\n");
+ if (vm.count("asc")) {
+ std::string filename = vm["asc"].as<std::string>();
+ std::ofstream f(filename);
+ write_asc(&ctx, f);
}
- }
- if (vm.count("asc")) {
- std::string filename = vm["asc"].as<std::string>();
- std::ofstream f(filename);
- write_asc(&ctx, f);
- }
-
- if (vm.count("run")) {
- std::vector<std::string> files =
- vm["run"].as<std::vector<std::string>>();
- for (auto filename : files)
- execute_python_file(filename.c_str());
- }
+ if (vm.count("run")) {
+ std::vector<std::string> files =
+ vm["run"].as<std::vector<std::string>>();
+ for (auto filename : files)
+ execute_python_file(filename.c_str());
+ }
- if (vm.count("gui")) {
- QApplication a(argc, argv);
- MainWindow w(&ctx);
- w.show();
+ if (vm.count("gui")) {
+ QApplication a(argc, argv);
+ MainWindow w(&ctx);
+ w.show();
- rc = a.exec();
+ rc = a.exec();
+ }
+ deinit_python();
+ return rc;
+ } catch (log_execution_error_exception) {
+#if defined(_MSC_VER)
+ _exit(EXIT_FAILURE);
+#else
+ _Exit(EXIT_FAILURE);
+#endif
}
- deinit_python();
- return rc;
}
#endif
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 7fcf2750..9258014e 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -487,15 +487,19 @@ static void promote_globals(Context *ctx)
// Main pack function
bool pack_design(Context *ctx)
{
- log_break();
- pack_constants(ctx);
- promote_globals(ctx);
- pack_io(ctx);
- pack_lut_lutffs(ctx);
- pack_nonlut_ffs(ctx);
- pack_ram(ctx);
- log_info("Checksum: 0x%08x\n", ctx->checksum());
- return true;
+ try {
+ log_break();
+ pack_constants(ctx);
+ promote_globals(ctx);
+ pack_io(ctx);
+ pack_lut_lutffs(ctx);
+ pack_nonlut_ffs(ctx);
+ pack_ram(ctx);
+ log_info("Checksum: 0x%08x\n", ctx->checksum());
+ return true;
+ } catch (log_execution_error_exception) {
+ return false;
+ }
}
NEXTPNR_NAMESPACE_END
diff --git a/ice40/pcf.cc b/ice40/pcf.cc
index 756aba4a..87d27ff1 100644
--- a/ice40/pcf.cc
+++ b/ice40/pcf.cc
@@ -27,44 +27,51 @@ NEXTPNR_NAMESPACE_BEGIN
// Read a w
// Apply PCF constraints to a pre-packing design
-void apply_pcf(Context *ctx, std::istream &in)
+bool apply_pcf(Context *ctx, std::istream &in)
{
- if (!in)
- log_error("failed to open PCF file");
- std::string line;
- while (std::getline(in, line)) {
- size_t cstart = line.find("#");
- if (cstart != std::string::npos)
- line = line.substr(0, cstart);
- std::stringstream ss(line);
- std::vector<std::string> words;
- std::string tmp;
- while (ss >> tmp)
- words.push_back(tmp);
- if (words.size() == 0)
- continue;
- std::string cmd = words.at(0);
- if (cmd == "set_io") {
- size_t args_end = 1;
- while (args_end < words.size() && words.at(args_end).at(0) == '-')
- args_end++;
- std::string cell = words.at(args_end);
- std::string pin = words.at(args_end + 1);
- auto fnd_cell = ctx->cells.find(cell);
- if (fnd_cell == ctx->cells.end()) {
- log_warning("unmatched pcf constraint %s\n", cell.c_str());
+ try {
+ if (!in)
+ log_error("failed to open PCF file");
+ std::string line;
+ while (std::getline(in, line)) {
+ size_t cstart = line.find("#");
+ if (cstart != std::string::npos)
+ line = line.substr(0, cstart);
+ std::stringstream ss(line);
+ std::vector<std::string> words;
+ std::string tmp;
+ while (ss >> tmp)
+ words.push_back(tmp);
+ if (words.size() == 0)
+ continue;
+ std::string cmd = words.at(0);
+ if (cmd == "set_io") {
+ size_t args_end = 1;
+ while (args_end < words.size() &&
+ words.at(args_end).at(0) == '-')
+ args_end++;
+ std::string cell = words.at(args_end);
+ std::string pin = words.at(args_end + 1);
+ auto fnd_cell = ctx->cells.find(cell);
+ if (fnd_cell == ctx->cells.end()) {
+ log_warning("unmatched pcf constraint %s\n", cell.c_str());
+ } else {
+ BelId pin_bel = ctx->getPackagePinBel(pin);
+ if (pin_bel == BelId())
+ log_error("package does not have a pin named %s\n",
+ pin.c_str());
+ fnd_cell->second->attrs["BEL"] =
+ ctx->getBelName(pin_bel).str();
+ log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
+ fnd_cell->second->attrs["BEL"].c_str());
+ }
} else {
- BelId pin_bel = ctx->getPackagePinBel(pin);
- if (pin_bel == BelId())
- log_error("package does not have a pin named %s\n",
- pin.c_str());
- fnd_cell->second->attrs["BEL"] = ctx->getBelName(pin_bel).str();
- log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
- fnd_cell->second->attrs["BEL"].c_str());
+ log_error("unsupported pcf command '%s'\n", cmd.c_str());
}
- } else {
- log_error("unsupported pcf command '%s'\n", cmd.c_str());
}
+ return true;
+ } catch (log_execution_error_exception) {
+ return false;
}
}
diff --git a/ice40/pcf.h b/ice40/pcf.h
index e0816075..b86a7609 100644
--- a/ice40/pcf.h
+++ b/ice40/pcf.h
@@ -27,7 +27,7 @@
NEXTPNR_NAMESPACE_BEGIN
// Apply PCF constraints to a pre-packing design
-void apply_pcf(Context *ctx, std::istream &in);
+bool apply_pcf(Context *ctx, std::istream &in);
NEXTPNR_NAMESPACE_END