aboutsummaryrefslogtreecommitdiffstats
path: root/mistral/lab.cc
diff options
context:
space:
mode:
Diffstat (limited to 'mistral/lab.cc')
-rw-r--r--mistral/lab.cc22
1 files changed, 22 insertions, 0 deletions
diff --git a/mistral/lab.cc b/mistral/lab.cc
index 2ef22412..f386aa00 100644
--- a/mistral/lab.cc
+++ b/mistral/lab.cc
@@ -881,6 +881,24 @@ bool get_phys_pin_val(bool l6_mode, bool arith_mode, int bit, IdString pin)
NPNR_ASSERT_FALSE("unknown physical pin!");
}
}
+
+static const std::array<int, 64> mlab_permute = {0, 1, 4, 5, 8, 9, 12, 13, 29, 28, 25, 24, 21, 20, 17, 16,
+ 2, 3, 6, 7, 10, 11, 14, 15, 31, 30, 27, 26, 23, 22, 19, 18,
+ 32, 33, 36, 37, 40, 41, 44, 45, 61, 60, 57, 56, 53, 52, 49, 48,
+ 34, 35, 38, 39, 42, 43, 46, 47, 63, 62, 59, 58, 55, 54, 51, 50};
+
+// MLABs have permuted init values in hardware, we need to correct for this
+uint64_t permute_mlab_init(uint64_t orig)
+{
+ uint64_t result = 0;
+ for (int i = 0; i < 64; i++) {
+ if ((orig >> uint64_t(i)) & 0x1) {
+ result |= (uint64_t(1) << uint64_t(mlab_permute.at(i)));
+ }
+ }
+ return result;
+}
+
} // namespace
uint64_t Arch::compute_lut_mask(uint32_t lab, uint8_t alm)
@@ -898,6 +916,7 @@ uint64_t Arch::compute_lut_mask(uint32_t lab, uint8_t alm)
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);
@@ -938,6 +957,9 @@ uint64_t Arch::compute_lut_mask(uint32_t lab, uint8_t alm)
// TODO: always inverted, or just certain paths?
mask = ~mask;
+ if (labs.at(lab).is_mlab)
+ mask = permute_mlab_init(mask);
+
#if 1
if (getCtx()->debug) {
auto pos = alm_data.lut_bels[0].pos;