aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2023-02-27 09:04:11 +0100
committermyrtle <gatecat@ds0.me>2023-02-28 21:39:25 +0100
commitcdd7bb676fbb060c63ed2d0e285b3bdf324a5107 (patch)
tree3dcad0fc015890dc576bd2acace6848266f96a23
parent1dcc2f777d644e1013a89da521f5d4c0d909e486 (diff)
downloadnextpnr-cdd7bb676fbb060c63ed2d0e285b3bdf324a5107.tar.gz
nextpnr-cdd7bb676fbb060c63ed2d0e285b3bdf324a5107.tar.bz2
nextpnr-cdd7bb676fbb060c63ed2d0e285b3bdf324a5107.zip
fabulous: Support for complex flops in PnR
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--generic/viaduct/fabulous/constids.inc3
-rw-r--r--generic/viaduct/fabulous/fab_cfg.h3
-rw-r--r--generic/viaduct/fabulous/fabulous.cc24
-rw-r--r--generic/viaduct/fabulous/validity_check.cc11
4 files changed, 37 insertions, 4 deletions
diff --git a/generic/viaduct/fabulous/constids.inc b/generic/viaduct/fabulous/constids.inc
index 7c8c3400..b7fe721d 100644
--- a/generic/viaduct/fabulous/constids.inc
+++ b/generic/viaduct/fabulous/constids.inc
@@ -110,5 +110,8 @@ X(VDD)
X(_CONST0_DRV)
X(_CONST1_DRV)
+X(_CONST0)
+X(_CONST1)
+
X(_LUT_PERM)
X(_LUT_PERM_IN)
diff --git a/generic/viaduct/fabulous/fab_cfg.h b/generic/viaduct/fabulous/fab_cfg.h
index dc487fbd..17f066cc 100644
--- a/generic/viaduct/fabulous/fab_cfg.h
+++ b/generic/viaduct/fabulous/fab_cfg.h
@@ -43,8 +43,9 @@ struct ControlSetConfig
signal can drive for a CLB with 8 FFs and 2 clocks split at halfway, the first entry would be 0x0F and the second
0xF0
*/
- std::vector<route_mask_t> routing = {0b11111111}; // default 1 shared between all
+ std::vector<route_mask_t> routing; // default 1 shared between all
bool have_signal = true;
+ int can_mask = -1;
bool can_invert = false;
};
diff --git a/generic/viaduct/fabulous/fabulous.cc b/generic/viaduct/fabulous/fabulous.cc
index f3d0878c..d658ce24 100644
--- a/generic/viaduct/fabulous/fabulous.cc
+++ b/generic/viaduct/fabulous/fabulous.cc
@@ -52,6 +52,7 @@ struct FabulousImpl : ViaductAPI
log_error("unrecognised fabulous option '%s'\n", a.first.c_str());
}
}
+
~FabulousImpl(){};
void init(Context *ctx) override
{
@@ -64,6 +65,7 @@ struct FabulousImpl : ViaductAPI
else
is_new_fab = false;
log_info("Detected FABulous %s format project.\n", is_new_fab ? "2.0" : "1.0");
+ init_default_ctrlset_cfg();
// To consider: a faster serialised form of the device data (like bba that other arches use) so we don't have to
// go through the whole csv parsing malarkey each time
blk_trk = std::make_unique<BlockTracker>(ctx, cfg);
@@ -76,6 +78,22 @@ struct FabulousImpl : ViaductAPI
ctx->ripup_penalty = 0.5;
}
+ void init_default_ctrlset_cfg()
+ {
+ // TODO: loading from file or something
+ uint64_t default_routing = (1ULL << (cfg.clb.lc_per_clb * cfg.clb.ff_per_lc)) - 1;
+ auto setup_cfg = [&](ControlSetConfig &ctrl, int mask) {
+ ctrl.routing.clear();
+ ctrl.routing.push_back(default_routing);
+ ctrl.can_mask = mask;
+ ctrl.can_invert = false;
+ };
+
+ setup_cfg(cfg.clb.clk, -1);
+ setup_cfg(cfg.clb.en, 1);
+ setup_cfg(cfg.clb.sr, 0);
+ }
+
void update_cell_timing(Context *ctx)
{
// These timings are not realistic. They just make sure nextpnr does some timing-driven optimisation...
@@ -605,9 +623,9 @@ struct FabulousImpl : ViaductAPI
return true;
bool is_carry = cell_tags.get(lut).comb.carry_used;
if (is_carry) {
- // Because you have to make sure you route _something_ to each HA input in this mode (undefined I1/I2 inputs aren't OK)
- // and you also can't swap I0 because it's fixed internally
- // LUT permutation in carry mode is just more trouble than it's worth.
+ // Because you have to make sure you route _something_ to each HA input in this mode (undefined I1/I2
+ // inputs aren't OK) and you also can't swap I0 because it's fixed internally LUT permutation in carry
+ // mode is just more trouble than it's worth.
return false;
} else {
return true; // TODO: other cases where perm illegal; e.g. LUTRAM
diff --git a/generic/viaduct/fabulous/validity_check.cc b/generic/viaduct/fabulous/validity_check.cc
index 81f057c8..10b67c3e 100644
--- a/generic/viaduct/fabulous/validity_check.cc
+++ b/generic/viaduct/fabulous/validity_check.cc
@@ -62,6 +62,10 @@ void CellTagger::assign_for(const Context *ctx, const FabricConfig &cfg, const C
auto get_ctrlsig = [&](IdString name) {
const NetInfo *sig = ci->getPort(name);
bool invert = sig && bool_or_default(ci->params, ctx->idf("NEG_%s", name.c_str(ctx)));
+ if (sig && sig->driver.cell && sig->driver.cell->type.in(id__CONST0_DRV, id__CONST1_DRV)) {
+ return ControlSig(((sig->driver.cell->type == id__CONST1_DRV) ^ invert) ? id__CONST1 : id__CONST0,
+ false);
+ }
return ControlSig(sig ? sig->name : id___disconnected, invert);
};
t.ff.clk = get_ctrlsig(id_CLK);
@@ -132,6 +136,13 @@ bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_dat
used_en(cfg.en.routing.size());
auto check_ctrlsig = [&](unsigned idx, ControlSig actual, const ControlSetConfig &ctrl,
SSOArray<ControlSig, 2> &used) {
+ if (ctrl.can_mask != -1) {
+ // Using the per-entry control signal masking
+ if (actual.net == id___disconnected || (actual.net == id__CONST0 && ctrl.can_mask == 0) ||
+ (actual.net == id__CONST1 && ctrl.can_mask == 0)) {
+ return true;
+ }
+ }
// see if we have an already-matching signal available
for (unsigned i = 0; i < ctrl.routing.size(); i++) {
// doesn't route to this pin