Support post-routing CSC and SCC

This commit is contained in:
Miodrag Milanovic 2024-07-10 12:18:50 +02:00
parent 9ba4e1381d
commit fb4171a63d
4 changed files with 118 additions and 29 deletions

View File

@ -366,8 +366,8 @@ def create_tile_types(ch: Chip, bels, bel_pins, crossbars, interconnects, muxes,
vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0)
vi = tt.create_pip(f"{name}.DJ",f"{name}.DC","Virtual")
vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0)
#vi = tt.create_pip(f"{name}.DJ",f"{name}.DS","Virtual")
#vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0)
vi = tt.create_pip(f"{name}.DJ",f"{name}.DS","Virtual")
vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0)
vi = tt.create_pip(f"{name}.DJ",f"{name}.DK","Virtual")
vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0)
# DFF bypass

View File

@ -262,12 +262,60 @@ bool NgUltraImpl::get_mux_data(WireId wire, uint8_t *value)
return false;
}
bool NgUltraImpl::update_bff_to_csc(CellInfo *cell, BelId bel, PipId dst_pip)
{
const auto &bel_data = chip_bel_info(ctx->chip_info, bel);
const auto &extra_data = *reinterpret_cast<const NGUltraBelExtraDataPOD *>(bel_data.extra_data.get());
// Check if CSC mode only if FE is capable
if (extra_data.flags & BEL_EXTRA_FE_CSC) {
WireId dwire = ctx->getPipDstWire(dst_pip);
for (PipId pip : ctx->getPipsDownhill(dwire)) {
if (!ctx->getBoundPipNet(pip))
continue;
for (PipId pip2 : ctx->getPipsDownhill(ctx->getPipDstWire(pip))) {
if (!ctx->getBoundPipNet(pip2))
continue;
IdString dst = ctx->getWireName(ctx->getPipDstWire(pip2))[1];
if (boost::ends_with(dst.c_str(ctx),".DS")) {
cell->setParam(ctx->id("type"), Property("CSC"));
return true;
}
}
}
}
return false;
}
bool NgUltraImpl::update_bff_to_scc(CellInfo *cell, BelId bel, PipId dst_pip)
{
const auto &bel_data = chip_bel_info(ctx->chip_info, bel);
const auto &extra_data = *reinterpret_cast<const NGUltraBelExtraDataPOD *>(bel_data.extra_data.get());
// Check if SCC mode only if FE is capable
if (extra_data.flags & BEL_EXTRA_FE_SCC) {
WireId dwire = ctx->getPipDstWire(dst_pip);
for (PipId pip : ctx->getPipsUphill(dwire)) {
if (!ctx->getBoundPipNet(pip))
continue;
for (PipId pip2 : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) {
if (!ctx->getBoundPipNet(pip2))
continue;
IdString dst = ctx->getWireName(ctx->getPipSrcWire(pip2))[1];
if (boost::starts_with(dst.c_str(ctx),"SYSTEM.ST1")) {
cell->setParam(ctx->id("type"), Property("SCC"));
return true;
}
}
}
}
return false;
}
void NgUltraImpl::postRoute()
{
ctx->assignArchInfo();
log_break();
log_info("Resources spent on routing:\n");
int dff_bypass = 0, lut_bypass = 0, fe_new = 0, wfg_bypass = 0, gck_bypass = 0;
int bff_count = 0, csc_count = 0, scc_count = 0, lut_bypass = 0, fe_new = 0, wfg_bypass = 0, gck_bypass = 0;
for (auto &net : ctx->nets) {
NetInfo *ni = net.second.get();
for (auto &w : ni->wires) {
@ -288,10 +336,16 @@ void NgUltraImpl::postRoute()
switch(type.index) {
case id_BEYOND_FE.index :
if (extra_data.input==0) {
dff_bypass++;
// set bypass mode for DFF
cell->setParam(ctx->id("type"), Property("BFF"));
cell->params[id_dff_used] = Property(1,1);
// Note: no conflict, CSC and SCC modes are never available on same position
if (update_bff_to_csc(cell, bel, w.second.pip))
csc_count++;
else if(update_bff_to_scc(cell, bel, w.second.pip))
scc_count++;
else
bff_count++;
} else {
lut_bypass++;
cell->params[id_lut_used] = Property(1,1);
@ -311,11 +365,20 @@ void NgUltraImpl::postRoute()
}
}
}
log_info(" %6d DFFs used in bypass mode (BFF)\n", dff_bypass);
log_info(" %6d LUTs used in bypass mode\n", lut_bypass);
log_info(" %6d newly allocated FEs\n", fe_new);
log_info(" %6d WFGs used as WFB\n", wfg_bypass);
log_info(" %6d GCK\n", gck_bypass);
if (bff_count)
log_info(" %6d DFFs used as BFF\n", bff_count);
if (csc_count)
log_info(" %6d DFFs used as CSC\n", csc_count);
if (scc_count)
log_info(" %6d DFFs used as SCC\n", scc_count);
if(lut_bypass)
log_info(" %6d LUTs used in bypass mode\n", lut_bypass);
if (fe_new)
log_info(" %6d newly allocated FEs\n", fe_new);
if (wfg_bypass)
log_info(" %6d WFGs used as WFB\n", wfg_bypass);
if (gck_bypass)
log_info(" %6d GCK\n", gck_bypass);
// Handle LUT permutation
for (auto &cell : ctx->cells) {

View File

@ -99,6 +99,9 @@ TESTABLE_PRIVATE:
void route_lowskew();
void parse_csv(const std::string &filename);
void remove_constants();
bool update_bff_to_csc(CellInfo *cell, BelId bel, PipId dst_pip);
bool update_bff_to_scc(CellInfo *cell, BelId bel, PipId dst_pip);
void disable_beyond_fe_s_output(BelId bel);
// Misc utility functions
bool get_mux_data(BelId bel, IdString port, uint8_t *value);

View File

@ -1984,35 +1984,58 @@ void NgUltraPacker::pre_place(void)
}
}
void NgUltraImpl::disable_beyond_fe_s_output(BelId bel)
{
WireId dwire = ctx->getBelPinWire(bel, id_DO);
for (PipId pip : ctx->getPipsDownhill(dwire)) {
for (PipId pip2 : ctx->getPipsDownhill(ctx->getPipDstWire(pip))) {
IdString dst = ctx->getWireName(ctx->getPipDstWire(pip2))[1];
if (boost::ends_with(dst.c_str(ctx),".DS")) {
blocked_pips.emplace(pip2);
return;
}
}
}
}
void NgUltraImpl::postPlace()
{
log_break();
log_info("Limiting routing...\n");
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
if (!ci.type.in(id_CY))
continue;
// In case A input is actually used, but it is connectd to GND
// it is considered that signal is comming from RI1 crossbar.
// We need to prevent router to use that crossbar output for
// any other signal.
for (int i=1;i<=4;i++) {
IdString port = ctx->idf("A%d",i);
NetInfo *net = ci.getPort(port);
if (!net)
continue;
if (net->name.in(ctx->id("$PACKER_GND"))) {
WireId dwire = ctx->getBelPinWire(ci.bel, port);
for (PipId pip : ctx->getPipsUphill(dwire)) {
WireId src = ctx->getPipSrcWire(pip);
const std::string src_name = ctx->getWireName(src)[1].str(ctx);
if (boost::starts_with(src_name,"RI1")) {
for (PipId pip2 : ctx->getPipsDownhill(src)) {
blocked_pips.emplace(pip2);
if (ci.type == id_BEYOND_FE) {
const auto &bel_data = chip_bel_info(ctx->chip_info, ci.bel);
const auto &extra_data = *reinterpret_cast<const NGUltraBelExtraDataPOD *>(bel_data.extra_data.get());
// Check if CSC mode only if FE is capable
if ((extra_data.flags & BEL_EXTRA_FE_CSC)) {
if (str_or_default(ci.params, ctx->id("type"), "")!="DFF") continue;
// Disable routing to S output if DFF used
disable_beyond_fe_s_output(ci.bel);
}
} else if (ci.type == id_CY) {
// In case A input is actually used, but it is connectd to GND
// it is considered that signal is comming from RI1 crossbar.
// We need to prevent router to use that crossbar output for
// any other signal.
for (int i=1;i<=4;i++) {
IdString port = ctx->idf("A%d",i);
NetInfo *net = ci.getPort(port);
if (!net)
continue;
if (net->name.in(ctx->id("$PACKER_GND"))) {
WireId dwire = ctx->getBelPinWire(ci.bel, port);
for (PipId pip : ctx->getPipsUphill(dwire)) {
WireId src = ctx->getPipSrcWire(pip);
const std::string src_name = ctx->getWireName(src)[1].str(ctx);
if (boost::starts_with(src_name,"RI1")) {
for (PipId pip2 : ctx->getPipsDownhill(src)) {
blocked_pips.emplace(pip2);
}
}
}
ci.disconnectPort(port); // Disconnect A
}
ci.disconnectPort(port); // Disconnect A
}
}
}