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
|
#ifndef LIBTRELLIS_ROUTING_GRAPH_H
#define LIBTRELLIS_ROUTING_GRAPH_H
#include <unordered_map>
#include <map>
#include <vector>
#include <string>
#include <set>
#include <regex>
#include <boost/functional/hash.hpp>
#include "Chip.hpp"
#include "Database.hpp"
using namespace std;
namespace Trellis {
typedef int32_t ident_t;
struct Location
{
int16_t x = -1, y = -1;
Location() : x(-1), y(-1)
{};
Location(int16_t x, int16_t y) : x(x), y(y)
{};
bool operator==(const Location &other) const
{ return x == other.x && y == other.y; }
bool operator!=(const Location &other) const
{ return x != other.x || y == other.y; }
bool operator<(const Location &other) const
{ return y < other.y || (y == other.y && x < other.x); }
};
extern const Location GlobalLoc;
inline Location operator+(const Location &a, const Location &b)
{ return Location(a.x + b.x, a.y + b.y); }
struct RoutingId
{
Location loc;
ident_t id = -1;
bool operator==(const RoutingId &other) const
{ return loc == other.loc && id == other.id; }
bool operator!=(const RoutingId &other) const
{ return loc != other.loc || id == other.id; }
bool operator<(const RoutingId &other) const
{ return loc < other.loc || (loc == other.loc && id < other.id); }
};
struct RoutingArc
{
ident_t id = -1;
ident_t tiletype = -1;
RoutingId source;
RoutingId sink;
bool configurable = false;
uint16_t lutperm_flags = 0;
mutable int cdb_id = 0;
};
struct RoutingWire
{
ident_t id = -1;
vector<RoutingId> uphill;
vector<RoutingId> downhill;
vector<pair<RoutingId, ident_t>> belsUphill;
vector<pair<RoutingId, ident_t>> belsDownhill;
mutable int cdb_id = 0;
};
inline bool operator==(const RoutingWire &a, const RoutingWire &b)
{
return a.id == b.id;
}
enum PortDirection {
PORT_IN = 0,
PORT_OUT = 1,
PORT_INOUT = 2
};
struct RoutingBel
{
ident_t name, type;
Location loc;
int z;
map<ident_t, pair<RoutingId, PortDirection>> pins;
mutable int cdb_id = 0;
};
struct RoutingTileLoc
{
Location loc;
map<ident_t, RoutingWire> wires;
map<ident_t, RoutingArc> arcs;
map<ident_t, RoutingBel> bels;
};
inline bool operator==(const RoutingArc &a, const RoutingArc &b)
{
return a.id == b.id;
}
class Chip;
class IdStore
{
public:
// Core functions
ident_t ident(const std::string &str) const;
std::string to_str(ident_t id) const;
RoutingId id_at_loc(int16_t x, int16_t y, const std::string &str) const;
private:
private:
mutable std::vector<std::string> identifiers;
mutable std::unordered_map<std::string, int32_t> str_to_id;
};
class RoutingGraph : public IdStore
{
public:
explicit RoutingGraph(const Chip &c);
// Must be set up beforehand
std::string chip_name;
std::string chip_family;
std::string chip_prefix;
int max_row, max_col;
// Routing tiles
std::map<Location, RoutingTileLoc> tiles;
// Obtain the unique, global identifier for a net inside a tile using the database name
// Returns an empty RoutingId if net is to be ignored
RoutingId globalise_net(int row, int col, const std::string &db_name);
// Add an arc to the graph, automatically adding nets and cross-references as appropriate
void add_arc(Location loc, const RoutingArc &arc);
// Add a wire to the graph by id (ignoring it if already existing)
void add_wire(RoutingId wire);
// Add a Bel to the graph
void add_bel(RoutingBel &bel);
// Add a Bel input or output pin
void add_bel_input(RoutingBel &bel, ident_t pin, int wire_x, int wire_y, ident_t wire_name);
void add_bel_output(RoutingBel &bel, ident_t pin, int wire_x, int wire_y, ident_t wire_name);
private:
// Factory functions
RoutingId globalise_net_ecp5(int row, int col, const std::string &db_name);
RoutingId globalise_net_machxo2(int row, int col, const std::string &db_name);
// Algorithm to give global nets a unique position in MachXO2 devices.
// ECP5 defers global routing to nextpnr.
// Given the tile from where a net was queried, find the actual physical
// wire on chip that corresponds to the queried net rather than the
// imprecise location stored with the database.
RoutingId find_machxo2_global_position(int row, int col, const std::string &db_name);
// We need access to globals.json to correctly assign global positions.
// Internal use only- do NOT expose below methods, members, and types to
// pytrellis for now.
const MachXO2GlobalsInfo *global_data_machxo2;
enum GlobalType {
CENTER,
SPINE_LEFT_RIGHT,
LEFT_RIGHT,
UP_DOWN,
BRANCH,
OTHER,
NONE
};
// Helper function to put all regexes in one place.
GlobalType get_global_type_from_name(const std::string &db_name, smatch &match);
};
}
namespace std {
template <> struct hash <Trellis::Location>
{
std::size_t operator()(const Trellis::Location &loc) const noexcept
{
std::size_t seed = 0;
boost::hash_combine(seed, hash<int>()(loc.x));
boost::hash_combine(seed, hash<int>()(loc.y));
return seed;
}
};
}
#endif
|