diff --git a/himbaechel/uarch/ng-ultra/extra_data.h b/himbaechel/uarch/ng-ultra/extra_data.h index 87957296..80726ef6 100644 --- a/himbaechel/uarch/ng-ultra/extra_data.h +++ b/himbaechel/uarch/ng-ultra/extra_data.h @@ -206,6 +206,7 @@ enum ClusterPlacement PLACE_FIFO_WEQ2, PLACE_FIFO_REQ2, PLACE_LUT_CHAIN, + PLACE_DFF_CHAIN, }; enum PipExtra diff --git a/himbaechel/uarch/ng-ultra/location_map.cc b/himbaechel/uarch/ng-ultra/location_map.cc index 83123030..db709f6c 100644 --- a/himbaechel/uarch/ng-ultra/location_map.cc +++ b/himbaechel/uarch/ng-ultra/location_map.cc @@ -471,7 +471,7 @@ Loc getNextLocInCYChain(Loc loc) return result; } -Loc getNextLocInLutChain(Loc loc) +Loc getNextLocInLUTChain(Loc loc) { Loc result = loc; result.x = loc.x; @@ -480,6 +480,24 @@ Loc getNextLocInLutChain(Loc loc) return result; } +Loc getNextLocInDFFChain(Loc loc) +{ + Loc result = loc; + if (loc.z == 31) { + if ((loc.x & 3) == 3) { + result.z = -1; // End of chain + return result; + } + result.z = 0; + result.x++; + return result; + } + int z = loc.z + 8; + if (z>31) z++; + result.z = z % 32; // BEL_LUT_Z is 0 + return result; +} + Loc getCYFE(Loc root, int pos) { int p[] = { 2-1, 25-1, 10-1, 17-1 }; diff --git a/himbaechel/uarch/ng-ultra/location_map.h b/himbaechel/uarch/ng-ultra/location_map.h index 0745d8a1..fa36b9d6 100644 --- a/himbaechel/uarch/ng-ultra/location_map.h +++ b/himbaechel/uarch/ng-ultra/location_map.h @@ -29,7 +29,8 @@ namespace ng_ultra { Loc getNextLocInDSPChain(const NgUltraImpl *impl, Loc loc); Loc getNextLocInCYChain(Loc loc); -Loc getNextLocInLutChain(Loc loc); +Loc getNextLocInLUTChain(Loc loc); +Loc getNextLocInDFFChain(Loc loc); Loc getCYFE(Loc root, int pos); Loc getXLUTFE(Loc root, int pos); Loc getXRFFE(Loc root, int pos); diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.cc b/himbaechel/uarch/ng-ultra/ng_ultra.cc index 643ec6d5..83666c2b 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.cc +++ b/himbaechel/uarch/ng-ultra/ng_ultra.cc @@ -644,7 +644,8 @@ bool NgUltraImpl::getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc Loc child_loc = if_using_basecluster(child, [&](const BaseClusterInfo *child) { switch(child->constr_z) { case PLACE_CY_CHAIN : { Loc l = getNextLocInCYChain(prev); prev = l; return l; } - case PLACE_LUT_CHAIN : { Loc l = getNextLocInLutChain(prev); prev = l; return l; } + case PLACE_LUT_CHAIN : { Loc l = getNextLocInLUTChain(prev); prev = l; return l; } + case PLACE_DFF_CHAIN : { Loc l = getNextLocInDFFChain(prev); prev = l; return l; } 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: diff --git a/himbaechel/uarch/ng-ultra/pack.cc b/himbaechel/uarch/ng-ultra/pack.cc index e53e82fa..64a74fab 100644 --- a/himbaechel/uarch/ng-ultra/pack.cc +++ b/himbaechel/uarch/ng-ultra/pack.cc @@ -382,6 +382,71 @@ void NgUltraPacker::pack_xluts(void) flush_cells(); } +void NgUltraPacker::pack_multi_dffs(void) +{ + log_info("Pack multi DFFs...\n"); + std::vector dff_chain_start; + for (auto &cell : ctx->cells) { + CellInfo &ci = *cell.second; + if (!ci.type.in(id_NX_DFF)) + continue; + NetInfo *inp = ci.getPort(id_I); + if (!inp || (inp->driver.cell && inp->driver.cell->type.in(id_NX_DFF))) continue; + int cnt = 0; + CellInfo *dff = &ci; + while(1) { + NetInfo *o = dff->getPort(id_O); + if (o->users.entries() != 1) break; + dff = (*o->users.begin()).cell; + if (dff->type == id_NX_DFF && (*o->users.begin()).port == id_I) { + cnt++; + } else break; + } + if (cnt) + dff_chain_start.push_back(&ci); + } + + int dff_only = 0, lut_and_ff = 0; + for (auto dff : dff_chain_start) { + CellInfo *root = create_cell_ptr(id_BEYOND_FE, ctx->id(dff->name.str(ctx) + "$fe")); + root->cluster = root->name; + NetInfo *net = dff->getPort(id_I); + NetInfo *o = dff->getPort(id_O); + if (net && net->driver.cell->type == id_NX_LUT && net->users.entries()==1) { + CellInfo *lut = net->driver.cell; + if (!lut->params.count(id_lut_table)) + log_error("Cell '%s' missing lut_table\n", lut->name.c_str(ctx)); + lut_to_fe(lut, root, false, lut->params[id_lut_table]); + packed_cells.insert(lut->name); + dff_to_fe(dff, root, false); + packed_cells.insert(dff->name); + ++lut_and_ff; + } else { + dff_to_fe(dff, root, true); + packed_cells.insert(dff->name); + ++dff_only; + } + while(1) { + if (o->users.entries() != 1) break; + dff = (*o->users.begin()).cell; + if (!(dff->type == id_NX_DFF && (*o->users.begin()).port == id_I)) break; + o = dff->getPort(id_O); + CellInfo *new_cell = create_cell_ptr(id_BEYOND_FE, ctx->id(dff->name.str(ctx) + "$fe")); + dff_to_fe(dff, new_cell, true); + ++dff_only; + root->constr_children.push_back(new_cell); + new_cell->cluster = root->cluster; + new_cell->constr_z = PLACE_DFF_CHAIN; + packed_cells.insert(dff->name); + } + } + if (lut_and_ff) + log_info(" %6d FEs used as LUT and DFF\n", lut_and_ff); + if (dff_only) + log_info(" %6d FEs used as DFF only\n", dff_only); + flush_cells(); +} + void NgUltraPacker::pack_lut_multi_dffs(void) { log_info("Pack LUT-multi DFFs...\n"); @@ -1994,6 +2059,7 @@ void NgUltraImpl::pack() packer.pack_cys(); packer.pack_xluts(); packer.pack_lut_multi_dffs(); + packer.pack_multi_dffs(); packer.pack_lut_dffs(); packer.pack_dffs(); diff --git a/himbaechel/uarch/ng-ultra/pack.h b/himbaechel/uarch/ng-ultra/pack.h index 7be3e1b9..f8b236c3 100644 --- a/himbaechel/uarch/ng-ultra/pack.h +++ b/himbaechel/uarch/ng-ultra/pack.h @@ -48,6 +48,7 @@ struct NgUltraPacker void update_dffs(); void pack_xluts(); void pack_lut_multi_dffs(); + void pack_multi_dffs(); void pack_lut_dffs(); void pack_dffs(); void pack_cys();