From bf42e525cb7ab6ae071b16dfeca55194878be69c Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 8 Aug 2018 14:37:59 +0200 Subject: [PATCH] Arch API: New specification for timing port classes Signed-off-by: David Shah --- common/nextpnr.h | 2 +- ecp5/arch.cc | 7 ++--- ecp5/arch.h | 6 ++--- generic/arch.cc | 8 +++--- generic/arch.h | 4 +-- ice40/arch.cc | 68 +++++++++++++++++++++++++++++++++++------------- ice40/arch.h | 6 ++--- 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