mirror of https://github.com/YosysHQ/nextpnr.git
gatemate: BRAM cascade mode support (#1487)
* BRAM cascade mode support * Removed unused connections * Exclusive connection
This commit is contained in:
parent
23a99989d1
commit
6c3956c3b9
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<std::pair<CellInfo *, CellInfo *>> rams;
|
||||
std::vector<std::pair<CellInfo *, CellInfo *>> rams_merged[2];
|
||||
std::map<CellInfo *, CellInfo *> 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));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue