diff options
| author | gatecat <gatecat@ds0.me> | 2021-05-03 20:37:59 +0100 | 
|---|---|---|
| committer | gatecat <gatecat@ds0.me> | 2021-05-15 14:54:33 +0100 | 
| commit | 1cd22b81daa4c87870f65dedef74dba02adac8fe (patch) | |
| tree | 36158dc8ec5c7957b41329cf689e942a795b1a92 | |
| parent | 9bd7ef5f5fcb77e36a988b0967a59965cfe55192 (diff) | |
| download | nextpnr-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.cc | 17 | ||||
| -rw-r--r-- | cyclonev/arch.h | 21 | ||||
| -rw-r--r-- | cyclonev/archdefs.h | 28 | ||||
| -rw-r--r-- | cyclonev/constids.inc | 1 | ||||
| -rw-r--r-- | cyclonev/lab.cc | 99 | 
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 | 
