diff options
Diffstat (limited to 'gowin/arch.cc')
-rw-r--r-- | gowin/arch.cc | 162 |
1 files changed, 157 insertions, 5 deletions
diff --git a/gowin/arch.cc b/gowin/arch.cc index ce893f1b..8033048f 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -1194,6 +1194,70 @@ void Arch::add_rpll_ports(DatabasePOD const *db, BelsPOD const *bel, IdString be } } +static bool skip_aux_oser16(std::string device, int row, int col) +{ + if (device == "GW1NSR-4C") { + switch (col) { + case 2: /* fall-through*/ + case 4: /* fall-through*/ + case 6: /* fall-through*/ + case 8: /* fall-through*/ + case 9: /* fall-through*/ + case 11: /* fall-through*/ + case 13: /* fall-through*/ + case 15: /* fall-through*/ + case 17: /* fall-through*/ + case 18: /* fall-through*/ + case 20: /* fall-through*/ + case 22: /* fall-through*/ + case 24: /* fall-through*/ + case 26: /* fall-through*/ + case 27: /* fall-through*/ + case 29: /* fall-through*/ + case 31: /* fall-through*/ + case 33: /* fall-through*/ + case 35: + return true; + default: + break; + } + } + if (device == "GW1NR-9" || device == "GW1NR-9C") { + switch (col) { + case 2: /* fall-through*/ + case 4: /* fall-through*/ + case 6: /* fall-through*/ + case 8: /* fall-through*/ + case 9: /* fall-through*/ + case 11: /* fall-through*/ + case 13: /* fall-through*/ + case 15: /* fall-through*/ + case 17: /* fall-through*/ + case 18: /* fall-through*/ + case 19: /* fall-through*/ + case 21: /* fall-through*/ + case 23: /* fall-through*/ + case 25: /* fall-through*/ + case 27: /* fall-through*/ + case 28: /* fall-through*/ + case 29: /* fall-through*/ + case 31: /* fall-through*/ + case 33: /* fall-through*/ + case 35: /* fall-through*/ + case 36: /* fall-through*/ + case 37: /* fall-through*/ + case 39: /* fall-through*/ + case 41: /* fall-through*/ + case 43: /* fall-through*/ + case 45: + return true; + default: + break; + } + } + return false; +} + Arch::Arch(ArchArgs args) : args(args) { family = args.family; @@ -1745,6 +1809,92 @@ Arch::Arch(ArchArgs args) : args(args) } } } break; + case ID_OSER16: { + if (skip_aux_oser16(device, row, col)) { + break; + } + belname = idf("R%dC%d_OSER16", row + 1, col + 1); + addBel(belname, id_OSER16, Loc(col, row, BelZ::oser16_z), false); + + IdString const oser16_in_ports[] = {id_RESET, id_PCLK, id_D0, id_D1, id_D2, id_D3, + id_D4, id_D5, id_D6, id_D7, id_D8, id_D9, + id_D10, id_D11, id_D12, id_D13, id_D14, id_D15}; + for (IdString port : oser16_in_ports) { + portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, port.hash())->src_id); + addBelInput(belname, port, idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + } + portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, id_Q0.hash())->src_id); + addBelOutput(belname, id_Q, idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + auto fclk = pairLookup(bel->ports.get(), bel->num_ports, ID_FCLK); + // XXX as long as there is no special processing of the pins + if (fclk != nullptr) { + portname = IdString(fclk->src_id); + IdString wire = idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); + if (wires.count(wire) == 0) { + GlobalAliasPOD alias; + alias.dest_col = col; + alias.dest_row = row; + alias.dest_id = portname.hash(); + auto alias_src = genericLookup(db->aliases.get(), db->num_aliases, alias, aliasCompare); + if (alias_src != nullptr) { + int srcrow = alias_src->src_row; + int srccol = alias_src->src_col; + IdString srcid = IdString(alias_src->src_id); + wire = wireToGlobal(srcrow, srccol, db, srcid); + if (wires.count(wire) == 0) { + addWire(wire, srcid, srccol, srcrow); + } + addBelInput(belname, id_FCLK, wire); + } + } else { + addBelInput(belname, id_FCLK, idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + } + } + } break; + case ID_IDES16: { + if (skip_aux_oser16(device, row, col)) { + break; + } + belname = idf("R%dC%d_IDES16", row + 1, col + 1); + addBel(belname, id_IDES16, Loc(col, row, BelZ::ides16_z), false); + + IdString const ides16_in_ports[] = {id_RESET, id_PCLK, id_CALIB, id_D}; + for (IdString port : ides16_in_ports) { + portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, port.hash())->src_id); + addBelInput(belname, port, idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + } + IdString const ides16_out_ports[] = {id_Q0, id_Q1, id_Q2, id_Q3, id_Q4, id_Q5, id_Q6, id_Q7, + id_Q8, id_Q9, id_Q10, id_Q11, id_Q12, id_Q13, id_Q14, id_Q15}; + for (IdString port : ides16_out_ports) { + portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, port.hash())->src_id); + addBelOutput(belname, port, idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + } + auto fclk = pairLookup(bel->ports.get(), bel->num_ports, ID_FCLK); + // XXX as long as there is no special processing of the pins + if (fclk != nullptr) { + portname = IdString(fclk->src_id); + IdString wire = idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); + if (wires.count(wire) == 0) { + GlobalAliasPOD alias; + alias.dest_col = col; + alias.dest_row = row; + alias.dest_id = portname.hash(); + auto alias_src = genericLookup(db->aliases.get(), db->num_aliases, alias, aliasCompare); + if (alias_src != nullptr) { + int srcrow = alias_src->src_row; + int srccol = alias_src->src_col; + IdString srcid = IdString(alias_src->src_id); + wire = wireToGlobal(srcrow, srccol, db, srcid); + if (wires.count(wire) == 0) { + addWire(wire, srcid, srccol, srcrow); + } + addBelInput(belname, id_FCLK, wire); + } + } else { + addBelInput(belname, id_FCLK, idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + } + } + } break; default: break; } @@ -2312,6 +2462,7 @@ void Arch::fix_pll_nets(Context *ctx) // mark with hclk is used void Arch::mark_used_hclk(Context *ctx) { + pool<IdString> aux_cells; for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); if (ci->type != id_IOLOGIC) { @@ -2322,6 +2473,7 @@ void Arch::mark_used_hclk(Context *ctx) } // if it's an aux cell if (ci->attrs.count(id_IOLOGIC_MASTER_CELL)) { + aux_cells.insert(ci->name); continue; } ci->setAttr(id_IOLOGIC_FCLK, Property("UNKNOWN")); @@ -2345,16 +2497,16 @@ void Arch::mark_used_hclk(Context *ctx) if (!checkPipAvail(pip)) { WireId src_wire = getPipSrcWire(pip); ci->setAttr(id_IOLOGIC_FCLK, Property(wire_info(src_wire).type.str(this))); - if (ci->attrs.count(id_IOLOGIC_AUX_CELL)) { - IdString aux_cell_name = ctx->id(ci->attrs[id_IOLOGIC_AUX_CELL].as_string()); - ctx->cells[aux_cell_name]->setAttr(id_IOLOGIC_FCLK, - Property(wire_info(src_wire).type.str(this))); - } } } } } } + for (auto acell : aux_cells) { + IdString main_cell = ctx->id(ctx->cells.at(acell)->attrs.at(id_IOLOGIC_MASTER_CELL).as_string()); + Property &fclk = ctx->cells.at(main_cell)->attrs.at(id_IOLOGIC_FCLK); + ctx->cells.at(acell)->setAttr(id_IOLOGIC_FCLK, fclk); + } } void Arch::pre_route(Context *ctx) |