diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | bba/bba.cmake | 12 | ||||
| -rw-r--r-- | bba/main.cc | 15 | ||||
| -rw-r--r-- | common/archcheck.cc | 5 | ||||
| -rw-r--r-- | common/nextpnr.h | 1 | ||||
| -rw-r--r-- | common/place_common.cc | 22 | ||||
| -rw-r--r-- | common/placer1.cc | 26 | ||||
| -rw-r--r-- | common/timing.cc | 3 | ||||
| -rw-r--r-- | ecp5/arch.cc | 46 | ||||
| -rw-r--r-- | ecp5/arch.h | 3 | ||||
| -rw-r--r-- | ecp5/arch_place.cc | 7 | ||||
| -rw-r--r-- | ecp5/bitstream.cc | 43 | ||||
| -rw-r--r-- | ecp5/main.cc | 4 | ||||
| -rw-r--r-- | generic/arch.cc | 40 | ||||
| -rw-r--r-- | generic/arch.h | 3 | ||||
| -rw-r--r-- | gui/fpgaviewwidget.cc | 6 | ||||
| -rw-r--r-- | ice40/arch.cc | 40 | ||||
| -rw-r--r-- | ice40/arch.h | 7 | ||||
| -rw-r--r-- | ice40/arch_place.cc | 7 | ||||
| -rw-r--r-- | ice40/arch_pybindings.cc | 2 | ||||
| -rw-r--r-- | ice40/chipdb.py | 38 | ||||
| -rw-r--r-- | ice40/family.cmake | 21 | ||||
| -rw-r--r-- | ice40/gfx.cc | 2 | ||||
| -rw-r--r-- | ice40/pack.cc | 4 | ||||
| -rw-r--r-- | ice40/place_legaliser.cc | 8 | 
26 files changed, 196 insertions, 173 deletions
@@ -25,3 +25,5 @@ build/  /Testing/*  CTestTestfile.cmake  install_manifest.txt +/bbasm +/ImportExecutables.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c8ee6805..55e57763 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,6 +167,8 @@ if(MINGW)      add_definitions("-Wa,-mbig-obj")  endif(MINGW) +include(bba/bba.cmake) +  foreach (family ${ARCH})      message(STATUS "Configuring architecture : ${family}")      string(TOUPPER ${family} ufamily) diff --git a/bba/bba.cmake b/bba/bba.cmake new file mode 100644 index 00000000..4bb9ea0e --- /dev/null +++ b/bba/bba.cmake @@ -0,0 +1,12 @@ +IF(CMAKE_CROSSCOMPILING) +    SET(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point it to the export file from a native build") +    INCLUDE(${IMPORT_EXECUTABLES}) +ENDIF(CMAKE_CROSSCOMPILING) + +IF(NOT CMAKE_CROSSCOMPILING) +    ADD_EXECUTABLE(bbasm bba/main.cc) +ENDIF(NOT CMAKE_CROSSCOMPILING) + +IF(NOT CMAKE_CROSSCOMPILING) +    EXPORT(TARGETS bbasm FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake ) +ENDIF(NOT CMAKE_CROSSCOMPILING) diff --git a/bba/main.cc b/bba/main.cc new file mode 100644 index 00000000..42b79504 --- /dev/null +++ b/bba/main.cc @@ -0,0 +1,15 @@ +#include <unistd.h> +#include <assert.h> +int main() +{ +    char buffer[512]; +    int i, j; +    while (1) { +        i = read(0, buffer, 512); +        if (i == 0) break; +        assert(i > 0); +        j = write(1, buffer, i); +        assert(i == j); +    } +    return 0; +} diff --git a/common/archcheck.cc b/common/archcheck.cc index 5c4ef26c..5059066d 100644 --- a/common/archcheck.cc +++ b/common/archcheck.cc @@ -17,8 +17,8 @@   *   */ -#include "nextpnr.h"  #include "log.h" +#include "nextpnr.h"  #if 0  #define dbg(...) log(__VA_ARGS__) @@ -84,8 +84,7 @@ void archcheck_locs(const Context *ctx)      log_info("Checking all locations..\n");      for (int x = 0; x < ctx->getGridDimX(); x++) -        for (int y = 0; y < ctx->getGridDimY(); y++) -        { +        for (int y = 0; y < ctx->getGridDimY(); y++) {              dbg("> %d %d\n", x, y);              std::unordered_set<int> usedz; diff --git a/common/nextpnr.h b/common/nextpnr.h index 021772fe..3ba4f3b3 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -147,6 +147,7 @@ struct GraphicElement      {          G_NONE,          G_LINE, +        G_ARROW,          G_BOX,          G_CIRCLE,          G_LABEL diff --git a/common/place_common.cc b/common/place_common.cc index 95b7b2aa..5673c847 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -28,19 +28,20 @@ NEXTPNR_NAMESPACE_BEGIN  wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type, float &tns)  {      wirelen_t wirelength = 0; -    int driver_x, driver_y; +    Loc driver_loc;      bool driver_gb;      CellInfo *driver_cell = net->driver.cell;      if (!driver_cell)          return 0;      if (driver_cell->bel == BelId())          return 0; -    ctx->estimatePosition(driver_cell->bel, driver_x, driver_y, driver_gb); +    driver_gb = ctx->getBelGlobalBuf(driver_cell->bel); +    driver_loc = ctx->getBelLocation(driver_cell->bel);      WireId drv_wire = ctx->getBelPinWire(driver_cell->bel, ctx->portPinFromId(net->driver.port));      if (driver_gb)          return 0;      float worst_slack = 1000; -    int xmin = driver_x, xmax = driver_x, ymin = driver_y, ymax = driver_y; +    int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y;      for (auto load : net->users) {          if (load.cell == nullptr)              continue; @@ -56,15 +57,14 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type              worst_slack = std::min(slack, worst_slack);          } -        int load_x, load_y; -        bool load_gb; -        ctx->estimatePosition(load_cell->bel, load_x, load_y, load_gb); -        if (load_gb) +        if (ctx->getBelGlobalBuf(load_cell->bel))              continue; -        xmin = std::min(xmin, load_x); -        ymin = std::min(ymin, load_y); -        xmax = std::max(xmax, load_x); -        ymax = std::max(ymax, load_y); +        Loc load_loc = ctx->getBelLocation(load_cell->bel); + +        xmin = std::min(xmin, load_loc.x); +        ymin = std::min(ymin, load_loc.y); +        xmax = std::max(xmax, load_loc.x); +        ymax = std::max(ymax, load_loc.y);      }      if (ctx->timing_driven && type == MetricType::COST) {          wirelength = wirelen_t((((ymax - ymin) + (xmax - xmin)) * std::min(5.0, (1.0 + std::exp(-worst_slack / 5))))); diff --git a/common/placer1.cc b/common/placer1.cc index 025c7c15..f713fb88 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -50,9 +50,7 @@ class SAPlacer      {          int num_bel_types = 0;          for (auto bel : ctx->getBels()) { -            int x, y; -            bool gb; -            ctx->estimatePosition(bel, x, y, gb); +            Loc loc = ctx->getBelLocation(bel);              BelType type = ctx->getBelType(bel);              int type_idx;              if (bel_types.find(type) == bel_types.end()) { @@ -63,13 +61,13 @@ class SAPlacer              }              if (int(fast_bels.size()) < type_idx + 1)                  fast_bels.resize(type_idx + 1); -            if (int(fast_bels.at(type_idx).size()) < (x + 1)) -                fast_bels.at(type_idx).resize(x + 1); -            if (int(fast_bels.at(type_idx).at(x).size()) < (y + 1)) -                fast_bels.at(type_idx).at(x).resize(y + 1); -            max_x = std::max(max_x, x); -            max_y = std::max(max_y, y); -            fast_bels.at(type_idx).at(x).at(y).push_back(bel); +            if (int(fast_bels.at(type_idx).size()) < (loc.x + 1)) +                fast_bels.at(type_idx).resize(loc.x + 1); +            if (int(fast_bels.at(type_idx).at(loc.x).size()) < (loc.y + 1)) +                fast_bels.at(type_idx).at(loc.x).resize(loc.y + 1); +            max_x = std::max(max_x, loc.x); +            max_y = std::max(max_y, loc.y); +            fast_bels.at(type_idx).at(loc.x).at(loc.y).push_back(bel);          }          diameter = std::max(max_x, max_y) + 1;      } @@ -404,12 +402,10 @@ class SAPlacer      BelId random_bel_for_cell(CellInfo *cell)      {          BelType targetType = ctx->belTypeFromId(cell->type); -        int x, y; -        bool gb; -        ctx->estimatePosition(cell->bel, x, y, gb); +        Loc curr_loc = ctx->getBelLocation(cell->bel);          while (true) { -            int nx = ctx->rng(2 * diameter + 1) + std::max(x - diameter, 0); -            int ny = ctx->rng(2 * diameter + 1) + std::max(y - diameter, 0); +            int nx = ctx->rng(2 * diameter + 1) + std::max(curr_loc.x - diameter, 0); +            int ny = ctx->rng(2 * diameter + 1) + std::max(curr_loc.y - diameter, 0);              int beltype_idx = bel_types.at(targetType);              if (nx >= int(fast_bels.at(beltype_idx).size()))                  continue; diff --git a/common/timing.cc b/common/timing.cc index 3a48935f..d91dea20 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -88,6 +88,9 @@ void assign_budget(Context *ctx)                  IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first);                  if (clock_domain != IdString()) {                      delay_t slack = delay_t(1.0e12 / ctx->target_freq); // TODO: clock constraints +                    delay_t clkToQ; +                    if (ctx->getCellDelay(cell.second.get(), clock_domain, port.first, clkToQ)) +                        slack -= clkToQ;                      if (port.second.net)                          follow_net(ctx, port.second.net, 0, slack);                  } diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 7d67dd0c..5507d1e3 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -192,17 +192,20 @@ BelId Arch::getBelByName(IdString name) const      return ret;  } -BelRange Arch::getBelsAtSameTile(BelId bel) const +BelRange Arch::getBelsByTile(int x, int y) const  {      BelRange br; -    NPNR_ASSERT(bel != BelId()); -    br.b.cursor_tile = bel.location.y * chip_info->width + bel.location.x; -    br.e.cursor_tile = bel.location.y * chip_info->width + bel.location.x; + +    br.b.cursor_tile = y * chip_info->width + x; +    br.e.cursor_tile = y * chip_info->width + x;      br.b.cursor_index = 0; -    br.e.cursor_index = locInfo(bel)->num_bels - 1; +    br.e.cursor_index = chip_info->locations[chip_info->location_type[br.b.cursor_tile]].num_bels - 1;      br.b.chip = chip_info;      br.e.chip = chip_info; -    ++br.e; +    if (br.e.cursor_index == -1) +        ++br.e.cursor_index; +    else +        ++br.e;      return br;  } @@ -278,6 +281,7 @@ PipId Arch::getPipByName(IdString name) const      Location loc;      std::string basename;      std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this)); +    ret.location = loc;      const LocationTypePOD *loci = locInfo(ret);      for (int i = 0; i < loci->num_pips; i++) {          PipId curr; @@ -285,6 +289,8 @@ PipId Arch::getPipByName(IdString name) const          curr.index = i;          pip_by_name[getPipName(curr)] = curr;      } +    if (pip_by_name.find(name) == pip_by_name.end()) +        NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this));      return pip_by_name[name];  } @@ -399,36 +405,8 @@ BelId Arch::getBelByLocation(Loc loc) const      return BelId();  } -BelRange Arch::getBelsByTile(int x, int y) const -{ -    BelRange br; - -    int num_bels = 0; - -    if (x < chip_info->width && y < chip_info->height) { -        const LocationTypePOD &locI = chip_info->locations[chip_info->location_type[y * chip_info->width + x]]; -        num_bels = locI.num_bels; -    } - -    br.b.cursor_tile = y * chip_info->width + x; -    br.e.cursor_tile = y * chip_info->width + x; -    br.b.cursor_index = 0; -    br.e.cursor_index = num_bels - 1; -    br.b.chip = chip_info; -    br.e.chip = chip_info; -    ++br.e; -    return br; -} -  // ----------------------------------------------------------------------- -void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const -{ -    x = bel.location.x; -    y = bel.location.y; -    gb = false; -} -  delay_t Arch::estimateDelay(WireId src, WireId dst) const  {      return 200 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y)); diff --git a/ecp5/arch.h b/ecp5/arch.h index ce2b90c3..4400db5e 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -482,8 +482,6 @@ struct Arch : BaseCtx          return range;      } -    BelRange getBelsAtSameTile(BelId bel) const; -      BelType getBelType(BelId bel) const      {          NPNR_ASSERT(bel != BelId()); @@ -752,7 +750,6 @@ struct Arch : BaseCtx      // ------------------------------------------------- -    void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;      delay_t estimateDelay(WireId src, WireId dst) const;      delay_t getDelayEpsilon() const { return 20; }      delay_t getRipupDelayPenalty() const { return 200; } diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index 22ebab67..84432043 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -66,7 +66,8 @@ bool Arch::isBelLocationValid(BelId bel) const  {      if (getBelType(bel) == TYPE_TRELLIS_SLICE) {          std::vector<const CellInfo *> bel_cells; -        for (auto bel_other : getBelsAtSameTile(bel)) { +        Loc bel_loc = getBelLocation(bel); +        for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {              IdString cell_other = getBoundBelCell(bel_other);              if (cell_other != IdString()) {                  const CellInfo *ci_other = cells.at(cell_other).get(); @@ -89,8 +90,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const          NPNR_ASSERT(getBelType(bel) == TYPE_TRELLIS_SLICE);          std::vector<const CellInfo *> bel_cells; - -        for (auto bel_other : getBelsAtSameTile(bel)) { +        Loc bel_loc = getBelLocation(bel); +        for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {              IdString cell_other = getBoundBelCell(bel_other);              if (cell_other != IdString() && bel_other != bel) {                  const CellInfo *ci_other = cells.at(cell_other).get(); diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 19ddb9f9..c2218762 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -30,6 +30,7 @@  #include <fstream>  #include <streambuf> +#include "io.h"  #include "log.h"  #include "util.h" @@ -182,12 +183,34 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex              }          }      } +    // Find bank voltages +    std::unordered_map<int, IOVoltage> bankVcc; +    for (auto &cell : ctx->cells) { +        CellInfo *ci = cell.second.get(); +        if (ci->bel != BelId() && ci->type == ctx->id("TRELLIS_IO")) { +            int bank = ctx->getPioBelBank(ci->bel); +            std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33"); +            IOVoltage vcc = get_vccio(ioType_from_str(iotype)); +            if (bankVcc.find(bank) != bankVcc.end()) { +                // TODO: strong and weak constraints +                if (bankVcc[bank] != vcc) { +                    log_error("Error processing '%s': incompatible IO voltages %s and %s on bank %d.", +                              cell.first.c_str(ctx), iovoltage_to_str(bankVcc[bank]).c_str(), +                              iovoltage_to_str(vcc).c_str(), bank); +                } +            } else { +                bankVcc[bank] = vcc; +            } +        } +    } -    // Set all bankref tiles to 3.3V (TODO) +    // Set all bankref tiles to appropriate VccIO      for (const auto &tile : empty_chip.tiles) {          std::string type = tile.second->info.type;          if (type.find("BANKREF") != std::string::npos && type != "BANKREF8") { -            cc.tiles[tile.first].add_enum("BANK.VCCIO", "3V3"); +            int bank = std::stoi(type.substr(7)); +            if (bankVcc.find(bank) != bankVcc.end()) +                cc.tiles[tile.first].add_enum("BANK.VCCIO", iovoltage_to_str(bankVcc[bank]));          }      } @@ -235,6 +258,20 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex              std::string pic_tile = get_pic_tile(ctx, empty_chip, bel);              cc.tiles[pio_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype);              cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); +            if (is_differential(ioType_from_str(iotype))) { +                // Explicitly disable other pair +                std::string other; +                if (pio == "PIOA") +                    other = "PIOB"; +                else if (pio == "PIOC") +                    other = "PIOD"; +                else +                    log_error("cannot place differential IO at location %s\n", pio.c_str()); +                cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); +                cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); +                cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE"); +                cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE"); +            }              if (dir != "INPUT" &&                  (ci->ports.find(ctx->id("T")) == ci->ports.end() || ci->ports.at(ctx->id("T")).net == nullptr)) {                  // Tie tristate low if unconnected for outputs or bidir @@ -247,7 +284,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex                  std::string cib_wirename = ctx->locInfo(cib_wire)->wire_data[cib_wire.index].name.get();                  cc.tiles[cib_tile].add_enum("CIB." + cib_wirename + "MUX", "0");              } -            if (dir == "INPUT") { +            if (dir == "INPUT" && !is_differential(ioType_from_str(iotype))) {                  cc.tiles[pio_tile].add_enum(pio + ".HYSTERESIS", "ON");              }          } else { diff --git a/ecp5/main.cc b/ecp5/main.cc index 5a4a900a..90096855 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -63,6 +63,7 @@ int main(int argc, char *argv[])  #ifndef NO_GUI          options.add_options()("gui", "start gui");  #endif +        options.add_options()("test", "check architecture database integrity");          options.add_options()("25k", "set device type to LFE5U-25F");          options.add_options()("45k", "set device type to LFE5U-45F"); @@ -148,6 +149,9 @@ int main(int argc, char *argv[])          if (vm.count("no-tmdriv"))              ctx->timing_driven = false; +        if (vm.count("test")) +            ctx->archcheck(); +  #ifndef NO_GUI          if (vm.count("gui")) {              Application a(argc, argv); diff --git a/generic/arch.cc b/generic/arch.cc index 0fff2e4c..ac79ebea 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -77,18 +77,18 @@ void Arch::addBel(IdString name, IdString type, Loc loc, bool gb)      bel_ids.push_back(name);      bel_by_loc[loc] = name; -    if (bels_by_tile.size() <= loc.x) +    if (int(bels_by_tile.size()) <= loc.x)          bels_by_tile.resize(loc.x + 1); -    if (bels_by_tile[loc.x].size() <= loc.y) +    if (int(bels_by_tile[loc.x].size()) <= loc.y)          bels_by_tile[loc.x].resize(loc.y + 1);      bels_by_tile[loc.x][loc.y].push_back(name); -    if (tileDimZ.size() <= loc.x) +    if (int(tileDimZ.size()) <= loc.x)          tileDimZ.resize(loc.x + 1); -    if (tileDimZ[loc.x].size() <= loc.y) +    if (int(tileDimZ[loc.x].size()) <= loc.y)          tileDimZ[loc.x].resize(loc.y + 1);      gridDimX = std::max(gridDimX, loc.x + 1); @@ -193,6 +193,30 @@ BelId Arch::getBelByName(IdString name) const  IdString Arch::getBelName(BelId bel) const { return bel; } +Loc Arch::getBelLocation(BelId bel) const +{ +    auto &info = bels.at(bel); +    return Loc(info.x, info.y, info.z); +} + +BelId Arch::getBelByLocation(Loc loc) const +{ +    auto it = bel_by_loc.find(loc); +    if (it != bel_by_loc.end()) +        return it->second; +    return BelId(); +} + +const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const +{ +    return bels_by_tile.at(x).at(y); +} + +bool Arch::getBelGlobalBuf(BelId bel) const +{ +    return  bels.at(bel).gb; +} +  uint32_t Arch::getBelChecksum(BelId bel) const  {      // FIXME @@ -234,6 +258,7 @@ std::vector<PortPin> Arch::getBelPins(BelId bel) const      std::vector<PortPin> ret;      for (auto &it : bels.at(bel).pins)          ret.push_back(it.first); +    return ret;  }  // --------------------------------------------------------------- @@ -368,13 +393,6 @@ const std::vector<GroupId> &Arch::getGroupGroups(GroupId group) const { return g  // --------------------------------------------------------------- -void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const -{ -    x = bels.at(bel).x; -    y = bels.at(bel).y; -    gb = bels.at(bel).gb; -} -  delay_t Arch::estimateDelay(WireId src, WireId dst) const  {      const WireInfo &s = wires.at(src); diff --git a/generic/arch.h b/generic/arch.h index 61e6b033..97ed1ac2 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -141,7 +141,7 @@ struct Arch : BaseCtx      IdString getBelName(BelId bel) const;      Loc getBelLocation(BelId bel) const;      BelId getBelByLocation(Loc loc) const; -    std::vector<BelId> getBelsByTile(int x, int y) const; +    const std::vector<BelId> &getBelsByTile(int x, int y) const;      bool getBelGlobalBuf(BelId bel) const;      uint32_t getBelChecksum(BelId bel) const;      void bindBel(BelId bel, IdString cell, PlaceStrength strength); @@ -191,7 +191,6 @@ struct Arch : BaseCtx      const std::vector<PipId> &getGroupPips(GroupId group) const;      const std::vector<GroupId> &getGroupGroups(GroupId group) const; -    void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;      delay_t estimateDelay(WireId src, WireId dst) const;      delay_t getDelayEpsilon() const { return 0.01; }      delay_t getRipupDelayPenalty() const { return 1.0; } diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index e21af678..7ccb3445 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -246,7 +246,7 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent)  {      colors_.background = QColor("#000000");      colors_.grid = QColor("#333"); -    colors_.frame = QColor("#d0d0d0"); +    colors_.frame = QColor("#808080");      colors_.hidden = QColor("#606060");      colors_.inactive = QColor("#303030");      colors_.active = QColor("#f0f0f0"); @@ -327,7 +327,7 @@ void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal)              line.build(out);          } -        if (el.type == GraphicElement::G_LINE) { +        if (el.type == GraphicElement::G_LINE || el.type == GraphicElement::G_ARROW) {              PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, offsetY + scale * el.y2)                      .build(out);          } @@ -360,7 +360,7 @@ void FPGAViewWidget::drawDecal(LineShaderData out[], const DecalXY &decal)              }          } -        if (el.type == GraphicElement::G_LINE) { +        if (el.type == GraphicElement::G_LINE || el.type == GraphicElement::G_ARROW) {              auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2,                                   offsetY + scale * el.y2);              switch (el.style) { diff --git a/ice40/arch.cc b/ice40/arch.cc index 5c632faa..1d7e9546 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -292,23 +292,6 @@ BelRange Arch::getBelsByTile(int x, int y) const      return br;  } -BelRange Arch::getBelsAtSameTile(BelId bel) const -{ -    BelRange br; -    NPNR_ASSERT(bel != BelId()); -    int x = chip_info->bel_data[bel.index].x; -    int y = chip_info->bel_data[bel.index].y; -    int start = bel.index, end = bel.index; -    while (start >= 0 && chip_info->bel_data[start].x == x && chip_info->bel_data[start].y == y) -        start--; -    start++; -    br.b.cursor = start; -    while (end < chip_info->num_bels && chip_info->bel_data[end].x == x && chip_info->bel_data[end].y == y) -        end++; -    br.e.cursor = end; -    return br; -} -  PortType Arch::getBelPinType(BelId bel, PortPin pin) const  {      NPNR_ASSERT(bel != BelId()); @@ -484,14 +467,6 @@ std::vector<GroupId> Arch::getGroupGroups(GroupId group) const  // ----------------------------------------------------------------------- -void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const -{ -    NPNR_ASSERT(bel != BelId()); -    x = chip_info->bel_data[bel.index].x; -    y = chip_info->bel_data[bel.index].y; -    gb = chip_info->bel_data[bel.index].type == TYPE_SB_GB; -} -  delay_t Arch::estimateDelay(WireId src, WireId dst) const  {      NPNR_ASSERT(src != WireId()); @@ -735,6 +710,14 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort          } else if (fromPort == id("I2") && toPort == id("COUT")) {              delay = 230;              return true; +        } else if (fromPort == id("CLK") && toPort == id("O")) { +            delay = 540; +            return true; +        } +    } else if (cell->type == id("ICESTORM_RAM")) { +        if (fromPort == id("RCLK")) { +            delay = 2140; +            return true;          }      }      return false; @@ -745,6 +728,11 @@ IdString Arch::getPortClock(const CellInfo *cell, IdString port) const      if (cell->type == id("ICESTORM_LC") && bool_or_default(cell->params, id("DFF_ENABLE"))) {          if (port != id("LO") && port != id("CIN") && port != id("COUT"))              return id("CLK"); +    } else if (cell->type == id("ICESTORM_RAM")) { +        if (port.str(this)[0] == 'R') +            return id("RCLK"); +        else +            return id("WCLK");      }      return IdString();  } @@ -753,6 +741,8 @@ bool Arch::isClockPort(const CellInfo *cell, IdString port) const  {      if (cell->type == id("ICESTORM_LC") && port == id("CLK"))          return true; +    if (cell->type == id("ICESTORM_RAM") && (port == id("RCLK") || (port == id("WCLK")))) +        return true;      return false;  } diff --git a/ice40/arch.h b/ice40/arch.h index f0060d48..3aec25a2 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -83,10 +83,6 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD {      int32_t num_uphill, num_downhill;      RelPtr<int32_t> pips_uphill, pips_downhill; -    int32_t num_bels_uphill, num_bels_downhill; -    RelPtr<BelPortPOD> bels_uphill; -    RelPtr<BelPortPOD> bels_downhill; -      int32_t num_bel_pins;      RelPtr<BelPortPOD> bel_pins; @@ -453,8 +449,6 @@ struct Arch : BaseCtx      bool getBelGlobalBuf(BelId bel) const { return chip_info->bel_data[bel.index].type == TYPE_SB_GB; } -    BelRange getBelsAtSameTile(BelId bel) const NPNR_DEPRECATED; -      BelType getBelType(BelId bel) const      {          NPNR_ASSERT(bel != BelId()); @@ -685,7 +679,6 @@ struct Arch : BaseCtx      // ------------------------------------------------- -    void estimatePosition(BelId bel, int &x, int &y, bool &gb) const NPNR_DEPRECATED;      delay_t estimateDelay(WireId src, WireId dst) const;      delay_t getDelayEpsilon() const { return 20; }      delay_t getRipupDelayPenalty() const { return 200; } diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index 16cc757e..59e1807d 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -72,7 +72,8 @@ bool Arch::isBelLocationValid(BelId bel) const  {      if (getBelType(bel) == TYPE_ICESTORM_LC) {          std::vector<const CellInfo *> bel_cells; -        for (auto bel_other : getBelsAtSameTile(bel)) { +        Loc bel_loc = getBelLocation(bel); +        for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {              IdString cell_other = getBoundBelCell(bel_other);              if (cell_other != IdString()) {                  const CellInfo *ci_other = cells.at(cell_other).get(); @@ -95,8 +96,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const          NPNR_ASSERT(getBelType(bel) == TYPE_ICESTORM_LC);          std::vector<const CellInfo *> bel_cells; - -        for (auto bel_other : getBelsAtSameTile(bel)) { +        Loc bel_loc = getBelLocation(bel); +        for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {              IdString cell_other = getBoundBelCell(bel_other);              if (cell_other != IdString() && bel_other != bel) {                  const CellInfo *ci_other = cells.at(cell_other).get(); diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index 246d0f57..98164e87 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -79,8 +79,6 @@ void arch_wrap_python()                    conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");      fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,                                                                                                               "getBels"); -    fn_wrapper_1a<Context, decltype(&Context::getBelsAtSameTile), &Context::getBelsAtSameTile, wrap_context<BelRange>, -                  conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelsAtSameTile");      fn_wrapper_2a<Context, decltype(&Context::getBelPinWire), &Context::getBelPinWire, conv_to_str<WireId>,                    conv_from_str<BelId>, conv_from_str<PortPin>>::def_wrap(ctx_cls, "getBelPinWire"); diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 63d90b45..108197c1 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -41,8 +41,6 @@ extra_cells = dict()  extra_cell_config = dict()  packages = list() -wire_uphill_belports = dict() -wire_downhill_belports = dict()  wire_belports = dict()  wire_names = dict() @@ -453,18 +451,12 @@ for i in range(8):      add_wire(0, 0, "padin_%d" % i)  def add_bel_input(bel, wire, port): -    if wire not in wire_downhill_belports: -        wire_downhill_belports[wire] = set() -    wire_downhill_belports[wire].add((bel, port))      if wire not in wire_belports:          wire_belports[wire] = set()      wire_belports[wire].add((bel, port))      bel_wires[bel].append((wire, port, 0))  def add_bel_output(bel, wire, port): -    if wire not in wire_uphill_belports: -        wire_uphill_belports[wire] = set() -    wire_uphill_belports[wire].add((bel, port))      if wire not in wire_belports:          wire_belports[wire] = set()      wire_belports[wire].add((bel, port)) @@ -672,7 +664,7 @@ for tile_xy, tile_type in sorted(tiles.items()):              add_bel_ec(ec)  for ec in sorted(extra_cells.keys()): -    if ec[1] == 0 and ec[2] == 0: +    if ec[1] in (0, dev_width - 1) and ec[2] in (0, dev_height - 1):          add_bel_ec(ec)  class BinaryBlobAssembler: @@ -1011,24 +1003,6 @@ for wire in range(num_wires):          num_downhill = 0          list_downhill = None -    if wire in wire_uphill_belports: -        num_bels_uphill = len(wire_uphill_belports[wire]) -        bba.l("wire%d_upbels" % wire, "BelPortPOD") -        for belport in sorted(wire_uphill_belports[wire]): -            bba.u32(belport[0], "bel_index") -            bba.u32(portpins[belport[1]], "port") -    else: -        num_bels_uphill = 0 - -    if wire in wire_downhill_belports: -        num_bels_downhill = len(wire_downhill_belports[wire]) -        bba.l("wire%d_downbels" % wire, "BelPortPOD") -        for belport in sorted(wire_downhill_belports[wire]): -            bba.u32(belport[0], "bel_index") -            bba.u32(portpins[belport[1]], "port") -    else: -        num_bels_downhill = 0 -      if wire in wire_belports:          num_bel_pins = len(wire_belports[wire])          bba.l("wire%d_bels" % wire, "BelPortPOD") @@ -1047,12 +1021,6 @@ for wire in range(num_wires):      info["num_downhill"] = num_downhill      info["list_downhill"] = list_downhill -    info["num_bels_downhill"] = num_bels_downhill -    info["list_bels_downhill"] = ("wire%d_downbels" % wire) if num_bels_downhill > 0 else None - -    info["num_bels_uphill"] = num_bels_uphill -    info["list_bels_uphill"] = ("wire%d_upbels" % wire) if num_bels_uphill > 0 else None -      info["num_bel_pins"] = num_bel_pins      info["list_bel_pins"] = ("wire%d_bels" % wire) if num_bel_pins > 0 else None @@ -1130,10 +1098,6 @@ for wire, info in enumerate(wireinfo):      bba.u32(info["num_downhill"], "num_downhill")      bba.r(info["list_uphill"], "pips_uphill")      bba.r(info["list_downhill"], "pips_downhill") -    bba.u32(info["num_bels_uphill"], "num_bels_uphill") -    bba.u32(info["num_bels_downhill"], "num_bels_downhill") -    bba.r(info["list_bels_uphill"], "bels_uphill") -    bba.r(info["list_bels_downhill"], "bels_downhill")      bba.u32(info["num_bel_pins"], "num_bel_pins")      bba.r(info["list_bel_pins"], "bel_pins")      bba.u32(len(wire_segments[wire]), "num_segments") diff --git a/ice40/family.cmake b/ice40/family.cmake index 9af06f82..95cdf331 100644 --- a/ice40/family.cmake +++ b/ice40/family.cmake @@ -19,13 +19,18 @@ if (MSVC)      set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ice40/resources/chipdb.rc PROPERTIES LANGUAGE RC)      foreach (dev ${devices})          set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt) +        set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bba)          set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bin)          set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/portpins.inc)          set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h) -        add_custom_command(OUTPUT ${DEV_CC_DB} -                COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -b -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_DB} +        add_custom_command(OUTPUT ${DEV_CC_BBA_DB} +                COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -b -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB}                  DEPENDS ${DEV_TXT_DB} ${DB_PY}                  ) +        add_custom_command(OUTPUT ${DEV_CC_DB} +                COMMAND bbasm < ${DEV_CC_BBA_DB} > ${DEV_CC_DB} +                DEPENDS bbasm ${DEV_CC_BBA_DB} +        )          target_sources(ice40_chipdb PRIVATE ${DEV_CC_DB})          set_source_files_properties(${DEV_CC_DB} PROPERTIES HEADER_FILE_ONLY TRUE)          foreach (target ${family_targets}) @@ -36,14 +41,20 @@ else()      target_compile_options(ice40_chipdb PRIVATE -g0 -O0 -w)      foreach (dev ${devices})          set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt) +        set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bba)          set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.cc)          set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/portpins.inc)          set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h) +        add_custom_command(OUTPUT ${DEV_CC_BBA_DB} +                COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -c -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB}.new +                COMMAND mv ${DEV_CC_BBA_DB}.new ${DEV_CC_BBA_DB} +                DEPENDS ${DEV_TXT_DB} ${DB_PY} +        )          add_custom_command(OUTPUT ${DEV_CC_DB} -                COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -c -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_DB}.new +                COMMAND bbasm < ${DEV_CC_BBA_DB} > ${DEV_CC_DB}.new                  COMMAND mv ${DEV_CC_DB}.new ${DEV_CC_DB} -                DEPENDS ${DEV_TXT_DB} ${DB_PY} -                ) +                DEPENDS bbasm ${DEV_CC_BBA_DB} +        )          target_sources(ice40_chipdb PRIVATE ${DEV_CC_DB})          foreach (target ${family_targets})              target_sources(${target} PRIVATE $<TARGET_OBJECTS:ice40_chipdb>) diff --git a/ice40/gfx.cc b/ice40/gfx.cc index f6ed789f..1b01cbd8 100644 --- a/ice40/gfx.cc +++ b/ice40/gfx.cc @@ -647,7 +647,7 @@ void pipGfx(std::vector<GraphicElement> &g, int x, int y, float x1, float y1, fl      float ty = 0.5 * (y1 + y2);      GraphicElement el; -    el.type = GraphicElement::G_LINE; +    el.type = GraphicElement::G_ARROW;      el.style = style;      if (fabsf(x1 - swx1) < 0.001 && fabsf(x2 - swx1) < 0.001) { diff --git a/ice40/pack.cc b/ice40/pack.cc index 03b33190..b1e7380e 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -312,6 +312,10 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne                         (user.port != ctx->id("CLK") &&                          ((constval && user.port == ctx->id("CE")) || (!constval && user.port != ctx->id("CE"))))) {                  uc->ports[user.port].net = nullptr; +            } else if (is_ram(ctx, uc) && !constval && user.port != ctx->id("RCLK") && user.port != ctx->id("RCLKN") && +                       user.port != ctx->id("WCLK") && user.port != ctx->id("WCLKN") && user.port != ctx->id("RCLKE") && +                       user.port != ctx->id("WCLKE")) { +                uc->ports[user.port].net = nullptr;              } else {                  uc->ports[user.port].net = constnet;                  constnet->users.push_back(user); diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc index 2aefb839..ebc2b865 100644 --- a/ice40/place_legaliser.cc +++ b/ice40/place_legaliser.cc @@ -75,11 +75,9 @@ static void get_chain_midpoint(const Context *ctx, const CellChain &chain, float      for (auto cell : chain.cells) {          if (cell->bel == BelId())              continue; -        int bel_x, bel_y; -        bool bel_gb; -        ctx->estimatePosition(cell->bel, bel_x, bel_y, bel_gb); -        total_x += bel_x; -        total_y += bel_y; +        Loc bel_loc = ctx->getBelLocation(cell->bel); +        total_x += bel_loc.x; +        total_y += bel_loc.y;          N++;      }      NPNR_ASSERT(N > 0);  | 
