mistral: Adding a function for computing ALM LUT masks
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
5d191f8297
commit
2612853238
@ -403,6 +403,8 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
void assign_control_sets(uint32_t lab); // lab.cc
|
void assign_control_sets(uint32_t lab); // lab.cc
|
||||||
void reassign_alm_inputs(uint32_t lab, uint8_t alm); // lab.cc
|
void reassign_alm_inputs(uint32_t lab, uint8_t alm); // lab.cc
|
||||||
|
|
||||||
|
uint64_t compute_lut_mask(uint32_t lab, uint8_t alm); // lab.cc
|
||||||
|
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
|
||||||
bool is_io_cell(IdString cell_type) const; // io.cc
|
bool is_io_cell(IdString cell_type) const; // io.cc
|
||||||
|
@ -653,4 +653,92 @@ const std::unordered_map<IdString, IdString> Arch::comb_pinmap = {
|
|||||||
{id_E, id_B}, {id_F, id_A}, {id_Q, id_COMBOUT}, {id_SO, id_COMBOUT},
|
{id_E, id_B}, {id_F, id_A}, {id_Q, id_COMBOUT}, {id_SO, id_COMBOUT},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// gets the value of the ith LUT init property of a given cell
|
||||||
|
uint64_t get_lut_init(const CellInfo *cell, int i)
|
||||||
|
{
|
||||||
|
if (cell->type == id_MISTRAL_NOT) {
|
||||||
|
return 1;
|
||||||
|
} else if (cell->type == id_MISTRAL_BUF) {
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
IdString prop;
|
||||||
|
if (cell->type == id_MISTRAL_ALUT_ARITH)
|
||||||
|
prop = (i == 1) ? id_LUT1 : id_LUT0;
|
||||||
|
else
|
||||||
|
prop = id_LUT;
|
||||||
|
auto fnd = cell->params.find(prop);
|
||||||
|
if (fnd == cell->params.end())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return fnd->second.as_int64();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// gets the state of a physical pin when evaluating the a given bit of LUT init for
|
||||||
|
bool get_phys_pin_val(bool l6_mode, bool arith_mode, int bit, IdString pin)
|
||||||
|
{
|
||||||
|
switch (pin.index) {
|
||||||
|
case ID_A:
|
||||||
|
return (bit >> 0) & 0x1;
|
||||||
|
case ID_B:
|
||||||
|
return (bit >> 1) & 0x1;
|
||||||
|
case ID_C:
|
||||||
|
return (l6_mode && bit >= 32) ? ((bit >> 3) & 0x1) : ((bit >> 2) & 0x1);
|
||||||
|
case ID_D:
|
||||||
|
return (l6_mode && bit < 32) ? ((bit >> 3) & 0x1) : ((bit >> 2) & 0x1);
|
||||||
|
case ID_E0:
|
||||||
|
case ID_E1:
|
||||||
|
return l6_mode ? ((bit >> 5) & 0x1) : ((bit >> 3) & 0x1);
|
||||||
|
case ID_F0:
|
||||||
|
case ID_F1:
|
||||||
|
return arith_mode ? ((bit >> 3) & 0x1) : ((bit >> 4) & 0x1);
|
||||||
|
default:
|
||||||
|
NPNR_ASSERT_FALSE("unknown physical pin!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
uint64_t Arch::compute_lut_mask(uint32_t lab, uint8_t alm)
|
||||||
|
{
|
||||||
|
uint64_t mask = 0;
|
||||||
|
auto &alm_data = labs.at(lab).alms.at(alm);
|
||||||
|
std::array<CellInfo *, 2> luts{getBoundBelCell(alm_data.lut_bels[0]), getBoundBelCell(alm_data.lut_bels[1])};
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
CellInfo *lut = luts[i];
|
||||||
|
if (!lut)
|
||||||
|
continue;
|
||||||
|
int offset = ((i == 1) && !alm_data.l6_mode) ? 32 : 0;
|
||||||
|
bool arith = lut->combInfo.is_carry;
|
||||||
|
for (int j = 0; j < (alm_data.l6_mode ? 64 : 32); j++) {
|
||||||
|
// Evaluate LUT function at this point
|
||||||
|
uint64_t init = get_lut_init(lut, (arith && j >= 16) ? 1 : 0);
|
||||||
|
int index = 0;
|
||||||
|
for (int k = 0; k < lut->combInfo.lut_input_count; k++) {
|
||||||
|
IdString log_pin = get_lut_pin(lut, k);
|
||||||
|
CellPinState state = lut->get_pin_state(log_pin);
|
||||||
|
if (state == PIN_0)
|
||||||
|
continue;
|
||||||
|
else if (state == PIN_1)
|
||||||
|
index |= (1 << k);
|
||||||
|
// Ignore if no associated physical pin
|
||||||
|
if (get_net_or_empty(lut, log_pin) == nullptr || lut->pin_data.at(log_pin).bel_pins.empty())
|
||||||
|
continue;
|
||||||
|
// ALM inputs appear to be inverted by default (TODO: check!)
|
||||||
|
// so only invert if an inverter has _not_ been folded into the pin
|
||||||
|
bool inverted = (state != PIN_INV);
|
||||||
|
// Depermute physical pin
|
||||||
|
IdString phys_pin = lut->pin_data.at(log_pin).bel_pins.at(0);
|
||||||
|
if (get_phys_pin_val(alm_data.l6_mode, arith, j, phys_pin) != inverted)
|
||||||
|
index |= (1 << k);
|
||||||
|
}
|
||||||
|
if ((init >> index) & 0x1) {
|
||||||
|
mask |= (1U << uint64_t(j + offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
Loading…
Reference in New Issue
Block a user