diff --git a/nexus/arch.cc b/nexus/arch.cc index bd1728dc..19fef385 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -30,6 +30,22 @@ NEXTPNR_NAMESPACE_BEGIN +namespace { +static std::tuple split_identifier_name(const std::string &name) +{ + size_t first_slash = name.find('/'); + NPNR_ASSERT(first_slash != std::string::npos); + size_t second_slash = name.find('/', first_slash + 1); + NPNR_ASSERT(second_slash != std::string::npos); + return std::make_tuple(std::stoi(name.substr(1, first_slash)), + std::stoi(name.substr(first_slash + 2, second_slash - first_slash)), + name.substr(second_slash + 1)); +}; + +static const DatabasePOD *get_chipdb(const RelPtr *ptr) { return ptr->get(); } + +} // namespace + // ----------------------------------------------------------------------- void IdString::initialize_arch(const BaseCtx *ctx) @@ -43,10 +59,6 @@ void IdString::initialize_arch(const BaseCtx *ctx) // ----------------------------------------------------------------------- -static const DatabasePOD *get_chipdb(const RelPtr *ptr) { return ptr->get(); } - -// ----------------------------------------------------------------------- - Arch::Arch(ArchArgs args) : args(args) { // Parse device string @@ -106,4 +118,197 @@ Arch::Arch(ArchArgs args) : args(args) } } +// ----------------------------------------------------------------------- + +std::string Arch::getChipName() const { return args.device; } +IdString Arch::archArgsToId(ArchArgs args) const { return id(args.device); } + +// ----------------------------------------------------------------------- + +BelId Arch::getBelByName(IdString name) const +{ + int x, y; + std::string belname; + std::tie(x, y, belname) = split_identifier_name(name.str(this)); + NPNR_ASSERT(x >= 0 && x < chip_info->width); + NPNR_ASSERT(y >= 0 && y < chip_info->height); + auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type]; + IdString bn = id(belname); + for (size_t i = 0; i < tile.num_bels; i++) { + if (tile.bels[i].name == bn.index) { + BelId ret; + ret.tile = y * chip_info->width + x; + ret.index = i; + return ret; + } + } + return BelId(); +} + +BelRange Arch::getBelsByTile(int x, int y) const +{ + BelRange br; + NPNR_ASSERT(x >= 0 && x < chip_info->width); + NPNR_ASSERT(y >= 0 && y < chip_info->height); + 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 = db->loctypes[chip_info->grid[br.b.cursor_tile].loc_type].num_bels; + br.b.chip = chip_info; + br.b.db = db; + br.e.chip = chip_info; + br.e.db = db; + if (br.e.cursor_index == -1) + ++br.e.cursor_index; + else + ++br.e; + return br; +} + +WireId Arch::getBelPinWire(BelId bel, IdString pin) const +{ + // Binary search on wire IdString, by ID + int num_bel_wires = bel_data(bel).num_ports; + const BelWirePOD *bel_ports = bel_data(bel).ports.get(); + + if (num_bel_wires < 7) { + for (int i = 0; i < num_bel_wires; i++) { + if (int(bel_ports[i].port) == pin.index) { + return canonical_wire(bel.tile, bel_ports[i].wire_index); + } + } + } else { + int b = 0, e = num_bel_wires - 1; + while (b <= e) { + int i = (b + e) / 2; + if (int(bel_ports[i].port) == pin.index) { + return canonical_wire(bel.tile, bel_ports[i].wire_index); + } + if (int(bel_ports[i].port) > pin.index) + e = i - 1; + else + b = i + 1; + } + } + + return WireId(); +} + +PortType Arch::getBelPinType(BelId bel, IdString pin) const +{ + // Binary search on wire IdString, by ID + int num_bel_wires = bel_data(bel).num_ports; + const BelWirePOD *bel_ports = bel_data(bel).ports.get(); + + if (num_bel_wires < 7) { + for (int i = 0; i < num_bel_wires; i++) { + if (int(bel_ports[i].port) == pin.index) { + return PortType(bel_ports[i].type); + } + } + } else { + int b = 0, e = num_bel_wires - 1; + while (b <= e) { + int i = (b + e) / 2; + if (int(bel_ports[i].port) == pin.index) { + return PortType(bel_ports[i].type); + } + if (int(bel_ports[i].port) > pin.index) + e = i - 1; + else + b = i + 1; + } + } + + NPNR_ASSERT_FALSE("unknown bel pin"); +} + +std::vector Arch::getBelPins(BelId bel) const +{ + std::vector ret; + int num_bel_wires = bel_data(bel).num_ports; + const BelWirePOD *bel_ports = bel_data(bel).ports.get(); + for (int i = 0; i < num_bel_wires; i++) + ret.push_back(IdString(bel_ports[i].port)); + return ret; +} + +// ----------------------------------------------------------------------- + +WireId Arch::getWireByName(IdString name) const +{ + int x, y; + std::string wirename; + std::tie(x, y, wirename) = split_identifier_name(name.str(this)); + NPNR_ASSERT(x >= 0 && x < chip_info->width); + NPNR_ASSERT(y >= 0 && y < chip_info->height); + auto &tile = db->loctypes[chip_info->grid[y * chip_info->width + x].loc_type]; + IdString wn = id(wirename); + for (size_t i = 0; i < tile.num_wires; i++) { + if (tile.wires[i].name == wn.index) { + WireId ret; + ret.tile = y * chip_info->width + x; + ret.index = i; + return ret; + } + } + return WireId(); +} + +IdString Arch::getWireType(WireId wire) const { return id("WIRE"); } + +std::vector> Arch::getWireAttrs(WireId wire) const +{ + std::vector> ret; + + ret.emplace_back(id("INDEX"), stringf("%d", wire.index)); + + ret.emplace_back(id("GRID_X"), stringf("%d", wire.tile % chip_info->width)); + ret.emplace_back(id("GRID_Y"), stringf("%d", wire.tile / chip_info->width)); + ret.emplace_back(id("FLAGS"), stringf("%u", wire_data(wire).flags)); + + return ret; +} + +// ----------------------------------------------------------------------- + +PipId Arch::getPipByName(IdString name) const +{ + int x, y; + std::string pipname; + std::tie(x, y, pipname) = split_identifier_name(name.str(this)); + NPNR_ASSERT(x >= 0 && x < chip_info->width); + NPNR_ASSERT(y >= 0 && y < chip_info->height); + PipId ret; + ret.tile = y * chip_info->width + x; + auto sep_pos = pipname.find(':'); + ret.index = std::stoi(pipname.substr(0, sep_pos)); + return ret; +} + +IdString Arch::getPipName(PipId pip) const +{ + NPNR_ASSERT(pip != PipId()); + return id(stringf("X%d/Y%d/%d:%s->%s", pip.tile % chip_info->width, pip.tile / chip_info->width, pip.index, + nameOf(loc_data(pip).wires[pip_data(pip).from_wire].name), + nameOf(loc_data(pip).wires[pip_data(pip).to_wire].name))); +} + +IdString Arch::getPipType(PipId pip) const { return IdString(); } + +std::vector> Arch::getPipAttrs(PipId pip) const +{ + std::vector> ret; + + ret.emplace_back(id("INDEX"), stringf("%d", pip.index)); + + ret.emplace_back(id("GRID_X"), stringf("%d", pip.tile % chip_info->width)); + ret.emplace_back(id("GRID_Y"), stringf("%d", pip.tile / chip_info->width)); + + ret.emplace_back(id("FROM_TILE_WIRE"), nameOf(loc_data(pip).wires[pip_data(pip).from_wire].name)); + ret.emplace_back(id("TO_TILE_WIRE"), nameOf(loc_data(pip).wires[pip_data(pip).to_wire].name)); + + return ret; +} + NEXTPNR_NAMESPACE_END \ No newline at end of file diff --git a/nexus/arch.h b/nexus/arch.h index 2c8bad7e..91bc5f25 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -766,7 +766,6 @@ struct Arch : BaseCtx return w2n == wire_to_net.end() ? nullptr : w2n->second; } - WireId getConflictingWireWire(WireId wire) const { return wire; } DelayInfo getWireDelay(WireId wire) const