gowin: Himbaechel. Implement the GSR primitive
On GW2A chips, the global set/reset is in its own cell. Also corrections to ALU generation. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
6cac19c055
commit
b2ec06dfe8
@ -1076,3 +1076,11 @@ X(MUX_SEL)
|
||||
X(ALU_CIN)
|
||||
X(ALU_COUT)
|
||||
|
||||
// fake dff inputs
|
||||
X(XD0)
|
||||
X(XD1)
|
||||
X(XD2)
|
||||
X(XD3)
|
||||
X(XD4)
|
||||
X(XD5)
|
||||
|
||||
|
@ -90,6 +90,7 @@ void GowinImpl::init(Context *ctx)
|
||||
partno = ctx->id(pn);
|
||||
ctx->settings[ctx->id("packer.partno")] = pn;
|
||||
|
||||
// package and speed class
|
||||
std::regex speedre = std::regex("(.*)(C[0-9]/I[0-9])$");
|
||||
std::smatch match;
|
||||
|
||||
@ -106,7 +107,7 @@ void GowinImpl::init(Context *ctx)
|
||||
}
|
||||
|
||||
if (ctx->debug) {
|
||||
log_info("packages:%d\n", ctx->chip_info->packages.ssize());
|
||||
log_info("packages:%ld\n", ctx->chip_info->packages.ssize());
|
||||
}
|
||||
for (int i = 0; i < ctx->chip_info->packages.ssize(); ++i) {
|
||||
if (IdString(ctx->chip_info->packages[i].name) == package_idx) {
|
||||
@ -121,6 +122,7 @@ void GowinImpl::init(Context *ctx)
|
||||
log_error("No package for partnumber %s\n", partno.c_str(ctx));
|
||||
}
|
||||
|
||||
// constraints
|
||||
if (args.options.count("cst")) {
|
||||
ctx->settings[ctx->id("cst.filename")] = args.options.at("cst");
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ MUX27_Z = 29
|
||||
ALU0_Z = 30 # : 35, 6 ALUs
|
||||
RAMW_Z = 36 # RAM16SDP4
|
||||
|
||||
GSR_Z = 276
|
||||
VCC_Z = 277
|
||||
GND_Z = 278
|
||||
|
||||
@ -140,6 +141,8 @@ def create_switch_matrix(tt: TileType, db: chipdb, x: int, y: int):
|
||||
def get_wire_type(name):
|
||||
if name.startswith('GB') or name.startswith('GT'):
|
||||
return "GLOBAL_CLK"
|
||||
elif name in {'XD0', 'XD1', 'XD2', 'XD3', 'XD4', 'XD5',}:
|
||||
return "X0"
|
||||
return ""
|
||||
|
||||
for dst, srcs in db.grid[y][x].pips.items():
|
||||
@ -188,6 +191,22 @@ def create_corner_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
|
||||
create_switch_matrix(tt, db, x, y)
|
||||
return (ttyp, tt)
|
||||
|
||||
# Global set/reset. GW2A series has special cell for it
|
||||
def create_gsr_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
|
||||
if ttyp in created_tiletypes:
|
||||
return ttyp, None
|
||||
typename = "GSR"
|
||||
tt = chip.create_tile_type(f"{typename}_{ttyp}")
|
||||
tt.extra_data = TileExtraData(chip.strs.id(typename))
|
||||
|
||||
portmap = db.grid[y][x].bels['GSR'].portmap
|
||||
tt.create_wire(portmap['GSRI'], "GSRI")
|
||||
io = tt.create_bel("GSR", "GSR", z = GSR_Z)
|
||||
tt.add_bel_pin(io, "GSRI", portmap['GSRI'], PinType.INPUT)
|
||||
|
||||
create_switch_matrix(tt, db, x, y)
|
||||
return (ttyp, tt)
|
||||
|
||||
# simple IO - only A and B
|
||||
def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
|
||||
if ttyp in created_tiletypes:
|
||||
@ -393,6 +412,7 @@ def main():
|
||||
logic_tiletypes = {12, 13, 14, 15, 16}
|
||||
io_tiletypes = {52, 53, 55, 58, 59, 64, 65, 66}
|
||||
ssram_tiletypes = {17, 18, 19}
|
||||
gsr_tiletypes = {1}
|
||||
# Setup tile grid
|
||||
for x in range(X):
|
||||
for y in range(Y):
|
||||
@ -403,7 +423,11 @@ def main():
|
||||
created_tiletypes.add(ttyp)
|
||||
ch.set_tile_type(x, y, f"CORNER_{ttyp}")
|
||||
continue
|
||||
if ttyp in logic_tiletypes:
|
||||
if ttyp in gsr_tiletypes:
|
||||
ttyp, _ = create_gsr_tiletype(ch, db, x, y, ttyp)
|
||||
created_tiletypes.add(ttyp)
|
||||
ch.set_tile_type(x, y, f"GSR_{ttyp}")
|
||||
elif ttyp in logic_tiletypes:
|
||||
ttyp, _ = create_logic_tiletype(ch, db, x, y, ttyp)
|
||||
created_tiletypes.add(ttyp)
|
||||
ch.set_tile_type(x, y, f"LOGIC_{ttyp}")
|
||||
|
@ -249,10 +249,14 @@ struct GowinPacker
|
||||
|
||||
if (cin_net->name == ctx->id("$PACKER_GND")) {
|
||||
cin_ci->params[id_ALU_MODE] = std::string("C2L");
|
||||
cin_ci->addInput(id_I2);
|
||||
cin_ci->connectPort(id_I2, ctx->nets[ctx->id("$PACKER_VCC")].get());
|
||||
return cin_ci;
|
||||
}
|
||||
if (cin_net->name == ctx->id("$PACKER_VCC")) {
|
||||
cin_ci->params[id_ALU_MODE] = std::string("ONE2C");
|
||||
cin_ci->addInput(id_I2);
|
||||
cin_ci->connectPort(id_I2, ctx->nets[ctx->id("$PACKER_VCC")].get());
|
||||
return cin_ci;
|
||||
}
|
||||
// CIN from logic
|
||||
@ -501,10 +505,47 @@ struct GowinPacker
|
||||
}
|
||||
}
|
||||
|
||||
// Pack global set-reset
|
||||
void pack_gsr(void)
|
||||
{
|
||||
log_info("Packing GSR..\n");
|
||||
|
||||
bool user_gsr = false;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx));
|
||||
if (ci->type == id_GSR) {
|
||||
user_gsr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!user_gsr) {
|
||||
bool have_gsr_bel = false;
|
||||
auto bels = ctx->getBels();
|
||||
for (auto bid : bels) {
|
||||
if (ctx->getBelType(bid) == id_GSR) {
|
||||
have_gsr_bel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (have_gsr_bel) {
|
||||
// make default GSR
|
||||
auto gsr_cell = std::make_unique<CellInfo>(ctx, id_GSR, id_GSR);
|
||||
gsr_cell->addInput(id_GSRI);
|
||||
gsr_cell->connectPort(id_GSRI, ctx->nets[ctx->id("$PACKER_VCC")].get());
|
||||
ctx->cells[gsr_cell->name] = std::move(gsr_cell);
|
||||
} else {
|
||||
log_info("No GSR in the chip base\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run(void)
|
||||
{
|
||||
pack_iobs();
|
||||
handle_constants();
|
||||
pack_gsr();
|
||||
pack_wideluts();
|
||||
pack_alus();
|
||||
constrain_lutffs();
|
||||
|
Loading…
Reference in New Issue
Block a user