cyclonev: More preparations for validity checking

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-05-03 20:37:59 +01:00
parent 9bd7ef5f5f
commit 1cd22b81da
5 changed files with 159 additions and 7 deletions

View File

@ -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; }

View File

@ -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
// -------------------------------------------------

View File

@ -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;
};

View File

@ -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)

View File

@ -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