aboutsummaryrefslogtreecommitdiffstats
path: root/mistral
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-10-03 15:18:41 +0100
committergatecat <gatecat@ds0.me>2021-10-03 15:18:41 +0100
commitfe31fba6231e31fa642f25e1ab23d588315e5510 (patch)
tree03da804494134ecf6dcfa9161e346ce63a2b74ae /mistral
parent4d97e299991c798e65ccd382f9614d87178e673d (diff)
downloadnextpnr-fe31fba6231e31fa642f25e1ab23d588315e5510.tar.gz
nextpnr-fe31fba6231e31fa642f25e1ab23d588315e5510.tar.bz2
nextpnr-fe31fba6231e31fa642f25e1ab23d588315e5510.zip
mistral: Add bel pins for MLAB write port
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'mistral')
-rw-r--r--mistral/constids.inc8
-rw-r--r--mistral/lab.cc49
2 files changed, 38 insertions, 19 deletions
diff --git a/mistral/constids.inc b/mistral/constids.inc
index 6bb45c3c..393989cd 100644
--- a/mistral/constids.inc
+++ b/mistral/constids.inc
@@ -76,3 +76,11 @@ X(LOC)
X(MISTRAL_CLKENA)
X(MISTRAL_CLKBUF)
+
+X(WA0)
+X(WA1)
+X(WA2)
+X(WA3)
+X(WA4)
+X(WCLK)
+X(WE)
diff --git a/mistral/lab.cc b/mistral/lab.cc
index f386aa00..2874aac3 100644
--- a/mistral/lab.cc
+++ b/mistral/lab.cc
@@ -34,6 +34,25 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
auto &lab = arch->labs.at(lab_idx);
auto &alm = lab.alms.at(z);
auto block_type = lab.is_mlab ? CycloneV::MLAB : CycloneV::LAB;
+ // Create the control set and E/F selection - which is per pair of FF
+ for (int i = 0; i < 2; i++) {
+ // Wires
+ alm.sel_clk[i] = arch->add_wire(x, y, arch->id(stringf("CLK%c[%d]", i ? 'B' : 'T', z)));
+ alm.sel_ena[i] = arch->add_wire(x, y, arch->id(stringf("ENA%c[%d]", i ? 'B' : 'T', z)));
+ alm.sel_aclr[i] = arch->add_wire(x, y, arch->id(stringf("ACLR%c[%d]", i ? 'B' : 'T', z)));
+ alm.sel_ef[i] = arch->add_wire(x, y, arch->id(stringf("%cEF[%d]", i ? 'B' : 'T', z)));
+ // Muxes - three CLK/ENA per LAB, two ACLR
+ for (int j = 0; j < 3; j++) {
+ arch->add_pip(lab.clk_wires[j], alm.sel_clk[i]);
+ arch->add_pip(lab.ena_wires[j], alm.sel_ena[i]);
+ if (j < 2)
+ arch->add_pip(lab.aclr_wires[j], alm.sel_aclr[i]);
+ }
+ // E/F pips
+ // Note that the F choice is mirrored, F from the other half is picked
+ arch->add_pip(arch->get_port(block_type, x, y, z, i ? CycloneV::E1 : CycloneV::E0), alm.sel_ef[i]);
+ arch->add_pip(arch->get_port(block_type, x, y, z, i ? CycloneV::F0 : CycloneV::F1), alm.sel_ef[i]);
+ }
// Create the combinational part of ALMs.
// There are two of these, for the two LUT outputs, and these also contain the carry chain and associated logic
// Each one has all 8 ALM inputs as input pins. In many cases only a subset of these are used; depending on mode;
@@ -83,6 +102,17 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
// Combinational output
alm.comb_out[i] = arch->add_wire(x, y, arch->id(stringf("COMBOUT[%d]", z * 2 + i)));
arch->add_bel_pin(bel, id_COMBOUT, PORT_OUT, alm.comb_out[i]);
+ if (lab.is_mlab) {
+ // Write address - shared between all ALMs in a LAB
+ arch->add_bel_pin(bel, id_WA0, PORT_IN, arch->get_port(block_type, x, y, 2, CycloneV::F1));
+ arch->add_bel_pin(bel, id_WA1, PORT_IN, arch->get_port(block_type, x, y, 3, CycloneV::F1));
+ arch->add_bel_pin(bel, id_WA2, PORT_IN, arch->get_port(block_type, x, y, 7, CycloneV::F1));
+ arch->add_bel_pin(bel, id_WA3, PORT_IN, arch->get_port(block_type, x, y, 6, CycloneV::F1));
+ arch->add_bel_pin(bel, id_WA4, PORT_IN, arch->get_port(block_type, x, y, 1, CycloneV::F1));
+ // Write clock and enable appear to be based on bottom FF
+ arch->add_bel_pin(bel, id_WCLK, PORT_IN, alm.sel_clk[1]);
+ arch->add_bel_pin(bel, id_WE, PORT_IN, alm.sel_ena[1]);
+ }
// Assign indexing
alm.lut_bels.at(i) = bel;
auto &b = arch->bel_data(bel);
@@ -90,25 +120,6 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
b.lab_data.alm = z;
b.lab_data.idx = i;
}
- // Create the control set and E/F selection - which is per pair of FF
- for (int i = 0; i < 2; i++) {
- // Wires
- alm.sel_clk[i] = arch->add_wire(x, y, arch->id(stringf("CLK%c[%d]", i ? 'B' : 'T', z)));
- alm.sel_ena[i] = arch->add_wire(x, y, arch->id(stringf("ENA%c[%d]", i ? 'B' : 'T', z)));
- alm.sel_aclr[i] = arch->add_wire(x, y, arch->id(stringf("ACLR%c[%d]", i ? 'B' : 'T', z)));
- alm.sel_ef[i] = arch->add_wire(x, y, arch->id(stringf("%cEF[%d]", i ? 'B' : 'T', z)));
- // Muxes - three CLK/ENA per LAB, two ACLR
- for (int j = 0; j < 3; j++) {
- arch->add_pip(lab.clk_wires[j], alm.sel_clk[i]);
- arch->add_pip(lab.ena_wires[j], alm.sel_ena[i]);
- if (j < 2)
- arch->add_pip(lab.aclr_wires[j], alm.sel_aclr[i]);
- }
- // E/F pips
- // Note that the F choice is mirrored, F from the other half is picked
- arch->add_pip(arch->get_port(block_type, x, y, z, i ? CycloneV::E1 : CycloneV::E0), alm.sel_ef[i]);
- arch->add_pip(arch->get_port(block_type, x, y, z, i ? CycloneV::F0 : CycloneV::F1), alm.sel_ef[i]);
- }
// Create the flipflops and associated routing
const CycloneV::port_type_t outputs[4] = {CycloneV::FFT0, CycloneV::FFT1, CycloneV::FFB0, CycloneV::FFB1};