nexus: Working on validity checking

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2020-01-20 15:57:06 +00:00
parent 887d7c717b
commit 84d5426242
6 changed files with 117 additions and 19 deletions

View File

@ -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);

View File

@ -410,12 +410,6 @@ bool Arch::route()
// -----------------------------------------------------------------------
void Arch::assignArchInfo() {}
void assignCellInfo(CellInfo *cell) {}
// -----------------------------------------------------------------------
#ifdef WITH_HEAP
const std::string Arch::defaultPlacer = "heap";
#else

View File

@ -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;
// -------------------------------------------------

View File

@ -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

View File

@ -169,7 +169,6 @@ struct ArchCellInfo
struct
{
bool is_memory, is_carry, mux2_used;
int input_count;
NetInfo *f, *ofx;
} lutInfo;
struct

View File

@ -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