apicula: add support for magic sip pins

This commit is contained in:
Pepijn de Vos 2024-09-20 18:01:44 +02:00
parent 6ca64526bb
commit 832275cb75
5 changed files with 64 additions and 0 deletions

View File

@ -138,6 +138,7 @@ NPNR_PACKED_STRUCT(struct PadInfoPOD {
NPNR_PACKED_STRUCT(struct PackageInfoPOD {
int32_t name;
RelSlice<PadInfoPOD> pads;
RelPtr<uint8_t> extra_data;
});
NPNR_PACKED_STRUCT(struct TileInstPOD {

View File

@ -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 @@ class PackageInfo(BBAStruct):
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):

View File

@ -240,8 +240,31 @@ struct GowinCstReader
}
};
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)));
}
}
bool gowin_apply_constraints(Context *ctx, std::istream &in)
{
// implicit constraints from SiP pins
const Extra_package_data_POD *extra = reinterpret_cast<const Extra_package_data_POD *>(ctx->package_info->extra_data.get());
if(extra != nullptr) {
add_sip_constraints(ctx, extra);
}
GowinCstReader reader(ctx, in);
return reader.run();
}

View File

@ -130,6 +130,17 @@ 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;
});
NPNR_PACKED_STRUCT(struct Extra_package_data_POD {
RelSlice<Constraint_POD> cst;
});
NPNR_PACKED_STRUCT(struct Extra_chip_data_POD {
int32_t chip_flags;
Bottom_io_POD bottom_io;

View File

@ -244,6 +244,22 @@ class ChipExtraData(BBAStruct):
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) 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)
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 +1222,10 @@ def create_packages(chip: Chip, db: chipdb):
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)