From 17ca049efdade87b30a7c5901c90c5216c3d9e7c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 28 Aug 2025 15:11:21 +0200 Subject: [PATCH] gatemate: Split BRAMs into halfs --- himbaechel/uarch/gatemate/constids.inc | 342 +++++++++++++++++++++++++ himbaechel/uarch/gatemate/delay.cc | 6 +- himbaechel/uarch/gatemate/extra_data.h | 4 + himbaechel/uarch/gatemate/gatemate.cc | 8 + himbaechel/uarch/gatemate/pack.cc | 174 +++++++++++++ himbaechel/uarch/gatemate/pack.h | 2 +- himbaechel/uarch/gatemate/pack_bram.cc | 110 ++++---- 7 files changed, 597 insertions(+), 49 deletions(-) diff --git a/himbaechel/uarch/gatemate/constids.inc b/himbaechel/uarch/gatemate/constids.inc index 024e068f..b7caeec2 100644 --- a/himbaechel/uarch/gatemate/constids.inc +++ b/himbaechel/uarch/gatemate/constids.inc @@ -1751,6 +1751,346 @@ X(F_RSTN) //X(CLOCK3) //X(CLOCK4) +// hardware primitive RAM_HALF_U +X(RAM_HALF_U) +// RAM_HALF_U pins +//X(CLKA[0]) +//X(ENA[0]) +//X(GLWEA[0]) +//X(CLKB[0]) +//X(ENB[0]) +//X(GLWEB[0]) +//X(WEA[0]) +//X(WEA[1]) +//X(WEA[2]) +//X(WEA[3]) +//X(WEA[4]) +//X(WEA[5]) +//X(WEA[6]) +//X(WEA[7]) +//X(WEA[8]) +//X(WEA[9]) +//X(WEA[10]) +//X(WEA[11]) +//X(WEA[12]) +//X(WEA[13]) +//X(WEA[14]) +//X(WEA[15]) +//X(WEA[16]) +//X(WEA[17]) +//X(WEA[18]) +//X(WEA[19]) +//X(WEB[0]) +//X(WEB[1]) +//X(WEB[2]) +//X(WEB[3]) +//X(WEB[4]) +//X(WEB[5]) +//X(WEB[6]) +//X(WEB[7]) +//X(WEB[8]) +//X(WEB[9]) +//X(WEB[10]) +//X(WEB[11]) +//X(WEB[12]) +//X(WEB[13]) +//X(WEB[14]) +//X(WEB[15]) +//X(WEB[16]) +//X(WEB[17]) +//X(WEB[18]) +//X(WEB[19]) +//X(ADDRA0[0]) +//X(ADDRA0[1]) +//X(ADDRA0[2]) +//X(ADDRA0[3]) +//X(ADDRA0[4]) +//X(ADDRA0[5]) +//X(ADDRA0[6]) +//X(ADDRA0[7]) +//X(ADDRA0[8]) +//X(ADDRA0[9]) +//X(ADDRA0[10]) +//X(ADDRA0[11]) +//X(ADDRA0[12]) +//X(ADDRA0[13]) +//X(ADDRA0[14]) +//X(ADDRA0[15]) +//X(ADDRB0[0]) +//X(ADDRB0[1]) +//X(ADDRB0[2]) +//X(ADDRB0[3]) +//X(ADDRB0[4]) +//X(ADDRB0[5]) +//X(ADDRB0[6]) +//X(ADDRB0[7]) +//X(ADDRB0[8]) +//X(ADDRB0[9]) +//X(ADDRB0[10]) +//X(ADDRB0[11]) +//X(ADDRB0[12]) +//X(ADDRB0[13]) +//X(ADDRB0[14]) +//X(ADDRB0[15]) +//X(DIA[0]) +//X(DIA[1]) +//X(DIA[2]) +//X(DIA[3]) +//X(DIA[4]) +//X(DIA[5]) +//X(DIA[6]) +//X(DIA[7]) +//X(DIA[8]) +//X(DIA[9]) +//X(DIA[10]) +//X(DIA[11]) +//X(DIA[12]) +//X(DIA[13]) +//X(DIA[14]) +//X(DIA[15]) +//X(DIA[16]) +//X(DIA[17]) +//X(DIA[18]) +//X(DIA[19]) +//X(DIB[0]) +//X(DIB[1]) +//X(DIB[2]) +//X(DIB[3]) +//X(DIB[4]) +//X(DIB[5]) +//X(DIB[6]) +//X(DIB[7]) +//X(DIB[8]) +//X(DIB[9]) +//X(DIB[10]) +//X(DIB[11]) +//X(DIB[12]) +//X(DIB[13]) +//X(DIB[14]) +//X(DIB[15]) +//X(DIB[16]) +//X(DIB[17]) +//X(DIB[18]) +//X(DIB[19]) +//X(DOA[0]) +//X(DOA[1]) +//X(DOA[2]) +//X(DOA[3]) +//X(DOA[4]) +//X(DOA[5]) +//X(DOA[6]) +//X(DOA[7]) +//X(DOA[8]) +//X(DOA[9]) +//X(DOA[10]) +//X(DOA[11]) +//X(DOA[12]) +//X(DOA[13]) +//X(DOA[14]) +//X(DOA[15]) +//X(DOA[16]) +//X(DOA[17]) +//X(DOA[18]) +//X(DOA[19]) +//X(DOB[0]) +//X(DOB[1]) +//X(DOB[2]) +//X(DOB[3]) +//X(DOB[4]) +//X(DOB[5]) +//X(DOB[6]) +//X(DOB[7]) +//X(DOB[8]) +//X(DOB[9]) +//X(DOB[10]) +//X(DOB[11]) +//X(DOB[12]) +//X(DOB[13]) +//X(DOB[14]) +//X(DOB[15]) +//X(DOB[16]) +//X(DOB[17]) +//X(DOB[18]) +//X(DOB[19]) +//X(ECC1B_ERRA[0]) +//X(ECC1B_ERRB[0]) +//X(ECC2B_ERRA[0]) +//X(ECC2B_ERRB[0]) +//X(CLOCK1) +//X(CLOCK2) +//X(CLOCK3) +//X(CLOCK4) + +// hardware primitive RAM_HALF_L +X(RAM_HALF_L) +// RAM_HALF_L pins +//X(CLKA[0]) +//X(ENA[0]) +//X(GLWEA[0]) +//X(CLKB[0]) +//X(ENB[0]) +//X(GLWEB[0]) +//X(WEA[0]) +//X(WEA[1]) +//X(WEA[2]) +//X(WEA[3]) +//X(WEA[4]) +//X(WEA[5]) +//X(WEA[6]) +//X(WEA[7]) +//X(WEA[8]) +//X(WEA[9]) +//X(WEA[10]) +//X(WEA[11]) +//X(WEA[12]) +//X(WEA[13]) +//X(WEA[14]) +//X(WEA[15]) +//X(WEA[16]) +//X(WEA[17]) +//X(WEA[18]) +//X(WEA[19]) +//X(WEB[0]) +//X(WEB[1]) +//X(WEB[2]) +//X(WEB[3]) +//X(WEB[4]) +//X(WEB[5]) +//X(WEB[6]) +//X(WEB[7]) +//X(WEB[8]) +//X(WEB[9]) +//X(WEB[10]) +//X(WEB[11]) +//X(WEB[12]) +//X(WEB[13]) +//X(WEB[14]) +//X(WEB[15]) +//X(WEB[16]) +//X(WEB[17]) +//X(WEB[18]) +//X(WEB[19]) +//X(ADDRA0[0]) +//X(ADDRA0[1]) +//X(ADDRA0[2]) +//X(ADDRA0[3]) +//X(ADDRA0[4]) +//X(ADDRA0[5]) +//X(ADDRA0[6]) +//X(ADDRA0[7]) +//X(ADDRA0[8]) +//X(ADDRA0[9]) +//X(ADDRA0[10]) +//X(ADDRA0[11]) +//X(ADDRA0[12]) +//X(ADDRA0[13]) +//X(ADDRA0[14]) +//X(ADDRA0[15]) +//X(ADDRB0[0]) +//X(ADDRB0[1]) +//X(ADDRB0[2]) +//X(ADDRB0[3]) +//X(ADDRB0[4]) +//X(ADDRB0[5]) +//X(ADDRB0[6]) +//X(ADDRB0[7]) +//X(ADDRB0[8]) +//X(ADDRB0[9]) +//X(ADDRB0[10]) +//X(ADDRB0[11]) +//X(ADDRB0[12]) +//X(ADDRB0[13]) +//X(ADDRB0[14]) +//X(ADDRB0[15]) +//X(DIA[0]) +//X(DIA[1]) +//X(DIA[2]) +//X(DIA[3]) +//X(DIA[4]) +//X(DIA[5]) +//X(DIA[6]) +//X(DIA[7]) +//X(DIA[8]) +//X(DIA[9]) +//X(DIA[10]) +//X(DIA[11]) +//X(DIA[12]) +//X(DIA[13]) +//X(DIA[14]) +//X(DIA[15]) +//X(DIA[16]) +//X(DIA[17]) +//X(DIA[18]) +//X(DIA[19]) +//X(DIB[0]) +//X(DIB[1]) +//X(DIB[2]) +//X(DIB[3]) +//X(DIB[4]) +//X(DIB[5]) +//X(DIB[6]) +//X(DIB[7]) +//X(DIB[8]) +//X(DIB[9]) +//X(DIB[10]) +//X(DIB[11]) +//X(DIB[12]) +//X(DIB[13]) +//X(DIB[14]) +//X(DIB[15]) +//X(DIB[16]) +//X(DIB[17]) +//X(DIB[18]) +//X(DIB[19]) +//X(DOA[0]) +//X(DOA[1]) +//X(DOA[2]) +//X(DOA[3]) +//X(DOA[4]) +//X(DOA[5]) +//X(DOA[6]) +//X(DOA[7]) +//X(DOA[8]) +//X(DOA[9]) +//X(DOA[10]) +//X(DOA[11]) +//X(DOA[12]) +//X(DOA[13]) +//X(DOA[14]) +//X(DOA[15]) +//X(DOA[16]) +//X(DOA[17]) +//X(DOA[18]) +//X(DOA[19]) +//X(DOB[0]) +//X(DOB[1]) +//X(DOB[2]) +//X(DOB[3]) +//X(DOB[4]) +//X(DOB[5]) +//X(DOB[6]) +//X(DOB[7]) +//X(DOB[8]) +//X(DOB[9]) +//X(DOB[10]) +//X(DOB[11]) +//X(DOB[12]) +//X(DOB[13]) +//X(DOB[14]) +//X(DOB[15]) +//X(DOB[16]) +//X(DOB[17]) +//X(DOB[18]) +//X(DOB[19]) +//X(ECC1B_ERRA[0]) +//X(ECC1B_ERRB[0]) +//X(ECC2B_ERRA[0]) +//X(ECC2B_ERRB[0]) +//X(CLOCK1) +//X(CLOCK2) +//X(CLOCK3) +//X(CLOCK4) + // hardware primitive SERDES X(SERDES) // SERDES pins @@ -2283,6 +2623,8 @@ X(L2T4_UPPER) X(CPE_MX8) X(CPE_BRIDGE) X(MULT_INVERT) +X(RAM_HALF) +X(RAM_HALF_DUMMY) // Timing X(timing_ADDF2x_IN5_8_comb2) diff --git a/himbaechel/uarch/gatemate/delay.cc b/himbaechel/uarch/gatemate/delay.cc index 1334914e..e1dcb7e7 100644 --- a/himbaechel/uarch/gatemate/delay.cc +++ b/himbaechel/uarch/gatemate/delay.cc @@ -153,7 +153,7 @@ bool GateMateImpl::getCellDelay(const CellInfo *cell, IdString fromPort, IdStrin return get_delay_from_tmg_db(ctx->idf("timing_clkin_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); } else if (cell->type.in(id_GLBOUT)) { return get_delay_from_tmg_db(ctx->idf("timing_glbout_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); - } else if (cell->type.in(id_RAM)) { + } else if (cell->type.in(id_RAM, id_RAM_HALF)) { return false; } return false; @@ -257,7 +257,7 @@ TimingPortClass GateMateImpl::getPortTimingClass(const CellInfo *cell, IdString if (port.in(id_CLK)) return TMG_CLOCK_INPUT; return TMG_IGNORE; - } else if (cell->type == id_RAM) { + } else if (cell->type.in(id_RAM,id_RAM_HALF)) { std::string name = port.str(ctx); if (boost::starts_with(name, "CLKA[") || boost::starts_with(name, "CLKB[") || boost::starts_with(name, "CLOCK")) return TMG_CLOCK_INPUT; @@ -326,7 +326,7 @@ TimingClockingInfo GateMateImpl::getPortClockingInfo(const CellInfo *cell, IdStr get_delay_from_tmg_db(id_timing_del_CPE_CP_Q, delay); info.clockToQ += delay; } - } else if (cell->type == id_RAM) { + } else if (cell->type.in(id_RAM,id_RAM_HALF)) { std::string name = port.str(ctx); if (boost::starts_with(name, "CLOCK")) get_delay_from_tmg_db(id_timing_RAM_NOECC_IOPATH_1, info.clockToQ); diff --git a/himbaechel/uarch/gatemate/extra_data.h b/himbaechel/uarch/gatemate/extra_data.h index 9252a389..59aeabcb 100644 --- a/himbaechel/uarch/gatemate/extra_data.h +++ b/himbaechel/uarch/gatemate/extra_data.h @@ -103,6 +103,10 @@ enum CPE_Z CPE_COMP_Z = 6, CPE_CPLINES_Z = 7, CPE_LT_FULL_Z = 8, + + RAM_FULL_Z = 10, + RAM_HALF_U_Z = 11, + RAM_HALF_L_Z = 12, }; enum ClusterPlacement diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 647b11cc..c397e0a2 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -327,6 +327,8 @@ IdString GateMateImpl::getBelBucketForCellType(IdString cell_type) const return id_CPE_FF; else if (cell_type.in(id_CPE_RAMIO, id_CPE_RAMI, id_CPE_RAMO)) return id_CPE_RAMIO; + else if (cell_type.in(id_RAM_HALF, id_RAM_HALF_DUMMY)) + return id_RAM_HALF; else return cell_type; } @@ -340,6 +342,8 @@ BelBucketId GateMateImpl::getBelBucketForBel(BelId bel) const return id_CPE_FF; else if (bel_type.in(id_CPE_RAMIO_U, id_CPE_RAMIO_L)) return id_CPE_RAMIO; + else if (bel_type.in(id_RAM_HALF_U, id_RAM_HALF_L)) + return id_RAM_HALF; return bel_type; } @@ -359,6 +363,10 @@ bool GateMateImpl::isValidBelForCellType(IdString cell_type, BelId bel) const return cell_type.in(id_CPE_FF_L, id_CPE_FF, id_CPE_LATCH); else if (bel_type.in(id_CPE_RAMIO_U, id_CPE_RAMIO_L)) return cell_type.in(id_CPE_RAMIO, id_CPE_RAMI, id_CPE_RAMO); + else if (bel_type == id_RAM_HALF_U) + return cell_type.in(id_RAM_HALF, id_RAM_HALF_DUMMY); + else if (bel_type == id_RAM_HALF_L) + return cell_type.in(id_RAM_HALF, id_RAM_HALF_DUMMY); else return (bel_type == cell_type); } diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index f2caef1d..19396946 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -293,8 +293,182 @@ void GateMatePacker::rename_param(CellInfo *cell, IdString name, IdString new_na } } +static void rename_or_move(CellInfo *main, CellInfo *other, IdString port, IdString other_port) +{ + if (main == other) + main->renamePort(port, other_port); + else + main->movePortTo(port, other, other_port); +} + void GateMatePacker::repack() { + log_info("Repacking RAMs..\n"); + dict> rams; + for (auto &cell : ctx->cells) { + if (cell.second->type.in(id_RAM_HALF)) { + Loc l = ctx->getBelLocation(cell.second->bel); + if (l.z == RAM_HALF_U_Z) { + rams[Loc(l.x,l.y,0)].first = cell.second.get(); + } else { + rams[Loc(l.x,l.y-8,0)].second = cell.second.get(); + } + } else if (cell.second->type.in(id_RAM_HALF_DUMMY)) + packed_cells.insert(cell.second->name); + + } + int id = 0; + for (auto &ram : rams) { + IdString name = ctx->idf("ram$merged$id%d",id); + /*if (!ram.second.first) + name = ram.second.second->name; + if (!ram.second.second) + name = ram.second.first->name;*/ + + CellInfo *cell = ctx->createCell(name, id_RAM); + BelId bel = ctx->getBelByLocation({ram.first.x, ram.first.y, RAM_FULL_Z}); + ctx->bindBel(bel, cell, PlaceStrength::STRENGTH_FIXED); + //ram.first. + if (ram.second.first) { + rename_or_move(ram.second.first, cell, ctx->idf("CLKA[0]"), ctx->idf("CLKA[0]")); + rename_or_move(ram.second.first, cell, ctx->idf("CLKB[0]"), ctx->idf("CLKB[0]")); + rename_or_move(ram.second.first, cell, ctx->idf("ENA[0]"), ctx->idf("ENA[0]")); + rename_or_move(ram.second.first, cell, ctx->idf("ENB[0]"), ctx->idf("ENB[0]")); + rename_or_move(ram.second.first, cell, ctx->idf("GLWEA[0]"), ctx->idf("GLWEA[0]")); + rename_or_move(ram.second.first, cell, ctx->idf("GLWEB[0]"), ctx->idf("GLWEB[0]")); + for (int i = 0; i < 20; i++) { + rename_or_move(ram.second.first, cell, ctx->idf("WEA[%d]", i), ctx->idf("WEA[%d]", i)); + rename_or_move(ram.second.first, cell, ctx->idf("WEB[%d]", i), ctx->idf("WEB[%d]", i)); + rename_or_move(ram.second.first, cell, ctx->idf("DIA[%d]", i), ctx->idf("DIA[%d]", i)); + rename_or_move(ram.second.first, cell, ctx->idf("DIB[%d]", i), ctx->idf("DIB[%d]", i)); + rename_or_move(ram.second.first, cell, ctx->idf("DOA[%d]", i), ctx->idf("DOA[%d]", i)); + rename_or_move(ram.second.first, cell, ctx->idf("DOB[%d]", i), ctx->idf("DOB[%d]", i)); + } + for (int i = 0; i < 16; i++) { + rename_or_move(ram.second.first, cell, ctx->idf("ADDRA0[%d]", i), ctx->idf("ADDRA0[%d]", i)); + rename_or_move(ram.second.first, cell, ctx->idf("ADDRB0[%d]", i), ctx->idf("ADDRB0[%d]", i)); + } + + cell->params[id_RAM_cfg_forward_a0_clk] = ram.second.first->params[id_RAM_cfg_forward_a0_clk]; + cell->params[id_RAM_cfg_forward_b0_clk] = ram.second.first->params[id_RAM_cfg_forward_b0_clk]; + + cell->params[id_RAM_cfg_forward_a0_en] = ram.second.first->params[id_RAM_cfg_forward_a0_en]; + cell->params[id_RAM_cfg_forward_b0_en] = ram.second.first->params[id_RAM_cfg_forward_b0_en]; + + cell->params[id_RAM_cfg_forward_a0_we] = ram.second.first->params[id_RAM_cfg_forward_a0_we]; + cell->params[id_RAM_cfg_forward_b0_we] = ram.second.first->params[id_RAM_cfg_forward_b0_we]; + + cell->params[id_RAM_cfg_input_config_a0] = ram.second.first->params[id_RAM_cfg_input_config_a0]; + cell->params[id_RAM_cfg_input_config_b0] = ram.second.first->params[id_RAM_cfg_input_config_b0]; + cell->params[id_RAM_cfg_output_config_a0] = ram.second.first->params[id_RAM_cfg_output_config_a0]; + cell->params[id_RAM_cfg_output_config_b0] = ram.second.first->params[id_RAM_cfg_output_config_b0]; + + cell->params[id_RAM_cfg_a0_writemode] = ram.second.first->params[id_RAM_cfg_a0_writemode]; + cell->params[id_RAM_cfg_b0_writemode] = ram.second.first->params[id_RAM_cfg_b0_writemode]; + + cell->params[id_RAM_cfg_a0_set_outputreg] = ram.second.first->params[id_RAM_cfg_a0_set_outputreg]; + cell->params[id_RAM_cfg_b0_set_outputreg] = ram.second.first->params[id_RAM_cfg_b0_set_outputreg]; + + cell->params[id_RAM_cfg_inversion_a0] = ram.second.first->params[id_RAM_cfg_inversion_a0]; + cell->params[id_RAM_cfg_inversion_b0] = ram.second.first->params[id_RAM_cfg_inversion_b0]; + + cell->params[id_RAM_cfg_forward_a_addr] = ram.second.first->params[id_RAM_cfg_forward_a_addr]; + cell->params[id_RAM_cfg_forward_b_addr] = ram.second.first->params[id_RAM_cfg_forward_b_addr]; + cell->params[id_RAM_cfg_sram_mode] = ram.second.first->params[id_RAM_cfg_sram_mode]; + cell->params[id_RAM_cfg_ecc_enable] = ram.second.first->params[id_RAM_cfg_ecc_enable]; + cell->params[id_RAM_cfg_sram_delay] = ram.second.first->params[id_RAM_cfg_sram_delay]; + cell->params[id_RAM_cfg_cascade_enable] = ram.second.first->params[id_RAM_cfg_cascade_enable]; + + packed_cells.insert(ram.second.first->name); + } + if (ram.second.second) { + rename_or_move(ram.second.second, cell, ctx->idf("CLKA[0]"), ctx->idf("CLKA[2]")); + rename_or_move(ram.second.second, cell, ctx->idf("CLKB[0]"), ctx->idf("CLKB[2]")); + rename_or_move(ram.second.second, cell, ctx->idf("ENA[0]"), ctx->idf("ENA[2]")); + rename_or_move(ram.second.second, cell, ctx->idf("ENB[0]"), ctx->idf("ENB[2]")); + rename_or_move(ram.second.second, cell, ctx->idf("GLWEA[0]"), ctx->idf("GLWEA[2]")); + rename_or_move(ram.second.second, cell, ctx->idf("GLWEB[0]"), ctx->idf("GLWEB[2]")); + for (int i = 0; i < 20; i++) { + rename_or_move(ram.second.second, cell, ctx->idf("WEA[%d]", i), ctx->idf("WEA[%d]", i + 20)); + rename_or_move(ram.second.second, cell, ctx->idf("WEB[%d]", i), ctx->idf("WEB[%d]", i + 20)); + rename_or_move(ram.second.second, cell, ctx->idf("DIA[%d]", i), ctx->idf("DIA[%d]", i + 20)); + rename_or_move(ram.second.second, cell, ctx->idf("DIB[%d]", i), ctx->idf("DIB[%d]", i + 20)); + rename_or_move(ram.second.second, cell, ctx->idf("DOA[%d]", i), ctx->idf("DOA[%d]", i + 20)); + rename_or_move(ram.second.second, cell, ctx->idf("DOB[%d]", i), ctx->idf("DOB[%d]", i + 20)); + } + for (int i = 0; i < 16; i++) { + rename_or_move(ram.second.second, cell, ctx->idf("ADDRA0[%d]", i), ctx->idf("ADDRA1[%d]", i)); + rename_or_move(ram.second.second, cell, ctx->idf("ADDRB0[%d]", i), ctx->idf("ADDRB1[%d]", i)); + } + + cell->params[id_RAM_cfg_forward_a1_clk] = ram.second.second->params[id_RAM_cfg_forward_a0_clk]; + cell->params[id_RAM_cfg_forward_b1_clk] = ram.second.second->params[id_RAM_cfg_forward_b0_clk]; + + cell->params[id_RAM_cfg_forward_a1_en] = ram.second.second->params[id_RAM_cfg_forward_a0_en]; + cell->params[id_RAM_cfg_forward_b1_en] = ram.second.second->params[id_RAM_cfg_forward_b0_en]; + + cell->params[id_RAM_cfg_forward_a1_we] = ram.second.second->params[id_RAM_cfg_forward_a0_we]; + cell->params[id_RAM_cfg_forward_b1_we] = ram.second.second->params[id_RAM_cfg_forward_b0_we]; + + cell->params[id_RAM_cfg_input_config_a1] = ram.second.second->params[id_RAM_cfg_input_config_a0]; + cell->params[id_RAM_cfg_input_config_b1] = ram.second.second->params[id_RAM_cfg_input_config_b0]; + cell->params[id_RAM_cfg_output_config_a1] = ram.second.second->params[id_RAM_cfg_output_config_a0]; + cell->params[id_RAM_cfg_output_config_b1] = ram.second.second->params[id_RAM_cfg_output_config_b0]; + + cell->params[id_RAM_cfg_a1_writemode] = ram.second.second->params[id_RAM_cfg_a0_writemode]; + cell->params[id_RAM_cfg_b1_writemode] = ram.second.second->params[id_RAM_cfg_b0_writemode]; + + cell->params[id_RAM_cfg_a1_set_outputreg] = ram.second.second->params[id_RAM_cfg_a0_set_outputreg]; + cell->params[id_RAM_cfg_b1_set_outputreg] = ram.second.second->params[id_RAM_cfg_b0_set_outputreg]; + + cell->params[id_RAM_cfg_inversion_a1] = ram.second.second->params[id_RAM_cfg_inversion_a0]; + cell->params[id_RAM_cfg_inversion_b1] = ram.second.second->params[id_RAM_cfg_inversion_b0]; + + cell->params[id_RAM_cfg_forward_a_addr] = ram.second.second->params[id_RAM_cfg_forward_a_addr]; + cell->params[id_RAM_cfg_forward_b_addr] = ram.second.second->params[id_RAM_cfg_forward_b_addr]; + cell->params[id_RAM_cfg_sram_mode] = ram.second.second->params[id_RAM_cfg_sram_mode]; + cell->params[id_RAM_cfg_ecc_enable] = ram.second.second->params[id_RAM_cfg_ecc_enable]; + cell->params[id_RAM_cfg_sram_delay] = ram.second.second->params[id_RAM_cfg_sram_delay]; + cell->params[id_RAM_cfg_cascade_enable] = ram.second.second->params[id_RAM_cfg_cascade_enable]; + + packed_cells.insert(ram.second.second->name); + } + + for (int i = 63; i >= 0; i--) { + std::vector orig_first; + if (ram.second.first) + orig_first = ram.second.first->params.at(ctx->idf("INIT_%02X", i)).extract(0, 320).as_bits(); + std::vector orig_second; + if (ram.second.second) + orig_second = ram.second.second->params.at(ctx->idf("INIT_%02X", i)).extract(0, 320).as_bits(); + std::string init[2]; + + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 4; k++) { + for (int l = 0; l < 40; l++) { + if (ram.second.second) + init[j].push_back(orig_second.at(319 - (l + k * 40 + j * 160)) ? '1' : '0'); + else + init[j].push_back('0'); + } + for (int l = 0; l < 40; l++) { + if (ram.second.first) + init[j].push_back(orig_first.at(319 - (l + k * 40 + j * 160)) ? '1' : '0'); + else + init[j].push_back('0'); + } + } + } + cell->params[ctx->idf("INIT_%02X", i * 2 + 1)] = Property::from_string(init[0]); + cell->params[ctx->idf("INIT_%02X", i * 2 + 0)] = Property::from_string(init[1]); + } + + + id++; + } + flush_cells(); + ctx->assignArchInfo(); + log_info("Repacking CPEs..\n"); for (auto &cell : ctx->cells) { if (cell.second->type.in(id_CPE_L2T4)) { diff --git a/himbaechel/uarch/gatemate/pack.h b/himbaechel/uarch/gatemate/pack.h index b589563e..43514167 100644 --- a/himbaechel/uarch/gatemate/pack.h +++ b/himbaechel/uarch/gatemate/pack.h @@ -102,7 +102,7 @@ struct GateMatePacker // Cell creating CellInfo *create_cell_ptr(IdString type, IdString name); void flush_cells(); - void pack_ram_cell(CellInfo &ci, CellInfo *cell, int num, bool is_split); + void pack_ram_cell(CellInfo &ci, CellInfo *cell, bool is_split); void copy_constraint(NetInfo *in_net, NetInfo *out_net); pool packed_cells; diff --git a/himbaechel/uarch/gatemate/pack_bram.cc b/himbaechel/uarch/gatemate/pack_bram.cc index 80778d77..883171dc 100644 --- a/himbaechel/uarch/gatemate/pack_bram.cc +++ b/himbaechel/uarch/gatemate/pack_bram.cc @@ -118,7 +118,7 @@ static void rename_or_move(CellInfo *main, CellInfo *other, IdString port, IdStr main->movePortTo(port, other, other_port); } -void GateMatePacker::pack_ram_cell(CellInfo &ci, CellInfo *cell, int num, bool is_split) +void GateMatePacker::pack_ram_cell(CellInfo &ci, CellInfo *cell, bool is_split) { // Port Widths int a_rd_width = int_or_default(cell->params, id_A_RD_WIDTH, 0); @@ -161,7 +161,7 @@ void GateMatePacker::pack_ram_cell(CellInfo &ci, CellInfo *cell, int num, bool i uint8_t a_we = ram_ctrl_signal(cell, id_A_WE, false); uint8_t b_we = ram_ctrl_signal(cell, id_B_WE, false); - if (num) { + /*if (num) { ci.params[id_RAM_cfg_forward_a1_clk] = Property(cfg_a, 8); ci.params[id_RAM_cfg_forward_b1_clk] = Property(cfg_b, 8); @@ -184,37 +184,37 @@ void GateMatePacker::pack_ram_cell(CellInfo &ci, CellInfo *cell, int num, bool i ci.params[id_RAM_cfg_inversion_a1] = Property(a_inv, 3); ci.params[id_RAM_cfg_inversion_b1] = Property(b_inv, 3); - } else { - ci.params[id_RAM_cfg_forward_a0_clk] = Property(cfg_a, 8); - if (!is_split) - ci.params[id_RAM_cfg_forward_a1_clk] = Property(cfg_a, 8); + } else {*/ + ci.params[id_RAM_cfg_forward_a0_clk] = Property(cfg_a, 8); + if (!is_split) + ci.params[id_RAM_cfg_forward_a1_clk] = Property(cfg_a, 8); - ci.params[id_RAM_cfg_forward_b0_clk] = Property(cfg_b, 8); - if (!is_split) - ci.params[id_RAM_cfg_forward_b1_clk] = Property(cfg_b, 8); + ci.params[id_RAM_cfg_forward_b0_clk] = Property(cfg_b, 8); + if (!is_split) + ci.params[id_RAM_cfg_forward_b1_clk] = Property(cfg_b, 8); - ci.params[id_RAM_cfg_forward_a0_en] = Property(a_en, 8); - ci.params[id_RAM_cfg_forward_b0_en] = Property(b_en, 8); + ci.params[id_RAM_cfg_forward_a0_en] = Property(a_en, 8); + ci.params[id_RAM_cfg_forward_b0_en] = Property(b_en, 8); - ci.params[id_RAM_cfg_forward_a0_we] = Property(a_we, 8); - ci.params[id_RAM_cfg_forward_b0_we] = Property(b_we, 8); + ci.params[id_RAM_cfg_forward_a0_we] = Property(a_we, 8); + ci.params[id_RAM_cfg_forward_b0_we] = Property(b_we, 8); - ci.params[id_RAM_cfg_input_config_a0] = Property(width_to_config(a_wr_width), 3); - ci.params[id_RAM_cfg_input_config_b0] = Property(width_to_config(b_wr_width), 3); - ci.params[id_RAM_cfg_output_config_a0] = Property(width_to_config(a_rd_width), 3); - ci.params[id_RAM_cfg_output_config_b0] = Property(width_to_config(b_rd_width), 3); + ci.params[id_RAM_cfg_input_config_a0] = Property(width_to_config(a_wr_width), 3); + ci.params[id_RAM_cfg_input_config_b0] = Property(width_to_config(b_wr_width), 3); + ci.params[id_RAM_cfg_output_config_a0] = Property(width_to_config(a_rd_width), 3); + ci.params[id_RAM_cfg_output_config_b0] = Property(width_to_config(b_rd_width), 3); - ci.params[id_RAM_cfg_a0_writemode] = Property(a_wr_mode, 1); - ci.params[id_RAM_cfg_b0_writemode] = Property(b_wr_mode, 1); + ci.params[id_RAM_cfg_a0_writemode] = Property(a_wr_mode, 1); + ci.params[id_RAM_cfg_b0_writemode] = Property(b_wr_mode, 1); - ci.params[id_RAM_cfg_a0_set_outputreg] = Property(a_do_reg, 1); - ci.params[id_RAM_cfg_b0_set_outputreg] = Property(b_do_reg, 1); + ci.params[id_RAM_cfg_a0_set_outputreg] = Property(a_do_reg, 1); + ci.params[id_RAM_cfg_b0_set_outputreg] = Property(b_do_reg, 1); - ci.params[id_RAM_cfg_inversion_a0] = Property(a_inv, 3); - ci.params[id_RAM_cfg_inversion_b0] = Property(b_inv, 3); - } + ci.params[id_RAM_cfg_inversion_a0] = Property(a_inv, 3); + ci.params[id_RAM_cfg_inversion_b0] = Property(b_inv, 3); +// } - int index = (num == 0) ? 0 : 2; + int index = 0;//(num == 0) ? 0 : 2; rename_or_move(cell, &ci, id_A_CLK, ctx->idf("CLKA[%d]", index)); rename_or_move(cell, &ci, id_B_CLK, ctx->idf("CLKB[%d]", index)); rename_or_move(cell, &ci, id_A_EN, ctx->idf("ENA[%d]", index)); @@ -232,27 +232,26 @@ void GateMatePacker::pack_ram_cell(CellInfo &ci, CellInfo *cell, int num, bool i } int items = is_split ? 20 : 40; for (int i = 0; i < items; i++) { - rename_or_move(cell, &ci, ctx->idf("A_BM[%d]", i), ctx->idf("WEA[%d]", i + num * 20)); - rename_or_move(cell, &ci, ctx->idf("B_BM[%d]", i), ctx->idf("WEB[%d]", i + num * 20)); + rename_or_move(cell, &ci, ctx->idf("A_BM[%d]", i), ctx->idf("WEA[%d]", i)); + rename_or_move(cell, &ci, ctx->idf("B_BM[%d]", i), ctx->idf("WEB[%d]", i)); } for (int i = 0; i < 16; i++) { - rename_or_move(cell, &ci, ctx->idf("A_ADDR[%d]", i), ctx->idf("ADDRA%d[%d]", num, i)); - rename_or_move(cell, &ci, ctx->idf("B_ADDR[%d]", i), ctx->idf("ADDRB%d[%d]", num, i)); + rename_or_move(cell, &ci, ctx->idf("A_ADDR[%d]", i), ctx->idf("ADDRA0[%d]", i)); + rename_or_move(cell, &ci, ctx->idf("B_ADDR[%d]", i), ctx->idf("ADDRB0[%d]", i)); } for (int i = 0; i < items; i++) { - rename_or_move(cell, &ci, ctx->idf("A_DI[%d]", i), ctx->idf("DIA[%d]", i + num * 20)); - rename_or_move(cell, &ci, ctx->idf("A_DO[%d]", i), ctx->idf("DOA[%d]", i + num * 20)); - rename_or_move(cell, &ci, ctx->idf("B_DI[%d]", i), ctx->idf("DIB[%d]", i + num * 20)); - rename_or_move(cell, &ci, ctx->idf("B_DO[%d]", i), ctx->idf("DOB[%d]", i + num * 20)); + rename_or_move(cell, &ci, ctx->idf("A_DI[%d]", i), ctx->idf("DIA[%d]", i)); + rename_or_move(cell, &ci, ctx->idf("A_DO[%d]", i), ctx->idf("DOA[%d]", i)); + rename_or_move(cell, &ci, ctx->idf("B_DI[%d]", i), ctx->idf("DIB[%d]", i)); + rename_or_move(cell, &ci, ctx->idf("B_DO[%d]", i), ctx->idf("DOB[%d]", i)); } } void GateMatePacker::pack_ram() { - std::vector> rams; - std::vector> rams_merged[2]; + std::vector rams; std::map ram_cascade; log_info("Packing RAMs..\n"); for (auto &cell : ctx->cells) { @@ -276,8 +275,26 @@ void GateMatePacker::pack_ram() ci.disconnectPort(ctx->idf("B_BM[%d]", i)); } + if (!split) + { + ci.cluster = ci.name; + + CellInfo *cell = ctx->createCell(ctx->idf("%s$dummy$u", ci.name.c_str(ctx)), id_RAM_HALF_DUMMY); + ci.constr_children.push_back(cell); + cell->constr_abs_z = true; + cell->constr_z = RAM_HALF_U_Z; + cell->cluster = ci.name; + + cell = ctx->createCell(ctx->idf("%s$dummy$l", ci.name.c_str(ctx)), id_RAM_HALF_DUMMY); + ci.constr_children.push_back(cell); + cell->constr_abs_z = true; + cell->constr_y = +8; + cell->constr_z = RAM_HALF_L_Z; + cell->cluster = ci.name; + } + if (split) { - bool added = false; + /*bool added = false; if (!rams_merged[ram_mode].empty()) { auto &last = rams_merged[ram_mode].back(); if (last.second == nullptr) { @@ -288,6 +305,8 @@ void GateMatePacker::pack_ram() } if (!added) rams_merged[ram_mode].push_back(std::make_pair(&ci, nullptr)); + */ + rams.push_back(&ci); } else { CellInfo *upper = nullptr; CellInfo *lower = nullptr; @@ -316,18 +335,18 @@ void GateMatePacker::pack_ram() 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)); + rams.push_back(&ci); } } - rams.insert(rams.end(), rams_merged[0].begin(), rams_merged[0].end()); - rams.insert(rams.end(), rams_merged[1].begin(), rams_merged[1].end()); + //rams.insert(rams.end(), rams_merged[0].begin(), rams_merged[0].end()); + //rams.insert(rams.end(), rams_merged[1].begin(), rams_merged[1].end()); for (auto item : rams) { - CellInfo &ci = *item.first; + CellInfo &ci = *item; int split = ci.type.in(id_CC_BRAM_20K) ? 1 : 0; bool is_fifo = ci.type.in(id_CC_FIFO_40K); - ci.type = id_RAM; + ci.type = split ? id_RAM_HALF : id_RAM; ci.cluster = ci.name; // Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED @@ -373,10 +392,11 @@ void GateMatePacker::pack_ram() ci.params[id_RAM_cfg_sram_mode] = Property(ram_mode << 1 | split, 2); - pack_ram_cell(ci, item.first, 0, split); - if (item.second) { + pack_ram_cell(ci, item, split); + /*if (item.second) { pack_ram_cell(ci, item.second, 1, split); - } + }*/ + /* if (split) { for (int i = 63; i >= 0; i--) { std::vector orig_first = @@ -402,7 +422,7 @@ void GateMatePacker::pack_ram() ci.params[ctx->idf("INIT_%02X", i * 2 + 1)] = Property::from_string(init[0]); ci.params[ctx->idf("INIT_%02X", i * 2 + 0)] = Property::from_string(init[1]); } - } + }*/ if (is_fifo) { int a_rd_width = int_or_default(ci.params, id_A_WIDTH, 0);