2023-06-30 15:18:14 +08:00
|
|
|
#ifndef GOWIN_H
|
|
|
|
#define GOWIN_H
|
|
|
|
|
|
|
|
#include "himbaechel_api.h"
|
|
|
|
#include "himbaechel_helpers.h"
|
|
|
|
#include "nextpnr.h"
|
|
|
|
|
|
|
|
#define GEN_INIT_CONSTIDS
|
|
|
|
#define HIMBAECHEL_CONSTIDS "uarch/gowin/constids.inc"
|
|
|
|
#include "himbaechel_constids.h"
|
|
|
|
|
|
|
|
NEXTPNR_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct GowinImpl : HimbaechelAPI
|
|
|
|
{
|
|
|
|
|
|
|
|
~GowinImpl(){};
|
|
|
|
void init_constids(Arch *arch) override { init_uarch_constids(arch); }
|
|
|
|
void init(Context *ctx) override;
|
|
|
|
|
|
|
|
void prePlace() override;
|
2023-07-01 17:09:27 +08:00
|
|
|
void pack() override;
|
2023-06-30 15:18:14 +08:00
|
|
|
|
|
|
|
bool isBelLocationValid(BelId bel, bool explain_invalid) const override;
|
|
|
|
|
|
|
|
// Bel bucket functions
|
|
|
|
IdString getBelBucketForCellType(IdString cell_type) const override;
|
|
|
|
|
|
|
|
bool isValidBelForCellType(IdString cell_type, BelId bel) const override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
HimbaechelHelpers h;
|
|
|
|
|
|
|
|
// Validity checking
|
|
|
|
struct GowinCellInfo
|
|
|
|
{
|
2023-06-30 20:44:19 +08:00
|
|
|
const NetInfo *lut_f = nullptr;
|
2023-07-01 17:09:27 +08:00
|
|
|
const NetInfo *ff_d = nullptr, *ff_ce = nullptr, *ff_clk = nullptr, *ff_lsr = nullptr;
|
2023-06-30 15:18:14 +08:00
|
|
|
};
|
|
|
|
std::vector<GowinCellInfo> fast_cell_info;
|
|
|
|
void assign_cell_info();
|
|
|
|
bool slice_valid(int x, int y, int z) const;
|
|
|
|
|
2023-07-01 17:09:27 +08:00
|
|
|
// modify LUTs with constant inputs
|
|
|
|
void mod_lut_inputs(void);
|
2023-06-30 15:18:14 +08:00
|
|
|
|
2023-07-02 14:09:39 +08:00
|
|
|
void pack_wideluts(void);
|
|
|
|
|
2023-07-01 17:09:27 +08:00
|
|
|
// Return true if a cell is a LUT
|
|
|
|
inline bool type_is_lut(IdString cell_type) const { return cell_type.in(id_LUT1, id_LUT2, id_LUT3, id_LUT4); }
|
|
|
|
inline bool is_lut(const CellInfo *cell) const { return type_is_lut(cell->type); }
|
|
|
|
// Return true if a cell is a DFF
|
|
|
|
inline bool type_is_dff(IdString cell_type) const
|
|
|
|
{
|
|
|
|
return cell_type.in(id_DFF, id_DFFE, id_DFFN, id_DFFNE, id_DFFS, id_DFFSE, id_DFFNS, id_DFFNSE, id_DFFR,
|
|
|
|
id_DFFRE, id_DFFNR, id_DFFNRE, id_DFFP, id_DFFPE, id_DFFNP, id_DFFNPE, id_DFFC, id_DFFCE,
|
|
|
|
id_DFFNC, id_DFFNCE);
|
|
|
|
}
|
|
|
|
inline bool is_dff(const CellInfo *cell) const { return type_is_dff(cell->type); }
|
2023-06-30 15:18:14 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct GowinArch : HimbaechelArch
|
|
|
|
{
|
|
|
|
GowinArch() : HimbaechelArch("gowin"){};
|
|
|
|
std::unique_ptr<HimbaechelAPI> create(const dict<std::string, std::string> &args)
|
|
|
|
{
|
|
|
|
return std::make_unique<GowinImpl>();
|
|
|
|
}
|
|
|
|
} exampleArch;
|
|
|
|
} // namespace
|
|
|
|
|
2023-07-02 14:09:39 +08:00
|
|
|
// Bels Z ranges. It is desirable that these numbers be synchronized with the chipdb generator
|
|
|
|
namespace BelZ {
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
LUT0_Z = 0,
|
|
|
|
LUT7_Z = 14,
|
|
|
|
MUX20_Z = 16,
|
|
|
|
MUX21_Z = 18,
|
|
|
|
MUX23_Z = 22,
|
|
|
|
MUX27_Z = 29,
|
|
|
|
|
|
|
|
VCC_Z = 277,
|
|
|
|
VSS_Z = 278
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-06-30 15:18:14 +08:00
|
|
|
NEXTPNR_NAMESPACE_END
|
|
|
|
#endif
|