diff options
-rw-r--r-- | common/design_utils.h | 7 | ||||
-rw-r--r-- | nexus/arch.cc | 6 | ||||
-rw-r--r-- | nexus/arch.h | 46 | ||||
-rw-r--r-- | nexus/arch_place.cc | 28 | ||||
-rw-r--r-- | nexus/archdefs.h | 1 | ||||
-rw-r--r-- | nexus/pack.cc | 48 |
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 <s) 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 <s) const { for (int s = 0; s < 4; s++) { @@ -93,8 +84,23 @@ bool Arch::nexus_logic_tile_valid(LogicTileStatus <s) 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 |