aboutsummaryrefslogtreecommitdiffstats
path: root/generic/viaduct/fabulous/validity_check.h
blob: 1f21e07b583fef4e6ebd2ac99ca1458f2b950bbc (plain)
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
/*
 *  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);
};

struct PseudoPipTags
{
    BelId bel;
    enum PPType : uint16_t
    {
        NONE,
        LUT_CONST,
        LUT_PERM,
    } type;
    uint16_t data;
    PseudoPipTags(PPType type = NONE, BelId bel = BelId(), uint16_t data = 0x0) : bel(bel), type(type), data(data) {}
};

NEXTPNR_NAMESPACE_END

#endif