gowin: Himbaechel. Initial BSRAM support

Only pROM/pROMX9 for now

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2023-10-03 21:11:40 +10:00 committed by myrtle
parent e3f4578b3b
commit f2c280feda
5 changed files with 160 additions and 4 deletions

View File

@ -885,6 +885,27 @@ X(DIC)
X(DID) X(DID)
X(WRE) X(WRE)
// BSRAM
X(BSRAM_SUBTYPE)
X(BIT_WIDTH)
X(ROM)
X(SP)
X(SPX9)
X(pROM)
X(pROMX9)
X(BSRAM)
X(OCE)
X(OCEA)
X(OCEB)
X(CEA)
X(CEB)
X(RESETA)
X(RESETB)
X(WREA)
X(WREB)
X(CLKA)
X(CLKB)
// IOB types // IOB types
X(IBUF) X(IBUF)
X(OBUF) X(OBUF)
@ -1064,6 +1085,8 @@ X(BOTTOM_IO_PORT_A)
X(BOTTOM_IO_PORT_B) X(BOTTOM_IO_PORT_B)
X(IOLOGIC_DUMMY) X(IOLOGIC_DUMMY)
//
// wire types // wire types
X(GLOBAL_CLK) X(GLOBAL_CLK)
X(TILE_CLK) X(TILE_CLK)

View File

@ -266,6 +266,9 @@ IdString GowinImpl::getBelBucketForCellType(IdString cell_type) const
if (type_is_iologic(cell_type)) { if (type_is_iologic(cell_type)) {
return id_IOLOGIC; return id_IOLOGIC;
} }
if (type_is_bsram(cell_type)) {
return id_BSRAM;
}
if (cell_type == id_GOWIN_GND) { if (cell_type == id_GOWIN_GND) {
return id_GND; return id_GND;
} }
@ -293,6 +296,9 @@ bool GowinImpl::isValidBelForCellType(IdString cell_type, BelId bel) const
if (bel_type == id_IOLOGIC) { if (bel_type == id_IOLOGIC) {
return type_is_iologic(cell_type); return type_is_iologic(cell_type);
} }
if (bel_type == id_BSRAM) {
return type_is_bsram(cell_type);
}
if (bel_type == id_GND) { if (bel_type == id_GND) {
return cell_type == id_GOWIN_GND; return cell_type == id_GOWIN_GND;
} }

View File

@ -39,6 +39,10 @@ inline bool is_iologic(const CellInfo *cell) { return type_is_iologic(cell->type
inline bool type_is_ssram(IdString cell_type) { return cell_type.in(id_RAM16SDP1, id_RAM16SDP2, id_RAM16SDP4); } 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); } 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 is_bsram(const CellInfo *cell) { return type_is_bsram(cell->type); }
// ========================================== // ==========================================
// extra data in the chip db // extra data in the chip db
// ========================================== // ==========================================
@ -89,6 +93,7 @@ enum
OSER16_Z = 73, OSER16_Z = 73,
BUFG_Z = 74, // : 81 reserve just in case BUFG_Z = 74, // : 81 reserve just in case
BSRAM_Z = 100,
OSC_Z = 274, OSC_Z = 274,
PLL_Z = 275, PLL_Z = 275,

View File

@ -33,6 +33,7 @@ IDES16_Z = 72
OSER16_Z = 73 OSER16_Z = 73
BUFG_Z = 74 # : 81 reserve just in case BUFG_Z = 74 # : 81 reserve just in case
BSRAM_Z = 100
OSC_Z = 274 OSC_Z = 274
PLL_Z = 275 PLL_Z = 275
@ -561,9 +562,49 @@ def create_ssram_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tde
tt.add_bel_pin(ff, f"RAD[{i}]", f"{lut_inputs[i]}0", PinType.INPUT) tt.add_bel_pin(ff, f"RAD[{i}]", f"{lut_inputs[i]}0", PinType.INPUT)
tt.add_bel_pin(ff, f"DO[{i}]", f"F{i}", PinType.OUTPUT) tt.add_bel_pin(ff, f"DO[{i}]", f"F{i}", PinType.OUTPUT)
tt.add_bel_pin(ff, f"CLK", "CLK2", PinType.INPUT) tt.add_bel_pin(ff, "CLK", "CLK2", PinType.INPUT)
tt.add_bel_pin(ff, f"CE", "CE2", PinType.INPUT) tt.add_bel_pin(ff, "CE", "CE2", PinType.INPUT)
tt.add_bel_pin(ff, f"WRE", "LSR2", PinType.INPUT) tt.add_bel_pin(ff, "WRE", "LSR2", PinType.INPUT)
return tt
# BSRAM
_bsram_inputs = {'CLK', 'OCE', 'CE', 'RESET', 'WRE'}
def create_bsram_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: TypeDesc):
typename = "BSRAM"
tiletype = f"{typename}_{ttyp}"
if tdesc.sfx != 0:
tiletype += f"_{tdesc.sfx}"
tt = chip.create_tile_type(tiletype)
tt.extra_data = TileExtraData(chip.strs.id(typename))
portmap = db.grid[y][x].bels['BSRAM'].portmap
bsram = tt.create_bel("BSRAM", "BSRAM", z = BSRAM_Z)
def add_port_wire(tt, bel, name, wire_type = "BSRAM_I", port_type = PinType.INPUT):
wire = portmap[name]
if not tt.has_wire(wire):
if name.startswith('CLK'):
tt.create_wire(wire, "TILE_CLK")
else:
tt.create_wire(wire, wire_type)
tt.add_bel_pin(bel, name, wire, port_type)
for sfx in {'', 'A', 'B'}:
for inp in _bsram_inputs:
add_port_wire(tt, bsram, f"{inp}{sfx}")
for idx in range(3):
add_port_wire(tt, bsram, f"BLKSEL{sfx}{idx}")
for idx in range(14):
add_port_wire(tt, bsram, f"AD{sfx}{idx}")
for idx in range(18):
add_port_wire(tt, bsram, f"DI{sfx}{idx}")
add_port_wire(tt, bsram, f"DO{sfx}{idx}", "BSRAM_O", PinType.OUTPUT)
if not sfx:
for idx in range(18, 36):
add_port_wire(tt, bsram, f"DI{idx}")
add_port_wire(tt, bsram, f"DO{idx}", "BSRAM_O", PinType.OUTPUT)
tdesc.tiletype = tiletype
return tt return tt
# PLL main tile # PLL main tile
@ -687,6 +728,7 @@ def main():
io_tiletypes = db.tile_types['I'] io_tiletypes = db.tile_types['I']
ssram_tiletypes = db.tile_types['M'] ssram_tiletypes = db.tile_types['M']
pll_tiletypes = db.tile_types['P'] pll_tiletypes = db.tile_types['P']
bsram_tiletypes = db.tile_types['B']
# Setup tile grid # Setup tile grid
for x in range(X): for x in range(X):
@ -704,6 +746,8 @@ def main():
create_tiletype(create_io_tiletype, ch, db, x, y, ttyp) create_tiletype(create_io_tiletype, ch, db, x, y, ttyp)
elif ttyp in pll_tiletypes: elif ttyp in pll_tiletypes:
create_tiletype(create_pll_tiletype, ch, db, x, y, ttyp) create_tiletype(create_pll_tiletype, ch, db, x, y, ttyp)
elif ttyp in bsram_tiletypes:
create_tiletype(create_bsram_tiletype, ch, db, x, y, ttyp)
else: else:
create_tiletype(create_null_tiletype, ch, db, x, y, ttyp) create_tiletype(create_null_tiletype, ch, db, x, y, ttyp)

View File

@ -1191,7 +1191,6 @@ struct GowinPacker
// =================================== // ===================================
// SSRAM cluster // SSRAM cluster
// =================================== // ===================================
// create ALU filler block
std::unique_ptr<CellInfo> ssram_make_lut(Context *ctx, CellInfo *ci, int index) std::unique_ptr<CellInfo> ssram_make_lut(Context *ctx, CellInfo *ci, int index)
{ {
IdString name_id = ctx->idf("%s_LUT%d", ci->name.c_str(ctx), index); IdString name_id = ctx->idf("%s_LUT%d", ci->name.c_str(ctx), index);
@ -1273,6 +1272,82 @@ struct GowinPacker
} }
} }
// ===================================
// Block RAM
// ===================================
void pack_ROM(CellInfo *ci)
{
// use block 111
ci->setParam(ctx->id("BLK_SEL"), Property(7, 32));
if (ci->type == id_pROM) {
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 < 3; ++i) {
IdString port = ctx->idf("BLKSEL%d", i);
ci->addInput(port);
ci->connectPort(port, vcc_net);
port = ctx->idf("BLKSELB%d", i);
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);
ci->connectPort(id_WREB, vss_net);
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) {
log_error("Bit width %d is not supported\n", bit_width);
}
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("DO[%d]", i), ctx->idf("DO%d", j % 36));
}
}
void pack_bsram(void)
{
log_info("Pack BSRAMs...\n");
for (auto &cell : ctx->cells) {
auto ci = cell.second.get();
if (is_bsram(ci)) {
if (ctx->verbose) {
log_info(" pack %s\n", ci->type.c_str(ctx));
}
switch (ci->type.hash()) {
case ID_pROM: /* fallthrough */
case ID_pROMX9:
pack_ROM(ci);
ci->type = id_ROM;
break;
default:
log_error("Unsupported BSRAM type '%s'\n", ci->type.c_str(ctx));
}
}
}
}
// =================================== // ===================================
// Global set/reset // Global set/reset
// =================================== // ===================================
@ -1397,6 +1472,9 @@ struct GowinPacker
pack_ram16sdp4(); pack_ram16sdp4();
ctx->check(); ctx->check();
pack_bsram();
ctx->check();
pack_buffered_nets(); pack_buffered_nets();
ctx->fixupHierarchy(); ctx->fixupHierarchy();