diff --git a/himbaechel/uarch/gowin/cst.cc b/himbaechel/uarch/gowin/cst.cc index 1ec12cb3..310e1406 100644 --- a/himbaechel/uarch/gowin/cst.cc +++ b/himbaechel/uarch/gowin/cst.cc @@ -63,9 +63,10 @@ struct GowinCstReader for (auto &bel : ctx->getBelsInBucket(ctx->getBelBucketForCellType(id_CLKDIV))) { auto this_loc = ctx->getBelLocation(bel); - if (!lr && this_loc.y == y_coord && this_loc.z == bel_z) // top or bottom side + if (lr && this_loc.x == x_coord && this_loc.z == bel_z && this_loc.y != 0 && + this_loc.y != maxY - 1) // left or right side return bel; - else if (lr && this_loc.x == x_coord && this_loc.z == bel_z) // left or right side + else if (!lr && this_loc.y == y_coord && this_loc.z == bel_z) // top or bottom side return bel; } return BelId(); diff --git a/himbaechel/uarch/gowin/gowin.cc b/himbaechel/uarch/gowin/gowin.cc index 36717849..f1dd88e0 100644 --- a/himbaechel/uarch/gowin/gowin.cc +++ b/himbaechel/uarch/gowin/gowin.cc @@ -388,13 +388,22 @@ void GowinImpl::place_constrained_hclk_cells() std::map> true_clkdivs; std::set used_bels; for (auto constr_pair : constrained_clkdivs) { - BelId option1 = ctx->getBelByName(constr_pair.first); - BelId option2 = gwu.get_other_hclk_clkdiv2(option1); + BelId option0 = ctx->getBelByName(constr_pair.first); + BelId option1 = gwu.get_other_hclk_clkdiv2(option0); + + // On the GW1N-9 devices, only the lower CLKDIV can be fed by a CLKDIV2 + std::vector options = {option1, option0}; + if (chip.str(ctx) == "GW1N-9C") { + auto ci = ctx->cells.at(constr_pair.second).get(); + for (auto cluster_child_cell : ci->constr_children) + if (cluster_child_cell->type == id_CLKDIV2 && options.back() == option0) { + options.pop_back(); + break; + } + } - // log_info("%s: option1: %s, option2: %s\n", constr_pair.second.c_str(ctx), ctx->nameOfBel(option1), - // ctx->nameOfBel(option2)); bool placed = false; - for (auto option : {option1, option2}) { + for (auto option : options) { if (placed || (used_bels.find(option) != used_bels.end())) continue; for (auto option_cell : bel_cell_map[option]) { @@ -413,8 +422,8 @@ void GowinImpl::place_constrained_hclk_cells() // We create a new alias to represent this if (!placed) { auto new_alias = std::pair(constr_pair.second, -1); - bel_cell_map[option1].insert(new_alias); - bel_cell_map[option2].insert(new_alias); + for (auto option : options) + bel_cell_map[option].insert(new_alias); alias_cells.push_back(new_alias); true_clkdivs[constr_pair.second] = new_alias; } @@ -457,12 +466,14 @@ void GowinImpl::place_constrained_hclk_cells() for (auto cell_alias : alias_cells) { auto ci = ctx->cells.at(cell_alias.first).get(); - if (final_placement.find(cell_alias) == final_placement.end()) + if (final_placement.find(cell_alias) == final_placement.end() && ctx->debug) if (ci->type == id_CLKDIV2 || ci->type == id_CLKDIV) - log_error("Unable to place HCLK cell %s; no BELs available to implement cell type %s\n", - ci->name.c_str(ctx), ci->type.c_str(ctx)); + log_info("Custom HCLK Placer: Unable to place HCLK cell %s; no BELs available to implement cell type " + "%s\n", + ci->name.c_str(ctx), ci->type.c_str(ctx)); else - log_error("Unable to route HCLK signal from %s to IOLOGIC\n", ci->name.c_str(ctx)); + log_info("Custom HCLK Placer: Unable to guarantee route for HCLK signal from %s to IOLOGIC\n", + ci->name.c_str(ctx)); else { auto placement = final_placement[cell_alias]; diff --git a/himbaechel/uarch/gowin/gowin.h b/himbaechel/uarch/gowin/gowin.h index 4cbd53fd..f12da324 100644 --- a/himbaechel/uarch/gowin/gowin.h +++ b/himbaechel/uarch/gowin/gowin.h @@ -70,7 +70,7 @@ inline bool is_clkdiv(const CellInfo *cell) { return type_is_clkdiv(cell->type); inline bool type_is_clkdiv2(IdString cell_type) { return cell_type == id_CLKDIV2; } inline bool is_clkdiv2(const CellInfo *cell) { return type_is_clkdiv2(cell->type); } -// Return true for HCLK BELs +// Return true for HCLK Cells inline bool is_hclk(const CellInfo *cell) { return type_is_clkdiv2(cell->type) || type_is_clkdiv(cell->type); } // ==========================================