From 59a790cd00421d14120927fbb1718da8cd77e3c4 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sat, 14 Jul 2018 20:24:20 +0100 Subject: Refactor IdString functionality into IdStringDB This lets us more precisely control the lifetime of IdString databases in contexts/arches. --- common/nextpnr.cc | 8 ++++---- common/nextpnr.h | 46 ++++++++++++++++++++++++++-------------------- ecp5/arch.cc | 2 +- generic/arch.cc | 2 +- ice40/arch.cc | 2 +- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 3861e5fe..c60d0e86 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -27,7 +27,7 @@ assertion_failure::assertion_failure(std::string msg, std::string expr_str, std: { } -void IdString::set(const BaseCtx *ctx, const std::string &s) +void IdString::set(const IdStringDB *ctx, const std::string &s) { auto it = ctx->idstring_str_to_idx->find(s); if (it == ctx->idstring_str_to_idx->end()) { @@ -39,11 +39,11 @@ void IdString::set(const BaseCtx *ctx, const std::string &s) } } -const std::string &IdString::str(const BaseCtx *ctx) const { return *ctx->idstring_idx_to_str->at(index); } +const std::string &IdString::str(const IdStringDB *ctx) const { return *ctx->idstring_idx_to_str->at(index); } -const char *IdString::c_str(const BaseCtx *ctx) const { return str(ctx).c_str(); } +const char *IdString::c_str(const IdStringDB *ctx) const { return str(ctx).c_str(); } -void IdString::initialize_add(const BaseCtx *ctx, const char *s, int idx) +void IdString::initialize_add(const IdStringDB *ctx, const char *s, int idx) { NPNR_ASSERT(ctx->idstring_str_to_idx->count(s) == 0); NPNR_ASSERT(int(ctx->idstring_idx_to_str->size()) == idx); diff --git a/common/nextpnr.h b/common/nextpnr.h index 50465869..87c50fe3 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf + * Copyright (C) 2018 Serge Bazanski * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -88,28 +89,28 @@ inline void assert_false_impl(std::string message, std::string filename, int lin #define NPNR_ASSERT_MSG(cond, msg) except_assert_impl((cond), msg, #cond, __FILE__, __LINE__) #define NPNR_ASSERT_FALSE(msg) assert_false_impl(msg, __FILE__, __LINE__) -struct BaseCtx; +struct IdStringDB; struct Context; struct IdString { int index = 0; - static void initialize_arch(const BaseCtx *ctx); + static void initialize_arch(const IdStringDB *ctx); - static void initialize_add(const BaseCtx *ctx, const char *s, int idx); + static void initialize_add(const IdStringDB *ctx, const char *s, int idx); IdString() {} - void set(const BaseCtx *ctx, const std::string &s); + void set(const IdStringDB *ctx, const std::string &s); - IdString(const BaseCtx *ctx, const std::string &s) { set(ctx, s); } + IdString(const IdStringDB *ctx, const std::string &s) { set(ctx, s); } - IdString(const BaseCtx *ctx, const char *s) { set(ctx, s); } + IdString(const IdStringDB *ctx, const char *s) { set(ctx, s); } - const std::string &str(const BaseCtx *ctx) const; + const std::string &str(const IdStringDB *ctx) const; - const char *c_str(const BaseCtx *ctx) const; + const char *c_str(const IdStringDB *ctx) const; bool operator<(const IdString &other) const { return index < other.index; } @@ -238,23 +239,18 @@ struct CellInfo std::unordered_map pins; }; -struct BaseCtx +class IdStringDB { - // -------------------------------------------------------------- - + friend class IdString; + private: mutable std::unordered_map *idstring_str_to_idx; mutable std::vector *idstring_idx_to_str; - + + public: IdString id(const std::string &s) const { return IdString(this, s); } - IdString id(const char *s) const { return IdString(this, s); } - // -------------------------------------------------------------- - - std::unordered_map> nets; - std::unordered_map> cells; - - BaseCtx() + IdStringDB() { idstring_str_to_idx = new std::unordered_map; idstring_idx_to_str = new std::vector; @@ -262,11 +258,21 @@ struct BaseCtx IdString::initialize_arch(this); } - ~BaseCtx() + ~IdStringDB() { delete idstring_str_to_idx; delete idstring_idx_to_str; } +}; + +class BaseCtx : public IdStringDB +{ + public: + std::unordered_map> nets; + std::unordered_map> cells; + + BaseCtx() {} + ~BaseCtx() {} Context *getCtx() { return reinterpret_cast(this); } diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 51f4db84..3950f4ba 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -62,7 +62,7 @@ BelType Arch::belTypeFromId(IdString type) const // ----------------------------------------------------------------------- -void IdString::initialize_arch(const BaseCtx *ctx) +void IdString::initialize_arch(const IdStringDB *ctx) { #define X(t) initialize_add(ctx, #t, PIN_##t); diff --git a/generic/arch.cc b/generic/arch.cc index 390830aa..edc2ef26 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -157,7 +157,7 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy) Arch::Arch(ArchArgs) {} -void IdString::initialize_arch(const BaseCtx *ctx) {} +void IdString::initialize_arch(const IdStringDB *ctx) {} // --------------------------------------------------------------- diff --git a/ice40/arch.cc b/ice40/arch.cc index adc37dbd..c9cda40d 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -102,7 +102,7 @@ BelType Arch::belTypeFromId(IdString type) const // ----------------------------------------------------------------------- -void IdString::initialize_arch(const BaseCtx *ctx) +void IdString::initialize_arch(const IdStringDB *ctx) { #define X(t) initialize_add(ctx, #t, PIN_##t); #include "portpins.inc" -- cgit v1.2.3 From 91db413c60c965b6b7cc095f53c8d03a1658566e Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sat, 14 Jul 2018 20:33:32 +0100 Subject: Refactor RNG out to separate DeterministicRNG class This well also allow for better lifecycle control over the state of the RNG in the future. --- common/nextpnr.h | 124 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 87c50fe3..e53e4d01 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -265,65 +265,15 @@ class IdStringDB } }; -class BaseCtx : public IdStringDB +class DeterministicRNG { - public: - std::unordered_map> nets; - std::unordered_map> cells; - - BaseCtx() {} - ~BaseCtx() {} - - Context *getCtx() { return reinterpret_cast(this); } - - const Context *getCtx() const { return reinterpret_cast(this); } - - // -------------------------------------------------------------- - - bool allUiReload = false; - bool frameUiReload = false; - std::unordered_set belUiReload; - std::unordered_set wireUiReload; - std::unordered_set pipUiReload; - std::unordered_set groupUiReload; - - void refreshUi() { allUiReload = true; } - - void refreshUiFrame() { frameUiReload = true; } - - void refreshUiBel(BelId bel) { belUiReload.insert(bel); } - - void refreshUiWire(WireId wire) { wireUiReload.insert(wire); } - - void refreshUiPip(PipId pip) { pipUiReload.insert(pip); } - - void refreshUiGroup(GroupId group) { groupUiReload.insert(group); } -}; - -NEXTPNR_NAMESPACE_END - -#include "arch.h" - -NEXTPNR_NAMESPACE_BEGIN - -struct Context : Arch -{ - bool verbose = false; - bool debug = false; - bool force = false; - bool timing_driven = true; - float target_freq = 12e6; - - Context(ArchArgs args) : Arch(args) {} - - // -------------------------------------------------------------- - - // provided by router1.cc - bool getActualRouteDelay(WireId src_wire, WireId dst_wire, delay_t &delay); - - // -------------------------------------------------------------- + private: + uint64_t rngstate; - uint64_t rngstate = 0x3141592653589793; + public: + DeterministicRNG() : rngstate(0x3141592653589793) + { + } uint64_t rng64() { @@ -383,6 +333,66 @@ struct Context : Arch shuffle(a); } +}; + +class BaseCtx : public IdStringDB, public DeterministicRNG +{ + public: + std::unordered_map> nets; + std::unordered_map> cells; + + BaseCtx() {} + ~BaseCtx() {} + + Context *getCtx() { return reinterpret_cast(this); } + + const Context *getCtx() const { return reinterpret_cast(this); } + + // -------------------------------------------------------------- + + bool allUiReload = false; + bool frameUiReload = false; + std::unordered_set belUiReload; + std::unordered_set wireUiReload; + std::unordered_set pipUiReload; + std::unordered_set groupUiReload; + + void refreshUi() { allUiReload = true; } + + void refreshUiFrame() { frameUiReload = true; } + + void refreshUiBel(BelId bel) { belUiReload.insert(bel); } + + void refreshUiWire(WireId wire) { wireUiReload.insert(wire); } + + void refreshUiPip(PipId pip) { pipUiReload.insert(pip); } + + void refreshUiGroup(GroupId group) { groupUiReload.insert(group); } +}; + +NEXTPNR_NAMESPACE_END + +#include "arch.h" + +NEXTPNR_NAMESPACE_BEGIN + +struct Context : Arch +{ + bool verbose = false; + bool debug = false; + bool force = false; + bool timing_driven = true; + float target_freq = 12e6; + + Context(ArchArgs args) : Arch(args) {} + + // -------------------------------------------------------------- + + // provided by router1.cc + bool getActualRouteDelay(WireId src_wire, WireId dst_wire, delay_t &delay); + + // -------------------------------------------------------------- + uint32_t checksum() const; void check() const; -- cgit v1.2.3 From 2f5b94fe309619c221c3e1ea5aa48a4523bd3156 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Tue, 17 Jul 2018 16:27:50 +0100 Subject: Add basic external locking, lock from P&R --- common/nextpnr.h | 19 +++++++++++++++++++ common/placer1.cc | 14 ++++++++++++++ common/router1.cc | 7 +++++++ 3 files changed, 40 insertions(+) diff --git a/common/nextpnr.h b/common/nextpnr.h index e53e4d01..7aa5b100 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -337,6 +339,11 @@ class DeterministicRNG class BaseCtx : public IdStringDB, public DeterministicRNG { + private: + std::mutex mutex; + bool mutex_owned; + pthread_t mutex_owner; + public: std::unordered_map> nets; std::unordered_map> cells; @@ -344,6 +351,18 @@ class BaseCtx : public IdStringDB, public DeterministicRNG BaseCtx() {} ~BaseCtx() {} + void lock(void) + { + mutex.lock(); + mutex_owner = pthread_self(); + } + + void unlock(void) + { + NPNR_ASSERT(pthread_equal(pthread_self(), mutex_owner) != 0); + mutex.unlock(); + } + Context *getCtx() { return reinterpret_cast(this); } const Context *getCtx() const { return reinterpret_cast(this); } diff --git a/common/placer1.cc b/common/placer1.cc index 74a11040..b229616c 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -80,6 +80,7 @@ class SAPlacer size_t placed_cells = 0; // Initial constraints placer + ctx->lock(); for (auto &cell_entry : ctx->cells) { CellInfo *cell = cell_entry.second.get(); auto loc = cell->attrs.find(ctx->id("BEL")); @@ -118,16 +119,19 @@ class SAPlacer } std::sort(autoplaced.begin(), autoplaced.end(), [](CellInfo *a, CellInfo *b) { return a->name < b->name; }); ctx->shuffle(autoplaced); + ctx->unlock(); // Place cells randomly initially log_info("Creating initial placement for remaining %d cells.\n", int(autoplaced.size())); for (auto cell : autoplaced) { + ctx->lock(); place_initial(cell); placed_cells++; 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())); + ctx->unlock(); } if ((placed_cells - constr_placed_cells) % 500 != 0) log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells), @@ -136,6 +140,7 @@ class SAPlacer log_info("Running simulated annealing placer.\n"); // Calculate metric after initial placement + ctx->lock(); curr_metric = 0; curr_tns = 0; for (auto &net : ctx->nets) { @@ -143,6 +148,7 @@ class SAPlacer metrics[net.first] = wl; curr_metric += wl; } + ctx->unlock(); int n_no_progress = 0; double avg_metric = curr_metric; @@ -150,6 +156,7 @@ class SAPlacer // Main simulated annealing loop for (int iter = 1;; iter++) { + ctx->lock(); n_move = n_accept = 0; improved = false; @@ -169,6 +176,7 @@ class SAPlacer try_swap_position(cell, try_bel); } } + // Heuristic to improve placement on the 8k if (improved) n_no_progress = 0; @@ -178,6 +186,7 @@ class SAPlacer if (temp <= 1e-3 && n_no_progress >= 5) { if (iter % 5 != 0) log_info(" at iteration #%d: temp = %f, cost = %f\n", iter, temp, double(curr_metric)); + ctx->unlock(); break; } @@ -232,8 +241,10 @@ class SAPlacer metrics[net.first] = wl; curr_metric += wl; } + ctx->unlock(); } // Final post-pacement validitiy check + ctx->lock(); for (auto bel : ctx->getBels()) { IdString cell = ctx->getBoundBelCell(bel); if (!ctx->isBelLocationValid(bel)) { @@ -251,6 +262,7 @@ class SAPlacer } } } + ctx->unlock(); return true; } @@ -436,7 +448,9 @@ bool placer1(Context *ctx) placer.place(); log_info("Checksum: 0x%08x\n", ctx->checksum()); #ifndef NDEBUG + ctx->lock(); ctx->check(); + ctx->unlock(); #endif return true; } catch (log_execution_error_exception) { diff --git a/common/router1.cc b/common/router1.cc index 94c7070e..a85de7c6 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -414,6 +414,7 @@ bool router1(Context *ctx) std::unordered_set netsQueue; + ctx->lock(); for (auto &net_it : ctx->nets) { auto net_name = net_it.first; auto net_info = net_it.second.get(); @@ -478,6 +479,7 @@ bool router1(Context *ctx) estimatedTotalDelayCnt++; } } + ctx->unlock(); log_info("estimated total wire delay: %.2f (avg %.2f)\n", float(estimatedTotalDelay), float(estimatedTotalDelay) / estimatedTotalDelayCnt); @@ -493,6 +495,7 @@ bool router1(Context *ctx) #endif return false; } + ctx->lock(); iterCnt++; if (ctx->verbose) @@ -621,6 +624,8 @@ bool router1(Context *ctx) if (iterCnt == 8 || iterCnt == 16 || iterCnt == 32 || iterCnt == 64 || iterCnt == 128) ripup_penalty += ctx->getRipupDelayPenalty(); + + ctx->unlock(); } log_info("routing complete after %d iterations.\n", iterCnt); @@ -637,7 +642,9 @@ bool router1(Context *ctx) return true; } catch (log_execution_error_exception) { #ifndef NDEBUG + ctx->lock(); ctx->check(); + ctx->unlock(); #endif return false; } -- cgit v1.2.3 From 03508faabfc2f5b76039cfd13d02a341baa848a4 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Tue, 17 Jul 2018 19:16:26 +0100 Subject: WIP. --- common/nextpnr.h | 2 +- common/placer1.cc | 9 +++ common/router1.cc | 2 + gui/application.cc | 20 ++--- gui/fpgaviewwidget.cc | 220 ++++++++++++++++++++++++++++++++++++-------------- gui/fpgaviewwidget.h | 62 ++++++++------ ice40/arch.h | 8 ++ 7 files changed, 227 insertions(+), 96 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 7aa5b100..fb5e042b 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -369,7 +369,7 @@ class BaseCtx : public IdStringDB, public DeterministicRNG // -------------------------------------------------------------- - bool allUiReload = false; + bool allUiReload = true; bool frameUiReload = false; std::unordered_set belUiReload; std::unordered_set wireUiReload; diff --git a/common/placer1.cc b/common/placer1.cc index b229616c..b58893ce 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +157,14 @@ class SAPlacer // Main simulated annealing loop for (int iter = 1;; iter++) { + // TODO(q3k): unwat + pthread_yield(); + pthread_yield(); + pthread_yield(); + pthread_yield(); + pthread_yield(); + pthread_yield(); + pthread_yield(); ctx->lock(); n_move = n_accept = 0; improved = false; diff --git a/common/router1.cc b/common/router1.cc index a85de7c6..bde3be31 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -637,7 +637,9 @@ bool router1(Context *ctx) log_info("Checksum: 0x%08x\n", ctx->checksum()); #ifndef NDEBUG + ctx->lock(); ctx->check(); + ctx->unlock(); #endif return true; } catch (log_execution_error_exception) { diff --git a/gui/application.cc b/gui/application.cc index 58dc23eb..12453b57 100644 --- a/gui/application.cc +++ b/gui/application.cc @@ -37,17 +37,17 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) bool Application::notify(QObject *receiver, QEvent *event) { bool retVal = true; - try { + //try { retVal = QApplication::notify(receiver, event); - } catch (assertion_failure ex) { - QString msg; - QTextStream out(&msg); - out << ex.filename.c_str() << " at " << ex.line << "\n"; - out << ex.msg.c_str(); - QMessageBox::critical(0, "Error", msg); - } catch (...) { - QMessageBox::critical(0, "Error", "Fatal error !!!"); - } + //} catch (assertion_failure ex) { + // QString msg; + // QTextStream out(&msg); + // out << ex.filename.c_str() << " at " << ex.line << "\n"; + // out << ex.msg.c_str(); + // QMessageBox::critical(0, "Error", msg); + //} catch (...) { + // QMessageBox::critical(0, "Error", "Fatal error !!!"); + //} return retVal; } diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index c926e5fa..f4bd2b97 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "fpgaviewwidget.h" @@ -241,26 +242,25 @@ void LineShader::draw(const LineShaderData &line, const QColor &color, float thi } FPGAViewWidget::FPGAViewWidget(QWidget *parent) - : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), selectedItemsChanged_(false) + : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), rendererData_(new FPGAViewWidget::RendererData), rendererArgs_(new FPGAViewWidget::RendererArgs) { - backgroundColor_ = QColor("#000000"); - gridColor_ = QColor("#333"); - gFrameColor_ = QColor("#d0d0d0"); - gHiddenColor_ = QColor("#606060"); - gInactiveColor_ = QColor("#303030"); - gActiveColor_ = QColor("#f0f0f0"); - gSelectedColor_ = QColor("#ff6600"); - frameColor_ = QColor("#0066ba"); - highlightColors[0] = QColor("#6495ed"); - highlightColors[1] = QColor("#7fffd4"); - highlightColors[2] = QColor("#98fb98"); - highlightColors[3] = QColor("#ffd700"); - highlightColors[4] = QColor("#cd5c5c"); - highlightColors[5] = QColor("#fa8072"); - highlightColors[6] = QColor("#ff69b4"); - highlightColors[7] = QColor("#da70d6"); - for (int i = 0; i < 8; i++) - highlightItemsChanged_[i] = false; + colors_.background = QColor("#000000"); + colors_.grid = QColor("#333"); + colors_.frame = QColor("#d0d0d0"); + colors_.hidden = QColor("#606060"); + colors_.inactive = QColor("#303030"); + colors_.active = QColor("#f0f0f0"); + colors_.selected = QColor("#ff6600"); + colors_.highlight[0] = QColor("#6495ed"); + colors_.highlight[1] = QColor("#7fffd4"); + colors_.highlight[2] = QColor("#98fb98"); + colors_.highlight[3] = QColor("#ffd700"); + colors_.highlight[4] = QColor("#cd5c5c"); + colors_.highlight[5] = QColor("#fa8072"); + colors_.highlight[6] = QColor("#ff69b4"); + colors_.highlight[7] = QColor("#da70d6"); + + rendererArgs_->highlightedOrSelectedChanged = false; auto fmt = format(); fmt.setMajorVersion(3); @@ -268,7 +268,6 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) setFormat(fmt); fmt = format(); - // printf("FPGAViewWidget running on OpenGL %d.%d\n", fmt.majorVersion(), fmt.minorVersion()); if (fmt.majorVersion() < 3) { printf("Could not get OpenGL 3.0 context. Aborting.\n"); log_abort(); @@ -276,6 +275,17 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) if (fmt.minorVersion() < 1) { printf("Could not get OpenGL 3.1 context - trying anyway...\n "); } + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(update())); + timer->start(1000/20); + + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(pokeRenderer())); + timer->start(1000/2); + + renderThread_ = std::unique_ptr(QThread::create([this] { renderLinesWorker(); })); + renderThread_->start(); } FPGAViewWidget::~FPGAViewWidget() {} @@ -283,8 +293,7 @@ FPGAViewWidget::~FPGAViewWidget() {} void FPGAViewWidget::newContext(Context *ctx) { ctx_ = ctx; - selectedItems_.clear(); - update(); + pokeRenderer(); } QSize FPGAViewWidget::minimumSizeHint() const { return QSize(640, 480); } @@ -297,7 +306,7 @@ void FPGAViewWidget::initializeGL() log_error("Could not compile shader.\n"); } initializeOpenGLFunctions(); - glClearColor(backgroundColor_.red() / 255, backgroundColor_.green() / 255, backgroundColor_.blue() / 255, 0.0); + glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, colors_.background.blue() / 255, 0.0); } void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal) @@ -398,67 +407,158 @@ void FPGAViewWidget::paintGL() PolyLine(-100.0f, i, 100.0f, i).build(grid); PolyLine(i, -100.0f, i, 100.0f).build(grid); } - lineShader_.draw(grid, gridColor_, thick1Px, matrix); + lineShader_.draw(grid, colors_.grid, thick1Px, matrix); - LineShaderData shaders[4] = {LineShaderData(), LineShaderData(), LineShaderData(), LineShaderData()}; + rendererDataLock_.lock(); + lineShader_.draw(rendererData_->decals[0], colors_.frame, thick11Px, matrix); + lineShader_.draw(rendererData_->decals[1], colors_.hidden, thick11Px, matrix); + lineShader_.draw(rendererData_->decals[2], colors_.inactive, thick11Px, matrix); + lineShader_.draw(rendererData_->decals[3], colors_.active, thick11Px, matrix); - if (ctx_) { - // Draw Bels. + for (int i = 0; i < 8; i++) + lineShader_.draw(rendererData_->highlighted[i], colors_.highlight[i], thick11Px, matrix); + + lineShader_.draw(rendererData_->selected, colors_.selected, thick11Px, matrix); + rendererDataLock_.unlock(); +} + +void FPGAViewWidget::pokeRenderer(void) { + render_.wakeOne(); +} + +void FPGAViewWidget::renderLinesWorker(void) { + for (;;) { + QMutex mutex; + mutex.lock(); + render_.wait(&mutex); + + renderLines(); + + mutex.unlock(); + } +} + +void FPGAViewWidget::renderLines(void) +{ + if (ctx_ == nullptr) + return; + + ctx_->lock(); + + // For now, collapse any decal changes into change of all decals. + // TODO(q3k): fix this + bool decalsChanged = false; + if (ctx_->allUiReload) { + ctx_->allUiReload = false; + decalsChanged = true; + } + if (ctx_->frameUiReload) { + ctx_->frameUiReload = false; + decalsChanged = true; + } + if (ctx_->belUiReload.size() > 0){ + ctx_->belUiReload.clear(); + decalsChanged = true; + } + if (ctx_->wireUiReload.size() > 0) { + ctx_->wireUiReload.clear(); + decalsChanged = true; + } + if (ctx_->pipUiReload.size() > 0) { + ctx_->pipUiReload.clear(); + decalsChanged = true; + } + if (ctx_->groupUiReload.size() > 0) { + ctx_->groupUiReload.clear(); + decalsChanged = true; + } + + // Local copy of decals, taken as fast as possible to not block the P&R. + std::vector belDecals; + std::vector wireDecals; + std::vector pipDecals; + std::vector groupDecals; + if (decalsChanged) { for (auto bel : ctx_->getBels()) { - drawDecal(shaders, ctx_->getBelDecal(bel)); + belDecals.push_back(ctx_->getBelDecal(bel)); } - // Draw Wires. for (auto wire : ctx_->getWires()) { - drawDecal(shaders, ctx_->getWireDecal(wire)); + wireDecals.push_back(ctx_->getWireDecal(wire)); } - // Draw Pips. for (auto pip : ctx_->getPips()) { - drawDecal(shaders, ctx_->getPipDecal(pip)); + pipDecals.push_back(ctx_->getPipDecal(pip)); } - // Draw Groups. for (auto group : ctx_->getGroups()) { - drawDecal(shaders, ctx_->getGroupDecal(group)); + groupDecals.push_back(ctx_->getGroupDecal(group)); } + } + ctx_->unlock(); - if (selectedItemsChanged_) { - selectedItemsChanged_ = false; - selectedShader_.clear(); - for (auto decal : selectedItems_) { - drawDecal(selectedShader_, decal); - } + rendererArgsLock_.lock(); + auto selectedItems = rendererArgs_->selectedItems; + auto highlightedItems = rendererArgs_->highlightedItems; + auto highlightedOrSelectedChanged = rendererArgs_->highlightedOrSelectedChanged; + rendererArgs_->highlightedOrSelectedChanged = false; + rendererArgsLock_.unlock(); + + if (decalsChanged) { + auto data = std::unique_ptr(new FPGAViewWidget::RendererData); + // Draw Bels. + for (auto const &decal : belDecals) { + drawDecal(data->decals, decal); + } + // Draw Wires. + for (auto const &decal : wireDecals) { + drawDecal(data->decals, decal); + } + // Draw Pips. + for (auto const &decal : pipDecals) { + drawDecal(data->decals, decal); + } + // Draw Groups. + for (auto const &decal : groupDecals) { + drawDecal(data->decals, decal); + } + + // Swap over. + rendererDataLock_.lock(); + rendererData_ = std::move(data); + rendererDataLock_.unlock(); + } + + rendererDataLock_.lock(); + if (decalsChanged || highlightedOrSelectedChanged) { + rendererData_->selected.clear(); + for (auto &decal : selectedItems) { + drawDecal(rendererData_->selected, decal); } for (int i = 0; i < 8; i++) { - if (highlightItemsChanged_[i]) { - highlightItemsChanged_[i] = false; - highlightShader_[i].clear(); - for (auto decal : highlightItems_[i]) { - drawDecal(highlightShader_[i], decal); - } + rendererData_->highlighted[i].clear(); + for (auto &decal : highlightedItems[i]) { + drawDecal(rendererData_->highlighted[i], decal); } } } - - lineShader_.draw(shaders[0], gFrameColor_, thick11Px, matrix); - lineShader_.draw(shaders[1], gHiddenColor_, thick11Px, matrix); - lineShader_.draw(shaders[2], gInactiveColor_, thick11Px, matrix); - lineShader_.draw(shaders[3], gActiveColor_, thick11Px, matrix); - for (int i = 0; i < 8; i++) - lineShader_.draw(highlightShader_[i], highlightColors[i], thick11Px, matrix); - lineShader_.draw(selectedShader_, gSelectedColor_, thick11Px, matrix); + rendererDataLock_.unlock(); } + void FPGAViewWidget::onSelectedArchItem(std::vector decals) { - selectedItems_ = decals; - selectedItemsChanged_ = true; - update(); + rendererArgsLock_.lock(); + rendererArgs_->selectedItems = decals; + rendererArgs_->highlightedOrSelectedChanged = true; + rendererArgsLock_.unlock(); + pokeRenderer(); } void FPGAViewWidget::onHighlightGroupChanged(std::vector decals, int group) { - highlightItems_[group] = decals; - highlightItemsChanged_[group] = true; - update(); + rendererArgsLock_.lock(); + rendererArgs_->highlightedItems[group] = decals; + rendererArgs_->highlightedOrSelectedChanged = true; + rendererArgsLock_.unlock(); + pokeRenderer(); } void FPGAViewWidget::resizeGL(int width, int height) {} diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 33eb2800..19440054 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -21,12 +21,15 @@ #define MAPGLWIDGET_H #include +#include #include #include #include #include #include #include +#include +#include #include "nextpnr.h" @@ -209,14 +212,6 @@ class LineShader class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT - Q_PROPERTY(QColor backgroundColor MEMBER backgroundColor_ DESIGNABLE true) - Q_PROPERTY(QColor gridColor MEMBER gridColor_ DESIGNABLE true) - Q_PROPERTY(QColor gFrameColor MEMBER gFrameColor_ DESIGNABLE true) - Q_PROPERTY(QColor gHiddenColor MEMBER gHiddenColor_ DESIGNABLE true) - Q_PROPERTY(QColor gInactiveColor MEMBER gInactiveColor_ DESIGNABLE true) - Q_PROPERTY(QColor gActiveColor MEMBER gActiveColor_ DESIGNABLE true) - Q_PROPERTY(QColor gSelectedColor MEMBER gSelectedColor_ DESIGNABLE true) - Q_PROPERTY(QColor frameColor MEMBER frameColor_ DESIGNABLE true) public: FPGAViewWidget(QWidget *parent = 0); @@ -246,8 +241,12 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions void newContext(Context *ctx); void onSelectedArchItem(std::vector decals); void onHighlightGroupChanged(std::vector decals, int group); + void pokeRenderer(void); private: + void renderLines(void); + void renderLinesWorker(void); + QPoint lastPos_; LineShader lineShader_; QMatrix4x4 viewMove_; @@ -263,23 +262,36 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions Context *ctx_; - QColor backgroundColor_; - QColor gridColor_; - QColor gFrameColor_; - QColor gHiddenColor_; - QColor gInactiveColor_; - QColor gActiveColor_; - QColor gSelectedColor_; - QColor frameColor_; - - LineShaderData selectedShader_; - std::vector selectedItems_; - bool selectedItemsChanged_; - - LineShaderData highlightShader_[8]; - std::vector highlightItems_[8]; - bool highlightItemsChanged_[8]; - QColor highlightColors[8]; + QWaitCondition render_; + std::unique_ptr renderThread_; + + struct { + QColor background; + QColor grid; + QColor frame; + QColor hidden; + QColor inactive; + QColor active; + QColor selected; + QColor highlight[8]; + } colors_; + + struct RendererData { + LineShaderData decals[4]; + LineShaderData selected; + LineShaderData highlighted[8]; + }; + + struct RendererArgs { + std::vector selectedItems; + std::vector highlightedItems[8]; + bool highlightedOrSelectedChanged; + }; + + std::unique_ptr rendererData_; + QMutex rendererDataLock_; + std::unique_ptr rendererArgs_; + QMutex rendererArgsLock_; }; NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.h b/ice40/arch.h index 5dab414b..b89a0b54 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -373,6 +373,7 @@ struct Arch : BaseCtx bel_to_cell[bel.index] = cell; cells[cell]->bel = bel; cells[cell]->belStrength = strength; + refreshUiBel(bel); } void unbindBel(BelId bel) @@ -382,6 +383,7 @@ struct Arch : BaseCtx cells[bel_to_cell[bel.index]]->bel = BelId(); cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE; bel_to_cell[bel.index] = IdString(); + refreshUiBel(bel); } bool checkBelAvail(BelId bel) const @@ -475,6 +477,7 @@ struct Arch : BaseCtx wire_to_net[wire.index] = net; nets[net]->wires[wire].pip = PipId(); nets[net]->wires[wire].strength = strength; + refreshUiWire(wire); } void unbindWire(WireId wire) @@ -494,6 +497,7 @@ struct Arch : BaseCtx net_wires.erase(it); wire_to_net[wire.index] = IdString(); + refreshUiWire(wire); } bool checkWireAvail(WireId wire) const @@ -541,6 +545,8 @@ struct Arch : BaseCtx wire_to_net[dst.index] = net; nets[net]->wires[dst].pip = pip; nets[net]->wires[dst].strength = strength; + refreshUiPip(pip); + refreshUiWire(dst); } void unbindPip(PipId pip) @@ -557,6 +563,8 @@ struct Arch : BaseCtx pip_to_net[pip.index] = IdString(); switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); + refreshUiPip(pip); + refreshUiWire(dst); } bool checkPipAvail(PipId pip) const -- cgit v1.2.3 From 0385ad1b1cc3dcd4673b3c674bc28ca12a7c7450 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 10:58:30 +0100 Subject: Refactor renderer thread --- gui/fpgaviewwidget.cc | 31 ++++++-------------------- gui/fpgaviewwidget.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 27 deletions(-) diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index f4bd2b97..9a03b2a5 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "fpgaviewwidget.h" @@ -242,7 +241,7 @@ void LineShader::draw(const LineShaderData &line, const QColor &color, float thi } FPGAViewWidget::FPGAViewWidget(QWidget *parent) - : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), rendererData_(new FPGAViewWidget::RendererData), rendererArgs_(new FPGAViewWidget::RendererArgs) + : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), paintTimer_(this), rendererData_(new FPGAViewWidget::RendererData), rendererArgs_(new FPGAViewWidget::RendererArgs) { colors_.background = QColor("#000000"); colors_.grid = QColor("#333"); @@ -276,16 +275,12 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) printf("Could not get OpenGL 3.1 context - trying anyway...\n "); } - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(1000/20); + connect(&paintTimer_, SIGNAL(timeout()), this, SLOT(update())); + paintTimer_.start(std::chrono::duration(1000/20)); // paint GL 20 times per second - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(pokeRenderer())); - timer->start(1000/2); - - renderThread_ = std::unique_ptr(QThread::create([this] { renderLinesWorker(); })); - renderThread_->start(); + renderRunner_ = std::unique_ptr(new PeriodicRunner(this, [this] { renderLines(); })); + renderRunner_->start(); + renderRunner_->startTimer(std::chrono::duration(1000/2)); // render line 2 times per second } FPGAViewWidget::~FPGAViewWidget() {} @@ -423,19 +418,7 @@ void FPGAViewWidget::paintGL() } void FPGAViewWidget::pokeRenderer(void) { - render_.wakeOne(); -} - -void FPGAViewWidget::renderLinesWorker(void) { - for (;;) { - QMutex mutex; - mutex.lock(); - render_.wait(&mutex); - - renderLines(); - - mutex.unlock(); - } + renderRunner_->poke(); } void FPGAViewWidget::renderLines(void) diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 19440054..f846abca 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -209,6 +210,60 @@ class LineShader void draw(const LineShaderData &data, const QColor &color, float thickness, const QMatrix4x4 &projection); }; +class PeriodicRunner : public QThread +{ + Q_OBJECT +private: + QMutex mutex_; + QWaitCondition condition_; + bool abort_; + std::function target_; + QTimer timer_; +public: + explicit PeriodicRunner(QObject *parent, std::function target) : + QThread(parent), abort_(false), target_(target), timer_(this) + { + connect(&timer_, &QTimer::timeout, this, &PeriodicRunner::poke); + } + + void run(void) override + { + for (;;) { + mutex_.lock(); + condition_.wait(&mutex_); + + if (abort_) { + mutex_.unlock(); + return; + } + + target_(); + + mutex_.unlock(); + } + } + + void startTimer(std::chrono::milliseconds value) + { + timer_.start(value); + } + + ~PeriodicRunner() + { + mutex_.lock(); + abort_ = true; + condition_.wakeOne(); + mutex_.unlock(); + + wait(); + } + + void poke(void) + { + condition_.wakeOne(); + } +}; + class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT @@ -245,7 +300,6 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions private: void renderLines(void); - void renderLinesWorker(void); QPoint lastPos_; LineShader lineShader_; @@ -261,9 +315,9 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions const float zoomLvl2_ = 50.0f; Context *ctx_; + QTimer paintTimer_; - QWaitCondition render_; - std::unique_ptr renderThread_; + std::unique_ptr renderRunner_; struct { QColor background; -- cgit v1.2.3 From b84a446eeff080715ba0b4b98c14822f0e3f8530 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 11:04:54 +0100 Subject: Mix-in Deterministic RNG at Context instead of BaseCtx --- common/nextpnr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 2a416a05..1f75434d 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -342,7 +342,7 @@ class DeterministicRNG }; -class BaseCtx : public IdStringDB, public DeterministicRNG +class BaseCtx : public IdStringDB { private: std::mutex mutex; @@ -400,7 +400,7 @@ NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_BEGIN -struct Context : Arch +struct Context : Arch, DeterministicRNG { bool verbose = false; bool debug = false; -- cgit v1.2.3 From b4b111a053a5e2aacd036508899277022914ae8f Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 13:15:22 +0100 Subject: Move pthread yield hack into BaseCtx --- common/nextpnr.h | 13 ++++++++++++- common/placer1.cc | 10 +--------- common/router1.cc | 1 + 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 1f75434d..e9cda565 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -346,8 +347,9 @@ class BaseCtx : public IdStringDB { private: std::mutex mutex; - bool mutex_owned; pthread_t mutex_owner; + + std::mutex generation_mutex; public: std::unordered_map> nets; @@ -360,6 +362,7 @@ class BaseCtx : public IdStringDB { mutex.lock(); mutex_owner = pthread_self(); + } void unlock(void) @@ -368,6 +371,14 @@ class BaseCtx : public IdStringDB mutex.unlock(); } + // TODO(q3k): get rid of this hack + void yield(void) + { + for (int i = 0; i < 10; i++) { + pthread_yield(); + } + } + Context *getCtx() { return reinterpret_cast(this); } const Context *getCtx() const { return reinterpret_cast(this); } diff --git a/common/placer1.cc b/common/placer1.cc index b58893ce..c8ba71a4 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -157,14 +156,7 @@ class SAPlacer // Main simulated annealing loop for (int iter = 1;; iter++) { - // TODO(q3k): unwat - pthread_yield(); - pthread_yield(); - pthread_yield(); - pthread_yield(); - pthread_yield(); - pthread_yield(); - pthread_yield(); + ctx->yield(); ctx->lock(); n_move = n_accept = 0; improved = false; diff --git a/common/router1.cc b/common/router1.cc index bde3be31..3a0aa19b 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -495,6 +495,7 @@ bool router1(Context *ctx) #endif return false; } + ctx->yield(); ctx->lock(); iterCnt++; -- cgit v1.2.3 From 19f4b68f07edcbcb24282f5d3941d5d4a97afa03 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 13:19:45 +0100 Subject: clang-format and uncomment debug --- common/nextpnr.h | 11 ++++------- gui/application.cc | 20 ++++++++++---------- gui/fpgaviewwidget.cc | 21 ++++++++++----------- gui/fpgaviewwidget.h | 32 +++++++++++++++----------------- 4 files changed, 39 insertions(+), 45 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index e9cda565..09174320 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -250,10 +250,11 @@ struct CellInfo : ArchCellInfo class IdStringDB { friend class IdString; + private: mutable std::unordered_map *idstring_str_to_idx; mutable std::vector *idstring_idx_to_str; - + public: IdString id(const std::string &s) const { return IdString(this, s); } IdString id(const char *s) const { return IdString(this, s); } @@ -279,9 +280,7 @@ class DeterministicRNG uint64_t rngstate; public: - DeterministicRNG() : rngstate(0x3141592653589793) - { - } + DeterministicRNG() : rngstate(0x3141592653589793) {} uint64_t rng64() { @@ -340,7 +339,6 @@ class DeterministicRNG std::sort(a.begin(), a.end()); shuffle(a); } - }; class BaseCtx : public IdStringDB @@ -348,7 +346,7 @@ class BaseCtx : public IdStringDB private: std::mutex mutex; pthread_t mutex_owner; - + std::mutex generation_mutex; public: @@ -362,7 +360,6 @@ class BaseCtx : public IdStringDB { mutex.lock(); mutex_owner = pthread_self(); - } void unlock(void) diff --git a/gui/application.cc b/gui/application.cc index 12453b57..58dc23eb 100644 --- a/gui/application.cc +++ b/gui/application.cc @@ -37,17 +37,17 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) bool Application::notify(QObject *receiver, QEvent *event) { bool retVal = true; - //try { + try { retVal = QApplication::notify(receiver, event); - //} catch (assertion_failure ex) { - // QString msg; - // QTextStream out(&msg); - // out << ex.filename.c_str() << " at " << ex.line << "\n"; - // out << ex.msg.c_str(); - // QMessageBox::critical(0, "Error", msg); - //} catch (...) { - // QMessageBox::critical(0, "Error", "Fatal error !!!"); - //} + } catch (assertion_failure ex) { + QString msg; + QTextStream out(&msg); + out << ex.filename.c_str() << " at " << ex.line << "\n"; + out << ex.msg.c_str(); + QMessageBox::critical(0, "Error", msg); + } catch (...) { + QMessageBox::critical(0, "Error", "Fatal error !!!"); + } return retVal; } diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 9a03b2a5..b990baca 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -241,9 +241,10 @@ void LineShader::draw(const LineShaderData &line, const QColor &color, float thi } FPGAViewWidget::FPGAViewWidget(QWidget *parent) - : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), paintTimer_(this), rendererData_(new FPGAViewWidget::RendererData), rendererArgs_(new FPGAViewWidget::RendererArgs) + : QOpenGLWidget(parent), lineShader_(this), zoom_(500.f), ctx_(nullptr), paintTimer_(this), + rendererData_(new FPGAViewWidget::RendererData), rendererArgs_(new FPGAViewWidget::RendererArgs) { - colors_.background = QColor("#000000"); + colors_.background = QColor("#000000"); colors_.grid = QColor("#333"); colors_.frame = QColor("#d0d0d0"); colors_.hidden = QColor("#606060"); @@ -275,12 +276,12 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) printf("Could not get OpenGL 3.1 context - trying anyway...\n "); } - connect(&paintTimer_, SIGNAL(timeout()), this, SLOT(update())); - paintTimer_.start(std::chrono::duration(1000/20)); // paint GL 20 times per second + connect(&paintTimer_, SIGNAL(timeout()), this, SLOT(update())); + paintTimer_.start(std::chrono::duration(1000 / 20)); // paint GL 20 times per second renderRunner_ = std::unique_ptr(new PeriodicRunner(this, [this] { renderLines(); })); renderRunner_->start(); - renderRunner_->startTimer(std::chrono::duration(1000/2)); // render line 2 times per second + renderRunner_->startTimer(std::chrono::duration(1000 / 2)); // render line 2 times per second } FPGAViewWidget::~FPGAViewWidget() {} @@ -301,7 +302,8 @@ void FPGAViewWidget::initializeGL() log_error("Could not compile shader.\n"); } initializeOpenGLFunctions(); - glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, colors_.background.blue() / 255, 0.0); + glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, colors_.background.blue() / 255, + 0.0); } void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal) @@ -417,9 +419,7 @@ void FPGAViewWidget::paintGL() rendererDataLock_.unlock(); } -void FPGAViewWidget::pokeRenderer(void) { - renderRunner_->poke(); -} +void FPGAViewWidget::pokeRenderer(void) { renderRunner_->poke(); } void FPGAViewWidget::renderLines(void) { @@ -439,7 +439,7 @@ void FPGAViewWidget::renderLines(void) ctx_->frameUiReload = false; decalsChanged = true; } - if (ctx_->belUiReload.size() > 0){ + if (ctx_->belUiReload.size() > 0) { ctx_->belUiReload.clear(); decalsChanged = true; } @@ -525,7 +525,6 @@ void FPGAViewWidget::renderLines(void) rendererDataLock_.unlock(); } - void FPGAViewWidget::onSelectedArchItem(std::vector decals) { rendererArgsLock_.lock(); diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index f846abca..0d0ef89c 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -28,8 +28,8 @@ #include #include #include -#include #include +#include #include #include "nextpnr.h" @@ -213,15 +213,16 @@ class LineShader class PeriodicRunner : public QThread { Q_OBJECT -private: + private: QMutex mutex_; QWaitCondition condition_; bool abort_; std::function target_; QTimer timer_; -public: - explicit PeriodicRunner(QObject *parent, std::function target) : - QThread(parent), abort_(false), target_(target), timer_(this) + + public: + explicit PeriodicRunner(QObject *parent, std::function target) + : QThread(parent), abort_(false), target_(target), timer_(this) { connect(&timer_, &QTimer::timeout, this, &PeriodicRunner::poke); } @@ -243,10 +244,7 @@ public: } } - void startTimer(std::chrono::milliseconds value) - { - timer_.start(value); - } + void startTimer(std::chrono::milliseconds value) { timer_.start(value); } ~PeriodicRunner() { @@ -258,10 +256,7 @@ public: wait(); } - void poke(void) - { - condition_.wakeOne(); - } + void poke(void) { condition_.wakeOne(); } }; class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions @@ -319,7 +314,8 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions std::unique_ptr renderRunner_; - struct { + struct + { QColor background; QColor grid; QColor frame; @@ -330,13 +326,15 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions QColor highlight[8]; } colors_; - struct RendererData { + struct RendererData + { LineShaderData decals[4]; LineShaderData selected; LineShaderData highlighted[8]; }; - - struct RendererArgs { + + struct RendererArgs + { std::vector selectedItems; std::vector highlightedItems[8]; bool highlightedOrSelectedChanged; -- cgit v1.2.3 From b5b956bd214742892cd242ec38e4cc64c213e59e Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 17:57:16 +0100 Subject: Remove dead code. --- common/nextpnr.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 09174320..2baedef4 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -347,8 +347,6 @@ class BaseCtx : public IdStringDB std::mutex mutex; pthread_t mutex_owner; - std::mutex generation_mutex; - public: std::unordered_map> nets; std::unordered_map> cells; -- cgit v1.2.3 From 76e5236fb3c161a860b2c494fe44fde3011670af Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 18:24:16 +0100 Subject: Nuke IdStringDB --- common/nextpnr.cc | 8 +++--- common/nextpnr.h | 77 ++++++++++++++++++++++++------------------------------- ecp5/arch.cc | 2 +- generic/arch.cc | 2 +- ice40/arch.cc | 2 +- 5 files changed, 41 insertions(+), 50 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index c60d0e86..3861e5fe 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -27,7 +27,7 @@ assertion_failure::assertion_failure(std::string msg, std::string expr_str, std: { } -void IdString::set(const IdStringDB *ctx, const std::string &s) +void IdString::set(const BaseCtx *ctx, const std::string &s) { auto it = ctx->idstring_str_to_idx->find(s); if (it == ctx->idstring_str_to_idx->end()) { @@ -39,11 +39,11 @@ void IdString::set(const IdStringDB *ctx, const std::string &s) } } -const std::string &IdString::str(const IdStringDB *ctx) const { return *ctx->idstring_idx_to_str->at(index); } +const std::string &IdString::str(const BaseCtx *ctx) const { return *ctx->idstring_idx_to_str->at(index); } -const char *IdString::c_str(const IdStringDB *ctx) const { return str(ctx).c_str(); } +const char *IdString::c_str(const BaseCtx *ctx) const { return str(ctx).c_str(); } -void IdString::initialize_add(const IdStringDB *ctx, const char *s, int idx) +void IdString::initialize_add(const BaseCtx *ctx, const char *s, int idx) { NPNR_ASSERT(ctx->idstring_str_to_idx->count(s) == 0); NPNR_ASSERT(int(ctx->idstring_idx_to_str->size()) == idx); diff --git a/common/nextpnr.h b/common/nextpnr.h index 2baedef4..d42d3446 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -93,28 +93,28 @@ inline bool assert_fail_impl_str(std::string message, const char *expr_str, cons #define NPNR_ASSERT_FALSE(msg) (assert_fail_impl(msg, "false", __FILE__, __LINE__)) #define NPNR_ASSERT_FALSE_STR(msg) (assert_fail_impl_str(msg, "false", __FILE__, __LINE__)) -struct IdStringDB; +struct BaseCtx; struct Context; struct IdString { int index = 0; - static void initialize_arch(const IdStringDB *ctx); + static void initialize_arch(const BaseCtx *ctx); - static void initialize_add(const IdStringDB *ctx, const char *s, int idx); + static void initialize_add(const BaseCtx *ctx, const char *s, int idx); IdString() {} - void set(const IdStringDB *ctx, const std::string &s); + void set(const BaseCtx *ctx, const std::string &s); - IdString(const IdStringDB *ctx, const std::string &s) { set(ctx, s); } + IdString(const BaseCtx *ctx, const std::string &s) { set(ctx, s); } - IdString(const IdStringDB *ctx, const char *s) { set(ctx, s); } + IdString(const BaseCtx *ctx, const char *s) { set(ctx, s); } - const std::string &str(const IdStringDB *ctx) const; + const std::string &str(const BaseCtx *ctx) const; - const char *c_str(const IdStringDB *ctx) const; + const char *c_str(const BaseCtx *ctx) const; bool operator<(const IdString &other) const { return index < other.index; } @@ -247,39 +247,10 @@ struct CellInfo : ArchCellInfo std::unordered_map pins; }; -class IdStringDB +struct DeterministicRNG { - friend class IdString; - - private: - mutable std::unordered_map *idstring_str_to_idx; - mutable std::vector *idstring_idx_to_str; - - public: - IdString id(const std::string &s) const { return IdString(this, s); } - IdString id(const char *s) const { return IdString(this, s); } - - IdStringDB() - { - idstring_str_to_idx = new std::unordered_map; - idstring_idx_to_str = new std::vector; - IdString::initialize_add(this, "", 0); - IdString::initialize_arch(this); - } - - ~IdStringDB() - { - delete idstring_str_to_idx; - delete idstring_idx_to_str; - } -}; - -class DeterministicRNG -{ - private: uint64_t rngstate; - public: DeterministicRNG() : rngstate(0x3141592653589793) {} uint64_t rng64() @@ -341,19 +312,35 @@ class DeterministicRNG } }; -class BaseCtx : public IdStringDB +struct BaseCtx { - private: + // Lock to perform mutating actions on the Context. std::mutex mutex; pthread_t mutex_owner; - public: + // ID String database. + mutable std::unordered_map *idstring_str_to_idx; + mutable std::vector *idstring_idx_to_str; + + // Placed nets and cells. std::unordered_map> nets; std::unordered_map> cells; - BaseCtx() {} - ~BaseCtx() {} + BaseCtx() + { + idstring_str_to_idx = new std::unordered_map; + idstring_idx_to_str = new std::vector; + IdString::initialize_add(this, "", 0); + IdString::initialize_arch(this); + } + + ~BaseCtx() + { + delete idstring_str_to_idx; + delete idstring_idx_to_str; + } + // Must be called before performing any mutating changes on the Ctx/Arch. void lock(void) { mutex.lock(); @@ -374,6 +361,10 @@ class BaseCtx : public IdStringDB } } + IdString id(const std::string &s) const { return IdString(this, s); } + + IdString id(const char *s) const { return IdString(this, s); } + Context *getCtx() { return reinterpret_cast(this); } const Context *getCtx() const { return reinterpret_cast(this); } diff --git a/ecp5/arch.cc b/ecp5/arch.cc index fb37aa84..1510a27f 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -62,7 +62,7 @@ BelType Arch::belTypeFromId(IdString type) const // ----------------------------------------------------------------------- -void IdString::initialize_arch(const IdStringDB *ctx) +void IdString::initialize_arch(const BaseCtx *ctx) { #define X(t) initialize_add(ctx, #t, PIN_##t); diff --git a/generic/arch.cc b/generic/arch.cc index edc2ef26..390830aa 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -157,7 +157,7 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy) Arch::Arch(ArchArgs) {} -void IdString::initialize_arch(const IdStringDB *ctx) {} +void IdString::initialize_arch(const BaseCtx *ctx) {} // --------------------------------------------------------------- diff --git a/ice40/arch.cc b/ice40/arch.cc index d1400a63..786d8ba1 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -102,7 +102,7 @@ BelType Arch::belTypeFromId(IdString type) const // ----------------------------------------------------------------------- -void IdString::initialize_arch(const IdStringDB *ctx) +void IdString::initialize_arch(const BaseCtx *ctx) { #define X(t) initialize_add(ctx, #t, PIN_##t); #include "portpins.inc" -- cgit v1.2.3 From 5d0dbe9db961f6dbd2494bd8ab730d8926d01626 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 18:24:34 +0100 Subject: clang-format --- ice40/arch.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ice40/arch.cc b/ice40/arch.cc index 786d8ba1..64a2a4be 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -19,13 +19,13 @@ #include #include +#include "cells.h" #include "gfx.h" #include "log.h" #include "nextpnr.h" #include "placer1.h" #include "router1.h" #include "util.h" -#include "cells.h" NEXTPNR_NAMESPACE_BEGIN // ----------------------------------------------------------------------- -- cgit v1.2.3 From 0311a27a53922783363ab607ca8f3832980990c6 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 18:34:59 +0100 Subject: Use UI lock for yielding --- common/nextpnr.h | 32 ++++++++++++++++++++++++++++---- common/placer1.cc | 6 +++--- common/router1.cc | 12 +++++++----- gui/fpgaviewwidget.cc | 4 ++-- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index d42d3446..8b8299bc 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -318,6 +318,11 @@ struct BaseCtx std::mutex mutex; pthread_t mutex_owner; + // Lock to be taken by UI when wanting to access context - the yield() + // method will lock/unlock it when its' released the main mutex to make + // sure the UI is not starved. + std::mutex ui_mutex; + // ID String database. mutable std::unordered_map *idstring_str_to_idx; mutable std::vector *idstring_idx_to_str; @@ -353,12 +358,31 @@ struct BaseCtx mutex.unlock(); } - // TODO(q3k): get rid of this hack + // Must be called by the UI before rendering data. This lock will be + // prioritized when processing code calls yield(). + void lock_ui(void) + { + ui_mutex.lock(); + mutex.lock(); + } + + void unlock_ui(void) + { + mutex.unlock(); + ui_mutex.unlock(); + } + + // Yield to UI by unlocking the main mutex, flashing the UI mutex and + // relocking the main mutex. Call this when you're performing a + // long-standing action while holding a lock to let the UI show + // visualization updates. + // Must be called with the main lock taken. void yield(void) { - for (int i = 0; i < 10; i++) { - pthread_yield(); - } + unlock(); + ui_mutex.lock(); + ui_mutex.unlock(); + lock(); } IdString id(const std::string &s) const { return IdString(this, s); } diff --git a/common/placer1.cc b/common/placer1.cc index c8ba71a4..025c7c15 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -156,8 +156,6 @@ class SAPlacer // Main simulated annealing loop for (int iter = 1;; iter++) { - ctx->yield(); - ctx->lock(); n_move = n_accept = 0; improved = false; @@ -242,7 +240,9 @@ class SAPlacer metrics[net.first] = wl; curr_metric += wl; } - ctx->unlock(); + + // Let the UI show visualization updates. + ctx->yield(); } // Final post-pacement validitiy check ctx->lock(); diff --git a/common/router1.cc b/common/router1.cc index 3a0aa19b..3e4416df 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -495,8 +495,6 @@ bool router1(Context *ctx) #endif return false; } - ctx->yield(); - ctx->lock(); iterCnt++; if (ctx->verbose) @@ -533,9 +531,11 @@ bool router1(Context *ctx) ripupQueue.insert(net_name); } - if ((ctx->verbose || iterCnt == 1) && !printNets && (netCnt % 100 == 0)) + 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())); + ctx->yield(); + } } int normalRouteCnt = netCnt - int(ripupQueue.size()); @@ -596,8 +596,10 @@ bool router1(Context *ctx) ripCnt += router.rippedNets.size(); - if ((ctx->verbose || iterCnt == 1) && !printNets && (netCnt % 100 == 0)) + if ((ctx->verbose || iterCnt == 1) && !printNets && (netCnt % 100 == 0)) { log_info(" routed %d nets, ripped %d nets.\n", netCnt, ripCnt); + ctx->yield(); + } } if ((ctx->verbose || iterCnt == 1) && (netCnt % 100 != 0)) @@ -626,7 +628,7 @@ bool router1(Context *ctx) if (iterCnt == 8 || iterCnt == 16 || iterCnt == 32 || iterCnt == 64 || iterCnt == 128) ripup_penalty += ctx->getRipupDelayPenalty(); - ctx->unlock(); + ctx->yield(); } log_info("routing complete after %d iterations.\n", iterCnt); diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index b990baca..86aae25d 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -426,7 +426,7 @@ void FPGAViewWidget::renderLines(void) if (ctx_ == nullptr) return; - ctx_->lock(); + ctx_->lock_ui(); // For now, collapse any decal changes into change of all decals. // TODO(q3k): fix this @@ -475,7 +475,7 @@ void FPGAViewWidget::renderLines(void) groupDecals.push_back(ctx_->getGroupDecal(group)); } } - ctx_->unlock(); + ctx_->unlock_ui(); rendererArgsLock_.lock(); auto selectedItems = rendererArgs_->selectedItems; -- cgit v1.2.3 From be14e161ae1963203e380bfbe02cfaeda828f838 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 20 Jul 2018 18:35:42 +0100 Subject: Re-enable drawing Pips. --- ice40/arch.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ice40/arch.cc b/ice40/arch.cc index 64a2a4be..e09f26be 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -484,9 +484,9 @@ DecalXY Arch::getWireDecal(WireId wire) const DecalXY Arch::getPipDecal(PipId pip) const { DecalXY decalxy; - // decalxy.decal.type = DecalId::TYPE_PIP; - // decalxy.decal.index = pip.index; - // decalxy.decal.active = pip_to_net.at(pip.index) != IdString(); + decalxy.decal.type = DecalId::TYPE_PIP; + decalxy.decal.index = pip.index; + decalxy.decal.active = pip_to_net.at(pip.index) != IdString(); return decalxy; }; -- cgit v1.2.3 From 30e2f0e1e8cfdb24abe6c3a8013691497c706975 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 21 Jul 2018 21:40:06 +0200 Subject: Add Loc constructors Signed-off-by: Clifford Wolf --- common/nextpnr.h | 3 +++ generic/arch.cc | 15 +++++---------- generic/arch.h | 2 +- ice40/arch.cc | 7 +------ 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 40fd3d13..c8915c19 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -164,6 +164,9 @@ struct Loc { int x = -1, y = -1, z = -1; + Loc() {} + Loc(int x, int y, int z) : x(x), y(y), z(z) {} + bool operator==(const Loc &other) const { return (x == other.x) && (y == other.y) && (z == other.z); } bool operator!=(const Loc &other) const { return (x != other.x) || (y != other.y) || (z == other.z); } }; diff --git a/generic/arch.cc b/generic/arch.cc index b7ec847e..447aaa35 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -62,28 +62,23 @@ void Arch::addAlias(IdString name, IdString srcWire, IdString dstWire, DelayInfo pip_ids.push_back(name); } -void Arch::addBel(IdString name, IdString type, int x, int y, int z, bool gb) +void Arch::addBel(IdString name, IdString type, Loc loc, bool gb) { - Loc loc; - loc.x = x; - loc.y = y; - loc.z = z; - NPNR_ASSERT(bels.count(name) == 0); NPNR_ASSERT(bel_by_loc.count(loc) == 0); BelInfo &bi = bels[name]; bi.name = name; bi.type = type; - bi.x = x; - bi.y = y; - bi.z = z; + bi.x = loc.x; + bi.y = loc.y; + bi.z = loc.z; bi.gb = gb; bel_ids.push_back(name); bel_ids_by_type[type].push_back(name); bel_by_loc[loc] = name; - bels_by_tile[x][y].push_back(name); + bels_by_tile[loc.x][loc.y].push_back(name); } void Arch::addBelInput(IdString bel, IdString name, IdString wire) diff --git a/generic/arch.h b/generic/arch.h index e1516569..f4ca4383 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -97,7 +97,7 @@ struct Arch : BaseCtx void addPip(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay); void addAlias(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay); - void addBel(IdString name, IdString type, int x, int y, int z, bool gb); + void addBel(IdString name, IdString type, Loc loc, bool gb); void addBelInput(IdString bel, IdString name, IdString wire); void addBelOutput(IdString bel, IdString name, IdString wire); void addBelInout(IdString bel, IdString name, IdString wire); diff --git a/ice40/arch.cc b/ice40/arch.cc index e9a7d2b6..bbed4000 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -279,12 +279,7 @@ BelRange Arch::getBelsByTile(int x, int y) const // In iCE40 chipdb bels at the same tile are consecutive and dense z ordinates are used BelRange br; - Loc loc; - loc.x = x; - loc.y = y; - loc.z = 0; - - br.b.cursor = Arch::getBelByLocation(loc).index; + br.b.cursor = Arch::getBelByLocation(Loc(x, y, 0)).index; br.e.cursor = br.b.cursor; if (br.e.cursor != -1) { -- cgit v1.2.3 From 44f52234fb95ee3031f8ccea35e15b52c19e7b14 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Sat, 21 Jul 2018 21:44:40 +0100 Subject: QTimer::start(std::chrono::duration -> int) The chrono::duration-friendly method is availble from Qt 5.8 only. --- gui/fpgaviewwidget.cc | 4 ++-- gui/fpgaviewwidget.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 86aae25d..9343419b 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -277,11 +277,11 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) } connect(&paintTimer_, SIGNAL(timeout()), this, SLOT(update())); - paintTimer_.start(std::chrono::duration(1000 / 20)); // paint GL 20 times per second + paintTimer_.start(1000 / 20); // paint GL 20 times per second renderRunner_ = std::unique_ptr(new PeriodicRunner(this, [this] { renderLines(); })); renderRunner_->start(); - renderRunner_->startTimer(std::chrono::duration(1000 / 2)); // render line 2 times per second + renderRunner_->startTimer(1000 / 2); // render lines 2 times per second } FPGAViewWidget::~FPGAViewWidget() {} diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 0d0ef89c..b87c5d0a 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -244,7 +244,7 @@ class PeriodicRunner : public QThread } } - void startTimer(std::chrono::milliseconds value) { timer_.start(value); } + void startTimer(int msecs) { timer_.start(msecs); } ~PeriodicRunner() { -- cgit v1.2.3 From 1e96999863da24021c215a3706b5a442789ba3a7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 22 Jul 2018 00:50:49 +0200 Subject: clangformat Signed-off-by: Clifford Wolf --- common/router1.cc | 55 ++++++++++++++++++++++--------------------------- gui/ice40/mainwindow.cc | 2 +- ice40/arch.cc | 3 +-- ice40/arch.h | 5 +---- ice40/main.cc | 4 ++-- 5 files changed, 30 insertions(+), 39 deletions(-) diff --git a/common/router1.cc b/common/router1.cc index a171374f..f8d86a5b 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -251,7 +251,8 @@ struct Router } } - Router(Context *ctx, RipupScoreboard &scores, IdString net_name, int user_idx = -1, bool reroute = false, bool ripup = false, delay_t ripup_penalty = 0) + Router(Context *ctx, RipupScoreboard &scores, IdString net_name, int user_idx = -1, bool reroute = false, + bool ripup = false, delay_t ripup_penalty = 0) : ctx(ctx), scores(scores), net_name(net_name), ripup(ripup), ripup_penalty(ripup_penalty) { auto net_info = ctx->nets.at(net_name).get(); @@ -336,7 +337,8 @@ struct Router user_it.port.c_str(ctx), user_port.c_str(ctx), user_it.cell->name.c_str(ctx), ctx->getBelName(dst_bel).c_str(ctx)); - std::function register_existing_path = [ctx, net_info, &src_wires, ®ister_existing_path](WireId wire) -> delay_t { + std::function register_existing_path = + [ctx, net_info, &src_wires, ®ister_existing_path](WireId wire) -> delay_t { auto it = src_wires.find(wire); if (it != src_wires.end()) return it->second; @@ -345,7 +347,7 @@ struct Router delay_t delay = register_existing_path(ctx->getPipSrcWire(pip)); delay += ctx->getPipDelay(pip).maxDelay(); delay += ctx->getWireDelay(wire).maxDelay(); - delay -= 2*ctx->getDelayEpsilon(); + delay -= 2 * ctx->getDelayEpsilon(); src_wires[wire] = delay; return delay; @@ -361,7 +363,7 @@ struct Router } register_existing_path(dst_wire); - check_next_user_for_existing_path:; + check_next_user_for_existing_path:; } std::vector ripup_wires; @@ -371,8 +373,8 @@ struct Router for (auto &it : ripup_wires) { if (ctx->debug) - log(" Unbind dangling wire for net %s: %s\n", - net_name.c_str(ctx), ctx->getWireName(it).c_str(ctx)); + log(" Unbind dangling wire for net %s: %s\n", net_name.c_str(ctx), + ctx->getWireName(it).c_str(ctx)); ctx->unbindWire(it); } } @@ -499,9 +501,8 @@ struct RouteJob }; }; -void addFullNetRouteJob(Context *ctx, IdString net_name, - std::unordered_map> &cache, - std::priority_queue, RouteJob::Greater> &queue) +void addFullNetRouteJob(Context *ctx, IdString net_name, std::unordered_map> &cache, + std::priority_queue, RouteJob::Greater> &queue) { NetInfo *net_info = ctx->nets.at(net_name).get(); @@ -541,8 +542,7 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, bool got_slack = false; - for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) - { + for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { if (net_cache[user_idx]) continue; @@ -550,8 +550,8 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, auto dst_bel = user_info.cell->bel; if (dst_bel == BelId()) - log_error("Destination cell %s (%s) is not mapped to a bel.\n", - user_info.cell->name.c_str(ctx), user_info.cell->type.c_str(ctx)); + log_error("Destination cell %s (%s) is not mapped to a bel.\n", user_info.cell->name.c_str(ctx), + user_info.cell->type.c_str(ctx)); IdString user_port = user_info.port; @@ -595,8 +595,7 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, net_cache[user_idx] = true; } -void addNetRouteJobs(Context *ctx, IdString net_name, - std::unordered_map> &cache, +void addNetRouteJobs(Context *ctx, IdString net_name, std::unordered_map> &cache, std::priority_queue, RouteJob::Greater> &queue) { NetInfo *net_info = ctx->nets.at(net_name).get(); @@ -629,8 +628,7 @@ void addNetRouteJobs(Context *ctx, IdString net_name, if (net_cache.empty()) net_cache.resize(net_info->users.size()); - for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) - { + for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { if (net_cache[user_idx]) continue; @@ -638,8 +636,8 @@ void addNetRouteJobs(Context *ctx, IdString net_name, auto dst_bel = user_info.cell->bel; if (dst_bel == BelId()) - log_error("Destination cell %s (%s) is not mapped to a bel.\n", - user_info.cell->name.c_str(ctx), user_info.cell->type.c_str(ctx)); + log_error("Destination cell %s (%s) is not mapped to a bel.\n", user_info.cell->name.c_str(ctx), + user_info.cell->type.c_str(ctx)); IdString user_port = user_info.port; @@ -661,12 +659,10 @@ void addNetRouteJobs(Context *ctx, IdString net_name, auto it = net_info->wires.find(cursor); if (it == net_info->wires.end()) { if (ctx->debug) - log("Adding job [%s %d]: %s %s (%s) -> %s %s (%s)\n", - net_name.c_str(ctx), user_idx, + log("Adding job [%s %d]: %s %s (%s) -> %s %s (%s)\n", net_name.c_str(ctx), user_idx, ctx->getBelName(src_bel).c_str(ctx), driver_port.c_str(ctx), - ctx->getWireName(src_wire).c_str(ctx), - ctx->getBelName(dst_bel).c_str(ctx), user_port.c_str(ctx), - ctx->getWireName(dst_wire).c_str(ctx)); + ctx->getWireName(src_wire).c_str(ctx), ctx->getBelName(dst_bel).c_str(ctx), + user_port.c_str(ctx), ctx->getWireName(dst_wire).c_str(ctx)); RouteJob job; job.net = net_name; job.user_idx = user_idx; @@ -736,7 +732,7 @@ bool router1(Context *ctx) bool printNets = ctx->verbose && (jobQueue.size() < 10); while (!jobQueue.empty()) { - if(ctx->debug) + if (ctx->debug) log("Next job slack: %f\n", double(jobQueue.top().slack)); auto net_name = jobQueue.top().net; @@ -745,8 +741,8 @@ bool router1(Context *ctx) if (printNets) { if (user_idx < 0) - log_info(" routing all %d users of net %s\n", - int(ctx->nets.at(net_name)->users.size()), net_name.c_str(ctx)); + log_info(" routing all %d users of net %s\n", int(ctx->nets.at(net_name)->users.size()), + net_name.c_str(ctx)); else log_info(" routing user %d of net %s\n", user_idx, net_name.c_str(ctx)); } @@ -854,9 +850,8 @@ bool router1(Context *ctx) } if (!ctx->verbose) - log_info("iteration %d: routed %d nets without ripup, routed %d nets with ripup.\n", - iterCnt, int(normalRouteNets.size()), int(ripupQueue.size())); - + log_info("iteration %d: routed %d nets without ripup, routed %d nets with ripup.\n", iterCnt, + int(normalRouteNets.size()), int(ripupQueue.size())); totalVisitCnt += visitCnt; totalRevisitCnt += revisitCnt; diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index 847698c5..810a98ae 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -222,7 +222,7 @@ void MainWindow::new_proj() QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type), 0, false, &ok); - if (ok && !item.isEmpty()) { + if (ok && !item.isEmpty()) { currentProj = ""; currentJson = ""; currentPCF = ""; diff --git a/ice40/arch.cc b/ice40/arch.cc index 5d7d1fb4..3833dcb7 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -283,8 +283,7 @@ BelRange Arch::getBelsByTile(int x, int y) const br.e.cursor = br.b.cursor; if (br.e.cursor != -1) { - while (br.e.cursor < chip_info->num_bels && - chip_info->bel_data[br.e.cursor].x == x && + while (br.e.cursor < chip_info->num_bels && chip_info->bel_data[br.e.cursor].x == x && chip_info->bel_data[br.e.cursor].y == y) br.e.cursor++; } diff --git a/ice40/arch.h b/ice40/arch.h index b7e66414..9a8ec7bc 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -455,10 +455,7 @@ struct Arch : BaseCtx BelId getBelByLocation(Loc loc) const; BelRange getBelsByTile(int x, int y) const; - bool getBelGlobalBuf(BelId bel) const - { - return chip_info->bel_data[bel.index].type == TYPE_SB_GB; - } + bool getBelGlobalBuf(BelId bel) const { return chip_info->bel_data[bel.index].type == TYPE_SB_GB; } BelRange getBelsAtSameTile(BelId bel) const NPNR_DEPRECATED; diff --git a/ice40/main.cc b/ice40/main.cc index 70324a91..b84d6d92 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -69,8 +69,8 @@ void svg_dump_decal(const Context *ctx, const DecalXY &decal) void conflicting_options(const boost::program_options::variables_map &vm, const char *opt1, const char *opt2) { if (vm.count(opt1) && !vm[opt1].defaulted() && vm.count(opt2) && !vm[opt2].defaulted()) { - std::string msg = "Conflicting options '"+ std::string(opt1) + "' and '" + std::string(opt1) + "'."; - log_error("%s\n",msg.c_str()); + std::string msg = "Conflicting options '" + std::string(opt1) + "' and '" + std::string(opt1) + "'."; + log_error("%s\n", msg.c_str()); } } -- cgit v1.2.3 From c6e4ad322745b478f0f289f4cc5f3668e05700ac Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 22 Jul 2018 02:16:03 +0200 Subject: Move common patterns from router1 to Context API Signed-off-by: Clifford Wolf --- common/nextpnr.cc | 56 ++++++++++++++ common/nextpnr.h | 4 + common/router1.cc | 214 ++++++++++++++++-------------------------------------- 3 files changed, 124 insertions(+), 150 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 3861e5fe..ac292e77 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -51,6 +51,62 @@ void IdString::initialize_add(const BaseCtx *ctx, const char *s, int idx) ctx->idstring_idx_to_str->push_back(&insert_rc.first->first); } +WireId Context::getNetinfoSourceWire(NetInfo *net_info) const +{ + if (net_info->driver.cell == nullptr) + return WireId(); + + auto src_bel = net_info->driver.cell->bel; + + if (src_bel == BelId()) + return WireId(); + + IdString driver_port = net_info->driver.port; + + 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; + + return getWireBelPin(src_bel, portPinFromId(driver_port)); +} + +WireId Context::getNetinfoSinkWire(NetInfo *net_info, int user_idx) const +{ + auto &user_info = net_info->users[user_idx]; + auto dst_bel = user_info.cell->bel; + + if (dst_bel == BelId()) + return WireId(); + + IdString user_port = user_info.port; + + auto user_port_it = user_info.cell->pins.find(user_port); + + if (user_port_it != user_info.cell->pins.end()) + user_port = user_port_it->second; + + return getWireBelPin(dst_bel, portPinFromId(user_port)); +} + +delay_t Context::getNetinfoRouteDelay(NetInfo *net_info, int user_idx) const +{ + WireId src_wire = getNetinfoSourceWire(net_info); + WireId cursor = getNetinfoSinkWire(net_info, user_idx); + delay_t delay = getWireDelay(src_wire).maxDelay(); + + while (cursor != WireId() && cursor != src_wire) { + auto it = net_info->wires.find(cursor); + if (it == net_info->wires.end()) + break; + PipId pip = it->second.pip; + delay += getPipDelay(pip).maxDelay(); + delay += getWireDelay(cursor).maxDelay(); + cursor = getPipSrcWire(pip); + } + + return delay; +} + static uint32_t xorshift32(uint32_t x) { x ^= x << 13; diff --git a/common/nextpnr.h b/common/nextpnr.h index d89eb15b..bb40e1b6 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -460,6 +460,10 @@ struct Context : Arch, DeterministicRNG // -------------------------------------------------------------- + WireId getNetinfoSourceWire(NetInfo *net_info) const; + WireId getNetinfoSinkWire(NetInfo *net_info, int user_idx) const; + delay_t getNetinfoRouteDelay(NetInfo *net_info, int user_idx) const; + // provided by router1.cc bool getActualRouteDelay(WireId src_wire, WireId dst_wire, delay_t &delay); diff --git a/common/router1.cc b/common/router1.cc index f8d86a5b..dbe3a003 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -263,42 +263,26 @@ struct Router if (ctx->debug) log(" Source: %s.%s.\n", net_info->driver.cell->name.c_str(ctx), net_info->driver.port.c_str(ctx)); - auto src_bel = net_info->driver.cell->bel; - - if (src_bel == BelId()) - log_error("Source cell %s (%s) is not mapped to a bel.\n", net_info->driver.cell->name.c_str(ctx), - net_info->driver.cell->type.c_str(ctx)); - - if (ctx->debug) - log(" Source bel: %s\n", ctx->getBelName(src_bel).c_str(ctx)); - - IdString driver_port = net_info->driver.port; - - 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 src_wire = ctx->getWireBelPin(src_bel, ctx->portPinFromId(driver_port)); + auto src_wire = ctx->getNetinfoSourceWire(net_info); if (src_wire == WireId()) - log_error("No wire found for port %s (pin %s) on source cell %s " - "(bel %s).\n", - net_info->driver.port.c_str(ctx), driver_port.c_str(ctx), net_info->driver.cell->name.c_str(ctx), - ctx->getBelName(src_bel).c_str(ctx)); + log_error("No wire found for port %s on source cell %s.\n", + net_info->driver.port.c_str(ctx), net_info->driver.cell->name.c_str(ctx)); if (ctx->debug) log(" Source wire: %s\n", ctx->getWireName(src_wire).c_str(ctx)); std::unordered_map src_wires; - std::vector users_array; + std::vector users_array; if (user_idx < 0) { // route all users - users_array = net_info->users; + for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) + users_array.push_back(user_idx); ctx->shuffle(users_array); } else { // route only the selected user - users_array.push_back(net_info->users[user_idx]); + users_array.push_back(user_idx); } if (reroute) { @@ -312,30 +296,12 @@ struct Router ctx->bindWire(src_wire, net_name, STRENGTH_WEAK); src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay(); - for (auto &user_it : net_info->users) { - auto dst_bel = user_it.cell->bel; - - if (dst_bel == BelId()) - log_error("Destination cell %s (%s) is not mapped to a bel.\n", user_it.cell->name.c_str(ctx), - user_it.cell->type.c_str(ctx)); - - if (ctx->debug) - log(" Destination bel: %s\n", ctx->getBelName(dst_bel).c_str(ctx)); - - IdString user_port = user_it.port; - - auto user_port_it = user_it.cell->pins.find(user_port); - - if (user_port_it != user_it.cell->pins.end()) - user_port = user_port_it->second; - - auto dst_wire = ctx->getWireBelPin(dst_bel, ctx->portPinFromId(user_port)); + for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { + auto dst_wire = ctx->getNetinfoSinkWire(net_info, user_idx); if (dst_wire == WireId()) - log_error("No wire found for port %s (pin %s) on destination " - "cell %s (bel %s).\n", - user_it.port.c_str(ctx), user_port.c_str(ctx), user_it.cell->name.c_str(ctx), - ctx->getBelName(dst_bel).c_str(ctx)); + log_error("No wire found for port %s on destination cell %s.\n", + net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); std::function register_existing_path = [ctx, net_info, &src_wires, ®ister_existing_path](WireId wire) -> delay_t { @@ -379,33 +345,15 @@ struct Router } } - for (auto &user_it : users_array) { - if (ctx->debug) - log(" Route to: %s.%s.\n", user_it.cell->name.c_str(ctx), user_it.port.c_str(ctx)); - - auto dst_bel = user_it.cell->bel; - - if (dst_bel == BelId()) - log_error("Destination cell %s (%s) is not mapped to a bel.\n", user_it.cell->name.c_str(ctx), - user_it.cell->type.c_str(ctx)); - + for (int user_idx : users_array) { if (ctx->debug) - log(" Destination bel: %s\n", ctx->getBelName(dst_bel).c_str(ctx)); - - IdString user_port = user_it.port; + log(" Route to: %s.%s.\n", net_info->users[user_idx].cell->name.c_str(ctx), net_info->users[user_idx].port.c_str(ctx)); - auto user_port_it = user_it.cell->pins.find(user_port); - - if (user_port_it != user_it.cell->pins.end()) - user_port = user_port_it->second; - - auto dst_wire = ctx->getWireBelPin(dst_bel, ctx->portPinFromId(user_port)); + auto dst_wire = ctx->getNetinfoSinkWire(net_info, user_idx); if (dst_wire == WireId()) - log_error("No wire found for port %s (pin %s) on destination " - "cell %s (bel %s).\n", - user_it.port.c_str(ctx), user_port.c_str(ctx), user_it.cell->name.c_str(ctx), - ctx->getBelName(dst_bel).c_str(ctx)); + log_error("No wire found for port %s on destination cell %s.\n", + net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); if (ctx->debug) { log(" Destination wire: %s\n", ctx->getWireName(dst_wire).c_str(ctx)); @@ -509,25 +457,11 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, std::unordered_mapdriver.cell == nullptr) return; - auto src_bel = net_info->driver.cell->bel; - - if (src_bel == BelId()) - log_error("Source cell %s (%s) is not mapped to a bel.\n", net_info->driver.cell->name.c_str(ctx), - net_info->driver.cell->type.c_str(ctx)); - - IdString driver_port = net_info->driver.port; - - 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 src_wire = ctx->getWireBelPin(src_bel, ctx->portPinFromId(driver_port)); + auto src_wire = ctx->getNetinfoSourceWire(net_info); if (src_wire == WireId()) - log_error("No wire found for port %s (pin %s) on source cell %s " - "(bel %s).\n", - net_info->driver.port.c_str(ctx), driver_port.c_str(ctx), net_info->driver.cell->name.c_str(ctx), - ctx->getBelName(src_bel).c_str(ctx)); + log_error("No wire found for port %s on source cell %s.\n", + net_info->driver.port.c_str(ctx), net_info->driver.cell->name.c_str(ctx)); auto &net_cache = cache[net_name]; @@ -546,41 +480,25 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, std::unordered_mapusers[user_idx]; - auto dst_bel = user_info.cell->bel; - - if (dst_bel == BelId()) - log_error("Destination cell %s (%s) is not mapped to a bel.\n", user_info.cell->name.c_str(ctx), - user_info.cell->type.c_str(ctx)); - - IdString user_port = user_info.port; - - auto user_port_it = user_info.cell->pins.find(user_port); - - if (user_port_it != user_info.cell->pins.end()) - user_port = user_port_it->second; - - auto dst_wire = ctx->getWireBelPin(dst_bel, ctx->portPinFromId(user_port)); + auto dst_wire = ctx->getNetinfoSinkWire(net_info, user_idx); if (dst_wire == WireId()) - log_error("No wire found for port %s (pin %s) on destination " - "cell %s (bel %s).\n", - user_info.port.c_str(ctx), user_port.c_str(ctx), user_info.cell->name.c_str(ctx), - ctx->getBelName(dst_bel).c_str(ctx)); + log_error("No wire found for port %s on destination cell %s.\n", + net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); if (user_idx == 0) - job.slack = user_info.budget - ctx->estimateDelay(src_wire, dst_wire); + job.slack = net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire); else - job.slack = std::min(job.slack, user_info.budget - ctx->estimateDelay(src_wire, dst_wire)); + job.slack = std::min(job.slack, net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire)); WireId cursor = dst_wire; while (src_wire != cursor) { auto it = net_info->wires.find(cursor); if (it == net_info->wires.end()) { if (!got_slack) - job.slack = user_info.budget - ctx->estimateDelay(src_wire, dst_wire); + job.slack = net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire); else - job.slack = std::min(job.slack, user_info.budget - ctx->estimateDelay(src_wire, dst_wire)); + job.slack = std::min(job.slack, net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire)); got_slack = true; break; } @@ -603,25 +521,11 @@ void addNetRouteJobs(Context *ctx, IdString net_name, std::unordered_mapdriver.cell == nullptr) return; - auto src_bel = net_info->driver.cell->bel; - - if (src_bel == BelId()) - log_error("Source cell %s (%s) is not mapped to a bel.\n", net_info->driver.cell->name.c_str(ctx), - net_info->driver.cell->type.c_str(ctx)); - - IdString driver_port = net_info->driver.port; - - 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 src_wire = ctx->getWireBelPin(src_bel, ctx->portPinFromId(driver_port)); + auto src_wire = ctx->getNetinfoSourceWire(net_info); if (src_wire == WireId()) - log_error("No wire found for port %s (pin %s) on source cell %s " - "(bel %s).\n", - net_info->driver.port.c_str(ctx), driver_port.c_str(ctx), net_info->driver.cell->name.c_str(ctx), - ctx->getBelName(src_bel).c_str(ctx)); + log_error("No wire found for port %s on source cell %s.\n", + net_info->driver.port.c_str(ctx), net_info->driver.cell->name.c_str(ctx)); auto &net_cache = cache[net_name]; @@ -632,41 +536,20 @@ void addNetRouteJobs(Context *ctx, IdString net_name, std::unordered_mapusers[user_idx]; - auto dst_bel = user_info.cell->bel; - - if (dst_bel == BelId()) - log_error("Destination cell %s (%s) is not mapped to a bel.\n", user_info.cell->name.c_str(ctx), - user_info.cell->type.c_str(ctx)); - - IdString user_port = user_info.port; - - auto user_port_it = user_info.cell->pins.find(user_port); - - if (user_port_it != user_info.cell->pins.end()) - user_port = user_port_it->second; - - auto dst_wire = ctx->getWireBelPin(dst_bel, ctx->portPinFromId(user_port)); + auto dst_wire = ctx->getNetinfoSinkWire(net_info, user_idx); if (dst_wire == WireId()) - log_error("No wire found for port %s (pin %s) on destination " - "cell %s (bel %s).\n", - user_info.port.c_str(ctx), user_port.c_str(ctx), user_info.cell->name.c_str(ctx), - ctx->getBelName(dst_bel).c_str(ctx)); + log_error("No wire found for port %s on destination cell %s.\n", + net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); WireId cursor = dst_wire; while (src_wire != cursor) { auto it = net_info->wires.find(cursor); if (it == net_info->wires.end()) { - if (ctx->debug) - log("Adding job [%s %d]: %s %s (%s) -> %s %s (%s)\n", net_name.c_str(ctx), user_idx, - ctx->getBelName(src_bel).c_str(ctx), driver_port.c_str(ctx), - ctx->getWireName(src_wire).c_str(ctx), ctx->getBelName(dst_bel).c_str(ctx), - user_port.c_str(ctx), ctx->getWireName(dst_wire).c_str(ctx)); RouteJob job; job.net = net_name; job.user_idx = user_idx; - job.slack = user_info.budget - ctx->estimateDelay(src_wire, dst_wire); + job.slack = net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire); job.randtag = ctx->rng(); queue.push(job); net_cache[user_idx] = true; @@ -870,6 +753,37 @@ bool router1(Context *ctx) totalVisitCnt, (100.0 * totalRevisitCnt) / totalVisitCnt, (100.0 * totalOvertimeRevisitCnt) / totalVisitCnt); + { + float tns = 0; + int tns_net_count = 0; + int tns_arc_count = 0; + for (auto &net_it : ctx->nets) { + bool got_negative_slack = false; + NetInfo *net_info = ctx->nets.at(net_it.first).get(); + for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { + delay_t arc_delay = ctx->getNetinfoRouteDelay(net_info, user_idx); + delay_t arc_budget = net_info->users[user_idx].budget; + delay_t arc_slack = arc_budget - arc_delay; + if (arc_slack < 0) { + if (!got_negative_slack) { + if (ctx->verbose) + log_info("net %s has negative slack arcs:\n", net_info->name.c_str(ctx)); + tns_net_count++; + } + if (ctx->verbose) + log_info(" arc %s -> %s has %f ns slack (delay %f, budget %f)\n", + ctx->getWireName(ctx->getNetinfoSourceWire(net_info)).c_str(ctx), + ctx->getWireName(ctx->getNetinfoSinkWire(net_info, user_idx)).c_str(ctx), + ctx->getDelayNS(arc_slack), ctx->getDelayNS(arc_delay), ctx->getDelayNS(arc_budget)); + tns += ctx->getDelayNS(arc_slack); + tns_arc_count++; + } + } + } + log_info("final tns with respect to arc budgets: %f ns (%d nets, %d arcs)\n", + tns, tns_net_count, tns_arc_count); + } + NPNR_ASSERT(jobQueue.empty()); jobCache.clear(); -- cgit v1.2.3 From 62b66e02085371c456dee95dc08d2cd41351c91f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 22 Jul 2018 10:59:21 +0200 Subject: Rename getWireBelPin to getBelPinWire Signed-off-by: Clifford Wolf --- common/nextpnr.cc | 4 ++-- common/place_common.cc | 4 ++-- ecp5/arch.cc | 2 +- ecp5/arch.h | 2 +- generic/arch.cc | 2 +- generic/arch.h | 2 +- ice40/arch.cc | 2 +- ice40/arch.h | 2 +- ice40/arch_place.cc | 2 +- ice40/arch_pybindings.cc | 4 ++-- ice40/bitstream.cc | 6 +++--- ice40/main.cc | 20 ++++++++++---------- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index ac292e77..74747642 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -67,7 +67,7 @@ WireId Context::getNetinfoSourceWire(NetInfo *net_info) const if (driver_port_it != net_info->driver.cell->pins.end()) driver_port = driver_port_it->second; - return getWireBelPin(src_bel, portPinFromId(driver_port)); + return getBelPinWire(src_bel, portPinFromId(driver_port)); } WireId Context::getNetinfoSinkWire(NetInfo *net_info, int user_idx) const @@ -85,7 +85,7 @@ WireId Context::getNetinfoSinkWire(NetInfo *net_info, int user_idx) const if (user_port_it != user_info.cell->pins.end()) user_port = user_port_it->second; - return getWireBelPin(dst_bel, portPinFromId(user_port)); + return getBelPinWire(dst_bel, portPinFromId(user_port)); } delay_t Context::getNetinfoRouteDelay(NetInfo *net_info, int user_idx) const diff --git a/common/place_common.cc b/common/place_common.cc index 370eff23..95b7b2aa 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -36,7 +36,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type if (driver_cell->bel == BelId()) return 0; ctx->estimatePosition(driver_cell->bel, driver_x, driver_y, driver_gb); - WireId drv_wire = ctx->getWireBelPin(driver_cell->bel, ctx->portPinFromId(net->driver.port)); + WireId drv_wire = ctx->getBelPinWire(driver_cell->bel, ctx->portPinFromId(net->driver.port)); if (driver_gb) return 0; float worst_slack = 1000; @@ -48,7 +48,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type if (load_cell->bel == BelId()) continue; if (ctx->timing_driven && type == MetricType::COST) { - WireId user_wire = ctx->getWireBelPin(load_cell->bel, ctx->portPinFromId(load.port)); + WireId user_wire = ctx->getBelPinWire(load_cell->bel, ctx->portPinFromId(load.port)); delay_t raw_wl = ctx->estimateDelay(drv_wire, user_wire); float slack = ctx->getDelayNS(load.budget) - ctx->getDelayNS(raw_wl); if (slack < 0) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 1510a27f..f6ee0711 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -206,7 +206,7 @@ BelRange Arch::getBelsAtSameTile(BelId bel) const return br; } -WireId Arch::getWireBelPin(BelId bel, PortPin pin) const +WireId Arch::getBelPinWire(BelId bel, PortPin pin) const { WireId ret; diff --git a/ecp5/arch.h b/ecp5/arch.h index bf36ef2f..234773e3 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -484,7 +484,7 @@ struct Arch : BaseCtx return locInfo(bel)->bel_data[bel.index].type; } - WireId getWireBelPin(BelId bel, PortPin pin) const; + WireId getBelPinWire(BelId bel, PortPin pin) const; BelPin getBelPinUphill(WireId wire) const { diff --git a/generic/arch.cc b/generic/arch.cc index 447aaa35..1a8b1a67 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -215,7 +215,7 @@ const std::vector &Arch::getBelsByType(BelType type) const BelType Arch::getBelType(BelId bel) const { return bels.at(bel).type; } -WireId Arch::getWireBelPin(BelId bel, PortPin pin) const { return bels.at(bel).pins.at(pin).wire; } +WireId Arch::getBelPinWire(BelId bel, PortPin pin) const { return bels.at(bel).pins.at(pin).wire; } BelPin Arch::getBelPinUphill(WireId wire) const { return wires.at(wire).uphill_bel_pin; } diff --git a/generic/arch.h b/generic/arch.h index f4ca4383..7bcb965f 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -145,7 +145,7 @@ struct Arch : BaseCtx const std::vector &getBels() const; const std::vector &getBelsByType(BelType type) const; BelType getBelType(BelId bel) const; - WireId getWireBelPin(BelId bel, PortPin pin) const; + WireId getBelPinWire(BelId bel, PortPin pin) const; BelPin getBelPinUphill(WireId wire) const; const std::vector &getBelPinsDownhill(WireId wire) const; diff --git a/ice40/arch.cc b/ice40/arch.cc index 3833dcb7..a670f286 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -308,7 +308,7 @@ BelRange Arch::getBelsAtSameTile(BelId bel) const return br; } -WireId Arch::getWireBelPin(BelId bel, PortPin pin) const +WireId Arch::getBelPinWire(BelId bel, PortPin pin) const { WireId ret; diff --git a/ice40/arch.h b/ice40/arch.h index 9a8ec7bc..566f807a 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -465,7 +465,7 @@ struct Arch : BaseCtx return chip_info->bel_data[bel.index].type; } - WireId getWireBelPin(BelId bel, PortPin pin) const; + WireId getBelPinWire(BelId bel, PortPin pin) const; BelPin getBelPinUphill(WireId wire) const { diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index 116ab7d3..cf1276a7 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -110,7 +110,7 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const } else if (cell->type == id_sb_gb) { NPNR_ASSERT(cell->ports.at(id_glb_buf_out).net != nullptr); const NetInfo *net = cell->ports.at(id_glb_buf_out).net; - IdString glb_net = getWireName(getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT)); + IdString glb_net = getWireName(getBelPinWire(bel, PIN_GLOBAL_BUFFER_OUTPUT)); int glb_id = std::stoi(std::string("") + glb_net.str(this).back()); if (net->is_reset && net->is_enable) return false; diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index fd5109b4..a1ce9f5b 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -82,8 +82,8 @@ void arch_wrap_python() fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBelsAtSameTile"); - fn_wrapper_2a, - conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getWireBelPin"); + fn_wrapper_2a, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getBelPinWire"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBelPinUphill"); fn_wrapper_1awire_to_net[ctx->getWireBelPin(bel, PIN_D_IN_0).index] != IdString()) || - (ctx->wire_to_net[ctx->getWireBelPin(bel, PIN_D_IN_1).index] != IdString())) { + if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).index] != IdString()) || + (ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != IdString())) { input_en = true; } @@ -762,7 +762,7 @@ bool read_asc(Context *ctx, std::istream &in) if (cell.second->bel != BelId()) { for (auto &port : cell.second->ports) { PortPin pin = ctx->portPinFromId(port.first); - WireId wire = ctx->getWireBelPin(cell.second->bel, pin); + WireId wire = ctx->getBelPinWire(cell.second->bel, pin); if (wire != WireId()) { IdString name = ctx->getBoundWireNet(wire); if (name != IdString()) { diff --git a/ice40/main.cc b/ice40/main.cc index b84d6d92..24b49184 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -322,25 +322,25 @@ int main(int argc, char *argv[]) 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)); + src_wires.push_back(ctx->getBelPinWire(b, PIN_O)); } if (ctx->getBelType(b) == TYPE_SB_IO) { - src_wires.push_back(ctx->getWireBelPin(b, PIN_D_IN_0)); + src_wires.push_back(ctx->getBelPinWire(b, PIN_D_IN_0)); } } 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)); + dst_wires.push_back(ctx->getBelPinWire(b, PIN_I0)); + dst_wires.push_back(ctx->getBelPinWire(b, PIN_I1)); + dst_wires.push_back(ctx->getBelPinWire(b, PIN_I2)); + dst_wires.push_back(ctx->getBelPinWire(b, PIN_I3)); + dst_wires.push_back(ctx->getBelPinWire(b, PIN_CEN)); + dst_wires.push_back(ctx->getBelPinWire(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)); + dst_wires.push_back(ctx->getBelPinWire(b, PIN_D_OUT_0)); + dst_wires.push_back(ctx->getBelPinWire(b, PIN_OUTPUT_ENABLE)); } } -- cgit v1.2.3 From bfa83b3bfd8020298b672d467dbd6c1c6c067c21 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 22 Jul 2018 11:12:28 +0200 Subject: Add Arch::getBelPinType() and Arch::getWireBelPins() in generic arch Signed-off-by: Clifford Wolf --- generic/arch.cc | 7 +++++++ generic/arch.h | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/generic/arch.cc b/generic/arch.cc index 1a8b1a67..8c7a7670 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -90,6 +90,7 @@ void Arch::addBelInput(IdString bel, IdString name, IdString wire) pi.type = PORT_IN; wires.at(wire).downhill_bel_pins.push_back(BelPin{bel, name}); + wires.at(wire).bel_pins.push_back(BelPin{bel, name}); } void Arch::addBelOutput(IdString bel, IdString name, IdString wire) @@ -101,6 +102,7 @@ void Arch::addBelOutput(IdString bel, IdString name, IdString wire) pi.type = PORT_OUT; wires.at(wire).uphill_bel_pin = BelPin{bel, name}; + wires.at(wire).bel_pins.push_back(BelPin{bel, name}); } void Arch::addBelInout(IdString bel, IdString name, IdString wire) @@ -112,6 +114,7 @@ void Arch::addBelInout(IdString bel, IdString name, IdString wire) pi.type = PORT_INOUT; wires.at(wire).downhill_bel_pins.push_back(BelPin{bel, name}); + wires.at(wire).bel_pins.push_back(BelPin{bel, name}); } void Arch::addGroupBel(IdString group, IdString bel) { groups[group].bels.push_back(bel); } @@ -217,6 +220,8 @@ BelType Arch::getBelType(BelId bel) const { return bels.at(bel).type; } WireId Arch::getBelPinWire(BelId bel, PortPin pin) const { return bels.at(bel).pins.at(pin).wire; } +PortType Arch::getBelPinType(BelId bel, PortPin pin) const { return bels.at(bel).pins.at(pin).type; } + BelPin Arch::getBelPinUphill(WireId wire) const { return wires.at(wire).uphill_bel_pin; } const std::vector &Arch::getBelPinsDownhill(WireId wire) const { return wires.at(wire).downhill_bel_pins; } @@ -267,6 +272,8 @@ IdString Arch::getBoundWireNet(WireId wire) const { return wires.at(wire).bound_ IdString Arch::getConflictingWireNet(WireId wire) const { return wires.at(wire).bound_net; } +const std::vector &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; } + const std::vector &Arch::getWires() const { return wire_ids; } // --------------------------------------------------------------- diff --git a/generic/arch.h b/generic/arch.h index 7bcb965f..2a74b1ae 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -43,6 +43,7 @@ struct WireInfo std::vector downhill, uphill, aliases; BelPin uphill_bel_pin; std::vector downhill_bel_pins; + std::vector bel_pins; DecalXY decalxy; int x, y; }; @@ -146,8 +147,9 @@ struct Arch : BaseCtx const std::vector &getBelsByType(BelType type) const; BelType getBelType(BelId bel) const; WireId getBelPinWire(BelId bel, PortPin pin) const; - BelPin getBelPinUphill(WireId wire) const; - const std::vector &getBelPinsDownhill(WireId wire) const; + PortType getBelPinType(BelId bel, PortPin pin) const; + BelPin getBelPinUphill(WireId wire) const NPNR_DEPRECATED; + const std::vector &getBelPinsDownhill(WireId wire) const NPNR_DEPRECATED; WireId getWireByName(IdString name) const; IdString getWireName(WireId wire) const; @@ -159,6 +161,7 @@ struct Arch : BaseCtx IdString getConflictingWireNet(WireId wire) const; DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); } const std::vector &getWires() const; + const std::vector &getWireBelPins(WireId wire) const; PipId getPipByName(IdString name) const; IdString getPipName(PipId pip) const; -- cgit v1.2.3 From b60c9485d2d324a221c7050aa6437b291b3dedf4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 22 Jul 2018 11:56:51 +0200 Subject: Add Arch::getBelPinType() and Arch::getWireBelPins() in iCE40 arch Signed-off-by: Clifford Wolf --- ice40/arch.cc | 14 ++++++++++++++ ice40/arch.h | 18 ++++++++++++++++-- ice40/chipdb.py | 29 +++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/ice40/arch.cc b/ice40/arch.cc index a670f286..5f0384a3 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -308,6 +308,20 @@ BelRange Arch::getBelsAtSameTile(BelId bel) const return br; } +PortType Arch::getBelPinType(BelId bel, PortPin pin) const +{ + NPNR_ASSERT(bel != BelId()); + + int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; + const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); + + for (int i = 0; i < num_bel_wires; i++) + if (bel_wires[i].port == pin) + return PortType(bel_wires[i].type); + + return PORT_INOUT; +} + WireId Arch::getBelPinWire(BelId bel, PortPin pin) const { WireId ret; diff --git a/ice40/arch.h b/ice40/arch.h index 566f807a..f3016424 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -46,6 +46,7 @@ template struct RelPtr NPNR_PACKED_STRUCT(struct BelWirePOD { int32_t wire_index; PortPin port; + int32_t type; }); NPNR_PACKED_STRUCT(struct BelInfoPOD { @@ -86,6 +87,9 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD { BelPortPOD bel_uphill; RelPtr bels_downhill; + int32_t num_bel_pins; + RelPtr bel_pins; + int32_t num_segments; RelPtr segments; @@ -466,8 +470,9 @@ struct Arch : BaseCtx } WireId getBelPinWire(BelId bel, PortPin pin) const; + PortType getBelPinType(BelId bel, PortPin pin) const; - BelPin getBelPinUphill(WireId wire) const + BelPin getBelPinUphill(WireId wire) const NPNR_DEPRECATED { BelPin ret; NPNR_ASSERT(wire != WireId()); @@ -480,7 +485,7 @@ struct Arch : BaseCtx return ret; } - BelPinRange getBelPinsDownhill(WireId wire) const + BelPinRange getBelPinsDownhill(WireId wire) const NPNR_DEPRECATED { BelPinRange range; NPNR_ASSERT(wire != WireId()); @@ -555,6 +560,15 @@ struct Arch : BaseCtx return delay; } + BelPinRange getWireBelPins(WireId wire) const + { + BelPinRange range; + NPNR_ASSERT(wire != WireId()); + range.b.ptr = chip_info->wire_data[wire.index].bel_pins.get(); + range.e.ptr = range.b.ptr + chip_info->wire_data[wire.index].num_bel_pins; + return range; + } + WireRange getWires() const { WireRange range; diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 329fef56..6e2bd2b5 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -43,6 +43,7 @@ packages = list() wire_uphill_belport = dict() wire_downhill_belports = dict() +wire_belports = dict() wire_names = dict() wire_names_r = dict() @@ -449,12 +450,18 @@ def add_bel_input(bel, wire, port): if wire not in wire_downhill_belports: wire_downhill_belports[wire] = set() wire_downhill_belports[wire].add((bel, port)) - bel_wires[bel].append((wire, port)) + if wire not in wire_belports: + wire_belports[wire] = set() + wire_belports[wire].add((bel, port)) + bel_wires[bel].append((wire, port, 0)) def add_bel_output(bel, wire, port): assert wire not in wire_uphill_belport wire_uphill_belport[wire] = (bel, port) - bel_wires[bel].append((wire, port)) + if wire not in wire_belports: + wire_belports[wire] = set() + wire_belports[wire].add((bel, port)) + bel_wires[bel].append((wire, port, 1)) def add_bel_lc(x, y, z): bel = len(bel_name) @@ -913,6 +920,7 @@ for bel in range(len(bel_name)): for i in range(len(bel_wires[bel])): bba.u32(bel_wires[bel][i][0], "wire_index") bba.u32(portpins[bel_wires[bel][i][1]], "port") + bba.u32(bel_wires[bel][i][2], "type") index += 1 bba.l("bel_data_%s" % dev_name, "BelInfoPOD") @@ -988,6 +996,15 @@ for wire in range(num_wires): else: num_bels_downhill = 0 + if wire in wire_belports: + num_bel_pins = len(wire_belports[wire]) + bba.l("wire%d_bels" % wire, "BelPortPOD") + for belport in sorted(wire_belports[wire]): + bba.u32(belport[0], "bel_index") + bba.u32(portpins[belport[1]], "port") + else: + num_bel_pins = 0 + info = dict() info["name"] = "X%d/Y%d/%s" % wire_names_r[wire] @@ -1000,6 +1017,9 @@ for wire in range(num_wires): info["num_bels_downhill"] = num_bels_downhill info["list_bels_downhill"] = ("wire%d_downbels" % wire) if num_bels_downhill > 0 else None + info["num_bel_pins"] = num_bel_pins + info["list_bel_pins"] = ("wire%d_bels" % wire) if num_bel_pins > 0 else None + if wire in wire_uphill_belport: info["uphill_bel"] = wire_uphill_belport[wire][0] info["uphill_pin"] = portpins[wire_uphill_belport[wire][1]] @@ -1007,6 +1027,9 @@ for wire in range(num_wires): info["uphill_bel"] = -1 info["uphill_pin"] = 0 + if num_bels_downhill == 0: + info["list_bel_pins"] = None + avg_x, avg_y = 0, 0 if wire in wire_xy: for x, y in wire_xy[wire]: @@ -1085,6 +1108,8 @@ for wire, info in enumerate(wireinfo): bba.u32(info["uphill_bel"], "bel_uphill.bel_index") bba.u32(info["uphill_pin"], "bel_uphill.port") bba.r(info["list_bels_downhill"], "bels_downhill") + bba.u32(info["num_bel_pins"], "num_bel_pins") + bba.r(info["list_bel_pins"], "bel_pins") bba.u32(len(wire_segments[wire]), "num_segments") if len(wire_segments[wire]): bba.r("wire_segments_%d" % wire, "segments") -- cgit v1.2.3 From e13fc7edabb449d21ad6473bab23d5c1b2cf3761 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 22 Jul 2018 12:08:52 +0200 Subject: Add Arch::getBelPins() to generic and iCE40 archs Signed-off-by: Clifford Wolf --- generic/arch.cc | 7 +++++++ generic/arch.h | 1 + ice40/arch.cc | 15 +++++++++++++++ ice40/arch.h | 2 ++ 4 files changed, 25 insertions(+) diff --git a/generic/arch.cc b/generic/arch.cc index 8c7a7670..0f2f5fe3 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -226,6 +226,13 @@ BelPin Arch::getBelPinUphill(WireId wire) const { return wires.at(wire).uphill_b const std::vector &Arch::getBelPinsDownhill(WireId wire) const { return wires.at(wire).downhill_bel_pins; } +std::vector Arch::getBelPins(BelId bel) const +{ + std::vector ret; + for (auto &it : bels.at(bel).pins) + ret.push_back(it.first); +} + // --------------------------------------------------------------- WireId Arch::getWireByName(IdString name) const diff --git a/generic/arch.h b/generic/arch.h index 2a74b1ae..e650906d 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -150,6 +150,7 @@ struct Arch : BaseCtx PortType getBelPinType(BelId bel, PortPin pin) const; BelPin getBelPinUphill(WireId wire) const NPNR_DEPRECATED; const std::vector &getBelPinsDownhill(WireId wire) const NPNR_DEPRECATED; + std::vector getBelPins(BelId bel) const; WireId getWireByName(IdString name) const; IdString getWireName(WireId wire) const; diff --git a/ice40/arch.cc b/ice40/arch.cc index 5f0384a3..65b21afd 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -340,6 +340,21 @@ WireId Arch::getBelPinWire(BelId bel, PortPin pin) const return ret; } +std::vector Arch::getBelPins(BelId bel) const +{ + std::vector ret; + + NPNR_ASSERT(bel != BelId()); + + int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; + const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); + + for (int i = 0; i < num_bel_wires; i++) + ret.push_back(bel_wires[i].port); + + return ret; +} + // ----------------------------------------------------------------------- WireId Arch::getWireByName(IdString name) const diff --git a/ice40/arch.h b/ice40/arch.h index f3016424..2e2018fb 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -494,6 +494,8 @@ struct Arch : BaseCtx return range; } + std::vector getBelPins(BelId bel) const; + // ------------------------------------------------- WireId getWireByName(IdString name) const; -- cgit v1.2.3 From 38431bd420ff2dcbaa9581571e6d0302dcfe2379 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sun, 22 Jul 2018 16:55:10 +0200 Subject: ecp5: Fix regression following router update Signed-off-by: David Shah --- ecp5/arch.cc | 2 +- ecp5/arch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index f6ee0711..c7896ca6 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -325,7 +325,7 @@ void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const delay_t Arch::estimateDelay(WireId src, WireId dst) const { - return abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y); + return 200 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y)); } // ----------------------------------------------------------------------- diff --git a/ecp5/arch.h b/ecp5/arch.h index 234773e3..13b2c3b8 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -694,7 +694,7 @@ struct Arch : BaseCtx { DelayInfo delay; NPNR_ASSERT(pip != PipId()); - delay.delay = locInfo(pip)->pip_data[pip.index].delay; + delay.delay = locInfo(pip)->pip_data[pip.index].delay * 100; return delay; } -- cgit v1.2.3 From 987fdc1b29d9cb7478df49c72f68ce5f3f9f740c Mon Sep 17 00:00:00 2001 From: David Shah Date: Sun, 22 Jul 2018 17:07:38 +0200 Subject: ecp5: Adding new Bel pin API Signed-off-by: David Shah --- ecp5/arch.cc | 30 ++++++++++++++++++++++++++++++ ecp5/arch.h | 24 ++++++++++++++++++++++-- ecp5/trellis_import.py | 12 +++++++++++- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index c7896ca6..90950492 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -224,6 +224,20 @@ WireId Arch::getBelPinWire(BelId bel, PortPin pin) const return ret; } +PortType Arch::getBelPinType(BelId bel, PortPin pin) const +{ + NPNR_ASSERT(bel != BelId()); + + int num_bel_wires = locInfo(bel)->bel_data[bel.index].num_bel_wires; + const BelWirePOD *bel_wires = locInfo(bel)->bel_data[bel.index].bel_wires.get(); + + for (int i = 0; i < num_bel_wires; i++) + if (bel_wires[i].port == pin) + return PortType(bel_wires[i].type); + + return PORT_INOUT; +} + // ----------------------------------------------------------------------- WireId Arch::getWireByName(IdString name) const @@ -314,6 +328,22 @@ std::string Arch::getBelPackagePin(BelId bel) const } return ""; } + +std::vector Arch::getBelPins(BelId bel) const + +{ + std::vector ret; + NPNR_ASSERT(bel != BelId()); + + int num_bel_wires = locInfo(bel)->bel_data[bel.index].num_bel_wires; + const BelWirePOD *bel_wires = locInfo(bel)->bel_data[bel.index].bel_wires.get(); + + for (int i = 0; i < num_bel_wires; i++) + ret.push_back(bel_wires[i].port); + + return ret; +} + // ----------------------------------------------------------------------- void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const diff --git a/ecp5/arch.h b/ecp5/arch.h index 13b2c3b8..b6aec856 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -50,6 +50,7 @@ NPNR_PACKED_STRUCT(struct BelWirePOD { LocationPOD rel_wire_loc; int32_t wire_index; PortPin port; + int32_t type; }); NPNR_PACKED_STRUCT(struct BelInfoPOD { @@ -87,6 +88,9 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD { int32_t num_bels_downhill; BelPortPOD bel_uphill; RelPtr bels_downhill; + + int32_t num_bel_pins; + RelPtr bel_pins; }); NPNR_PACKED_STRUCT(struct LocationTypePOD { @@ -486,7 +490,7 @@ struct Arch : BaseCtx WireId getBelPinWire(BelId bel, PortPin pin) const; - BelPin getBelPinUphill(WireId wire) const + BelPin getBelPinUphill(WireId wire) const NPNR_DEPRECATED { BelPin ret; NPNR_ASSERT(wire != WireId()); @@ -500,7 +504,7 @@ struct Arch : BaseCtx return ret; } - BelPinRange getBelPinsDownhill(WireId wire) const + BelPinRange getBelPinsDownhill(WireId wire) const NPNR_DEPRECATED { BelPinRange range; NPNR_ASSERT(wire != WireId()); @@ -511,6 +515,19 @@ struct Arch : BaseCtx return range; } + BelPinRange getWireBelPins(WireId wire) const + { + BelPinRange range; + NPNR_ASSERT(wire != WireId()); + range.b.ptr = locInfo(wire)->wire_data[wire.index].bel_pins.get(); + range.b.wire_loc = wire.location; + range.e.ptr = range.b.ptr + locInfo(wire)->wire_data[wire.index].num_bel_pins; + range.e.wire_loc = wire.location; + return range; + } + + std::vector getBelPins(BelId bel) const; + // ------------------------------------------------- WireId getWireByName(IdString name) const; @@ -581,6 +598,7 @@ struct Arch : BaseCtx DelayInfo getWireDelay(WireId wire) const { DelayInfo delay; + delay.delay = 0; return delay; } @@ -739,6 +757,8 @@ struct Arch : BaseCtx BelId getPackagePinBel(const std::string &pin) const; std::string getBelPackagePin(BelId bel) const; + PortType getBelPinType(BelId bel, PortPin pin) const; + // ------------------------------------------------- GroupId getGroupByName(IdString name) const { return GroupId(); } diff --git a/ecp5/trellis_import.py b/ecp5/trellis_import.py index af5386e7..b0cbdd90 100755 --- a/ecp5/trellis_import.py +++ b/ecp5/trellis_import.py @@ -407,6 +407,12 @@ def write_database(dev_name, ddrg, endianness): write_loc(db.bel.rel, "rel_bel_loc") bba.u32(db.bel.id, "bel_index") bba.u32(portpins[ddrg.to_str(db.pin)], "port") + if len(wire.belPins) > 0: + bba.l("loc%d_wire%d_belpins" % (idx, wire_idx), "BelPortPOD") + for bp in wire.belPins: + write_loc(bp.bel.rel, "rel_bel_loc") + bba.u32(bp.bel.id, "bel_index") + bba.u32(portpins[ddrg.to_str(bp.pin)], "port") bba.l("loc%d_wires" % idx, "WireInfoPOD") for wire_idx in range(len(loctype.wires)): wire = loctype.wires[wire_idx] @@ -424,14 +430,18 @@ def write_database(dev_name, ddrg, endianness): bba.u32(0xFFFFFFFF, "bel_uphill.bel_index") bba.u32(0, "bel_uphill.port") bba.r("loc%d_wire%d_downbels" % (idx, wire_idx) if len(wire.belsDownhill) > 0 else None, "bels_downhill") + bba.u32(len(wire.belPins), "num_bel_pins") + bba.r("loc%d_wire%d_belpins" % (idx, wire_idx) if len(wire.belPins) > 0 else None, "bel_pins") + if len(loctype.bels) > 0: for bel_idx in range(len(loctype.bels)): bel = loctype.bels[bel_idx] - bba.l("loc%d_bel%d_wires" % (idx, bel_idx), "BelPortPOD") + bba.l("loc%d_bel%d_wires" % (idx, bel_idx), "BelWirePOD") for pin in bel.wires: write_loc(pin.wire.rel, "rel_wire_loc") bba.u32(pin.wire.id, "wire_index") bba.u32(portpins[ddrg.to_str(pin.pin)], "port") + bba.u32(int(pin.dir), "dir") bba.l("loc%d_bels" % idx, "BelInfoPOD") for bel_idx in range(len(loctype.bels)): bel = loctype.bels[bel_idx] -- cgit v1.2.3 From f93fc6fa79276a82b8f6d1070d7f7ddcd65254b2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 22 Jul 2018 19:43:56 +0200 Subject: Move to new api --- gui/designwidget.cc | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/gui/designwidget.cc b/gui/designwidget.cc index a59307f0..c571e303 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -515,23 +515,14 @@ void DesignWidget::onItemSelectionChanged() addProperty(delayItem, QVariant::Double, "Min Fall", delay.minFallDelay()); addProperty(delayItem, QVariant::Double, "Max Fall", delay.maxFallDelay()); - QtProperty *belpinItem = addSubGroup(topItem, "BelPin Uphill"); - BelPin uphill = ctx->getBelPinUphill(wire); - if (uphill.bel != BelId()) - addProperty(belpinItem, QVariant::String, "Bel", ctx->getBelName(uphill.bel).c_str(ctx), ElementType::BEL); - else - addProperty(belpinItem, QVariant::String, "Bel", "", ElementType::BEL); - - addProperty(belpinItem, QVariant::String, "PortPin", ctx->portPinToId(uphill.pin).c_str(ctx), ElementType::BEL); - - QtProperty *downhillItem = addSubGroup(topItem, "BelPin Downhill"); - for (const auto &item : ctx->getBelPinsDownhill(wire)) { + QtProperty *belpinsItem = addSubGroup(topItem, "BelPins"); + for (const auto &item : ctx->getWireBelPins(wire)) { QString belname = ""; if (item.bel != BelId()) belname = ctx->getBelName(item.bel).c_str(ctx); QString pinname = ctx->portPinToId(item.pin).c_str(ctx); - QtProperty *dhItem = addSubGroup(downhillItem, belname + "-" + pinname); + QtProperty *dhItem = addSubGroup(belpinsItem, belname + "-" + pinname); addProperty(dhItem, QVariant::String, "Bel", belname, ElementType::BEL); addProperty(dhItem, QVariant::String, "PortPin", pinname); } -- cgit v1.2.3 From b9c413a5aa06a325de5c55e254441aee58143676 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 22 Jul 2018 19:58:17 +0200 Subject: Move to new API and remove deprecated --- ecp5/arch.h | 25 ---------------- generic/arch.cc | 4 --- generic/arch.h | 2 -- ice40/arch.h | 23 --------------- ice40/arch_pybindings.cc | 6 ++-- ice40/bitstream.cc | 74 +++++++++++++++++++++++++----------------------- 6 files changed, 40 insertions(+), 94 deletions(-) diff --git a/ecp5/arch.h b/ecp5/arch.h index b6aec856..cce9f09d 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -490,31 +490,6 @@ struct Arch : BaseCtx WireId getBelPinWire(BelId bel, PortPin pin) const; - BelPin getBelPinUphill(WireId wire) const NPNR_DEPRECATED - { - BelPin ret; - NPNR_ASSERT(wire != WireId()); - - if (locInfo(wire)->wire_data[wire.index].bel_uphill.bel_index >= 0) { - ret.bel.index = locInfo(wire)->wire_data[wire.index].bel_uphill.bel_index; - ret.bel.location = wire.location + locInfo(wire)->wire_data[wire.index].bel_uphill.rel_bel_loc; - ret.pin = locInfo(wire)->wire_data[wire.index].bel_uphill.port; - } - - return ret; - } - - BelPinRange getBelPinsDownhill(WireId wire) const NPNR_DEPRECATED - { - BelPinRange range; - NPNR_ASSERT(wire != WireId()); - range.b.ptr = locInfo(wire)->wire_data[wire.index].bels_downhill.get(); - range.b.wire_loc = wire.location; - range.e.ptr = range.b.ptr + locInfo(wire)->wire_data[wire.index].num_bels_downhill; - range.e.wire_loc = wire.location; - return range; - } - BelPinRange getWireBelPins(WireId wire) const { BelPinRange range; diff --git a/generic/arch.cc b/generic/arch.cc index 0f2f5fe3..6f2bd5df 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -222,10 +222,6 @@ WireId Arch::getBelPinWire(BelId bel, PortPin pin) const { return bels.at(bel).p PortType Arch::getBelPinType(BelId bel, PortPin pin) const { return bels.at(bel).pins.at(pin).type; } -BelPin Arch::getBelPinUphill(WireId wire) const { return wires.at(wire).uphill_bel_pin; } - -const std::vector &Arch::getBelPinsDownhill(WireId wire) const { return wires.at(wire).downhill_bel_pins; } - std::vector Arch::getBelPins(BelId bel) const { std::vector ret; diff --git a/generic/arch.h b/generic/arch.h index e650906d..a77dca68 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -148,8 +148,6 @@ struct Arch : BaseCtx BelType getBelType(BelId bel) const; WireId getBelPinWire(BelId bel, PortPin pin) const; PortType getBelPinType(BelId bel, PortPin pin) const; - BelPin getBelPinUphill(WireId wire) const NPNR_DEPRECATED; - const std::vector &getBelPinsDownhill(WireId wire) const NPNR_DEPRECATED; std::vector getBelPins(BelId bel) const; WireId getWireByName(IdString name) const; diff --git a/ice40/arch.h b/ice40/arch.h index 2e2018fb..3ae6ce65 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -471,29 +471,6 @@ struct Arch : BaseCtx WireId getBelPinWire(BelId bel, PortPin pin) const; PortType getBelPinType(BelId bel, PortPin pin) const; - - BelPin getBelPinUphill(WireId wire) const NPNR_DEPRECATED - { - BelPin ret; - NPNR_ASSERT(wire != WireId()); - - if (chip_info->wire_data[wire.index].bel_uphill.bel_index >= 0) { - ret.bel.index = chip_info->wire_data[wire.index].bel_uphill.bel_index; - ret.pin = chip_info->wire_data[wire.index].bel_uphill.port; - } - - return ret; - } - - BelPinRange getBelPinsDownhill(WireId wire) const NPNR_DEPRECATED - { - BelPinRange range; - NPNR_ASSERT(wire != WireId()); - range.b.ptr = chip_info->wire_data[wire.index].bels_downhill.get(); - range.e.ptr = range.b.ptr + chip_info->wire_data[wire.index].num_bels_downhill; - return range; - } - std::vector getBelPins(BelId bel) const; // ------------------------------------------------- diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index a1ce9f5b..246d0f57 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -84,10 +84,8 @@ void arch_wrap_python() fn_wrapper_2a, conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getBelPinWire"); - fn_wrapper_1a, - conv_from_str>::def_wrap(ctx_cls, "getBelPinUphill"); - fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBelPinsDownhill"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getWireBelPins"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getWireChecksum"); diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 9f5d1f66..5559c2ce 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -717,42 +717,44 @@ bool read_asc(Context *ctx, std::istream &in) for (auto w : net.second->wires) { if (w.second.pip == PipId()) { WireId wire = w.first; - BelPin belpin = ctx->getBelPinUphill(wire); - if (ctx->checkBelAvail(belpin.bel)) { - if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LC) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_IO")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_GB")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); - // TODO: Add port mapping to nets - } - if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) { - std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC")); - IdString name = created->name; - ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); - // TODO: Add port mapping to nets + for (auto belpin : ctx->getWireBelPins(wire)) { + + if (ctx->checkBelAvail(belpin.bel)) { + if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LC) { + std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); + IdString name = created->name; + ctx->cells[name] = std::move(created); + ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + // TODO: Add port mapping to nets + } + if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) { + std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_IO")); + IdString name = created->name; + ctx->cells[name] = std::move(created); + ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + // TODO: Add port mapping to nets + } + if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) { + std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_GB")); + IdString name = created->name; + ctx->cells[name] = std::move(created); + ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + // TODO: Add port mapping to nets + } + if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) { + std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT")); + IdString name = created->name; + ctx->cells[name] = std::move(created); + ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + // TODO: Add port mapping to nets + } + if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) { + std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC")); + IdString name = created->name; + ctx->cells[name] = std::move(created); + ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + // TODO: Add port mapping to nets + } } } } -- cgit v1.2.3 From 7f473f5199fbf26c8e2bdf43b19ea6ab84c8e021 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 22 Jul 2018 20:37:54 +0200 Subject: Added Bel port info to GUI --- gui/designwidget.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gui/designwidget.cc b/gui/designwidget.cc index c571e303..91ec5163 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -497,6 +497,14 @@ void DesignWidget::onItemSelectionChanged() addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->getConflictingBelCell(bel).c_str(ctx), ElementType::CELL); + QtProperty *belpinsItem = addSubGroup(topItem, "Ports"); + for (const auto &item : ctx->getBelPins(bel)) { + QtProperty *portInfoItem = addSubGroup(belpinsItem, ctx->portPinToId(item).c_str(ctx)); + addProperty(portInfoItem, QVariant::String, "Name", ctx->portPinToId(item).c_str(ctx)); + addProperty(portInfoItem, QVariant::Int, "Type", int(ctx->getBelPinType(bel, item))); + WireId wire = ctx->getBelPinWire(bel, item); + addProperty(portInfoItem, QVariant::String, "Wire", ctx->getWireName(wire).c_str(ctx), ElementType::WIRE); + } } else if (type == ElementType::WIRE) { WireId wire = ctx->getWireByName(c); QtProperty *topItem = addTopLevelProperty("Wire"); -- cgit v1.2.3 From 3788bd26e609f8488ba0f135731a46fb32afa843 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 23 Jul 2018 00:25:49 +0200 Subject: Bugfix in iCE40 chipdb.py Signed-off-by: Clifford Wolf --- ice40/chipdb.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 6e2bd2b5..8cb51e38 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -1027,9 +1027,6 @@ for wire in range(num_wires): info["uphill_bel"] = -1 info["uphill_pin"] = 0 - if num_bels_downhill == 0: - info["list_bel_pins"] = None - avg_x, avg_y = 0, 0 if wire in wire_xy: for x, y in wire_xy[wire]: -- cgit v1.2.3 From d0ed23d673013b4fc44f5e938bc74103d1268c13 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 23 Jul 2018 10:32:42 +0200 Subject: ecp5: Remove obsolete db entries, add Bel z-position Signed-off-by: David Shah --- ecp5/arch.h | 5 +---- ecp5/trellis_import.py | 16 +--------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/ecp5/arch.h b/ecp5/arch.h index cce9f09d..9d99da8c 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -56,6 +56,7 @@ NPNR_PACKED_STRUCT(struct BelWirePOD { NPNR_PACKED_STRUCT(struct BelInfoPOD { RelPtr name; BelType type; + int32_t z; int32_t num_bel_wires; RelPtr bel_wires; }); @@ -85,10 +86,6 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD { int32_t num_uphill, num_downhill; RelPtr pips_uphill, pips_downhill; - int32_t num_bels_downhill; - BelPortPOD bel_uphill; - RelPtr bels_downhill; - int32_t num_bel_pins; RelPtr bel_pins; }); diff --git a/ecp5/trellis_import.py b/ecp5/trellis_import.py index b0cbdd90..b5cd53f1 100755 --- a/ecp5/trellis_import.py +++ b/ecp5/trellis_import.py @@ -401,12 +401,6 @@ def write_database(dev_name, ddrg, endianness): for up in wire.arcsUphill: write_loc(up.rel, "rel_loc") bba.u32(up.id, "index") - if len(wire.belsDownhill) > 0: - bba.l("loc%d_wire%d_downbels" % (idx, wire_idx), "BelPortPOD") - for db in wire.belsDownhill: - write_loc(db.bel.rel, "rel_bel_loc") - bba.u32(db.bel.id, "bel_index") - bba.u32(portpins[ddrg.to_str(db.pin)], "port") if len(wire.belPins) > 0: bba.l("loc%d_wire%d_belpins" % (idx, wire_idx), "BelPortPOD") for bp in wire.belPins: @@ -421,15 +415,6 @@ def write_database(dev_name, ddrg, endianness): bba.u32(len(wire.arcsDownhill), "num_downhill") bba.r("loc%d_wire%d_uppips" % (idx, wire_idx) if len(wire.arcsUphill) > 0 else None, "pips_uphill") bba.r("loc%d_wire%d_downpips" % (idx, wire_idx) if len(wire.arcsDownhill) > 0 else None, "pips_downhill") - bba.u32(len(wire.belsDownhill), "num_bels_downhill") - write_loc(wire.belUphill.bel.rel, "uphill_bel_loc") - if wire.belUphill.pin != -1: - bba.u32(wire.belUphill.bel.id, "uphill_bel_idx") - bba.u32(portpins[ddrg.to_str(wire.belUphill.pin)], "uphill_bel_pin") - else: - bba.u32(0xFFFFFFFF, "bel_uphill.bel_index") - bba.u32(0, "bel_uphill.port") - bba.r("loc%d_wire%d_downbels" % (idx, wire_idx) if len(wire.belsDownhill) > 0 else None, "bels_downhill") bba.u32(len(wire.belPins), "num_bel_pins") bba.r("loc%d_wire%d_belpins" % (idx, wire_idx) if len(wire.belPins) > 0 else None, "bel_pins") @@ -447,6 +432,7 @@ def write_database(dev_name, ddrg, endianness): bel = loctype.bels[bel_idx] bba.s(ddrg.to_str(bel.name), "name") bba.u32(bel_types[ddrg.to_str(bel.type)], "type") + bba.u32(bel.z, "z") bba.u32(len(bel.wires), "num_bel_wires") bba.r("loc%d_bel%d_wires" % (idx, bel_idx), "bel_wires") -- cgit v1.2.3 From 54d1b8adcee3d1a89bf86b87be281e683d1cea93 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 23 Jul 2018 10:53:07 +0200 Subject: ecp5: Implement new Grid APIs Signed-off-by: David Shah --- ecp5/arch.cc | 36 ++++++++++++++++++++++++++++++++++++ ecp5/arch.h | 14 ++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 90950492..a817651e 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -344,6 +344,42 @@ std::vector Arch::getBelPins(BelId bel) const return ret; } +BelId Arch::getBelByLocation(Loc loc) const { + if (loc.x >= chip_info->width || loc.y >= chip_info->height) + return BelId(); + const LocationTypePOD &locI = chip_info->locations[chip_info->location_type[loc.y * chip_info->width + loc.x]]; + for (int i = 0; i < locI.num_bels; i++) { + if (locI.bel_data[i].z == loc.z) { + BelId bi; + bi.location.x = loc.x; + bi.location.y = loc.y; + bi.index = i; + return bi; + } + } + return BelId(); +} + +BelRange Arch::getBelsByTile(int x, int y) const { + BelRange br; + + int num_bels = 0; + + if (x < chip_info->width && y < chip_info->height) { + const LocationTypePOD &locI = chip_info->locations[chip_info->location_type[y * chip_info->width + x]]; + num_bels = locI.num_bels; + } + + br.b.cursor_tile = y * chip_info->width + x; + br.e.cursor_tile = y * chip_info->width + x; + br.b.cursor_index = 0; + br.e.cursor_index = num_bels - 1; + br.b.chip = chip_info; + br.e.chip = chip_info; + ++br.e; + return br; +} + // ----------------------------------------------------------------------- void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const diff --git a/ecp5/arch.h b/ecp5/arch.h index 9d99da8c..92240719 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -426,6 +426,20 @@ struct Arch : BaseCtx bel_to_cell[bel] = IdString(); } + Loc getBelLocation(BelId bel) const + { + Loc loc; + loc.x = bel.location.x; + loc.y = bel.location.y; + loc.z = locInfo(bel)->bel_data[bel.index].z; + return loc; + } + + BelId getBelByLocation(Loc loc) const; + BelRange getBelsByTile(int x, int y) const; + + bool getBelGlobalBuf(BelId bel) const { return false; } + bool checkBelAvail(BelId bel) const { NPNR_ASSERT(bel != BelId()); -- cgit v1.2.3 From 27c523682601e7b504c924a00bec98743fd3477c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 23 Jul 2018 12:19:54 +0200 Subject: Add getGridDimX(), getGridDimY(), getTileDimZ() API Signed-off-by: Clifford Wolf --- generic/arch.cc | 17 +++++++++++++++++ generic/arch.h | 9 ++++++++- ice40/arch.h | 6 ++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/generic/arch.cc b/generic/arch.cc index 6f2bd5df..4fc07613 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -78,7 +78,24 @@ void Arch::addBel(IdString name, IdString type, Loc loc, bool gb) bel_ids_by_type[type].push_back(name); bel_by_loc[loc] = name; + + if (bels_by_tile.size() <= loc.x) + bels_by_tile.resize(loc.x + 1); + + if (bels_by_tile[loc.x].size() <= loc.y) + bels_by_tile[loc.x].resize(loc.y + 1); + bels_by_tile[loc.x][loc.y].push_back(name); + + if (tileDimZ.size() <= loc.x) + tileDimZ.resize(loc.x + 1); + + if (tileDimZ[loc.x].size() <= loc.y) + tileDimZ[loc.x].resize(loc.y + 1); + + gridDimX = std::max(gridDimX, loc.x + 1); + gridDimY = std::max(gridDimY, loc.x + 1); + tileDimZ[loc.x][loc.y] = std::max(tileDimZ[loc.x][loc.y], loc.z + 1); } void Arch::addBelInput(IdString bel, IdString name, IdString wire) diff --git a/generic/arch.h b/generic/arch.h index a77dca68..5f0df988 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -87,11 +87,14 @@ struct Arch : BaseCtx std::unordered_map> bel_ids_by_type; std::unordered_map bel_by_loc; - std::unordered_map>> bels_by_tile; + std::vector>> bels_by_tile; std::unordered_map> decal_graphics; DecalXY frame_decalxy; + int gridDimX, gridDimY; + std::vector> tileDimZ; + float grid_distance_to_delay; void addWire(IdString name, int x, int y); @@ -131,6 +134,10 @@ struct Arch : BaseCtx BelType belTypeFromId(IdString id) const { return id; } PortPin portPinFromId(IdString id) const { return id; } + int getGridDimX() const { return gridDimX; } + int getGridDimY() const { return gridDimY; } + int getTileDimZ(int x, int y) const { return tileDimZ[x][y]; } + BelId getBelByName(IdString name) const; IdString getBelName(BelId bel) const; Loc getBelLocation(BelId bel) const; diff --git a/ice40/arch.h b/ice40/arch.h index 3ae6ce65..cd699a0c 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -377,6 +377,12 @@ struct Arch : BaseCtx // ------------------------------------------------- + int getGridDimX() const { return 34; } + int getGridDimY() const { return 34; } + int getTileDimZ(int, int) const { return 8; } + + // ------------------------------------------------- + BelId getBelByName(IdString name) const; IdString getBelName(BelId bel) const -- cgit v1.2.3 From a436facfd0a610c8b055e07d3a72e4122df677c6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 23 Jul 2018 12:44:26 +0200 Subject: Add fallback to estimateDelay() in getNetinfoRouteDelay() Signed-off-by: Clifford Wolf --- common/nextpnr.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 74747642..2c50c9a1 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -92,7 +92,7 @@ delay_t Context::getNetinfoRouteDelay(NetInfo *net_info, int user_idx) const { WireId src_wire = getNetinfoSourceWire(net_info); WireId cursor = getNetinfoSinkWire(net_info, user_idx); - delay_t delay = getWireDelay(src_wire).maxDelay(); + delay_t delay = 0; while (cursor != WireId() && cursor != src_wire) { auto it = net_info->wires.find(cursor); @@ -104,6 +104,11 @@ delay_t Context::getNetinfoRouteDelay(NetInfo *net_info, int user_idx) const cursor = getPipSrcWire(pip); } + if (cursor == src_wire) + delay += getWireDelay(src_wire).maxDelay(); + else + delay += estimateDelay(src_wire, cursor); + return delay; } -- cgit v1.2.3 From 38962d0f02720799d797326cc3d5ce906f853359 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 23 Jul 2018 12:45:31 +0200 Subject: clangformat Signed-off-by: Clifford Wolf --- common/router1.cc | 40 ++++++++++++++++++++++------------------ ecp5/arch.cc | 6 ++++-- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/common/router1.cc b/common/router1.cc index dbe3a003..fbf3c467 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -266,8 +266,8 @@ struct Router auto src_wire = ctx->getNetinfoSourceWire(net_info); if (src_wire == WireId()) - log_error("No wire found for port %s on source cell %s.\n", - net_info->driver.port.c_str(ctx), net_info->driver.cell->name.c_str(ctx)); + log_error("No wire found for port %s on source cell %s.\n", net_info->driver.port.c_str(ctx), + net_info->driver.cell->name.c_str(ctx)); if (ctx->debug) log(" Source wire: %s\n", ctx->getWireName(src_wire).c_str(ctx)); @@ -301,7 +301,8 @@ struct Router if (dst_wire == WireId()) log_error("No wire found for port %s on destination cell %s.\n", - net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); + net_info->users[user_idx].port.c_str(ctx), + net_info->users[user_idx].cell->name.c_str(ctx)); std::function register_existing_path = [ctx, net_info, &src_wires, ®ister_existing_path](WireId wire) -> delay_t { @@ -347,7 +348,8 @@ struct Router for (int user_idx : users_array) { if (ctx->debug) - log(" Route to: %s.%s.\n", net_info->users[user_idx].cell->name.c_str(ctx), net_info->users[user_idx].port.c_str(ctx)); + log(" Route to: %s.%s.\n", net_info->users[user_idx].cell->name.c_str(ctx), + net_info->users[user_idx].port.c_str(ctx)); auto dst_wire = ctx->getNetinfoSinkWire(net_info, user_idx); @@ -460,8 +462,8 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, std::unordered_mapgetNetinfoSourceWire(net_info); if (src_wire == WireId()) - log_error("No wire found for port %s on source cell %s.\n", - net_info->driver.port.c_str(ctx), net_info->driver.cell->name.c_str(ctx)); + log_error("No wire found for port %s on source cell %s.\n", net_info->driver.port.c_str(ctx), + net_info->driver.cell->name.c_str(ctx)); auto &net_cache = cache[net_name]; @@ -483,8 +485,8 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, std::unordered_mapgetNetinfoSinkWire(net_info, user_idx); if (dst_wire == WireId()) - log_error("No wire found for port %s on destination cell %s.\n", - net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); + log_error("No wire found for port %s on destination cell %s.\n", net_info->users[user_idx].port.c_str(ctx), + net_info->users[user_idx].cell->name.c_str(ctx)); if (user_idx == 0) job.slack = net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire); @@ -498,7 +500,8 @@ void addFullNetRouteJob(Context *ctx, IdString net_name, std::unordered_mapusers[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire); else - job.slack = std::min(job.slack, net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire)); + job.slack = std::min(job.slack, + net_info->users[user_idx].budget - ctx->estimateDelay(src_wire, dst_wire)); got_slack = true; break; } @@ -524,8 +527,8 @@ void addNetRouteJobs(Context *ctx, IdString net_name, std::unordered_mapgetNetinfoSourceWire(net_info); if (src_wire == WireId()) - log_error("No wire found for port %s on source cell %s.\n", - net_info->driver.port.c_str(ctx), net_info->driver.cell->name.c_str(ctx)); + log_error("No wire found for port %s on source cell %s.\n", net_info->driver.port.c_str(ctx), + net_info->driver.cell->name.c_str(ctx)); auto &net_cache = cache[net_name]; @@ -539,8 +542,8 @@ void addNetRouteJobs(Context *ctx, IdString net_name, std::unordered_mapgetNetinfoSinkWire(net_info, user_idx); if (dst_wire == WireId()) - log_error("No wire found for port %s on destination cell %s.\n", - net_info->users[user_idx].port.c_str(ctx), net_info->users[user_idx].cell->name.c_str(ctx)); + log_error("No wire found for port %s on destination cell %s.\n", net_info->users[user_idx].port.c_str(ctx), + net_info->users[user_idx].cell->name.c_str(ctx)); WireId cursor = dst_wire; while (src_wire != cursor) { @@ -772,16 +775,17 @@ bool router1(Context *ctx) } if (ctx->verbose) log_info(" arc %s -> %s has %f ns slack (delay %f, budget %f)\n", - ctx->getWireName(ctx->getNetinfoSourceWire(net_info)).c_str(ctx), - ctx->getWireName(ctx->getNetinfoSinkWire(net_info, user_idx)).c_str(ctx), - ctx->getDelayNS(arc_slack), ctx->getDelayNS(arc_delay), ctx->getDelayNS(arc_budget)); + ctx->getWireName(ctx->getNetinfoSourceWire(net_info)).c_str(ctx), + ctx->getWireName(ctx->getNetinfoSinkWire(net_info, user_idx)).c_str(ctx), + ctx->getDelayNS(arc_slack), ctx->getDelayNS(arc_delay), + ctx->getDelayNS(arc_budget)); tns += ctx->getDelayNS(arc_slack); tns_arc_count++; } } } - log_info("final tns with respect to arc budgets: %f ns (%d nets, %d arcs)\n", - tns, tns_net_count, tns_arc_count); + log_info("final tns with respect to arc budgets: %f ns (%d nets, %d arcs)\n", tns, tns_net_count, + tns_arc_count); } NPNR_ASSERT(jobQueue.empty()); diff --git a/ecp5/arch.cc b/ecp5/arch.cc index a817651e..7ac56378 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -344,7 +344,8 @@ std::vector Arch::getBelPins(BelId bel) const return ret; } -BelId Arch::getBelByLocation(Loc loc) const { +BelId Arch::getBelByLocation(Loc loc) const +{ if (loc.x >= chip_info->width || loc.y >= chip_info->height) return BelId(); const LocationTypePOD &locI = chip_info->locations[chip_info->location_type[loc.y * chip_info->width + loc.x]]; @@ -360,7 +361,8 @@ BelId Arch::getBelByLocation(Loc loc) const { return BelId(); } -BelRange Arch::getBelsByTile(int x, int y) const { +BelRange Arch::getBelsByTile(int x, int y) const +{ BelRange br; int num_bels = 0; -- cgit v1.2.3 From a3864c2936dbb47af431e5c1b3dfa08f10666936 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 23 Jul 2018 13:02:37 +0200 Subject: ecp5: Add Add getGridDimX(), getGridDimY(), getTileDimZ() Signed-off-by: David Shah --- ecp5/arch.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ecp5/arch.h b/ecp5/arch.h index 92240719..f53817fd 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -388,7 +388,12 @@ struct Arch : BaseCtx IdString portPinToId(PortPin type) const; PortPin portPinFromId(IdString id) const; + // ------------------------------------------------- + int getGridDimX() const { return chip_info->width; }; + int getGridDimY() const { return chip_info->height; }; + int getTileDimZ(int,int) const { return 4; }; + // ------------------------------------------------- BelId getBelByName(IdString name) const; -- cgit v1.2.3 From bfa1137fe03a62bf4bcef1d039d520116cc5a13a Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 23 Jul 2018 13:02:57 +0200 Subject: clangformat Signed-off-by: David Shah --- ecp5/arch.h | 4 ++-- ice40/bitstream.cc | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ecp5/arch.h b/ecp5/arch.h index f53817fd..aada2079 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -392,8 +392,8 @@ struct Arch : BaseCtx int getGridDimX() const { return chip_info->width; }; int getGridDimY() const { return chip_info->height; }; - int getTileDimZ(int,int) const { return 4; }; - + int getTileDimZ(int, int) const { return 4; }; + // ------------------------------------------------- BelId getBelByName(IdString name) const; diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 5559c2ce..9ac8e857 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -482,8 +482,9 @@ void write_asc(const Context *ctx, std::ostream &out) set_config(ti, config.at(y).at(x), "Cascade.IPCON_LC0" + std::to_string(lc_idx) + "_inmux02_5", true); else - set_config(ti, config.at(y).at(x), "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) + - "_LC0" + std::to_string(lc_idx) + "_inmux02_5", + set_config(ti, config.at(y).at(x), + "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) + "_LC0" + + std::to_string(lc_idx) + "_inmux02_5", true); } } -- cgit v1.2.3 From 90fe002a36a9b90cd6d003d34398242a5d5affb6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 23 Jul 2018 13:16:27 +0200 Subject: Remove getBelsByType() API Signed-off-by: Clifford Wolf --- ecp5/arch.h | 14 -------------- generic/arch.cc | 10 ---------- generic/arch.h | 2 -- ice40/arch.h | 14 -------------- 4 files changed, 40 deletions(-) diff --git a/ecp5/arch.h b/ecp5/arch.h index aada2079..b3ef5195 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -482,20 +482,6 @@ struct Arch : BaseCtx return range; } - BelRange getBelsByType(BelType type) const - { - BelRange range; -// FIXME -#if 0 - if (type == "TYPE_A") { - range.b.cursor = bels_type_a_begin; - range.e.cursor = bels_type_a_end; - } - ... -#endif - return range; - } - BelRange getBelsAtSameTile(BelId bel) const; BelType getBelType(BelId bel) const diff --git a/generic/arch.cc b/generic/arch.cc index 4fc07613..0fff2e4c 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -75,8 +75,6 @@ void Arch::addBel(IdString name, IdString type, Loc loc, bool gb) bi.gb = gb; bel_ids.push_back(name); - bel_ids_by_type[type].push_back(name); - bel_by_loc[loc] = name; if (bels_by_tile.size() <= loc.x) @@ -225,14 +223,6 @@ IdString Arch::getConflictingBelCell(BelId bel) const { return bels.at(bel).boun const std::vector &Arch::getBels() const { return bel_ids; } -const std::vector &Arch::getBelsByType(BelType type) const -{ - static std::vector empty_list; - if (bel_ids_by_type.count(type)) - return bel_ids_by_type.at(type); - return empty_list; -} - BelType Arch::getBelType(BelId bel) const { return bels.at(bel).type; } WireId Arch::getBelPinWire(BelId bel, PortPin pin) const { return bels.at(bel).pins.at(pin).wire; } diff --git a/generic/arch.h b/generic/arch.h index 5f0df988..61e6b033 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -84,7 +84,6 @@ struct Arch : BaseCtx std::unordered_map groups; std::vector bel_ids, wire_ids, pip_ids; - std::unordered_map> bel_ids_by_type; std::unordered_map bel_by_loc; std::vector>> bels_by_tile; @@ -151,7 +150,6 @@ struct Arch : BaseCtx IdString getBoundBelCell(BelId bel) const; IdString getConflictingBelCell(BelId bel) const; const std::vector &getBels() const; - const std::vector &getBelsByType(BelType type) const; BelType getBelType(BelId bel) const; WireId getBelPinWire(BelId bel, PortPin pin) const; PortType getBelPinType(BelId bel, PortPin pin) const; diff --git a/ice40/arch.h b/ice40/arch.h index cd699a0c..d4d71cfc 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -439,20 +439,6 @@ struct Arch : BaseCtx return range; } - BelRange getBelsByType(BelType type) const - { - BelRange range; -// FIXME -#if 0 - if (type == "TYPE_A") { - range.b.cursor = bels_type_a_begin; - range.e.cursor = bels_type_a_end; - } - ... -#endif - return range; - } - Loc getBelLocation(BelId bel) const { Loc loc; -- cgit v1.2.3 From e647604e2a584917ad2fc9acfe838a1395c613c2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 23 Jul 2018 14:03:23 +0200 Subject: Add Context::archcheck() and "nextpnr-ice40 --test" Signed-off-by: Clifford Wolf --- common/archcheck.cc | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++ common/log.h | 6 +-- common/nextpnr.h | 1 + ice40/chipdb.py | 94 +++++++++++++++++++-------------- ice40/main.cc | 6 +++ 5 files changed, 208 insertions(+), 45 deletions(-) create mode 100644 common/archcheck.cc diff --git a/common/archcheck.cc b/common/archcheck.cc new file mode 100644 index 00000000..5c4ef26c --- /dev/null +++ b/common/archcheck.cc @@ -0,0 +1,146 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf + * + * 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 "nextpnr.h" +#include "log.h" + +#if 0 +#define dbg(...) log(__VA_ARGS__) +#else +#define dbg(...) +#endif + +USING_NEXTPNR_NAMESPACE + +namespace { + +void archcheck_names(const Context *ctx) +{ + log_info("Checking entity names.\n"); + + log_info("Checking bel names..\n"); + for (BelId bel : ctx->getBels()) { + IdString name = ctx->getBelName(bel); + BelId bel2 = ctx->getBelByName(name); + log_assert(bel == bel2); + } + + log_info("Checking wire names..\n"); + for (WireId wire : ctx->getWires()) { + IdString name = ctx->getWireName(wire); + WireId wire2 = ctx->getWireByName(name); + log_assert(wire == wire2); + } + + log_info("Checking pip names..\n"); + for (PipId pip : ctx->getPips()) { + IdString name = ctx->getPipName(pip); + PipId pip2 = ctx->getPipByName(name); + log_assert(pip == pip2); + } + + log_break(); +} + +void archcheck_locs(const Context *ctx) +{ + log_info("Checking location data.\n"); + + log_info("Checking all bels..\n"); + for (BelId bel : ctx->getBels()) { + log_assert(bel != BelId()); + dbg("> %s\n", ctx->getBelName(bel).c_str(ctx)); + + Loc loc = ctx->getBelLocation(bel); + dbg(" ... %d %d %d\n", loc.x, loc.y, loc.z); + + log_assert(0 <= loc.x); + log_assert(0 <= loc.y); + log_assert(0 <= loc.z); + log_assert(loc.x < ctx->getGridDimX()); + log_assert(loc.y < ctx->getGridDimY()); + log_assert(loc.z < ctx->getTileDimZ(loc.x, loc.y)); + + BelId bel2 = ctx->getBelByLocation(loc); + dbg(" ... %s\n", ctx->getBelName(bel2).c_str(ctx)); + log_assert(bel == bel2); + } + + log_info("Checking all locations..\n"); + for (int x = 0; x < ctx->getGridDimX(); x++) + for (int y = 0; y < ctx->getGridDimY(); y++) + { + dbg("> %d %d\n", x, y); + std::unordered_set usedz; + + for (int z = 0; z < ctx->getTileDimZ(x, y); z++) { + BelId bel = ctx->getBelByLocation(Loc(x, y, z)); + if (bel == BelId()) + continue; + Loc loc = ctx->getBelLocation(bel); + dbg(" + %d %s\n", z, ctx->getBelName(bel).c_str(ctx)); + log_assert(x == loc.x); + log_assert(y == loc.y); + log_assert(z == loc.z); + usedz.insert(z); + } + + for (BelId bel : ctx->getBelsByTile(x, y)) { + Loc loc = ctx->getBelLocation(bel); + dbg(" - %d %s\n", loc.z, ctx->getBelName(bel).c_str(ctx)); + log_assert(x == loc.x); + log_assert(y == loc.y); + log_assert(usedz.count(loc.z)); + usedz.erase(loc.z); + } + + log_assert(usedz.empty()); + } + + log_break(); +} + +void archcheck_conn(const Context *ctx) +{ +#if 0 + log_info("Checking connectivity data.\n"); + + log_info("Checking all wires..\n"); + for (WireId wire : ctx->getWires()) + { + ... + } +#endif +} + +} // namespace + +NEXTPNR_NAMESPACE_BEGIN + +void Context::archcheck() const +{ + log_info("Running architecture database integrity check.\n"); + log_break(); + + archcheck_names(this); + archcheck_locs(this); + archcheck_conn(this); +} + +NEXTPNR_NAMESPACE_END diff --git a/common/log.h b/common/log.h index c3607e39..35450311 100644 --- a/common/log.h +++ b/common/log.h @@ -69,17 +69,13 @@ NPNR_NORETURN void log_cmd_error(const char *format, ...) NPNR_ATTRIBUTE(format( void log_break(); void log_flush(); -#ifndef NDEBUG static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) { if (!cond) log_error("Assert `%s' failed in %s:%d.\n", expr, file, line); } #define log_assert(_assert_expr_) \ - YOSYS_NAMESPACE_PREFIX log_assert_worker(_assert_expr_, #_assert_expr_, __FILE__, __LINE__) -#else -#define log_assert(_assert_expr_) -#endif + NEXTPNR_NAMESPACE_PREFIX log_assert_worker(_assert_expr_, #_assert_expr_, __FILE__, __LINE__) #define log_abort() log_error("Abort in %s:%d.\n", __FILE__, __LINE__) #define log_ping() log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__) diff --git a/common/nextpnr.h b/common/nextpnr.h index bb40e1b6..021772fe 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -472,6 +472,7 @@ struct Context : Arch, DeterministicRNG uint32_t checksum() const; void check() const; + void archcheck() const; }; NEXTPNR_NAMESPACE_END diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 8cb51e38..0e8e3ba7 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -373,8 +373,12 @@ with open(args.filename, "r") as f: if line[0] == ".extra_cell": if len(line) >= 5: mode = ("extra_cell", (line[4], int(line[1]), int(line[2]), int(line[3]))) - else: + elif line[3] == "WARMBOOT": + mode = ("extra_cell", (line[3], int(line[1]), int(line[2]), 0)) + elif line[3] == "PLL": mode = ("extra_cell", (line[3], int(line[1]), int(line[2]), 3)) + else: + assert 0 extra_cells[mode[1]] = [] continue @@ -564,11 +568,14 @@ def add_bel_ram(x, y): add_bel_input(bel, wire_names[(x, y1, "ram/RCLKE")], "RCLKE") add_bel_input(bel, wire_names[(x, y1, "ram/RE")], "RE") -def add_bel_gb(x, y, g): +def add_bel_gb(xy, x, y, g): + if xy[0] != x or xy[1] != y: + return + bel = len(bel_name) bel_name.append("X%d/Y%d/gb" % (x, y)) bel_type.append("SB_GB") - bel_pos.append((x, y, 0)) + bel_pos.append((x, y, 2)) bel_wires.append(list()) add_bel_input(bel, wire_names[(x, y, "fabout")], "USER_SIGNAL_TO_GLOBAL_BUFFER") @@ -605,51 +612,58 @@ for tile_xy, tile_type in sorted(tiles.items()): if tile_type == "logic": for i in range(8): add_bel_lc(tile_xy[0], tile_xy[1], i) + if tile_type == "io": for i in range(2): add_bel_io(tile_xy[0], tile_xy[1], i) + + if dev_name == "1k": + add_bel_gb(tile_xy, 7, 0, 0) + add_bel_gb(tile_xy, 7, 17, 1) + add_bel_gb(tile_xy, 13, 9, 2) + add_bel_gb(tile_xy, 0, 9, 3) + add_bel_gb(tile_xy, 6, 17, 4) + add_bel_gb(tile_xy, 6, 0, 5) + add_bel_gb(tile_xy, 0, 8, 6) + add_bel_gb(tile_xy, 13, 8, 7) + elif dev_name == "5k": + add_bel_gb(tile_xy, 13, 0, 0) + add_bel_gb(tile_xy, 13, 31, 1) + add_bel_gb(tile_xy, 19, 31, 2) + add_bel_gb(tile_xy, 6, 31, 3) + add_bel_gb(tile_xy, 12, 31, 4) + add_bel_gb(tile_xy, 12, 0, 5) + add_bel_gb(tile_xy, 6, 0, 6) + add_bel_gb(tile_xy, 19, 0, 7) + elif dev_name == "8k": + add_bel_gb(tile_xy, 33, 16, 7) + add_bel_gb(tile_xy, 0, 16, 6) + add_bel_gb(tile_xy, 17, 33, 1) + add_bel_gb(tile_xy, 17, 0, 0) + add_bel_gb(tile_xy, 0, 17, 3) + add_bel_gb(tile_xy, 33, 17, 2) + add_bel_gb(tile_xy, 16, 0, 5) + add_bel_gb(tile_xy, 16, 33, 4) + elif dev_name == "384": + add_bel_gb(tile_xy, 7, 4, 7) + add_bel_gb(tile_xy, 0, 4, 6) + add_bel_gb(tile_xy, 4, 9, 1) + add_bel_gb(tile_xy, 4, 0, 0) + add_bel_gb(tile_xy, 0, 5, 3) + add_bel_gb(tile_xy, 7, 5, 2) + add_bel_gb(tile_xy, 3, 0, 5) + add_bel_gb(tile_xy, 3, 9, 4) + if tile_type == "ramb": add_bel_ram(tile_xy[0], tile_xy[1]) -if dev_name == "1k": - add_bel_gb( 7, 0, 0) - add_bel_gb( 7, 17, 1) - add_bel_gb(13, 9, 2) - add_bel_gb( 0, 9, 3) - add_bel_gb( 6, 17, 4) - add_bel_gb( 6, 0, 5) - add_bel_gb( 0, 8, 6) - add_bel_gb(13, 8, 7) -elif dev_name == "5k": - add_bel_gb(13, 0, 0) - add_bel_gb(13, 31, 1) - add_bel_gb(19, 31, 2) - add_bel_gb( 6, 31, 3) - add_bel_gb(12, 31, 4) - add_bel_gb(12, 0, 5) - add_bel_gb( 6, 0, 6) - add_bel_gb(19, 0, 7) -elif dev_name == "8k": - add_bel_gb(33, 16, 7) - add_bel_gb( 0, 16, 6) - add_bel_gb(17, 33, 1) - add_bel_gb(17, 0, 0) - add_bel_gb( 0, 17, 3) - add_bel_gb(33, 17, 2) - add_bel_gb(16, 0, 5) - add_bel_gb(16, 33, 4) -elif dev_name == "384": - add_bel_gb( 7, 4, 7) - add_bel_gb( 0, 4, 6) - add_bel_gb( 4, 9, 1) - add_bel_gb( 4, 0, 0) - add_bel_gb( 0, 5, 3) - add_bel_gb( 7, 5, 2) - add_bel_gb( 3, 0, 5) - add_bel_gb( 3, 9, 4) + for ec in sorted(extra_cells.keys()): + if ec[1] == tile_xy[0] and ec[2] == tile_xy[1]: + add_bel_ec(ec) for ec in sorted(extra_cells.keys()): - add_bel_ec(ec) + if ec[1] == 0 and ec[2] == 0: + add_bel_ec(ec) class BinaryBlobAssembler: def __init__(self, cname, endianness, nodebug = False): diff --git a/ice40/main.cc b/ice40/main.cc index 24b49184..4de05d00 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -107,6 +107,7 @@ int main(int argc, char *argv[]) options.add_options()("seed", po::value(), "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()("test", "check architecture database integrity"); #ifdef ICE40_HX1K_ONLY options.add_options()("hx1k", "set device type to iCE40HX1K"); #else @@ -315,6 +316,9 @@ int main(int argc, char *argv[]) std::cout << "\n"; } + if (vm.count("test")) + ctx->archcheck(); + if (vm.count("tmfuzz")) { std::vector src_wires, dst_wires; @@ -360,8 +364,10 @@ int main(int argc, char *argv[]) ctx->chip_info->wire_data[dst.index].type); } } + if (vm.count("freq")) ctx->target_freq = vm["freq"].as() * 1e6; + ctx->timing_driven = true; if (vm.count("no-tmdriv")) ctx->timing_driven = false; -- cgit v1.2.3