aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-05-03 20:37:59 +0100
committergatecat <gatecat@ds0.me>2021-05-15 14:54:33 +0100
commit1cd22b81daa4c87870f65dedef74dba02adac8fe (patch)
tree36158dc8ec5c7957b41329cf689e942a795b1a92
parent9bd7ef5f5fcb77e36a988b0967a59965cfe55192 (diff)
downloadnextpnr-1cd22b81daa4c87870f65dedef74dba02adac8fe.tar.gz
nextpnr-1cd22b81daa4c87870f65dedef74dba02adac8fe.tar.bz2
nextpnr-1cd22b81daa4c87870f65dedef74dba02adac8fe.zip
cyclonev: More preparations for validity checking
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--cyclonev/arch.cc17
-rw-r--r--cyclonev/arch.h21
-rw-r--r--cyclonev/archdefs.h28
-rw-r--r--cyclonev/constids.inc1
-rw-r--r--cyclonev/lab.cc99
5 files changed, 159 insertions, 7 deletions
diff --git a/cyclonev/arch.cc b/cyclonev/arch.cc
index 98a09d3b..62acf9e2 100644
--- a/cyclonev/arch.cc
+++ b/cyclonev/arch.cc
@@ -210,6 +210,23 @@ std::vector<IdString> Arch::getBelPins(BelId bel) const
return pins;
}
+bool Arch::isValidBelForCellType(IdString cell_type, BelId bel) const {
+ // Any combinational cell type can - theoretically - be placed at a combinational ALM bel
+ // The precise legality mechanics will be dealt with in isBelLocationValid.
+ IdString bel_type = getBelType(bel);
+ if (bel_type == id_MISTRAL_COMB)
+ return is_comb_cell(cell_type);
+ else
+ return bel_type == cell_type;
+}
+
+BelBucketId Arch::getBelBucketForCellType(IdString cell_type) const {
+ if (is_comb_cell(cell_type))
+ return id_MISTRAL_COMB;
+ else
+ return cell_type;
+}
+
bool Arch::pack() { return true; }
bool Arch::place() { return true; }
bool Arch::route() { return true; }
diff --git a/cyclonev/arch.h b/cyclonev/arch.h
index 53fa4174..34d90a04 100644
--- a/cyclonev/arch.h
+++ b/cyclonev/arch.h
@@ -44,6 +44,8 @@ struct ALMInfo
std::array<BelId, 2> lut_bels;
std::array<BelId, 4> ff_bels;
// TODO: ALM configuration (L5/L6 mode, LUT input permutation, etc)
+ // So we only validity-check changed parts
+ bool valid = false, dirty = false;
};
struct LABInfo
@@ -54,6 +56,9 @@ struct LABInfo
std::array<WireId, 2> aclr_wires;
WireId sclr_wire, sload_wire;
// TODO: LAB configuration (control set etc)
+
+ // These apply to the validity-checking status of the shared FF control sets
+ bool ctrl_valid = false, ctrl_dirty = false;
};
struct PinInfo
@@ -313,6 +318,11 @@ struct Arch : BaseArch<ArchRanges>
// -------------------------------------------------
+ bool isValidBelForCellType(IdString cell_type, BelId bel) const override;
+ BelBucketId getBelBucketForCellType(IdString cell_type) const override;
+
+ // -------------------------------------------------
+
bool pack() override;
bool place() override;
bool route() override;
@@ -331,14 +341,17 @@ struct Arch : BaseArch<ArchRanges>
return WireId(cyclonev->pnode_to_rnode(CycloneV::pnode(bt, x, y, port, bi, pi)));
}
- void create_lab(int x, int y);
+ void create_lab(int x, int y); // lab.cc
void create_gpio(int x, int y);
// -------------------------------------------------
- bool is_comb_cell(IdString cell_type) const;
- bool is_alm_legal(uint32_t lab, uint8_t alm) const;
- bool is_lab_ctrlset_legal(uint32_t lab) const;
+ bool is_comb_cell(IdString cell_type) const; // lab.cc
+ bool is_alm_legal(uint32_t lab, uint8_t alm) const; // lab.cc
+ bool is_lab_ctrlset_legal(uint32_t lab) const; // lab.cc
+
+ void assign_comb_info(CellInfo *cell) const; // lab.cc
+ void assign_ff_info(CellInfo *cell) const; // lab.cc
// -------------------------------------------------
diff --git a/cyclonev/archdefs.h b/cyclonev/archdefs.h
index d6555887..5afdd783 100644
--- a/cyclonev/archdefs.h
+++ b/cyclonev/archdefs.h
@@ -134,6 +134,28 @@ struct ArchPinInfo
struct NetInfo;
+// Structures for representing how FF control sets are stored and validity-checked
+struct ControlSig
+{
+ const NetInfo *net;
+ bool inverted;
+
+ bool connected() const { return net != nullptr; }
+ bool operator==(const ControlSig &other) const { return net == other.net && inverted == other.inverted; }
+ bool operator!=(const ControlSig &other) const { return net == other.net && inverted == other.inverted; }
+};
+
+struct FFControlSet
+{
+ ControlSig clk, ena, aclr, sclr, sload;
+
+ bool operator==(const FFControlSet &other) const
+ {
+ return clk == other.clk && ena == other.ena && aclr == other.aclr && sclr == other.sclr && sload == other.sload;
+ }
+ bool operator!=(const FFControlSet &other) const { return !(*this == other); }
+};
+
struct ArchCellInfo
{
union
@@ -141,7 +163,7 @@ struct ArchCellInfo
struct
{
// Store the nets here for fast validity checking (avoids too many map lookups in a hot path)
- std::array<const NetInfo *, 7> input_sigs;
+ std::array<const NetInfo *, 7> lut_in;
const NetInfo *comb_out;
int lut_input_count;
@@ -151,8 +173,8 @@ struct ArchCellInfo
} combInfo;
struct
{
- const NetInfo *clk, *ena, *aclr, *sclr, *sload, *sdata, *datain;
- bool clk_inv, ena_inv, aclr_inv, sclr_inv, sload_inv;
+ FFControlSet ctrlset;
+ const NetInfo *sdata, *datain;
} ffInfo;
};
diff --git a/cyclonev/constids.inc b/cyclonev/constids.inc
index a22bda47..90d5e753 100644
--- a/cyclonev/constids.inc
+++ b/cyclonev/constids.inc
@@ -47,6 +47,7 @@ X(MISTRAL_ALUT4)
X(MISTRAL_ALUT3)
X(MISTRAL_ALUT2)
X(MISTRAL_NOT)
+X(MISTRAL_CONST)
X(MISTRAL_ALUT_ARITH)
X(D0)
diff --git a/cyclonev/lab.cc b/cyclonev/lab.cc
index a4619a8c..2c2c619a 100644
--- a/cyclonev/lab.cc
+++ b/cyclonev/lab.cc
@@ -19,11 +19,14 @@
#include "log.h"
#include "nextpnr.h"
+#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
// This file contains functions related to our custom LAB structure, including creating the LAB bels; checking the
// legality of LABs; and manipulating LUT inputs and equations
+
+// LAB/ALM structure creation functions
namespace {
static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
{
@@ -185,4 +188,100 @@ void Arch::create_lab(int x, int y)
}
}
+// Cell handling and annotation functions
+namespace {
+ ControlSig get_ctrlsig(const CellInfo *cell, IdString port) {
+ ControlSig result;
+ result.net = get_net_or_empty(cell, port);
+ if (cell->pin_data.count(port))
+ result.inverted = cell->pin_data.at(port).inverted;
+ else
+ result.inverted = false;
+ return result;
+ }
+}
+
+bool Arch::is_comb_cell(IdString cell_type) const
+{
+ // Return true if a cell is a combinational cell type, to be a placed at a MISTRAL_COMB location
+ switch (cell_type.index) {
+ case ID_MISTRAL_ALUT6:
+ case ID_MISTRAL_ALUT5:
+ case ID_MISTRAL_ALUT4:
+ case ID_MISTRAL_ALUT3:
+ case ID_MISTRAL_ALUT2:
+ case ID_MISTRAL_NOT:
+ case ID_MISTRAL_CONST:
+ case ID_MISTRAL_ALUT_ARITH:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void Arch::assign_comb_info(CellInfo *cell) const
+{
+ cell->combInfo.is_carry = false;
+ cell->combInfo.is_shared = false;
+ cell->combInfo.is_extended = false;
+
+ if (cell->type == id_MISTRAL_ALUT_ARITH) {
+ cell->combInfo.is_carry = true;
+ cell->combInfo.lut_input_count = 5;
+ cell->combInfo.lut_bits_count = 32;
+ // This is a special case in terms of naming
+ int i = 0;
+ for (auto pin : {id_A, id_B, id_C, id_D0, id_D1}) {
+ cell->combInfo.lut_in[i++] = get_net_or_empty(cell, pin);
+ }
+ cell->combInfo.comb_out = get_net_or_empty(cell, id_SO);
+ } else {
+ cell->combInfo.lut_input_count = 0;
+ switch (cell->type.index) {
+ case ID_MISTRAL_ALUT6:
+ ++cell->combInfo.lut_input_count;
+ cell->combInfo.lut_in[5] = get_net_or_empty(cell, id_F);
+ [[fallthrough]];
+ case ID_MISTRAL_ALUT5:
+ ++cell->combInfo.lut_input_count;
+ cell->combInfo.lut_in[4] = get_net_or_empty(cell, id_E);
+ [[fallthrough]];
+ case ID_MISTRAL_ALUT4:
+ ++cell->combInfo.lut_input_count;
+ cell->combInfo.lut_in[3] = get_net_or_empty(cell, id_D);
+ [[fallthrough]];
+ case ID_MISTRAL_ALUT3:
+ ++cell->combInfo.lut_input_count;
+ cell->combInfo.lut_in[2] = get_net_or_empty(cell, id_C);
+ [[fallthrough]];
+ case ID_MISTRAL_ALUT2:
+ ++cell->combInfo.lut_input_count;
+ cell->combInfo.lut_in[1] = get_net_or_empty(cell, id_B);
+ [[fallthrough]];
+ case ID_MISTRAL_NOT:
+ ++cell->combInfo.lut_input_count;
+ cell->combInfo.lut_in[0] = get_net_or_empty(cell, id_A);
+ [[fallthrough]];
+ case ID_MISTRAL_CONST:
+ // MISTRAL_CONST is a nextpnr-inserted cell type for 0-input, constant-generating LUTs
+ break;
+ default:
+ log_error("unexpected combinational cell type %s\n", getCtx()->nameOf(cell->type));
+ }
+ // Note that this relationship won't hold for extended mode, when that is supported
+ cell->combInfo.lut_bits_count = (1 << cell->combInfo.lut_input_count);
+ }
+}
+
+void Arch::assign_ff_info(CellInfo *cell) const
+{
+ cell->ffInfo.ctrlset.clk = get_ctrlsig(cell, id_CLK);
+ cell->ffInfo.ctrlset.ena = get_ctrlsig(cell, id_ENA);
+ cell->ffInfo.ctrlset.aclr = get_ctrlsig(cell, id_ACLR);
+ cell->ffInfo.ctrlset.sclr = get_ctrlsig(cell, id_SCLR);
+ cell->ffInfo.ctrlset.sload = get_ctrlsig(cell, id_SLOAD);
+ cell->ffInfo.sdata = get_net_or_empty(cell, id_SDATA);
+ cell->ffInfo.datain = get_net_or_empty(cell, id_DATAIN);
+}
+
NEXTPNR_NAMESPACE_END \ No newline at end of file