From e049d5f2fc126a7157d0c33a36f094332da7bace Mon Sep 17 00:00:00 2001 From: "D. Shah" Date: Wed, 27 Jan 2021 16:46:18 +0000 Subject: nexus: Switch from RelPtr to RelSlice This replaces RelPtrs and a separate length field with a Rust-style slice containing both a pointer and a length; with bounds checking always enforced. Thus iterating over these structures is both cleaner and safer. Signed-off-by: D. Shah --- nexus/arch.h | 162 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 77 insertions(+), 85 deletions(-) (limited to 'nexus/arch.h') diff --git a/nexus/arch.h b/nexus/arch.h index 2bc56b53..00934797 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -46,6 +46,28 @@ template struct RelPtr const T *operator->() const { return get(); } }; +NPNR_PACKED_STRUCT(template struct RelSlice { + int32_t offset; + uint32_t length; + + const T *get() const { return reinterpret_cast(reinterpret_cast(this) + offset); } + + const T &operator[](size_t index) const + { + NPNR_ASSERT(index < length); + return get()[index]; + } + + const T *begin() const { return get(); } + const T *end() const { return get() + length; } + + const size_t size() const { return length; } + + const T &operator*() const { return *(get()); } + + const T *operator->() const { return get(); } +}); + /* Fully deduplicated database @@ -73,12 +95,11 @@ NPNR_PACKED_STRUCT(struct BelWirePOD { }); NPNR_PACKED_STRUCT(struct BelInfoPOD { - int32_t name; // bel name in tile IdString - int32_t type; // bel type IdString - int16_t rel_x, rel_y; // bel location relative to parent - int32_t z; // bel location absolute Z - RelPtr ports; // ports, sorted by name IdString - int32_t num_ports; // number of ports + int32_t name; // bel name in tile IdString + int32_t type; // bel type IdString + int16_t rel_x, rel_y; // bel location relative to parent + int32_t z; // bel location absolute Z + RelSlice ports; // ports, sorted by name IdString }); NPNR_PACKED_STRUCT(struct BelPinPOD { @@ -94,10 +115,9 @@ enum TileWireFlags : uint32_t NPNR_PACKED_STRUCT(struct LocWireInfoPOD { int32_t name; // wire name in tile IdString uint32_t flags; - int32_t num_uphill, num_downhill, num_bpins; // Note this pip lists exclude neighbourhood pips - RelPtr pips_uh, pips_dh; // list of uphill/downhill pip indices in tile - RelPtr bel_pins; + RelSlice pips_uh, pips_dh; // list of uphill/downhill pip indices in tile + RelSlice bel_pins; }); enum PipFlags @@ -137,19 +157,15 @@ NPNR_PACKED_STRUCT(struct RelWireInfoPOD { uint8_t arc_flags; }); -NPNR_PACKED_STRUCT(struct WireNeighboursInfoPOD { - uint32_t num_nwires; - RelPtr neigh_wires; -}); +NPNR_PACKED_STRUCT(struct WireNeighboursInfoPOD { RelSlice neigh_wires; }); -NPNR_PACKED_STRUCT(struct LocNeighourhoodPOD { RelPtr wire_neighbours; }); +NPNR_PACKED_STRUCT(struct LocNeighourhoodPOD { RelSlice wire_neighbours; }); NPNR_PACKED_STRUCT(struct LocTypePOD { - uint32_t num_bels, num_wires, num_pips, num_nhtypes; - RelPtr bels; - RelPtr wires; - RelPtr pips; - RelPtr neighbourhoods; + RelSlice bels; + RelSlice wires; + RelSlice pips; + RelSlice neighbourhoods; }); // A physical (bitstream) tile; of which there may be more than @@ -180,8 +196,8 @@ NPNR_PACKED_STRUCT(struct GridLocationPOD { uint32_t loc_type; uint32_t loc_flags; uint16_t neighbourhood_type; - uint16_t num_phys_tiles; - RelPtr phys_tiles; + uint16_t padding; + RelSlice phys_tiles; }); enum PioSide : uint8_t @@ -216,12 +232,10 @@ NPNR_PACKED_STRUCT(struct PadInfoPOD { int8_t vref_index; // VREF index in bank, or -1 if N/A - uint16_t num_funcs; // length of special function list - uint16_t padding; // padding for alignment - - RelPtr func_strs; // list of special function IdStrings + int16_t padding; - RelPtr> pins; // package index --> package pin name + RelSlice func_strs; // list of special function IdStrings + RelSlice> pins; // package index --> package pin name }); NPNR_PACKED_STRUCT(struct GlobalBranchInfoPOD { @@ -243,34 +257,28 @@ NPNR_PACKED_STRUCT(struct GlobalSpineInfoPOD { NPNR_PACKED_STRUCT(struct GlobalHrowInfoPOD { uint16_t hrow_col; uint16_t padding; - uint32_t num_spine_cols; - RelPtr spine_cols; + RelSlice spine_cols; }); NPNR_PACKED_STRUCT(struct GlobalInfoPOD { - uint32_t num_branches, num_spines, num_hrows; - RelPtr branches; - RelPtr spines; - RelPtr hrows; + RelSlice branches; + RelSlice spines; + RelSlice hrows; }); NPNR_PACKED_STRUCT(struct ChipInfoPOD { RelPtr device_name; uint16_t width; uint16_t height; - uint32_t num_tiles; - uint32_t num_pads; - uint32_t num_packages; - RelPtr grid; + RelSlice grid; RelPtr globals; - RelPtr pads; - RelPtr packages; + RelSlice pads; + RelSlice packages; }); NPNR_PACKED_STRUCT(struct IdStringDBPOD { - uint32_t num_file_ids; // number of IDs loaded from constids.inc - uint32_t num_bba_ids; // number of IDs in BBA file - RelPtr> bba_id_strs; + uint32_t num_file_ids; + RelSlice> bba_id_strs; }); // Timing structures are generally sorted using IdString indices as keys for fast binary searches @@ -298,10 +306,8 @@ NPNR_PACKED_STRUCT(struct CellSetupHoldPOD { NPNR_PACKED_STRUCT(struct CellTimingPOD { int32_t cell_type; int32_t cell_variant; - int32_t num_prop_delays; - int32_t num_setup_holds; - RelPtr prop_delays; - RelPtr setup_holds; + RelSlice prop_delays; + RelSlice setup_holds; }); NPNR_PACKED_STRUCT(struct PipTimingPOD { @@ -314,21 +320,16 @@ NPNR_PACKED_STRUCT(struct PipTimingPOD { NPNR_PACKED_STRUCT(struct SpeedGradePOD { RelPtr name; - int32_t num_cell_types; - int32_t num_pip_classes; - RelPtr cell_types; - RelPtr pip_classes; + RelSlice cell_types; + RelSlice pip_classes; }); NPNR_PACKED_STRUCT(struct DatabasePOD { uint32_t version; - uint32_t num_chips; - uint32_t num_loctypes; - uint32_t num_speed_grades; RelPtr family; - RelPtr chips; - RelPtr loctypes; - RelPtr speed_grades; + RelSlice chips; + RelSlice loctypes; + RelSlice speed_grades; RelPtr ids; }); @@ -376,8 +377,7 @@ inline bool chip_rel_tile(const ChipInfoPOD *chip, int32_t base, int16_t rel_x, inline int32_t chip_tile_from_xy(const ChipInfoPOD *chip, int32_t x, int32_t y) { return y * chip->width + x; } inline bool chip_get_branch_loc(const ChipInfoPOD *chip, int32_t x, int32_t &branch_x) { - for (int i = 0; i < int(chip->globals->num_branches); i++) { - auto &b = chip->globals->branches[i]; + for (auto &b : chip->globals->branches) { if (x >= b.from_col && x <= b.to_col) { branch_x = b.branch_col; return true; @@ -388,8 +388,7 @@ inline bool chip_get_branch_loc(const ChipInfoPOD *chip, int32_t x, int32_t &bra inline bool chip_get_spine_loc(const ChipInfoPOD *chip, int32_t x, int32_t y, int32_t &spine_x, int32_t &spine_y) { bool y_found = false; - for (int i = 0; i < int(chip->globals->num_spines); i++) { - auto &s = chip->globals->spines[i]; + for (auto &s : chip->globals->spines) { if (y >= s.from_row && y <= s.to_row) { spine_y = s.spine_row; y_found = true; @@ -398,10 +397,8 @@ inline bool chip_get_spine_loc(const ChipInfoPOD *chip, int32_t x, int32_t y, in } if (!y_found) return false; - for (int i = 0; i < int(chip->globals->num_hrows); i++) { - auto &hr = chip->globals->hrows[i]; - for (int j = 0; j < int(hr.num_spine_cols); j++) { - int32_t sc = hr.spine_cols[j]; + for (auto &hr : chip->globals->hrows) { + for (int32_t sc : hr.spine_cols) { if (std::abs(sc - x) < 3) { spine_x = sc; return true; @@ -413,8 +410,7 @@ inline bool chip_get_spine_loc(const ChipInfoPOD *chip, int32_t x, int32_t y, in inline bool chip_get_hrow_loc(const ChipInfoPOD *chip, int32_t x, int32_t y, int32_t &hrow_x, int32_t &hrow_y) { bool y_found = false; - for (int i = 0; i < int(chip->globals->num_spines); i++) { - auto &s = chip->globals->spines[i]; + for (auto &s : chip->globals->spines) { if (std::abs(y - s.spine_row) < 3) { hrow_y = s.spine_row; y_found = true; @@ -423,10 +419,8 @@ inline bool chip_get_hrow_loc(const ChipInfoPOD *chip, int32_t x, int32_t y, int } if (!y_found) return false; - for (int i = 0; i < int(chip->globals->num_hrows); i++) { - auto &hr = chip->globals->hrows[i]; - for (int j = 0; j < int(hr.num_spine_cols); j++) { - int32_t sc = hr.spine_cols[j]; + for (auto &hr : chip->globals->hrows) { + for (int32_t sc : hr.spine_cols) { if (std::abs(sc - x) < 3) { hrow_x = hr.hrow_col; return true; @@ -487,8 +481,7 @@ inline WireId chip_canonical_wire(const DatabasePOD *db, const ChipInfoPOD *chip // Not primary; find the primary location which forms the canonical ID auto &nd = chip_nh_data(db, chip, wire); auto &wn = nd.wire_neighbours[index]; - for (size_t i = 0; i < wn.num_nwires; i++) { - auto &nw = wn.neigh_wires[i]; + for (auto &nw : wn.neigh_wires) { if (nw.arc_flags & LOGICAL_TO_PRIMARY) { if (chip_rel_loc_tile(chip, tile, nw, wire.tile)) { wire.index = nw.wire_index; @@ -507,8 +500,7 @@ inline bool chip_wire_is_primary(const DatabasePOD *db, const ChipInfoPOD *chip, // Not primary; find the primary location which forms the canonical ID auto &nd = chip_nh_data(db, chip, wire); auto &wn = nd.wire_neighbours[index]; - for (size_t i = 0; i < wn.num_nwires; i++) { - auto &nw = wn.neigh_wires[i]; + for (auto &nw : wn.neigh_wires) { if (nw.arc_flags & LOGICAL_TO_PRIMARY) { if (chip_rel_loc_tile(chip, tile, nw, wire.tile)) { return false; @@ -531,8 +523,8 @@ struct BelIterator BelIterator operator++() { cursor_index++; - while (cursor_tile < int(chip->num_tiles) && - cursor_index >= int(db->loctypes[chip->grid[cursor_tile].loc_type].num_bels)) { + while (cursor_tile < int(chip->grid.size()) && + cursor_index >= int(db->loctypes[chip->grid[cursor_tile].loc_type].bels.size())) { cursor_index = 0; cursor_tile++; } @@ -585,12 +577,12 @@ struct WireIterator // Iterate over nodes first, then tile wires that aren't nodes do { cursor_index++; - while (cursor_tile < int(chip->num_tiles) && - cursor_index >= int(db->loctypes[chip->grid[cursor_tile].loc_type].num_wires)) { + while (cursor_tile < int(chip->grid.size()) && + cursor_index >= int(db->loctypes[chip->grid[cursor_tile].loc_type].wires.size())) { cursor_index = 0; cursor_tile++; } - } while (cursor_tile < int(chip->num_tiles) && !chip_wire_is_primary(db, chip, cursor_tile, cursor_index)); + } while (cursor_tile < int(chip->grid.size()) && !chip_wire_is_primary(db, chip, cursor_tile, cursor_index)); return *this; } @@ -641,7 +633,7 @@ struct NeighWireIterator int32_t tile; do cursor++; - while (cursor < int(wn.num_nwires) && + while (cursor < int(wn.neigh_wires.size()) && ((wn.neigh_wires[cursor].arc_flags & LOGICAL_TO_PRIMARY) || !chip_rel_tile(chip, baseWire.tile, wn.neigh_wires[cursor].rel_x, wn.neigh_wires[cursor].rel_y, tile))); } @@ -683,8 +675,8 @@ struct AllPipIterator AllPipIterator operator++() { cursor_index++; - while (cursor_tile < int(chip->num_tiles) && - cursor_index >= int(db->loctypes[chip->grid[cursor_tile].loc_type].num_pips)) { + while (cursor_tile < int(chip->grid.size()) && + cursor_index >= int(db->loctypes[chip->grid[cursor_tile].loc_type].pips.size())) { cursor_index = 0; cursor_tile++; } @@ -741,7 +733,7 @@ struct UpDownhillPipIterator break; WireId w = *twi; auto &tile = db->loctypes[chip->grid[w.tile].loc_type]; - if (cursor < int(uphill ? tile.wires[w.index].num_uphill : tile.wires[w.index].num_downhill)) + if (cursor < int(uphill ? tile.wires[w.index].pips_uh.size() : tile.wires[w.index].pips_dh.size())) break; ++twi; cursor = 0; @@ -780,7 +772,7 @@ struct WireBelPinIterator while (true) { if (!(twi != twi_end)) break; - if (cursor < chip_wire_data(db, chip, *twi).num_bpins) + if (cursor < int(chip_wire_data(db, chip, *twi).bel_pins.size())) break; ++twi; cursor = 0; @@ -1176,7 +1168,7 @@ struct Arch : BaseCtx ++range.b; //-1 and then ++ deals with the case of no wires in the first tile range.e.chip = chip_info; range.e.db = db; - range.e.cursor_tile = chip_info->num_tiles; + range.e.cursor_tile = chip_info->grid.size(); range.e.cursor_index = 0; return range; } @@ -1485,7 +1477,7 @@ struct Arch : BaseCtx range.e.chip = chip_info; range.e.db = db; range.e.baseWire = wire; - range.e.cursor = nh_data(wire).wire_neighbours[wire.index].num_nwires; + range.e.cursor = nh_data(wire).wire_neighbours[wire.index].neigh_wires.size(); return range; } -- cgit v1.2.3