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_CIN)
|
||||||
X(ALU_COUT)
|
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);
|
partno = ctx->id(pn);
|
||||||
ctx->settings[ctx->id("packer.partno")] = pn;
|
ctx->settings[ctx->id("packer.partno")] = pn;
|
||||||
|
|
||||||
|
// package and speed class
|
||||||
std::regex speedre = std::regex("(.*)(C[0-9]/I[0-9])$");
|
std::regex speedre = std::regex("(.*)(C[0-9]/I[0-9])$");
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ void GowinImpl::init(Context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->debug) {
|
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) {
|
for (int i = 0; i < ctx->chip_info->packages.ssize(); ++i) {
|
||||||
if (IdString(ctx->chip_info->packages[i].name) == package_idx) {
|
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));
|
log_error("No package for partnumber %s\n", partno.c_str(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constraints
|
||||||
if (args.options.count("cst")) {
|
if (args.options.count("cst")) {
|
||||||
ctx->settings[ctx->id("cst.filename")] = args.options.at("cst");
|
ctx->settings[ctx->id("cst.filename")] = args.options.at("cst");
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ MUX27_Z = 29
|
|||||||
ALU0_Z = 30 # : 35, 6 ALUs
|
ALU0_Z = 30 # : 35, 6 ALUs
|
||||||
RAMW_Z = 36 # RAM16SDP4
|
RAMW_Z = 36 # RAM16SDP4
|
||||||
|
|
||||||
|
GSR_Z = 276
|
||||||
VCC_Z = 277
|
VCC_Z = 277
|
||||||
GND_Z = 278
|
GND_Z = 278
|
||||||
|
|
||||||
@ -140,6 +141,8 @@ def create_switch_matrix(tt: TileType, db: chipdb, x: int, y: int):
|
|||||||
def get_wire_type(name):
|
def get_wire_type(name):
|
||||||
if name.startswith('GB') or name.startswith('GT'):
|
if name.startswith('GB') or name.startswith('GT'):
|
||||||
return "GLOBAL_CLK"
|
return "GLOBAL_CLK"
|
||||||
|
elif name in {'XD0', 'XD1', 'XD2', 'XD3', 'XD4', 'XD5',}:
|
||||||
|
return "X0"
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
for dst, srcs in db.grid[y][x].pips.items():
|
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)
|
create_switch_matrix(tt, db, x, y)
|
||||||
return (ttyp, tt)
|
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
|
# simple IO - only A and B
|
||||||
def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
|
def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
|
||||||
if ttyp in created_tiletypes:
|
if ttyp in created_tiletypes:
|
||||||
@ -393,6 +412,7 @@ def main():
|
|||||||
logic_tiletypes = {12, 13, 14, 15, 16}
|
logic_tiletypes = {12, 13, 14, 15, 16}
|
||||||
io_tiletypes = {52, 53, 55, 58, 59, 64, 65, 66}
|
io_tiletypes = {52, 53, 55, 58, 59, 64, 65, 66}
|
||||||
ssram_tiletypes = {17, 18, 19}
|
ssram_tiletypes = {17, 18, 19}
|
||||||
|
gsr_tiletypes = {1}
|
||||||
# Setup tile grid
|
# Setup tile grid
|
||||||
for x in range(X):
|
for x in range(X):
|
||||||
for y in range(Y):
|
for y in range(Y):
|
||||||
@ -403,7 +423,11 @@ def main():
|
|||||||
created_tiletypes.add(ttyp)
|
created_tiletypes.add(ttyp)
|
||||||
ch.set_tile_type(x, y, f"CORNER_{ttyp}")
|
ch.set_tile_type(x, y, f"CORNER_{ttyp}")
|
||||||
continue
|
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)
|
ttyp, _ = create_logic_tiletype(ch, db, x, y, ttyp)
|
||||||
created_tiletypes.add(ttyp)
|
created_tiletypes.add(ttyp)
|
||||||
ch.set_tile_type(x, y, f"LOGIC_{ttyp}")
|
ch.set_tile_type(x, y, f"LOGIC_{ttyp}")
|
||||||
|
@ -249,10 +249,14 @@ struct GowinPacker
|
|||||||
|
|
||||||
if (cin_net->name == ctx->id("$PACKER_GND")) {
|
if (cin_net->name == ctx->id("$PACKER_GND")) {
|
||||||
cin_ci->params[id_ALU_MODE] = std::string("C2L");
|
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;
|
return cin_ci;
|
||||||
}
|
}
|
||||||
if (cin_net->name == ctx->id("$PACKER_VCC")) {
|
if (cin_net->name == ctx->id("$PACKER_VCC")) {
|
||||||
cin_ci->params[id_ALU_MODE] = std::string("ONE2C");
|
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;
|
return cin_ci;
|
||||||
}
|
}
|
||||||
// CIN from logic
|
// 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)
|
void run(void)
|
||||||
{
|
{
|
||||||
pack_iobs();
|
pack_iobs();
|
||||||
handle_constants();
|
handle_constants();
|
||||||
|
pack_gsr();
|
||||||
pack_wideluts();
|
pack_wideluts();
|
||||||
pack_alus();
|
pack_alus();
|
||||||
constrain_lutffs();
|
constrain_lutffs();
|
||||||
|
Loading…
Reference in New Issue
Block a user