aboutsummaryrefslogtreecommitdiffstats
path: root/ice40
diff options
context:
space:
mode:
Diffstat (limited to 'ice40')
-rw-r--r--ice40/arch.cc101
-rw-r--r--ice40/arch.h20
2 files changed, 89 insertions, 32 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc
index fcc9d798..5e56ea10 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
}
@@ -291,7 +294,8 @@ BelId Arch::getBelByLocation(Loc loc) const
BelRange Arch::getBelsByTile(int x, int y) const
{
- // In iCE40 chipdb bels at the same tile are consecutive and dense z ordinates are used
+ // In iCE40 chipdb bels at the same tile are consecutive and dense z ordinates
+ // are used
BelRange br;
br.b.cursor = Arch::getBelByLocation(Loc(x, y, 0)).index;
@@ -645,23 +649,27 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
auto sink_loc = getBelLocation(sink.cell->bel);
if (driver_loc.y == sink_loc.y)
budget = 0;
- else switch (args.type) {
+ else
+ switch (args.type) {
#ifndef ICE40_HX1K_ONLY
case ArchArgs::HX8K:
#endif
case ArchArgs::HX1K:
- budget = 190; break;
+ budget = 190;
+ break;
#ifndef ICE40_HX1K_ONLY
case ArchArgs::LP384:
case ArchArgs::LP1K:
case ArchArgs::LP8K:
- budget = 290; break;
+ budget = 290;
+ break;
case ArchArgs::UP5K:
- budget = 560; break;
+ budget = 560;
+ break;
#endif
default:
log_error("Unsupported iCE40 chip type.\n");
- }
+ }
return true;
}
return false;
@@ -883,27 +891,76 @@ 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;
+ 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) {
+
+ if (port == id_rclk || port == id_wclk)
+ return TMG_CLOCK_INPUT;
+
if (port.str(this)[0] == 'R')
- return id_rclk;
+ clockPort = id_rclk;
else
- return id_wclk;
- }
- return IdString();
-}
+ clockPort = id_wclk;
-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;
+ if (cell->ports.at(port).type == PORT_OUT)
+ return TMG_REGISTER_OUTPUT;
+ else
+ return TMG_REGISTER_INPUT;
+ } else if (cell->type == id("ICESTORM_DSP") || cell->type == id("ICESTORM_SPRAM")) {
+ clockPort = id_clk;
+ if (port == id_clk)
+ return TMG_CLOCK_INPUT;
+ else if (cell->ports.at(port).type == PORT_OUT)
+ return TMG_REGISTER_OUTPUT;
+ else
+ 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") || port == id("OUTPUT_ENABLE"))
+ return TMG_ENDPOINT;
+ 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;
+ } else if (cell->type == id_sb_gb) {
+ if (port == id_glb_buf_out)
+ return TMG_COMB_OUTPUT;
+ return TMG_COMB_INPUT;
+ } else if (cell->type == id("SB_WARMBOOT")) {
+ return TMG_ENDPOINT;
+ }
+ log_error("no timing info for port '%s' of cell type '%s'\n", port.c_str(this), cell->type.c_str(this));
}
bool Arch::isGlobalNet(const NetInfo *net) const
diff --git a/ice40/arch.h b/ice40/arch.h
index 73f1ea0e..b35b657b 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -400,10 +400,10 @@ struct Arch : BaseCtx
mutable std::unordered_map<Loc, int> bel_by_loc;
std::vector<bool> bel_carry;
- std::vector<CellInfo*> bel_to_cell;
- std::vector<NetInfo*> wire_to_net;
- std::vector<NetInfo*> pip_to_net;
- std::vector<NetInfo*> switches_locked;
+ std::vector<CellInfo *> bel_to_cell;
+ std::vector<NetInfo *> wire_to_net;
+ std::vector<NetInfo *> pip_to_net;
+ std::vector<NetInfo *> switches_locked;
ArchArgs args;
Arch(ArchArgs args);
@@ -789,16 +789,15 @@ 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;
// -------------------------------------------------
- // Perform placement validity checks, returning false on failure (all implemented in arch_place.cc)
+ // Perform placement validity checks, returning false on failure (all
+ // implemented in arch_place.cc)
// Whether or not a given cell can be placed at a given Bel
// This is not intended for Bel type checks, but finer-grained constraints
@@ -812,7 +811,8 @@ struct Arch : BaseCtx
bool logicCellsCompatible(const std::vector<const CellInfo *> &cells) const;
// -------------------------------------------------
- // Assign architecure-specific arguments to nets and cells, which must be called between packing or further
+ // Assign architecure-specific arguments to nets and cells, which must be
+ // called between packing or further
// netlist modifications, and validity checks
void assignArchInfo();
void assignCellInfo(CellInfo *cell);