aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-05-07 21:11:34 +0100
committergatecat <gatecat@ds0.me>2021-05-15 14:54:33 +0100
commit9eb0bc482e171037095dd156d13a286b3b1c6d59 (patch)
tree9126d1b4488920431cf6daef8e6416bf86a77127
parenta6ea72fd84706de8bdb6fd28005e3c735903ad4c (diff)
downloadnextpnr-9eb0bc482e171037095dd156d13a286b3b1c6d59.tar.gz
nextpnr-9eb0bc482e171037095dd156d13a286b3b1c6d59.tar.bz2
nextpnr-9eb0bc482e171037095dd156d13a286b3b1c6d59.zip
cyclonev: More validity checking thoughts
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--cyclonev/arch.cc13
-rw-r--r--cyclonev/arch.h5
-rw-r--r--cyclonev/archdefs.h14
-rw-r--r--cyclonev/constids.inc1
-rw-r--r--cyclonev/lab.cc23
5 files changed, 49 insertions, 7 deletions
diff --git a/cyclonev/arch.cc b/cyclonev/arch.cc
index 9aee5a59..fd2f345d 100644
--- a/cyclonev/arch.cc
+++ b/cyclonev/arch.cc
@@ -308,6 +308,19 @@ void Arch::add_bel_pin(BelId bel, IdString pin, PortType dir, WireId wire)
wires[wire].bel_pins.push_back(bel_pin);
}
+void Arch::assign_default_pinmap(CellInfo *cell)
+{
+ for (auto &port : cell->ports) {
+ auto &pinmap = cell->pin_data[port.first].bel_pins;
+ if (!pinmap.empty())
+ continue; // already mapped
+ if (is_comb_cell(cell->type) && comb_pinmap.count(port.first))
+ pinmap.push_back(comb_pinmap.at(port.first)); // default comb mapping for placer purposes
+ else
+ pinmap.push_back(port.first); // default: assume bel pin named the same as cell pin
+ }
+}
+
#ifdef WITH_HEAP
const std::string Arch::defaultPlacer = "heap";
#else
diff --git a/cyclonev/arch.h b/cyclonev/arch.h
index 301f19d8..ff006881 100644
--- a/cyclonev/arch.h
+++ b/cyclonev/arch.h
@@ -393,6 +393,11 @@ struct Arch : BaseArch<ArchRanges>
BelInfo &bel_data(BelId bel) { return bels_by_tile.at(pos2idx(bel.pos)).at(bel.z); }
const BelInfo &bel_data(BelId bel) const { return bels_by_tile.at(pos2idx(bel.pos)).at(bel.z); }
+
+ // -------------------------------------------------
+
+ void assign_default_pinmap(CellInfo *cell);
+ static const std::unordered_map<IdString, IdString> comb_pinmap;
};
NEXTPNR_NAMESPACE_END
diff --git a/cyclonev/archdefs.h b/cyclonev/archdefs.h
index 5afdd783..31f64a6a 100644
--- a/cyclonev/archdefs.h
+++ b/cyclonev/archdefs.h
@@ -124,10 +124,19 @@ struct ArchNetInfo
{
};
+enum CellPinState
+{
+ PIN_SIG = 0,
+ PIN_0 = 1,
+ PIN_1 = 2,
+ PIN_INV = 3,
+};
+
struct ArchPinInfo
{
- // An inverter (INV) has been pushed onto this signal
- bool inverted;
+ // Used to represent signals that are either tied to implicit constants (rather than explicitly routed constants);
+ // or are inverted
+ CellPinState state = PIN_SIG;
// The physical bel pins that this logical pin maps to
std::vector<IdString> bel_pins;
};
@@ -167,6 +176,7 @@ struct ArchCellInfo
const NetInfo *comb_out;
int lut_input_count;
+ int used_lut_input_count; // excluding those null/constant
int lut_bits_count;
bool is_carry, is_shared, is_extended;
diff --git a/cyclonev/constids.inc b/cyclonev/constids.inc
index fcc723f8..c4af45e6 100644
--- a/cyclonev/constids.inc
+++ b/cyclonev/constids.inc
@@ -55,6 +55,7 @@ X(MISTRAL_ALUT4)
X(MISTRAL_ALUT3)
X(MISTRAL_ALUT2)
X(MISTRAL_NOT)
+X(MISTRAL_BUF)
X(MISTRAL_CONST)
X(MISTRAL_ALUT_ARITH)
diff --git a/cyclonev/lab.cc b/cyclonev/lab.cc
index 6f7c5e6d..1f117106 100644
--- a/cyclonev/lab.cc
+++ b/cyclonev/lab.cc
@@ -195,7 +195,7 @@ 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;
+ result.inverted = cell->pin_data.at(port).state == PIN_INV;
else
result.inverted = false;
return result;
@@ -259,7 +259,8 @@ void Arch::assign_comb_info(CellInfo *cell) const
++cell->combInfo.lut_input_count;
cell->combInfo.lut_in[1] = get_net_or_empty(cell, id_B);
[[fallthrough]];
- case ID_MISTRAL_NOT:
+ case ID_MISTRAL_BUF: // used to route through to FFs etc
+ case ID_MISTRAL_NOT: // used for inverters that map to LUTs
++cell->combInfo.lut_input_count;
cell->combInfo.lut_in[0] = get_net_or_empty(cell, id_A);
[[fallthrough]];
@@ -272,6 +273,10 @@ void Arch::assign_comb_info(CellInfo *cell) const
// 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);
}
+ cell->combInfo.used_lut_input_count = 0;
+ for (int i = 0; i < cell->combInfo.lut_input_count; i++)
+ if (cell->combInfo.lut_in[i])
+ ++cell->combInfo.used_lut_input_count;
}
void Arch::assign_ff_info(CellInfo *cell) const
@@ -336,9 +341,9 @@ bool Arch::is_alm_legal(uint32_t lab, uint8_t alm) const
// There are two ways to route from the fabric into FF data - either routing through a LUT or using the E/F
// signals and SLOAD=1 (*PKREF*)
bool route_thru_lut_avail = !luts[i] && (total_lut_inputs < 8) && (used_lut_bits < 64);
- // E/F is available if the LUT is using less than 6 inputs - TODO: is this correct considering all possible LUT
- // sharing
- bool ef_available = (!luts[i] || luts[i]->combInfo.lut_input_count < 6);
+ // E/F is available if this LUT is using 3 or fewer inputs - this is conservative and sharing can probably
+ // improve this situation
+ bool ef_available = (!luts[i] || luts[i]->combInfo.used_lut_input_count <= 3);
// Control set checking
bool found_ff = false;
@@ -383,4 +388,12 @@ bool Arch::is_lab_ctrlset_legal(uint32_t lab) const
return true;
}
+// This default cell-bel pin mapping is used to provide estimates during placement only. It will have errors and
+// overlaps and a correct mapping will be resolved twixt placement and routing
+const std::unordered_map<IdString, IdString> Arch::comb_pinmap = {
+ {id_A, id_F0}, // fastest input first
+ {id_B, id_E0}, {id_C, id_D}, {id_D, id_C}, {id_D0, id_C}, {id_D1, id_B},
+ {id_E, id_B}, {id_F, id_A}, {id_Q, id_COMBOUT}, {id_SO, id_COMBOUT},
+};
+
NEXTPNR_NAMESPACE_END \ No newline at end of file