aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/nextpnr.h2
-rw-r--r--ecp5/arch.cc7
-rw-r--r--ecp5/arch.h6
-rw-r--r--generic/arch.cc8
-rw-r--r--generic/arch.h4
-rw-r--r--ice40/arch.cc68
-rw-r--r--ice40/arch.h6
7 files changed, 66 insertions, 35 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index d4925a16..938f4f95 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -301,7 +301,7 @@ enum TimingPortClass
TMG_COMB_OUTPUT, // Combinational output, no paths start here
TMG_STARTPOINT, // Unclocked primary startpoint, such as an IO cell output
TMG_ENDPOINT, // Unclocked primary endpoint, such as an IO cell input
- TMG_ASYNC, // Asynchronous to all clocks, "don't care", and should be ignored (false path) for analysis
+ TMG_IGNORE, // Asynchronous to all clocks, "don't care", and should be ignored (false path) for analysis
};
struct DeterministicRNG
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index de3abd44..12707a03 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -495,9 +495,10 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
return false;
}
-IdString Arch::getPortClock(const CellInfo *cell, IdString port) const { return IdString(); }
-
-bool Arch::isClockPort(const CellInfo *cell, IdString port) const { return false; }
+TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const
+{
+ return TMG_IGNORE;
+}
bool Arch::isIOCell(const CellInfo *cell) const { return cell->type == id("TRELLIS_IO"); }
diff --git a/ecp5/arch.h b/ecp5/arch.h
index fd8d0a13..7bbb9da5 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -827,10 +827,8 @@ struct Arch : BaseCtx
// Get the delay through a cell from one port to another, returning false
// if no path exists
bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
- // Get the associated clock to a port, or empty if the port is combinational
- IdString getPortClock(const CellInfo *cell, IdString port) const;
- // Return true if a port is a clock
- bool isClockPort(const CellInfo *cell, IdString port) const;
+ // Get the port class, also setting clockPort if applicable
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const;
// Return true if a port is a net
bool isGlobalNet(const NetInfo *net) const;
// Return true if a cell is an IO
diff --git a/generic/arch.cc b/generic/arch.cc
index 0fa93da8..25e4d08c 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -435,9 +435,11 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
return false;
}
-IdString Arch::getPortClock(const CellInfo *cell, IdString port) const { return IdString(); }
-
-bool Arch::isClockPort(const CellInfo *cell, IdString port) const { return false; }
+// Get the port class, also setting clockPort if applicable
+TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const
+{
+ return TMG_IGNORE;
+}
bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; }
bool Arch::isBelLocationValid(BelId bel) const { return true; }
diff --git a/generic/arch.h b/generic/arch.h
index e7010885..fb4f3660 100644
--- a/generic/arch.h
+++ b/generic/arch.h
@@ -213,8 +213,8 @@ struct Arch : BaseCtx
DecalXY getGroupDecal(GroupId group) const;
bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
- IdString getPortClock(const CellInfo *cell, IdString port) const;
- bool isClockPort(const CellInfo *cell, IdString port) const;
+ // Get the port class, also setting clockPort if applicable
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const;
// Return true if a cell is an IO
bool isIOCell(const CellInfo *cell) const;
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 16104033..0f81bfea 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -27,6 +27,7 @@
#include "placer1.h"
#include "router1.h"
#include "util.h"
+
NEXTPNR_NAMESPACE_BEGIN
// -----------------------------------------------------------------------
@@ -106,7 +107,9 @@ BelType Arch::belTypeFromId(IdString type) const
void IdString::initialize_arch(const BaseCtx *ctx)
{
#define X(t) initialize_add(ctx, #t, PIN_##t);
+
#include "portpins.inc"
+
#undef X
}
@@ -888,27 +891,56 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
return false;
}
-IdString Arch::getPortClock(const CellInfo *cell, IdString port) const
+// Get the port class, also setting clockPort to associated clock if applicable
+TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const
{
- if (cell->type == id_icestorm_lc && cell->lcInfo.dffEnable) {
- if (port != id_lo && port != id_cin && port != id_cout)
- return id_clk;
- } else if (cell->type == id_icestorm_ram) {
- if (port.str(this)[0] == 'R')
- return id_rclk;
+ if (cell->type == id_icestorm_lc) {
+ if (port == id_clk)
+ return TMG_CLOCK_INPUT;
+ if (port == id_cin)
+ return TMG_COMB_INPUT;
+ if (port == id_cout || port == id_lo)
+ return TMG_COMB_OUTPUT;
+ if (cell->lcInfo.dffEnable) {
+ clockPort = id_clk;
+ if (port == id_o)
+ return TMG_REGISTER_OUTPUT;
+ else
+ return TMG_REGISTER_INPUT;
+ } else {
+ if (port == id_o)
+ return TMG_COMB_OUTPUT;
+ else
+ return TMG_COMB_INPUT;
+ }
+ } else if (cell->type == id_icestorm_ram || cell->type == id("ICESTORM_DSP") ||
+ cell->type == id("ICESTORM_SPRAM")) {
+ if (port == id_clk)
+ return TMG_CLOCK_INPUT;
+ else if (cell->ports.at(port).type == PORT_OUT)
+ return TMG_REGISTER_OUTPUT;
else
- return id_wclk;
+ return TMG_REGISTER_INPUT;
+ } else if (cell->type == id_sb_io) {
+ 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_IGNORE;
+ } else if (cell->type == id("ICESTORM_PLL")) {
+ if (port == id("PLLOUT_A") || port == id("PLLOUT_B"))
+ return TMG_GEN_CLOCK;
+ return TMG_IGNORE;
+ } else if (cell->type == id("ICESTORM_LFOSC")) {
+ if (port == id("CLKLF"))
+ return TMG_GEN_CLOCK;
+ return TMG_IGNORE;
+ } else if (cell->type == id("ICESTORM_HFOSC")) {
+ if (port == id("CLKHF"))
+ return TMG_GEN_CLOCK;
+ return TMG_IGNORE;
}
- return IdString();
-}
-
-bool Arch::isClockPort(const CellInfo *cell, IdString port) const
-{
- if (cell->type == id("ICESTORM_LC") && port == id("CLK"))
- return true;
- if (cell->type == id("ICESTORM_RAM") && (port == id("RCLK") || (port == id("WCLK"))))
- return true;
- return false;
+ return TMG_IGNORE;
}
bool Arch::isGlobalNet(const NetInfo *net) const
diff --git a/ice40/arch.h b/ice40/arch.h
index a5be7e33..7cc8495d 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -788,10 +788,8 @@ struct Arch : BaseCtx
// Get the delay through a cell from one port to another, returning false
// if no path exists
bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
- // Get the associated clock to a port, or empty if the port is combinational
- IdString getPortClock(const CellInfo *cell, IdString port) const;
- // Return true if a port is a clock
- bool isClockPort(const CellInfo *cell, IdString port) const;
+ // Get the port class, also setting clockDomain if applicable
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockDomain) const;
// Return true if a port is a net
bool isGlobalNet(const NetInfo *net) const;
// Return true if a cell is an IO