1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2021 Lofty <dan.ravensloft@gmail.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef MISTRAL_ARCHDEFS_H
#define MISTRAL_ARCHDEFS_H
#include "base_clusterinfo.h"
#include "cyclonev.h"
#include "hashlib.h"
#include "idstring.h"
#include "nextpnr_assertions.h"
#include "nextpnr_namespaces.h"
#include <limits>
NEXTPNR_NAMESPACE_BEGIN
using mistral::CycloneV;
typedef int delay_t;
// https://bugreports.qt.io/browse/QTBUG-80789
#ifndef Q_MOC_RUN
enum ConstIds
{
ID_NONE
#define X(t) , ID_##t
#include "constids.inc"
#undef X
};
#define X(t) static constexpr auto id_##t = IdString(ID_##t);
#include "constids.inc"
#undef X
#endif
struct DelayInfo
{
delay_t delay = 0;
delay_t minRaiseDelay() const { return delay; }
delay_t maxRaiseDelay() const { return delay; }
delay_t minFallDelay() const { return delay; }
delay_t maxFallDelay() const { return delay; }
delay_t minDelay() const { return delay; }
delay_t maxDelay() const { return delay; }
DelayInfo operator+(const DelayInfo &other) const
{
DelayInfo ret;
ret.delay = this->delay + other.delay;
return ret;
}
};
struct BelId
{
BelId() = default;
BelId(CycloneV::pos_t _pos, uint16_t _z) : pos{_pos}, z{_z} {}
// pos_t is used for X/Y, nextpnr-cyclonev uses its own Z coordinate system.
CycloneV::pos_t pos = 0;
uint16_t z = 0;
bool operator==(const BelId &other) const { return pos == other.pos && z == other.z; }
bool operator!=(const BelId &other) const { return pos != other.pos || z != other.z; }
bool operator<(const BelId &other) const { return pos < other.pos || (pos == other.pos && z < other.z); }
unsigned int hash() const { return mkhash(pos, z); }
};
static constexpr auto invalid_rnode = std::numeric_limits<CycloneV::rnode_t>::max();
struct WireId
{
WireId() = default;
explicit WireId(CycloneV::rnode_t node) : node(node){};
CycloneV::rnode_t node = invalid_rnode;
// Wires created by nextpnr have rnode type >= 128
bool is_nextpnr_created() const
{
NPNR_ASSERT(node != invalid_rnode);
return unsigned(CycloneV::rn2t(node)) >= 128;
}
bool operator==(const WireId &other) const { return node == other.node; }
bool operator!=(const WireId &other) const { return node != other.node; }
bool operator<(const WireId &other) const { return node < other.node; }
unsigned int hash() const { return unsigned(node); }
};
struct PipId
{
PipId() = default;
PipId(CycloneV::rnode_t src, CycloneV::rnode_t dst) : src(src), dst(dst){};
CycloneV::rnode_t src = invalid_rnode, dst = invalid_rnode;
bool operator==(const PipId &other) const { return src == other.src && dst == other.dst; }
bool operator!=(const PipId &other) const { return src != other.src || dst != other.dst; }
bool operator<(const PipId &other) const { return dst < other.dst || (dst == other.dst && src < other.src); }
unsigned int hash() const { return mkhash(src, dst); }
};
typedef IdString DecalId;
typedef IdString GroupId;
typedef IdString BelBucketId;
typedef IdString ClusterId;
struct ArchNetInfo
{
bool is_global = false;
};
enum CellPinState
{
PIN_SIG = 0,
PIN_0 = 1,
PIN_1 = 2,
PIN_INV = 3,
};
struct ArchPinInfo
{
// 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;
};
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 : BaseClusterInfo
{
union
{
struct
{
// Store the nets here for fast validity checking (avoids too many map lookups in a hot path)
std::array<const NetInfo *, 7> lut_in;
const NetInfo *comb_out;
int lut_input_count;
int used_lut_input_count; // excluding those null/constant
int lut_bits_count;
// for the LAB routeability check (see the detailed description in lab.cc); usually the same signal feeding
// multiple ALMs in a LAB is counted multiple times, due to not knowing which routing resources it will need
// in each case. But carry chains where we know how things will pack are allowed to share across ALMs as a
// special case, primarily to support adders/subtractors with a 'B invert' control signal shared across all
// ALMs.
int chain_shared_input_count;
bool is_carry, is_shared, is_extended;
bool carry_start, carry_end;
// MLABs with compatible write ports have this set to the same non-negative integer. -1 means this isn't a
// MLAB
int mlab_group;
ControlSig wclk, we;
} combInfo;
struct
{
FFControlSet ctrlset;
const NetInfo *sdata, *datain;
} ffInfo;
};
dict<IdString, ArchPinInfo> pin_data;
CellPinState get_pin_state(IdString pin) const;
};
NEXTPNR_NAMESPACE_END
#endif
|