mistral: Adding a function for computing ALM LUT masks

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-05-09 14:28:56 +01:00
parent 5d191f8297
commit 2612853238
2 changed files with 90 additions and 0 deletions

View File

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

View File

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