Gowin. Add PLL pads.
If the CLKIN input of the PLL is connected to a special pin, then it makes sense to try to place the PLL so that it uses a direct implicit non-switched connection to this pin. The transfer of information about pins for various purposes has been implemented (clock input signal, feedback, etc), but so far only CLKIN is used. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
9bb46b98b4
commit
6b7723e4c1
@ -1140,6 +1140,10 @@ X(router)
|
||||
X(GOWIN_GND)
|
||||
X(GOWIN_VCC)
|
||||
X(PLL)
|
||||
X(CLKIN_T)
|
||||
X(CLKIN_C)
|
||||
X(FB_T)
|
||||
X(FB_C)
|
||||
X(BOTTOM_IO_PORT_A)
|
||||
X(BOTTOM_IO_PORT_B)
|
||||
X(IOLOGIC_DUMMY)
|
||||
|
@ -65,6 +65,12 @@ inline bool is_dsp(const CellInfo *cell) { return type_is_dsp(cell->type); }
|
||||
// ==========================================
|
||||
// extra data in the chip db
|
||||
// ==========================================
|
||||
NPNR_PACKED_STRUCT(struct Pad_extra_data_POD {
|
||||
int32_t pll_tile;
|
||||
int32_t pll_bel;
|
||||
int32_t pll_type;
|
||||
});
|
||||
|
||||
NPNR_PACKED_STRUCT(struct Tile_extra_data_POD {
|
||||
int32_t class_id;
|
||||
int16_t io16_x_off;
|
||||
|
@ -157,6 +157,20 @@ class ChipExtraData(BBAStruct):
|
||||
self.bottom_io.serialise(f"{context}_bottom_io", bba)
|
||||
bba.slice(f"{context}_diff_io_types", len(self.diff_io_types))
|
||||
|
||||
@dataclass
|
||||
class PadExtraData(BBAStruct):
|
||||
# Which PLL does this pad belong to.
|
||||
pll_tile: IdString
|
||||
pll_bel: IdString
|
||||
pll_type: IdString
|
||||
|
||||
def serialise_lists(self, context: str, bba: BBAWriter):
|
||||
pass
|
||||
def serialise(self, context: str, bba: BBAWriter):
|
||||
bba.u32(self.pll_tile.index)
|
||||
bba.u32(self.pll_bel.index)
|
||||
bba.u32(self.pll_type.index)
|
||||
|
||||
# Unique features of the tiletype
|
||||
class TypeDesc:
|
||||
def __init__(self, dups, tiletype = '', extra_func = None, sfx = 0):
|
||||
@ -917,6 +931,15 @@ def create_pll_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc
|
||||
tdesc.tiletype = tiletype
|
||||
return tt
|
||||
|
||||
# add Pll's bel to the pad
|
||||
def add_pll(chip: Chip, db: chipdb, pad: PadInfo, ioloc: str):
|
||||
try:
|
||||
if ioloc in db.pad_pll:
|
||||
row, col, ttyp, bel_name = db.pad_pll[ioloc]
|
||||
pad.extra_data = PadExtraData(chip.strs.id(f'X{col}Y{row}'), chip.strs.id(bel_name), chip.strs.id(ttyp))
|
||||
except:
|
||||
return
|
||||
|
||||
# pinouts, packages...
|
||||
_tbrlre = re.compile(r"IO([TBRL])(\d+)(\w)")
|
||||
def create_packages(chip: Chip, db: chipdb):
|
||||
@ -953,6 +976,8 @@ def create_packages(chip: Chip, db: chipdb):
|
||||
pad_func = pad_func.rstrip('/')
|
||||
bank = int(db.pin_bank[io_loc])
|
||||
pad = pkg.create_pad(pinno, tile, bel, pad_func, bank)
|
||||
# add PLL if any is connected
|
||||
add_pll(chip, db, pad, io_loc)
|
||||
|
||||
# Extra chip data
|
||||
def create_extra_data(chip: Chip, db: chipdb, chip_flags: int):
|
||||
|
@ -30,9 +30,9 @@ Loc GowinUtils::get_tile_io16_offs(int x, int y)
|
||||
}
|
||||
|
||||
// pin functions: GCLKT_4, SSPI_CS, READY etc
|
||||
IdStringList GowinUtils::get_pin_funcs(BelId bel)
|
||||
IdStringList GowinUtils::get_pin_funcs(BelId io_bel)
|
||||
{
|
||||
IdStringList bel_name = ctx->getBelName(bel);
|
||||
IdStringList bel_name = ctx->getBelName(io_bel);
|
||||
|
||||
const PadInfoPOD *pins = ctx->package_info->pads.get();
|
||||
size_t len = ctx->package_info->pads.ssize();
|
||||
@ -45,6 +45,25 @@ IdStringList GowinUtils::get_pin_funcs(BelId bel)
|
||||
return IdStringList();
|
||||
}
|
||||
|
||||
// PLL pads
|
||||
BelId GowinUtils::get_pll_bel(BelId io_bel, IdString type)
|
||||
{
|
||||
IdStringList bel_name = ctx->getBelName(io_bel);
|
||||
|
||||
const PadInfoPOD *pins = ctx->package_info->pads.get();
|
||||
size_t len = ctx->package_info->pads.ssize();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
const PadInfoPOD *pin = &pins[i];
|
||||
if (IdString(pin->tile) == bel_name[0] && IdString(pin->bel) == bel_name[1]) {
|
||||
const Pad_extra_data_POD *extra = reinterpret_cast<const Pad_extra_data_POD *>(pin->extra_data.get());
|
||||
if (extra != nullptr && IdString(extra->pll_type) == type) {
|
||||
return ctx->getBelByName(IdStringList::concat(IdString(extra->pll_tile), IdString(extra->pll_bel)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return BelId();
|
||||
}
|
||||
|
||||
bool GowinUtils::is_simple_io_bel(BelId bel)
|
||||
{
|
||||
return chip_bel_info(ctx->chip_info, bel).flags & BelFlags::FLAG_SIMPLE_IO;
|
||||
|
@ -24,7 +24,10 @@ struct GowinUtils
|
||||
Loc get_tile_io16_offs(int x, int y);
|
||||
|
||||
// pin functions: GCLKT_4, SSPI_CS, READY etc
|
||||
IdStringList get_pin_funcs(BelId bel);
|
||||
IdStringList get_pin_funcs(BelId io_bel);
|
||||
|
||||
// PLL pads (type - CLKIN, FeedBack, etc)
|
||||
BelId get_pll_bel(BelId io_bel, IdString type);
|
||||
|
||||
// Bels and pips
|
||||
bool is_simple_io_bel(BelId bel);
|
||||
|
@ -2624,6 +2624,8 @@ struct GowinPacker
|
||||
{
|
||||
log_info("Pack PLL...\n");
|
||||
|
||||
pool<BelId> used_pll_bels;
|
||||
|
||||
for (auto &cell : ctx->cells) {
|
||||
auto &ci = *cell.second;
|
||||
|
||||
@ -2639,6 +2641,26 @@ struct GowinPacker
|
||||
ci.renamePort(ctx->idf("FDLY[%d]", i), ctx->idf("FDLY%d", i));
|
||||
}
|
||||
}
|
||||
// If CLKIN is connected to a special pin, then it makes sense
|
||||
// to try to place the PLL so that it uses a direct connection
|
||||
// to this pin.
|
||||
if (ci.bel == BelId()) {
|
||||
NetInfo *ni = ci.getPort(id_CLKIN);
|
||||
if (ni && ni->driver.cell) {
|
||||
BelId pll_bel = gwu.get_pll_bel(ni->driver.cell->bel, id_CLKIN_T);
|
||||
if (ctx->debug) {
|
||||
log_info("PLL clkin driver:%s at %s, PLL bel:%s\n", ctx->nameOf(ni->driver.cell),
|
||||
ctx->getBelName(ni->driver.cell->bel).str(ctx).c_str(),
|
||||
pll_bel != BelId() ? ctx->getBelName(pll_bel).str(ctx).c_str() : "NULL");
|
||||
}
|
||||
if (pll_bel != BelId() && used_pll_bels.count(pll_bel) == 0) {
|
||||
used_pll_bels.insert(pll_bel);
|
||||
ctx->bindBel(pll_bel, &ci, PlaceStrength::STRENGTH_LOCKED);
|
||||
ci.disconnectPort(id_CLKIN);
|
||||
ci.setParam(id_INSEL, std::string("CLKIN0"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user