aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/design_utils.h7
-rw-r--r--nexus/arch.cc6
-rw-r--r--nexus/arch.h46
-rw-r--r--nexus/arch_place.cc28
-rw-r--r--nexus/archdefs.h1
-rw-r--r--nexus/pack.cc48
6 files changed, 117 insertions, 19 deletions
diff --git a/common/design_utils.h b/common/design_utils.h
index 1ae1d648..301547c6 100644
--- a/common/design_utils.h
+++ b/common/design_utils.h
@@ -82,6 +82,13 @@ template <typename F1> CellInfo *net_driven_by(const Context *ctx, const NetInfo
}
}
+// Check if a port is used
+inline bool port_used(CellInfo *cell, IdString port_name)
+{
+ auto port_fnd = cell->ports.find(port_name);
+ return port_fnd != cell->ports.end() && port_fnd->second.net != nullptr;
+}
+
// Connect a net to a port
void connect_port(const Context *ctx, NetInfo *net, CellInfo *cell, IdString port_name);
diff --git a/nexus/arch.cc b/nexus/arch.cc
index 663941ff..7efc5c61 100644
--- a/nexus/arch.cc
+++ b/nexus/arch.cc
@@ -410,12 +410,6 @@ bool Arch::route()
// -----------------------------------------------------------------------
-void Arch::assignArchInfo() {}
-
-void assignCellInfo(CellInfo *cell) {}
-
-// -----------------------------------------------------------------------
-
#ifdef WITH_HEAP
const std::string Arch::defaultPlacer = "heap";
#else
diff --git a/nexus/arch.h b/nexus/arch.h
index 29acc5f5..4f1a84ba 100644
--- a/nexus/arch.h
+++ b/nexus/arch.h
@@ -159,7 +159,7 @@ NPNR_PACKED_STRUCT(struct PhysicalTileInfoPOD {
int32_t tiletype; // tile type IdString
});
-enum LocFlagsPOD : uint32_t
+enum LocFlags : uint32_t
{
LOC_LOGIC = 0x000001,
LOC_IO18 = 0x000002,
@@ -816,12 +816,19 @@ struct Arch : BaseCtx
cell->bel = bel;
cell->belStrength = strength;
refreshUiBel(bel);
+
+ if (tile_is(bel, LOC_LOGIC))
+ update_logic_bel(bel, cell);
}
void unbindBel(BelId bel)
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(tileStatus[bel.tile].boundcells[bel.index] != nullptr);
+
+ if (tile_is(bel, LOC_LOGIC))
+ update_logic_bel(bel, nullptr);
+
tileStatus[bel.tile].boundcells[bel.index]->bel = BelId();
tileStatus[bel.tile].boundcells[bel.index]->belStrength = STRENGTH_NONE;
tileStatus[bel.tile].boundcells[bel.index] = nullptr;
@@ -1302,6 +1309,43 @@ struct Arch : BaseCtx
// -------------------------------------------------
+ template <typename TId> uint32_t tile_loc_flags(TId id) const { return chip_info->grid[id.tile].loc_flags; }
+
+ template <typename TId> bool tile_is(TId id, LocFlags lf) const { return tile_loc_flags(id) & lf; }
+
+ // -------------------------------------------------
+
+ enum LogicBelZ
+ {
+ BEL_LUT0 = 0,
+ BEL_LUT1 = 1,
+ BEL_FF0 = 2,
+ BEL_FF1 = 3,
+ BEL_RAMW = 4,
+ };
+
+ void update_logic_bel(BelId bel, CellInfo *cell)
+ {
+ int z = bel_data(bel).z;
+ NPNR_ASSERT(z < 32);
+ auto &tts = tileStatus[bel.tile];
+ if (tts.lts == nullptr)
+ tts.lts = new LogicTileStatus();
+ auto &ts = *(tts.lts);
+ ts.cells[z] = cell;
+ switch (z & 0x7) {
+ case BEL_FF0:
+ case BEL_FF1:
+ case BEL_RAMW:
+ ts.halfs[(z >> 3) / 2].dirty = true;
+ /* fall-through */
+ case BEL_LUT0:
+ case BEL_LUT1:
+ ts.slices[(z >> 3)].dirty = true;
+ break;
+ }
+ }
+
bool nexus_logic_tile_valid(LogicTileStatus &lts) const;
// -------------------------------------------------
diff --git a/nexus/arch_place.cc b/nexus/arch_place.cc
index 6444d1e9..fa1a75e7 100644
--- a/nexus/arch_place.cc
+++ b/nexus/arch_place.cc
@@ -23,15 +23,6 @@
NEXTPNR_NAMESPACE_BEGIN
-enum LogicBelZ
-{
- BEL_LUT0 = 0,
- BEL_LUT1 = 1,
- BEL_FF0 = 2,
- BEL_FF1 = 3,
- BEL_RAMW = 4,
-};
-
bool Arch::nexus_logic_tile_valid(LogicTileStatus &lts) const
{
for (int s = 0; s < 4; s++) {
@@ -93,8 +84,23 @@ bool Arch::nexus_logic_tile_valid(LogicTileStatus &lts) const
return true;
}
-bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; }
+bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
+{
+ // FIXME
+ return true;
+}
-bool Arch::isBelLocationValid(BelId bel) const { return true; }
+bool Arch::isBelLocationValid(BelId bel) const
+{
+ if (tile_is(bel, LOC_LOGIC)) {
+ LogicTileStatus *lts = tileStatus[bel.tile].lts;
+ if (lts == nullptr)
+ return true;
+ else
+ return nexus_logic_tile_valid(*lts);
+ } else {
+ return true;
+ }
+}
NEXTPNR_NAMESPACE_END
diff --git a/nexus/archdefs.h b/nexus/archdefs.h
index 098333b9..8709cc9c 100644
--- a/nexus/archdefs.h
+++ b/nexus/archdefs.h
@@ -169,7 +169,6 @@ struct ArchCellInfo
struct
{
bool is_memory, is_carry, mux2_used;
- int input_count;
NetInfo *f, *ofx;
} lutInfo;
struct
diff --git a/nexus/pack.cc b/nexus/pack.cc
index c1e3664f..2b88a095 100644
--- a/nexus/pack.cc
+++ b/nexus/pack.cc
@@ -25,6 +25,10 @@
NEXTPNR_NAMESPACE_BEGIN
+namespace {
+bool is_enabled(CellInfo *ci, IdString prop) { return str_or_default(ci->params, prop, "") == "ENABLED"; }
+} // namespace
+
struct NexusPacker
{
Context *ctx;
@@ -182,4 +186,48 @@ bool Arch::pack()
return true;
}
+// -----------------------------------------------------------------------
+
+void Arch::assignArchInfo()
+{
+ for (auto cell : sorted(cells)) {
+ assignCellInfo(cell.second);
+ }
+}
+
+void Arch::assignCellInfo(CellInfo *cell)
+{
+ if (cell->type == id_OXIDE_COMB) {
+ cell->lutInfo.is_memory = str_or_default(cell->params, id_MODE, "LOGIC") == "DPRAM";
+ cell->lutInfo.is_carry = str_or_default(cell->params, id_MODE, "LOGIC") == "CCU2";
+ cell->lutInfo.mux2_used = port_used(cell, id_OFX);
+ cell->lutInfo.f = get_net_or_empty(cell, id_F);
+ cell->lutInfo.ofx = get_net_or_empty(cell, id_OFX);
+ } else if (cell->type == id_OXIDE_FF) {
+ cell->ffInfo.ctrlset.async = str_or_default(cell->params, id_SRMODE, "LSR_OVER_CE") == "ASYNC";
+ cell->ffInfo.ctrlset.regddr_en = is_enabled(cell, id_REGDDR);
+ cell->ffInfo.ctrlset.gsr_en = is_enabled(cell, id_GSR);
+ cell->ffInfo.ctrlset.clkmux = id(str_or_default(cell->params, id_CLKMUX, "CLK")).index;
+ cell->ffInfo.ctrlset.cemux = id(str_or_default(cell->params, id_CEMUX, "CE")).index;
+ cell->ffInfo.ctrlset.lsrmux = id(str_or_default(cell->params, id_LSRMUX, "LSR")).index;
+ cell->ffInfo.ctrlset.clk = get_net_or_empty(cell, id_CLK);
+ cell->ffInfo.ctrlset.ce = get_net_or_empty(cell, id_CE);
+ cell->ffInfo.ctrlset.lsr = get_net_or_empty(cell, id_LSR);
+ cell->ffInfo.di = get_net_or_empty(cell, id_DI);
+ cell->ffInfo.m = get_net_or_empty(cell, id_M);
+ } else if (cell->type == ID_RAMW) {
+ cell->ffInfo.ctrlset.async = false;
+ cell->ffInfo.ctrlset.regddr_en = false;
+ cell->ffInfo.ctrlset.gsr_en = false;
+ cell->ffInfo.ctrlset.clkmux = id(str_or_default(cell->params, id_CLKMUX, "CLK")).index;
+ cell->ffInfo.ctrlset.cemux = ID_CE;
+ cell->ffInfo.ctrlset.lsrmux = id(str_or_default(cell->params, id_LSRMUX, "LSR")).index;
+ cell->ffInfo.ctrlset.clk = get_net_or_empty(cell, id_CLK);
+ cell->ffInfo.ctrlset.ce = nullptr;
+ cell->ffInfo.ctrlset.lsr = get_net_or_empty(cell, id_LSR);
+ cell->ffInfo.di = nullptr;
+ cell->ffInfo.m = nullptr;
+ }
+}
+
NEXTPNR_NAMESPACE_END \ No newline at end of file