2020-01-07 21:06:37 +08:00
|
|
|
/*
|
|
|
|
* nextpnr -- Next Generation Place and Route
|
|
|
|
*
|
2021-06-09 20:09:08 +08:00
|
|
|
* Copyright (C) 2020 gatecat <gatecat@ds0.me>
|
2020-01-07 21:06:37 +08:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "log.h"
|
|
|
|
#include "nextpnr.h"
|
|
|
|
|
|
|
|
NEXTPNR_NAMESPACE_BEGIN
|
|
|
|
|
2020-01-09 04:52:19 +08:00
|
|
|
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];
|
2020-10-19 20:31:21 +08:00
|
|
|
|
|
|
|
if (s == 2) {
|
|
|
|
CellInfo *ramw = lts.cells[(s << 3) | BEL_RAMW];
|
|
|
|
// Nothing else in SLICEC can be used if the RAMW is used
|
|
|
|
if (ramw != nullptr) {
|
|
|
|
if (lut0 != nullptr || lut1 != nullptr || ff0 != nullptr || ff1 != nullptr)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-09 04:52:19 +08:00
|
|
|
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;
|
2020-10-23 02:25:17 +08:00
|
|
|
if (!lut1->lutInfo.is_carry && lut0 != nullptr && lut0->lutInfo.is_carry)
|
|
|
|
return false;
|
2020-01-09 04:52:19 +08:00
|
|
|
}
|
|
|
|
// 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;
|
2020-10-03 22:13:53 +08:00
|
|
|
for (int i = 0; i < 2; i++) {
|
2020-01-09 04:52:19 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-12-07 17:27:58 +08:00
|
|
|
bool Arch::isBelLocationValid(BelId bel, bool explain_invalid) const
|
2020-01-20 23:57:06 +08:00
|
|
|
{
|
2020-11-16 21:22:52 +08:00
|
|
|
if (bel_tile_is(bel, LOC_LOGIC)) {
|
2020-01-20 23:57:06 +08:00
|
|
|
LogicTileStatus *lts = tileStatus[bel.tile].lts;
|
|
|
|
if (lts == nullptr)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return nexus_logic_tile_valid(*lts);
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2020-01-07 21:06:37 +08:00
|
|
|
|
|
|
|
NEXTPNR_NAMESPACE_END
|