
* Gowin. Add the ability to place registers in IOB IO blocks have registers: for input, for output and for OutputEnable signal - IREG, OREG and TREG respectively. Each of the registers has one implicit non-switched wire, which one depends on the type of register (IREG has a Q wire, OREG has a D wire). Although the registers can be activated independently of each other they share the CLK, ClockEnable and LocalSetReset wires and this places restrictions on the possible combinations of register types in a single IO. Register placement in IO blocks is enabled by specifying the command line keys --vopt ireg_in_iob, --vopt oreg_in_iob, or --vopt ioreg_in_iob. It should be noted that specifying these keys leads to attempts to place registers in IO blocks, but no errors are generated in case of failure. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. Registers in IO Check for unconnected ports. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. IO regs. Verbose warnings. If an attempt to place an FF in an IO block fails, issue a warning detailing the reason for the failure, whether it is a register type conflict, a network requirement violation, or a control signal conflict. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. BUGFIX. Fix FFs compatibility. Flipflops with a fixed ClockEnable input cannot coexist with flipflops with a variable one. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. FFs in IO. Changing diagnostic messages. Placement modes are still specified by the command line keys ireg_in_iob/oreg_in_iob/ioreg_in_iob, but also introduces more granular control in the form of attributes at I/O ports: (* NOIOBFF *) - registers are never placed in this IO, (* IOBFF *) - registers must be placed in this IO, in case of failure a warning (not an error) with the reason for nonplacement is issued, _attribute_absence_ - no diagnostics will be issued: managed to place - good, failed - not bad either. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. Registers in IO. Change the logic for handling command line keys and attributes - attributes allow routines to be placed in IO regardless of global mode. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> * Gowin. Registers in IO. Fix style. Signed-off-by: YRabbit <rabbit@yrabbit.cyou> --------- Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
264 lines
7.6 KiB
C++
264 lines
7.6 KiB
C++
#ifndef GOWIN_H
|
|
#define GOWIN_H
|
|
|
|
#include "nextpnr.h"
|
|
|
|
NEXTPNR_NAMESPACE_BEGIN
|
|
|
|
namespace {
|
|
// Return true if a cell is a LUT
|
|
inline bool type_is_lut(IdString cell_type) { return cell_type.in(id_LUT1, id_LUT2, id_LUT3, id_LUT4); }
|
|
inline bool is_lut(const CellInfo *cell) { return type_is_lut(cell->type); }
|
|
// Return true if a cell is a DFF
|
|
inline bool type_is_dff(IdString cell_type)
|
|
{
|
|
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) { return type_is_dff(cell->type); }
|
|
// Return true if a cell is a ALU
|
|
inline bool type_is_alu(IdString cell_type) { return cell_type == id_ALU; }
|
|
inline bool is_alu(const CellInfo *cell) { return type_is_alu(cell->type); }
|
|
|
|
// io
|
|
inline bool type_is_io(IdString cell_type) { return cell_type.in(id_IBUF, id_OBUF, id_IOBUF, id_TBUF); }
|
|
inline bool is_io(const CellInfo *cell) { return type_is_io(cell->type); }
|
|
|
|
inline bool type_is_diffio(IdString cell_type)
|
|
{
|
|
return cell_type.in(id_ELVDS_IOBUF, id_ELVDS_IBUF, id_ELVDS_TBUF, id_ELVDS_OBUF, id_TLVDS_IOBUF, id_TLVDS_IBUF,
|
|
id_TLVDS_TBUF, id_TLVDS_OBUF);
|
|
}
|
|
inline bool is_diffio(const CellInfo *cell) { return type_is_diffio(cell->type); }
|
|
|
|
// IOLOGIC input and output separately
|
|
|
|
inline bool type_is_iologico(IdString cell_type)
|
|
{
|
|
return cell_type.in(id_ODDR, id_ODDRC, id_OSER4, id_OSER8, id_OSER10, id_OVIDEO, id_IOLOGICO_EMPTY);
|
|
}
|
|
inline bool is_iologico(const CellInfo *cell) { return type_is_iologico(cell->type); }
|
|
|
|
inline bool type_is_iologici(IdString cell_type)
|
|
{
|
|
return cell_type.in(id_IDDR, id_IDDRC, id_IDES4, id_IDES8, id_IDES10, id_IVIDEO, id_IOLOGICI_EMPTY);
|
|
}
|
|
inline bool is_iologici(const CellInfo *cell) { return type_is_iologici(cell->type); }
|
|
|
|
// Return true if a cell is a SSRAM
|
|
inline bool type_is_ssram(IdString cell_type) { return cell_type.in(id_RAM16SDP1, id_RAM16SDP2, id_RAM16SDP4); }
|
|
inline bool is_ssram(const CellInfo *cell) { return type_is_ssram(cell->type); }
|
|
|
|
// Return true if a cell is a BSRAM
|
|
inline bool type_is_bsram(IdString cell_type)
|
|
{
|
|
return cell_type.in(id_SP, id_SPX9, id_pROM, id_pROMX9, id_ROM, id_SDP, id_SDPB, id_SDPX9B, id_DP, id_DPB,
|
|
id_DPX9B);
|
|
}
|
|
inline bool is_bsram(const CellInfo *cell) { return type_is_bsram(cell->type); }
|
|
|
|
// Return true if a cell is a DSP
|
|
inline bool type_is_dsp(IdString cell_type)
|
|
{
|
|
return cell_type.in(id_PADD9, id_PADD18, id_MULT9X9, id_MULT18X18, id_MULT36X36, id_ALU54D, id_MULTALU18X18,
|
|
id_MULTALU36X18, id_MULTADDALU18X18);
|
|
}
|
|
inline bool is_dsp(const CellInfo *cell) { return type_is_dsp(cell->type); }
|
|
|
|
// Return true if a cell is CLKDIV
|
|
inline bool type_is_clkdiv(IdString cell_type) { return cell_type == id_CLKDIV; }
|
|
inline bool is_clkdiv(const CellInfo *cell) { return type_is_clkdiv(cell->type); }
|
|
|
|
// Return true if a cell is CLKDIV2
|
|
inline bool type_is_clkdiv2(IdString cell_type) { return cell_type == id_CLKDIV2; }
|
|
inline bool is_clkdiv2(const CellInfo *cell) { return type_is_clkdiv2(cell->type); }
|
|
|
|
// Return true for HCLK Cells
|
|
inline bool is_hclk(const CellInfo *cell) { return type_is_clkdiv2(cell->type) || type_is_clkdiv(cell->type); }
|
|
|
|
// Return true if a cell is a UserFlash
|
|
inline bool type_is_userflash(IdString cell_type)
|
|
{
|
|
return cell_type.in(id_FLASH96K, id_FLASH256K, id_FLASH608K, id_FLASH128K, id_FLASH64K, id_FLASH64K, id_FLASH64KZ,
|
|
id_FLASH96KA);
|
|
}
|
|
inline bool is_userflash(const CellInfo *cell) { return type_is_userflash(cell->type); }
|
|
|
|
// Return true if a cell is a EMCU
|
|
inline bool type_is_emcu(IdString cell_type) { return cell_type == id_EMCU; }
|
|
inline bool is_emcu(const CellInfo *cell) { return type_is_emcu(cell->type); }
|
|
|
|
// ==========================================
|
|
// extra data in the chip db
|
|
// ==========================================
|
|
NPNR_PACKED_STRUCT(struct Pad_extra_data_POD {
|
|
int32_t pll_tile;
|
|
int32_t pll_bel;
|
|
int32_t pll_type;
|
|
});
|
|
|
|
NPNR_PACKED_STRUCT(struct Tile_extra_data_POD {
|
|
int32_t class_id;
|
|
int16_t io16_x_off;
|
|
int16_t io16_y_off;
|
|
});
|
|
|
|
NPNR_PACKED_STRUCT(struct Bottom_io_cnd_POD {
|
|
int32_t wire_a_net;
|
|
int32_t wire_b_net;
|
|
});
|
|
|
|
NPNR_PACKED_STRUCT(struct Bottom_io_POD {
|
|
// simple OBUF
|
|
static constexpr int8_t NORMAL = 0;
|
|
// DDR
|
|
static constexpr int8_t DDR = 1;
|
|
RelSlice<Bottom_io_cnd_POD> conditions;
|
|
});
|
|
|
|
NPNR_PACKED_STRUCT(struct Spine_bel_POD {
|
|
int32_t spine;
|
|
int32_t bel_x;
|
|
int32_t bel_y;
|
|
int32_t bel_z;
|
|
});
|
|
|
|
NPNR_PACKED_STRUCT(struct Wire_bel_POD {
|
|
int32_t pip_xy;
|
|
int32_t pip_dst;
|
|
int32_t pip_src;
|
|
int32_t bel_x;
|
|
int32_t bel_y;
|
|
int32_t bel_z;
|
|
int32_t side;
|
|
});
|
|
|
|
NPNR_PACKED_STRUCT(struct Constraint_POD {
|
|
int32_t net;
|
|
int32_t row;
|
|
int32_t col;
|
|
int32_t bel;
|
|
int32_t iostd;
|
|
});
|
|
|
|
NPNR_PACKED_STRUCT(struct Extra_package_data_POD { RelSlice<Constraint_POD> cst; });
|
|
|
|
NPNR_PACKED_STRUCT(struct Extra_chip_data_POD {
|
|
int32_t chip_flags;
|
|
Bottom_io_POD bottom_io;
|
|
RelSlice<IdString> diff_io_types;
|
|
RelSlice<Spine_bel_POD> dqce_bels;
|
|
RelSlice<Spine_bel_POD> dcs_bels;
|
|
RelSlice<Wire_bel_POD> dhcen_bels;
|
|
// chip flags
|
|
static constexpr int32_t HAS_SP32 = 1;
|
|
static constexpr int32_t NEED_SP_FIX = 2;
|
|
static constexpr int32_t NEED_BSRAM_OUTREG_FIX = 4;
|
|
static constexpr int32_t NEED_BLKSEL_FIX = 8;
|
|
static constexpr int32_t HAS_BANDGAP = 16;
|
|
});
|
|
|
|
} // namespace
|
|
|
|
// 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,
|
|
ALU0_Z = 30, // :35, 6 ALU
|
|
RAMW_Z = 36, // RAM16SDP4
|
|
|
|
IOBA_Z = 50,
|
|
IOBB_Z = 51, // +IOBC...IOBL
|
|
|
|
IOLOGICA_Z = 70,
|
|
IDES16_Z = 74,
|
|
OSER16_Z = 75,
|
|
|
|
BUFG_Z = 76, // : 81 reserve just in case
|
|
BSRAM_Z = 100,
|
|
|
|
OSC_Z = 274,
|
|
PLL_Z = 275,
|
|
GSR_Z = 276,
|
|
VCC_Z = 277,
|
|
VSS_Z = 278,
|
|
BANDGAP_Z = 279,
|
|
|
|
DQCE_Z = 280, // : 286 reserve for 6 DQCEs
|
|
DCS_Z = 286, // : 288 reserve for 2 DCSs
|
|
DHCEN_Z = 288, // : 298
|
|
|
|
USERFLASH_Z = 298,
|
|
|
|
EMCU_Z = 300,
|
|
|
|
// The two least significant bits encode Z for 9-bit adders and
|
|
// multipliers, if they are equal to 0, then we get Z of their common
|
|
// 18-bit equivalent.
|
|
DSP_Z = 509, // DSP
|
|
|
|
DSP_0_Z = 511, // DSP macro 0
|
|
PADD18_0_0_Z = 512,
|
|
PADD9_0_0_Z = 512 + 1,
|
|
PADD9_0_1_Z = 512 + 2,
|
|
PADD18_0_1_Z = 516,
|
|
PADD9_0_2_Z = 516 + 1,
|
|
PADD9_0_3_Z = 516 + 2,
|
|
|
|
MULT18X18_0_0_Z = 520,
|
|
MULT9X9_0_0_Z = 520 + 1,
|
|
MULT9X9_0_1_Z = 520 + 2,
|
|
MULT18X18_0_1_Z = 524,
|
|
MULT9X9_0_2_Z = 524 + 1,
|
|
MULT9X9_0_3_Z = 524 + 2,
|
|
|
|
ALU54D_0_Z = 524 + 3,
|
|
MULTALU18X18_0_Z = 528,
|
|
MULTALU36X18_0_Z = 528 + 1,
|
|
MULTADDALU18X18_0_Z = 528 + 2,
|
|
|
|
MULT36X36_Z = 528 + 3,
|
|
|
|
DSP_1_Z = 543, // DSP macro 1
|
|
PADD18_1_0_Z = 544,
|
|
PADD9_1_0_Z = 544 + 1,
|
|
PADD9_1_1_Z = 544 + 2,
|
|
PADD18_1_1_Z = 548,
|
|
PADD9_1_2_Z = 548 + 1,
|
|
PADD9_1_3_Z = 548 + 2,
|
|
|
|
MULT18X18_1_0_Z = 552,
|
|
MULT9X9_1_0_Z = 552 + 1,
|
|
MULT9X9_1_1_Z = 552 + 2,
|
|
MULT18X18_1_1_Z = 556,
|
|
MULT9X9_1_2_Z = 556 + 1,
|
|
MULT9X9_1_3_Z = 556 + 2,
|
|
|
|
ALU54D_1_Z = 556 + 3,
|
|
MULTALU18X18_1_Z = 560,
|
|
MULTALU36X18_1_Z = 560 + 1,
|
|
MULTADDALU18X18_1_Z = 560 + 2,
|
|
|
|
// HCLK Bels
|
|
CLKDIV2_0_Z = 610,
|
|
CLKDIV2_1_Z = 611,
|
|
CLKDIV2_2_Z = 612,
|
|
CLKDIV2_3_Z = 613,
|
|
|
|
CLKDIV_0_Z = 620,
|
|
CLKDIV_1_Z = 621,
|
|
CLKDIV_2_Z = 622,
|
|
CLKDIV_3_Z = 623
|
|
};
|
|
}
|
|
|
|
NEXTPNR_NAMESPACE_END
|
|
#endif
|