gowin: Himbaechel. Initial BSRAM support
Only pROM/pROMX9 for now Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
e3f4578b3b
commit
f2c280feda
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user