Initial XLUT support

This commit is contained in:
Miodrag Milanovic 2024-06-25 10:04:10 +02:00
parent 294e97babf
commit 37dadd121a
5 changed files with 88 additions and 15 deletions

View File

@ -42,6 +42,10 @@ enum ClusterPlacement
PLACE_CY_FE2,
PLACE_CY_FE3,
PLACE_CY_FE4,
PLACE_XLUT_FE1,
PLACE_XLUT_FE2,
PLACE_XLUT_FE3,
PLACE_XLUT_FE4,
PLACE_XRF_I1,
PLACE_XRF_I2,
PLACE_XRF_I3,

View File

@ -376,6 +376,10 @@ def create_tile_types(ch: Chip, bels, bel_pins, crossbars, interconnects, muxes,
# LUT bypass
by = tt.create_pip(f"{name}.I1",f"{name}.LO","BYPASS")
by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,1,0)
elif (tile_type.startswith("TILE") and bel=="XLUT"):
for out in ["G1","G2","G3","G4"]:
vi = tt.create_pip(f"{name}.J",f"{name}.{out}","Virtual")
vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0)
elif (tile_type.startswith("TILE") and bel=="CY"):
# matrix of each input to each output combination
# crossbar but use mux placeholder for convenience
@ -384,16 +388,16 @@ def create_tile_types(ch: Chip, bels, bel_pins, crossbars, interconnects, muxes,
pd = tt.create_pip(f"{name}."+inp,f"{name}."+out,"MATRIX_PIP")
pd.extra_data = PipExtraData(ch.strs.id(f"{name}."+inp),PIP_EXTRA_MUX,int(inp[1:])-1,int(out[1:])-1)
#elif (tile_type.startswith("CKG") and bel=="WFG"):
# by = tt.create_pip(f"{name}.ZI",f"{name}.ZO","BYPASS")
# by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0)
#elif (tile_type.startswith("TUBE") and bel=="GCK"):
# # 20 clock signals comming to 20 GCK, SI1 is bypass
# by = tt.create_pip(f"{name}.SI1",f"{name}.SO","BYPASS")
# by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0)
# # there are CMD signals that can be bypassed as well
# by = tt.create_pip(f"{name}.CMD",f"{name}.SO","BYPASS")
# by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,1,0)
elif (tile_type.startswith("CKG") and bel=="WFG"):
by = tt.create_pip(f"{name}.ZI",f"{name}.ZO","BYPASS")
by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0)
elif (tile_type.startswith("TUBE") and bel=="GCK"):
# 20 clock signals comming to 20 GCK, SI1 is bypass
by = tt.create_pip(f"{name}.SI1",f"{name}.SO","BYPASS")
by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,0,0)
# there are CMD signals that can be bypassed as well
by = tt.create_pip(f"{name}.CMD",f"{name}.SO","BYPASS")
by.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_BYPASS,1,0)
# Add LUT permutation

View File

@ -512,6 +512,15 @@ Loc getCYFE(Loc root, int pos)
return result;
}
Loc getXLUTFE(Loc root, int pos)
{
Loc result;
result.x = root.x;
result.y = root.y;
result.z = root.z - BEL_XLUT_Z + 8 * pos;
return result;
}
Loc getXRFFE(Loc root, int pos)
{
static const std::vector<Loc> map =
@ -591,7 +600,6 @@ Loc getXRFFE(Loc root, int pos)
return result;
}
Loc getCDCFE(Loc root, int pos)
{
static const std::vector<Loc> cdc1 =
@ -963,10 +971,8 @@ bool NgUltraImpl::getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc
Loc child_loc = if_using_basecluster<Loc>(child, [&](const BaseClusterInfo *child) {
switch(child->constr_z) {
case PLACE_CY_CHAIN : { Loc l = getNextLocInCYChain(prev); prev = l; return l; }
case PLACE_CY_FE1: return getCYFE(root_loc,0);
case PLACE_CY_FE2: return getCYFE(root_loc,1);
case PLACE_CY_FE3: return getCYFE(root_loc,2);
case PLACE_CY_FE4: return getCYFE(root_loc,3);
case PLACE_CY_FE1 ... PLACE_CY_FE4: return getCYFE(root_loc, child->constr_z - PLACE_CY_FE1 );
case PLACE_XLUT_FE1 ... PLACE_XLUT_FE4: return getXLUTFE(root_loc, child->constr_z - PLACE_XLUT_FE1 );
case PLACE_XRF_I1 ... PLACE_XRF_WEA:
return getXRFFE(root_loc, child->constr_z - PLACE_XRF_I1 );
case PLACE_CDC_AI1 ... PLACE_CDC_DDRSTI:

View File

@ -294,6 +294,63 @@ void NgUltraPacker::bind_attr_loc(CellInfo *cell, dict<IdString, Property> *attr
}
}
void NgUltraPacker::pack_xluts(void)
{
log_info("Pack XLUTs...\n");
int lut_only = 0;//, lut_and_ff = 0;
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
if (!ci.type.in(id_NX_LUT))
continue;
if (!ci.params.count(id_lut_table))
log_error("Cell '%s' missing lut_table\n", ci.name.c_str(ctx));
if (ci.cluster!=ClusterId())
continue;
CellInfo *lut[4];
if (!ci.getPort(id_I1))
continue;
if (!ci.getPort(id_I2))
continue;
if (!ci.getPort(id_I3))
continue;
if (!ci.getPort(id_I4))
continue;
lut[0] = net_driven_by(ctx, ci.getPort(id_I1), is_lut, id_O);
if (!lut[0] || ci.getPort(id_I1)->users.entries()!=1)
continue;
lut[1] = net_driven_by(ctx, ci.getPort(id_I2), is_lut, id_O);
if (!lut[1] || ci.getPort(id_I2)->users.entries()!=1)
continue;
lut[2] = net_driven_by(ctx, ci.getPort(id_I3), is_lut, id_O);
if (!lut[2] || ci.getPort(id_I3)->users.entries()!=1)
continue;
lut[3] = net_driven_by(ctx, ci.getPort(id_I4), is_lut, id_O);
if (!lut[3] || ci.getPort(id_I4)->users.entries()!=1)
continue;
ci.type = id_XLUT;
bind_attr_loc(&ci, &ci.attrs);
ci.cluster = ci.name;
lut_only++;
for (int i=0;i<4;i++) {
ci.constr_children.push_back(lut[i]);
lut[i]->cluster = ci.cluster;
lut[i]->type = id_BEYOND_FE;
lut[i]->constr_z = PLACE_XLUT_FE1 + i;
lut[i]->renamePort(id_O, id_LO);
lut[i]->params[id_lut_used] = Property(1,1);
lut[i]->timing_index = ctx->get_cell_timing_idx(ctx->id("BEYOND_FE_LUT"));
lut_only++;
}
}
if (lut_only)
log_info(" %6d FEs used as LUT only\n", lut_only);
//if (lut_and_ff)
// log_info(" %6d FEs used as LUT and DFF\n", lut_and_ff);
flush_cells();
}
void NgUltraPacker::pack_lut_dffs(void)
{
log_info("Pack LUT-DFFs...\n");
@ -1774,6 +1831,7 @@ void NgUltraImpl::pack()
packer.pack_cdcs();
packer.pack_fifos();
packer.pack_cys();
packer.pack_xluts();
packer.pack_lut_dffs();
packer.pack_dffs();

View File

@ -46,6 +46,7 @@ struct NgUltraPacker
// LUTs & FFs
void update_lut_init();
void update_dffs();
void pack_xluts();
void pack_lut_dffs();
void pack_dffs();
void pack_cys();