diff options
author | gatecat <gatecat@ds0.me> | 2021-03-22 09:30:38 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-22 09:30:38 +0000 |
commit | 68ca923bfefde24fa2b7cbc8c6f9817f1d93e1e5 (patch) | |
tree | bad29dce65cf448e36704e6d7b1773d8dfd573a2 /fpga_interchange/arch_iterators.h | |
parent | f52b5229642cdb54d61b54f5ab9a7478a119298e (diff) | |
parent | 22c6754bcd08f66b6f8e87a58dc09ed260c72c25 (diff) | |
download | nextpnr-68ca923bfefde24fa2b7cbc8c6f9817f1d93e1e5.tar.gz nextpnr-68ca923bfefde24fa2b7cbc8c6f9817f1d93e1e5.tar.bz2 nextpnr-68ca923bfefde24fa2b7cbc8c6f9817f1d93e1e5.zip |
Merge pull request #635 from litghost/refactor_headers
Refactor header structures in FPGA interchange Arch.
Diffstat (limited to 'fpga_interchange/arch_iterators.h')
-rw-r--r-- | fpga_interchange/arch_iterators.h | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/fpga_interchange/arch_iterators.h b/fpga_interchange/arch_iterators.h new file mode 100644 index 00000000..c59a7d18 --- /dev/null +++ b/fpga_interchange/arch_iterators.h @@ -0,0 +1,497 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2021 Symbiflow Authors + * + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef ARCH_ITERATORS_H +#define ARCH_ITERATORS_H + +#include "chipdb.h" +#include "nextpnr_namespaces.h" +#include "nextpnr_types.h" + +NEXTPNR_NAMESPACE_BEGIN + +struct BelIterator +{ + const ChipInfoPOD *chip; + int cursor_index; + int cursor_tile; + + BelIterator operator++() + { + cursor_index++; + while (cursor_tile < chip->tiles.ssize() && cursor_index >= tile_info(chip, cursor_tile).bel_data.ssize()) { + cursor_index = 0; + cursor_tile++; + } + return *this; + } + BelIterator operator++(int) + { + BelIterator prior(*this); + ++(*this); + return prior; + } + + bool operator!=(const BelIterator &other) const + { + return cursor_index != other.cursor_index || cursor_tile != other.cursor_tile; + } + + bool operator==(const BelIterator &other) const + { + return cursor_index == other.cursor_index && cursor_tile == other.cursor_tile; + } + + BelId operator*() const + { + BelId ret; + ret.tile = cursor_tile; + ret.index = cursor_index; + return ret; + } +}; + +struct BelRange +{ + BelIterator b, e; + BelIterator begin() const { return b; } + BelIterator end() const { return e; } +}; + +struct FilteredBelIterator +{ + std::function<bool(BelId)> filter; + BelIterator b, e; + + FilteredBelIterator operator++() + { + ++b; + while (b != e) { + if (filter(*b)) { + break; + } + + ++b; + } + return *this; + } + + bool operator!=(const FilteredBelIterator &other) const + { + NPNR_ASSERT(e == other.e); + return b != other.b; + } + + bool operator==(const FilteredBelIterator &other) const + { + NPNR_ASSERT(e == other.e); + return b == other.b; + } + + BelId operator*() const + { + BelId bel = *b; + NPNR_ASSERT(filter(bel)); + return bel; + } +}; + +struct FilteredBelRange +{ + FilteredBelRange(BelIterator bel_b, BelIterator bel_e, std::function<bool(BelId)> filter) + { + b.filter = filter; + b.b = bel_b; + b.e = bel_e; + + if (b.b != b.e && !filter(*b.b)) { + ++b; + } + + e.b = bel_e; + e.e = bel_e; + + if (b != e) { + NPNR_ASSERT(filter(*b.b)); + } + } + + FilteredBelIterator b, e; + FilteredBelIterator begin() const { return b; } + FilteredBelIterator end() const { return e; } +}; + +// ----------------------------------------------------------------------- + +// Iterate over TileWires for a wire (will be more than one if nodal) +struct TileWireIterator +{ + const ChipInfoPOD *chip; + WireId baseWire; + int cursor = -1; + + 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 + { + if (baseWire.tile == -1) { + WireId tw; + const auto &node_wire = chip->nodes[baseWire.index].tile_wires[cursor]; + tw.tile = node_wire.tile; + tw.index = node_wire.index; + return tw; + } else { + return baseWire; + } + } +}; + +struct TileWireRange +{ + TileWireIterator b, e; + TileWireIterator begin() const { return b; } + TileWireIterator end() const { return e; } +}; + +NPNR_ALWAYS_INLINE inline WireId canonical_wire(const ChipInfoPOD *chip_info, int32_t tile, int32_t wire) +{ + WireId id; + + if (wire >= chip_info->tiles[tile].tile_wire_to_node.ssize()) { + // Cannot be a nodal wire + id.tile = tile; + id.index = wire; + } else { + int32_t node = chip_info->tiles[tile].tile_wire_to_node[wire]; + if (node == -1) { + // Not a nodal wire + id.tile = tile; + id.index = wire; + } else { + // Is a nodal wire, set tile to -1 + id.tile = -1; + id.index = node; + } + } + + return id; +} + +// ----------------------------------------------------------------------- + +struct WireIterator +{ + const ChipInfoPOD *chip; + int cursor_index = 0; + int cursor_tile = -1; + + WireIterator operator++() + { + // Iterate over nodes first, then tile wires that aren't nodes + do { + cursor_index++; + if (cursor_tile == -1 && cursor_index >= chip->nodes.ssize()) { + cursor_tile = 0; + cursor_index = 0; + } + while (cursor_tile != -1 && cursor_tile < chip->tiles.ssize() && + cursor_index >= chip->tile_types[chip->tiles[cursor_tile].type].wire_data.ssize()) { + cursor_index = 0; + cursor_tile++; + } + + } while ((cursor_tile != -1 && cursor_tile < chip->tiles.ssize() && + cursor_index < chip->tiles[cursor_tile].tile_wire_to_node.ssize() && + chip->tiles[cursor_tile].tile_wire_to_node[cursor_index] != -1)); + + return *this; + } + WireIterator operator++(int) + { + WireIterator prior(*this); + ++(*this); + return prior; + } + + bool operator!=(const WireIterator &other) const + { + return cursor_index != other.cursor_index || cursor_tile != other.cursor_tile; + } + + bool operator==(const WireIterator &other) const + { + return cursor_index == other.cursor_index && cursor_tile == other.cursor_tile; + } + + WireId operator*() const + { + WireId ret; + ret.tile = cursor_tile; + ret.index = cursor_index; + return ret; + } +}; + +struct WireRange +{ + WireIterator b, e; + WireIterator begin() const { return b; } + WireIterator end() const { return e; } +}; + +// ----------------------------------------------------------------------- +struct AllPipIterator +{ + const ChipInfoPOD *chip; + int cursor_index; + int cursor_tile; + + AllPipIterator operator++() + { + cursor_index++; + while (cursor_tile < chip->tiles.ssize() && + cursor_index >= chip->tile_types[chip->tiles[cursor_tile].type].pip_data.ssize()) { + cursor_index = 0; + cursor_tile++; + } + return *this; + } + AllPipIterator operator++(int) + { + AllPipIterator prior(*this); + ++(*this); + return prior; + } + + bool operator!=(const AllPipIterator &other) const + { + return cursor_index != other.cursor_index || cursor_tile != other.cursor_tile; + } + + bool operator==(const AllPipIterator &other) const + { + return cursor_index == other.cursor_index && cursor_tile == other.cursor_tile; + } + + PipId operator*() const + { + PipId ret; + ret.tile = cursor_tile; + ret.index = cursor_index; + return ret; + } +}; + +struct AllPipRange +{ + AllPipIterator b, e; + AllPipIterator begin() const { return b; } + AllPipIterator end() const { return e; } +}; + +// ----------------------------------------------------------------------- + +struct UphillPipIterator +{ + const ChipInfoPOD *chip; + TileWireIterator twi, twi_end; + int cursor = -1; + + void operator++() + { + cursor++; + while (true) { + if (!(twi != twi_end)) + break; + WireId w = *twi; + auto &tile = chip->tile_types[chip->tiles[w.tile].type]; + if (cursor < tile.wire_data[w.index].pips_uphill.ssize()) + break; + ++twi; + cursor = 0; + } + } + bool operator!=(const UphillPipIterator &other) const { return twi != other.twi || cursor != other.cursor; } + + PipId operator*() const + { + PipId ret; + WireId w = *twi; + ret.tile = w.tile; + ret.index = chip->tile_types[chip->tiles[w.tile].type].wire_data[w.index].pips_uphill[cursor]; + return ret; + } +}; + +struct UphillPipRange +{ + UphillPipIterator b, e; + UphillPipIterator begin() const { return b; } + UphillPipIterator end() const { return e; } +}; + +struct DownhillPipIterator +{ + const ChipInfoPOD *chip; + TileWireIterator twi, twi_end; + int cursor = -1; + + int32_t tile; + int32_t tile_type; + const RelSlice<int32_t> *pips_downhill = nullptr; + + void operator++() + { + cursor++; + while (true) { + if (!(twi != twi_end)) + break; + + if (pips_downhill == nullptr) { + WireId w = *twi; + tile_type = chip->tiles[w.tile].type; + const TileTypeInfoPOD &type = chip->tile_types[tile_type]; + + tile = w.tile; + pips_downhill = &type.wire_data[w.index].pips_downhill; + } + + if (cursor < pips_downhill->ssize()) + break; + + ++twi; + cursor = 0; + pips_downhill = nullptr; + } + } + bool operator!=(const DownhillPipIterator &other) const { return twi != other.twi || cursor != other.cursor; } + + PipId operator*() const + { + PipId ret; + ret.tile = tile; + ret.index = (*pips_downhill)[cursor]; + return ret; + } +}; + +struct DownhillPipRange +{ + DownhillPipIterator b, e; + DownhillPipIterator begin() const { return b; } + DownhillPipIterator end() const { return e; } +}; + +struct BelPinIterator +{ + const ChipInfoPOD *chip; + TileWireIterator twi, twi_end; + int cursor = -1; + + void operator++() + { + cursor++; + + while (twi != twi_end) { + WireId w = *twi; + auto &tile = tile_info(chip, w.tile); + if (cursor < tile.wire_data[w.index].bel_pins.ssize()) + break; + + ++twi; + cursor = 0; + } + } + bool operator!=(const BelPinIterator &other) const { return twi != other.twi || cursor != other.cursor; } + + BelPin operator*() const + { + BelPin ret; + WireId w = *twi; + ret.bel.tile = w.tile; + ret.bel.index = tile_info(chip, w.tile).wire_data[w.index].bel_pins[cursor].bel_index; + ret.pin.index = tile_info(chip, w.tile).wire_data[w.index].bel_pins[cursor].port; + return ret; + } +}; + +struct BelPinRange +{ + BelPinIterator b, e; + BelPinIterator begin() const { return b; } + BelPinIterator end() const { return e; } +}; + +struct IdStringIterator : std::iterator<std::forward_iterator_tag, + /*T=*/IdString, + /*Distance=*/ptrdiff_t, + /*pointer=*/IdString *, + /*reference=*/IdString> +{ + const int32_t *cursor; + + void operator++() { cursor += 1; } + + bool operator!=(const IdStringIterator &other) const { return cursor != other.cursor; } + + bool operator==(const IdStringIterator &other) const { return cursor == other.cursor; } + + IdString operator*() const { return IdString(*cursor); } +}; + +struct IdStringRange +{ + IdStringIterator b, e; + IdStringIterator begin() const { return b; } + IdStringIterator end() const { return e; } +}; + +struct BelBucketIterator +{ + IdStringIterator cursor; + + void operator++() { ++cursor; } + + bool operator!=(const BelBucketIterator &other) const { return cursor != other.cursor; } + + bool operator==(const BelBucketIterator &other) const { return cursor == other.cursor; } + + BelBucketId operator*() const + { + BelBucketId bucket; + bucket.name = IdString(*cursor); + return bucket; + } +}; + +struct BelBucketRange +{ + BelBucketIterator b, e; + BelBucketIterator begin() const { return b; } + BelBucketIterator end() const { return e; } +}; + +NEXTPNR_NAMESPACE_END + +#endif /* ARCH_ITERATORS_H */ |