diff --git a/himbaechel/uarch/gatemate/constids.inc b/himbaechel/uarch/gatemate/constids.inc index 17574961..91fd3ab3 100644 --- a/himbaechel/uarch/gatemate/constids.inc +++ b/himbaechel/uarch/gatemate/constids.inc @@ -1593,198 +1593,6 @@ X(F_RSTN) //X(FRD_ADDRX[14]) //X(FRD_ADDR[15]) //X(FRD_ADDRX[15]) -X(FORW_CAS_WRAO) -X(FORW_CAS_WRAI) -X(FORW_CAS_WRBO) -X(FORW_CAS_WRBI) -X(FORW_CAS_BMAO) -X(FORW_CAS_BMAI) -X(FORW_CAS_BMBO) -X(FORW_CAS_BMBI) -X(FORW_CAS_RDAO) -X(FORW_CAS_RDAI) -X(FORW_CAS_RDBO) -X(FORW_CAS_RDBI) -//X(FORW_UADDRAO[0]) -//X(FORW_UADDRAO[1]) -//X(FORW_UADDRAO[2]) -//X(FORW_UADDRAO[3]) -//X(FORW_UADDRAO[4]) -//X(FORW_UADDRAO[5]) -//X(FORW_UADDRAO[6]) -//X(FORW_UADDRAO[7]) -//X(FORW_UADDRAO[8]) -//X(FORW_UADDRAO[9]) -//X(FORW_UADDRAO[10]) -//X(FORW_UADDRAO[11]) -//X(FORW_UADDRAO[12]) -//X(FORW_UADDRAO[13]) -//X(FORW_UADDRAO[14]) -//X(FORW_UADDRAO[15]) -//X(FORW_LADDRAI[0]) -//X(FORW_LADDRAI[1]) -//X(FORW_LADDRAI[2]) -//X(FORW_LADDRAI[3]) -//X(FORW_LADDRAI[4]) -//X(FORW_LADDRAI[5]) -//X(FORW_LADDRAI[6]) -//X(FORW_LADDRAI[7]) -//X(FORW_LADDRAI[8]) -//X(FORW_LADDRAI[9]) -//X(FORW_LADDRAI[10]) -//X(FORW_LADDRAI[11]) -//X(FORW_LADDRAI[12]) -//X(FORW_LADDRAI[13]) -//X(FORW_LADDRAI[14]) -//X(FORW_LADDRAI[15]) -//X(FORW_LADDRAO[0]) -//X(FORW_LADDRAO[1]) -//X(FORW_LADDRAO[2]) -//X(FORW_LADDRAO[3]) -//X(FORW_LADDRAO[4]) -//X(FORW_LADDRAO[5]) -//X(FORW_LADDRAO[6]) -//X(FORW_LADDRAO[7]) -//X(FORW_LADDRAO[8]) -//X(FORW_LADDRAO[9]) -//X(FORW_LADDRAO[10]) -//X(FORW_LADDRAO[11]) -//X(FORW_LADDRAO[12]) -//X(FORW_LADDRAO[13]) -//X(FORW_LADDRAO[14]) -//X(FORW_LADDRAO[15]) -//X(FORW_UADDRAI[0]) -//X(FORW_UADDRAI[1]) -//X(FORW_UADDRAI[2]) -//X(FORW_UADDRAI[3]) -//X(FORW_UADDRAI[4]) -//X(FORW_UADDRAI[5]) -//X(FORW_UADDRAI[6]) -//X(FORW_UADDRAI[7]) -//X(FORW_UADDRAI[8]) -//X(FORW_UADDRAI[9]) -//X(FORW_UADDRAI[10]) -//X(FORW_UADDRAI[11]) -//X(FORW_UADDRAI[12]) -//X(FORW_UADDRAI[13]) -//X(FORW_UADDRAI[14]) -//X(FORW_UADDRAI[15]) -//X(FORW_UADDRBO[0]) -//X(FORW_UADDRBO[1]) -//X(FORW_UADDRBO[2]) -//X(FORW_UADDRBO[3]) -//X(FORW_UADDRBO[4]) -//X(FORW_UADDRBO[5]) -//X(FORW_UADDRBO[6]) -//X(FORW_UADDRBO[7]) -//X(FORW_UADDRBO[8]) -//X(FORW_UADDRBO[9]) -//X(FORW_UADDRBO[10]) -//X(FORW_UADDRBO[11]) -//X(FORW_UADDRBO[12]) -//X(FORW_UADDRBO[13]) -//X(FORW_UADDRBO[14]) -//X(FORW_UADDRBO[15]) -//X(FORW_LADDRBI[0]) -//X(FORW_LADDRBI[1]) -//X(FORW_LADDRBI[2]) -//X(FORW_LADDRBI[3]) -//X(FORW_LADDRBI[4]) -//X(FORW_LADDRBI[5]) -//X(FORW_LADDRBI[6]) -//X(FORW_LADDRBI[7]) -//X(FORW_LADDRBI[8]) -//X(FORW_LADDRBI[9]) -//X(FORW_LADDRBI[10]) -//X(FORW_LADDRBI[11]) -//X(FORW_LADDRBI[12]) -//X(FORW_LADDRBI[13]) -//X(FORW_LADDRBI[14]) -//X(FORW_LADDRBI[15]) -//X(FORW_LADDRBO[0]) -//X(FORW_LADDRBO[1]) -//X(FORW_LADDRBO[2]) -//X(FORW_LADDRBO[3]) -//X(FORW_LADDRBO[4]) -//X(FORW_LADDRBO[5]) -//X(FORW_LADDRBO[6]) -//X(FORW_LADDRBO[7]) -//X(FORW_LADDRBO[8]) -//X(FORW_LADDRBO[9]) -//X(FORW_LADDRBO[10]) -//X(FORW_LADDRBO[11]) -//X(FORW_LADDRBO[12]) -//X(FORW_LADDRBO[13]) -//X(FORW_LADDRBO[14]) -//X(FORW_LADDRBO[15]) -//X(FORW_UADDRBI[0]) -//X(FORW_UADDRBI[1]) -//X(FORW_UADDRBI[2]) -//X(FORW_UADDRBI[3]) -//X(FORW_UADDRBI[4]) -//X(FORW_UADDRBI[5]) -//X(FORW_UADDRBI[6]) -//X(FORW_UADDRBI[7]) -//X(FORW_UADDRBI[8]) -//X(FORW_UADDRBI[9]) -//X(FORW_UADDRBI[10]) -//X(FORW_UADDRBI[11]) -//X(FORW_UADDRBI[12]) -//X(FORW_UADDRBI[13]) -//X(FORW_UADDRBI[14]) -//X(FORW_UADDRBI[15]) -X(FORW_UA0CLKO) -X(FORW_LA0CLKI) -X(FORW_UA0ENO) -X(FORW_LA0ENI) -X(FORW_UA0WEO) -X(FORW_LA0WEI) -X(FORW_LA0CLKO) -X(FORW_UA0CLKI) -X(FORW_LA0ENO) -X(FORW_UA0ENI) -X(FORW_LA0WEO) -X(FORW_UA0WEI) -X(FORW_UA1CLKO) -X(FORW_LA1CLKI) -X(FORW_UA1ENO) -X(FORW_LA1ENI) -X(FORW_UA1WEO) -X(FORW_LA1WEI) -X(FORW_LA1CLKO) -X(FORW_UA1CLKI) -X(FORW_LA1ENO) -X(FORW_UA1ENI) -X(FORW_LA1WEO) -X(FORW_UA1WEI) -X(FORW_UB0CLKO) -X(FORW_LB0CLKI) -X(FORW_UB0ENO) -X(FORW_LB0ENI) -X(FORW_UB0WEO) -X(FORW_LB0WEI) -X(FORW_LB0CLKO) -X(FORW_UB0CLKI) -X(FORW_LB0ENO) -X(FORW_UB0ENI) -X(FORW_LB0WEO) -X(FORW_UB0WEI) -X(FORW_UB1CLKO) -X(FORW_LB1CLKI) -X(FORW_UB1ENO) -X(FORW_LB1ENI) -X(FORW_UB1WEO) -X(FORW_LB1WEI) -X(FORW_LB1CLKO) -X(FORW_UB1CLKI) -X(FORW_LB1ENO) -X(FORW_UB1ENI) -X(FORW_LB1WEO) -X(FORW_UB1WEI) -//X(CLOCK1) -//X(CLOCK2) -//X(CLOCK3) -//X(CLOCK4) // hardware primitive SERDES X(SERDES) diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 537dcd43..5523c1b3 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -128,6 +128,10 @@ bool GateMateImpl::getChildPlacement(const BaseClusterInfo *cluster, Loc root_lo child_loc.y = root_loc.y + child->constr_y; child_loc.z = child->constr_abs_z ? child->constr_z : (root_loc.z + child->constr_z); } + if (child_loc.x < 0 || child_loc.x >= ctx->getGridDimX()) + return false; + if (child_loc.y < 0 || child_loc.y >= ctx->getGridDimY()) + return false; BelId child_bel = ctx->getBelByLocation(child_loc); if (child_bel == BelId() || !this->isValidBelForCellType(child->type, child_bel)) return false; diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index 497aafd6..6714754a 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -55,7 +55,7 @@ CellInfo *GateMatePacker::move_ram_i(CellInfo *cell, IdString origPort, bool pla cpe_half = create_cell_ptr(id_CPE_HALF, ctx->idf("%s$%s_cpe_half", cell->name.c_str(ctx), origPort.c_str(ctx))); if (place) { cell->constr_children.push_back(cpe_half); - cpe_half->cluster = cell->name; + cpe_half->cluster = cell->cluster; cpe_half->constr_abs_z = false; cpe_half->constr_z = PLACE_DB_CONSTR + origPort.index; } @@ -77,7 +77,7 @@ CellInfo *GateMatePacker::move_ram_o(CellInfo *cell, IdString origPort, bool pla cpe_half = create_cell_ptr(id_CPE_HALF, ctx->idf("%s$%s_cpe_half", cell->name.c_str(ctx), origPort.c_str(ctx))); if (place) { cell->constr_children.push_back(cpe_half); - cpe_half->cluster = cell->name; + cpe_half->cluster = cell->cluster; cpe_half->constr_abs_z = false; cpe_half->constr_z = PLACE_DB_CONSTR + origPort.index; } @@ -133,7 +133,7 @@ CellInfo *GateMatePacker::move_ram_io(CellInfo *cell, IdString iPort, IdString o cpe_half = create_cell_ptr(id_CPE_HALF, ctx->idf("%s$%s_cpe_half", cell->name.c_str(ctx), oPort.c_str(ctx))); if (place) { cell->constr_children.push_back(cpe_half); - cpe_half->cluster = cell->name; + cpe_half->cluster = cell->cluster; cpe_half->constr_abs_z = false; cpe_half->constr_z = PLACE_DB_CONSTR + oPort.index; } diff --git a/himbaechel/uarch/gatemate/pack_bram.cc b/himbaechel/uarch/gatemate/pack_bram.cc index 78752703..f3e28914 100644 --- a/himbaechel/uarch/gatemate/pack_bram.cc +++ b/himbaechel/uarch/gatemate/pack_bram.cc @@ -17,6 +17,7 @@ * */ +#include "design_utils.h" #include "pack.h" #define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" @@ -24,6 +25,8 @@ NEXTPNR_NAMESPACE_BEGIN +inline bool is_bram_40k(const BaseCtx *ctx, const CellInfo *cell) { return cell->type.in(id_CC_BRAM_40K); } + uint8_t GateMatePacker::ram_ctrl_signal(CellInfo *cell, IdString port, bool alt) { NetInfo *net = cell->getPort(port); @@ -223,6 +226,7 @@ void GateMatePacker::pack_ram() { std::vector> rams; std::vector> rams_merged[2]; + std::map ram_cascade; for (auto &cell : ctx->cells) { CellInfo &ci = *cell.second; if (!ci.type.in(id_CC_BRAM_20K, id_CC_BRAM_40K, id_CC_FIFO_40K)) @@ -232,6 +236,9 @@ void GateMatePacker::pack_ram() if (ram_mode_str != "SDP" && ram_mode_str != "TDP") log_error("Unknown RAM_MODE parameter value '%s' for cell %s.\n", ram_mode_str.c_str(), ci.name.c_str(ctx)); int ram_mode = ram_mode_str == "SDP" ? 1 : 0; + std::string cas = str_or_default(ci.params, id_CAS, "NONE"); + if (cas != "NONE" && !ci.type.in(id_CC_BRAM_40K)) + log_error("Cascade feature only supported for CC_BRAM_40K.\n"); if (split) { bool added = false; if (!rams_merged[ram_mode].empty()) { @@ -245,6 +252,33 @@ void GateMatePacker::pack_ram() if (!added) rams_merged[ram_mode].push_back(std::make_pair(&ci, nullptr)); } else { + CellInfo *upper = nullptr; + CellInfo *lower = nullptr; + if (cas != "NONE" && ram_mode_str != "TDP") + log_error("Cascade feature only supported in TDP mode.\n"); + int a_rd_width = int_or_default(ci.params, id_A_WIDTH, 0); + int b_wr_width = int_or_default(ci.params, id_B_WIDTH, 0); + if (cas != "NONE" && (a_rd_width > 1 || b_wr_width > 1)) + log_error("Cascade feature only supported in 1 bit data width mode.\n"); + if (cas == "UPPER") { + if (!net_driven_by(ctx, ci.getPort(id_A_CI), is_bram_40k, id_A_CO)) + log_error("Port A_CI of '%s' must be driven by other CC_BRAM_40K.", ci.name.c_str(ctx)); + if (!net_driven_by(ctx, ci.getPort(id_B_CI), is_bram_40k, id_B_CO)) + log_error("Port B_CI of '%s' must be driven by other CC_BRAM_40K.", ci.name.c_str(ctx)); + upper = &ci; + lower = ci.getPort(id_A_CI)->driver.cell; + } else if (cas == "LOWER") { + if (!net_only_drives(ctx, ci.getPort(id_A_CO), is_bram_40k, id_A_CI, true)) + log_error("Port A_CO of '%s' must be driving one other CC_BRAM_40K.", ci.name.c_str(ctx)); + if (!net_only_drives(ctx, ci.getPort(id_B_CO), is_bram_40k, id_B_CI, true)) + log_error("Port B_CO of '%s' must be driving one other CC_BRAM_40K.", ci.name.c_str(ctx)); + upper = (*ci.getPort(id_A_CO)->users.begin()).cell; + lower = &ci; + } + if (ram_cascade.count(lower) && ram_cascade[lower] != upper) + log_error("RAM cell '%s' already cascaded to different RAM block.\n", ci.name.c_str(ctx)); + ram_cascade[lower] = upper; + rams.push_back(std::make_pair(&ci, nullptr)); } } @@ -264,12 +298,25 @@ void GateMatePacker::pack_ram() std::string cas = str_or_default(ci.params, id_CAS, "NONE"); int cascade = 0; + // Concepts of UPPER and LOWER are different in documentation if (cas == "NONE") { cascade = 0; } else if (cas == "UPPER") { - cascade = 1; - } else if (cas == "LOWER") { cascade = 2; + ci.disconnectPort(id_A_CI); + ci.disconnectPort(id_B_CI); + } else if (cas == "LOWER") { + cascade = 1; + ci.disconnectPort(id_A_CO); + ci.disconnectPort(id_B_CO); + if (!ram_cascade.count(&ci)) + log_error("Unable to find cascaded RAM for '%s'.\n", ci.name.c_str(ctx)); + CellInfo *upper = ram_cascade[&ci]; + ci.cluster = upper->name; + upper->constr_children.push_back(&ci); + ci.constr_abs_z = false; + ci.constr_y = -16; + ci.constr_z = 0; } else { log_error("Unknown CAS parameter value '%s' for cell %s.\n", cas.c_str(), ci.name.c_str(ctx)); }