aboutsummaryrefslogtreecommitdiffstats
path: root/gowin/cells.h
blob: 7aba480531baa28ffdeada291ba816e4be16d7d8 (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
/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2019  gatecat <gatecat@ds0.me>
 *  Copyright (C) 2020  Pepijn de Vos <pepijn@symbioticeda.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.
 *
 */

#include "nextpnr.h"

#ifndef GENERIC_CELLS_H
#define GENERIC_CELLS_H

NEXTPNR_NAMESPACE_BEGIN

// Create a generic arch cell and return it
// Name will be automatically assigned if not specified
std::unique_ptr<CellInfo> create_generic_cell(Context *ctx, IdString type, std::string name = "");

// Return true if a cell is a LUT
inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell)
{
    switch (cell->type.index) {
    case ID_LUT1:
    case ID_LUT2:
    case ID_LUT3:
    case ID_LUT4:
        return true;
    default:
        return false;
    }
}

// Return true if a cell is a wide LUT mux
inline bool is_widelut(const BaseCtx *ctx, const CellInfo *cell)
{
    switch (cell->type.index) {
    case ID_MUX2_LUT5:
    case ID_MUX2_LUT6:
    case ID_MUX2_LUT7:
    case ID_MUX2_LUT8:
        return true;
    default:
        return false;
    }
}

inline bool is_alu(const BaseCtx *ctx, const CellInfo *cell) { return (cell->type.index == ID_ALU); }

// is MUX2_LUT5
inline bool is_mux2_lut5(const BaseCtx *ctx, const CellInfo *cell) { return (cell->type.index == ID_MUX2_LUT5); }

// is MUX2_LUT6
inline bool is_mux2_lut6(const BaseCtx *ctx, const CellInfo *cell) { return (cell->type.index == ID_MUX2_LUT6); }

// is MUX2_LUT7
inline bool is_mux2_lut7(const BaseCtx *ctx, const CellInfo *cell) { return (cell->type.index == ID_MUX2_LUT7); }

// is MUX2_LUT8
inline bool is_mux2_lut8(const BaseCtx *ctx, const CellInfo *cell) { return (cell->type.index == ID_MUX2_LUT8); }

// Return true if a cell is a flipflop
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell)
{
    switch (cell->type.index) {
    case ID_DFF:
    case ID_DFFE:
    case ID_DFFS:
    case ID_DFFSE:
    case ID_DFFR:
    case ID_DFFRE:
    case ID_DFFP:
    case ID_DFFPE:
    case ID_DFFC:
    case ID_DFFCE:
    case ID_DFFN:
    case ID_DFFNE:
    case ID_DFFNS:
    case ID_DFFNSE:
    case ID_DFFNR:
    case ID_DFFNRE:
    case ID_DFFNP:
    case ID_DFFNPE:
    case ID_DFFNC:
    case ID_DFFNCE:
        return true;
    default:
        return false;
    }
}

inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SLICE; }

inline bool is_sram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_RAM16SDP4; }

inline bool is_iob(const Context *ctx, const CellInfo *cell) { return (cell->type.index == ID_IOB); }

// Convert a LUT primitive to (part of) an GENERIC_SLICE, swapping ports
// as needed. Set no_dff if a DFF is not being used, so that the output
// can be reconnected
void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff = true);

// Convert a DFF primitive to (part of) an GENERIC_SLICE, setting parameters
// and reconnecting signals as necessary. If pass_thru_lut is True, the LUT will
// be configured as pass through and D connected to I0, otherwise D will be
// ignored
void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false);

// Convert a Gowin IO buffer to a IOB bel
void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells);

// Reconnect PLL signals (B)
void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll);
void reconnect_rpll(Context *ctx, CellInfo *pll, CellInfo *new_pll);

// Convert RAM16 to write port
void sram_to_ramw_split(Context *ctx, CellInfo *ram, CellInfo *ramw);

// Convert RAM16 to slice
void sram_to_slice(Context *ctx, CellInfo *ram, CellInfo *slice, int index);

NEXTPNR_NAMESPACE_END

#endif