From 2612853238af4c84fa38c1c5e349fa19c5c51ebe Mon Sep 17 00:00:00 2001 From: gatecat Date: Sun, 9 May 2021 14:28:56 +0100 Subject: [PATCH] mistral: Adding a function for computing ALM LUT masks Signed-off-by: gatecat --- mistral/arch.h | 2 ++ mistral/lab.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/mistral/arch.h b/mistral/arch.h index 790c6782..868d8650 100644 --- a/mistral/arch.h +++ b/mistral/arch.h @@ -403,6 +403,8 @@ struct Arch : BaseArch void assign_control_sets(uint32_t lab); // 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 diff --git a/mistral/lab.cc b/mistral/lab.cc index eab4d54d..da50fe33 100644 --- a/mistral/lab.cc +++ b/mistral/lab.cc @@ -653,4 +653,92 @@ const std::unordered_map Arch::comb_pinmap = { {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 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 \ No newline at end of file