File: RoutingGraph.hpp

package info (click to toggle)
prjtrellis 1.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 83,000 kB
  • sloc: cpp: 20,813; python: 16,246; sh: 375; makefile: 262; asm: 80; ansic: 58
file content (207 lines) | stat: -rw-r--r-- 5,241 bytes parent folder | download
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