aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5/pack.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ecp5/pack.cc')
-rw-r--r--ecp5/pack.cc122
1 files changed, 117 insertions, 5 deletions
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index 14b387d5..0045617b 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -108,7 +108,7 @@ class Ecp5Packer
}
// Return whether or not an FF can be added to a tile (pairing checks must also be done using the fn above)
- bool can_add_ff_to_file(const std::vector<CellInfo *> &tile_ffs, CellInfo *ff0)
+ bool can_add_ff_to_tile(const std::vector<CellInfo *> &tile_ffs, CellInfo *ff0)
{
for (const auto &existing : tile_ffs) {
if (net_or_nullptr(existing, ctx->id("CLK")) != net_or_nullptr(ff0, ctx->id("CLK")))
@@ -128,6 +128,20 @@ class Ecp5Packer
return true;
}
+ // Return true if a FF can be added to a DPRAM slice
+ bool can_pack_ff_dram(CellInfo *dpram, CellInfo *ff)
+ {
+ std::string wckmux = str_or_default(dpram->params, ctx->id("WCKMUX"), "WCK");
+ std::string clkmux = str_or_default(ff->params, ctx->id("CLKMUX"), "CLK");
+ if (wckmux != clkmux && !(wckmux == "WCK" && clkmux == "CLK"))
+ return false;
+ std::string wremux = str_or_default(dpram->params, ctx->id("WREMUX"), "WRE");
+ std::string lsrmux = str_or_default(ff->params, ctx->id("LSRMUX"), "LSR");
+ if (wremux != lsrmux && !(wremux == "WRE" && lsrmux == "LSR"))
+ return false;
+ return true;
+ }
+
// Return true if two LUTs can be paired considering FF compatibility
bool can_pack_lutff(IdString lut0, IdString lut1)
{
@@ -496,6 +510,7 @@ class Ecp5Packer
std::vector<std::vector<CellInfo *>> packed_chains;
// Chain packing
+ std::vector<std::tuple<CellInfo *, CellInfo *, int>> ff_packing;
for (auto &chain : all_chains) {
int cell_count = 0;
std::vector<CellInfo *> tile_ffs;
@@ -512,8 +527,8 @@ class Ecp5Packer
NetInfo *f0net = slice->ports.at(ctx->id("F0")).net;
if (f0net != nullptr) {
ff0 = net_only_drives(ctx, f0net, is_ff, ctx->id("DI"), false);
- if (ff0 != nullptr && can_add_ff_to_file(tile_ffs, ff0)) {
- ff_to_slice(ctx, ff0, slice.get(), 0, true);
+ if (ff0 != nullptr && can_add_ff_to_tile(tile_ffs, ff0)) {
+ ff_packing.push_back(std::make_tuple(ff0, slice.get(), 0));
tile_ffs.push_back(ff0);
packed_cells.insert(ff0->name);
}
@@ -524,8 +539,8 @@ class Ecp5Packer
if (f1net != nullptr) {
ff1 = net_only_drives(ctx, f1net, is_ff, ctx->id("DI"), false);
if (ff1 != nullptr && (ff0 == nullptr || can_pack_ffs(ff0, ff1)) &&
- can_add_ff_to_file(tile_ffs, ff1)) {
- ff_to_slice(ctx, ff1, slice.get(), 1, true);
+ can_add_ff_to_tile(tile_ffs, ff1)) {
+ ff_packing.push_back(std::make_tuple(ff1, slice.get(), 1));
tile_ffs.push_back(ff1);
packed_cells.insert(ff1->name);
}
@@ -538,6 +553,9 @@ class Ecp5Packer
packed_chains.push_back(packed_chain);
}
+ for (auto ff : ff_packing)
+ ff_to_slice(ctx, std::get<0>(ff), std::get<1>(ff), std::get<2>(ff), true);
+
// Relative chain placement
for (auto &chain : packed_chains) {
chain.at(0)->constr_abs_z = true;
@@ -555,6 +573,98 @@ class Ecp5Packer
flush_cells();
}
+ // Pack distributed RAM
+ void pack_dram()
+ {
+ for (auto cell : sorted(ctx->cells)) {
+ CellInfo *ci = cell.second;
+ if (is_dpram(ctx, ci)) {
+
+ // Create RAMW slice
+ std::unique_ptr<CellInfo> ramw_slice =
+ create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "$RAMW_SLICE");
+ dram_to_ramw(ctx, ci, ramw_slice.get());
+
+ // Create actual RAM slices
+ std::unique_ptr<CellInfo> ram0_slice =
+ create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "$DPRAM0_SLICE");
+ dram_to_ram_slice(ctx, ci, ram0_slice.get(), ramw_slice.get(), 0);
+
+ std::unique_ptr<CellInfo> ram1_slice =
+ create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "$DPRAM1_SLICE");
+ dram_to_ram_slice(ctx, ci, ram1_slice.get(), ramw_slice.get(), 1);
+
+ // Disconnect ports of original cell after packing
+ disconnect_port(ctx, ci, id_WCK);
+ disconnect_port(ctx, ci, id_WRE);
+
+ disconnect_port(ctx, ci, ctx->id("RAD[0]"));
+ disconnect_port(ctx, ci, ctx->id("RAD[1]"));
+ disconnect_port(ctx, ci, ctx->id("RAD[2]"));
+ disconnect_port(ctx, ci, ctx->id("RAD[3]"));
+
+ // Attempt to pack FFs into RAM slices
+ std::vector<std::tuple<CellInfo *, CellInfo *, int>> ff_packing;
+ std::vector<CellInfo *> tile_ffs;
+ for (auto slice : {ram0_slice.get(), ram1_slice.get()}) {
+ CellInfo *ff0 = nullptr;
+ NetInfo *f0net = slice->ports.at(ctx->id("F0")).net;
+ if (f0net != nullptr) {
+ ff0 = net_only_drives(ctx, f0net, is_ff, ctx->id("DI"), false);
+ if (ff0 != nullptr && can_add_ff_to_tile(tile_ffs, ff0)) {
+ if (can_pack_ff_dram(slice, ff0)) {
+ ff_packing.push_back(std::make_tuple(ff0, slice, 0));
+ tile_ffs.push_back(ff0);
+ packed_cells.insert(ff0->name);
+ }
+ }
+ }
+
+ CellInfo *ff1 = nullptr;
+ NetInfo *f1net = slice->ports.at(ctx->id("F1")).net;
+ if (f1net != nullptr) {
+ ff1 = net_only_drives(ctx, f1net, is_ff, ctx->id("DI"), false);
+ if (ff1 != nullptr && (ff0 == nullptr || can_pack_ffs(ff0, ff1)) &&
+ can_add_ff_to_tile(tile_ffs, ff1)) {
+ if (can_pack_ff_dram(slice, ff1)) {
+ ff_packing.push_back(std::make_tuple(ff1, slice, 1));
+ tile_ffs.push_back(ff1);
+ packed_cells.insert(ff1->name);
+ }
+ }
+ }
+ }
+
+ for (auto ff : ff_packing)
+ ff_to_slice(ctx, std::get<0>(ff), std::get<1>(ff), std::get<2>(ff), true);
+
+ // Setup placement constraints
+ ram0_slice->constr_abs_z = true;
+ ram0_slice->constr_z = 0;
+
+ ram1_slice->constr_parent = ram0_slice.get();
+ ram1_slice->constr_abs_z = true;
+ ram1_slice->constr_x = 0;
+ ram1_slice->constr_y = 0;
+ ram1_slice->constr_z = 1;
+ ram0_slice->constr_children.push_back(ram1_slice.get());
+
+ ramw_slice->constr_parent = ram0_slice.get();
+ ramw_slice->constr_abs_z = true;
+ ramw_slice->constr_x = 0;
+ ramw_slice->constr_y = 0;
+ ramw_slice->constr_z = 2;
+ ram0_slice->constr_children.push_back(ramw_slice.get());
+
+ new_cells.push_back(std::move(ram0_slice));
+ new_cells.push_back(std::move(ram1_slice));
+ new_cells.push_back(std::move(ramw_slice));
+ packed_cells.insert(ci->name);
+ }
+ }
+ flush_cells();
+ }
+
// Pack LUTs that have been paired together
void pack_lut_pairs()
{
@@ -804,6 +914,7 @@ class Ecp5Packer
{
pack_io();
pack_constants();
+ pack_dram();
pack_carries();
find_lutff_pairs();
pack_lut5s();
@@ -811,6 +922,7 @@ class Ecp5Packer
pack_lut_pairs();
pack_remaining_luts();
pack_remaining_ffs();
+ ctx->check();
}
private: