diff --git a/common/kernel/relptr.h b/common/kernel/relptr.h index f0f45b7d03..4a98dd682b 100644 --- a/common/kernel/relptr.h +++ b/common/kernel/relptr.h @@ -33,6 +33,8 @@ template struct RelPtr const T *get() const { return reinterpret_cast(reinterpret_cast(this) + offset); } + bool is_null() const { return offset == 0; } + const T &operator[](std::size_t index) const { return get()[index]; } const T &operator*() const { return *(get()); } diff --git a/himbaechel/chipdb.h b/himbaechel/chipdb.h index 2ac7f60b42..17430ac4c2 100644 --- a/himbaechel/chipdb.h +++ b/himbaechel/chipdb.h @@ -138,6 +138,7 @@ NPNR_PACKED_STRUCT(struct PadInfoPOD { NPNR_PACKED_STRUCT(struct PackageInfoPOD { int32_t name; RelSlice pads; + RelPtr extra_data; }); NPNR_PACKED_STRUCT(struct TileInstPOD { diff --git a/himbaechel/himbaechel_dbgen/chip.py b/himbaechel/himbaechel_dbgen/chip.py index 19aa8914d6..8650813d93 100644 --- a/himbaechel/himbaechel_dbgen/chip.py +++ b/himbaechel/himbaechel_dbgen/chip.py @@ -411,6 +411,7 @@ class PackageInfo(BBAStruct): strs: StringPool name: IdString pads: list[int] = field(default_factory=list) + extra_data: object = None def create_pad(self, package_pin: str, tile: str, bel: str, pad_function: str, pad_bank: int, flags: int = 0): pad = PadInfo(package_pin = self.strs.id(package_pin), tile = self.strs.id(tile), bel = self.strs.id(bel), @@ -424,10 +425,18 @@ def serialise_lists(self, context: str, bba: BBAWriter): bba.label(f"{context}_pads") for i, pad in enumerate(self.pads): pad.serialise(f"{context}_pad{i}", bba) + 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.slice(f"{context}_pads", len(self.pads)) + if self.extra_data is not None: + bba.ref(f"{context}_extra_data") + else: + bba.u32(0) class TimingValue(BBAStruct): def __init__(self, fast_min=0, fast_max=None, slow_min=None, slow_max=None): diff --git a/himbaechel/uarch/gowin/cst.cc b/himbaechel/uarch/gowin/cst.cc index a933cc19c6..5229a4c2a5 100644 --- a/himbaechel/uarch/gowin/cst.cc +++ b/himbaechel/uarch/gowin/cst.cc @@ -240,8 +240,38 @@ struct GowinCstReader } }; + +static void add_sip_constraints(Context *ctx, const Extra_package_data_POD *extra) { + for(auto cst : extra->cst) { + auto it = ctx->cells.find(IdString(cst.net)); + if (it == ctx->cells.end()) { + log_info("Cell %s not found\n", IdString(cst.net).c_str(ctx)); + continue; + } + Loc loc = Loc(cst.col, cst.row, cst.bel); + BelId bel = ctx->getBelByLocation(loc); + if (bel == BelId()) { + log_error("Pin not found.\n"); + } + it->second->setAttr(IdString(ID_BEL), std::string(ctx->nameOfBel(bel))); + + if(cst.iostd > 0) { + std::string attr = "&IO_TYPE="; + attr += IdString(cst.iostd).c_str(ctx); + boost::algorithm::to_upper(attr); + it->second->setAttr(ctx->id(attr), 1); + } + } +} + bool gowin_apply_constraints(Context *ctx, std::istream &in) { + // implicit constraints from SiP pins + if(!ctx->package_info->extra_data.is_null()) { + const Extra_package_data_POD *extra = reinterpret_cast(ctx->package_info->extra_data.get()); + add_sip_constraints(ctx, extra); + } + GowinCstReader reader(ctx, in); return reader.run(); } diff --git a/himbaechel/uarch/gowin/gowin.h b/himbaechel/uarch/gowin/gowin.h index 1588b27b91..001c1cfb07 100644 --- a/himbaechel/uarch/gowin/gowin.h +++ b/himbaechel/uarch/gowin/gowin.h @@ -130,6 +130,18 @@ NPNR_PACKED_STRUCT(struct Wire_bel_POD { int32_t side; }); +NPNR_PACKED_STRUCT(struct Constraint_POD { + int32_t net; + int32_t row; + int32_t col; + int32_t bel; + int32_t iostd; +}); + +NPNR_PACKED_STRUCT(struct Extra_package_data_POD { + RelSlice cst; +}); + NPNR_PACKED_STRUCT(struct Extra_chip_data_POD { int32_t chip_flags; Bottom_io_POD bottom_io; diff --git a/himbaechel/uarch/gowin/gowin_arch_gen.py b/himbaechel/uarch/gowin/gowin_arch_gen.py index 7daed96354..473efa21a9 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -244,6 +244,23 @@ def serialise(self, context: str, bba: BBAWriter): bba.slice(f"{context}_dcs_bels", len(self.dcs_bels)) bba.slice(f"{context}_dhcen_bels", len(self.dhcen_bels)) +@dataclass +class PackageExtraData(BBAStruct): + strs: StringPool + cst: list + + def serialise_lists(self, context: str, bba: BBAWriter): + bba.label(f"{context}_constraints") + for (net, row, col, bel, iostd) in self.cst: + bba.u32(self.strs.id(net).index) + bba.u32(row) + bba.u32(col) + bba.u32(ord(bel[0])-ord('A')+IOBA_Z) + bba.u32(self.strs.id(iostd).index if iostd else 0) + + def serialise(self, context: str, bba: BBAWriter): + bba.slice(f"{context}_constraints", len(self.cst)) + @dataclass class PadExtraData(BBAStruct): # Which PLL does this pad belong to. @@ -1206,6 +1223,10 @@ def ioloc_to_tile_bel(ioloc): continue created_pkgs.add(partno) pkg = chip.create_package(partno) + + if variant in db.sip_cst and pkgname in db.sip_cst[variant]: + pkg.extra_data = PackageExtraData(chip.strs, db.sip_cst[variant][pkgname]) + for pinno, pininfo in db.pinout[variant][pkgname].items(): io_loc, cfgs = pininfo tile, bel = ioloc_to_tile_bel(io_loc)