diff options
-rw-r--r-- | common/kernel/exclusive_state_groups.h | 5 | ||||
-rw-r--r-- | ecp5/arch_place.cc | 100 | ||||
-rw-r--r-- | fpga_interchange/arch.cc | 6 | ||||
-rw-r--r-- | fpga_interchange/luts.cc | 2 | ||||
-rw-r--r-- | fpga_interchange/pseudo_pip_model.cc | 2 | ||||
-rw-r--r-- | gowin/arch.cc | 98 | ||||
-rw-r--r-- | gowin/arch.h | 2 | ||||
-rw-r--r-- | gowin/cells.cc | 57 | ||||
-rw-r--r-- | gowin/cells.h | 5 | ||||
-rw-r--r-- | gowin/constids.inc | 1 | ||||
-rw-r--r-- | gowin/globals.cc | 42 | ||||
-rw-r--r-- | gowin/pack.cc | 24 |
12 files changed, 172 insertions, 172 deletions
diff --git a/common/kernel/exclusive_state_groups.h b/common/kernel/exclusive_state_groups.h index 68ce7c4e..7d447ffe 100644 --- a/common/kernel/exclusive_state_groups.h +++ b/common/kernel/exclusive_state_groups.h @@ -125,7 +125,10 @@ template <size_t StateCount, typename StateType = int8_t, typename CountType = u } } - template <typename StateRange> bool requires(const StateRange &state_range) const + template <typename StateRange> + bool + requires(const StateRange &state_range) + const { if (state < 0) { return false; diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index 2bb601c2..e89e8fb4 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -200,26 +200,24 @@ bool Arch::isBelLocationValid(BelId bel, bool explain_invalid) const // Check if this DSP cell placement would result in more than four distinct // CLK/CE/RST signals per block of two DSP slices. -bool Arch::is_dsp_location_valid(CellInfo* cell) const +bool Arch::is_dsp_location_valid(CellInfo *cell) const { // Find the location of the DSP0 tile. int block_x = cell->getLocation().x - cell->getLocation().z; int block_y = cell->getLocation().y; - const std::array<std::array<IdString, 4>, 3> block_ports = {{ - {id_CLK0, id_CLK1, id_CLK2, id_CLK3}, - {id_CE0, id_CE1, id_CE2, id_CE3}, - {id_RST0, id_RST1, id_RST2, id_RST3} - }}; - const std::array<const char*, 3> port_names = {"CLK", "CE", "RST"}; - std::array<std::set<NetInfo*>, 3> block_nets = {}; + const std::array<std::array<IdString, 4>, 3> block_ports = {{{id_CLK0, id_CLK1, id_CLK2, id_CLK3}, + {id_CE0, id_CE1, id_CE2, id_CE3}, + {id_RST0, id_RST1, id_RST2, id_RST3}}}; + const std::array<const char *, 3> port_names = {"CLK", "CE", "RST"}; + std::array<std::set<NetInfo *>, 3> block_nets = {}; bool cells_locked = true; // Count the number of distinct CLK, CE, and RST signals used by // all the MULT18X18D and ALU54B bels in the DSP block. for (int dx : {0, 1, 3, 4, 5, 7}) { BelId dsp_bel = getBelByLocation(Loc(block_x + dx, block_y, dx)); - CellInfo* dsp_cell = getBoundBelCell(dsp_bel); + CellInfo *dsp_cell = getBoundBelCell(dsp_bel); if (dsp_cell == nullptr) continue; @@ -240,9 +238,7 @@ bool Arch::is_dsp_location_valid(CellInfo* cell) const if (cells_locked) { log_error("DSP block containing %s '%s' has more than " "four distinct %s signals.\n", - dsp_cell->type.c_str(getCtx()), - dsp_cell->name.c_str(getCtx()), - port_names[i]); + dsp_cell->type.c_str(getCtx()), dsp_cell->name.c_str(getCtx()), port_names[i]); } return false; } @@ -260,12 +256,12 @@ void Arch::remap_dsp_blocks() std::set<Location> processed_blocks; const std::array<std::array<IdString, 4>, 3> block_ports = {{ - {id_CLK0, id_CLK1, id_CLK2, id_CLK3}, - {id_CE0, id_CE1, id_CE2, id_CE3}, - {id_RST0, id_RST1, id_RST2, id_RST3}, + {id_CLK0, id_CLK1, id_CLK2, id_CLK3}, + {id_CE0, id_CE1, id_CE2, id_CE3}, + {id_RST0, id_RST1, id_RST2, id_RST3}, }}; - for (auto &cell: cells) { + for (auto &cell : cells) { CellInfo *ci = cell.second.get(); if (!ci->type.in(id_MULT18X18D, id_ALU54B)) continue; @@ -279,13 +275,13 @@ void Arch::remap_dsp_blocks() for (auto &ports : block_ports) { // Store assigned nets for each port. - std::array<NetInfo*, 4> assigned_nets = {}; + std::array<NetInfo *, 4> assigned_nets = {}; // Process each possible MULT18X18D or ALU54B in this block. for (int dx : {0, 1, 3, 4, 5, 7}) { Loc dsp_loc = Loc(block_loc.x + dx, block_loc.y, dx); BelId dsp_bel = getBelByLocation(dsp_loc); - CellInfo* dsp_cell = getBoundBelCell(dsp_bel); + CellInfo *dsp_cell = getBoundBelCell(dsp_bel); if (dsp_cell == nullptr) continue; remap_dsp_cell(dsp_cell, ports, assigned_nets); @@ -314,34 +310,25 @@ void Arch::remap_dsp_blocks() // ports: array of port names to remap, either CLK0-3 or CE0-3 or RST0-3 // assigned_nets: array of final net assignments to those four ports for // the block this cell is in. -void Arch::remap_dsp_cell( - CellInfo* ci, - const std::array<IdString, 4> &ports, - std::array<NetInfo*, 4> &assigned_nets -) { +void Arch::remap_dsp_cell(CellInfo *ci, const std::array<IdString, 4> &ports, std::array<NetInfo *, 4> &assigned_nets) +{ // New names to use in attributes that used to refer to an old port name. std::array<IdString, 4> remap_ports = {}; // Parameters that might need updating when ports are remapped. const std::array<IdString, 48> remap_params = { - id_REG_INPUTA_CLK, id_REG_INPUTA_CE, id_REG_INPUTA_RST, - id_REG_INPUTB_CLK, id_REG_INPUTB_CE, id_REG_INPUTB_RST, - id_REG_INPUTC_CLK, id_REG_INPUTC_CE, id_REG_INPUTC_RST, - id_REG_PIPELINE_CLK, id_REG_PIPELINE_CE, id_REG_PIPELINE_RST, - id_REG_OUTPUT_CLK, id_REG_OUTPUT_CE, id_REG_OUTPUT_RST, - id_REG_INPUTC0_CLK, id_REG_INPUTC0_CE, id_REG_INPUTC0_RST, - id_REG_INPUTC1_CLK, id_REG_INPUTC1_CE, id_REG_INPUTC1_RST, - id_REG_OPCODEOP0_0_CLK, id_REG_OPCODEOP0_0_CE, id_REG_OPCODEOP0_0_RST, - id_REG_OPCODEOP1_0_CLK, - id_REG_OPCODEOP0_1_CLK, id_REG_OPCODEOP0_1_CE, id_REG_OPCODEOP0_1_RST, - id_REG_OPCODEOP1_1_CLK, - id_REG_OPCODEIN_0_CLK, id_REG_OPCODEIN_0_CE, id_REG_OPCODEIN_0_RST, - id_REG_OPCODEIN_1_CLK, id_REG_OPCODEIN_1_CE, id_REG_OPCODEIN_1_RST, - id_REG_OUTPUT0_CLK, id_REG_OUTPUT0_CE, id_REG_OUTPUT0_RST, - id_REG_OUTPUT1_CLK, id_REG_OUTPUT1_CE, id_REG_OUTPUT1_RST, - id_REG_FLAG_CLK, id_REG_FLAG_CE, id_REG_FLAG_RST, - id_REG_INPUTCFB_CLK, id_REG_INPUTCFB_CE, id_REG_INPUTCFB_RST, - id_HIGHSPEED_CLK, + id_REG_INPUTA_CLK, id_REG_INPUTA_CE, id_REG_INPUTA_RST, id_REG_INPUTB_CLK, + id_REG_INPUTB_CE, id_REG_INPUTB_RST, id_REG_INPUTC_CLK, id_REG_INPUTC_CE, + id_REG_INPUTC_RST, id_REG_PIPELINE_CLK, id_REG_PIPELINE_CE, id_REG_PIPELINE_RST, + id_REG_OUTPUT_CLK, id_REG_OUTPUT_CE, id_REG_OUTPUT_RST, id_REG_INPUTC0_CLK, + id_REG_INPUTC0_CE, id_REG_INPUTC0_RST, id_REG_INPUTC1_CLK, id_REG_INPUTC1_CE, + id_REG_INPUTC1_RST, id_REG_OPCODEOP0_0_CLK, id_REG_OPCODEOP0_0_CE, id_REG_OPCODEOP0_0_RST, + id_REG_OPCODEOP1_0_CLK, id_REG_OPCODEOP0_1_CLK, id_REG_OPCODEOP0_1_CE, id_REG_OPCODEOP0_1_RST, + id_REG_OPCODEOP1_1_CLK, id_REG_OPCODEIN_0_CLK, id_REG_OPCODEIN_0_CE, id_REG_OPCODEIN_0_RST, + id_REG_OPCODEIN_1_CLK, id_REG_OPCODEIN_1_CE, id_REG_OPCODEIN_1_RST, id_REG_OUTPUT0_CLK, + id_REG_OUTPUT0_CE, id_REG_OUTPUT0_RST, id_REG_OUTPUT1_CLK, id_REG_OUTPUT1_CE, + id_REG_OUTPUT1_RST, id_REG_FLAG_CLK, id_REG_FLAG_CE, id_REG_FLAG_RST, + id_REG_INPUTCFB_CLK, id_REG_INPUTCFB_CE, id_REG_INPUTCFB_RST, id_HIGHSPEED_CLK, }; // First, go through each port and determine which new port to assign @@ -363,22 +350,18 @@ void Arch::remap_dsp_cell( // we need to assign the net to a different port and // update any attributes that refer to it, while // ensuring the net at the new port is preserved. - size_t j = std::distance( - assigned_nets.cbegin(), - std::find(assigned_nets.cbegin(), assigned_nets.cend(), nullptr)); + size_t j = std::distance(assigned_nets.cbegin(), + std::find(assigned_nets.cbegin(), assigned_nets.cend(), nullptr)); if (j == assigned_nets.size()) { log_error("DSP block containing %s '%s': no unused ports " "to remap %s to; too many distinct signals in " "block.\n", - ci->type.c_str(getCtx()), - ci->name.c_str(getCtx()), - port.c_str(getCtx())); + ci->type.c_str(getCtx()), ci->name.c_str(getCtx()), port.c_str(getCtx())); } assigned_nets[j] = net; remap_ports[i] = ports[j]; - log_info("DSP: %s '%s': Connection to %s remapped to %s\n", - ci->type.c_str(getCtx()), ci->name.c_str(getCtx()), - ports[i].c_str(getCtx()), ports[j].c_str(getCtx())); + log_info("DSP: %s '%s': Connection to %s remapped to %s\n", ci->type.c_str(getCtx()), + ci->name.c_str(getCtx()), ports[i].c_str(getCtx()), ports[j].c_str(getCtx())); } } else if (*assigned != assigned_nets[i]) { // If the net has been assigned already and to a different @@ -386,9 +369,8 @@ void Arch::remap_dsp_cell( // to point to the already-assigned port. size_t j = std::distance(assigned_nets.cbegin(), assigned); remap_ports[i] = ports[j]; - log_info("DSP: %s '%s': Connection to %s remapped to %s\n", - ci->type.c_str(getCtx()), ci->name.c_str(getCtx()), - ports[i].c_str(getCtx()), ports[j].c_str(getCtx())); + log_info("DSP: %s '%s': Connection to %s remapped to %s\n", ci->type.c_str(getCtx()), + ci->name.c_str(getCtx()), ports[i].c_str(getCtx()), ports[j].c_str(getCtx())); } } @@ -409,10 +391,7 @@ void Arch::remap_dsp_cell( continue; for (size_t i = 0; i < remap_ports.size(); i++) { Property &prop = param->second; - if (remap_ports[i] != IdString() - && prop.is_string - && prop.str == ports[i].str(getCtx()) - ) { + if (remap_ports[i] != IdString() && prop.is_string && prop.str == ports[i].str(getCtx())) { prop = Property(remap_ports[i].str(getCtx())); break; } @@ -421,8 +400,7 @@ void Arch::remap_dsp_cell( // Finally, only when remapping CLK ports, also move any `CLKn_DIV` // to the new clock port. - const std::array<IdString, 4> clk_div_params = { - id_CLK0_DIV, id_CLK1_DIV, id_CLK2_DIV, id_CLK3_DIV}; + const std::array<IdString, 4> clk_div_params = {id_CLK0_DIV, id_CLK1_DIV, id_CLK2_DIV, id_CLK3_DIV}; std::array<Property, 4> new_clk_div_props = {}; if (ports[0] == id_CLK0) { for (size_t i = 0; i < 4; i++) { @@ -431,9 +409,7 @@ void Arch::remap_dsp_cell( auto param = ci->params.find(clk_div_params[i]); if (param == ci->params.end()) continue; - size_t j = std::distance( - ports.cbegin(), - std::find(ports.cbegin(), ports.cend(), remap_ports[i])); + size_t j = std::distance(ports.cbegin(), std::find(ports.cbegin(), ports.cend(), remap_ports[i])); if (j != ports.size()) { new_clk_div_props[j] = param->second; } diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index a1651c81..2682010f 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -46,9 +46,9 @@ // scope of the header. #include <tcl.h> -//#define DEBUG_BINDING -//#define USE_LOOKAHEAD -//#define DEBUG_CELL_PIN_MAPPING +// #define DEBUG_BINDING +// #define USE_LOOKAHEAD +// #define DEBUG_CELL_PIN_MAPPING // Define to enable some idempotent sanity checks for some important // operations prior to placement and routing. diff --git a/fpga_interchange/luts.cc b/fpga_interchange/luts.cc index 2a847253..009b601e 100644 --- a/fpga_interchange/luts.cc +++ b/fpga_interchange/luts.cc @@ -24,7 +24,7 @@ #include "site_lut_mapping_cache.h" -//#define DEBUG_LUT_ROTATION +// #define DEBUG_LUT_ROTATION NEXTPNR_NAMESPACE_BEGIN diff --git a/fpga_interchange/pseudo_pip_model.cc b/fpga_interchange/pseudo_pip_model.cc index 7f2427c4..0b767369 100644 --- a/fpga_interchange/pseudo_pip_model.cc +++ b/fpga_interchange/pseudo_pip_model.cc @@ -22,7 +22,7 @@ #include "context.h" -//#define DEBUG_PSEUDO_PIP +// #define DEBUG_PSEUDO_PIP NEXTPNR_NAMESPACE_BEGIN diff --git a/gowin/arch.cc b/gowin/arch.cc index f43cc00a..88b9f42f 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -1098,16 +1098,33 @@ void Arch::addMuxBels(const DatabasePOD *db, int row, int col) } } -void Arch::add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col) +void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col) { IdString portname; - for (int pid : {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5, - ID_IDSEL0, ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1, - ID_ODSEL2, ID_ODSEL3, ID_ODSEL4, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0, - ID_DUTYDA1, ID_DUTYDA2, ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3}) { + for (int pid : + {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5, ID_IDSEL0, + ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1, ID_ODSEL2, ID_ODSEL3, + ID_ODSEL4, ID_ODSEL5, ID_VREN, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0, ID_DUTYDA1, + ID_DUTYDA2, ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3, ID_RESET, ID_RESET_P}) { portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id); - addBelInput(belname, IdString(pid), idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + 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); + NPNR_ASSERT(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, IdString(pid), wire); } for (int pid : {ID_LOCK, ID_CLKOUT, ID_CLKOUTP, ID_CLKOUTD, ID_CLKOUTD3}) { portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id); @@ -1115,16 +1132,23 @@ void Arch::add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col } } -void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col) +void Arch::add_rpll_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col) { IdString portname; for (int pid : - {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5, ID_IDSEL0, - ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1, ID_ODSEL2, ID_ODSEL3, - ID_ODSEL4, ID_ODSEL5, ID_VREN, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0, ID_DUTYDA1, - ID_DUTYDA2, ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3, ID_RESET, ID_RESET_P}) { - portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id); + {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5, ID_IDSEL0, + ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1, ID_ODSEL2, ID_ODSEL3, + ID_ODSEL4, ID_ODSEL5, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0, ID_DUTYDA1, ID_DUTYDA2, + ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3, ID_RESET, ID_RESET_P}) { + const PairPOD *port = pairLookup(bel->ports.get(), bel->num_ports, pid); + // old base + if (port == nullptr) { + log_warning("When building nextpnr, obsolete old apicula bases were used. Probably not working properly " + "with PLL.\n"); + return; + } + portname = IdString(port->src_id); IdString wire = idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); if (wires.count(wire) == 0) { GlobalAliasPOD alias; @@ -1137,20 +1161,39 @@ void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString b int srccol = alias_src->src_col; IdString srcid = IdString(alias_src->src_id); wire = wireToGlobal(srcrow, srccol, db, srcid); - // addWire(wire, portname, srccol, srcrow); + if (wires.count(wire) == 0) { + addWire(wire, srcid, srccol, srcrow); + } } addBelInput(belname, IdString(pid), wire); } for (int pid : {ID_LOCK, ID_CLKOUT, ID_CLKOUTP, ID_CLKOUTD, ID_CLKOUTD3}) { portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id); - addBelOutput(belname, IdString(pid), idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this))); + 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); + NPNR_ASSERT(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); + } + } + addBelOutput(belname, IdString(pid), wire); } } + Arch::Arch(ArchArgs args) : args(args) { family = args.family; - max_clock = 5; + max_clock = 6; if (family == "GW1NZ-1") { max_clock = 3; } @@ -1312,24 +1355,9 @@ Arch::Arch(ArchArgs args) : args(args) add_pllvr_ports(db, bel, belname, row, col); break; case ID_RPLLA: - snprintf(buf, 32, "R%dC%d_RPLLA", row + 1, col + 1); - belname = id(buf); - addBel(belname, id_RPLLA, Loc(col, row, BelZ::pll_z), false); - add_plla_ports(bel, belname, row, col); - break; - case ID_RPLLB: - snprintf(buf, 32, "R%dC%d_RPLLB", row + 1, col + 1); - belname = id(buf); - addBel(belname, id_RPLLB, Loc(col, row, BelZ::pll_z), false); - portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_RESET)->src_id); - snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); - addBelInput(belname, id_RESET, id(buf)); - portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_RESET_P)->src_id); - snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); - addBelInput(belname, id_RESET_P, id(buf)); - portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_ODSEL5)->src_id); - snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); - addBelInput(belname, id_ODSEL5, id(buf)); + belname = idf("R%dC%d_rPLL", row + 1, col + 1); + addBel(belname, id_rPLL, Loc(col, row, BelZ::pll_z), false); + add_rpll_ports(db, bel, belname, row, col); break; case ID_BUFS7: z++; /* fall-through*/ @@ -2086,7 +2114,7 @@ void Arch::fix_pll_nets(Context *ctx) { for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); - if (ci->type != id_RPLLA && ci->type != id_PLLVR) { + if (ci->type != id_rPLL && ci->type != id_PLLVR) { continue; } // *** CLKIN @@ -2101,7 +2129,7 @@ void Arch::fix_pll_nets(Context *ctx) break; } if (net_driven_by(ctx, net, is_RPLL_T_IN_iob, id_O) != nullptr) { - if (ci->type == id_RPLLA) { + if (ci->type == id_rPLL) { ci->disconnectPort(id_CLKIN); ci->setParam(id_INSEL, Property("CLKIN0")); break; diff --git a/gowin/arch.h b/gowin/arch.h index 0dd5a62b..f060165a 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -478,8 +478,8 @@ struct Arch : BaseArch<ArchRanges> void pre_route(Context *ctx); void post_route(Context *ctx); void auto_longwires(); - void add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col); void add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col); + void add_rpll_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col); void fix_pll_nets(Context *ctx); bool is_GCLKT_iob(const CellInfo *cell); diff --git a/gowin/cells.cc b/gowin/cells.cc index ae420160..c30a4706 100644 --- a/gowin/cells.cc +++ b/gowin/cells.cc @@ -79,16 +79,12 @@ std::unique_ptr<CellInfo> create_generic_cell(Context *ctx, IdString type, std:: } else if (type == id_BUFS) { new_cell->addInput(id_I); new_cell->addOutput(id_O); - } else if (type == id_RPLLB) { - new_cell->addInput(id_RESET); - new_cell->addInput(id_RESET_P); - new_cell->addInput(id_ODSEL5); - } else if (type == id_RPLLA) { + } else if (type == id_rPLL) { for (IdString iid : - {id_CLKIN, id_CLKFB, id_FBDSEL0, id_FBDSEL1, id_FBDSEL2, id_FBDSEL3, id_FBDSEL4, id_FBDSEL5, - id_IDSEL0, id_IDSEL1, id_IDSEL2, id_IDSEL3, id_IDSEL4, id_IDSEL5, id_ODSEL0, id_ODSEL1, - id_ODSEL2, id_ODSEL3, id_ODSEL4, id_PSDA0, id_PSDA1, id_PSDA2, id_PSDA3, id_DUTYDA0, - id_DUTYDA1, id_DUTYDA2, id_DUTYDA3, id_FDLY0, id_FDLY1, id_FDLY2, id_FDLY3}) { + {id_CLKIN, id_CLKFB, id_FBDSEL0, id_FBDSEL1, id_FBDSEL2, id_FBDSEL3, id_FBDSEL4, id_FBDSEL5, id_IDSEL0, + id_IDSEL1, id_IDSEL2, id_IDSEL3, id_IDSEL4, id_IDSEL5, id_ODSEL0, id_ODSEL1, id_ODSEL2, id_ODSEL3, + id_ODSEL4, id_ODSEL5, id_PSDA0, id_PSDA1, id_PSDA2, id_PSDA3, id_DUTYDA0, id_DUTYDA1, id_DUTYDA2, + id_DUTYDA3, id_FDLY0, id_FDLY1, id_FDLY2, id_FDLY3, id_RESET, id_RESET_P}) { new_cell->addInput(iid); } new_cell->addOutput(id_CLKOUT); @@ -206,40 +202,33 @@ void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &to } } -void reconnect_rplla(Context *ctx, CellInfo *pll, CellInfo *plla) +void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll) { - pll->movePortTo(id_CLKIN, plla, id_CLKIN); - pll->movePortTo(id_CLKFB, plla, id_CLKFB); + pll->movePortTo(id_CLKIN, new_pll, id_CLKIN); + pll->movePortTo(id_VREN, new_pll, id_VREN); + pll->movePortTo(id_CLKFB, new_pll, id_CLKFB); + pll->movePortTo(id_RESET, new_pll, id_RESET); + pll->movePortTo(id_RESET_P, new_pll, id_RESET_P); for (int i = 0; i < 6; ++i) { - pll->movePortTo(ctx->idf("FBDSEL[%d]", i), plla, ctx->idf("FBDSEL%d", i)); - pll->movePortTo(ctx->idf("IDSEL[%d]", i), plla, ctx->idf("IDSEL%d", i)); - if (i < 5) { - pll->movePortTo(ctx->idf("ODSEL[%d]", i), plla, ctx->idf("ODSEL%d", i)); - } + pll->movePortTo(ctx->idf("FBDSEL[%d]", i), new_pll, ctx->idf("FBDSEL%d", i)); + pll->movePortTo(ctx->idf("IDSEL[%d]", i), new_pll, ctx->idf("IDSEL%d", i)); + pll->movePortTo(ctx->idf("ODSEL[%d]", i), new_pll, ctx->idf("ODSEL%d", i)); if (i < 4) { - pll->movePortTo(ctx->idf("PSDA[%d]", i), plla, ctx->idf("PSDA%d", i)); - pll->movePortTo(ctx->idf("DUTYDA[%d]", i), plla, ctx->idf("DUTYDA%d", i)); - pll->movePortTo(ctx->idf("FDLY[%d]", i), plla, ctx->idf("FDLY%d", i)); + pll->movePortTo(ctx->idf("PSDA[%d]", i), new_pll, ctx->idf("PSDA%d", i)); + pll->movePortTo(ctx->idf("DUTYDA[%d]", i), new_pll, ctx->idf("DUTYDA%d", i)); + pll->movePortTo(ctx->idf("FDLY[%d]", i), new_pll, ctx->idf("FDLY%d", i)); } } - pll->movePortTo(id_CLKOUT, plla, id_CLKOUT); - pll->movePortTo(id_CLKOUTP, plla, id_CLKOUTP); - pll->movePortTo(id_CLKOUTD, plla, id_CLKOUTD); - pll->movePortTo(id_CLKOUTD3, plla, id_CLKOUTD3); - pll->movePortTo(id_LOCK, plla, id_LOCK); -} - -void reconnect_rpllb(Context *ctx, CellInfo *pll, CellInfo *pllb) -{ - pll->movePortTo(id_RESET, pllb, id_RESET); - pll->movePortTo(id_RESET_P, pllb, id_RESET_P); - pll->movePortTo(ctx->id("ODSEL[5]"), pllb, id_ODSEL5); + pll->movePortTo(id_CLKOUT, new_pll, id_CLKOUT); + pll->movePortTo(id_CLKOUTP, new_pll, id_CLKOUTP); + pll->movePortTo(id_CLKOUTD, new_pll, id_CLKOUTD); + pll->movePortTo(id_CLKOUTD3, new_pll, id_CLKOUTD3); + pll->movePortTo(id_LOCK, new_pll, id_LOCK); } -void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll) +void reconnect_rpll(Context *ctx, CellInfo *pll, CellInfo *new_pll) { pll->movePortTo(id_CLKIN, new_pll, id_CLKIN); - pll->movePortTo(id_VREN, new_pll, id_VREN); pll->movePortTo(id_CLKFB, new_pll, id_CLKFB); pll->movePortTo(id_RESET, new_pll, id_RESET); pll->movePortTo(id_RESET_P, new_pll, id_RESET_P); diff --git a/gowin/cells.h b/gowin/cells.h index 78a746f3..7aba4805 100644 --- a/gowin/cells.h +++ b/gowin/cells.h @@ -122,9 +122,8 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells); // Reconnect PLL signals (B) -void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *pllb); -void reconnect_rplla(Context *ctx, CellInfo *pll, CellInfo *pllb); -void reconnect_rpllb(Context *ctx, CellInfo *pll, CellInfo *pllb); +void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll); +void reconnect_rpll(Context *ctx, CellInfo *pll, CellInfo *new_pll); // Convert RAM16 to write port void sram_to_ramw_split(Context *ctx, CellInfo *ram, CellInfo *ramw); diff --git a/gowin/constids.inc b/gowin/constids.inc index e3e451a1..dac84a1e 100644 --- a/gowin/constids.inc +++ b/gowin/constids.inc @@ -855,7 +855,6 @@ X(OSCF) // PLLs X(rPLL) X(RPLLA) -X(RPLLB) X(PLLVR) // primitive attributes diff --git a/gowin/globals.cc b/gowin/globals.cc index 6ed8f770..3273191c 100644 --- a/gowin/globals.cc +++ b/gowin/globals.cc @@ -53,7 +53,7 @@ std::pair<WireId, BelId> GowinGlobalRouter::clock_src(Context *ctx, PortRef cons } return std::make_pair(WireId(), BelId()); } - if (driver.cell->type == id_RPLLA || driver.cell->type == id_PLLVR) { + if (driver.cell->type == id_rPLL || driver.cell->type == id_PLLVR) { if (driver.port == id_CLKOUT || driver.port == id_CLKOUTP || driver.port == id_CLKOUTD || driver.port == id_CLKOUTD3) { wire = bel.pins[driver.port].wire; @@ -103,12 +103,20 @@ void GowinGlobalRouter::gather_clock_nets(Context *ctx, std::vector<globalnet_t> IdString GowinGlobalRouter::route_to_non_clock_port(Context *ctx, WireId const dstWire, int clock, pool<IdString> &used_pips, pool<IdString> &undo_wires) { - static std::vector<IdString> one_hop = {id_S111, id_S121, id_N111, id_N121, id_W111, id_W121, id_E111, id_E121}; - char buf[40]; + static std::vector<IdString> one_hop_0 = {id_W111, id_W121, id_E111, id_E121}; + static std::vector<IdString> one_hop_4 = {id_S111, id_S121, id_N111, id_N121}; // uphill pips for (auto const uphill : ctx->getPipsUphill(dstWire)) { WireId srcWire = ctx->getPipSrcWire(uphill); - if (find(one_hop.begin(), one_hop.end(), ctx->wire_info(ctx->getPipSrcWire(uphill)).type) != one_hop.end()) { + bool found; + if (clock < 4) { + found = find(one_hop_0.begin(), one_hop_0.end(), ctx->wire_info(ctx->getPipSrcWire(uphill)).type) != + one_hop_0.end(); + } else { + found = find(one_hop_4.begin(), one_hop_4.end(), ctx->wire_info(ctx->getPipSrcWire(uphill)).type) != + one_hop_4.end(); + } + if (found) { // found one hop pip if (used_wires.count(srcWire)) { if (used_wires[srcWire] != clock) { @@ -117,8 +125,13 @@ IdString GowinGlobalRouter::route_to_non_clock_port(Context *ctx, WireId const d } WireInfo wi = ctx->wire_info(srcWire); std::string wire_alias = srcWire.str(ctx).substr(srcWire.str(ctx).rfind("_") + 1); - snprintf(buf, sizeof(buf), "R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, clock, wire_alias.c_str()); - IdString gb = ctx->id(buf); + IdString gb = ctx->idf("R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, clock, wire_alias.c_str()); + if (ctx->verbose) { + log_info(" 1-hop gb:%s\n", gb.c_str(ctx)); + } + // sanity + NPNR_ASSERT(find(ctx->getPipsUphill(srcWire).begin(), ctx->getPipsUphill(srcWire).end(), gb) != + ctx->getPipsUphill(srcWire).end()); auto up_pips = ctx->getPipsUphill(srcWire); if (find(up_pips.begin(), up_pips.end(), gb) != up_pips.end()) { if (!used_wires.count(srcWire)) { @@ -154,11 +167,10 @@ void GowinGlobalRouter::route_net(Context *ctx, globalnet_t const &net) char buf[30]; PipId gb_pip_id; - if (user.port == id_CLK) { + if (user.port == id_CLK || user.port == id_CLKIN) { WireInfo const wi = ctx->wire_info(dstWire); - snprintf(buf, sizeof(buf), "R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, net.clock, - ctx->wire_info(dstWire).type.c_str(ctx)); - gb_pip_id = ctx->id(buf); + gb_pip_id = + ctx->idf("R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, net.clock, ctx->wire_info(dstWire).type.c_str(ctx)); // sanity NPNR_ASSERT(find(ctx->getPipsUphill(dstWire).begin(), ctx->getPipsUphill(dstWire).end(), gb_pip_id) != ctx->getPipsUphill(dstWire).end()); @@ -192,11 +204,10 @@ void GowinGlobalRouter::route_net(Context *ctx, globalnet_t const &net) dstWire = ctx->getPipSrcWire(gb_pip_id); WireInfo dstWireInfo = ctx->wire_info(dstWire); int branch_tap_idx = net.clock > 3 ? 1 : 0; - snprintf(buf, sizeof(buf), "R%dC%d_GT%d0_GBO%d", dstWireInfo.y + 1, dstWireInfo.x + 1, branch_tap_idx, - branch_tap_idx); - PipId gt_pip_id = ctx->id(buf); + PipId gt_pip_id = + ctx->idf("R%dC%d_GT%d0_GBO%d", dstWireInfo.y + 1, dstWireInfo.x + 1, branch_tap_idx, branch_tap_idx); if (ctx->verbose) { - log_info(" GT Pip:%s\n", buf); + log_info(" GT Pip:%s\n", gt_pip_id.c_str(ctx)); } // sanity NPNR_ASSERT(find(ctx->getPipsUphill(dstWire).begin(), ctx->getPipsUphill(dstWire).end(), gt_pip_id) != @@ -251,12 +262,13 @@ void GowinGlobalRouter::route_net(Context *ctx, globalnet_t const &net) for (auto const uphill_pip : ctx->getPipsUphill(dstWire)) { if (ctx->getPipSrcWire(uphill_pip) == net.clock_wire) { src_pip_id = uphill_pip; + break; } } - NPNR_ASSERT(src_pip_id != PipId()); if (ctx->verbose) { log_info(" Src Pip:%s\n", src_pip_id.c_str(ctx)); } + NPNR_ASSERT(src_pip_id != PipId()); // if already routed if (used_pips.count(src_pip_id)) { if (ctx->verbose) { diff --git a/gowin/pack.cc b/gowin/pack.cc index 1ebd5315..cb24ac02 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -1034,7 +1034,7 @@ static void pack_plls(Context *ctx) if (ctx->verbose) log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx)); if (is_pll(ctx, ci)) { - std::string parm_device = str_or_default(ci->params, id_DEVICE, "GW1N-1"); + std::string parm_device = str_or_default(ci->params, id_DEVICE, ctx->device.c_str()); if (parm_device != ctx->device) { log_error("Cell '%s': wrong PLL device:%s instead of %s\n", ctx->nameOf(ci), parm_device.c_str(), ctx->device.c_str()); @@ -1043,27 +1043,21 @@ static void pack_plls(Context *ctx) switch (ci->type.hash()) { case ID_rPLL: { - if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1") { + if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1" || parm_device == "GW1NR-9C") { pll_disable_unused_ports(ctx, ci); - // B half - std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_RPLLB, ci->name.str(ctx) + "$rpllb"); - reconnect_rpllb(ctx, ci, cell.get()); + // A cell + std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll"); + reconnect_rpll(ctx, ci, cell.get()); new_cells.push_back(std::move(cell)); - auto pllb_cell = new_cells.back().get(); - // A half - cell = create_generic_cell(ctx, id_RPLLA, ci->name.str(ctx) + "$rplla"); - reconnect_rplla(ctx, ci, cell.get()); - new_cells.push_back(std::move(cell)); - auto plla_cell = new_cells.back().get(); + auto pll_cell = new_cells.back().get(); // need params for gowin_pack for (auto &parm : ci->params) { - plla_cell->setParam(parm.first, parm.second); - pllb_cell->setParam(parm.first, parm.second); + pll_cell->setParam(parm.first, parm.second); } packed_cells.insert(ci->name); } else { - log_error("PLL isn't supported for %s\n", ctx->device.c_str()); + log_error("rPLL isn't supported for %s\n", ctx->device.c_str()); } } break; case ID_PLLVR: { @@ -1080,7 +1074,7 @@ static void pack_plls(Context *ctx) } packed_cells.insert(ci->name); } else { - log_error("PLL isn't supported for %s\n", ctx->device.c_str()); + log_error("PLLVR isn't supported for %s\n", ctx->device.c_str()); } } break; default: |