diff options
-rw-r--r-- | common/timing.cc | 32 | ||||
-rw-r--r-- | gui/ecp5/mainwindow.cc | 12 | ||||
-rw-r--r-- | gui/ecp5/mainwindow.h | 1 | ||||
-rw-r--r-- | gui/generic/mainwindow.cc | 3 | ||||
-rw-r--r-- | ice40/arch.cc | 4 |
5 files changed, 33 insertions, 19 deletions
diff --git a/common/timing.cc b/common/timing.cc index 841f8e92..15a4d126 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -84,20 +84,20 @@ struct Timing input_ports.push_back(port.first); } - bool is_io = ctx->isIOCell(cell.second.get()); for (auto o : output_ports) { - IdString clock_domain = ctx->getPortClock(cell.second.get(), o->name); + IdString clockPort; + TimingPortClass portClass = ctx->getPortTimingClass(cell.second.get(), o->name, clockPort); // If output port is influenced by a clock (e.g. FF output) // then add it to the ordering as a timing start-point - if (clock_domain != IdString()) { + if (portClass == TMG_REGISTER_OUTPUT) { DelayInfo clkToQ; - ctx->getCellDelay(cell.second.get(), clock_domain, o->name, clkToQ); + ctx->getCellDelay(cell.second.get(), clockPort, o->name, clkToQ); topographical_order.emplace_back(o->net); net_data.emplace(o->net, TimingData{clkToQ.maxDelay()}); } else { // Also add I/O cells too // TODO(eddieh): More generic way of detecting PLLs - if (is_io || cell.second->type == ctx->id("ICESTORM_PLL")) { + if (portClass == TMG_STARTPOINT || portClass == TMG_IGNORE) { // IGNORE: ???? topographical_order.emplace_back(o->net); net_data.emplace(o->net, TimingData{}); } @@ -137,12 +137,13 @@ struct Timing DelayInfo clkToQ; for (auto &usr : net->users) { - auto clock_domain = ctx->getPortClock(usr.cell, usr.port); + IdString clockPort; + TimingPortClass portClass = ctx->getPortTimingClass(usr.cell, usr.port, clockPort); for (auto &port : usr.cell->ports) { if (port.second.type != PORT_OUT || !port.second.net) continue; // Skip if this is a clocked output (but allow non-clocked ones) - if (clock_domain != IdString() && ctx->getCellDelay(usr.cell, clock_domain, port.first, clkToQ)) + if (portClass == TMG_REGISTER_OUTPUT || portClass == TMG_ENDPOINT || portClass == TMG_IGNORE) continue; DelayInfo comb_delay; bool is_path = ctx->getCellDelay(usr.cell, usr.port, port.first, comb_delay); @@ -173,7 +174,9 @@ struct Timing const auto net_length_plus_one = nd.max_path_length + 1; nd.min_remaining_budget = clk_period; for (auto &usr : net->users) { - if (ctx->getPortClock(usr.cell, usr.port) != IdString()) { + IdString clockPort; + TimingPortClass portClass = ctx->getPortTimingClass(usr.cell, usr.port, clockPort); + if (portClass == TMG_REGISTER_INPUT || portClass == TMG_ENDPOINT || portClass == TMG_IGNORE) { } else { auto net_delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t(); auto budget_override = ctx->getBudgetOverride(net, usr, net_delay); @@ -212,7 +215,9 @@ struct Timing for (auto &usr : net->users) { auto net_delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t(); auto budget_override = ctx->getBudgetOverride(net, usr, net_delay); - if (ctx->getPortClock(usr.cell, usr.port) != IdString()) { + IdString associatedClock; + TimingPortClass portClass = ctx->getPortTimingClass(usr.cell, usr.port, associatedClock); + if (portClass == TMG_REGISTER_INPUT || portClass == TMG_ENDPOINT) { const auto net_arrival = nd.max_arrival; auto path_budget = clk_period - (net_arrival + net_delay); if (update) { @@ -267,7 +272,10 @@ struct Timing if (!is_path) continue; // If input port is influenced by a clock, skip - if (ctx->getPortClock(crit_net->driver.cell, port.first) != IdString()) + IdString portClock; + TimingPortClass portClass = ctx->getPortTimingClass(crit_net->driver.cell, port.first, portClock); + if (portClass == TMG_REGISTER_INPUT || portClass == TMG_CLOCK_INPUT || portClass == TMG_ENDPOINT || + portClass == TMG_IGNORE) continue; // And find the fanin net with the latest arrival time @@ -373,7 +381,9 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_path) auto &front = crit_path.front(); auto &front_port = front->cell->ports.at(front->port); auto &front_driver = front_port.net->driver; - auto last_port = ctx->getPortClock(front_driver.cell, front_driver.port); + + IdString last_port; + ctx->getPortTimingClass(front_driver.cell, front_driver.port, last_port); for (auto sink : crit_path) { auto sink_cell = sink->cell; auto &port = sink_cell->ports.at(sink->port); diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index efaad364..e5a5f1ba 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -29,7 +29,8 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } NEXTPNR_NAMESPACE_BEGIN
-MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent) : BaseMainWindow(std::move(context), args, parent)
+MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent)
+ : BaseMainWindow(std::move(context), args, parent)
{
initMainResource();
@@ -50,7 +51,8 @@ void MainWindow::newContext(Context *ctx) setWindowTitle(title.c_str());
}
-void MainWindow::createMenu() {
+void MainWindow::createMenu()
+{
// Add arch specific actions
actionLoadBase = new QAction("Open Base Config", this);
actionLoadBase->setIcon(QIcon(":/icons/resources/open_base.png"));
@@ -71,7 +73,7 @@ void MainWindow::createMenu() { menuDesign->addSeparator();
menuDesign->addAction(actionLoadBase);
- menuDesign->addAction(actionSaveConfig);
+ menuDesign->addAction(actionSaveConfig);
}
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }
@@ -96,8 +98,8 @@ static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip) return packages;
}
-
-void MainWindow::new_proj() {
+void MainWindow::new_proj()
+{
QMap<QString, int> arch;
arch.insert("Lattice ECP5 25K", ArchArgs::LFE5U_25F);
arch.insert("Lattice ECP5 45K", ArchArgs::LFE5U_45F);
diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index d1d5a5a2..9460913c 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -47,6 +47,7 @@ class MainWindow : public BaseMainWindow void newContext(Context *ctx);
void open_base();
void save_config();
+
private:
QAction *actionLoadBase;
QAction *actionSaveConfig;
diff --git a/gui/generic/mainwindow.cc b/gui/generic/mainwindow.cc index 050c0fb8..01eeb4ef 100644 --- a/gui/generic/mainwindow.cc +++ b/gui/generic/mainwindow.cc @@ -23,7 +23,8 @@ static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } NEXTPNR_NAMESPACE_BEGIN
-MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent) : BaseMainWindow(std::move(context), args, parent)
+MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent)
+ : BaseMainWindow(std::move(context), args, parent)
{
initMainResource();
diff --git a/ice40/arch.cc b/ice40/arch.cc index 0f81bfea..fddfabfd 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -915,7 +915,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id } } else if (cell->type == id_icestorm_ram || cell->type == id("ICESTORM_DSP") || cell->type == id("ICESTORM_SPRAM")) { - if (port == id_clk) + if (port == id_clk || port == id_rclk || port == id_wclk) return TMG_CLOCK_INPUT; else if (cell->ports.at(port).type == PORT_OUT) return TMG_REGISTER_OUTPUT; @@ -925,7 +925,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id if (port == id("D_IN_0") || port == id("D_IN_1")) return TMG_STARTPOINT; if (port == id("D_OUT_0") || port == id("D_OUT_1")) - return TMG_STARTPOINT; + return TMG_ENDPOINT; return TMG_IGNORE; } else if (cell->type == id("ICESTORM_PLL")) { if (port == id("PLLOUT_A") || port == id("PLLOUT_B")) |