gowin: Himbaechel. Add GW1NZ-1 BSRAM.
The following primitives are implemented for the GW1NZ-1 chip: * pROM - read only memory - (bitwidth: 1, 2, 4, 8, 16, 32). * pROMX9 - read only memory - (bitwidth: 9, 18, 36). * SDPB - semidual port - (bitwidth: 1, 2, 4, 8, 16, 32). * SDPX9B - semidual port - (bitwidth: 9, 18, 36). * DPB - dual port - (bitwidth: 16). * DPX9B - dual port - (bitwidth: 18). * SP - single port - (bitwidth: 1, 2, 4, 8, 16, 32). * SPX9 - single port - (bitwidth: 9, 18, 36). Also: - The creation of databases for GW1NS-2 has been removed - this was not planned to be supported in Himbaechel from the very beginning and even examples were not created in apicula for this chip due to the lack of boards with it on sale. - It is temporarily prohibited to connect DFFs and LUTs into clusters because for some reason this prevents the creation of images on lower chips (placer cannot find the placement), although without these clusters the images are quite working. Requires further research. - Added creation of ALU with mode 0 - addition. Such an element is not generated by Yosys, but it is a favorite vendor element and its support here greatly simplifies the compilation of vendor netlists. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
f2c280feda
commit
90d4863dd4
@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
project(himbaechel-gowin-chipdb NONE)
|
||||
|
||||
find_package(Python3 3.5 REQUIRED COMPONENTS Interpreter)
|
||||
set(ALL_HIMBAECHEL_GOWIN_DEVICES GW1N-1 GW1NZ-1 GW1NS-2 GW1N-4 GW1N-9 GW1N-9C GW1NS-4 GW2A-18 GW2A-18C)
|
||||
set(ALL_HIMBAECHEL_GOWIN_DEVICES GW1N-1 GW1NZ-1 GW1N-4 GW1N-9 GW1N-9C GW1NS-4 GW2A-18 GW2A-18C)
|
||||
set(HIMBAECHEL_GOWIN_DEVICES "" CACHE STRING
|
||||
"Include support for these Gowin devices (available: ${ALL_HIMBAECHEL_GOWIN_DEVICES})")
|
||||
if(HIMBAECHEL_GOWIN_DEVICES STREQUAL "all")
|
||||
|
@ -685,6 +685,7 @@ X(IOBIS)
|
||||
X(IOBJS)
|
||||
|
||||
// long wires
|
||||
X(LONGWIRE)
|
||||
X(BUFS)
|
||||
X(BUFS0)
|
||||
X(BUFS1)
|
||||
@ -888,9 +889,17 @@ X(WRE)
|
||||
// BSRAM
|
||||
X(BSRAM_SUBTYPE)
|
||||
X(BIT_WIDTH)
|
||||
X(BIT_WIDTH_0)
|
||||
X(BIT_WIDTH_1)
|
||||
X(ROM)
|
||||
X(DP)
|
||||
X(DPB)
|
||||
X(DPX9B)
|
||||
X(SP)
|
||||
X(SPX9)
|
||||
X(SDP)
|
||||
X(SDPB)
|
||||
X(SDPX9B)
|
||||
X(pROM)
|
||||
X(pROMX9)
|
||||
X(BSRAM)
|
||||
|
@ -40,7 +40,11 @@ inline bool type_is_ssram(IdString cell_type) { return cell_type.in(id_RAM16SDP1
|
||||
inline bool is_ssram(const CellInfo *cell) { return type_is_ssram(cell->type); }
|
||||
|
||||
// Return true if a cell is a SSRAM
|
||||
inline bool type_is_bsram(IdString cell_type) { return cell_type.in(id_SP, id_SPX9, id_pROM, id_pROMX9, id_ROM); }
|
||||
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); }
|
||||
|
||||
// ==========================================
|
||||
|
@ -728,7 +728,7 @@ def main():
|
||||
io_tiletypes = db.tile_types['I']
|
||||
ssram_tiletypes = db.tile_types['M']
|
||||
pll_tiletypes = db.tile_types['P']
|
||||
bsram_tiletypes = db.tile_types['B']
|
||||
bsram_tiletypes = db.tile_types.get('B', set())
|
||||
|
||||
# Setup tile grid
|
||||
for x in range(X):
|
||||
|
@ -35,6 +35,9 @@ struct GowinUtils
|
||||
bool have_bottom_io_cnds(void);
|
||||
IdString get_bottom_io_wire_a_net(int8_t condition);
|
||||
IdString get_bottom_io_wire_b_net(int8_t condition);
|
||||
|
||||
// wires
|
||||
inline bool is_wire_type_default(IdString wire_type) { return wire_type == IdString(); }
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -1023,6 +1023,8 @@ struct GowinPacker
|
||||
return cin_ci;
|
||||
}
|
||||
// CIN from logic
|
||||
cin_ci->addInput(id_I0);
|
||||
cin_ci->connectPort(id_I0, ctx->nets.at(ctx->id("$PACKER_GND")).get());
|
||||
cin_ci->addInput(id_I1);
|
||||
cin_ci->addInput(id_I3);
|
||||
cin_ci->connectPort(id_I1, cin_net);
|
||||
@ -1113,6 +1115,12 @@ struct GowinPacker
|
||||
ci->constr_x = alu_chain_len / 6;
|
||||
ci->constr_y = 0;
|
||||
ci->constr_z = alu_chain_len % 6;
|
||||
// XXX mode 0 - ADD
|
||||
if (ci->params[id_ALU_MODE].as_int64() == 0) {
|
||||
ci->renamePort(id_I3, id_I2);
|
||||
ci->renamePort(id_I0, id_I3);
|
||||
ci->renamePort(id_I2, id_I0);
|
||||
}
|
||||
// XXX I2 is pin C which must be set to 1 for all ALU modes except MUL
|
||||
// we use only mode 2 ADDSUB so create and connect this pin
|
||||
ci->addInput(id_I2);
|
||||
@ -1184,7 +1192,7 @@ struct GowinPacker
|
||||
{id_DFFP, id_D}, {id_DFFPE, id_D}, {id_DFFNP, id_D}, {id_DFFNPE, id_D},
|
||||
{id_DFFC, id_D}, {id_DFFCE, id_D}, {id_DFFNC, id_D}, {id_DFFNCE, id_D}};
|
||||
|
||||
int lutffs = h.constrain_cell_pairs(lut_outs, dff_ins, 1);
|
||||
int lutffs = h.constrain_cell_pairs(lut_outs, dff_ins, 0);
|
||||
log_info("Constrained %d LUTFF pairs.\n", lutffs);
|
||||
}
|
||||
|
||||
@ -1275,9 +1283,20 @@ struct GowinPacker
|
||||
// ===================================
|
||||
// Block RAM
|
||||
// ===================================
|
||||
void bsram_rename_ports(CellInfo *ci, int bit_width, char const *from, char const *to, int offset = 0)
|
||||
{
|
||||
int num = (bit_width == 9 || bit_width == 18 || bit_width == 36) ? 36 : 32;
|
||||
for (int i = 0, j = offset; i < num; ++i, ++j) {
|
||||
if (((i + 1) % 9) == 0 && (bit_width == 16 || bit_width == 32)) {
|
||||
++j;
|
||||
}
|
||||
ci->renamePort(ctx->idf(from, i), ctx->idf(to, offset ? j % 36 : j));
|
||||
}
|
||||
}
|
||||
|
||||
void pack_ROM(CellInfo *ci)
|
||||
{
|
||||
// use block 111
|
||||
// XXX use block 111
|
||||
ci->setParam(ctx->id("BLK_SEL"), Property(7, 32));
|
||||
if (ci->type == id_pROM) {
|
||||
ci->setAttr(id_BSRAM_SUBTYPE, Property(""));
|
||||
@ -1295,11 +1314,7 @@ struct GowinPacker
|
||||
ci->addInput(port);
|
||||
ci->connectPort(port, vcc_net);
|
||||
}
|
||||
// use port B
|
||||
ci->renamePort(id_CLK, id_CLKB);
|
||||
ci->renamePort(id_OCE, id_OCEB);
|
||||
ci->renamePort(id_CE, id_CEB);
|
||||
ci->renamePort(id_RESET, id_RESETB);
|
||||
|
||||
ci->addInput(id_WRE);
|
||||
ci->connectPort(id_WRE, vss_net);
|
||||
ci->addInput(id_WREB);
|
||||
@ -1308,20 +1323,158 @@ struct GowinPacker
|
||||
if (!ci->params.count(id_BIT_WIDTH)) {
|
||||
ci->setParam(id_BIT_WIDTH, Property(32, 32));
|
||||
}
|
||||
|
||||
int bit_width = ci->params[id_BIT_WIDTH].as_int64();
|
||||
if (bit_width == 32 || bit_width == 36) {
|
||||
ci->copyPortTo(id_CLK, ci, id_CLKB);
|
||||
ci->copyPortTo(id_CE, ci, id_CEB);
|
||||
ci->copyPortTo(id_OCE, ci, id_OCEB);
|
||||
ci->copyPortTo(id_RESET, ci, id_RESETB);
|
||||
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
ci->renamePort(ctx->idf("AD[%d]", i), ctx->idf("ADA%d", i));
|
||||
ci->copyPortTo(ctx->idf("ADA%d", i), ci, ctx->idf("ADB%d", i));
|
||||
}
|
||||
bsram_rename_ports(ci, bit_width, "DO[%d]", "DO%d");
|
||||
} else {
|
||||
// use port B
|
||||
ci->renamePort(id_CLK, id_CLKB);
|
||||
ci->renamePort(id_OCE, id_OCEB);
|
||||
ci->renamePort(id_CE, id_CEB);
|
||||
ci->renamePort(id_RESET, id_RESETB);
|
||||
|
||||
ci->addInput(id_CEA);
|
||||
ci->connectPort(id_CEA, vss_net);
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
ci->renamePort(ctx->idf("AD[%d]", i), ctx->idf("ADB%d", i));
|
||||
}
|
||||
bsram_rename_ports(ci, bit_width, "DO[%d]", "DO%d", 18);
|
||||
}
|
||||
}
|
||||
|
||||
void pack_SDPB(CellInfo *ci)
|
||||
{
|
||||
if (ci->type == id_SDPB) {
|
||||
ci->setAttr(id_BSRAM_SUBTYPE, Property(""));
|
||||
} else {
|
||||
ci->setAttr(id_BSRAM_SUBTYPE, Property("X9"));
|
||||
}
|
||||
|
||||
NetInfo *vcc_net = ctx->nets.at(ctx->id("$PACKER_VCC")).get();
|
||||
NetInfo *vss_net = ctx->nets.at(ctx->id("$PACKER_GND")).get();
|
||||
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
ci->renamePort(ctx->idf("ADA[%d]", i), ctx->idf("ADA%d", i));
|
||||
ci->renamePort(ctx->idf("ADB[%d]", i), ctx->idf("ADB%d", i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ci->renamePort(ctx->idf("BLKSELA[%d]", i), ctx->idf("BLKSELA%d", i));
|
||||
ci->renamePort(ctx->idf("BLKSELB[%d]", i), ctx->idf("BLKSELB%d", i));
|
||||
}
|
||||
|
||||
ci->copyPortTo(id_OCE, ci, id_OCEB);
|
||||
|
||||
// Port A
|
||||
ci->addInput(id_WRE);
|
||||
ci->connectPort(id_WRE, vcc_net);
|
||||
|
||||
if (!ci->params.count(id_BIT_WIDTH_0)) {
|
||||
ci->setParam(id_BIT_WIDTH_0, Property(32, 32));
|
||||
}
|
||||
|
||||
int bit_width = ci->params[id_BIT_WIDTH_0].as_int64();
|
||||
bsram_rename_ports(ci, bit_width, "DI[%d]", "DI%d");
|
||||
|
||||
// Port B
|
||||
ci->addInput(id_WREB);
|
||||
if (!ci->params.count(id_BIT_WIDTH_1)) {
|
||||
ci->setParam(id_BIT_WIDTH_1, Property(32, 32));
|
||||
}
|
||||
bit_width = ci->params[id_BIT_WIDTH_1].as_int64();
|
||||
if (bit_width == 32 || bit_width == 36) {
|
||||
ci->connectPort(id_WREB, vcc_net);
|
||||
bsram_rename_ports(ci, bit_width, "DO[%d]", "DO%d");
|
||||
} else {
|
||||
ci->connectPort(id_WREB, vss_net);
|
||||
bsram_rename_ports(ci, bit_width, "DO[%d]", "DO%d", 18);
|
||||
}
|
||||
}
|
||||
|
||||
void pack_DPB(CellInfo *ci)
|
||||
{
|
||||
if (ci->type == id_DPB) {
|
||||
ci->setAttr(id_BSRAM_SUBTYPE, Property(""));
|
||||
} else {
|
||||
ci->setAttr(id_BSRAM_SUBTYPE, Property("X9"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
ci->renamePort(ctx->idf("ADA[%d]", i), ctx->idf("ADA%d", i));
|
||||
ci->renamePort(ctx->idf("ADB[%d]", i), ctx->idf("ADB%d", i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ci->renamePort(ctx->idf("BLKSELA[%d]", i), ctx->idf("BLKSELA%d", i));
|
||||
ci->renamePort(ctx->idf("BLKSELB[%d]", i), ctx->idf("BLKSELB%d", i));
|
||||
}
|
||||
|
||||
if (!ci->params.count(id_BIT_WIDTH_0)) {
|
||||
ci->setParam(id_BIT_WIDTH_0, Property(16, 32));
|
||||
}
|
||||
int bit_width = ci->params[id_BIT_WIDTH_0].as_int64();
|
||||
if (bit_width == 32 || bit_width == 36) {
|
||||
log_error("Bit width %d is not supported\n", bit_width);
|
||||
}
|
||||
bsram_rename_ports(ci, bit_width, "DIA[%d]", "DIA%d");
|
||||
bsram_rename_ports(ci, bit_width, "DOA[%d]", "DOA%d");
|
||||
|
||||
if (!ci->params.count(id_BIT_WIDTH_1)) {
|
||||
ci->setParam(id_BIT_WIDTH_1, Property(16, 32));
|
||||
}
|
||||
bit_width = ci->params[id_BIT_WIDTH_1].as_int64();
|
||||
if (bit_width == 32 || bit_width == 36) {
|
||||
log_error("Bit width %d is not supported\n", bit_width);
|
||||
}
|
||||
bsram_rename_ports(ci, bit_width, "DIB[%d]", "DIB%d");
|
||||
bsram_rename_ports(ci, bit_width, "DOB[%d]", "DOB%d");
|
||||
}
|
||||
|
||||
void pack_SP(CellInfo *ci)
|
||||
{
|
||||
if (ci->type == id_SP) {
|
||||
ci->setAttr(id_BSRAM_SUBTYPE, Property(""));
|
||||
} else {
|
||||
ci->setAttr(id_BSRAM_SUBTYPE, Property("X9"));
|
||||
}
|
||||
|
||||
NetInfo *vcc_net = ctx->nets.at(ctx->id("$PACKER_VCC")).get();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ci->renamePort(ctx->idf("BLKSEL[%d]", i), ctx->idf("BLKSEL%d", i));
|
||||
ci->copyPortTo(ctx->idf("BLKSEL%d", i), ci, ctx->idf("BLKSELB%d", i));
|
||||
}
|
||||
|
||||
if (!ci->params.count(id_BIT_WIDTH)) {
|
||||
ci->setParam(id_BIT_WIDTH, Property(32, 32));
|
||||
}
|
||||
int bit_width = ci->params[id_BIT_WIDTH].as_int64();
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
ci->renamePort(ctx->idf("AD[%d]", i), ctx->idf("ADB%d", i));
|
||||
}
|
||||
int out_num = (bit_width == 9 || bit_width == 18) ? 36 : 32;
|
||||
for (int i = 0, j = 18; i < out_num; ++i, ++j) {
|
||||
if (((i + 1) % 9) == 0 && bit_width == 16) {
|
||||
++j;
|
||||
ci->renamePort(ctx->idf("AD[%d]", i), ctx->idf("AD%d", i));
|
||||
if (bit_width == 32 || bit_width == 36) {
|
||||
ci->copyPortTo(ctx->idf("AD%d", i), ci, ctx->idf("ADB%d", i));
|
||||
}
|
||||
ci->renamePort(ctx->idf("DO[%d]", i), ctx->idf("DO%d", j % 36));
|
||||
}
|
||||
if (bit_width == 32 || bit_width == 36) {
|
||||
ci->copyPortTo(id_CLK, ci, id_CLKB);
|
||||
ci->copyPortTo(id_OCE, ci, id_OCEB);
|
||||
ci->copyPortTo(id_CE, ci, id_CEB);
|
||||
ci->copyPortTo(id_RESET, ci, id_RESETB);
|
||||
ci->copyPortTo(id_WRE, ci, id_WREB);
|
||||
ci->disconnectPort(ctx->id("ADB4"));
|
||||
ci->connectPort(ctx->id("ADB4"), vcc_net);
|
||||
}
|
||||
bsram_rename_ports(ci, bit_width, "DI[%d]", "DI%d");
|
||||
bsram_rename_ports(ci, bit_width, "DO[%d]", "DO%d");
|
||||
}
|
||||
|
||||
void pack_bsram(void)
|
||||
@ -1336,11 +1489,26 @@ struct GowinPacker
|
||||
log_info(" pack %s\n", ci->type.c_str(ctx));
|
||||
}
|
||||
switch (ci->type.hash()) {
|
||||
case ID_pROM: /* fallthrough */
|
||||
case ID_pROMX9:
|
||||
case ID_pROMX9: /* fallthrough */
|
||||
case ID_pROM:
|
||||
pack_ROM(ci);
|
||||
ci->type = id_ROM;
|
||||
break;
|
||||
case ID_SDPX9B: /* fallthrough */
|
||||
case ID_SDPB:
|
||||
pack_SDPB(ci);
|
||||
ci->type = id_SDP;
|
||||
break;
|
||||
case ID_DPX9B: /* fallthrough */
|
||||
case ID_DPB:
|
||||
pack_DPB(ci);
|
||||
ci->type = id_DP;
|
||||
break;
|
||||
case ID_SPX9: /* fallthrough */
|
||||
case ID_SP:
|
||||
pack_SP(ci);
|
||||
ci->type = id_SP;
|
||||
break;
|
||||
default:
|
||||
log_error("Unsupported BSRAM type '%s'\n", ci->type.c_str(ctx));
|
||||
}
|
||||
@ -1463,7 +1631,8 @@ struct GowinPacker
|
||||
pack_alus();
|
||||
ctx->check();
|
||||
|
||||
constrain_lutffs();
|
||||
// XXX Leads to the impossibility of placement on lower models.
|
||||
// constrain_lutffs();
|
||||
ctx->check();
|
||||
|
||||
pack_pll();
|
||||
|
Loading…
Reference in New Issue
Block a user