diff --git a/common/kernel/base_arch.h b/common/kernel/base_arch.h index 2929bcba..96f1d804 100644 --- a/common/kernel/base_arch.h +++ b/common/kernel/base_arch.h @@ -443,7 +443,8 @@ template struct BaseArch : ArchAPI } // Routing methods - virtual void expandBoundingBox(BoundingBox &bb) const override { + virtual void expandBoundingBox(BoundingBox &bb) const override + { bb.x0 = std::max(bb.x0 - 1, 0); bb.y0 = std::max(bb.y0 - 1, 0); bb.x1 = std::min(bb.x1 + 1, this->getGridDimX()); diff --git a/himbaechel/arch.cc b/himbaechel/arch.cc index 9ae9225e..8da731f3 100644 --- a/himbaechel/arch.cc +++ b/himbaechel/arch.cc @@ -33,7 +33,7 @@ NEXTPNR_NAMESPACE_BEGIN -static constexpr int database_version = 5; +static constexpr int database_version = 6; static const ChipInfoPOD *get_chip_info(const RelPtr *ptr) { return ptr->get(); } @@ -307,6 +307,23 @@ IdStringList Arch::getPipName(PipId pip) const IdString Arch::getPipType(PipId pip) const { return IdString(); } +GroupId Arch::getGroupByName(IdStringList name) const +{ + NPNR_ASSERT(name.size() == 2); + int tile = tile_name2idx.at(name[0]); + const auto &tdata = chip_tile_info(chip_info, tile); + for (int group = 0; group < tdata.groups.ssize(); group++) { + if (IdString(tdata.groups[group].name) == name[1]) + return GroupId(tile, group); + } + return GroupId(); +} + +IdStringList Arch::getGroupName(GroupId group) const +{ + return IdStringList::concat(tile_name.at(group.tile), IdString(chip_group_info(chip_info, group).name)); +} + std::string Arch::getChipName() const { return chip_info->name.get(); } IdString Arch::archArgsToId(ArchArgs args) const @@ -504,15 +521,21 @@ IdString Arch::get_tile_type(int tile) const std::vector Arch::getDecalGraphics(DecalId decal) const { std::vector ret; - if (decal.type == DecalId::TYPE_BEL) { + if (decal.type == DecalId::TYPE_GROUP) { + GroupId group(decal.tile, decal.index); + Loc loc; + tile_xy(chip_info, decal.tile, loc.x, loc.y); + uarch->drawGroup(ret, getGroupType(group), loc); + } else if (decal.type == DecalId::TYPE_BEL) { BelId bel(decal.tile, decal.index); GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; uarch->drawBel(ret, style, getBelType(bel), getBelLocation(bel)); } else if (decal.type == DecalId::TYPE_WIRE) { WireId w(decal.tile, decal.index); - for (WireId wire: get_tile_wire_range(w)) { + for (WireId wire : get_tile_wire_range(w)) { auto wire_type = getWireType(wire); - GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; + GraphicElement::style_t style = + decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; Loc loc; tile_xy(chip_info, wire.tile, loc.x, loc.y); int32_t tilewire = chip_wire_info(chip_info, wire).tile_wire; @@ -526,7 +549,8 @@ std::vector Arch::getDecalGraphics(DecalId decal) const int32_t src_id = chip_wire_info(chip_info, src_wire).tile_wire; int32_t dst_id = chip_wire_info(chip_info, dst_wire).tile_wire; GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_HIDDEN; - uarch->drawPip(ret, style, loc, src_wire, getWireType(src_wire), src_id, dst_wire, getWireType(dst_wire), dst_id); + uarch->drawPip(ret, style, loc, src_wire, getWireType(src_wire), src_id, dst_wire, getWireType(dst_wire), + dst_id); } return ret; } @@ -557,7 +581,10 @@ DecalXY Arch::getPipDecal(PipId pip) const DecalXY Arch::getGroupDecal(GroupId group) const { - return DecalXY(); + DecalXY decalxy; + decalxy.decal = DecalId(group.tile, group.index, DecalId::TYPE_GROUP); + decalxy.decal.active = true; + return decalxy; } NEXTPNR_NAMESPACE_END diff --git a/himbaechel/arch.h b/himbaechel/arch.h index ca965c86..29f5cb8d 100644 --- a/himbaechel/arch.h +++ b/himbaechel/arch.h @@ -49,6 +49,10 @@ inline const PipDataPOD &chip_pip_info(const ChipInfoPOD *chip, PipId pip) { return chip_tile_info(chip, pip.tile).pips[pip.index]; } +inline const GroupDataPOD &chip_group_info(const ChipInfoPOD *chip, GroupId group) +{ + return chip_tile_info(chip, group.tile).groups[group.index]; +} inline const TileRoutingShapePOD &chip_tile_shape(const ChipInfoPOD *chip, int tile) { return chip->tile_shapes[chip->tile_insts[tile].shape]; @@ -332,6 +336,41 @@ template TileWireDataPOD::*ptr> struct UpDownhillPipRange // ----------------------------------------------------------------------- +template GroupDataPOD::*ptr> struct GroupObjIterator +{ + const GroupDataPOD &group; + int tile = -1; + int cursor = -1; + + GroupObjIterator(const GroupDataPOD &group, int tile, int cursor) : group(group), tile(tile), cursor(cursor) {}; + + void operator++() { cursor++; } + + bool operator!=(const GroupObjIterator &other) const + { + return tile != other.tile || cursor != other.cursor; + } + + bool operator==(const GroupObjIterator &other) const + { + return tile == other.tile && cursor == other.cursor; + } + + Tid operator*() const { return Tid(tile, (group.*ptr)[cursor]); } +}; + +template GroupDataPOD::*ptr> struct GroupObjRange +{ + using iterator = GroupObjIterator; + GroupObjRange(const GroupDataPOD &group, int tile) : b(group, tile, 0), e(group, tile, (group.*ptr).ssize()) {} + + iterator b, e; + iterator begin() const { return b; } + iterator end() const { return e; } +}; + +// ----------------------------------------------------------------------- + struct BelPinIterator { const ChipInfoPOD *chip; @@ -393,10 +432,16 @@ struct ArchArgs typedef TileObjRange BelRange; typedef TileObjRange AllPipRange; +typedef TileObjRange GroupRange; typedef UpDownhillPipRange<&TileWireDataPOD::pips_uphill> UphillPipRange; typedef UpDownhillPipRange<&TileWireDataPOD::pips_downhill> DownhillPipRange; +typedef GroupObjRange GroupBelRange; +typedef GroupObjRange GroupWireRange; +typedef GroupObjRange GroupPipRange; +typedef GroupObjRange GroupGroupRange; + struct ArchRanges : BaseArchRanges { using ArchArgsT = ArchArgs; @@ -412,6 +457,12 @@ struct ArchRanges : BaseArchRanges using WireBelPinRangeT = BelPinRange; // Pips using AllPipsRangeT = AllPipRange; + // Groups + using AllGroupsRangeT = GroupRange; + using GroupBelsRangeT = GroupBelRange; + using GroupWiresRangeT = GroupWireRange; + using GroupPipsRangeT = GroupPipRange; + using GroupGroupsRangeT = GroupGroupRange; }; struct Arch : BaseArch @@ -699,6 +750,29 @@ struct Arch : BaseArch return uarch->getClusterPlacement(cluster, root_bel, placement); } + // ------------------------------------------------- + // Group methods + GroupId getGroupByName(IdStringList name) const override; + IdStringList getGroupName(GroupId group) const override; + GroupRange getGroups() const override { return GroupRange(chip_info); } + IdString getGroupType(GroupId group) const { return IdString(chip_group_info(chip_info, group).group_type); } + GroupBelRange getGroupBels(GroupId group) const override + { + return GroupBelRange(chip_group_info(chip_info, group), group.tile); + } + GroupWireRange getGroupWires(GroupId group) const override + { + return GroupWireRange(chip_group_info(chip_info, group), group.tile); + } + GroupPipRange getGroupPips(GroupId group) const override + { + return GroupPipRange(chip_group_info(chip_info, group), group.tile); + } + GroupGroupRange getGroupGroups(GroupId group) const override + { + return GroupGroupRange(chip_group_info(chip_info, group), group.tile); + } + // ------------------------------------------------- // Decal methods std::vector getDecalGraphics(DecalId decal) const override; diff --git a/himbaechel/archdefs.h b/himbaechel/archdefs.h index 589dea99..13318bbe 100644 --- a/himbaechel/archdefs.h +++ b/himbaechel/archdefs.h @@ -102,12 +102,34 @@ struct DecalId DecalId() = default; DecalId(int32_t tile, int32_t index, DecalType type) : tile(tile), index(index), type(type) {}; - bool operator==(const DecalId &other) const { return tile == other.tile && index == other.index && type == other.type; } - bool operator!=(const DecalId &other) const { return tile != other.tile || index != other.index || type != other.type; } + bool operator==(const DecalId &other) const + { + return tile == other.tile && index == other.index && type == other.type; + } + bool operator!=(const DecalId &other) const + { + return tile != other.tile || index != other.index || type != other.type; + } unsigned int hash() const { return mkhash(tile, mkhash(index, type)); } }; -typedef IdString GroupId; +struct GroupId +{ + int32_t tile = -1; + int32_t index = -1; + + GroupId() = default; + GroupId(int32_t tile, int32_t index) : tile(tile), index(index) {}; + + bool operator==(const GroupId &other) const { return tile == other.tile && index == other.index; } + bool operator!=(const GroupId &other) const { return tile != other.tile || index != other.index; } + bool operator<(const GroupId &other) const + { + return tile < other.tile || (tile == other.tile && index < other.index); + } + unsigned int hash() const { return mkhash(tile, index); } +}; + typedef IdString BelBucketId; typedef IdString ClusterId; diff --git a/himbaechel/chipdb.h b/himbaechel/chipdb.h index 4f3241c7..099a1112 100644 --- a/himbaechel/chipdb.h +++ b/himbaechel/chipdb.h @@ -93,11 +93,23 @@ NPNR_PACKED_STRUCT(struct NodeShapePOD { int32_t timing_idx; }); +NPNR_PACKED_STRUCT(struct GroupDataPOD { + int32_t name; + int32_t group_type; + RelSlice group_bels; + RelSlice group_wires; + RelSlice group_pips; + RelSlice group_groups; + + RelPtr extra_data; +}); + NPNR_PACKED_STRUCT(struct TileTypePOD { int32_t type_name; RelSlice bels; RelSlice wires; RelSlice pips; + RelSlice groups; RelPtr extra_data; }); diff --git a/himbaechel/himbaechel_api.cc b/himbaechel/himbaechel_api.cc index 23b24769..717d1879 100644 --- a/himbaechel/himbaechel_api.cc +++ b/himbaechel/himbaechel_api.cc @@ -85,10 +85,7 @@ bool HimbaechelAPI::getClusterPlacement(ClusterId cluster, BelId root_bel, return ctx->BaseArch::getClusterPlacement(cluster, root_bel, placement); } -void HimbaechelAPI::expandBoundingBox(BoundingBox &bb) const -{ - ctx->BaseArch::expandBoundingBox(bb); -} +void HimbaechelAPI::expandBoundingBox(BoundingBox &bb) const { ctx->BaseArch::expandBoundingBox(bb); } HimbaechelArch *HimbaechelArch::list_head; HimbaechelArch::HimbaechelArch(const std::string &name) : name(name) diff --git a/himbaechel/himbaechel_api.h b/himbaechel/himbaechel_api.h index fa757401..f64c138c 100644 --- a/himbaechel/himbaechel_api.h +++ b/himbaechel/himbaechel_api.h @@ -109,10 +109,13 @@ struct HimbaechelAPI // Graphics virtual void drawBel(std::vector &g, GraphicElement::style_t style, IdString bel_type, Loc loc) {}; - virtual void drawWire(std::vector &g, GraphicElement::style_t style, Loc loc, IdString wire_type, int32_t tilewire, IdString tile_type) {}; + virtual void drawWire(std::vector &g, GraphicElement::style_t style, Loc loc, IdString wire_type, + int32_t tilewire, IdString tile_type) {}; - virtual void drawPip(std::vector &g,GraphicElement::style_t style, Loc loc, - WireId src, IdString src_type, int32_t src_id, WireId dst, IdString dst_type, int32_t dst_id) {}; + virtual void drawPip(std::vector &g, GraphicElement::style_t style, Loc loc, WireId src, + IdString src_type, int32_t src_id, WireId dst, IdString dst_type, int32_t dst_id) {}; + + virtual void drawGroup(std::vector &g, IdString group_type, Loc loc) {}; // Routing methods virtual void expandBoundingBox(BoundingBox &bb) const; diff --git a/himbaechel/himbaechel_dbgen/chip.py b/himbaechel/himbaechel_dbgen/chip.py index bedf0f28..6f7a3086 100644 --- a/himbaechel/himbaechel_dbgen/chip.py +++ b/himbaechel/himbaechel_dbgen/chip.py @@ -202,6 +202,47 @@ class PipData(BBAStruct): else: bba.u32(0) @dataclass +class GroupData(BBAStruct): + index: int + name: IdString + group_type: IdString = field(default_factory=IdString) + group_bels: list[int] = field(default_factory=list) + group_wires: list[int] = field(default_factory=list) + group_pips: list[int] = field(default_factory=list) + group_groups: list[int] = field(default_factory=list) + extra_data: object = None + + def serialise_lists(self, context: str, bba: BBAWriter): + bba.label(f"{context}_group_bels") + for idx in self.group_bels: + bba.u32(idx) + bba.label(f"{context}_group_wires") + for idx in self.group_wires: + bba.u32(idx) + bba.label(f"{context}_group_pips") + for idx in self.group_pips: + bba.u32(idx) + bba.label(f"{context}_group_groups") + for idx in self.group_groups: + bba.u32(idx) + # extra data (optional) + if self.extra_data is not None: + self.extra_data.serialise_lists(f"{context}_extra_data", bba) + bba.label(f"{context}_extra_data") + self.extra_data.serialise(f"{context}_extra_data", bba) + def serialise(self, context: str, bba: BBAWriter): + bba.u32(self.name.index) + bba.u32(self.group_type.index) + bba.slice(f"{context}_group_bels", len(self.group_bels)) + bba.slice(f"{context}_group_wires", len(self.group_wires)) + bba.slice(f"{context}_group_pips", len(self.group_pips)) + bba.slice(f"{context}_group_groups", len(self.group_groups)) + if self.extra_data is not None: + bba.ref(f"{context}_extra_data") + else: + bba.u32(0) + +@dataclass class TileType(BBAStruct): strs: StringPool gfx_wire_ids: dict() @@ -210,8 +251,10 @@ class TileType(BBAStruct): bels: list[BelData] = field(default_factory=list) pips: list[PipData] = field(default_factory=list) wires: list[TileWireData] = field(default_factory=list) + groups: list[GroupData] = field(default_factory=list) _wire2idx: dict[IdString, int] = field(default_factory=dict) + _group2idx: dict[IdString, int] = field(default_factory=dict) extra_data: object = None @@ -253,6 +296,26 @@ class TileType(BBAStruct): self.wires[dst_idx].pips_uphill.append(pip.index) self.pips.append(pip) return pip + def create_group(self, name: str, type: str): + # Create a new group of a given name and type in the tile type + group = GroupData(index=len(self.groups), + name=self.strs.id(name), + group_type=self.strs.id(type)) + self._group2idx[group.name] = group.index + self.groups.append(group) + return group + def add_bel_to_group(self, bel: BelData, group: str): + group_idx = self._group2idx[self.strs.id(group)] + self.groups[group_idx].group_bels.append(bel.index) + def add_wire_to_group(self, wire: TileWireData, group: str): + group_idx = self._group2idx[self.strs.id(group)] + self.groups[group_idx].group_wires.append(wire.index) + def add_pip_to_group(self, pip: PipData, group: str): + group_idx = self._group2idx[self.strs.id(group)] + self.groups[group_idx].group_pips.append(pip.index) + def add_group_to_group(self, sub_group: GroupData, group: str): + group_idx = self._group2idx[self.strs.id(group)] + self.groups[group_idx].group_groups.append(sub_group.index) def has_wire(self, wire: str): # Check if a wire has already been created return self.strs.id(wire) in self._wire2idx @@ -267,6 +330,8 @@ class TileType(BBAStruct): wire.serialise_lists(f"{context}_wire{i}", bba) for i, pip in enumerate(self.pips): pip.serialise_lists(f"{context}_pip{i}", bba) + for i, group in enumerate(self.groups): + group.serialise_lists(f"{context}_group{i}", bba) # lists of members bba.label(f"{context}_bels") for i, bel in enumerate(self.bels): @@ -277,6 +342,9 @@ class TileType(BBAStruct): bba.label(f"{context}_pips") for i, pip in enumerate(self.pips): pip.serialise(f"{context}_pip{i}", bba) + bba.label(f"{context}_groups") + for i, group in enumerate(self.groups): + group.serialise(f"{context}_group{i}", bba) # extra data (optional) if self.extra_data is not None: self.extra_data.serialise_lists(f"{context}_extra_data", bba) @@ -287,6 +355,7 @@ class TileType(BBAStruct): bba.slice(f"{context}_bels", len(self.bels)) bba.slice(f"{context}_wires", len(self.wires)) bba.slice(f"{context}_pips", len(self.pips)) + bba.slice(f"{context}_groups", len(self.groups)) if self.extra_data is not None: bba.ref(f"{context}_extra_data") else: @@ -839,7 +908,7 @@ class Chip: bba.label("chip_info") bba.u32(0x00ca7ca7) # magic - bba.u32(5) # version + bba.u32(6) # version bba.u32(self.width) bba.u32(self.height) diff --git a/himbaechel/himbaechel_gfxids.h b/himbaechel/himbaechel_gfxids.h index 8d954bb3..78bbabc3 100644 --- a/himbaechel/himbaechel_gfxids.h +++ b/himbaechel/himbaechel_gfxids.h @@ -44,7 +44,7 @@ enum GfxTileWireId , }; #endif -}; +}; // namespace HIMBAECHEL_UARCH NEXTPNR_NAMESPACE_END