From fdcfe8cd8188b6c4ea2450843bd22d822856a091 Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Mon, 30 Aug 2021 11:12:49 +0200 Subject: [PATCH 1/8] Adding support for MacroCells --- common/exclusive_state_groups.impl.h | 5 +- fpga_interchange/arch.h | 1 + fpga_interchange/arch_pack_clusters.cc | 341 ++++++++++++++++++++++++- fpga_interchange/chipdb.h | 41 ++- fpga_interchange/macros.cc | 3 + 5 files changed, 385 insertions(+), 6 deletions(-) diff --git a/common/exclusive_state_groups.impl.h b/common/exclusive_state_groups.impl.h index 53e4e83c..4a5b1228 100644 --- a/common/exclusive_state_groups.impl.h +++ b/common/exclusive_state_groups.impl.h @@ -74,10 +74,11 @@ void ExclusiveStateGroup::explain_requires(con log_info("Placing cell %s at bel %s does not violate %s.%s\n", cell.c_str(ctx), ctx->nameOfBel(bel), object.c_str(ctx), definition.prefix.c_str(ctx)); } else { + log_info("%d\n", state); log_info("Placing cell %s at bel %s does violates %s.%s, because current state is %s, constraint requires one " "of:\n", - cell.c_str(ctx), ctx->nameOfBel(bel), object.c_str(ctx), definition.prefix.c_str(ctx), - definition.states.at(state).c_str(ctx)); + cell.c_str(ctx), ctx->nameOfBel(bel), object.c_str(ctx), definition.prefix.c_str(ctx), "-1"); +// definition.states.at(state).c_str(ctx)); for (const auto required_state : state_range) { log_info(" - %s\n", definition.states.at(required_state).c_str(ctx)); diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index 7873a8ec..fab6c700 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -720,6 +720,7 @@ struct Arch : ArchAPI // Clusters void pack_cluster(); void prepare_cluster(const ClusterPOD *cluster, uint32_t index); + void prepare_macro_cluster(const ClusterPOD *cluster, uint32_t index); dict clusters; // User constraints diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc index f4e50233..3514d7c7 100644 --- a/fpga_interchange/arch_pack_clusters.cc +++ b/fpga_interchange/arch_pack_clusters.cc @@ -40,7 +40,8 @@ enum ClusterWireNodeState enum ExpansionDirection { CLUSTER_UPHILL_DIR = 0, - CLUSTER_DOWNHILL_DIR = 1 + CLUSTER_DOWNHILL_DIR = 1, + CLUSTER_BOTH_DIR = 2 }; struct ClusterWireNode @@ -370,6 +371,330 @@ static bool check_cluster_cells_compatibility(CellInfo *old_cell, CellInfo *new_ return true; } +bool reduce(uint32_t x, uint32_t y, const ClusterPOD *cluster, dict> &domain, Context *ctx){ + bool change = false; + std::vector remove_cell; + uint32_t counter = 0; + for (const auto &connection : cluster->connection_graph[x].connections){ + if(connection.target_idx == y) + break; + counter ++; + } + for (const auto &x_cell : domain[x]){ + if (ctx->verbose) + log_info("Testing cell %s\n", x_cell->name.c_str(ctx)); + bool found = false; + for (const auto &y_cell : domain[y]){ + if (ctx->verbose) + log_info(" - Y candidate: %s\n", y_cell->name.c_str(ctx)); + for (const auto edge : cluster->connection_graph[x].connections[counter].edges){ + if (!x_cell->ports.count(IdString(edge.cell_pin)) || !y_cell->ports.count(IdString(edge.other_cell_pin))) + break; + const auto x_net = x_cell->ports[IdString(edge.cell_pin)].net; + const auto y_net = y_cell->ports[IdString(edge.other_cell_pin)].net; + + if (x_net != y_net) + break; + bool x_driver = x_net->driver.cell == x_cell; + bool y_driver = y_net->driver.cell == y_cell; + if ((edge.dir != 0 || !y_driver) && (edge.dir != 1 || !x_driver) && (edge.dir != 2 || y_driver || x_driver)) + break; + found = true; + } + if (found){ + log_info(" - Works for %s\n", y_cell->name.c_str(ctx)); + break; + } + } + if (!found) + remove_cell.push_back(x_cell); + } + + for (const auto &cell : remove_cell){ + domain[x].erase(cell); + change = true; + } + + return change; +} + +void binary_constraint_check(const ClusterPOD *cluster, + std::queue> &workqueue, + dict> &idx_to_cells, Context *ctx){ + while (!workqueue.empty()){ + std::pair arc = workqueue.front(); + workqueue.pop(); + uint32_t x,y; + x = arc.first; y = arc.second; + if (ctx->verbose) + log_info("Checking pair %d:%d\n", x, y); + if (reduce(x, y, cluster, idx_to_cells, ctx)){ + for (const auto &connection : cluster->connection_graph[arc.first].connections) + if (connection.target_idx != y) + workqueue.push(std::pair(arc.first, connection.target_idx)); + } + } +} + +bool back_solver(const ClusterPOD *cluster, + dict> &idx_to_cells, Context *ctx){ + dict, hash_ptr_ops> possible_idx; + for (const auto &arc : idx_to_cells) + for (const auto &cell : arc.second) + possible_idx[cell].insert(arc.first); + std::queue prep; + for (const auto &arc : idx_to_cells){ + if (arc.second.size() == 0) + return false; + if (arc.second.size()>1){ + for (const auto &cell : arc.second){ + auto copy_idx_to_cells(idx_to_cells); + copy_idx_to_cells[arc.first].clear(); + for (uint32_t idx : possible_idx[cell]){ + copy_idx_to_cells[idx].erase(cell); + prep.push(idx); + } + copy_idx_to_cells[arc.first].insert(cell); + std::queue> workqueue; + while(!prep.empty()){ + uint32_t idx = prep.front(); prep.pop(); + for (const auto &connection : cluster->connection_graph[idx].connections) + if (arc.first != connection.target_idx) + workqueue.push(std::pair(arc.first, connection.target_idx)); + } + binary_constraint_check(cluster, workqueue, copy_idx_to_cells, ctx); + if (back_solver(cluster, copy_idx_to_cells, ctx)){ + idx_to_cells = std::move(copy_idx_to_cells); + return true; + } + } + } + } + return true; +} + +void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) +{ + Context *ctx = getCtx(); + IdString cluster_name(cluster->name); + + pool cluster_cell_types; + for (auto cell_type : cluster->root_cell_types) + cluster_cell_types.insert(IdString(cell_type)); + + // Find cluster roots for each macro only ones + dict roots; + for (auto &cell : cells){ + CellInfo *ci = cell.second.get(); + if(ci->macro_parent == IdString()) + continue; + if(ci->cluster != ClusterId()) + continue; + if (!cluster_cell_types.count(ci->type)) + continue; + if(roots.count(ci->macro_parent)) + continue; + // Simple check based on cell type counting + dict cells_in_macro, counter; + pool cell_types; + for (auto &cell_type : cluster->required_cells){ + cells_in_macro[IdString(cell_type.name)] = cell_type.count; + cell_types.insert(IdString(cell_type.name)); + } + + for (auto &node_cell : macro_to_cells[ci->macro_parent]){ + auto cell_type = node_cell->type; + if(!counter.count(cell_type)) + counter[cell_type] = 0; + counter[cell_type]++; + cell_types.insert(cell_type); + } + bool failed = false; + for(auto cell_type : cell_types){ + if(ctx->verbose && cells_in_macro.count(cell_type)) + log_info("Required: %s %d\n", cell_type.c_str(ctx), cells_in_macro[cell_type]); + if(ctx->verbose && cells_in_macro.count(cell_type)) + log_info("Have: %s %d\n", cell_type.c_str(ctx), counter[cell_type]); + if(!cells_in_macro.count(cell_type) || !counter.count(cell_type) || cells_in_macro[cell_type] != counter[cell_type]) + failed = true; + if(failed && ctx->verbose) + log_info("Cell count stage failed, for sure not this cluster\n"); + if(failed) + break; + } + if(failed){ + roots[ci->macro_parent] = nullptr; + continue; + } + + // Arc consistency + dict> idx_to_cells; + // First singular constraints, like used cell type and used_cell ports + for (auto &cell : macro_to_cells[ci->macro_parent]) + for (auto &node : cluster->connection_graph) + if (IdString(node.cell_type) == cell->type) + if (node.idx != 0 && cell->name != ci->name || + node.idx == 0 && cell->name == ci->name ){ + idx_to_cells[node.idx].insert(cell); + } + + for (auto &arc : idx_to_cells){ + std::vector remove_cell; + pool used_ports; + for (const auto &port : cluster->connection_graph[arc.first].used_ports) + used_ports.insert(IdString(port.name)); + for (const auto &cell : arc.second){ + uint32_t count = 0; + for (const auto &port : cell->ports){ + if (!used_ports.count(port.first)){ + remove_cell.push_back(cell); + break; + } + count++; + } + if (count != used_ports.size()){ + remove_cell.push_back(cell); + break; + } + } + for (const auto &cell : remove_cell){ + arc.second.erase(cell); + } + } + if (ctx->verbose){ + log_info("After mono constraints are applied\n"); + dict, hash_ptr_ops> possible_idx; + for (const auto &arc : idx_to_cells) + for (const auto &cell : arc.second) + possible_idx[cell].insert(arc.first); + + for (const auto arc : possible_idx){ + log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); + for (const auto idx : arc.second) + log_info(" - %d\n", idx); + } + } + // Solve for binary constraints + std::queue> workqueue; + for (const auto &arc : idx_to_cells) + for (const auto &connection : cluster->connection_graph[arc.first].connections) + workqueue.push(std::pair(arc.first, connection.target_idx)); + + binary_constraint_check(cluster, workqueue, idx_to_cells, ctx); + for (const auto &arc : idx_to_cells){ + if (arc.second.size() == 0){ + if (ctx->verbose) + log_info("AC-3 failed\n"); + failed = true; + break; + } + } + if (failed) + continue; + + if (ctx->verbose){ + log_info("After AC-3\n"); + dict, hash_ptr_ops> possible_idx; + for (const auto &arc : idx_to_cells) + for (const auto &cell : arc.second) + possible_idx[cell].insert(arc.first); + + for (const auto arc : possible_idx){ + log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); + for (const auto idx : arc.second) + log_info(" - %d\n", idx); + } + } + + bool change = false; + std::queue> removequeue; + // Keep assigning cells to indices that only map to single cell + // Remove this cell from other mappings and recheck binary constraints + // Fail if there is no cell for idx or cell has no idx assign + do{ + change = false; + dict, hash_ptr_ops> possible_idx; + pool changed_idxs; + for (const auto &arc : idx_to_cells){ + if (arc.second.size() == 0){ + failed = true; + break; + } + for (const auto &cell : arc.second) + possible_idx[cell].insert(arc.first); + } + if(failed) + break; + for (auto &cell : macro_to_cells[ci->macro_parent]) + if (possible_idx[cell].size() == 0){ + failed = true; + break; + } + if(failed) + break; + for (const auto &arc : idx_to_cells){ + if (arc.second.size() == 1) + for (const auto &idx : possible_idx[*arc.second.begin()]) + if (idx != arc.first) + removequeue.push(std::pair(idx, *arc.second.begin())); + } + while(!removequeue.empty()){ + auto t = removequeue.front(); removequeue.pop(); + uint32_t idx = t.first; + CellInfo *cell = t.second; + idx_to_cells[idx].erase(cell); + change = true; + changed_idxs.insert(idx); + } + for (const uint32_t &idx : changed_idxs) + for (const auto &connection : cluster->connection_graph[idx].connections) + workqueue.push(std::pair(idx, connection.target_idx)); + + binary_constraint_check(cluster, workqueue, idx_to_cells, ctx); + }while(change); + if(failed){ + if(ctx->verbose) + log_info("Single cell mapping failed\n"); + continue; + } + if (ctx->verbose){ + log_info("After mapping indices with single cell\n"); + dict, hash_ptr_ops> possible_idx; + for (const auto &arc : idx_to_cells) + for (const auto &cell : arc.second) + possible_idx[cell].insert(arc.first); + + for (const auto arc : possible_idx){ + log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); + for (const auto idx : arc.second) + log_info(" - %d\n", idx); + } + } + // At this point all indices that cloud only be mapped to single cell are mapped + // Next step is to run solver with backtracing to solve for other idx<->cell mappings + if (ctx->verbose) + log_info("Back solver\n"); + if(!back_solver(cluster, idx_to_cells, ctx)){ + if(ctx->verbose) + log_info("Back solver failed\n"); + continue; + } + if (ctx->verbose){ + log_info("Final mapping after back solver\n"); + dict, hash_ptr_ops> possible_idx; + for (const auto &arc : idx_to_cells) + for (const auto &cell : arc.second) + possible_idx[cell].insert(arc.first); + + for (const auto arc : possible_idx){ + log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); + for (const auto idx : arc.second) + log_info(" - %d\n", idx); + } + } + } +} + void Arch::prepare_cluster(const ClusterPOD *cluster, uint32_t index) { Context *ctx = getCtx(); @@ -383,6 +708,8 @@ void Arch::prepare_cluster(const ClusterPOD *cluster, uint32_t index) std::vector roots; for (auto &cell : cells) { CellInfo *ci = cell.second.get(); + if (ci->macro_parent != IdString()) + continue; if (ci->cluster != ClusterId()) continue; @@ -564,9 +891,17 @@ void Arch::pack_cluster() dump_clusters(chip_info, ctx); for (uint32_t i = 0; i < chip_info->clusters.size(); ++i) { - const auto &cluster = chip_info->clusters[i]; + if (!chip_info->clusters[i].from_macro){ + const auto &cluster = chip_info->clusters[i]; - prepare_cluster(&cluster, i); + prepare_cluster(&cluster, i); + } else { + const auto &cluster = chip_info->clusters[i]; + if(ctx->verbose) + log_info("%s\n", IdString(cluster.name).c_str(ctx)); + + prepare_macro_cluster(&cluster, i); + } } } diff --git a/fpga_interchange/chipdb.h b/fpga_interchange/chipdb.h index 85dc7f25..1086976a 100644 --- a/fpga_interchange/chipdb.h +++ b/fpga_interchange/chipdb.h @@ -34,7 +34,12 @@ NEXTPNR_NAMESPACE_BEGIN * kExpectedChipInfoVersion */ -static constexpr int32_t kExpectedChipInfoVersion = 14; +static constexpr int32_t kExpectedChipInfoVersion = 15; + +NPNR_PACKED_STRUCT(struct BelConnectedPinsPOD { + uint32_t pin1; + uint32_t pin2; +}); // Flattened site indexing. // @@ -80,6 +85,8 @@ NPNR_PACKED_STRUCT(struct BelInfoPOD { int8_t inverting_pin; int16_t padding; + + RelSlice connected_pins; }); enum BELCategory @@ -416,13 +423,45 @@ NPNR_PACKED_STRUCT(struct ChainablePortPOD { int16_t avg_y_offset; }); +NPNR_PACKED_STRUCT(struct ClusterRequiredCellPOD{ + uint32_t name; + uint32_t count; +}); + +NPNR_PACKED_STRUCT(struct ClusterUsedPortPOD{ + uint32_t name; +}); + +NPNR_PACKED_STRUCT(struct ClusterEdgePOD{ + uint32_t dir; + uint32_t cell_pin; + uint32_t other_cell_pin; + uint32_t other_cell_type; +}); + +NPNR_PACKED_STRUCT(struct ClusterConnectionsPOD{ + uint32_t target_idx; + RelSlice edges; +}); + +NPNR_PACKED_STRUCT(struct ClusterConnectionGraphPOD{ + uint32_t idx; + uint32_t cell_type; + RelSlice connections; + RelSlice used_ports; +}); + + NPNR_PACKED_STRUCT(struct ClusterPOD { uint32_t name; RelSlice root_cell_types; RelSlice chainable_ports; RelSlice cluster_cells_map; + RelSlice required_cells; + RelSlice connection_graph; uint32_t out_of_site_clusters; uint32_t disallow_other_cells; + uint32_t from_macro; }); NPNR_PACKED_STRUCT(struct ChipInfoPOD { diff --git a/fpga_interchange/macros.cc b/fpga_interchange/macros.cc index 762615c1..4011f683 100644 --- a/fpga_interchange/macros.cc +++ b/fpga_interchange/macros.cc @@ -50,6 +50,7 @@ static IdString derived_name(Context *ctx, IdString base_name, IdString suffix) void Arch::expand_macros() { + log_info("Expand macros\n"); // Make up a list of cells, so we don't have modify-while-iterating issues Context *ctx = getCtx(); std::vector cells; @@ -78,6 +79,7 @@ void Arch::expand_macros() // Get the ultimate root of this macro expansion IdString parent = (cell->macro_parent == IdString()) ? cell->name : cell->macro_parent; + log_info("%s %s\n", cell->name.c_str(ctx), parent.c_str(ctx)); // Create child instances for (const auto &inst : macro->cell_insts) { CellInfo *inst_cell = @@ -86,6 +88,7 @@ void Arch::expand_macros() inst_cell->params[IdString(param.key)] = IdString(param.value).str(ctx); } inst_cell->macro_parent = parent; + log_info(" %s %s\n", inst_cell->name.c_str(ctx), inst_cell->type.c_str(ctx)); next_cells.push_back(inst_cell); } // Create and connect nets From 3cd459912a23b03640e3e1621dd454874ed11381 Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Tue, 14 Sep 2021 12:51:15 +0200 Subject: [PATCH 2/8] Adding MacroCell placement Signed-off-by: Maciej Dudek --- common/exclusive_state_groups.impl.h | 7 +- fpga_interchange/arch.h | 7 +- fpga_interchange/arch_pack_clusters.cc | 356 ++++++++++++++++++++++++- fpga_interchange/chipdb.h | 4 +- 4 files changed, 353 insertions(+), 21 deletions(-) diff --git a/common/exclusive_state_groups.impl.h b/common/exclusive_state_groups.impl.h index 4a5b1228..f3ddb5fd 100644 --- a/common/exclusive_state_groups.impl.h +++ b/common/exclusive_state_groups.impl.h @@ -74,11 +74,10 @@ void ExclusiveStateGroup::explain_requires(con log_info("Placing cell %s at bel %s does not violate %s.%s\n", cell.c_str(ctx), ctx->nameOfBel(bel), object.c_str(ctx), definition.prefix.c_str(ctx)); } else { - log_info("%d\n", state); - log_info("Placing cell %s at bel %s does violates %s.%s, because current state is %s, constraint requires one " + log_info("Placing cell %s at bel %s does violate %s.%s, because current state is %s, constraint requires one " "of:\n", - cell.c_str(ctx), ctx->nameOfBel(bel), object.c_str(ctx), definition.prefix.c_str(ctx), "-1"); -// definition.states.at(state).c_str(ctx)); + cell.c_str(ctx), ctx->nameOfBel(bel), object.c_str(ctx), definition.prefix.c_str(ctx), + state != -1 ? definition.states.at(state).c_str(ctx) : "unset"); for (const auto required_state : state_range) { log_info(" - %s\n", definition.states.at(required_state).c_str(ctx)); diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index fab6c700..756ac4d9 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -858,7 +858,8 @@ struct Arch : ArchAPI return true; } const TileStatus &tile_status = iter->second; - const CellInfo *cell = tile_status.boundcells[bel.index]; + CellInfo *cell = tile_status.boundcells[bel.index]; + auto &bel_data = bel_info(chip_info, bel); auto &bel_data = bel_info(chip_info, bel); auto &site_status = get_site_status(tile_status, bel_data); @@ -900,6 +901,10 @@ struct Arch : ArchAPI ArcBounds getClusterBounds(ClusterId cluster) const override; Loc getClusterOffset(const CellInfo *cell) const override; bool isClusterStrict(const CellInfo *cell) const override; + bool normal_cluster_placement(const Context *, const Cluster &, const ClusterPOD &,CellInfo*, + BelId, std::vector> &) const; + bool macro_cluster_placement(const Context *, const Cluster &, const ClusterPOD &,CellInfo*, + BelId, std::vector> &) const; bool getClusterPlacement(ClusterId cluster, BelId root_bel, std::vector> &placement) const override; diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc index 3514d7c7..bbf3a6b8 100644 --- a/fpga_interchange/arch_pack_clusters.cc +++ b/fpga_interchange/arch_pack_clusters.cc @@ -49,6 +49,7 @@ struct ClusterWireNode WireId wire; ClusterWireNodeState state; int depth; + bool only_down; }; static void handle_expansion_node(const Context *ctx, WireId prev_wire, PipId pip, ClusterWireNode curr_node, @@ -188,18 +189,10 @@ CellInfo *Arch::getClusterRootCell(ClusterId cluster) const return clusters.at(cluster).root; } -bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel, - std::vector> &placement) const +bool Arch::normal_cluster_placement( + const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, + CellInfo *root_cell, BelId root_bel, std::vector> &placement) const { - const Context *ctx = getCtx(); - const Cluster &packed_cluster = clusters.at(cluster); - - auto &cluster_data = cluster_info(chip_info, packed_cluster.index); - - CellInfo *root_cell = getClusterRootCell(cluster); - if (!ctx->isValidBelForCellType(root_cell->type, root_bel)) - return false; - BelId next_bel; // Place cluster @@ -283,6 +276,312 @@ bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel, return true; } +static void handle_macro_expansion_node( + const Context *ctx, WireId wire, PipId pip, ClusterWireNode curr_node, + std::vector &nodes_to_expand, BelPin root_pin, + dict, dict> &bels, + ExpansionDirection direction, pool &visited, CellInfo *cell) +{ + if (curr_node.state == IN_SINK_SITE || curr_node.state == ONLY_IN_SOURCE_SITE) { + for (BelPin bel_pin : ctx->getWireBelPins(wire)) { + BelId bel = bel_pin.bel; + log_info("\t\t\tconsidering:\n"); + for (auto s : ctx->getBelName(bel)){ + log_info("\t\t\t\t - %s\n", s.c_str(ctx)); + } + log_info("\t\t\t\t pin: %s\n",bel_pin.pin.c_str(ctx)); + if (bel == root_pin.bel) + continue; + auto const &bel_data = bel_info(ctx->chip_info, bel); + + if (bels.count(std::pair(root_pin.bel, bel))) + continue; + + if (bel_data.category != BEL_CATEGORY_LOGIC){ + continue; + } + + if (bel_data.synthetic) + continue; + + if (!ctx->isValidBelForCellType(cell->type, bel)) + continue; + + log_info("\t\t\tfound: %s\n", bel_pin.pin.c_str(ctx)); + bels[std::pair(root_pin.bel, bel_pin.bel)].insert( + std::pair(root_pin.pin, bel_pin.pin)); + } + } + + WireId next_wire; + + if (direction == CLUSTER_UPHILL_DIR) + next_wire = ctx->getPipSrcWire(pip); + else + next_wire = ctx->getPipDstWire(pip); + + log_info("\t\t\tPIP:\n"); + for (auto s : ctx->getPipName(pip)){ + log_info("\t\t\t\t - %s\n", s.c_str(ctx)); + } + log_info("\t\t\t next_wire:\n"); + for (auto s : ctx->getWireName(next_wire)){ + log_info("\t\t\t\t - %s\n", s.c_str(ctx)); + } + + if (next_wire == WireId() || visited.count(next_wire)) + return; + + ClusterWireNode next_node; + next_node.wire = next_wire; + next_node.depth = curr_node.depth; + next_node.only_down = false; + if (direction == CLUSTER_DOWNHILL_DIR) + next_node.only_down = true; + + if (next_node.depth >= 2) + return; + + auto const &wire_data = ctx->wire_info(next_wire); + + bool expand_node = true; + if (ctx->is_site_port(pip)) { + switch (curr_node.state) { + case ONLY_IN_SOURCE_SITE: + expand_node = false; + break; + case IN_SOURCE_SITE: + NPNR_ASSERT(wire_data.site == -1); + next_node.state = IN_ROUTING; + break; + case IN_ROUTING: + NPNR_ASSERT(wire_data.site != -1); + next_node.state = IN_SINK_SITE; + break; + case IN_SINK_SITE: + expand_node = false; + break; + default: + // Unreachable!!! + NPNR_ASSERT(false); + } + } else { + if (next_node.state == IN_ROUTING) + next_node.depth++; + next_node.state = curr_node.state; + } + + if (curr_node.state != IN_ROUTING){ + const auto &pip_data = pip_info(ctx->chip_info, pip); + BelId bel; + bel.tile = pip.tile; + bel.index = pip_data.bel; + log_info("Pip bel stat:\n"); + for (auto s : ctx->getBelName(bel)){ + log_info("\t - %s\n", s.c_str(ctx)); + } + const auto &bel_data = bel_info(ctx->chip_info, bel); + if(bel_data.category == BEL_CATEGORY_LOGIC) + expand_node = false; + } + + if (expand_node) + nodes_to_expand.push_back(next_node); + else + return; + + return; +} + +static void + find_macro_cluster_bels(const Context *ctx, WireId wire, + dict, dict> &possible_places, + ExpansionDirection direction, BelPin root_pin, CellInfo *cell, bool out_of_site_expansion = false) +{ + std::vector nodes_to_expand; + pool visited; + + const auto &wire_data = ctx->wire_info(wire); + NPNR_ASSERT(wire_data.site != -1); + + ClusterWireNode wire_node; + wire_node.wire = wire; + wire_node.state = IN_SOURCE_SITE; + if (!out_of_site_expansion) + wire_node.state = ONLY_IN_SOURCE_SITE; + wire_node.depth = 0; + wire_node.only_down = false; + + nodes_to_expand.push_back(wire_node); + + while (!nodes_to_expand.empty()) { + ClusterWireNode node_to_expand = nodes_to_expand.back(); + WireId wire = node_to_expand.wire; + nodes_to_expand.pop_back(); + visited.insert(wire); + log_info("\t\t visited:\n"); + for (auto s : ctx->getWireName(wire)){ + log_info("\t\t\t - %s\n", s.c_str(ctx)); + } + + if (direction == CLUSTER_DOWNHILL_DIR) { + for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) { + if (ctx->is_pip_synthetic(pip)) + continue; + + handle_macro_expansion_node( + ctx, wire, pip, node_to_expand, nodes_to_expand, + root_pin, possible_places, direction, visited, cell); + } + } else if (direction == CLUSTER_UPHILL_DIR){ + for (PipId pip : ctx->getPipsUphill(node_to_expand.wire)) { + if (ctx->is_pip_synthetic(pip)) + continue; + + handle_macro_expansion_node( + ctx, wire, pip, node_to_expand, nodes_to_expand, + root_pin, possible_places, direction, visited, cell); + } + } else { + NPNR_ASSERT(direction == CLUSTER_BOTH_DIR); + for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) { + if (ctx->is_pip_synthetic(pip)) + continue; + + handle_macro_expansion_node( + ctx, wire, pip, node_to_expand, nodes_to_expand, + root_pin, possible_places, CLUSTER_DOWNHILL_DIR, visited, cell); + } + if (!node_to_expand.only_down) + for (PipId pip : ctx->getPipsUphill(node_to_expand.wire)) { + if (ctx->is_pip_synthetic(pip)) + continue; + + handle_macro_expansion_node( + ctx, wire, pip, node_to_expand, nodes_to_expand, + root_pin, possible_places, CLUSTER_UPHILL_DIR, visited, cell); + } + } + } + return; +} + +bool Arch::macro_cluster_placement( + const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, + CellInfo *root_cell, BelId root_bel, std::vector> &placement) const +{ + const auto &bel_data = bel_info(chip_info, root_bel); + + log_info("Bel_name: %s type: %s\n", IdString(bel_data.name).c_str(ctx), IdString(bel_data.type).c_str(ctx)); + log_info("Cell_name: %s type: %s\n", root_cell->name.c_str(ctx), root_cell->type.c_str(ctx)); + + // Build a cell to bell mapping required to find BELs connected to the cluster ports. + dict> cell_bel_pins; + dict bel_cell_pins; + + int32_t mapping = bel_data.pin_map[get_cell_type_index(root_cell->type)]; + NPNR_ASSERT(mapping >= 0); + + const CellBelMapPOD &cell_pin_map = chip_info->cell_map->cell_bel_map[mapping]; + for (const auto &pin_map : cell_pin_map.common_pins) { + IdString cell_pin(pin_map.cell_pin); + IdString bel_pin(pin_map.bel_pin); + log_info("%s %s\n", cell_pin.c_str(ctx), bel_pin.c_str(ctx)); + + cell_bel_pins[cell_pin].push_back(bel_pin); + bel_cell_pins[bel_pin] = cell_pin; + } + + for (const auto &pair : bel_data.connected_pins){ + IdString p1(pair.pin1), p2(pair.pin2); + IdString i1(bel_cell_pins[p1]), i2(bel_cell_pins[p2]); + log_info("%s %s\n", i1.c_str(ctx), i2.c_str(ctx)); + if (root_cell->ports[i1].net != root_cell->ports[i2].net){ + log_info("%s != %s\n", root_cell->ports[i1].net->name.c_str(ctx), + root_cell->ports[i2].net->name.c_str(ctx)); + return false; + } + } + + dict> idx_bel_map; + idx_bel_map[0].insert(root_bel); + std::queue queue; + queue.push(0); + + while (!queue.empty()){ + uint32_t idx = queue.front(); queue.pop(); + std::vector remove_bels; + dict, dict> possible_places; + for (const auto &root_bel : idx_bel_map[idx]){ + for (const auto &connection : cluster_data.connection_graph[idx].connections){ + log_info("Target idx:%d\n", connection.target_idx); + CellInfo *cell_to_place = packed_cluster.cluster_nodes[connection.target_idx]; + pool needed_pins; + for (const auto &edge : connection.edges){ + log_info("\t - %s %s\n", IdString(edge.cell_pin).c_str(ctx), IdString(edge.other_cell_pin).c_str(ctx)); + for (auto &root_pin : cell_bel_pins.at(IdString(edge.cell_pin))) { + WireId bel_pin_wire = ctx->getBelPinWire(root_bel, root_pin); + BelPin root; + root.bel = root_bel; + root.pin = root_pin; + needed_pins.insert(root_pin); + for (auto s : ctx->getWireName(bel_pin_wire)){ + log_info("\t\t - %s\n", s.c_str(ctx)); + } + find_macro_cluster_bels( + ctx, bel_pin_wire, possible_places, + ExpansionDirection(edge.dir), root, + cell_to_place); + } + } + + for (const auto &place : possible_places){ + BelId check_bel = place.first.second; + const auto &bel_data2 = bel_info(chip_info, check_bel); + bool failed = false; + for (const auto &pin : needed_pins){ + log_info("Pin: %s\n", pin.c_str(ctx)); + if (!place.second.count(pin)){ + failed = true; + break; + } + } + if (failed) + continue; + log_info("Bel_name: %s type: %s\n", IdString(bel_data2.name).c_str(ctx), + IdString(bel_data2.type).c_str(ctx)); + log_info("Cell_name: %s type: %s\n", cell_to_place->name.c_str(ctx), cell_to_place->type.c_str(ctx)); + } + } + } + } + + exit(0); + return true; +} + +bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel, + std::vector> &placement) const +{ + const Context *ctx = getCtx(); + const Cluster &packed_cluster = clusters.at(cluster); + + auto &cluster_data = cluster_info(chip_info, packed_cluster.index); + + CellInfo *root_cell = getClusterRootCell(cluster); + if (!ctx->isValidBelForCellType(root_cell->type, root_bel)) + return false; + if (!cluster_data.from_macro) + return normal_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, + root_bel, placement); + else{ + log_info("Macro cluster\n"); + bool temp = macro_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, + root_bel, placement); + return temp; + } +} + ArcBounds Arch::getClusterBounds(ClusterId cluster) const { // TODO: Implement this @@ -692,6 +991,19 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) log_info(" - %d\n", idx); } } + Cluster cluster_info; + cluster_info.root = ci; + cluster_info.index = index; + cluster_info.cluster_nodes.resize(idx_to_cells.size()); + ci->cluster.set(ctx, ci->name.str(ctx)); + for (auto &arc : idx_to_cells){ + CellInfo * sub_cell = arc.second.pop(); + if (ctx->verbose) + log_info("%d %s - %s\n", arc.first, sub_cell->name.c_str(ctx), sub_cell->type.c_str(ctx)); + sub_cell->cluster = ci->cluster; + cluster_info.cluster_nodes[arc.first] = sub_cell; + } + clusters.emplace(ci->cluster, cluster_info); } } @@ -895,13 +1207,29 @@ void Arch::pack_cluster() const auto &cluster = chip_info->clusters[i]; prepare_cluster(&cluster, i); - } else { + } else if(!chip_info->clusters[i].out_of_site_clusters) { const auto &cluster = chip_info->clusters[i]; - if(ctx->verbose) - log_info("%s\n", IdString(cluster.name).c_str(ctx)); + if(ctx->verbose){ + log_info("%s\n", IdString(cluster.name).c_str(ctx));\ + } prepare_macro_cluster(&cluster, i); } + else { + // No good way to handle out of site clusters, as fulfiling routing requirements + // can be done by router. Right now cluster connection map creates connections from each + // cell to each cell, and in placement this is used as well. + // We could assume that in macros, where there are no root cells and + // we have multiple unconnected graphs, source cells must be in the same site. + // Why create a macro if these cells have nothing in common. + // For now python-fpga-interchange does not support this assumption + // and neither does placement code. + // Cluster preparing and packing works for both, but as we cannot place + // out of site clusters, we don't create them, letting generic P&R do it. + const auto &cluster = chip_info->clusters[i]; + if(ctx->verbose) + log_info("Out of site cluster from macro: %s\n", IdString(cluster.name).c_str(ctx)); + } } } diff --git a/fpga_interchange/chipdb.h b/fpga_interchange/chipdb.h index 1086976a..0f57bdc0 100644 --- a/fpga_interchange/chipdb.h +++ b/fpga_interchange/chipdb.h @@ -37,8 +37,8 @@ NEXTPNR_NAMESPACE_BEGIN static constexpr int32_t kExpectedChipInfoVersion = 15; NPNR_PACKED_STRUCT(struct BelConnectedPinsPOD { - uint32_t pin1; - uint32_t pin2; + int32_t pin1; + int32_t pin2; }); // Flattened site indexing. From 94acf7a7976fb1cddd5a8c7228694aa308b6532c Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Mon, 20 Sep 2021 13:51:08 +0200 Subject: [PATCH 3/8] Change Cluster placement algorithm Use physical placement from device DB It should reduce runtime Signed-off-by: Maciej Dudek --- fpga_interchange/arch.h | 2 - fpga_interchange/arch_pack_clusters.cc | 243 +++++++++++++------------ fpga_interchange/chipdb.h | 9 + 3 files changed, 132 insertions(+), 122 deletions(-) diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index 756ac4d9..9ce1eb4d 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -859,8 +859,6 @@ struct Arch : ArchAPI } const TileStatus &tile_status = iter->second; CellInfo *cell = tile_status.boundcells[bel.index]; - auto &bel_data = bel_info(chip_info, bel); - auto &bel_data = bel_info(chip_info, bel); auto &site_status = get_site_status(tile_status, bel_data); diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc index bbf3a6b8..85527041 100644 --- a/fpga_interchange/arch_pack_clusters.cc +++ b/fpga_interchange/arch_pack_clusters.cc @@ -276,26 +276,25 @@ bool Arch::normal_cluster_placement( return true; } +/* static void handle_macro_expansion_node( const Context *ctx, WireId wire, PipId pip, ClusterWireNode curr_node, std::vector &nodes_to_expand, BelPin root_pin, - dict, dict> &bels, + dict, dict>> &bels, ExpansionDirection direction, pool &visited, CellInfo *cell) { if (curr_node.state == IN_SINK_SITE || curr_node.state == ONLY_IN_SOURCE_SITE) { for (BelPin bel_pin : ctx->getWireBelPins(wire)) { BelId bel = bel_pin.bel; - log_info("\t\t\tconsidering:\n"); - for (auto s : ctx->getBelName(bel)){ - log_info("\t\t\t\t - %s\n", s.c_str(ctx)); - } - log_info("\t\t\t\t pin: %s\n",bel_pin.pin.c_str(ctx)); if (bel == root_pin.bel) continue; auto const &bel_data = bel_info(ctx->chip_info, bel); - if (bels.count(std::pair(root_pin.bel, bel))) + if (bels.count(std::pair(root_pin.bel, bel)) &&\ + bels[std::pair(root_pin.bel, bel)].count(root_pin.pin) &&\ + bels[std::pair(root_pin.bel, bel)][root_pin.pin].count(bel_pin.pin)){ continue; + } if (bel_data.category != BEL_CATEGORY_LOGIC){ continue; @@ -307,9 +306,8 @@ static void handle_macro_expansion_node( if (!ctx->isValidBelForCellType(cell->type, bel)) continue; - log_info("\t\t\tfound: %s\n", bel_pin.pin.c_str(ctx)); - bels[std::pair(root_pin.bel, bel_pin.bel)].insert( - std::pair(root_pin.pin, bel_pin.pin)); + bels[std::pair(root_pin.bel, bel_pin.bel)][root_pin.pin].\ + insert(bel_pin.pin); } } @@ -320,15 +318,6 @@ static void handle_macro_expansion_node( else next_wire = ctx->getPipDstWire(pip); - log_info("\t\t\tPIP:\n"); - for (auto s : ctx->getPipName(pip)){ - log_info("\t\t\t\t - %s\n", s.c_str(ctx)); - } - log_info("\t\t\t next_wire:\n"); - for (auto s : ctx->getWireName(next_wire)){ - log_info("\t\t\t\t - %s\n", s.c_str(ctx)); - } - if (next_wire == WireId() || visited.count(next_wire)) return; @@ -376,10 +365,6 @@ static void handle_macro_expansion_node( BelId bel; bel.tile = pip.tile; bel.index = pip_data.bel; - log_info("Pip bel stat:\n"); - for (auto s : ctx->getBelName(bel)){ - log_info("\t - %s\n", s.c_str(ctx)); - } const auto &bel_data = bel_info(ctx->chip_info, bel); if(bel_data.category == BEL_CATEGORY_LOGIC) expand_node = false; @@ -395,7 +380,7 @@ static void handle_macro_expansion_node( static void find_macro_cluster_bels(const Context *ctx, WireId wire, - dict, dict> &possible_places, + dict, dict>> &possible_places, ExpansionDirection direction, BelPin root_pin, CellInfo *cell, bool out_of_site_expansion = false) { std::vector nodes_to_expand; @@ -419,11 +404,6 @@ static void WireId wire = node_to_expand.wire; nodes_to_expand.pop_back(); visited.insert(wire); - log_info("\t\t visited:\n"); - for (auto s : ctx->getWireName(wire)){ - log_info("\t\t\t - %s\n", s.c_str(ctx)); - } - if (direction == CLUSTER_DOWNHILL_DIR) { for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) { if (ctx->is_pip_synthetic(pip)) @@ -465,98 +445,136 @@ static void } return; } +*/ bool Arch::macro_cluster_placement( const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, CellInfo *root_cell, BelId root_bel, std::vector> &placement) const { + // Check root_bel site_type + const auto &cluster = cluster_info(chip_info, packed_cluster.index); + bool found = false; + uint32_t idx = 0; + const auto &site_inst = ctx->get_site_inst(root_bel); + IdString site_type(site_inst.site_type); + + if(ctx->debug) + log_info("%s\n", ctx->get_site_name(root_bel)); + + if (ctx->debug){ + log_info("Root_bel site_type: %s\n", site_type.c_str(ctx)); + log_info("Allowed site_types:\n"); + } + for(const auto &site : cluster.physical_placements){ + IdString name(site.site_type); + if(ctx->debug) + log_info("\t%s\n", name.c_str(ctx)); + + if (name == site_type){ + found = true; + break; + } + idx++; + } + if (!found) + return false; + + // Check if root_bel name + uint32_t placement_idx = 0; + found = false; const auto &bel_data = bel_info(chip_info, root_bel); + IdString root_bel_name(bel_data.name); + if(ctx->debug){ + log_info("Root_bel name: %s\n", root_bel_name.c_str(ctx)); + log_info("Allowed root_bels:\n"); + } + for(const auto &place : cluster.physical_placements[idx].places){ + // root_bel has idx 0 + IdString name(place.bels[0]); + if(ctx->debug) + log_info("\t%s\n",name.c_str(ctx)); - log_info("Bel_name: %s type: %s\n", IdString(bel_data.name).c_str(ctx), IdString(bel_data.type).c_str(ctx)); - log_info("Cell_name: %s type: %s\n", root_cell->name.c_str(ctx), root_cell->type.c_str(ctx)); + if(name == root_bel_name){ + found = true; + break; + } + placement_idx++; + } + if (!found) + return false; - // Build a cell to bell mapping required to find BELs connected to the cluster ports. - dict> cell_bel_pins; - dict bel_cell_pins; - - int32_t mapping = bel_data.pin_map[get_cell_type_index(root_cell->type)]; - NPNR_ASSERT(mapping >= 0); - - const CellBelMapPOD &cell_pin_map = chip_info->cell_map->cell_bel_map[mapping]; - for (const auto &pin_map : cell_pin_map.common_pins) { - IdString cell_pin(pin_map.cell_pin); - IdString bel_pin(pin_map.bel_pin); - log_info("%s %s\n", cell_pin.c_str(ctx), bel_pin.c_str(ctx)); - - cell_bel_pins[cell_pin].push_back(bel_pin); - bel_cell_pins[bel_pin] = cell_pin; + // Check if all better placements are used + auto root_bel_full_name = ctx->getBelName(root_bel); + for(uint32_t i = 0; i < placement_idx; i++){ + IdStringList cpy(root_bel_full_name.size()); + for(uint32_t j = 0; j < root_bel_full_name.size(); j++) + cpy.ids[j] = root_bel_full_name[j]; + cpy.ids[1] = IdString(cluster.physical_placements[idx].places[i].bels[0]); + BelId t = ctx->getBelByName(cpy); + if(ctx->debug){ + for (auto str : cpy) + log_info("%s\n", str.c_str(ctx)); + } + if (ctx->getBoundBelCell(t) == nullptr) + return false; } - for (const auto &pair : bel_data.connected_pins){ - IdString p1(pair.pin1), p2(pair.pin2); - IdString i1(bel_cell_pins[p1]), i2(bel_cell_pins[p2]); - log_info("%s %s\n", i1.c_str(ctx), i2.c_str(ctx)); - if (root_cell->ports[i1].net != root_cell->ports[i2].net){ - log_info("%s != %s\n", root_cell->ports[i1].net->name.c_str(ctx), - root_cell->ports[i2].net->name.c_str(ctx)); + // Check if bels are avaiable + dict idx_bel_map; + uint32_t t_idx = 0; + for(const auto &bel : cluster.physical_placements[idx].places[placement_idx].bels){ + IdStringList cpy(root_bel_full_name.size()); + for(uint32_t j = 0; j < root_bel_full_name.size(); j++) + cpy.ids[j] = root_bel_full_name[j]; + cpy.ids[1] = IdString(bel); + BelId t = ctx->getBelByName(cpy); + if(ctx->debug){ + for (auto str : cpy) + log_info("%s\n", str.c_str(ctx)); + } + if (ctx->getBoundBelCell(t) != nullptr && + ctx->getBoundBelCell(t) != packed_cluster.cluster_nodes[t_idx]){ + if(ctx->debug) + log_info("Failed\n"); return false; } + idx_bel_map[t_idx] = t; + t_idx++; } - dict> idx_bel_map; - idx_bel_map[0].insert(root_bel); - std::queue queue; - queue.push(0); +/* + for(auto idx_bel : idx_bel_map){ + const auto &bel_data = bel_info(chip_info, idx_bel.second); + dict> cell_bel_pins; + dict bel_cell_pins; - while (!queue.empty()){ - uint32_t idx = queue.front(); queue.pop(); - std::vector remove_bels; - dict, dict> possible_places; - for (const auto &root_bel : idx_bel_map[idx]){ - for (const auto &connection : cluster_data.connection_graph[idx].connections){ - log_info("Target idx:%d\n", connection.target_idx); - CellInfo *cell_to_place = packed_cluster.cluster_nodes[connection.target_idx]; - pool needed_pins; - for (const auto &edge : connection.edges){ - log_info("\t - %s %s\n", IdString(edge.cell_pin).c_str(ctx), IdString(edge.other_cell_pin).c_str(ctx)); - for (auto &root_pin : cell_bel_pins.at(IdString(edge.cell_pin))) { - WireId bel_pin_wire = ctx->getBelPinWire(root_bel, root_pin); - BelPin root; - root.bel = root_bel; - root.pin = root_pin; - needed_pins.insert(root_pin); - for (auto s : ctx->getWireName(bel_pin_wire)){ - log_info("\t\t - %s\n", s.c_str(ctx)); - } - find_macro_cluster_bels( - ctx, bel_pin_wire, possible_places, - ExpansionDirection(edge.dir), root, - cell_to_place); - } - } + CellInfo *cell = packed_cluster.cluster_nodes[idx_bel.first]; - for (const auto &place : possible_places){ - BelId check_bel = place.first.second; - const auto &bel_data2 = bel_info(chip_info, check_bel); - bool failed = false; - for (const auto &pin : needed_pins){ - log_info("Pin: %s\n", pin.c_str(ctx)); - if (!place.second.count(pin)){ - failed = true; - break; - } - } - if (failed) - continue; - log_info("Bel_name: %s type: %s\n", IdString(bel_data2.name).c_str(ctx), - IdString(bel_data2.type).c_str(ctx)); - log_info("Cell_name: %s type: %s\n", cell_to_place->name.c_str(ctx), cell_to_place->type.c_str(ctx)); - } + int32_t mapping = bel_data.pin_map[get_cell_type_index(cell->type)]; + NPNR_ASSERT(mapping >= 0); + + const CellBelMapPOD &cell_pin_map = chip_info->cell_map->cell_bel_map[mapping]; + for (const auto &pin_map : cell_pin_map.common_pins) { + IdString cell_pin(pin_map.cell_pin); + IdString bel_pin(pin_map.bel_pin); + cell_bel_pins[cell_pin].insert(bel_pin); + bel_cell_pins[bel_pin] = cell_pin; + } + + for (const auto &pair : bel_data.connected_pins){ + IdString p1(pair.pin1), p2(pair.pin2); + IdString i1(bel_cell_pins[p1]), i2(bel_cell_pins[p2]); + if (root_cell->ports[i1].net != root_cell->ports[i2].net){ + return false; } } } +*/ + + for(auto idx_bel : idx_bel_map){ + placement.emplace_back(packed_cluster.cluster_nodes[idx_bel.first], idx_bel.second); + } - exit(0); return true; } @@ -575,7 +593,6 @@ bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel, return normal_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, root_bel, placement); else{ - log_info("Macro cluster\n"); bool temp = macro_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, root_bel, placement); return temp; @@ -680,12 +697,8 @@ bool reduce(uint32_t x, uint32_t y, const ClusterPOD *cluster, dictverbose) - log_info("Testing cell %s\n", x_cell->name.c_str(ctx)); bool found = false; for (const auto &y_cell : domain[y]){ - if (ctx->verbose) - log_info(" - Y candidate: %s\n", y_cell->name.c_str(ctx)); for (const auto edge : cluster->connection_graph[x].connections[counter].edges){ if (!x_cell->ports.count(IdString(edge.cell_pin)) || !y_cell->ports.count(IdString(edge.other_cell_pin))) break; @@ -701,7 +714,6 @@ bool reduce(uint32_t x, uint32_t y, const ClusterPOD *cluster, dictname.c_str(ctx)); break; } } @@ -725,8 +737,6 @@ void binary_constraint_check(const ClusterPOD *cluster, workqueue.pop(); uint32_t x,y; x = arc.first; y = arc.second; - if (ctx->verbose) - log_info("Checking pair %d:%d\n", x, y); if (reduce(x, y, cluster, idx_to_cells, ctx)){ for (const auto &connection : cluster->connection_graph[arc.first].connections) if (connection.target_idx != y) @@ -1207,7 +1217,7 @@ void Arch::pack_cluster() const auto &cluster = chip_info->clusters[i]; prepare_cluster(&cluster, i); - } else if(!chip_info->clusters[i].out_of_site_clusters) { + } else if(chip_info->clusters[i].physical_placements.size() > 0) { const auto &cluster = chip_info->clusters[i]; if(ctx->verbose){ log_info("%s\n", IdString(cluster.name).c_str(ctx));\ @@ -1216,16 +1226,9 @@ void Arch::pack_cluster() prepare_macro_cluster(&cluster, i); } else { - // No good way to handle out of site clusters, as fulfiling routing requirements - // can be done by router. Right now cluster connection map creates connections from each - // cell to each cell, and in placement this is used as well. - // We could assume that in macros, where there are no root cells and - // we have multiple unconnected graphs, source cells must be in the same site. - // Why create a macro if these cells have nothing in common. - // For now python-fpga-interchange does not support this assumption - // and neither does placement code. - // Cluster preparing and packing works for both, but as we cannot place - // out of site clusters, we don't create them, letting generic P&R do it. + // No physical placement definitions found for given macro. + // Use default place and route algorithm as routes connectiong + // cells will use global routing const auto &cluster = chip_info->clusters[i]; if(ctx->verbose) log_info("Out of site cluster from macro: %s\n", IdString(cluster.name).c_str(ctx)); diff --git a/fpga_interchange/chipdb.h b/fpga_interchange/chipdb.h index 0f57bdc0..4e09f704 100644 --- a/fpga_interchange/chipdb.h +++ b/fpga_interchange/chipdb.h @@ -451,6 +451,14 @@ NPNR_PACKED_STRUCT(struct ClusterConnectionGraphPOD{ RelSlice used_ports; }); +NPNR_PACKED_STRUCT(struct ClusterPhysicalPlacementEntryPOD{ + RelSlice bels; +}); + +NPNR_PACKED_STRUCT(struct ClusterPhysicalPlacementsPOD{ + uint32_t site_type; + RelSlice places; +}); NPNR_PACKED_STRUCT(struct ClusterPOD { uint32_t name; @@ -459,6 +467,7 @@ NPNR_PACKED_STRUCT(struct ClusterPOD { RelSlice cluster_cells_map; RelSlice required_cells; RelSlice connection_graph; + RelSlice physical_placements; uint32_t out_of_site_clusters; uint32_t disallow_other_cells; uint32_t from_macro; From b12119d8e88bf99a801e12e947c170d3a0ae6e40 Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Tue, 21 Sep 2021 00:59:52 +0200 Subject: [PATCH 4/8] Improve macro cluster placement Signed-off-by: Maciej Dudek --- fpga_interchange/arch_pack_clusters.cc | 278 ++++--------------------- 1 file changed, 42 insertions(+), 236 deletions(-) diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc index 85527041..b7892fa2 100644 --- a/fpga_interchange/arch_pack_clusters.cc +++ b/fpga_interchange/arch_pack_clusters.cc @@ -276,176 +276,19 @@ bool Arch::normal_cluster_placement( return true; } -/* -static void handle_macro_expansion_node( - const Context *ctx, WireId wire, PipId pip, ClusterWireNode curr_node, - std::vector &nodes_to_expand, BelPin root_pin, - dict, dict>> &bels, - ExpansionDirection direction, pool &visited, CellInfo *cell) -{ - if (curr_node.state == IN_SINK_SITE || curr_node.state == ONLY_IN_SOURCE_SITE) { - for (BelPin bel_pin : ctx->getWireBelPins(wire)) { - BelId bel = bel_pin.bel; - if (bel == root_pin.bel) - continue; - auto const &bel_data = bel_info(ctx->chip_info, bel); +static dict> tileAndBelNameToBelIdCache; - if (bels.count(std::pair(root_pin.bel, bel)) &&\ - bels[std::pair(root_pin.bel, bel)].count(root_pin.pin) &&\ - bels[std::pair(root_pin.bel, bel)][root_pin.pin].count(bel_pin.pin)){ - continue; - } - - if (bel_data.category != BEL_CATEGORY_LOGIC){ - continue; - } - - if (bel_data.synthetic) - continue; - - if (!ctx->isValidBelForCellType(cell->type, bel)) - continue; - - bels[std::pair(root_pin.bel, bel_pin.bel)][root_pin.pin].\ - insert(bel_pin.pin); - } - } - - WireId next_wire; - - if (direction == CLUSTER_UPHILL_DIR) - next_wire = ctx->getPipSrcWire(pip); +BelId check_and_return(int32_t tile, IdString name){ + if(tileAndBelNameToBelIdCache.count(tile) + && tileAndBelNameToBelIdCache[tile].count(name)) + return tileAndBelNameToBelIdCache[tile][name]; else - next_wire = ctx->getPipDstWire(pip); - - if (next_wire == WireId() || visited.count(next_wire)) - return; - - ClusterWireNode next_node; - next_node.wire = next_wire; - next_node.depth = curr_node.depth; - next_node.only_down = false; - if (direction == CLUSTER_DOWNHILL_DIR) - next_node.only_down = true; - - if (next_node.depth >= 2) - return; - - auto const &wire_data = ctx->wire_info(next_wire); - - bool expand_node = true; - if (ctx->is_site_port(pip)) { - switch (curr_node.state) { - case ONLY_IN_SOURCE_SITE: - expand_node = false; - break; - case IN_SOURCE_SITE: - NPNR_ASSERT(wire_data.site == -1); - next_node.state = IN_ROUTING; - break; - case IN_ROUTING: - NPNR_ASSERT(wire_data.site != -1); - next_node.state = IN_SINK_SITE; - break; - case IN_SINK_SITE: - expand_node = false; - break; - default: - // Unreachable!!! - NPNR_ASSERT(false); - } - } else { - if (next_node.state == IN_ROUTING) - next_node.depth++; - next_node.state = curr_node.state; - } - - if (curr_node.state != IN_ROUTING){ - const auto &pip_data = pip_info(ctx->chip_info, pip); - BelId bel; - bel.tile = pip.tile; - bel.index = pip_data.bel; - const auto &bel_data = bel_info(ctx->chip_info, bel); - if(bel_data.category == BEL_CATEGORY_LOGIC) - expand_node = false; - } - - if (expand_node) - nodes_to_expand.push_back(next_node); - else - return; - - return; + return BelId(); } -static void - find_macro_cluster_bels(const Context *ctx, WireId wire, - dict, dict>> &possible_places, - ExpansionDirection direction, BelPin root_pin, CellInfo *cell, bool out_of_site_expansion = false) -{ - std::vector nodes_to_expand; - pool visited; - - const auto &wire_data = ctx->wire_info(wire); - NPNR_ASSERT(wire_data.site != -1); - - ClusterWireNode wire_node; - wire_node.wire = wire; - wire_node.state = IN_SOURCE_SITE; - if (!out_of_site_expansion) - wire_node.state = ONLY_IN_SOURCE_SITE; - wire_node.depth = 0; - wire_node.only_down = false; - - nodes_to_expand.push_back(wire_node); - - while (!nodes_to_expand.empty()) { - ClusterWireNode node_to_expand = nodes_to_expand.back(); - WireId wire = node_to_expand.wire; - nodes_to_expand.pop_back(); - visited.insert(wire); - if (direction == CLUSTER_DOWNHILL_DIR) { - for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) { - if (ctx->is_pip_synthetic(pip)) - continue; - - handle_macro_expansion_node( - ctx, wire, pip, node_to_expand, nodes_to_expand, - root_pin, possible_places, direction, visited, cell); - } - } else if (direction == CLUSTER_UPHILL_DIR){ - for (PipId pip : ctx->getPipsUphill(node_to_expand.wire)) { - if (ctx->is_pip_synthetic(pip)) - continue; - - handle_macro_expansion_node( - ctx, wire, pip, node_to_expand, nodes_to_expand, - root_pin, possible_places, direction, visited, cell); - } - } else { - NPNR_ASSERT(direction == CLUSTER_BOTH_DIR); - for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) { - if (ctx->is_pip_synthetic(pip)) - continue; - - handle_macro_expansion_node( - ctx, wire, pip, node_to_expand, nodes_to_expand, - root_pin, possible_places, CLUSTER_DOWNHILL_DIR, visited, cell); - } - if (!node_to_expand.only_down) - for (PipId pip : ctx->getPipsUphill(node_to_expand.wire)) { - if (ctx->is_pip_synthetic(pip)) - continue; - - handle_macro_expansion_node( - ctx, wire, pip, node_to_expand, nodes_to_expand, - root_pin, possible_places, CLUSTER_UPHILL_DIR, visited, cell); - } - } - } - return; +void add_to_cache(int32_t tile, IdString name, BelId t){ + tileAndBelNameToBelIdCache[tile][name] = t; } -*/ bool Arch::macro_cluster_placement( const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, @@ -489,88 +332,51 @@ bool Arch::macro_cluster_placement( log_info("Allowed root_bels:\n"); } for(const auto &place : cluster.physical_placements[idx].places){ - // root_bel has idx 0 - IdString name(place.bels[0]); - if(ctx->debug) - log_info("\t%s\n",name.c_str(ctx)); + for (const auto bel : place.bels){ + IdString name(bel); + if(ctx->debug) + log_info("\t%s\n",name.c_str(ctx)); - if(name == root_bel_name){ - found = true; - break; + if(name == root_bel_name){ + found = true; + break; + } } + if (found) + break; placement_idx++; } if (!found) return false; - // Check if all better placements are used auto root_bel_full_name = ctx->getBelName(root_bel); - for(uint32_t i = 0; i < placement_idx; i++){ - IdStringList cpy(root_bel_full_name.size()); - for(uint32_t j = 0; j < root_bel_full_name.size(); j++) - cpy.ids[j] = root_bel_full_name[j]; - cpy.ids[1] = IdString(cluster.physical_placements[idx].places[i].bels[0]); - BelId t = ctx->getBelByName(cpy); - if(ctx->debug){ - for (auto str : cpy) - log_info("%s\n", str.c_str(ctx)); - } - if (ctx->getBoundBelCell(t) == nullptr) - return false; - } - // Check if bels are avaiable dict idx_bel_map; uint32_t t_idx = 0; + if(ctx->debug) + log_info("Used bels:\n"); for(const auto &bel : cluster.physical_placements[idx].places[placement_idx].bels){ + IdString s_bel(bel); + BelId t = check_and_return(root_bel.tile, s_bel); IdStringList cpy(root_bel_full_name.size()); - for(uint32_t j = 0; j < root_bel_full_name.size(); j++) - cpy.ids[j] = root_bel_full_name[j]; - cpy.ids[1] = IdString(bel); - BelId t = ctx->getBelByName(cpy); - if(ctx->debug){ - for (auto str : cpy) - log_info("%s\n", str.c_str(ctx)); + if (t == BelId()){ + for(uint32_t j = 0; j < root_bel_full_name.size(); j++) + cpy.ids[j] = root_bel_full_name[j]; + cpy.ids[1] = s_bel; + t = ctx->getBelByName(cpy); + add_to_cache(root_bel.tile, s_bel, t); } - if (ctx->getBoundBelCell(t) != nullptr && - ctx->getBoundBelCell(t) != packed_cluster.cluster_nodes[t_idx]){ - if(ctx->debug) - log_info("Failed\n"); - return false; + if(ctx->debug){ + for(uint32_t j = 0; j < root_bel_full_name.size(); j++) + cpy.ids[j] = root_bel_full_name[j]; + cpy.ids[1] = s_bel; + for (auto str : cpy) + log_info("\t%s\n", str.c_str(ctx)); } idx_bel_map[t_idx] = t; t_idx++; } -/* - for(auto idx_bel : idx_bel_map){ - const auto &bel_data = bel_info(chip_info, idx_bel.second); - dict> cell_bel_pins; - dict bel_cell_pins; - - CellInfo *cell = packed_cluster.cluster_nodes[idx_bel.first]; - - int32_t mapping = bel_data.pin_map[get_cell_type_index(cell->type)]; - NPNR_ASSERT(mapping >= 0); - - const CellBelMapPOD &cell_pin_map = chip_info->cell_map->cell_bel_map[mapping]; - for (const auto &pin_map : cell_pin_map.common_pins) { - IdString cell_pin(pin_map.cell_pin); - IdString bel_pin(pin_map.bel_pin); - cell_bel_pins[cell_pin].insert(bel_pin); - bel_cell_pins[bel_pin] = cell_pin; - } - - for (const auto &pair : bel_data.connected_pins){ - IdString p1(pair.pin1), p2(pair.pin2); - IdString i1(bel_cell_pins[p1]), i2(bel_cell_pins[p2]); - if (root_cell->ports[i1].net != root_cell->ports[i2].net){ - return false; - } - } - } -*/ - for(auto idx_bel : idx_bel_map){ placement.emplace_back(packed_cluster.cluster_nodes[idx_bel.first], idx_bel.second); } @@ -870,7 +676,7 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) arc.second.erase(cell); } } - if (ctx->verbose){ + if (ctx->debug){ log_info("After mono constraints are applied\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) @@ -892,7 +698,7 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) binary_constraint_check(cluster, workqueue, idx_to_cells, ctx); for (const auto &arc : idx_to_cells){ if (arc.second.size() == 0){ - if (ctx->verbose) + if (ctx->debug) log_info("AC-3 failed\n"); failed = true; break; @@ -901,7 +707,7 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) if (failed) continue; - if (ctx->verbose){ + if (ctx->debug){ log_info("After AC-3\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) @@ -962,11 +768,11 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) binary_constraint_check(cluster, workqueue, idx_to_cells, ctx); }while(change); if(failed){ - if(ctx->verbose) + if(ctx->debug) log_info("Single cell mapping failed\n"); continue; } - if (ctx->verbose){ + if (ctx->debug){ log_info("After mapping indices with single cell\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) @@ -981,14 +787,14 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) } // At this point all indices that cloud only be mapped to single cell are mapped // Next step is to run solver with backtracing to solve for other idx<->cell mappings - if (ctx->verbose) + if (ctx->debug) log_info("Back solver\n"); if(!back_solver(cluster, idx_to_cells, ctx)){ - if(ctx->verbose) + if(ctx->debug) log_info("Back solver failed\n"); continue; } - if (ctx->verbose){ + if (ctx->debug){ log_info("Final mapping after back solver\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) From 44def159cc1babb18a29f71e4961df85d230afef Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Tue, 21 Sep 2021 20:48:50 +0200 Subject: [PATCH 5/8] Fix AC-3 algorithm Signed-off-by: Maciej Dudek --- fpga_interchange/arch_pack_clusters.cc | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc index b7892fa2..74823b8e 100644 --- a/fpga_interchange/arch_pack_clusters.cc +++ b/fpga_interchange/arch_pack_clusters.cc @@ -505,23 +505,28 @@ bool reduce(uint32_t x, uint32_t y, const ClusterPOD *cluster, dictconnection_graph[x].connections[counter].edges){ - if (!x_cell->ports.count(IdString(edge.cell_pin)) || !y_cell->ports.count(IdString(edge.other_cell_pin))) + if (!x_cell->ports.count(IdString(edge.cell_pin)) || !y_cell->ports.count(IdString(edge.other_cell_pin))){ + found = false; break; + } const auto x_net = x_cell->ports[IdString(edge.cell_pin)].net; const auto y_net = y_cell->ports[IdString(edge.other_cell_pin)].net; - if (x_net != y_net) + if (x_net != y_net){ + found = false; break; + } bool x_driver = x_net->driver.cell == x_cell; bool y_driver = y_net->driver.cell == y_cell; - if ((edge.dir != 0 || !y_driver) && (edge.dir != 1 || !x_driver) && (edge.dir != 2 || y_driver || x_driver)) + if ((edge.dir != 0 || !y_driver) && (edge.dir != 1 || !x_driver) && (edge.dir != 2 || y_driver || x_driver)){ + found = false; break; - found = true; + } } - if (found){ + if (found) break; - } } if (!found) remove_cell.push_back(x_cell); @@ -544,9 +549,12 @@ void binary_constraint_check(const ClusterPOD *cluster, uint32_t x,y; x = arc.first; y = arc.second; if (reduce(x, y, cluster, idx_to_cells, ctx)){ - for (const auto &connection : cluster->connection_graph[arc.first].connections) - if (connection.target_idx != y) - workqueue.push(std::pair(arc.first, connection.target_idx)); + for (const auto &node : cluster->connection_graph){ + if (node.idx != arc.first) + for (const auto &connection : node.connections) + if (connection.target_idx == arc.first) + workqueue.push(std::pair(node.idx, arc.first)); + } } } } From 2de1ecfabe71c655e83a05a58ab07332db0b8fac Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Thu, 23 Sep 2021 15:05:05 +0200 Subject: [PATCH 6/8] Update python-fpga-interchange to v0.0.20 Signed-off-by: Maciej Dudek --- .github/workflows/interchange_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/interchange_ci.yml b/.github/workflows/interchange_ci.yml index 05220abd..3c165cf8 100644 --- a/.github/workflows/interchange_ci.yml +++ b/.github/workflows/interchange_ci.yml @@ -114,7 +114,7 @@ jobs: env: RAPIDWRIGHT_PATH: ${{ github.workspace }}/RapidWright PYTHON_INTERCHANGE_PATH: ${{ github.workspace }}/python-fpga-interchange - PYTHON_INTERCHANGE_TAG: v0.0.18 + PYTHON_INTERCHANGE_TAG: v0.0.20 PRJOXIDE_REVISION: 1bf30dee9c023c4c66cfc44fd0bc28addd229c89 DEVICE: ${{ matrix.device }} run: | From 439ae9609b8245e56cda9c8f38f8d6a4bde90d5b Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Fri, 24 Sep 2021 11:07:37 +0200 Subject: [PATCH 7/8] Break up macro_cluster_placement into smaller functions Signed-off-by: Maciej Dudek --- fpga_interchange/arch_pack_clusters.cc | 53 ++++++++++++++++---------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc index 74823b8e..51724d30 100644 --- a/fpga_interchange/arch_pack_clusters.cc +++ b/fpga_interchange/arch_pack_clusters.cc @@ -290,21 +290,13 @@ void add_to_cache(int32_t tile, IdString name, BelId t){ tileAndBelNameToBelIdCache[tile][name] = t; } -bool Arch::macro_cluster_placement( - const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, - CellInfo *root_cell, BelId root_bel, std::vector> &placement) const -{ - // Check root_bel site_type - const auto &cluster = cluster_info(chip_info, packed_cluster.index); +bool find_site_idx(const Context *ctx, const ClusterPOD &cluster, BelId root_bel, uint32_t &idx){ bool found = false; - uint32_t idx = 0; const auto &site_inst = ctx->get_site_inst(root_bel); IdString site_type(site_inst.site_type); - if(ctx->debug) - log_info("%s\n", ctx->get_site_name(root_bel)); - if (ctx->debug){ + log_info("%s\n", ctx->get_site_name(root_bel)); log_info("Root_bel site_type: %s\n", site_type.c_str(ctx)); log_info("Allowed site_types:\n"); } @@ -319,13 +311,13 @@ bool Arch::macro_cluster_placement( } idx++; } - if (!found) - return false; + return found; +} - // Check if root_bel name - uint32_t placement_idx = 0; - found = false; - const auto &bel_data = bel_info(chip_info, root_bel); +bool find_placement_idx(const Context *ctx, const ClusterPOD &cluster, + BelId root_bel, uint32_t idx, uint32_t &placement_idx){ + bool found = false; + const auto &bel_data = bel_info(ctx->chip_info, root_bel); IdString root_bel_name(bel_data.name); if(ctx->debug){ log_info("Root_bel name: %s\n", root_bel_name.c_str(ctx)); @@ -346,12 +338,13 @@ bool Arch::macro_cluster_placement( break; placement_idx++; } - if (!found) - return false; + return found; +} - auto root_bel_full_name = ctx->getBelName(root_bel); - // Check if bels are avaiable +dict idx_bel_mapping(const Context *ctx, BelId root_bel, + const ClusterPOD &cluster, uint32_t idx, uint32_t placement_idx){ dict idx_bel_map; + auto root_bel_full_name = ctx->getBelName(root_bel); uint32_t t_idx = 0; if(ctx->debug) log_info("Used bels:\n"); @@ -376,6 +369,26 @@ bool Arch::macro_cluster_placement( idx_bel_map[t_idx] = t; t_idx++; } + return idx_bel_map; +} + +bool Arch::macro_cluster_placement( + const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, + CellInfo *root_cell, BelId root_bel, std::vector> &placement) const +{ + // Check root_bel site_type + const auto &cluster = cluster_info(chip_info, packed_cluster.index); + uint32_t idx = 0; + if(!find_site_idx(ctx, cluster, root_bel, idx)) + return false; + + // Check if root_bel name + uint32_t placement_idx = 0; + if (!find_placement_idx(ctx, cluster, root_bel, idx, placement_idx)) + return false; + + // Map cells to bels + dict idx_bel_map = idx_bel_mapping(ctx, root_bel, cluster, idx, placement_idx); for(auto idx_bel : idx_bel_map){ placement.emplace_back(packed_cluster.cluster_nodes[idx_bel.first], idx_bel.second); From ea489f6d934ac6e649bcd81e10856e809f6b30d2 Mon Sep 17 00:00:00 2001 From: Maciej Dudek Date: Mon, 27 Sep 2021 16:16:33 +0200 Subject: [PATCH 8/8] Fix small isses and code formatting Signed-off-by: Maciej Dudek --- common/placer1.cc | 4 +- fpga_interchange/arch.h | 8 +- fpga_interchange/arch_pack_clusters.cc | 266 +++++++++++++------------ fpga_interchange/chipdb.h | 18 +- fpga_interchange/macros.cc | 2 - 5 files changed, 150 insertions(+), 148 deletions(-) diff --git a/common/placer1.cc b/common/placer1.cc index 3501e446..4db1c951 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -731,11 +731,11 @@ class SAPlacer return true; swap_fail: #if CHAIN_DEBUG - log_info("Swap failed\n"); + log_info("Swap failed\n"); #endif for (auto cell_pair : moved_cells) { CellInfo *cell = ctx->cells.at(cell_pair.first).get(); - if (cell->bel != BelId()){ + if (cell->bel != BelId()) { #if CHAIN_DEBUG log_info("%d unbind %s\n", __LINE__, ctx->nameOfBel(cell->bel)); #endif diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index 9ce1eb4d..482bf911 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -899,10 +899,10 @@ struct Arch : ArchAPI ArcBounds getClusterBounds(ClusterId cluster) const override; Loc getClusterOffset(const CellInfo *cell) const override; bool isClusterStrict(const CellInfo *cell) const override; - bool normal_cluster_placement(const Context *, const Cluster &, const ClusterPOD &,CellInfo*, - BelId, std::vector> &) const; - bool macro_cluster_placement(const Context *, const Cluster &, const ClusterPOD &,CellInfo*, - BelId, std::vector> &) const; + bool normal_cluster_placement(const Context *, const Cluster &, const ClusterPOD &, CellInfo *, BelId, + std::vector> &) const; + bool macro_cluster_placement(const Context *, const Cluster &, const ClusterPOD &, CellInfo *, BelId, + std::vector> &) const; bool getClusterPlacement(ClusterId cluster, BelId root_bel, std::vector> &placement) const override; diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc index 51724d30..998c944e 100644 --- a/fpga_interchange/arch_pack_clusters.cc +++ b/fpga_interchange/arch_pack_clusters.cc @@ -189,9 +189,9 @@ CellInfo *Arch::getClusterRootCell(ClusterId cluster) const return clusters.at(cluster).root; } -bool Arch::normal_cluster_placement( - const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, - CellInfo *root_cell, BelId root_bel, std::vector> &placement) const +bool Arch::normal_cluster_placement(const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, + CellInfo *root_cell, BelId root_bel, + std::vector> &placement) const { BelId next_bel; @@ -278,34 +278,33 @@ bool Arch::normal_cluster_placement( static dict> tileAndBelNameToBelIdCache; -BelId check_and_return(int32_t tile, IdString name){ - if(tileAndBelNameToBelIdCache.count(tile) - && tileAndBelNameToBelIdCache[tile].count(name)) +BelId check_and_return(int32_t tile, IdString name) +{ + if (tileAndBelNameToBelIdCache.count(tile) && tileAndBelNameToBelIdCache[tile].count(name)) return tileAndBelNameToBelIdCache[tile][name]; else return BelId(); } -void add_to_cache(int32_t tile, IdString name, BelId t){ - tileAndBelNameToBelIdCache[tile][name] = t; -} +void add_to_cache(int32_t tile, IdString name, BelId t) { tileAndBelNameToBelIdCache[tile][name] = t; } -bool find_site_idx(const Context *ctx, const ClusterPOD &cluster, BelId root_bel, uint32_t &idx){ +bool find_site_idx(const Context *ctx, const ClusterPOD &cluster, BelId root_bel, uint32_t &idx) +{ bool found = false; const auto &site_inst = ctx->get_site_inst(root_bel); IdString site_type(site_inst.site_type); - if (ctx->debug){ + if (ctx->debug) { log_info("%s\n", ctx->get_site_name(root_bel)); log_info("Root_bel site_type: %s\n", site_type.c_str(ctx)); log_info("Allowed site_types:\n"); } - for(const auto &site : cluster.physical_placements){ + for (const auto &site : cluster.physical_placements) { IdString name(site.site_type); - if(ctx->debug) + if (ctx->debug) log_info("\t%s\n", name.c_str(ctx)); - if (name == site_type){ + if (name == site_type) { found = true; break; } @@ -314,22 +313,23 @@ bool find_site_idx(const Context *ctx, const ClusterPOD &cluster, BelId root_bel return found; } -bool find_placement_idx(const Context *ctx, const ClusterPOD &cluster, - BelId root_bel, uint32_t idx, uint32_t &placement_idx){ +bool find_placement_idx(const Context *ctx, const ClusterPOD &cluster, BelId root_bel, uint32_t idx, + uint32_t &placement_idx) +{ bool found = false; const auto &bel_data = bel_info(ctx->chip_info, root_bel); IdString root_bel_name(bel_data.name); - if(ctx->debug){ + if (ctx->debug) { log_info("Root_bel name: %s\n", root_bel_name.c_str(ctx)); log_info("Allowed root_bels:\n"); } - for(const auto &place : cluster.physical_placements[idx].places){ - for (const auto bel : place.bels){ + for (const auto &place : cluster.physical_placements[idx].places) { + for (const auto bel : place.bels) { IdString name(bel); - if(ctx->debug) - log_info("\t%s\n",name.c_str(ctx)); + if (ctx->debug) + log_info("\t%s\n", name.c_str(ctx)); - if(name == root_bel_name){ + if (name == root_bel_name) { found = true; break; } @@ -341,26 +341,27 @@ bool find_placement_idx(const Context *ctx, const ClusterPOD &cluster, return found; } -dict idx_bel_mapping(const Context *ctx, BelId root_bel, - const ClusterPOD &cluster, uint32_t idx, uint32_t placement_idx){ +dict idx_bel_mapping(const Context *ctx, BelId root_bel, const ClusterPOD &cluster, uint32_t idx, + uint32_t placement_idx) +{ dict idx_bel_map; auto root_bel_full_name = ctx->getBelName(root_bel); uint32_t t_idx = 0; - if(ctx->debug) + if (ctx->debug) log_info("Used bels:\n"); - for(const auto &bel : cluster.physical_placements[idx].places[placement_idx].bels){ + for (const auto &bel : cluster.physical_placements[idx].places[placement_idx].bels) { IdString s_bel(bel); BelId t = check_and_return(root_bel.tile, s_bel); IdStringList cpy(root_bel_full_name.size()); - if (t == BelId()){ - for(uint32_t j = 0; j < root_bel_full_name.size(); j++) + if (t == BelId()) { + for (uint32_t j = 0; j < root_bel_full_name.size(); j++) cpy.ids[j] = root_bel_full_name[j]; - cpy.ids[1] = s_bel; + cpy.ids[root_bel_full_name.size() - 1] = s_bel; t = ctx->getBelByName(cpy); add_to_cache(root_bel.tile, s_bel, t); } - if(ctx->debug){ - for(uint32_t j = 0; j < root_bel_full_name.size(); j++) + if (ctx->debug) { + for (uint32_t j = 0; j < root_bel_full_name.size(); j++) cpy.ids[j] = root_bel_full_name[j]; cpy.ids[1] = s_bel; for (auto str : cpy) @@ -372,14 +373,14 @@ dict idx_bel_mapping(const Context *ctx, BelId root_bel, return idx_bel_map; } -bool Arch::macro_cluster_placement( - const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, - CellInfo *root_cell, BelId root_bel, std::vector> &placement) const +bool Arch::macro_cluster_placement(const Context *ctx, const Cluster &packed_cluster, const ClusterPOD &cluster_data, + CellInfo *root_cell, BelId root_bel, + std::vector> &placement) const { // Check root_bel site_type const auto &cluster = cluster_info(chip_info, packed_cluster.index); uint32_t idx = 0; - if(!find_site_idx(ctx, cluster, root_bel, idx)) + if (!find_site_idx(ctx, cluster, root_bel, idx)) return false; // Check if root_bel name @@ -390,7 +391,7 @@ bool Arch::macro_cluster_placement( // Map cells to bels dict idx_bel_map = idx_bel_mapping(ctx, root_bel, cluster, idx, placement_idx); - for(auto idx_bel : idx_bel_map){ + for (auto idx_bel : idx_bel_map) { placement.emplace_back(packed_cluster.cluster_nodes[idx_bel.first], idx_bel.second); } @@ -409,11 +410,9 @@ bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel, if (!ctx->isValidBelForCellType(root_cell->type, root_bel)) return false; if (!cluster_data.from_macro) - return normal_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, - root_bel, placement); - else{ - bool temp = macro_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, - root_bel, placement); + return normal_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, root_bel, placement); + else { + bool temp = macro_cluster_placement(ctx, packed_cluster, cluster_data, root_cell, root_bel, placement); return temp; } } @@ -506,34 +505,39 @@ static bool check_cluster_cells_compatibility(CellInfo *old_cell, CellInfo *new_ return true; } -bool reduce(uint32_t x, uint32_t y, const ClusterPOD *cluster, dict> &domain, Context *ctx){ +bool reduce(uint32_t x, uint32_t y, const ClusterPOD *cluster, dict> &domain, + Context *ctx) +{ + // Reduce X domain by removing values, which don't satisfy binary constraint with values from Y domain. bool change = false; std::vector remove_cell; uint32_t counter = 0; - for (const auto &connection : cluster->connection_graph[x].connections){ - if(connection.target_idx == y) + for (const auto &connection : cluster->connection_graph[x].connections) { + if (connection.target_idx == y) break; - counter ++; + counter++; } - for (const auto &x_cell : domain[x]){ + for (const auto &x_cell : domain[x]) { bool found = false; - for (const auto &y_cell : domain[y]){ + for (const auto &y_cell : domain[y]) { found = true; - for (const auto edge : cluster->connection_graph[x].connections[counter].edges){ - if (!x_cell->ports.count(IdString(edge.cell_pin)) || !y_cell->ports.count(IdString(edge.other_cell_pin))){ + for (const auto edge : cluster->connection_graph[x].connections[counter].edges) { + if (!x_cell->ports.count(IdString(edge.cell_pin)) || + !y_cell->ports.count(IdString(edge.other_cell_pin))) { found = false; break; } const auto x_net = x_cell->ports[IdString(edge.cell_pin)].net; const auto y_net = y_cell->ports[IdString(edge.other_cell_pin)].net; - if (x_net != y_net){ + if (x_net != y_net) { found = false; break; } bool x_driver = x_net->driver.cell == x_cell; bool y_driver = y_net->driver.cell == y_cell; - if ((edge.dir != 0 || !y_driver) && (edge.dir != 1 || !x_driver) && (edge.dir != 2 || y_driver || x_driver)){ + if ((edge.dir != 0 || !y_driver) && (edge.dir != 1 || !x_driver) && + (edge.dir != 2 || y_driver || x_driver)) { found = false; break; } @@ -545,7 +549,7 @@ bool reduce(uint32_t x, uint32_t y, const ClusterPOD *cluster, dict> &workqueue, - dict> &idx_to_cells, Context *ctx){ - while (!workqueue.empty()){ +void binary_constraint_check(const ClusterPOD *cluster, std::queue> &workqueue, + dict> &idx_to_cells, Context *ctx) +{ + while (!workqueue.empty()) { std::pair arc = workqueue.front(); workqueue.pop(); - uint32_t x,y; - x = arc.first; y = arc.second; - if (reduce(x, y, cluster, idx_to_cells, ctx)){ - for (const auto &node : cluster->connection_graph){ + uint32_t x, y; + x = arc.first; + y = arc.second; + if (reduce(x, y, cluster, idx_to_cells, ctx)) { + for (const auto &node : cluster->connection_graph) { if (node.idx != arc.first) for (const auto &connection : node.connections) if (connection.target_idx == arc.first) @@ -572,34 +577,35 @@ void binary_constraint_check(const ClusterPOD *cluster, } } -bool back_solver(const ClusterPOD *cluster, - dict> &idx_to_cells, Context *ctx){ +bool back_solver(const ClusterPOD *cluster, dict> &idx_to_cells, Context *ctx) +{ dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) for (const auto &cell : arc.second) possible_idx[cell].insert(arc.first); std::queue prep; - for (const auto &arc : idx_to_cells){ + for (const auto &arc : idx_to_cells) { if (arc.second.size() == 0) return false; - if (arc.second.size()>1){ - for (const auto &cell : arc.second){ + if (arc.second.size() > 1) { + for (const auto &cell : arc.second) { auto copy_idx_to_cells(idx_to_cells); copy_idx_to_cells[arc.first].clear(); - for (uint32_t idx : possible_idx[cell]){ + for (uint32_t idx : possible_idx[cell]) { copy_idx_to_cells[idx].erase(cell); prep.push(idx); } copy_idx_to_cells[arc.first].insert(cell); std::queue> workqueue; - while(!prep.empty()){ - uint32_t idx = prep.front(); prep.pop(); + while (!prep.empty()) { + uint32_t idx = prep.front(); + prep.pop(); for (const auto &connection : cluster->connection_graph[idx].connections) if (arc.first != connection.target_idx) workqueue.push(std::pair(arc.first, connection.target_idx)); } binary_constraint_check(cluster, workqueue, copy_idx_to_cells, ctx); - if (back_solver(cluster, copy_idx_to_cells, ctx)){ + if (back_solver(cluster, copy_idx_to_cells, ctx)) { idx_to_cells = std::move(copy_idx_to_cells); return true; } @@ -609,7 +615,7 @@ bool back_solver(const ClusterPOD *cluster, return true; } -void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) +void Arch::prepare_macro_cluster(const ClusterPOD *cluster, uint32_t index) { Context *ctx = getCtx(); IdString cluster_name(cluster->name); @@ -620,45 +626,48 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) // Find cluster roots for each macro only ones dict roots; - for (auto &cell : cells){ + for (auto &cell : cells) { CellInfo *ci = cell.second.get(); - if(ci->macro_parent == IdString()) + if (ci->macro_parent == IdString()) continue; - if(ci->cluster != ClusterId()) + if (ci->cluster != ClusterId()) continue; if (!cluster_cell_types.count(ci->type)) continue; - if(roots.count(ci->macro_parent)) + if (roots.count(ci->macro_parent)) continue; // Simple check based on cell type counting + dict cells_in_macro, counter; + // cells_in_macro stores cell_types used in tested cluster and + // cell_types that are in macro_to_cells[ci->macro_parent] + pool cell_types; - for (auto &cell_type : cluster->required_cells){ + for (auto &cell_type : cluster->required_cells) { cells_in_macro[IdString(cell_type.name)] = cell_type.count; cell_types.insert(IdString(cell_type.name)); } - for (auto &node_cell : macro_to_cells[ci->macro_parent]){ + for (auto &node_cell : macro_to_cells[ci->macro_parent]) { auto cell_type = node_cell->type; - if(!counter.count(cell_type)) - counter[cell_type] = 0; counter[cell_type]++; cell_types.insert(cell_type); } bool failed = false; - for(auto cell_type : cell_types){ - if(ctx->verbose && cells_in_macro.count(cell_type)) + for (auto cell_type : cell_types) { + if (ctx->verbose && cells_in_macro.count(cell_type)) log_info("Required: %s %d\n", cell_type.c_str(ctx), cells_in_macro[cell_type]); - if(ctx->verbose && cells_in_macro.count(cell_type)) + if (ctx->verbose && cells_in_macro.count(cell_type)) log_info("Have: %s %d\n", cell_type.c_str(ctx), counter[cell_type]); - if(!cells_in_macro.count(cell_type) || !counter.count(cell_type) || cells_in_macro[cell_type] != counter[cell_type]) + if (!cells_in_macro.count(cell_type) || !counter.count(cell_type) || + cells_in_macro[cell_type] != counter[cell_type]) failed = true; - if(failed && ctx->verbose) + if (failed && ctx->verbose) log_info("Cell count stage failed, for sure not this cluster\n"); - if(failed) + if (failed) break; } - if(failed){ + if (failed) { roots[ci->macro_parent] = nullptr; continue; } @@ -669,42 +678,41 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) for (auto &cell : macro_to_cells[ci->macro_parent]) for (auto &node : cluster->connection_graph) if (IdString(node.cell_type) == cell->type) - if (node.idx != 0 && cell->name != ci->name || - node.idx == 0 && cell->name == ci->name ){ + if (node.idx != 0 && cell->name != ci->name || node.idx == 0 && cell->name == ci->name) { idx_to_cells[node.idx].insert(cell); } - for (auto &arc : idx_to_cells){ + for (auto &arc : idx_to_cells) { std::vector remove_cell; pool used_ports; for (const auto &port : cluster->connection_graph[arc.first].used_ports) used_ports.insert(IdString(port.name)); - for (const auto &cell : arc.second){ + for (const auto &cell : arc.second) { uint32_t count = 0; - for (const auto &port : cell->ports){ - if (!used_ports.count(port.first)){ + for (const auto &port : cell->ports) { + if (!used_ports.count(port.first)) { remove_cell.push_back(cell); break; } count++; } - if (count != used_ports.size()){ + if (count != used_ports.size()) { remove_cell.push_back(cell); break; } } - for (const auto &cell : remove_cell){ + for (const auto &cell : remove_cell) { arc.second.erase(cell); } } - if (ctx->debug){ + if (ctx->debug) { log_info("After mono constraints are applied\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) for (const auto &cell : arc.second) possible_idx[cell].insert(arc.first); - for (const auto arc : possible_idx){ + for (const auto arc : possible_idx) { log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); for (const auto idx : arc.second) log_info(" - %d\n", idx); @@ -714,11 +722,11 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) std::queue> workqueue; for (const auto &arc : idx_to_cells) for (const auto &connection : cluster->connection_graph[arc.first].connections) - workqueue.push(std::pair(arc.first, connection.target_idx)); + workqueue.emplace(arc.first, connection.target_idx); binary_constraint_check(cluster, workqueue, idx_to_cells, ctx); - for (const auto &arc : idx_to_cells){ - if (arc.second.size() == 0){ + for (const auto &arc : idx_to_cells) { + if (arc.second.size() == 0) { if (ctx->debug) log_info("AC-3 failed\n"); failed = true; @@ -728,14 +736,14 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) if (failed) continue; - if (ctx->debug){ + if (ctx->debug) { log_info("After AC-3\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) for (const auto &cell : arc.second) possible_idx[cell].insert(arc.first); - for (const auto arc : possible_idx){ + for (const auto arc : possible_idx) { log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); for (const auto idx : arc.second) log_info(" - %d\n", idx); @@ -747,35 +755,36 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) // Keep assigning cells to indices that only map to single cell // Remove this cell from other mappings and recheck binary constraints // Fail if there is no cell for idx or cell has no idx assign - do{ + do { change = false; dict, hash_ptr_ops> possible_idx; pool changed_idxs; - for (const auto &arc : idx_to_cells){ - if (arc.second.size() == 0){ + for (const auto &arc : idx_to_cells) { + if (arc.second.size() == 0) { failed = true; break; } for (const auto &cell : arc.second) possible_idx[cell].insert(arc.first); } - if(failed) + if (failed) break; for (auto &cell : macro_to_cells[ci->macro_parent]) - if (possible_idx[cell].size() == 0){ + if (possible_idx[cell].size() == 0) { failed = true; break; } - if(failed) + if (failed) break; - for (const auto &arc : idx_to_cells){ + for (const auto &arc : idx_to_cells) { if (arc.second.size() == 1) for (const auto &idx : possible_idx[*arc.second.begin()]) if (idx != arc.first) - removequeue.push(std::pair(idx, *arc.second.begin())); + removequeue.push(std::pair(idx, *arc.second.begin())); } - while(!removequeue.empty()){ - auto t = removequeue.front(); removequeue.pop(); + while (!removequeue.empty()) { + auto t = removequeue.front(); + removequeue.pop(); uint32_t idx = t.first; CellInfo *cell = t.second; idx_to_cells[idx].erase(cell); @@ -787,20 +796,20 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) workqueue.push(std::pair(idx, connection.target_idx)); binary_constraint_check(cluster, workqueue, idx_to_cells, ctx); - }while(change); - if(failed){ - if(ctx->debug) + } while (change); + if (failed) { + if (ctx->debug) log_info("Single cell mapping failed\n"); continue; } - if (ctx->debug){ + if (ctx->debug) { log_info("After mapping indices with single cell\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) for (const auto &cell : arc.second) possible_idx[cell].insert(arc.first); - for (const auto arc : possible_idx){ + for (const auto arc : possible_idx) { log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); for (const auto idx : arc.second) log_info(" - %d\n", idx); @@ -810,19 +819,19 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) // Next step is to run solver with backtracing to solve for other idx<->cell mappings if (ctx->debug) log_info("Back solver\n"); - if(!back_solver(cluster, idx_to_cells, ctx)){ - if(ctx->debug) + if (!back_solver(cluster, idx_to_cells, ctx)) { + if (ctx->debug) log_info("Back solver failed\n"); continue; } - if (ctx->debug){ + if (ctx->debug) { log_info("Final mapping after back solver\n"); dict, hash_ptr_ops> possible_idx; for (const auto &arc : idx_to_cells) for (const auto &cell : arc.second) possible_idx[cell].insert(arc.first); - for (const auto arc : possible_idx){ + for (const auto arc : possible_idx) { log_info("Possible idx %s:\n", arc.first->name.c_str(ctx)); for (const auto idx : arc.second) log_info(" - %d\n", idx); @@ -832,9 +841,9 @@ void Arch::prepare_macro_cluster( const ClusterPOD *cluster, uint32_t index) cluster_info.root = ci; cluster_info.index = index; cluster_info.cluster_nodes.resize(idx_to_cells.size()); - ci->cluster.set(ctx, ci->name.str(ctx)); - for (auto &arc : idx_to_cells){ - CellInfo * sub_cell = arc.second.pop(); + ci->cluster = ci->name; + for (auto &arc : idx_to_cells) { + CellInfo *sub_cell = arc.second.pop(); if (ctx->verbose) log_info("%d %s - %s\n", arc.first, sub_cell->name.c_str(ctx), sub_cell->type.c_str(ctx)); sub_cell->cluster = ci->cluster; @@ -1040,24 +1049,23 @@ void Arch::pack_cluster() dump_clusters(chip_info, ctx); for (uint32_t i = 0; i < chip_info->clusters.size(); ++i) { - if (!chip_info->clusters[i].from_macro){ + if (!chip_info->clusters[i].from_macro) { const auto &cluster = chip_info->clusters[i]; prepare_cluster(&cluster, i); - } else if(chip_info->clusters[i].physical_placements.size() > 0) { + } else if (chip_info->clusters[i].physical_placements.size() > 0) { const auto &cluster = chip_info->clusters[i]; - if(ctx->verbose){ - log_info("%s\n", IdString(cluster.name).c_str(ctx));\ + if (ctx->verbose) { + log_info("%s\n", IdString(cluster.name).c_str(ctx)); } prepare_macro_cluster(&cluster, i); - } - else { + } else { // No physical placement definitions found for given macro. // Use default place and route algorithm as routes connectiong // cells will use global routing const auto &cluster = chip_info->clusters[i]; - if(ctx->verbose) + if (ctx->verbose) log_info("Out of site cluster from macro: %s\n", IdString(cluster.name).c_str(ctx)); } } diff --git a/fpga_interchange/chipdb.h b/fpga_interchange/chipdb.h index 4e09f704..7ef0914d 100644 --- a/fpga_interchange/chipdb.h +++ b/fpga_interchange/chipdb.h @@ -423,39 +423,35 @@ NPNR_PACKED_STRUCT(struct ChainablePortPOD { int16_t avg_y_offset; }); -NPNR_PACKED_STRUCT(struct ClusterRequiredCellPOD{ +NPNR_PACKED_STRUCT(struct ClusterRequiredCellPOD { uint32_t name; uint32_t count; }); -NPNR_PACKED_STRUCT(struct ClusterUsedPortPOD{ - uint32_t name; -}); +NPNR_PACKED_STRUCT(struct ClusterUsedPortPOD { uint32_t name; }); -NPNR_PACKED_STRUCT(struct ClusterEdgePOD{ +NPNR_PACKED_STRUCT(struct ClusterEdgePOD { uint32_t dir; uint32_t cell_pin; uint32_t other_cell_pin; uint32_t other_cell_type; }); -NPNR_PACKED_STRUCT(struct ClusterConnectionsPOD{ +NPNR_PACKED_STRUCT(struct ClusterConnectionsPOD { uint32_t target_idx; RelSlice edges; }); -NPNR_PACKED_STRUCT(struct ClusterConnectionGraphPOD{ +NPNR_PACKED_STRUCT(struct ClusterConnectionGraphPOD { uint32_t idx; uint32_t cell_type; RelSlice connections; RelSlice used_ports; }); -NPNR_PACKED_STRUCT(struct ClusterPhysicalPlacementEntryPOD{ - RelSlice bels; -}); +NPNR_PACKED_STRUCT(struct ClusterPhysicalPlacementEntryPOD { RelSlice bels; }); -NPNR_PACKED_STRUCT(struct ClusterPhysicalPlacementsPOD{ +NPNR_PACKED_STRUCT(struct ClusterPhysicalPlacementsPOD { uint32_t site_type; RelSlice places; }); diff --git a/fpga_interchange/macros.cc b/fpga_interchange/macros.cc index 4011f683..aa7d3184 100644 --- a/fpga_interchange/macros.cc +++ b/fpga_interchange/macros.cc @@ -79,7 +79,6 @@ void Arch::expand_macros() // Get the ultimate root of this macro expansion IdString parent = (cell->macro_parent == IdString()) ? cell->name : cell->macro_parent; - log_info("%s %s\n", cell->name.c_str(ctx), parent.c_str(ctx)); // Create child instances for (const auto &inst : macro->cell_insts) { CellInfo *inst_cell = @@ -88,7 +87,6 @@ void Arch::expand_macros() inst_cell->params[IdString(param.key)] = IdString(param.value).str(ctx); } inst_cell->macro_parent = parent; - log_info(" %s %s\n", inst_cell->name.c_str(ctx), inst_cell->type.c_str(ctx)); next_cells.push_back(inst_cell); } // Create and connect nets