gowin: Himbaechel. Add IDES primitives
As well as the implementation of all OSC primitives. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
3a073540c2
commit
87ae77fbc6
@ -30,7 +30,8 @@ inline bool is_diffio(const CellInfo *cell) { return type_is_diffio(cell->type);
|
||||
|
||||
inline bool type_is_iologic(IdString cell_type)
|
||||
{
|
||||
return cell_type.in(id_ODDR, id_ODDRC, id_OSER4, id_OSER8, id_OSER10, id_OVIDEO);
|
||||
return cell_type.in(id_ODDR, id_ODDRC, id_OSER4, id_OSER8, id_OSER10, id_OVIDEO, id_IDDR, id_IDDRC, id_IDES4,
|
||||
id_IDES8, id_IDES10, id_IVIDEO);
|
||||
}
|
||||
inline bool is_iologic(const CellInfo *cell) { return type_is_iologic(cell->type); }
|
||||
|
||||
@ -77,6 +78,7 @@ enum
|
||||
|
||||
IOLOGICA_Z = 70,
|
||||
|
||||
OSC_Z = 274,
|
||||
PLL_Z = 275,
|
||||
GSR_Z = 276,
|
||||
VCC_Z = 277,
|
||||
|
@ -30,6 +30,7 @@ IOBB_Z = 51
|
||||
|
||||
IOLOGICA_Z = 70
|
||||
|
||||
OSC_Z = 274
|
||||
PLL_Z = 275
|
||||
GSR_Z = 276
|
||||
VCC_Z = 277
|
||||
@ -292,6 +293,19 @@ def create_corner_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
|
||||
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)
|
||||
if (y, x) in db.extra_cell_func:
|
||||
funcs = db.extra_cell_func[(y, x)]
|
||||
if 'osc' in funcs:
|
||||
osc_type = funcs['osc']['type']
|
||||
portmap = db.grid[y][x].bels[osc_type].portmap
|
||||
for port, wire in portmap.items():
|
||||
tt.create_wire(wire, port)
|
||||
io = tt.create_bel(osc_type, osc_type, z = OSC_Z)
|
||||
for port, wire in portmap.items():
|
||||
if 'OUT' in port:
|
||||
tt.add_bel_pin(io, port, wire, PinType.OUTPUT)
|
||||
else:
|
||||
tt.add_bel_pin(io, port, wire, PinType.INPUT)
|
||||
|
||||
return (tiletype, tt)
|
||||
|
||||
|
@ -451,9 +451,9 @@ struct GowinPacker
|
||||
|
||||
bool is_diff_io(BelId bel) { return ctx->getBoundBelCell(bel)->attrs.count(id_DIFF_TYPE) != 0; }
|
||||
|
||||
void create_aux_iologic_cells(CellInfo &ci)
|
||||
void create_aux_iologic_cells(CellInfo &ci, IdString mode)
|
||||
{
|
||||
if (ci.type.in(id_ODDR, id_ODDRC, id_OSER4)) {
|
||||
if (ci.type.in(id_ODDR, id_ODDRC, id_OSER4, id_IDDR, id_IDDRC, id_IDES4)) {
|
||||
return;
|
||||
}
|
||||
IdString aux_name = create_aux_iologic_name(ci.name);
|
||||
@ -472,12 +472,101 @@ struct GowinPacker
|
||||
ci.copyPortTo(id_PCLK, ctx->cells.at(aux_name).get(), id_PCLK);
|
||||
aux->addInput(id_RESET);
|
||||
ci.copyPortTo(id_RESET, ctx->cells.at(aux_name).get(), id_RESET);
|
||||
ctx->cells.at(aux_name)->setParam(ctx->id("OUTMODE"), Property("DDRENABLE"));
|
||||
ctx->cells.at(aux_name)->setParam(mode, Property("DDRENABLE"));
|
||||
ctx->cells.at(aux_name)->setAttr(ctx->id("IOLOGIC_TYPE"), Property("DUMMY"));
|
||||
ctx->cells.at(aux_name)->setAttr(ctx->id("MAIN_CELL"), Property(ci.name.str(ctx)));
|
||||
ctx->bindBel(bel, aux, PlaceStrength::STRENGTH_LOCKED);
|
||||
}
|
||||
|
||||
void reconnect_ides_outs(CellInfo *ci)
|
||||
{
|
||||
switch (ci->type.hash()) {
|
||||
case ID_IDDR: /* fall-through*/
|
||||
case ID_IDDRC:
|
||||
ci->renamePort(id_Q1, id_Q9);
|
||||
ci->renamePort(id_Q0, id_Q8);
|
||||
break;
|
||||
case ID_IDES4:
|
||||
ci->renamePort(id_Q3, id_Q9);
|
||||
ci->renamePort(id_Q2, id_Q8);
|
||||
ci->renamePort(id_Q1, id_Q7);
|
||||
ci->renamePort(id_Q0, id_Q6);
|
||||
break;
|
||||
case ID_IVIDEO:
|
||||
ci->renamePort(id_Q6, id_Q9);
|
||||
ci->renamePort(id_Q5, id_Q8);
|
||||
ci->renamePort(id_Q4, id_Q7);
|
||||
ci->renamePort(id_Q3, id_Q6);
|
||||
ci->renamePort(id_Q2, id_Q5);
|
||||
ci->renamePort(id_Q1, id_Q4);
|
||||
ci->renamePort(id_Q0, id_Q3);
|
||||
break;
|
||||
case ID_IDES8:
|
||||
ci->renamePort(id_Q7, id_Q9);
|
||||
ci->renamePort(id_Q6, id_Q8);
|
||||
ci->renamePort(id_Q5, id_Q7);
|
||||
ci->renamePort(id_Q4, id_Q6);
|
||||
ci->renamePort(id_Q3, id_Q5);
|
||||
ci->renamePort(id_Q2, id_Q4);
|
||||
ci->renamePort(id_Q1, id_Q3);
|
||||
ci->renamePort(id_Q0, id_Q2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pack_ides_iol(CellInfo &ci, std::vector<IdString> &cells_to_remove, std::vector<IdString> &nets_to_remove)
|
||||
{
|
||||
IdString in_port = id_D;
|
||||
|
||||
CellInfo *in_iob = net_driven_by(ctx, ci.ports.at(in_port).net, is_iob, id_O);
|
||||
NPNR_ASSERT(in_iob != nullptr && in_iob->bel != BelId());
|
||||
BelId iob_bel = in_iob->bel;
|
||||
|
||||
BelId l_bel = get_iologic_bel(in_iob);
|
||||
if (l_bel == BelId()) {
|
||||
log_error("Can't place IOLOGIC %s at %s\n", ctx->nameOf(&ci), ctx->nameOfBel(iob_bel));
|
||||
}
|
||||
|
||||
if (!ctx->checkBelAvail(l_bel)) {
|
||||
log_error("Can't place %s at %s because it's already taken by %s\n", ctx->nameOf(&ci),
|
||||
ctx->nameOfBel(l_bel), ctx->nameOf(ctx->getBoundBelCell(l_bel)));
|
||||
}
|
||||
ctx->bindBel(l_bel, &ci, PlaceStrength::STRENGTH_LOCKED);
|
||||
std::string in_mode;
|
||||
switch (ci.type.hash()) {
|
||||
case ID_IDDR:
|
||||
case ID_IDDRC:
|
||||
in_mode = "IDDRX1";
|
||||
break;
|
||||
case ID_IDES4:
|
||||
in_mode = "IDDRX2";
|
||||
break;
|
||||
case ID_IDES8:
|
||||
in_mode = "IDDRX4";
|
||||
break;
|
||||
case ID_IDES10:
|
||||
in_mode = "IDDRX5";
|
||||
break;
|
||||
case ID_IVIDEO:
|
||||
in_mode = "VIDEORX";
|
||||
break;
|
||||
}
|
||||
ci.setParam(ctx->id("INMODE"), in_mode);
|
||||
|
||||
// mark IOB as used by IOLOGIC
|
||||
in_iob->setParam(id_IOLOGIC_IOB, 1);
|
||||
// disconnect Q output: it is wired internally
|
||||
nets_to_remove.push_back(ci.getPort(in_port)->name);
|
||||
in_iob->disconnectPort(id_O);
|
||||
ci.disconnectPort(in_port);
|
||||
set_daaj_nets(ci, iob_bel);
|
||||
reconnect_ides_outs(&ci);
|
||||
|
||||
make_iob_nets(*in_iob);
|
||||
}
|
||||
|
||||
void pack_iologic()
|
||||
{
|
||||
log_info("Pack IO logic...\n");
|
||||
@ -493,12 +582,17 @@ struct GowinPacker
|
||||
}
|
||||
if (ci.type.in(id_ODDR, id_ODDRC, id_OSER4, id_OSER8)) {
|
||||
pack_bi_output_iol(ci, cells_to_remove, nets_to_remove);
|
||||
create_aux_iologic_cells(ci);
|
||||
create_aux_iologic_cells(ci, ctx->id("OUTMODE"));
|
||||
continue;
|
||||
}
|
||||
if (ci.type.in(id_OVIDEO, id_OSER10)) {
|
||||
pack_single_output_iol(ci, cells_to_remove, nets_to_remove);
|
||||
create_aux_iologic_cells(ci);
|
||||
create_aux_iologic_cells(ci, ctx->id("OUTMODE"));
|
||||
continue;
|
||||
}
|
||||
if (ci.type.in(id_IDDR, id_IDDRC, id_IDES4, id_IDES8, id_IDES10, id_IVIDEO)) {
|
||||
pack_ides_iol(ci, cells_to_remove, nets_to_remove);
|
||||
create_aux_iologic_cells(ci, ctx->id("INMODE"));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user