diff --git a/gowin/arch.cc b/gowin/arch.cc index 801540cc..2f61685a 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -870,6 +870,39 @@ Arch::Arch(ArchArgs args) : args(args) snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); addBelInput(belname, id_OEN, id(buf)); break; + // Simplified IO + case ID_IOBJS: + z++; /* fall-through*/ + case ID_IOBIS: + z++; /* fall-through*/ + case ID_IOBHS: + z++; /* fall-through*/ + case ID_IOBGS: + z++; /* fall-through*/ + case ID_IOBFS: + z++; /* fall-through*/ + case ID_IOBES: + z++; /* fall-through*/ + case ID_IOBDS: + z++; /* fall-through*/ + case ID_IOBCS: + z++; /* fall-through*/ + case ID_IOBBS: + z++; /* fall-through*/ + case ID_IOBAS: + snprintf(buf, 32, "R%dC%d_IOB%c", row + 1, col + 1, 'A' + z); + belname = id(buf); + addBel(belname, id_IOBS, Loc(col, row, z), false); + portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_O)->src_id); + snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); + addBelOutput(belname, id_O, id(buf)); + portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_I)->src_id); + snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); + addBelInput(belname, id_I, id(buf)); + portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_OE)->src_id); + snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); + addBelInput(belname, id_OEN, id(buf)); + break; default: break; diff --git a/gowin/cells.cc b/gowin/cells.cc index 57f3ab9c..dce3f456 100644 --- a/gowin/cells.cc +++ b/gowin/cells.cc @@ -64,14 +64,14 @@ std::unique_ptr create_generic_cell(Context *ctx, IdString type, std:: add_port(ctx, new_cell.get(), id_I1, PORT_IN); add_port(ctx, new_cell.get(), id_SEL, PORT_IN); add_port(ctx, new_cell.get(), id_OF, PORT_OUT); - } else if (type == id_IOB) { + } else if (type == id_IOB || type == id_IOBS) { new_cell->params[id_INPUT_USED] = 0; new_cell->params[id_OUTPUT_USED] = 0; new_cell->params[id_ENABLE_USED] = 0; add_port(ctx, new_cell.get(), id_PAD, PORT_INOUT); add_port(ctx, new_cell.get(), id_I, PORT_IN); - add_port(ctx, new_cell.get(), id_EN, PORT_IN); + add_port(ctx, new_cell.get(), id_OEN, PORT_IN); add_port(ctx, new_cell.get(), id_O, PORT_OUT); } else { log_error("unable to create generic cell of type %s\n", type.c_str(ctx)); @@ -140,9 +140,17 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool &todelete_cells) { if (nxio->type == id_IBUF) { + if (iob->type == id_IOBS) { + // VCC -> OEN + connect_port(ctx, ctx->nets[ctx->id("$PACKER_VCC_NET")].get(), iob, id_OEN); + } iob->params[id_INPUT_USED] = 1; replace_port(nxio, id_O, iob, id_O); } else if (nxio->type == id_OBUF) { + if (iob->type == id_IOBS) { + // VSS -> OEN + connect_port(ctx, ctx->nets[ctx->id("$PACKER_GND_NET")].get(), iob, id_OEN); + } iob->params[id_OUTPUT_USED] = 1; replace_port(nxio, id_I, iob, id_I); } else if (nxio->type == id_TBUF) { diff --git a/gowin/constids.inc b/gowin/constids.inc index 7de754fc..6a730d5d 100644 --- a/gowin/constids.inc +++ b/gowin/constids.inc @@ -358,6 +358,19 @@ X(IOBH) X(IOBI) X(IOBJ) +// simplified iobs +X(IOBS) +X(IOBAS) +X(IOBBS) +X(IOBCS) +X(IOBDS) +X(IOBES) +X(IOBFS) +X(IOBGS) +X(IOBHS) +X(IOBIS) +X(IOBJS) + // Wide LUTs X(MUX2_LUT5) X(MUX2_LUT6) diff --git a/gowin/pack.cc b/gowin/pack.cc index cb63f1c9..553eeb4e 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -629,7 +629,7 @@ static void pack_constants(Context *ctx) std::vector dead_nets; - bool gnd_used = false; + bool gnd_used = true; // XXX May be needed for simplified IO for (auto &net : ctx->nets) { NetInfo *ni = net.second.get(); @@ -718,8 +718,27 @@ static void pack_io(Context *ctx) } packed_cells.insert(iob->name); } + // what type to create + IdString new_cell_type = id_IOB; + std::string constr_bel_name = std::string(""); + // check whether the given IO is limited to simplified IO cells + auto constr_bel = ci->attrs.find(id_BEL); + if (constr_bel != ci->attrs.end()) { + constr_bel_name = constr_bel->second.as_string(); + } + constr_bel = iob->attrs.find(id_BEL); + if (constr_bel != iob->attrs.end()) { + constr_bel_name = constr_bel->second.as_string(); + } + if (!constr_bel_name.empty()) { + BelId constr_bel = ctx->getBelByNameStr(constr_bel_name); + if (constr_bel != BelId()) { + new_cell_type = ctx->bels[constr_bel].type; + } + } + // Create a IOB buffer - std::unique_ptr ice_cell = create_generic_cell(ctx, id_IOB, ci->name.str(ctx) + "$iob"); + std::unique_ptr ice_cell = create_generic_cell(ctx, new_cell_type, ci->name.str(ctx) + "$iob"); gwio_to_iob(ctx, ci, ice_cell.get(), packed_cells); new_cells.push_back(std::move(ice_cell)); auto gwiob = new_cells.back().get();