aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mistral/arch.cc6
-rw-r--r--mistral/arch.h12
-rw-r--r--mistral/base_bitstream.cc86
-rw-r--r--mistral/lab.cc55
4 files changed, 131 insertions, 28 deletions
diff --git a/mistral/arch.cc b/mistral/arch.cc
index 592eddff..632fb0b2 100644
--- a/mistral/arch.cc
+++ b/mistral/arch.cc
@@ -303,6 +303,12 @@ WireId Arch::add_wire(int x, int y, IdString name, uint64_t flags)
}
}
+bool Arch::wires_connected(WireId src, WireId dst) const
+{
+ PipId pip(src.node, dst.node);
+ return getBoundPipNet(pip) != nullptr;
+}
+
PipId Arch::add_pip(WireId src, WireId dst)
{
wires[src].wires_downhill.push_back(dst);
diff --git a/mistral/arch.h b/mistral/arch.h
index 868d8650..860b3327 100644
--- a/mistral/arch.h
+++ b/mistral/arch.h
@@ -40,6 +40,10 @@ struct ArchArgs
// These structures are used for fast ALM validity checking
struct ALMInfo
{
+ // Wires, so bitstream gen can determine connectivity
+ std::array<WireId, 2> comb_out;
+ std::array<WireId, 2> sel_clk, sel_ena, sel_aclr, sel_ef;
+ std::array<WireId, 4> ff_in, ff_out;
// Pointers to bels
std::array<BelId, 2> lut_bels;
std::array<BelId, 4> ff_bels;
@@ -326,6 +330,8 @@ struct Arch : BaseArch<ArchRanges>
const std::vector<BelPin> &getWireBelPins(WireId wire) const override { return wires.at(wire).bel_pins; }
AllWireRange getWires() const override { return AllWireRange(wires); }
+ bool wires_connected(WireId src, WireId dst) const;
+
// -------------------------------------------------
PipId getPipByName(IdStringList name) const override;
@@ -461,9 +467,15 @@ struct Arch : BaseArch<ArchRanges>
static const std::unordered_map<IdString, CellPinsData> cell_pins_db; // pins.cc
CellPinStyle get_cell_pin_style(const CellInfo *cell, IdString port) const; // pins.cc
+ // -------------------------------------------------
+
// List of IO constraints, used by QSF parser
std::unordered_map<IdString, std::unordered_map<IdString, Property>> io_attr;
void read_qsf(std::istream &in); // qsf.cc
+
+ // -------------------------------------------------
+
+ void init_base_bitstream(); // base_bitstream.cc
};
NEXTPNR_NAMESPACE_END
diff --git a/mistral/base_bitstream.cc b/mistral/base_bitstream.cc
new file mode 100644
index 00000000..95199b18
--- /dev/null
+++ b/mistral/base_bitstream.cc
@@ -0,0 +1,86 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2021 gatecat <gatecat@ds0.me>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "log.h"
+#include "nextpnr.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+namespace {
+// Device-specific default config for the sx120f die
+void default_sx120f(CycloneV *cv)
+{
+ // Default PMA config?
+ cv->bmux_m_set(CycloneV::PMA3, CycloneV::xy2pos(0, 11), CycloneV::FFPLL_IQCLK_DIRECTION, 0, CycloneV::TRISTATE);
+ cv->bmux_m_set(CycloneV::PMA3, CycloneV::xy2pos(0, 11), CycloneV::FFPLL_IQCLK_DIRECTION, 1, CycloneV::TRISTATE);
+ cv->bmux_m_set(CycloneV::PMA3, CycloneV::xy2pos(0, 23), CycloneV::FFPLL_IQCLK_DIRECTION, 0, CycloneV::DOWN);
+ cv->bmux_m_set(CycloneV::PMA3, CycloneV::xy2pos(0, 23), CycloneV::FFPLL_IQCLK_DIRECTION, 1, CycloneV::UP);
+ cv->bmux_m_set(CycloneV::PMA3, CycloneV::xy2pos(0, 35), CycloneV::FFPLL_IQCLK_DIRECTION, 0, CycloneV::UP);
+ cv->bmux_m_set(CycloneV::PMA3, CycloneV::xy2pos(0, 35), CycloneV::FFPLL_IQCLK_DIRECTION, 1, CycloneV::UP);
+ cv->bmux_b_set(CycloneV::PMA3, CycloneV::xy2pos(0, 35), CycloneV::FPLL_DRV_EN, -1, false);
+ cv->bmux_m_set(CycloneV::PMA3, CycloneV::xy2pos(0, 35), CycloneV::HCLK_TOP_OUT_DRIVER, -1, CycloneV::TRISTATE);
+ // Default PLL config
+ cv->bmux_b_set(CycloneV::FPLL, CycloneV::xy2pos(0, 73), CycloneV::PL_AUX_ATB_EN0, -1, true);
+ cv->bmux_b_set(CycloneV::FPLL, CycloneV::xy2pos(0, 73), CycloneV::PL_AUX_ATB_EN0_PRECOMP, -1, true);
+ cv->bmux_b_set(CycloneV::FPLL, CycloneV::xy2pos(0, 73), CycloneV::PL_AUX_ATB_EN1, -1, true);
+ cv->bmux_b_set(CycloneV::FPLL, CycloneV::xy2pos(0, 73), CycloneV::PL_AUX_ATB_EN1_PRECOMP, -1, true);
+ cv->bmux_b_set(CycloneV::FPLL, CycloneV::xy2pos(0, 73), CycloneV::PL_AUX_BG_KICKSTART, -1, true);
+ cv->bmux_b_set(CycloneV::FPLL, CycloneV::xy2pos(0, 73), CycloneV::PL_AUX_VBGMON_POWERDOWN, -1, true);
+
+ // Discover these mux values using
+ // grep 'i [_A-Z0-9.]* 1' empty.bt
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 12), 69), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 13), 4), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 34), 69), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 35), 4), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 37), 31), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 40), 43), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 46), 69), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 47), 53), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 53), 69), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 54), 4), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 73), 68), true);
+
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 18), 66), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 20), 8), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 27), 69), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 28), 43), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 59), 66), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 61), 8), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 68), 69), true);
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(9, 69), 43), true);
+
+ for (int z = 10; z <= 45; z++)
+ cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(51, 80), z), true);
+}
+} // namespace
+
+void Arch::init_base_bitstream()
+{
+ switch (cyclonev->current_model()->variant.die.type) {
+ case CycloneV::SX120F:
+ default_sx120f(cyclonev);
+ break;
+ default:
+ log_error("FIXME: die type %s currently unsupported for bitgen.\n",
+ cyclonev->current_model()->variant.die.name);
+ }
+}
+
+NEXTPNR_NAMESPACE_END \ No newline at end of file
diff --git a/mistral/lab.cc b/mistral/lab.cc
index da50fe33..663b86e2 100644
--- a/mistral/lab.cc
+++ b/mistral/lab.cc
@@ -32,6 +32,7 @@ namespace {
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);
// 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;
@@ -79,33 +80,32 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
arch->add_bel_pin(bel, id_COUT, PORT_OUT, carry_out);
arch->add_bel_pin(bel, id_SHAREOUT, PORT_OUT, share_out);
// Combinational output
- WireId comb_out = arch->add_wire(x, y, arch->id(stringf("COMBOUT[%d]", z * 2 + i)));
- arch->add_bel_pin(bel, id_COMBOUT, PORT_OUT, comb_out);
+ 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]);
// Assign indexing
- lab.alms.at(z).lut_bels.at(i) = bel;
+ alm.lut_bels.at(i) = bel;
auto &b = arch->bel_data(bel);
b.lab_data.lab = 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
- std::array<WireId, 2> sel_clk, sel_ena, sel_aclr, sel_ef;
for (int i = 0; i < 2; i++) {
// Wires
- sel_clk[i] = arch->add_wire(x, y, arch->id(stringf("CLK%c[%d]", i ? 'B' : 'T', z)));
- sel_ena[i] = arch->add_wire(x, y, arch->id(stringf("ENA%c[%d]", i ? 'B' : 'T', z)));
- sel_aclr[i] = arch->add_wire(x, y, arch->id(stringf("ACLR%c[%d]", i ? 'B' : 'T', z)));
- sel_ef[i] = arch->add_wire(x, y, arch->id(stringf("%cEF[%d]", i ? 'B' : 'T', z)));
+ 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], sel_clk[i]);
- arch->add_pip(lab.ena_wires[j], sel_ena[i]);
+ 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], sel_aclr[i]);
+ arch->add_pip(lab.aclr_wires[j], alm.sel_aclr[i]);
}
// E/F pips
- arch->add_pip(arch->get_port(CycloneV::LAB, x, y, z, i ? CycloneV::E1 : CycloneV::E0), sel_ef[i]);
- arch->add_pip(arch->get_port(CycloneV::LAB, x, y, z, i ? CycloneV::F1 : CycloneV::F0), sel_ef[i]);
+ arch->add_pip(arch->get_port(CycloneV::LAB, x, y, z, i ? CycloneV::E1 : CycloneV::E0), alm.sel_ef[i]);
+ arch->add_pip(arch->get_port(CycloneV::LAB, x, y, z, i ? CycloneV::F1 : CycloneV::F0), alm.sel_ef[i]);
}
// Create the flipflops and associated routing
@@ -114,32 +114,31 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
for (int i = 0; i < 4; i++) {
// FF input, selected by *PKREG*
- WireId comb_out = arch->add_wire(x, y, arch->id(stringf("COMBOUT[%d]", (z * 2) + (i / 2))));
- WireId ff_in = arch->add_wire(x, y, arch->id(stringf("FFIN[%d]", (z * 4) + i)));
- arch->add_pip(comb_out, ff_in);
- arch->add_pip(sel_ef[i / 2], ff_in);
+ alm.ff_in[i] = arch->add_wire(x, y, arch->id(stringf("FFIN[%d]", (z * 4) + i)));
+ arch->add_pip(alm.comb_out[i / 2], alm.ff_in[i]);
+ arch->add_pip(alm.sel_ef[i / 2], alm.ff_in[i]);
// FF bel
BelId bel = arch->add_bel(x, y, arch->id(stringf("ALM%d_FF%d", z, i)), id_MISTRAL_FF);
- arch->add_bel_pin(bel, id_CLK, PORT_IN, sel_clk[i / 2]);
- arch->add_bel_pin(bel, id_ENA, PORT_IN, sel_ena[i / 2]);
- arch->add_bel_pin(bel, id_ACLR, PORT_IN, sel_aclr[i / 2]);
+ arch->add_bel_pin(bel, id_CLK, PORT_IN, alm.sel_clk[i / 2]);
+ arch->add_bel_pin(bel, id_ENA, PORT_IN, alm.sel_ena[i / 2]);
+ arch->add_bel_pin(bel, id_ACLR, PORT_IN, alm.sel_aclr[i / 2]);
arch->add_bel_pin(bel, id_SCLR, PORT_IN, lab.sclr_wire);
arch->add_bel_pin(bel, id_SLOAD, PORT_IN, lab.sload_wire);
- arch->add_bel_pin(bel, id_DATAIN, PORT_IN, ff_in);
- arch->add_bel_pin(bel, id_SDATA, PORT_IN, sel_ef[i / 2]);
+ arch->add_bel_pin(bel, id_DATAIN, PORT_IN, alm.ff_in[i]);
+ arch->add_bel_pin(bel, id_SDATA, PORT_IN, alm.sel_ef[i / 2]);
// FF output
- WireId ff_out = arch->add_wire(x, y, arch->id(stringf("FFOUT[%d]", (z * 4) + i)));
- arch->add_bel_pin(bel, id_Q, PORT_OUT, ff_out);
+ alm.ff_out[i] = arch->add_wire(x, y, arch->id(stringf("FFOUT[%d]", (z * 4) + i)));
+ arch->add_bel_pin(bel, id_Q, PORT_OUT, alm.ff_out[i]);
// Output mux (*DFF*)
WireId out = arch->get_port(CycloneV::LAB, x, y, z, outputs[i]);
- arch->add_pip(ff_out, out);
- arch->add_pip(comb_out, out);
+ arch->add_pip(alm.ff_out[i], out);
+ arch->add_pip(alm.comb_out[i / 2], out);
// 'L' output mux where applicable
if (i == 1 || i == 3) {
WireId l_out = arch->get_port(CycloneV::LAB, x, y, z, l_outputs[i / 2]);
- arch->add_pip(ff_out, l_out);
- arch->add_pip(comb_out, l_out);
+ arch->add_pip(alm.ff_out[i], l_out);
+ arch->add_pip(alm.comb_out[i / 2], l_out);
}
lab.alms.at(z).ff_bels.at(i) = bel;
href='#n657'>657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699