aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/nextpnr.cc19
-rw-r--r--common/nextpnr.h14
-rw-r--r--common/placer_heap.cc17
-rw-r--r--common/router2.cc20
4 files changed, 62 insertions, 8 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 1156490c..c16a601c 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -23,6 +23,25 @@
#include "log.h"
#include "util.h"
+#if defined(__wasm)
+extern "C" {
+ // FIXME: WASI does not currently support exceptions.
+ void* __cxa_allocate_exception(size_t thrown_size) throw() {
+ return malloc(thrown_size);
+ }
+ bool __cxa_uncaught_exception() throw();
+ void __cxa_throw(void* thrown_exception, struct std::type_info * tinfo, void (*dest)(void*)) {
+ std::terminate();
+ }
+}
+
+namespace boost {
+ void throw_exception( std::exception const & e ) {
+ NEXTPNR_NAMESPACE::log_error("boost::exception(): %s\n", e.what());
+ }
+}
+#endif
+
NEXTPNR_NAMESPACE_BEGIN
assertion_failure::assertion_failure(std::string msg, std::string expr_str, std::string filename, int line)
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 66bba997..4d481d06 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -33,7 +33,9 @@
#include <boost/functional/hash.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range/adaptor/reversed.hpp>
+#ifndef NPNR_DISABLE_THREADS
#include <boost/thread.hpp>
+#endif
#ifndef NEXTPNR_H
#define NEXTPNR_H
@@ -647,6 +649,7 @@ struct DeterministicRNG
struct BaseCtx
{
+#ifndef NPNR_DISABLE_THREADS
// Lock to perform mutating actions on the Context.
std::mutex mutex;
boost::thread::id mutex_owner;
@@ -655,6 +658,7 @@ struct BaseCtx
// method will lock/unlock it when its' released the main mutex to make
// sure the UI is not starved.
std::mutex ui_mutex;
+#endif
// ID String database.
mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
@@ -706,28 +710,36 @@ struct BaseCtx
// Must be called before performing any mutating changes on the Ctx/Arch.
void lock(void)
{
+#ifndef NPNR_DISABLE_THREADS
mutex.lock();
mutex_owner = boost::this_thread::get_id();
+#endif
}
void unlock(void)
{
+#ifndef NPNR_DISABLE_THREADS
NPNR_ASSERT(boost::this_thread::get_id() == mutex_owner);
mutex.unlock();
+#endif
}
// Must be called by the UI before rendering data. This lock will be
// prioritized when processing code calls yield().
void lock_ui(void)
{
+#ifndef NPNR_DISABLE_THREADS
ui_mutex.lock();
mutex.lock();
+#endif
}
void unlock_ui(void)
{
+#ifndef NPNR_DISABLE_THREADS
mutex.unlock();
ui_mutex.unlock();
+#endif
}
// Yield to UI by unlocking the main mutex, flashing the UI mutex and
@@ -737,10 +749,12 @@ struct BaseCtx
// Must be called with the main lock taken.
void yield(void)
{
+#ifndef NPNR_DISABLE_THREADS
unlock();
ui_mutex.lock();
ui_mutex.unlock();
lock();
+#endif
}
IdString id(const std::string &s) const { return IdString(this, s); }
diff --git a/common/placer_heap.cc b/common/placer_heap.cc
index c04e7091..8c43c433 100644
--- a/common/placer_heap.cc
+++ b/common/placer_heap.cc
@@ -37,7 +37,6 @@
#include <Eigen/Core>
#include <Eigen/IterativeLinearSolvers>
#include <boost/optional.hpp>
-#include <boost/thread.hpp>
#include <chrono>
#include <deque>
#include <fstream>
@@ -154,9 +153,14 @@ class HeAPPlacer
for (int i = 0; i < 4; i++) {
setup_solve_cells();
auto solve_startt = std::chrono::high_resolution_clock::now();
+#ifdef NPNR_DISABLE_THREADS
+ build_solve_direction(false, -1);
+ build_solve_direction(true, -1);
+#else
boost::thread xaxis([&]() { build_solve_direction(false, -1); });
build_solve_direction(true, -1);
xaxis.join();
+#endif
auto solve_endt = std::chrono::high_resolution_clock::now();
solve_time += std::chrono::duration<double>(solve_endt - solve_startt).count();
@@ -211,13 +215,16 @@ class HeAPPlacer
// Heuristic: don't bother with threading below a certain size
auto solve_startt = std::chrono::high_resolution_clock::now();
- if (solve_cells.size() < 500) {
- build_solve_direction(false, (iter == 0) ? -1 : iter);
- build_solve_direction(true, (iter == 0) ? -1 : iter);
- } else {
+#ifndef NPNR_DISABLE_THREADS
+ if (solve_cells.size() >= 500) {
boost::thread xaxis([&]() { build_solve_direction(false, (iter == 0) ? -1 : iter); });
build_solve_direction(true, (iter == 0) ? -1 : iter);
xaxis.join();
+ } else
+#endif
+ {
+ build_solve_direction(false, (iter == 0) ? -1 : iter);
+ build_solve_direction(true, (iter == 0) ? -1 : iter);
}
auto solve_endt = std::chrono::high_resolution_clock::now();
solve_time += std::chrono::duration<double>(solve_endt - solve_startt).count();
diff --git a/common/router2.cc b/common/router2.cc
index 26e78eaa..4dfd868b 100644
--- a/common/router2.cc
+++ b/common/router2.cc
@@ -33,7 +33,6 @@
#include <deque>
#include <fstream>
#include <queue>
-#include <thread>
#include "log.h"
#include "nextpnr.h"
#include "router1.h"
@@ -985,8 +984,22 @@ struct Router2
}
if (ctx->verbose)
log_info("%d/%d nets not multi-threadable\n", int(tcs.at(N).route_nets.size()), int(route_queue.size()));
+#ifdef NPNR_DISABLE_THREADS
+ // Singlethreaded routing - quadrants
+ for (int i = 0; i < Nq; i++) {
+ router_thread(tcs.at(i));
+ }
+ // Vertical splits
+ for (int i = Nq; i < Nq + Nv; i++) {
+ router_thread(tcs.at(i));
+ }
+ // Horizontal splits
+ for (int i = Nq + Nv; i < Nq + Nv + Nh; i++) {
+ router_thread(tcs.at(i));
+ }
+#else
// Multithreaded part of routing - quadrants
- std::vector<std::thread> threads;
+ std::vector<boost::thread> threads;
for (int i = 0; i < Nq; i++) {
threads.emplace_back([this, &tcs, i]() { router_thread(tcs.at(i)); });
}
@@ -1007,6 +1020,7 @@ struct Router2
for (auto &t : threads)
t.join();
threads.clear();
+#endif
// Singlethreaded part of routing - nets that cross partitions
// or don't fit within bounding box
for (auto st_net : tcs.at(N).route_nets)
@@ -1130,4 +1144,4 @@ Router2Cfg::Router2Cfg(Context *ctx)
perf_profile = ctx->setting<float>("router2/perfProfile", false);
}
-NEXTPNR_NAMESPACE_END \ No newline at end of file
+NEXTPNR_NAMESPACE_END