From 490dddf636bc50945ee6e6858f7c1942faa3aaf5 Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Sun, 5 Jun 2022 16:59:06 +0200 Subject: WIP shadowram --- gowin/arch.cc | 36 +++++++++++++++++++++++ gowin/arch.h | 2 ++ gowin/cells.cc | 33 ++++++++++++++++++++++ gowin/cells.h | 8 ++++++ gowin/constids.inc | 13 +++++++++ gowin/pack.cc | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 175 insertions(+) (limited to 'gowin') diff --git a/gowin/arch.cc b/gowin/arch.cc index 4fc2cd43..d554bd64 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -791,6 +791,39 @@ void Arch::read_cst(std::istream &in) settings[id_cst] = 1; } +void Arch::addShadowRamBels(const DatabasePOD *db, int row, int col) +{ + IdString belname, bel_id; + char buf[32]; + snprintf(buf, 32, "R%dC%d_RAMW", row + 1, col + 1); + belname = id(buf); + addBel(belname, id_RAMW, Loc(col, row, BelZ::lutram_0_z), false); + + snprintf(buf, 32, "R%dC%d_A%d", row + 1, col + 1, 4); + addBelInput(belname, id_A4, id(buf)); + snprintf(buf, 32, "R%dC%d_B%d", row + 1, col + 1, 4); + addBelInput(belname, id_B4, id(buf)); + snprintf(buf, 32, "R%dC%d_C%d", row + 1, col + 1, 4); + addBelInput(belname, id_C4, id(buf)); + snprintf(buf, 32, "R%dC%d_D%d", row + 1, col + 1, 4); + addBelInput(belname, id_D4, id(buf)); + + snprintf(buf, 32, "R%dC%d_A%d", row + 1, col + 1, 5); + addBelInput(belname, id_A5, id(buf)); + snprintf(buf, 32, "R%dC%d_B%d", row + 1, col + 1, 5); + addBelInput(belname, id_B5, id(buf)); + snprintf(buf, 32, "R%dC%d_C%d", row + 1, col + 1, 5); + addBelInput(belname, id_C5, id(buf)); + snprintf(buf, 32, "R%dC%d_D%d", row + 1, col + 1, 5); + addBelInput(belname, id_D5, id(buf)); + + snprintf(buf, 32, "R%dC%d_CLK%d", row + 1, col + 1, 2); + addBelInput(belname, id_CLK, id(buf)); + snprintf(buf, 32, "R%dC%d_LSR%d", row + 1, col + 1, 2); + addBelInput(belname, id_LSR, id(buf)); +} + + // Add all MUXes for the cell void Arch::addMuxBels(const DatabasePOD *db, int row, int col) { @@ -1112,6 +1145,9 @@ Arch::Arch(ArchArgs args) : args(args) if (z == 0) { addMuxBels(db, row, col); } + if (z == 4) { + addShadowRamBels(db, row, col); + } if (z % 2 == 0) { snprintf(buf, 32, "R%dC%d_LUT_GRP%d", row + 1, col + 1, z); grpname = id(buf); diff --git a/gowin/arch.h b/gowin/arch.h index 14181d79..80f887bb 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -344,6 +344,7 @@ struct Arch : BaseArch DelayQuad getWireTypeDelay(IdString wire); void read_cst(std::istream &in); void addMuxBels(const DatabasePOD *db, int row, int col); + void addShadowRamBels(const DatabasePOD *db, int row, int col); // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. @@ -485,6 +486,7 @@ enum { mux_0_z = 10, // start Z for the MUX2LUT5 bels iologic_0_z = 20, // start Z for the IOLOGIC bels + lutram_0_z = 30, // start Z for the IOLOGIC bels vcc_0_z = 277, // virtual VCC bel Z gnd_0_z = 278, // virtual VSS bel Z osc_z = 280 // Z for the oscillator bels diff --git a/gowin/cells.cc b/gowin/cells.cc index c3b21782..8285dc4e 100644 --- a/gowin/cells.cc +++ b/gowin/cells.cc @@ -166,4 +166,37 @@ void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool &to } } +void sram_to_ramw_split(Context *ctx, CellInfo *ram, CellInfo *ramw) +{ + if (ramw->hierpath == IdString()) + ramw->hierpath = ramw->hierpath; + ram->movePortTo(ctx->id("WAD[0]"), ramw, id_A4); + ram->movePortTo(ctx->id("WAD[1]"), ramw, id_B4); + ram->movePortTo(ctx->id("WAD[2]"), ramw, id_C4); + ram->movePortTo(ctx->id("WAD[3]"), ramw, id_D4); + + ram->movePortTo(ctx->id("DI[0]"), ramw, id_A5); + ram->movePortTo(ctx->id("DI[1]"), ramw, id_B5); + ram->movePortTo(ctx->id("DI[2]"), ramw, id_C5); + ram->movePortTo(ctx->id("DI[3]"), ramw, id_D5); + + ram->movePortTo(ctx->id("CLK"), ramw, id_CLK); + ram->movePortTo(ctx->id("WRE"), ramw, id_LSR); +} + +void sram_to_slice(Context *ctx, CellInfo *ram, CellInfo *slice, int index) +{ + char buf1[32]; + if (slice->hierpath == IdString()) + slice->hierpath = slice->hierpath; + + snprintf(buf1, 32, "DO[%d]", index); + ram->movePortTo(ctx->id(buf1), slice, id_F); + + ram->copyPortTo(ctx->id("RAD[0]"), slice, id_A); + ram->copyPortTo(ctx->id("RAD[1]"), slice, id_B); + ram->copyPortTo(ctx->id("RAD[2]"), slice, id_C); + ram->copyPortTo(ctx->id("RAD[3]"), slice, id_D); +} + NEXTPNR_NAMESPACE_END diff --git a/gowin/cells.h b/gowin/cells.h index 8f0636b8..b6d86497 100644 --- a/gowin/cells.h +++ b/gowin/cells.h @@ -111,6 +111,8 @@ inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SLICE; } +inline bool is_sram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_RAM16SDP4; } + // Convert a LUT primitive to (part of) an GENERIC_SLICE, swapping ports // as needed. Set no_dff if a DFF is not being used, so that the output // can be reconnected @@ -125,6 +127,12 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l // Convert a Gowin IO buffer to a IOB bel void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool &todelete_cells); +// Convert RAM16 to write port +void sram_to_ramw_split(Context *ctx, CellInfo *ram, CellInfo *ramw); + +// Convert RAM16 to slice +void sram_to_slice(Context *ctx, CellInfo *ram, CellInfo *slice, int index); + NEXTPNR_NAMESPACE_END #endif diff --git a/gowin/constids.inc b/gowin/constids.inc index 3691c506..d9ca1f0c 100644 --- a/gowin/constids.inc +++ b/gowin/constids.inc @@ -748,6 +748,19 @@ X(DFFNPE) X(DFFNC) X(DFFNCE) +// Shadow RAM +X(RAMW) +X(RAM16SDP4) +X(WADA) +X(WADB) +X(WADC) +X(WADD) +X(DIA) +X(DIB) +X(DIC) +X(DID) +X(WRE) + // IOB types X(IBUF) X(OBUF) diff --git a/gowin/pack.cc b/gowin/pack.cc index 4adfec1a..fa88772a 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -692,6 +692,89 @@ static void pack_gsr(Context *ctx) } } +// Pack shadow RAM +void pack_sram(Context *ctx) +{ + pool packed_cells; + std::vector> new_cells; + + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + if (is_sram(ctx, ci)) { + + // Create RAMW slice + std::unique_ptr ramw_slice = + create_generic_cell(ctx, id_RAMW, ci->name.str(ctx) + "$RAMW_SLICE"); + sram_to_ramw_split(ctx, ci, ramw_slice.get()); + + // Create actual RAM slices + std::unique_ptr ram_comb[4]; + for (int i = 0; i < 4; i++) { + ram_comb[i] = create_generic_cell(ctx, id_SLICE, + ci->name.str(ctx) + "$SRAM_SLICE" + std::to_string(i)); + sram_to_slice(ctx, ci, ram_comb[i].get(), i); + } + // Create 'block' SLICEs as a placement hint that these cells are mutually exclusive with the RAMW + std::unique_ptr ramw_block[2]; + for (int i = 0; i < 2; i++) { + ramw_block[i] = create_generic_cell(ctx, id_SLICE, + ci->name.str(ctx) + "$RAMW_BLOCK" + std::to_string(i)); + ramw_block[i]->params[id_FF_TYPE] = std::string("RAMW_BLOCK"); + } + + // Disconnect ports of original cell after packing + // ci->disconnectPort(id_WCK); + // ci->disconnectPort(id_WRE); + + for (int i = 0; i < 4; i++) + ci->disconnectPort(ctx->id(stringf("RAD[%d]", i))); + + // Setup placement constraints + // Use the 0th bit as an anchor + ram_comb[0]->constr_abs_z = true; + ram_comb[0]->constr_z = 0; + ram_comb[0]->cluster = ram_comb[0]->name; + for (int i = 1; i < 4; i++) { + ram_comb[i]->cluster = ram_comb[0]->name; + ram_comb[i]->constr_abs_z = true; + ram_comb[i]->constr_x = 0; + ram_comb[i]->constr_y = 0; + ram_comb[i]->constr_z = i; + ram_comb[0]->constr_children.push_back(ram_comb[i].get()); + } + for (int i = 0; i < 2; i++) { + ramw_block[i]->cluster = ram_comb[0]->name; + ramw_block[i]->constr_abs_z = true; + ramw_block[i]->constr_x = 0; + ramw_block[i]->constr_y = 0; + ramw_block[i]->constr_z = i + 4; + ram_comb[0]->constr_children.push_back(ramw_block[i].get()); + } + + ramw_slice->cluster = ram_comb[0]->name; + ramw_slice->constr_abs_z = true; + ramw_slice->constr_x = 0; + ramw_slice->constr_y = 0; + ramw_slice->constr_z = 4; + ram_comb[0]->constr_children.push_back(ramw_slice.get()); + + for (int i = 0; i < 4; i++) + new_cells.push_back(std::move(ram_comb[i])); + for (int i = 0; i < 2; i++) + new_cells.push_back(std::move(ramw_block[i])); + new_cells.push_back(std::move(ramw_slice)); + packed_cells.insert(ci->name); + } + } + for (auto pcell : packed_cells) { + ctx->cells.erase(pcell); + } + for (auto &ncell : new_cells) { + ctx->cells[ncell->name] = std::move(ncell); + } +} + + static bool is_nextpnr_iob(const Context *ctx, CellInfo *cell) { return cell->type == ctx->id("$nextpnr_ibuf") || cell->type == ctx->id("$nextpnr_obuf") || -- cgit v1.2.3 From de1bee9352c9f760cb21a35912c48ed2f830c023 Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Mon, 6 Jun 2022 14:35:33 +0200 Subject: lutram actually PnRs --- gowin/arch.cc | 64 ++++++++++++++++++++++++------------------------------ gowin/arch.h | 1 - gowin/cells.cc | 10 +++++++++ gowin/constids.inc | 1 + gowin/pack.cc | 5 ++++- 5 files changed, 43 insertions(+), 38 deletions(-) (limited to 'gowin') diff --git a/gowin/arch.cc b/gowin/arch.cc index d554bd64..cba492ab 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -791,39 +791,6 @@ void Arch::read_cst(std::istream &in) settings[id_cst] = 1; } -void Arch::addShadowRamBels(const DatabasePOD *db, int row, int col) -{ - IdString belname, bel_id; - char buf[32]; - snprintf(buf, 32, "R%dC%d_RAMW", row + 1, col + 1); - belname = id(buf); - addBel(belname, id_RAMW, Loc(col, row, BelZ::lutram_0_z), false); - - snprintf(buf, 32, "R%dC%d_A%d", row + 1, col + 1, 4); - addBelInput(belname, id_A4, id(buf)); - snprintf(buf, 32, "R%dC%d_B%d", row + 1, col + 1, 4); - addBelInput(belname, id_B4, id(buf)); - snprintf(buf, 32, "R%dC%d_C%d", row + 1, col + 1, 4); - addBelInput(belname, id_C4, id(buf)); - snprintf(buf, 32, "R%dC%d_D%d", row + 1, col + 1, 4); - addBelInput(belname, id_D4, id(buf)); - - snprintf(buf, 32, "R%dC%d_A%d", row + 1, col + 1, 5); - addBelInput(belname, id_A5, id(buf)); - snprintf(buf, 32, "R%dC%d_B%d", row + 1, col + 1, 5); - addBelInput(belname, id_B5, id(buf)); - snprintf(buf, 32, "R%dC%d_C%d", row + 1, col + 1, 5); - addBelInput(belname, id_C5, id(buf)); - snprintf(buf, 32, "R%dC%d_D%d", row + 1, col + 1, 5); - addBelInput(belname, id_D5, id(buf)); - - snprintf(buf, 32, "R%dC%d_CLK%d", row + 1, col + 1, 2); - addBelInput(belname, id_CLK, id(buf)); - snprintf(buf, 32, "R%dC%d_LSR%d", row + 1, col + 1, 2); - addBelInput(belname, id_LSR, id(buf)); -} - - // Add all MUXes for the cell void Arch::addMuxBels(const DatabasePOD *db, int row, int col) { @@ -1100,6 +1067,34 @@ Arch::Arch(ArchArgs args) : args(args) snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this)); addBelInput(belname, id_OSCEN, id(buf)); break; + case ID_RAM16: + snprintf(buf, 32, "R%dC%d_RAMW", row + 1, col + 1); + belname = id(buf); + addBel(belname, id_RAMW, Loc(col, row, BelZ::lutram_0_z), false); + + snprintf(buf, 32, "R%dC%d_A%d", row + 1, col + 1, 4); + addBelInput(belname, id_A4, id(buf)); + snprintf(buf, 32, "R%dC%d_B%d", row + 1, col + 1, 4); + addBelInput(belname, id_B4, id(buf)); + snprintf(buf, 32, "R%dC%d_C%d", row + 1, col + 1, 4); + addBelInput(belname, id_C4, id(buf)); + snprintf(buf, 32, "R%dC%d_D%d", row + 1, col + 1, 4); + addBelInput(belname, id_D4, id(buf)); + + snprintf(buf, 32, "R%dC%d_A%d", row + 1, col + 1, 5); + addBelInput(belname, id_A5, id(buf)); + snprintf(buf, 32, "R%dC%d_B%d", row + 1, col + 1, 5); + addBelInput(belname, id_B5, id(buf)); + snprintf(buf, 32, "R%dC%d_C%d", row + 1, col + 1, 5); + addBelInput(belname, id_C5, id(buf)); + snprintf(buf, 32, "R%dC%d_D%d", row + 1, col + 1, 5); + addBelInput(belname, id_D5, id(buf)); + + snprintf(buf, 32, "R%dC%d_CLK%d", row + 1, col + 1, 2); + addBelInput(belname, id_CLK, id(buf)); + snprintf(buf, 32, "R%dC%d_LSR%d", row + 1, col + 1, 2); + addBelInput(belname, id_LSR, id(buf)); + break; // fall through the ++ case ID_LUT7: z++; @@ -1145,9 +1140,6 @@ Arch::Arch(ArchArgs args) : args(args) if (z == 0) { addMuxBels(db, row, col); } - if (z == 4) { - addShadowRamBels(db, row, col); - } if (z % 2 == 0) { snprintf(buf, 32, "R%dC%d_LUT_GRP%d", row + 1, col + 1, z); grpname = id(buf); diff --git a/gowin/arch.h b/gowin/arch.h index 80f887bb..c13cdf09 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -344,7 +344,6 @@ struct Arch : BaseArch DelayQuad getWireTypeDelay(IdString wire); void read_cst(std::istream &in); void addMuxBels(const DatabasePOD *db, int row, int col); - void addShadowRamBels(const DatabasePOD *db, int row, int col); // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. diff --git a/gowin/cells.cc b/gowin/cells.cc index 8285dc4e..63ee71ed 100644 --- a/gowin/cells.cc +++ b/gowin/cells.cc @@ -48,6 +48,13 @@ std::unique_ptr create_generic_cell(Context *ctx, IdString type, std:: new_cell->addOutput(id_Q); new_cell->addInput(id_CE); new_cell->addInput(id_LSR); + } else if (type == id_RAMW) { + IdString names[8] = {id_A4, id_B4, id_C4, id_D4, id_A5, id_B5, id_C5, id_D5}; + for (int i = 0; i < 8; i++) { + new_cell->addInput(names[i]); + } + new_cell->addInput(id_CLK); + new_cell->addInput(id_LSR); } else if (type == id_GW_MUX2_LUT5 || type == id_GW_MUX2_LUT6 || type == id_GW_MUX2_LUT7 || type == id_GW_MUX2_LUT7 || type == id_GW_MUX2_LUT8) { new_cell->addInput(id_I0); @@ -190,6 +197,9 @@ void sram_to_slice(Context *ctx, CellInfo *ram, CellInfo *slice, int index) if (slice->hierpath == IdString()) slice->hierpath = slice->hierpath; + snprintf(buf1, 32, "INIT_%d", index); + slice->params[id_INIT] = ram->params[ctx->id(buf1)]; + snprintf(buf1, 32, "DO[%d]", index); ram->movePortTo(ctx->id(buf1), slice, id_F); diff --git a/gowin/constids.inc b/gowin/constids.inc index d9ca1f0c..0c788ecd 100644 --- a/gowin/constids.inc +++ b/gowin/constids.inc @@ -749,6 +749,7 @@ X(DFFNC) X(DFFNCE) // Shadow RAM +X(RAM16) X(RAMW) X(RAM16SDP4) X(WADA) diff --git a/gowin/pack.cc b/gowin/pack.cc index fa88772a..7d3a8e98 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -695,6 +695,8 @@ static void pack_gsr(Context *ctx) // Pack shadow RAM void pack_sram(Context *ctx) { + log_info("Packing Shadow RAM..\n"); + pool packed_cells; std::vector> new_cells; @@ -755,7 +757,7 @@ void pack_sram(Context *ctx) ramw_slice->constr_abs_z = true; ramw_slice->constr_x = 0; ramw_slice->constr_y = 0; - ramw_slice->constr_z = 4; + ramw_slice->constr_z = BelZ::lutram_0_z; ram_comb[0]->constr_children.push_back(ramw_slice.get()); for (int i = 0; i < 4; i++) @@ -1091,6 +1093,7 @@ bool Arch::pack() try { log_break(); pack_constants(ctx); + pack_sram(ctx); pack_gsr(ctx); pack_io(ctx); pack_diff_io(ctx); -- cgit v1.2.3 From b7992ec7724000f813ab053ac6042326f3795471 Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Thu, 16 Jun 2022 11:38:23 +0200 Subject: hook up CE maybe --- gowin/arch.cc | 2 ++ gowin/cells.cc | 1 + gowin/pack.cc | 1 + 3 files changed, 4 insertions(+) (limited to 'gowin') diff --git a/gowin/arch.cc b/gowin/arch.cc index cba492ab..65f15204 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -1094,6 +1094,8 @@ Arch::Arch(ArchArgs args) : args(args) addBelInput(belname, id_CLK, id(buf)); snprintf(buf, 32, "R%dC%d_LSR%d", row + 1, col + 1, 2); addBelInput(belname, id_LSR, id(buf)); + snprintf(buf, 32, "R%dC%d_CE%d", row + 1, col + 1, 2); + addBelInput(belname, id_CE, id(buf)); break; // fall through the ++ case ID_LUT7: diff --git a/gowin/cells.cc b/gowin/cells.cc index 63ee71ed..0dc0ce06 100644 --- a/gowin/cells.cc +++ b/gowin/cells.cc @@ -54,6 +54,7 @@ std::unique_ptr create_generic_cell(Context *ctx, IdString type, std:: new_cell->addInput(names[i]); } new_cell->addInput(id_CLK); + new_cell->addInput(id_CE); new_cell->addInput(id_LSR); } else if (type == id_GW_MUX2_LUT5 || type == id_GW_MUX2_LUT6 || type == id_GW_MUX2_LUT7 || type == id_GW_MUX2_LUT7 || type == id_GW_MUX2_LUT8) { diff --git a/gowin/pack.cc b/gowin/pack.cc index 7d3a8e98..0ba71705 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -708,6 +708,7 @@ void pack_sram(Context *ctx) std::unique_ptr ramw_slice = create_generic_cell(ctx, id_RAMW, ci->name.str(ctx) + "$RAMW_SLICE"); sram_to_ramw_split(ctx, ci, ramw_slice.get()); + ramw_slice->connectPort(id_CE, ctx->nets[ctx->id("$PACKER_VCC_NET")].get()); // Create actual RAM slices std::unique_ptr ram_comb[4]; -- cgit v1.2.3 From 6f56ad298c1a94259698cbd487f03efbd68f0342 Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Sat, 2 Jul 2022 20:44:59 +0200 Subject: use DFF RAM mode --- gowin/pack.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'gowin') diff --git a/gowin/pack.cc b/gowin/pack.cc index fbd2092f..9f4b54e2 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -715,6 +715,8 @@ void pack_sram(Context *ctx) for (int i = 0; i < 4; i++) { ram_comb[i] = create_generic_cell(ctx, id_SLICE, ci->name.str(ctx) + "$SRAM_SLICE" + std::to_string(i)); + ram_comb[i]->params[id_FF_USED] = 1; + ram_comb[i]->params[id_FF_TYPE] = std::string("RAM"); sram_to_slice(ctx, ci, ram_comb[i].get(), i); } // Create 'block' SLICEs as a placement hint that these cells are mutually exclusive with the RAMW @@ -722,7 +724,8 @@ void pack_sram(Context *ctx) for (int i = 0; i < 2; i++) { ramw_block[i] = create_generic_cell(ctx, id_SLICE, ci->name.str(ctx) + "$RAMW_BLOCK" + std::to_string(i)); - ramw_block[i]->params[id_FF_TYPE] = std::string("RAMW_BLOCK"); + ram_comb[i]->params[id_FF_USED] = 1; + ramw_block[i]->params[id_FF_TYPE] = std::string("RAM"); } // Disconnect ports of original cell after packing -- cgit v1.2.3