nexus: Logic tile validity check functions
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
b00595f3da
commit
871f3c66bc
20
nexus/arch.h
20
nexus/arch.h
@ -576,10 +576,26 @@ struct Arch : BaseCtx
|
||||
const ChipInfoPOD *chip_info;
|
||||
|
||||
// Binding states
|
||||
struct LogicTileStatus
|
||||
{
|
||||
struct SliceStatus
|
||||
{
|
||||
bool valid = true, dirty = true;
|
||||
} slices[4];
|
||||
struct HalfTileStatus
|
||||
{
|
||||
bool valid = true, dirty = true;
|
||||
} halfs[2];
|
||||
CellInfo *cells[32];
|
||||
};
|
||||
|
||||
struct TileStatus
|
||||
{
|
||||
std::vector<CellInfo *> boundcells;
|
||||
LogicTileStatus *lts = nullptr;
|
||||
~TileStatus() { delete lts; }
|
||||
};
|
||||
|
||||
std::vector<TileStatus> tileStatus;
|
||||
std::unordered_map<WireId, NetInfo *> wire_to_net;
|
||||
std::unordered_map<PipId, NetInfo *> pip_to_net;
|
||||
@ -1088,6 +1104,10 @@ struct Arch : BaseCtx
|
||||
range.e.cursor = nh_data(wire).wire_neighbours[wire.index].num_nwires;
|
||||
return range;
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
bool nexus_logic_tile_valid(LogicTileStatus <s) const;
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -23,6 +23,76 @@
|
||||
|
||||
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++) {
|
||||
if (lts.slices[s].dirty) {
|
||||
lts.slices[s].valid = false;
|
||||
lts.slices[s].dirty = false;
|
||||
CellInfo *lut0 = lts.cells[(s << 3) | BEL_LUT0];
|
||||
CellInfo *lut1 = lts.cells[(s << 3) | BEL_LUT1];
|
||||
CellInfo *ff0 = lts.cells[(s << 3) | BEL_FF0];
|
||||
CellInfo *ff1 = lts.cells[(s << 3) | BEL_FF1];
|
||||
if (lut0 != nullptr) {
|
||||
// Check for overuse of M signal
|
||||
if (lut0->lutInfo.mux2_used && ff0 != nullptr && ff0->ffInfo.m != nullptr)
|
||||
return false;
|
||||
}
|
||||
// Check for correct use of FF0 DI
|
||||
if (ff0 != nullptr && ff0->ffInfo.di != nullptr &&
|
||||
(lut0 == nullptr || (ff0->ffInfo.di != lut0->lutInfo.f && ff0->ffInfo.di != lut0->lutInfo.ofx)))
|
||||
return false;
|
||||
if (lut1 != nullptr) {
|
||||
// LUT1 cannot contain a MUX2
|
||||
if (lut1->lutInfo.mux2_used)
|
||||
return false;
|
||||
// If LUT1 is carry then LUT0 must be carry too
|
||||
if (lut1->lutInfo.is_carry && (lut0 == nullptr || !lut0->lutInfo.is_carry))
|
||||
return false;
|
||||
}
|
||||
// Check for correct use of FF1 DI
|
||||
if (ff1 != nullptr && ff1->ffInfo.di != nullptr && (lut1 == nullptr || ff1->ffInfo.di != lut1->lutInfo.f))
|
||||
return false;
|
||||
lts.slices[s].valid = true;
|
||||
} else if (!lts.slices[s].valid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int h = 0; h < 2; h++) {
|
||||
if (lts.halfs[h].dirty) {
|
||||
bool found_ff = false;
|
||||
FFControlSet ctrlset;
|
||||
for (int i = 0; i < 1; i++) {
|
||||
for (auto bel : {BEL_FF0, BEL_FF1, BEL_RAMW}) {
|
||||
if (bel == BEL_RAMW && (h != 1 || i != 0))
|
||||
continue;
|
||||
CellInfo *ci = lts.cells[(h * 2 + i) << 3 | bel];
|
||||
if (ci == nullptr)
|
||||
continue;
|
||||
if (!found_ff) {
|
||||
ctrlset = ci->ffInfo.ctrlset;
|
||||
found_ff = true;
|
||||
} else if (ci->ffInfo.ctrlset != ctrlset) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!lts.halfs[h].valid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; }
|
||||
|
||||
bool Arch::isBelLocationValid(BelId bel) const { return true; }
|
||||
|
@ -148,19 +148,34 @@ struct ArchNetInfo
|
||||
|
||||
struct NetInfo;
|
||||
|
||||
struct FFControlSet
|
||||
{
|
||||
int clkmux, cemux, lsrmux;
|
||||
bool async, regddr_en, gsr_en;
|
||||
NetInfo *clk, *lsr, *ce;
|
||||
};
|
||||
|
||||
inline bool operator!=(const FFControlSet &a, const FFControlSet &b)
|
||||
{
|
||||
return (a.clkmux != b.clkmux) || (a.cemux != b.cemux) || (a.lsrmux != b.lsrmux) || (a.async != b.async) ||
|
||||
(a.regddr_en != b.regddr_en) || (a.gsr_en != b.gsr_en) || (a.clk != b.clk) || (a.lsr != b.lsr) ||
|
||||
(a.ce != b.ce);
|
||||
}
|
||||
|
||||
struct ArchCellInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool is_memory, is_carry;
|
||||
bool is_memory, is_carry, mux2_used;
|
||||
int input_count;
|
||||
NetInfo *f, *ofx;
|
||||
} lutInfo;
|
||||
struct
|
||||
{
|
||||
bool is_clkinv, is_lsrinv, is_ceinv, is_async, gsr;
|
||||
NetInfo *clk, *lsr, *ce, *d;
|
||||
FFControlSet ctrlset;
|
||||
NetInfo *di, *m;
|
||||
} ffInfo;
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user