diff options
Diffstat (limited to 'fpga_interchange')
| -rw-r--r-- | fpga_interchange/arch.cc | 203 | ||||
| -rw-r--r-- | fpga_interchange/arch.h | 67 | 
2 files changed, 201 insertions, 69 deletions
| diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index 6e69f137..acbe205f 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -145,10 +145,10 @@ BelRange Arch::getBelsByTile(int x, int y) const      br.e.cursor_index = chip_info->tile_types[chip_info->tiles[br.b.cursor_tile].type].num_bels;      br.b.chip = chip_info;      br.e.chip = chip_info; -    if (br.e.cursor_index == -1) -        ++br.e.cursor_index; -    else + +    if(br.b != br.e) {          ++br.e; +    }      return br;  } @@ -156,36 +156,34 @@ WireId Arch::getBelPinWire(BelId bel, IdString pin) const  {      NPNR_ASSERT(bel != BelId()); -    int num_bel_wires = locInfo(bel).bel_data[bel.index].num_bel_wires; -    const int32_t *ports = locInfo(bel).bel_data[bel.index].ports.get(); -    for (int i = 0; i < num_bel_wires; i++) { -        if (ports[i] == pin.index) { -            const int32_t *wires = locInfo(bel).bel_data[bel.index].wires.get(); -            int32_t wire_index = wires[i]; +    int pin_index = getBelPinIndex(bel, pin); +    if(pin_index < 0) { +        // Port could not be found! +        return WireId(); +    } else { +        const int32_t *wires = locInfo(bel).bel_data[bel.index].wires.get(); +        int32_t wire_index = wires[pin_index]; +        if(wire_index < 0) { +            // This BEL pin is not connected. +            return WireId(); +        } else {              return canonicalWireId(chip_info, bel.tile, wire_index);          }      } - -    // Port could not be found! -    return WireId();  }  PortType Arch::getBelPinType(BelId bel, IdString pin) const  {      NPNR_ASSERT(bel != BelId()); -    int num_bel_wires = locInfo(bel).bel_data[bel.index].num_bel_wires; -    const int32_t *ports = locInfo(bel).bel_data[bel.index].ports.get(); - -    for (int i = 0; i < num_bel_wires; i++) { -        if (ports[i] == pin.index) { -            const int32_t *types = locInfo(bel).bel_data[bel.index].types.get(); -            return PortType(types[i]); -        } +    int pin_index = getBelPinIndex(bel, pin); +    if(pin_index < 0) { +        // Port could not be found! +        return PORT_INOUT; +    } else { +        const int32_t *types = locInfo(bel).bel_data[bel.index].types.get(); +        return PortType(types[pin_index]);      } - - -    return PORT_INOUT;  }  // ----------------------------------------------------------------------- @@ -250,29 +248,95 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co  PipId Arch::getPipByName(IdString name) const  { -    if (pip_by_name_cache.count(name)) -        return pip_by_name_cache.at(name); +    // PIP name structure: +    // Tile PIP: <tile name>/<source wire name>.<destination wire name> +    // Site PIP: <site name>/<bel name>/<input bel pin name> +    // Site pin: <site name>/<bel name>      PipId ret;      setup_byname();      const std::string &s = name.str(this); -    auto sp = split_identifier_name(s.substr(8)); +    auto sp = split_identifier_name(s);      auto iter = site_by_name.find(sp.first);      if (iter != site_by_name.end()) { +        // This is either a site pip or site pin.          int tile;          int site;          std::tie(tile, site) = iter->second;          auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type]; -        auto sp3 = split_identifier_name(sp.second); -        IdString belname = id(sp3.first); -        IdString pinname = id(sp3.second); -        for (int i = 0; i < tile_info.num_pips; i++) { -            if (tile_info.pip_data[i].site == site && tile_info.pip_data[i].bel == belname.index && -                tile_info.pip_data[i].extra_data == pinname.index) { -                ret.tile = tile; -                ret.index = i; -                break; + +        // psuedo site pips are <site>/<src site wire>.<dst site wire> +        // site pips are <site>/<bel>/<pin> +        // site pins are <site>/<bel> +        auto split = sp.second.find('/'); +        if(split != std::string::npos) { +            // This is a site pip! +            IdString belname = id(sp.second.substr(0, split)); +            IdString pinname = id(sp.second.substr(split+1)); +            BelId bel = getBelByName(id(sp.first + '/' + belname.str(this))); +            NPNR_ASSERT(bel != BelId()); + +            int pin_index = getBelPinIndex(bel, pinname); +            NPNR_ASSERT(pin_index >= 0); + +            for (int i = 0; i < tile_info.num_pips; i++) { +                if (tile_info.pip_data[i].site == site && +                    tile_info.pip_data[i].bel == bel.index && +                    tile_info.pip_data[i].extra_data == pin_index) { +                    ret.tile = tile; +                    ret.index = i; +                    break; +                } +            } +        } else { +            auto split = sp.second.find('.'); +            if(split == std::string::npos) { +                // This is a site pin! +                BelId bel = getBelByName(name); +                NPNR_ASSERT(bel != BelId()); + +                for (int i = 0; i < tile_info.num_pips; i++) { +                    if (tile_info.pip_data[i].site == site && +                        tile_info.pip_data[i].bel == bel.index) { +                        ret.tile = tile; +                        ret.index = i; +                        break; +                    } +                } +            } else { +                // This is a psuedo site pip! +                IdString src_site_wire = id(sp.second.substr(0, split)); +                IdString dst_site_wire = id(sp.second.substr(split+1)); +                int32_t src_index = -1; +                int32_t dst_index = -1; +                for (int i = 0; i < tile_info.num_wires; i++) { +                    if (tile_info.wire_data[i].site == site && tile_info.wire_data[i].name == src_site_wire.index) { +                        src_index = i; +                        if(dst_index != -1) { +                            break; +                        } +                    } +                    if (tile_info.wire_data[i].site == site && tile_info.wire_data[i].name == dst_site_wire.index) { +                        dst_index = i; +                        if(src_index != -1) { +                            break; +                        } +                    } +                } + +                NPNR_ASSERT(src_index != -1); +                NPNR_ASSERT(dst_index != -1); + +                for (int i = 0; i < tile_info.num_pips; i++) { +                    if (tile_info.pip_data[i].site == site && +                        tile_info.pip_data[i].src_index == src_index && +                        tile_info.pip_data[i].dst_index == dst_index) { +                        ret.tile = tile; +                        ret.index = i; +                        break; +                    } +                }              }          }      } else { @@ -280,11 +344,32 @@ PipId Arch::getPipByName(IdString name) const          auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type];          auto spn = split_identifier_name_dot(sp.second); -        int fromwire = std::stoi(spn.first), towire = std::stoi(spn.second); +        auto src_wire_name = id(spn.first); +        auto dst_wire_name = id(spn.second); + +        int32_t src_index = -1; +        int32_t dst_index = -1; +        for (int i = 0; i < tile_info.num_wires; i++) { +            if (tile_info.wire_data[i].site == -1 && tile_info.wire_data[i].name == src_wire_name.index) { +                src_index = i; +                if(dst_index != -1) { +                    break; +                } +            } +            if (tile_info.wire_data[i].site == -1 && tile_info.wire_data[i].name == dst_wire_name.index) { +                dst_index = i; +                if(src_index != -1) { +                    break; +                } +            } +        } + +        NPNR_ASSERT(src_index != -1); +        NPNR_ASSERT(dst_index != -1);          for (int i = 0; i < tile_info.num_pips; i++) { -            if (tile_info.pip_data[i].src_index == fromwire && -                tile_info.pip_data[i].dst_index == towire) { +            if (tile_info.pip_data[i].src_index == src_index && +                tile_info.pip_data[i].dst_index == dst_index) {                  ret.tile = tile;                  ret.index = i;                  break; @@ -292,23 +377,45 @@ PipId Arch::getPipByName(IdString name) const          }      } -    pip_by_name_cache[name] = ret; -      return ret;  }  IdString Arch::getPipName(PipId pip) const  { +    // PIP name structure: +    // Tile PIP: <tile name>/<source wire name>.<destination wire name> +    // Psuedo site PIP: <site name>/<input site wire>.<output site wire> +    // Site PIP: <site name>/<bel name>/<input bel pin name> +    // Site pin: <site name>/<bel name>      NPNR_ASSERT(pip != PipId()); -    if (locInfo(pip).pip_data[pip.index].site != -1) { -        auto site_index = chip_info->tiles[pip.tile].sites[locInfo(pip).pip_data[pip.index].site]; -        auto &site = chip_info->sites[site_index]; -        return id(site.name.get() + std::string("/") + IdString(locInfo(pip).pip_data[pip.index].bel).str(this) + "/" + -                  IdString(locInfo(pip).wire_data[locInfo(pip).pip_data[pip.index].src_index].name).str(this)); +    auto &tile = chip_info->tiles[pip.tile]; +    auto &tile_type = locInfo(pip); +    auto &pip_info = tile_type.pip_data[pip.index]; +    if (pip_info.site != -1) { +        // This is either a site pin or a site pip. +        auto &site = chip_info->sites[tile.sites[pip_info.site]]; +        auto &bel = tile_type.bel_data[pip_info.bel]; +        IdString bel_name(bel.name); +        if(bel.category == BEL_CATEGORY_LOGIC) { +            // This is a psuedo pip +            IdString src_wire_name = IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].src_index].name); +            IdString dst_wire_name = IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].dst_index].name); +            return id(site.name.get() + std::string("/") + src_wire_name.str(this) + "." + dst_wire_name.str(this)); + +        } else if(bel.category == BEL_CATEGORY_ROUTING) { +            // This is a site pip. +            IdString pin_name(bel.ports[pip_info.extra_data]); +            return id(site.name.get() + std::string("/") + bel_name.str(this) + "/" + pin_name.str(this)); +        } else { +            NPNR_ASSERT(bel.category == BEL_CATEGORY_SITE_PORT); +            // This is a site pin, just the name of the BEL is a unique identifier. +            return id(site.name.get() + std::string("/") + bel_name.str(this)); +        }      } else { -        return id(std::string(chip_info->tiles[pip.tile].name.get()) + "/" + -                  std::to_string(locInfo(pip).pip_data[pip.index].src_index) + "." + -                  std::to_string(locInfo(pip).pip_data[pip.index].dst_index)); +        // This is a tile pip. +        return id(std::string(tile.name.get()) + "/" + +                  IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].src_index].name).str(this) + "." + +                  IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].dst_index].name).str(this));      }  } diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index 390af594..f00ae04f 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -77,15 +77,24 @@ NPNR_PACKED_STRUCT(struct BelInfoPOD {      int32_t num_bel_wires;      RelPtr<int32_t> ports; // port name constid -    RelPtr<int32_t> types; // port name (IN/OUT/BIDIR) +    RelPtr<int32_t> types; // port type (IN/OUT/BIDIR)      RelPtr<int32_t> wires; // connected wire index in tile, or -1 if NA      int16_t site;      int16_t site_variant; // some sites have alternative types -    int16_t is_routing; +    int16_t category;      int16_t padding;  }); +enum BELCategory { +    // BEL is a logic element +    BEL_CATEGORY_LOGIC = 0, +    // BEL is a site routing mux +    BEL_CATEGORY_ROUTING = 1, +    // BEL is a site port, e.g. boundry between site and routing graph. +    BEL_CATEGORY_SITE_PORT = 2 +}; +  NPNR_PACKED_STRUCT(struct BelPortPOD {      int32_t bel_index;      int32_t port; @@ -255,8 +264,16 @@ struct TileWireIterator      WireId baseWire;      int cursor = -1; -    void operator++() { cursor++; } -    bool operator!=(const TileWireIterator &other) const { return cursor != other.cursor; } +    void operator++() { +        cursor++; +    } + +    bool operator==(const TileWireIterator &other) const { +        return cursor == other.cursor; +    } +    bool operator!=(const TileWireIterator &other) const { +        return cursor != other.cursor; +    }      // Returns a *denormalised* identifier always pointing to a tile wire rather than a node      WireId operator*() const @@ -505,13 +522,13 @@ struct BelPinIterator      void operator++()      {          cursor++; -        while (true) { -            if (!(twi != twi_end)) -                break; + +        while (twi != twi_end) {              WireId w = *twi;              auto &tile = tileInfo(chip, w.tile);              if (cursor < tile.wire_data[w.index].num_bel_pins)                  break; +              ++twi;              cursor = 0;          } @@ -606,7 +623,7 @@ struct Arch : BaseCtx      {          NPNR_ASSERT(bel != BelId());          int site_index = locInfo(bel).bel_data[bel.index].site; -        NPNR_ASSERT(site_index != -1); +        NPNR_ASSERT(site_index >= 0);          const SiteInstInfoPOD &site = chip_info->sites[chip_info->tiles[bel.tile].sites[site_index]];          return id(std::string(site.name.get()) +                  "/" + IdString(locInfo(bel).bel_data[bel.index].name).str(this)); @@ -683,7 +700,9 @@ struct Arch : BaseCtx          return false;      } -    bool getBelHidden(BelId bel) const { return locInfo(bel).bel_data[bel.index].is_routing; } +    bool getBelHidden(BelId bel) const { +        return locInfo(bel).bel_data[bel.index].category != BEL_CATEGORY_LOGIC; +    }      IdString getBelType(BelId bel) const      { @@ -693,6 +712,19 @@ struct Arch : BaseCtx      std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const; +    int getBelPinIndex(BelId bel, IdString pin) const { +        NPNR_ASSERT(bel != BelId()); +        int num_bel_wires = locInfo(bel).bel_data[bel.index].num_bel_wires; +        const int32_t *ports = locInfo(bel).bel_data[bel.index].ports.get(); +        for (int i = 0; i < num_bel_wires; i++) { +            if (ports[i] == pin.index) { +                return i; +            } +        } + +        return -1; +    } +      WireId getBelPinWire(BelId bel, IdString pin) const;      PortType getBelPinType(BelId bel, IdString pin) const;      std::vector<IdString> getBelPins(BelId bel) const; @@ -813,10 +845,11 @@ struct Arch : BaseCtx          range.e.chip = chip_info;          range.e.baseWire = wire; -        if (wire.tile == -1) +        if (wire.tile == -1) {              range.e.cursor = chip_info->nodes[wire.index].num_tile_wires; -        else +        } else {              range.e.cursor = 1; +        }          return range;      } @@ -824,12 +857,14 @@ struct Arch : BaseCtx      {          BelPinRange range;          NPNR_ASSERT(wire != WireId()); +          TileWireRange twr = getTileWireRange(wire);          range.b.chip = chip_info;          range.b.twi = twr.b;          range.b.twi_end = twr.e;          range.b.cursor = -1;          ++range.b; +          range.e.chip = chip_info;          range.e.twi = twr.e;          range.e.twi_end = twr.e; @@ -991,16 +1026,6 @@ struct Arch : BaseCtx          return range;      } -    UphillPipRange getWireAliases(WireId wire) const -    { -        UphillPipRange range; -        range.b.cursor = 0; -        range.b.twi.cursor = 0; -        range.e.cursor = 0; -        range.e.twi.cursor = 0; -        return range; -    } -      // -------------------------------------------------      GroupId getGroupByName(IdString name) const { return GroupId(); } | 
