diff options
| -rw-r--r-- | common/util.h | 10 | ||||
| -rwxr-xr-x | ice40/carry_tests/test.sh | 22 | ||||
| -rw-r--r-- | ice40/main.cc | 2 | ||||
| -rw-r--r-- | ice40/pack.cc | 8 | ||||
| -rw-r--r-- | ice40/place_legaliser.cc | 38 | 
5 files changed, 64 insertions, 16 deletions
diff --git a/common/util.h b/common/util.h index c888c8b8..a9ad2172 100644 --- a/common/util.h +++ b/common/util.h @@ -21,6 +21,7 @@  #define UTIL_H  #include <map> +#include <set>  #include <string>  #include "nextpnr.h" @@ -65,6 +66,15 @@ template <typename K, typename V> std::map<K, V *> sorted(const std::unordered_m      return retVal;  }; +// Wrap an unordered_set, and allow it to be iterated over sorted by key +template <typename K> std::set<K> sorted(const std::unordered_set<K> &orig) +{ +    std::set<K> retVal; +    for (auto &item : orig) +        retVal.insert(item); +    return retVal; +}; +  NEXTPNR_NAMESPACE_END  #endif diff --git a/ice40/carry_tests/test.sh b/ice40/carry_tests/test.sh index 47a9e5ef..9f6b00b2 100755 --- a/ice40/carry_tests/test.sh +++ b/ice40/carry_tests/test.sh @@ -2,15 +2,15 @@  set -ex  NAME=${1%.v}  yosys -p "synth_ice40 -top top; write_json ${NAME}.json" $1 -../../nextpnr-ice40 --json ${NAME}.json --pcf test.pcf --asc ${NAME}.asc --verbose -icebox_vlog -p test.pcf ${NAME}.asc > ${NAME}_out.v +../../nextpnr-ice40 --force --json ${NAME}.json --pcf test.pcf --asc ${NAME}.asc --verbose ../../python/dump_design.py +#icebox_vlog -p test.pcf ${NAME}.asc > ${NAME}_out.v -yosys -p "read_verilog +/ice40/cells_sim.v;\ -          rename chip gate;\ -          read_verilog $1;\ -          rename top gold;\ -          hierarchy;\ -          proc;\ -          clk2fflogic;\ -          miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter;\ -          sat -dump_vcd equiv_${NAME}.vcd -verify-no-timeout -timeout 60 -seq 50 -prove trigger 0 -prove-skip 1 -show-inputs -show-outputs miter" ${NAME}_out.v +#yosys -p "read_verilog +/ice40/cells_sim.v;\ +#          rename chip gate;\ +#          read_verilog $1;\ +#          rename top gold;\ +#          hierarchy;\ +#          proc;\ +#          clk2fflogic;\ +#          miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter;\ +#          sat -dump_vcd equiv_${NAME}.vcd -verify-no-timeout -timeout 60 -seq 50 -prove trigger 0 -prove-skip 1 -show-inputs -show-outputs miter" ${NAME}_out.v diff --git a/ice40/main.cc b/ice40/main.cc index 8babf8b9..7f913bb3 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -45,6 +45,7 @@  #include "route.h"  #include "timing.h"  #include "version.h" +#include "place_legaliser.h"  USING_NEXTPNR_NAMESPACE @@ -375,6 +376,7 @@ int main(int argc, char *argv[])              if (!vm.count("pack-only")) {                  if (!place_design_sa(&ctx, timing_driven) && !ctx.force)                      log_error("Placing design failed.\n"); +                legalise_design(&ctx);                  if (!route_design(&ctx) && !ctx.force)                      log_error("Routing design failed.\n");              } diff --git a/ice40/pack.cc b/ice40/pack.cc index 3a255257..0d48d58c 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -126,7 +126,6 @@ static void pack_carries(Context *ctx)              packed_cells.insert(cell.first);              CellInfo *carry_ci_lc = net_only_drives(ctx, ci->ports.at(ctx->id("CI")).net, is_lc, ctx->id("I3"), false); -              std::set<IdString> i0_matches, i1_matches;              NetInfo *i0_net = ci->ports.at(ctx->id("I0")).net;              NetInfo *i1_net = ci->ports.at(ctx->id("I1")).net; @@ -161,9 +160,9 @@ static void pack_carries(Context *ctx)              if (carry_ci_lc) {                  if (carry_lcs.find(carry_ci_lc->name) == carry_lcs.end()) {                      if (ctx->verbose) { -                        for(auto i0 : i0_matches) +                        for (auto i0 : i0_matches)                              log_info("I0 candidate: '%s'\n", i0.c_str(ctx)); -                        for(auto i1 : i1_matches) +                        for (auto i1 : i1_matches)                              log_info("I1 candidate: '%s'\n", i1.c_str(ctx));                          log_info("I3 connects to: '%s'\n", carry_ci_lc->name.c_str(ctx));                      } @@ -275,7 +274,8 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne              CellInfo *uc = user.cell;              if (ctx->verbose)                  log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx)); -            if ((is_lut(ctx, uc) || is_lc(ctx, uc) || is_carry(ctx, uc)) && (user.port.str(ctx).at(0) == 'I') && !constval) { +            if ((is_lut(ctx, uc) || is_lc(ctx, uc) || is_carry(ctx, uc)) && (user.port.str(ctx).at(0) == 'I') && +                !constval) {                  uc->ports[user.port].net = nullptr;              } else {                  uc->ports[user.port].net = constnet; diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc index 29dab0a0..8f5680bf 100644 --- a/ice40/place_legaliser.cc +++ b/ice40/place_legaliser.cc @@ -93,11 +93,13 @@ class PlacementLegaliser      bool legalise()      { +        log_info("Legalising design..\n");          init_logic_cells();          bool legalised_carries = legalise_carries();          if (!legalised_carries && !ctx->force)              return false; -        return legalised_carries; +        bool replaced_cells = replace_cells(); +        return legalised_carries && replaced_cells;      }    private: @@ -313,6 +315,40 @@ class PlacementLegaliser          return ctx->cells[name].get();      } +    // Replace ripped-up cells +    bool replace_cells() +    { +        bool success = true; +        for (auto cell : sorted(rippedCells)) { +            CellInfo *ci = ctx->cells.at(cell).get(); +            bool placed = place_single_cell(ci); +            if (!placed) { +                if (ctx->force) { +                    log_warning("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx), +                                ci->type.c_str(ctx)); +                    success = false; +                } else { +                    log_error("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx), +                              ci->type.c_str(ctx)); +                } +            } +        } +        return success; +    } + +    // Place a single cell in the first valid location +    bool place_single_cell(CellInfo *cell) +    { +        BelType tgtType = ctx->belTypeFromId(cell->type); +        for (auto bel : ctx->getBels()) { +            if (ctx->getBelType(bel) == tgtType && ctx->checkBelAvail(bel) && ctx->isValidBelForCell(cell, bel)) { +                ctx->bindBel(bel, cell->name, STRENGTH_WEAK); +                return true; +            } +        } +        return false; +    } +      Context *ctx;      std::unordered_set<IdString> rippedCells;      std::unordered_set<IdString> createdCells;  | 
