wip
This commit is contained in:
parent
8fb85fc44a
commit
243384d31c
@ -54,8 +54,8 @@ void NgUltraImpl::init(Context *ctx)
|
|||||||
HimbaechelAPI::init(ctx);
|
HimbaechelAPI::init(ctx);
|
||||||
for (auto bel : ctx->getBels()) {
|
for (auto bel : ctx->getBels()) {
|
||||||
if (ctx->getBelType(bel) == id_IOM) {
|
if (ctx->getBelType(bel) == id_IOM) {
|
||||||
std::deque<BelId> wfgs;
|
pool<BelId> wfgs;
|
||||||
std::deque<BelId> plls;
|
pool<BelId> plls;
|
||||||
IdString bank = tile_name_id(bel.tile);
|
IdString bank = tile_name_id(bel.tile);
|
||||||
iom_bels.emplace(bank,bel);
|
iom_bels.emplace(bank,bel);
|
||||||
WireId belpin = ctx->getBelPinWire(bel,id_CKO1);
|
WireId belpin = ctx->getBelPinWire(bel,id_CKO1);
|
||||||
@ -63,10 +63,12 @@ void NgUltraImpl::init(Context *ctx)
|
|||||||
WireId pip_dst = ctx->getPipDstWire(dh);
|
WireId pip_dst = ctx->getPipDstWire(dh);
|
||||||
for (const auto &item : ctx->getWireBelPins(pip_dst)) {
|
for (const auto &item : ctx->getWireBelPins(pip_dst)) {
|
||||||
if (boost::contains(ctx->nameOfBel(item.bel),"WFG_C")) {
|
if (boost::contains(ctx->nameOfBel(item.bel),"WFG_C")) {
|
||||||
wfgs.push_back(item.bel);
|
wfgs.emplace(item.bel);
|
||||||
|
unused_wfg.emplace(item.bel);
|
||||||
}
|
}
|
||||||
else if (boost::contains(ctx->nameOfBel(item.bel),"PLL")) {
|
else if (boost::contains(ctx->nameOfBel(item.bel),"PLL")) {
|
||||||
plls.push_back(item.bel);
|
plls.emplace(item.bel);
|
||||||
|
unused_pll.emplace(item.bel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,10 @@ public:
|
|||||||
dict<int,pool<BelId>> gck_per_lobe;
|
dict<int,pool<BelId>> gck_per_lobe;
|
||||||
|
|
||||||
pool<PipId> blocked_pips;
|
pool<PipId> blocked_pips;
|
||||||
dict<IdString, std::deque<BelId>> wfg_c_per_bank;
|
dict<IdString, pool<BelId>> wfg_c_per_bank;
|
||||||
dict<IdString, std::deque<BelId>> pll_per_bank;
|
dict<IdString, pool<BelId>> pll_per_bank;
|
||||||
|
std::set<BelId> unused_wfg;
|
||||||
|
std::set<BelId> unused_pll;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void write_bitstream_json(const std::string &filename);
|
void write_bitstream_json(const std::string &filename);
|
||||||
|
@ -48,6 +48,9 @@ inline bool is_fe(const BaseCtx *ctx, const CellInfo *cell) { return cell->type
|
|||||||
// Return true if a cell is a DFR
|
// Return true if a cell is a DFR
|
||||||
inline bool is_dfr(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_NX_DFR; }
|
inline bool is_dfr(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_NX_DFR; }
|
||||||
|
|
||||||
|
// Return true if a cell is a WFG/WFB
|
||||||
|
inline bool is_wfg(const BaseCtx *ctx, const CellInfo *cell) { return cell->type.in(id_WFB, id_WFG); }
|
||||||
|
|
||||||
// Process the contents of packed_cells
|
// Process the contents of packed_cells
|
||||||
void NgUltraPacker::flush_cells()
|
void NgUltraPacker::flush_cells()
|
||||||
{
|
{
|
||||||
@ -1052,19 +1055,34 @@ void NgUltraPacker::insert_ioms()
|
|||||||
ctx->cells.erase(bfr->name);
|
ctx->cells.erase(bfr->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &cell : ctx->cells) {
|
|
||||||
CellInfo &ci = *cell.second;
|
|
||||||
if (!ci.type.in(id_IOM))
|
|
||||||
continue;
|
|
||||||
insert_wfb(&ci, id_CKO1);
|
|
||||||
insert_wfb(&ci, id_CKO2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bfr_removed)
|
if (bfr_removed)
|
||||||
log_info(" Removed %d unused BFR\n", bfr_removed);
|
log_info(" Removed %d unused BFR\n", bfr_removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NgUltraPacker::insert_wfbs()
|
||||||
|
{
|
||||||
|
log_info("Inserting WFBs for IOMs...\n");
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
CellInfo &ci = *cell.second;
|
||||||
|
if (ci.type.in(id_IOM)) {
|
||||||
|
insert_wfb(&ci, id_CKO1);
|
||||||
|
insert_wfb(&ci, id_CKO2);
|
||||||
|
} else if (ci.type.in(id_PLL)) {
|
||||||
|
insert_wfb(&ci, id_VCO);
|
||||||
|
insert_wfb(&ci, id_REFO);
|
||||||
|
insert_wfb(&ci, id_LDFO);
|
||||||
|
insert_wfb(&ci, id_CLK_DIV1);
|
||||||
|
insert_wfb(&ci, id_CLK_DIV2);
|
||||||
|
insert_wfb(&ci, id_CLK_DIV3);
|
||||||
|
insert_wfb(&ci, id_CLK_DIVD1);
|
||||||
|
insert_wfb(&ci, id_CLK_DIVD2);
|
||||||
|
insert_wfb(&ci, id_CLK_DIVD3);
|
||||||
|
insert_wfb(&ci, id_CLK_DIVD4);
|
||||||
|
insert_wfb(&ci, id_CLK_DIVD5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NgUltraPacker::mandatory_param(CellInfo *cell, IdString param)
|
void NgUltraPacker::mandatory_param(CellInfo *cell, IdString param)
|
||||||
{
|
{
|
||||||
if (!cell->params.count(param))
|
if (!cell->params.count(param))
|
||||||
@ -1121,13 +1139,9 @@ void NgUltraPacker::insert_wfb(CellInfo *cell, IdString port)
|
|||||||
{
|
{
|
||||||
NetInfo *net = cell->getPort(port);
|
NetInfo *net = cell->getPort(port);
|
||||||
if (!net) return;
|
if (!net) return;
|
||||||
IdString bank;
|
|
||||||
if (cell->type == id_IOM) {
|
CellInfo *wfg = net_only_drives(ctx, net, is_wfg, id_ZI, true);
|
||||||
bank = uarch->tile_name_id(cell->bel.tile);
|
if (wfg) return;
|
||||||
log("bank:%s\n",bank.c_str(ctx));
|
|
||||||
}
|
|
||||||
BelId bel = uarch->wfg_c_per_bank[bank].back();
|
|
||||||
uarch->wfg_c_per_bank[bank].pop_back();
|
|
||||||
log_info(" Inserting WFB for cell '%s' port '%s'\n", cell->name.c_str(ctx), port.c_str(ctx));
|
log_info(" Inserting WFB for cell '%s' port '%s'\n", cell->name.c_str(ctx), port.c_str(ctx));
|
||||||
CellInfo *wfb = create_cell_ptr(id_WFB, ctx->id(std::string(cell->name.c_str(ctx)) + "$" + port.c_str(ctx)));
|
CellInfo *wfb = create_cell_ptr(id_WFB, ctx->id(std::string(cell->name.c_str(ctx)) + "$" + port.c_str(ctx)));
|
||||||
cell->disconnectPort(port);
|
cell->disconnectPort(port);
|
||||||
@ -1135,7 +1149,6 @@ void NgUltraPacker::insert_wfb(CellInfo *cell, IdString port)
|
|||||||
NetInfo *new_out = ctx->createNet(ctx->id(net->name.str(ctx) + "$" + port.c_str(ctx)));
|
NetInfo *new_out = ctx->createNet(ctx->id(net->name.str(ctx) + "$" + port.c_str(ctx)));
|
||||||
cell->connectPort(port, new_out);
|
cell->connectPort(port, new_out);
|
||||||
wfb->connectPort(id_ZI, new_out);
|
wfb->connectPort(id_ZI, new_out);
|
||||||
ctx->bindBel(bel, wfb, PlaceStrength::STRENGTH_LOCKED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NgUltraPacker::constrain_location(CellInfo *cell)
|
void NgUltraPacker::constrain_location(CellInfo *cell)
|
||||||
@ -1180,17 +1193,6 @@ void NgUltraPacker::pack_plls(void)
|
|||||||
disconnect_if_gnd(&ci, id_EXT_CAL5);
|
disconnect_if_gnd(&ci, id_EXT_CAL5);
|
||||||
disconnect_if_gnd(&ci, id_EXT_CAL_LOCKED);
|
disconnect_if_gnd(&ci, id_EXT_CAL_LOCKED);
|
||||||
disconnect_if_gnd(&ci, id_ARST_CAL);
|
disconnect_if_gnd(&ci, id_ARST_CAL);
|
||||||
insert_wfb(&ci, id_VCO);
|
|
||||||
insert_wfb(&ci, id_REFO);
|
|
||||||
insert_wfb(&ci, id_LDFO);
|
|
||||||
insert_wfb(&ci, id_CLK_DIV1);
|
|
||||||
insert_wfb(&ci, id_CLK_DIV2);
|
|
||||||
insert_wfb(&ci, id_CLK_DIV3);
|
|
||||||
insert_wfb(&ci, id_CLK_DIVD1);
|
|
||||||
insert_wfb(&ci, id_CLK_DIVD2);
|
|
||||||
insert_wfb(&ci, id_CLK_DIVD3);
|
|
||||||
insert_wfb(&ci, id_CLK_DIVD4);
|
|
||||||
insert_wfb(&ci, id_CLK_DIVD5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,7 +1365,7 @@ void NgUltraPacker::setup()
|
|||||||
// clock_sinks[id_XWFIFO].insert(id_WCK1);
|
// clock_sinks[id_XWFIFO].insert(id_WCK1);
|
||||||
// clock_sinks[id_XWFIFO].insert(id_WCK2);
|
// clock_sinks[id_XWFIFO].insert(id_WCK2);
|
||||||
|
|
||||||
// clock_sinks[id_DSP].insert(id_CK);
|
clock_sinks[id_DSP].insert(id_CK);
|
||||||
|
|
||||||
clock_sinks[id_PLL].insert(id_CLK_CAL);
|
clock_sinks[id_PLL].insert(id_CLK_CAL);
|
||||||
clock_sinks[id_PLL].insert(id_FBK);
|
clock_sinks[id_PLL].insert(id_FBK);
|
||||||
@ -1403,26 +1405,96 @@ void NgUltraImpl::pack()
|
|||||||
if (args.options.count("csv")) {
|
if (args.options.count("csv")) {
|
||||||
parse_csv(args.options.at("csv"));
|
parse_csv(args.options.at("csv"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
NgUltraPacker packer(ctx, this);
|
NgUltraPacker packer(ctx, this);
|
||||||
packer.setup();
|
packer.setup();
|
||||||
packer.pack_constants();
|
packer.pack_constants();
|
||||||
packer.update_lut_init();
|
packer.update_lut_init();
|
||||||
packer.update_dffs();
|
packer.update_dffs();
|
||||||
packer.pack_iobs();
|
|
||||||
packer.pack_ioms();
|
// CGB
|
||||||
packer.pack_gcks();
|
|
||||||
packer.pack_plls();
|
|
||||||
packer.pack_wfgs();
|
|
||||||
packer.pack_rams();
|
packer.pack_rams();
|
||||||
packer.pack_dsps();
|
packer.pack_dsps();
|
||||||
|
|
||||||
|
// TILE
|
||||||
packer.pack_rfs();
|
packer.pack_rfs();
|
||||||
packer.pack_cys();
|
packer.pack_cys();
|
||||||
packer.pack_lut_dffs();
|
packer.pack_lut_dffs();
|
||||||
packer.pack_dffs();
|
packer.pack_dffs();
|
||||||
|
|
||||||
|
// Tube
|
||||||
|
packer.pack_gcks();
|
||||||
|
|
||||||
|
// Ring
|
||||||
|
packer.pack_iobs();
|
||||||
|
packer.pack_ioms();
|
||||||
|
packer.pack_plls();
|
||||||
|
packer.pack_wfgs();
|
||||||
packer.insert_ioms();
|
packer.insert_ioms();
|
||||||
|
packer.insert_wfbs();
|
||||||
|
|
||||||
|
packer.pre_place();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NgUltraPacker::pre_place(void)
|
||||||
|
{
|
||||||
|
log_info("Pre-placing PLLs..\n");
|
||||||
|
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
CellInfo &ci = *cell.second;
|
||||||
|
if (!ci.type.in(id_PLL))
|
||||||
|
continue;
|
||||||
|
// Remove from list those that are used
|
||||||
|
if (ci.bel != BelId()) {
|
||||||
|
uarch->unused_pll.erase(ci.bel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// First process those on dedicated clock pins
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
CellInfo &ci = *cell.second;
|
||||||
|
if (!ci.type.in(id_PLL) || ci.bel != BelId())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NetInfo *ref = ci.getPort(id_REF);
|
||||||
|
if (ref && ref->driver.cell && ref->driver.cell->type == id_IOM) {
|
||||||
|
IdString bank= uarch->tile_name_id(ref->driver.cell->bel.tile);
|
||||||
|
bool found = false;
|
||||||
|
for (auto &bel : uarch->pll_per_bank[bank]) {
|
||||||
|
if (uarch->unused_pll.count(bel)) {
|
||||||
|
uarch->unused_pll.erase(bel);
|
||||||
|
log_info(" Using PLL in '%s' for cell '%s'.\n", uarch->tile_name(bel.tile).c_str(), ci.name.c_str(ctx));
|
||||||
|
ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_LOCKED);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
log_error(" No more available PLLs for driving '%s'.\n", ci.name.c_str(ctx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
CellInfo &ci = *cell.second;
|
||||||
|
if (!ci.type.in(id_PLL) || ci.bel != BelId())
|
||||||
|
continue;
|
||||||
|
log_warning(" PLL '%s' is not driven by clock dedicated pin.\n", ci.name.c_str(ctx));
|
||||||
|
if (uarch->unused_pll.empty())
|
||||||
|
log_error(" No more available PLLs for driving '%s'.\n", ci.name.c_str(ctx));
|
||||||
|
BelId bel = *uarch->unused_pll.begin();
|
||||||
|
uarch->unused_pll.erase(bel);
|
||||||
|
log_info(" Using PLL in '%s' for cell '%s'.\n", uarch->tile_name(bel.tile).c_str(), ci.name.c_str(ctx));
|
||||||
|
ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info("Pre-placing WFB/WFGs..\n");
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
CellInfo &ci = *cell.second;
|
||||||
|
if (!ci.type.in(id_WFG, id_WFB))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NgUltraImpl::postPlace()
|
void NgUltraImpl::postPlace()
|
||||||
{
|
{
|
||||||
log_break();
|
log_break();
|
||||||
|
@ -60,8 +60,10 @@ struct NgUltraPacker
|
|||||||
void pack_gcks();
|
void pack_gcks();
|
||||||
void pack_plls();
|
void pack_plls();
|
||||||
void pack_wfgs();
|
void pack_wfgs();
|
||||||
|
void pre_place();
|
||||||
|
|
||||||
void insert_ioms();
|
void insert_ioms();
|
||||||
|
void insert_wfbs();
|
||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user