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_GND)
|
||||||
X(GOWIN_VCC)
|
X(GOWIN_VCC)
|
||||||
X(PLL)
|
X(PLL)
|
||||||
|
X(CLKIN_T)
|
||||||
|
X(CLKIN_C)
|
||||||
|
X(FB_T)
|
||||||
|
X(FB_C)
|
||||||
X(BOTTOM_IO_PORT_A)
|
X(BOTTOM_IO_PORT_A)
|
||||||
X(BOTTOM_IO_PORT_B)
|
X(BOTTOM_IO_PORT_B)
|
||||||
X(IOLOGIC_DUMMY)
|
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
|
// 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 {
|
NPNR_PACKED_STRUCT(struct Tile_extra_data_POD {
|
||||||
int32_t class_id;
|
int32_t class_id;
|
||||||
int16_t io16_x_off;
|
int16_t io16_x_off;
|
||||||
|
@ -157,6 +157,20 @@ class ChipExtraData(BBAStruct):
|
|||||||
self.bottom_io.serialise(f"{context}_bottom_io", bba)
|
self.bottom_io.serialise(f"{context}_bottom_io", bba)
|
||||||
bba.slice(f"{context}_diff_io_types", len(self.diff_io_types))
|
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
|
# Unique features of the tiletype
|
||||||
class TypeDesc:
|
class TypeDesc:
|
||||||
def __init__(self, dups, tiletype = '', extra_func = None, sfx = 0):
|
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
|
tdesc.tiletype = tiletype
|
||||||
return tt
|
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...
|
# pinouts, packages...
|
||||||
_tbrlre = re.compile(r"IO([TBRL])(\d+)(\w)")
|
_tbrlre = re.compile(r"IO([TBRL])(\d+)(\w)")
|
||||||
def create_packages(chip: Chip, db: chipdb):
|
def create_packages(chip: Chip, db: chipdb):
|
||||||
@ -953,6 +976,8 @@ def create_packages(chip: Chip, db: chipdb):
|
|||||||
pad_func = pad_func.rstrip('/')
|
pad_func = pad_func.rstrip('/')
|
||||||
bank = int(db.pin_bank[io_loc])
|
bank = int(db.pin_bank[io_loc])
|
||||||
pad = pkg.create_pad(pinno, tile, bel, pad_func, bank)
|
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
|
# Extra chip data
|
||||||
def create_extra_data(chip: Chip, db: chipdb, chip_flags: int):
|
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
|
// 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();
|
const PadInfoPOD *pins = ctx->package_info->pads.get();
|
||||||
size_t len = ctx->package_info->pads.ssize();
|
size_t len = ctx->package_info->pads.ssize();
|
||||||
@ -45,6 +45,25 @@ IdStringList GowinUtils::get_pin_funcs(BelId bel)
|
|||||||
return IdStringList();
|
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)
|
bool GowinUtils::is_simple_io_bel(BelId bel)
|
||||||
{
|
{
|
||||||
return chip_bel_info(ctx->chip_info, bel).flags & BelFlags::FLAG_SIMPLE_IO;
|
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);
|
Loc get_tile_io16_offs(int x, int y);
|
||||||
|
|
||||||
// pin functions: GCLKT_4, SSPI_CS, READY etc
|
// 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
|
// Bels and pips
|
||||||
bool is_simple_io_bel(BelId bel);
|
bool is_simple_io_bel(BelId bel);
|
||||||
|
@ -2624,6 +2624,8 @@ struct GowinPacker
|
|||||||
{
|
{
|
||||||
log_info("Pack PLL...\n");
|
log_info("Pack PLL...\n");
|
||||||
|
|
||||||
|
pool<BelId> used_pll_bels;
|
||||||
|
|
||||||
for (auto &cell : ctx->cells) {
|
for (auto &cell : ctx->cells) {
|
||||||
auto &ci = *cell.second;
|
auto &ci = *cell.second;
|
||||||
|
|
||||||
@ -2639,6 +2641,26 @@ struct GowinPacker
|
|||||||
ci.renamePort(ctx->idf("FDLY[%d]", i), ctx->idf("FDLY%d", i));
|
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