aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-05-11 21:07:22 +0100
committergatecat <gatecat@ds0.me>2021-05-15 14:54:33 +0100
commitbacba274a2edf4bf8cb05b109388e6e18ca5fc16 (patch)
tree7d393316b0576e5ea391500d25b2874b0d6b31df
parentd1f635242d2984331da85212b478950bf299b636 (diff)
downloadnextpnr-bacba274a2edf4bf8cb05b109388e6e18ca5fc16.tar.gz
nextpnr-bacba274a2edf4bf8cb05b109388e6e18ca5fc16.tar.bz2
nextpnr-bacba274a2edf4bf8cb05b109388e6e18ca5fc16.zip
mistral: Write LUT inits
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--mistral/bitstream.cc37
-rw-r--r--mistral/lab.cc36
2 files changed, 72 insertions, 1 deletions
diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc
index 2d64c337..3337c38e 100644
--- a/mistral/bitstream.cc
+++ b/mistral/bitstream.cc
@@ -196,6 +196,42 @@ struct MistralBitgen
}
}
+ void write_alm(uint32_t lab, uint8_t alm)
+ {
+ auto &alm_data = ctx->labs.at(lab).alms.at(alm);
+
+ std::array<CellInfo *, 2> luts{ctx->getBoundBelCell(alm_data.lut_bels[0]),
+ ctx->getBoundBelCell(alm_data.lut_bels[1])};
+ std::array<CellInfo *, 4> ffs{
+ ctx->getBoundBelCell(alm_data.ff_bels[0]), ctx->getBoundBelCell(alm_data.ff_bels[1]),
+ ctx->getBoundBelCell(alm_data.ff_bels[2]), ctx->getBoundBelCell(alm_data.ff_bels[3])};
+ // Skip empty ALMs
+ if (std::all_of(luts.begin(), luts.end(), [](CellInfo *c) { return !c; }) &&
+ std::all_of(ffs.begin(), ffs.end(), [](CellInfo *c) { return !c; }))
+ return;
+
+ auto pos = alm_data.lut_bels[0].pos;
+ // Combinational mode - TODO: flop feedback
+ cv->bmux_m_set(CycloneV::LAB, pos, CycloneV::MODE, alm, alm_data.l6_mode ? CycloneV::L6 : CycloneV::L5);
+ // LUT function
+ cv->bmux_r_set(CycloneV::LAB, pos, CycloneV::LUT_MASK, alm, ctx->compute_lut_mask(lab, alm));
+ // DFF output - foce to LUT for now...
+ cv->bmux_m_set(CycloneV::LAB, pos, CycloneV::TDFF0, alm, CycloneV::NLUT);
+ cv->bmux_m_set(CycloneV::LAB, pos, CycloneV::TDFF1, alm, CycloneV::NLUT);
+ cv->bmux_m_set(CycloneV::LAB, pos, CycloneV::TDFF1L, alm, CycloneV::NLUT);
+ cv->bmux_m_set(CycloneV::LAB, pos, CycloneV::BDFF0, alm, CycloneV::NLUT);
+ cv->bmux_m_set(CycloneV::LAB, pos, CycloneV::BDFF1, alm, CycloneV::NLUT);
+ cv->bmux_m_set(CycloneV::LAB, pos, CycloneV::BDFF1L, alm, CycloneV::NLUT);
+ }
+
+ void write_labs()
+ {
+ for (size_t lab = 0; lab < ctx->labs.size(); lab++) {
+ for (uint8_t alm = 0; alm < 10; alm++)
+ write_alm(lab, alm);
+ }
+ }
+
void run()
{
cv->clear();
@@ -203,6 +239,7 @@ struct MistralBitgen
write_routing();
write_dqs();
write_cells();
+ write_labs();
}
};
} // namespace
diff --git a/mistral/lab.cc b/mistral/lab.cc
index 663b86e2..e93ef8a8 100644
--- a/mistral/lab.cc
+++ b/mistral/lab.cc
@@ -732,11 +732,45 @@ uint64_t Arch::compute_lut_mask(uint32_t lab, uint8_t alm)
index |= (1 << k);
}
if ((init >> index) & 0x1) {
- mask |= (1U << uint64_t(j + offset));
+ mask |= (1ULL << uint64_t(j + offset));
}
}
}
+ // TODO: always inverted, or just certain paths?
+ mask = ~mask;
+
+#if 1
+ if (getCtx()->debug) {
+ auto pos = alm_data.lut_bels[0].pos;
+ log("ALM %03d.%03d.%d\n", CycloneV::pos2x(pos), CycloneV::pos2y(pos), alm);
+ for (int i = 0; i < 2; i++) {
+ log(" LUT%d: ", i);
+ if (luts[i]) {
+ log("%s:%s", nameOf(luts[i]), nameOf(luts[i]->type));
+ for (auto &pin : luts[i]->pin_data) {
+ if (!luts[i]->ports.count(pin.first) || luts[i]->ports.at(pin.first).type != PORT_IN)
+ continue;
+ log(" %s:", nameOf(pin.first));
+ if (pin.second.state == PIN_0)
+ log("0");
+ else if (pin.second.state == PIN_1)
+ log("1");
+ else if (pin.second.state == PIN_INV)
+ log("~");
+ for (auto bp : pin.second.bel_pins)
+ log("%s", nameOf(bp));
+ }
+ } else {
+ log("<null>");
+ }
+ log("\n");
+ }
+ log("INIT: %016lx\n", mask);
+ log("\n");
+ }
+#endif
+
return mask;
}