nexus: Working on validity checking
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
887d7c717b
commit
84d5426242
@ -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
|
// Connect a net to a port
|
||||||
void connect_port(const Context *ctx, NetInfo *net, CellInfo *cell, IdString port_name);
|
void connect_port(const Context *ctx, NetInfo *net, CellInfo *cell, IdString port_name);
|
||||||
|
|
||||||
|
@ -410,12 +410,6 @@ bool Arch::route()
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
void Arch::assignArchInfo() {}
|
|
||||||
|
|
||||||
void assignCellInfo(CellInfo *cell) {}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef WITH_HEAP
|
#ifdef WITH_HEAP
|
||||||
const std::string Arch::defaultPlacer = "heap";
|
const std::string Arch::defaultPlacer = "heap";
|
||||||
#else
|
#else
|
||||||
|
46
nexus/arch.h
46
nexus/arch.h
@ -159,7 +159,7 @@ NPNR_PACKED_STRUCT(struct PhysicalTileInfoPOD {
|
|||||||
int32_t tiletype; // tile type IdString
|
int32_t tiletype; // tile type IdString
|
||||||
});
|
});
|
||||||
|
|
||||||
enum LocFlagsPOD : uint32_t
|
enum LocFlags : uint32_t
|
||||||
{
|
{
|
||||||
LOC_LOGIC = 0x000001,
|
LOC_LOGIC = 0x000001,
|
||||||
LOC_IO18 = 0x000002,
|
LOC_IO18 = 0x000002,
|
||||||
@ -816,12 +816,19 @@ struct Arch : BaseCtx
|
|||||||
cell->bel = bel;
|
cell->bel = bel;
|
||||||
cell->belStrength = strength;
|
cell->belStrength = strength;
|
||||||
refreshUiBel(bel);
|
refreshUiBel(bel);
|
||||||
|
|
||||||
|
if (tile_is(bel, LOC_LOGIC))
|
||||||
|
update_logic_bel(bel, cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unbindBel(BelId bel)
|
void unbindBel(BelId bel)
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(bel != BelId());
|
NPNR_ASSERT(bel != BelId());
|
||||||
NPNR_ASSERT(tileStatus[bel.tile].boundcells[bel.index] != nullptr);
|
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]->bel = BelId();
|
||||||
tileStatus[bel.tile].boundcells[bel.index]->belStrength = STRENGTH_NONE;
|
tileStatus[bel.tile].boundcells[bel.index]->belStrength = STRENGTH_NONE;
|
||||||
tileStatus[bel.tile].boundcells[bel.index] = nullptr;
|
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;
|
bool nexus_logic_tile_valid(LogicTileStatus <s) const;
|
||||||
|
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
@ -23,15 +23,6 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
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
|
bool Arch::nexus_logic_tile_valid(LogicTileStatus <s) const
|
||||||
{
|
{
|
||||||
for (int s = 0; s < 4; s++) {
|
for (int s = 0; s < 4; s++) {
|
||||||
@ -93,8 +84,23 @@ bool Arch::nexus_logic_tile_valid(LogicTileStatus <s) const
|
|||||||
return true;
|
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
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -169,7 +169,6 @@ struct ArchCellInfo
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool is_memory, is_carry, mux2_used;
|
bool is_memory, is_carry, mux2_used;
|
||||||
int input_count;
|
|
||||||
NetInfo *f, *ofx;
|
NetInfo *f, *ofx;
|
||||||
} lutInfo;
|
} lutInfo;
|
||||||
struct
|
struct
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool is_enabled(CellInfo *ci, IdString prop) { return str_or_default(ci->params, prop, "") == "ENABLED"; }
|
||||||
|
} // namespace
|
||||||
|
|
||||||
struct NexusPacker
|
struct NexusPacker
|
||||||
{
|
{
|
||||||
Context *ctx;
|
Context *ctx;
|
||||||
@ -182,4 +186,48 @@ bool Arch::pack()
|
|||||||
return true;
|
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
|
NEXTPNR_NAMESPACE_END
|
Loading…
Reference in New Issue
Block a user