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
|
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2021-22 gatecat <gatecat@ds0.me>
*
* 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 VALIDITY_CHECKING_H
#define VALIDITY_CHECKING_H
#include "fab_cfg.h"
#include "fab_defs.h"
#include "sso_array.h"
#include "nextpnr.h"
NEXTPNR_NAMESPACE_BEGIN
// The validity checking engine for the fabulous configurable CLB
// data that we tag onto cells for fast lookup, so we aren't doing slow hash map accesses in the inner-loop-critical
// validity checking code
struct ControlSig
{
ControlSig() : net(), invert(false){};
ControlSig(IdString net, bool invert) : net(net), invert(invert){};
IdString net;
bool invert;
bool operator==(const ControlSig &other) const { return net == other.net && invert == other.invert; }
bool operator!=(const ControlSig &other) const { return net != other.net || invert != other.invert; }
};
struct CellTags
{
struct
{
SSOArray<IdString, MAX_LUTK> lut_inputs; // for checking fracturable LUTs
bool carry_used = false;
const NetInfo *lut_out = nullptr;
// ...
} comb; // data for LUTs, or the LUT part of combined LUT+FF cells
struct
{
ControlSig clk, sr, en;
bool ff_used = false;
bool async = false;
bool latch = false;
const NetInfo *d = nullptr, *q = nullptr;
} ff; // data for FFs, or the FF part of combined LUT+FF cells
};
// map between cell and tags, using the flat_index that viaduct defines for this purpose
struct CellTagger
{
std::vector<CellTags> data;
const CellTags &get(const CellInfo *ci) const { return data.at(ci->flat_index); }
void assign_for(const Context *ctx, const FabricConfig &cfg, const CellInfo *ci);
};
// we need to add some extra data to CLB bels to track what they do, so we can update CLBState accordingly
struct BelFlags
{
enum BlockType : uint8_t
{
BLOCK_OTHER,
BLOCK_CLB,
// ...
} block = BlockType::BLOCK_OTHER;
enum FuncType : uint8_t
{
FUNC_LC_COMB,
FUNC_FF,
FUNC_MUX,
FUNC_OTHER,
} func;
uint8_t index;
// ...
};
// state of a CLB, for fast bel->cell lookup
// TODO: add valid/dirty tracking for incremental validity re-checking, important once we have bigger/more complex CLBs
// (cf. xilinx/intel arches in nextpnr)
struct CLBState
{
explicit CLBState(const LogicConfig &cfg);
// In combined-LC mode (LC bel contains LUT and FF), this indexes the entire LC bel to cell. In separate mode, this
// indexes the combinational part (LUT or LUT+carry only).
std::unique_ptr<CellInfo *[]> lc_comb;
// In split-LC mode only, this maps FF bel (in CLB) index to cell
std::unique_ptr<CellInfo *[]> ff;
// If there is (a) separate mux bel(s), map them to cells
std::unique_ptr<CellInfo *[]> mux;
bool check_validity(const LogicConfig &cfg, const CellTagger &cell_data);
};
struct BlockTracker
{
Context *ctx;
const FabricConfig &cfg;
std::vector<BelFlags> bel_data;
BlockTracker(Context *ctx, const FabricConfig &cfg) : ctx(ctx), cfg(cfg){};
void set_bel_type(BelId bel, BelFlags::BlockType block, BelFlags::FuncType func, uint8_t index);
void update_bel(BelId bel, CellInfo *old_cell, CellInfo *new_cell);
struct TileData
{
std::unique_ptr<CLBState> clb;
// ...
};
std::vector<std::vector<TileData>> tiles;
bool check_validity(BelId bel, const FabricConfig &cfg, const CellTagger &cell_data);
};
NEXTPNR_NAMESPACE_END
#endif
|