diff options
| -rw-r--r-- | gowin/arch.cc | 10 | ||||
| -rw-r--r-- | gowin/arch.h | 1 | ||||
| -rw-r--r-- | gowin/globals.cc | 73 | ||||
| -rw-r--r-- | gowin/globals.h | 20 | ||||
| -rw-r--r-- | gowin/main.cc | 10 | 
5 files changed, 69 insertions, 45 deletions
| diff --git a/gowin/arch.cc b/gowin/arch.cc index 40570af7..33f25405 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -2016,6 +2016,16 @@ static bool is_PLL_T_FB_iob(const Context *ctx, const CellInfo *cell)      return is_spec_iob(ctx, cell, ctx->id("RPLL_T_FB"));  } +bool Arch::is_GCLKT_iob(const CellInfo *cell) +{ +    for (int i = 0; i < 6; ++i) { +        if (is_spec_iob(getCtx(), cell, idf("GCLKT_%d", i))) { +            return true; +        } +    } +    return false; +} +  // If the PLL input can be connected using a direct wire, then do so,  // bypassing conventional routing.  void Arch::fix_pll_nets(Context *ctx) diff --git a/gowin/arch.h b/gowin/arch.h index bbaf3e60..a5c339cc 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -480,6 +480,7 @@ struct Arch : BaseArch<ArchRanges>      void auto_longwires();      void add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col);      void fix_pll_nets(Context *ctx); +    bool is_GCLKT_iob(const CellInfo *cell);      GowinGlobalRouter globals_router;      void mark_gowin_globals(Context *ctx); diff --git a/gowin/globals.cc b/gowin/globals.cc index 21ee722a..785a0111 100644 --- a/gowin/globals.cc +++ b/gowin/globals.cc @@ -38,22 +38,28 @@ bool GowinGlobalRouter::is_clock_port(PortRef const &user)      return false;  } -std::pair<WireId, BelId> GowinGlobalRouter::clock_io(Context *ctx, PortRef const &driver) +std::pair<WireId, BelId> GowinGlobalRouter::clock_src(Context *ctx, PortRef const &driver)  { -    // XXX normally all alternative functions of the pins should be passed -    // in the chip database, but at the moment we find them from aliases/pips -    // XXX check diff inputs too -    if (driver.cell == nullptr || driver.cell->type != id_IOB || !driver.cell->attrs.count(id_BEL)) { +    if (driver.cell == nullptr) {          return std::make_pair(WireId(), BelId());      } -    // clock IOs have pips output->SPINExx -    BelInfo &bel = ctx->bel_info(ctx->id(driver.cell->attrs[id_BEL].as_string())); -    WireId wire = bel.pins[id_O].wire; -    for (auto const pip : ctx->getPipsDownhill(wire)) { -        if (ctx->wire_info(ctx->getPipDstWire(pip)).type.str(ctx).rfind("SPINE", 0) == 0) { +    BelInfo &bel = ctx->bel_info(driver.cell->bel); +    WireId wire; +    if (driver.cell->type == id_IOB) { +        if (ctx->is_GCLKT_iob(driver.cell)) { +            wire = bel.pins[id_O].wire;              return std::make_pair(wire, bel.name);          } +        return std::make_pair(WireId(), BelId()); +    } +    if (driver.cell->type == id_RPLLA) { +        if (driver.port == id_CLKOUT || driver.port == id_CLKOUTP || driver.port == id_CLKOUTD || +            driver.port == id_CLKOUTD3) { +            wire = bel.pins[driver.port].wire; +            return std::make_pair(wire, bel.name); +        } +        return std::make_pair(WireId(), BelId());      }      return std::make_pair(WireId(), BelId());  } @@ -64,12 +70,12 @@ void GowinGlobalRouter::gather_clock_nets(Context *ctx, std::vector<globalnet_t>      for (auto const &net : ctx->nets) {          NetInfo const *ni = net.second.get();          auto new_clock = clock_nets.end(); -        auto clock_wire_bel = clock_io(ctx, ni->driver); +        auto clock_wire_bel = clock_src(ctx, ni->driver);          if (clock_wire_bel.first != WireId()) {              clock_nets.emplace_back(net.first);              new_clock = --clock_nets.end(); -            new_clock->clock_io_wire = clock_wire_bel.first; -            new_clock->clock_io_bel = clock_wire_bel.second; +            new_clock->clock_wire = clock_wire_bel.first; +            new_clock->clock_bel = clock_wire_bel.second;          }          for (auto const &user : ni->users) {              if (is_clock_port(user)) { @@ -86,8 +92,8 @@ void GowinGlobalRouter::gather_clock_nets(Context *ctx, std::vector<globalnet_t>      if (ctx->verbose) {          for (auto const &net : clock_nets) { -            log_info("  Net:%s, ports:%d, io:%s\n", net.name.c_str(ctx), net.clock_ports, -                     net.clock_io_wire == WireId() ? "No" : net.clock_io_wire.c_str(ctx)); +            log_info("  Net:%s, ports:%d, clock source:%s\n", net.name.c_str(ctx), net.clock_ports, +                     net.clock_wire == WireId() ? "No" : net.clock_wire.c_str(ctx));          }      }  } @@ -238,33 +244,35 @@ void GowinGlobalRouter::route_net(Context *ctx, globalnet_t const &net)          }          used_pips.insert(spine_pip_id); -        // >>> SPINExx <- IO +        // >>> SPINExx <- Src          dstWire = ctx->getPipSrcWire(spine_pip_id);          dstWireInfo = ctx->wire_info(dstWire); -        PipId io_pip_id = PipId(); +        PipId src_pip_id = PipId();          for (auto const uphill_pip : ctx->getPipsUphill(dstWire)) { -            if (ctx->getPipSrcWire(uphill_pip) == net.clock_io_wire) { -                io_pip_id = uphill_pip; +            if (ctx->getPipSrcWire(uphill_pip) == net.clock_wire) { +                src_pip_id = uphill_pip;              }          } -        NPNR_ASSERT(io_pip_id != PipId()); +        NPNR_ASSERT(src_pip_id != PipId());          if (ctx->verbose) { -            log_info("       IO Pip:%s\n", io_pip_id.c_str(ctx)); +            log_info("       Src Pip:%s\n", src_pip_id.c_str(ctx));          }          // if already routed -        if (used_pips.count(io_pip_id)) { +        if (used_pips.count(src_pip_id)) {              if (ctx->verbose) {                  log_info("      ^routed already^\n");              }              continue;          } -        used_pips.insert(io_pip_id); +        used_pips.insert(src_pip_id);      }      log_info("  Net %s is routed.\n", net.name.c_str(ctx)); -    for (auto const pip : used_pips) { -        ctx->bindPip(pip, &ctx->net_info(net.name), STRENGTH_LOCKED); +    if (!ctx->net_info(net.name).users.empty()) { +        for (auto const pip : used_pips) { +            ctx->bindPip(pip, &ctx->net_info(net.name), STRENGTH_LOCKED); +        } +        ctx->bindWire(net.clock_wire, &ctx->net_info(net.name), STRENGTH_LOCKED);      } -    ctx->bindWire(net.clock_io_wire, &ctx->net_info(net.name), STRENGTH_LOCKED);  }  void GowinGlobalRouter::route_globals(Context *ctx) @@ -289,16 +297,21 @@ void GowinGlobalRouter::mark_globals(Context *ctx)      int max_clock = 3, cur_clock = -1;      for (auto &net : clock_nets) {          // XXX only IO clock for now -        if (net.clock_io_wire == WireId()) { -            log_info(" Non IO clock, skip %s.\n", net.name.c_str(ctx)); +        if (net.clock_wire == WireId()) { +            log_info(" Non clock source, skip %s.\n", net.name.c_str(ctx));              continue;          }          if (++cur_clock >= max_clock) {              log_info(" No more clock wires left, skip the remaining nets.\n");              break;          } -        net.clock = cur_clock; -        BelInfo &bi = ctx->bel_info(net.clock_io_bel); +        if (ctx->net_info(net.name).users.empty()) { +            --cur_clock; +            net.clock = -1; +        } else { +            net.clock = cur_clock; +        } +        BelInfo &bi = ctx->bel_info(net.clock_bel);          bi.gb = true;          nets.emplace_back(net);      } diff --git a/gowin/globals.h b/gowin/globals.h index 69232d7c..307a1a2c 100644 --- a/gowin/globals.h +++ b/gowin/globals.h @@ -39,32 +39,32 @@ class GowinGlobalRouter      {          IdString name;          int clock_ports; -        BelId clock_io_bel; -        WireId clock_io_wire; // IO wire if there is one -        int clock;            // clock # +        BelId clock_bel; +        WireId clock_wire; // clock wire if there is one +        int clock;         // clock #          globalnet_t()          {              name = IdString();              clock_ports = 0; -            clock_io_bel = BelId(); -            clock_io_wire = WireId(); +            clock_bel = BelId(); +            clock_wire = WireId();              clock = -1;          }          globalnet_t(IdString _name)          {              name = _name;              clock_ports = 0; -            clock_io_bel = BelId(); -            clock_io_wire = WireId(); +            clock_bel = BelId(); +            clock_wire = WireId();              clock = -1;          }          // sort          bool operator<(const globalnet_t &other) const          { -            if ((clock_io_wire != WireId()) ^ (other.clock_io_wire != WireId())) { -                return !(clock_io_wire != WireId()); +            if ((clock_wire != WireId()) ^ (other.clock_wire != WireId())) { +                return !(clock_wire != WireId());              }              return clock_ports < other.clock_ports;          } @@ -76,7 +76,7 @@ class GowinGlobalRouter      std::vector<globalnet_t> nets;      bool is_clock_port(PortRef const &user); -    std::pair<WireId, BelId> clock_io(Context *ctx, PortRef const &driver); +    std::pair<WireId, BelId> clock_src(Context *ctx, PortRef const &driver);      void gather_clock_nets(Context *ctx, std::vector<globalnet_t> &clock_nets);      IdString route_to_non_clock_port(Context *ctx, WireId const dstWire, int clock, pool<IdString> &used_pips,                                       pool<IdString> &undo_wires); diff --git a/gowin/main.cc b/gowin/main.cc index 36bd8656..ccf4d190 100644 --- a/gowin/main.cc +++ b/gowin/main.cc @@ -51,7 +51,8 @@ po::options_description GowinCommandHandler::getArchOptions()      specific.add_options()("device", po::value<std::string>(), "device name");      specific.add_options()("family", po::value<std::string>(), "family name");      specific.add_options()("cst", po::value<std::string>(), "physical constraints file"); -    specific.add_options()("enable-globals", "separate routing of the clocks"); +    specific.add_options()("enable-globals", "enable separate routing of the clocks"); +    specific.add_options()("disable-globals", "disable separate routing of the clocks");      specific.add_options()("enable-auto-longwires", "automatic detection and routing of long wires");      return specific;  } @@ -84,11 +85,10 @@ std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Pr      auto ctx = std::unique_ptr<Context>(new Context(chipArgs));      // routing options -    // the default values will change in the future -    ctx->settings[ctx->id("arch.enable-globals")] = 0; +    ctx->settings[ctx->id("arch.enable-globals")] = 1;      ctx->settings[ctx->id("arch.enable-auto-longwires")] = 0; -    if (vm.count("enable-globals")) { -        ctx->settings[ctx->id("arch.enable-globals")] = 1; +    if (vm.count("disable-globals")) { +        ctx->settings[ctx->id("arch.enable-globals")] = 0;      }      if (vm.count("enable-auto-longwires")) {          ctx->settings[ctx->id("arch.enable-auto-longwires")] = 1; | 
