From af6735bdf413d1b3663d085b573f2aaf3e018e44 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 21 Dec 2021 17:10:45 +0000 Subject: mistral: add M10K bel --- mistral/arch.cc | 3 +++ mistral/arch.h | 1 + mistral/constids.inc | 6 ++++- mistral/m10k.cc | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 mistral/m10k.cc diff --git a/mistral/arch.cc b/mistral/arch.cc index e79a3910..6ba16939 100644 --- a/mistral/arch.cc +++ b/mistral/arch.cc @@ -122,6 +122,9 @@ Arch::Arch(ArchArgs args) CycloneV::pos2y(hps_pos[CycloneV::I_HPS_MPU_GENERAL_PURPOSE])); } + for (auto m10k_pos : cyclonev->m10k_get_pos()) + create_m10k(CycloneV::pos2x(m10k_pos), CycloneV::pos2y(m10k_pos)); + // This import takes about 5s, perhaps long term we can speed it up, e.g. defer to Mistral more... log_info("Initialising routing graph...\n"); int pip_count = 0; diff --git a/mistral/arch.h b/mistral/arch.h index e17be331..8fcea291 100644 --- a/mistral/arch.h +++ b/mistral/arch.h @@ -467,6 +467,7 @@ struct Arch : BaseArch bool has_port(CycloneV::block_type_t bt, int x, int y, int bi, CycloneV::port_type_t port, int pi = -1) const; void create_lab(int x, int y, bool is_mlab); // lab.cc + void create_m10k(int x, int y); // m10k.cc void create_gpio(int x, int y); // io.cc void create_clkbuf(int x, int y); // globals.cc void create_control(int x, int y); // globals.cc diff --git a/mistral/constids.inc b/mistral/constids.inc index d241c8ef..82cd9ecc 100644 --- a/mistral/constids.inc +++ b/mistral/constids.inc @@ -98,10 +98,14 @@ X(WE_INV) X(cyclonev_oscillator) X(cyclonev_hps_interface_mpu_general_purpose) +X(MISTRAL_M10K) +X(ADDRSTALLA) +X(ADDRSTALLB) + X(clkout) X(clkout1) X(compress_rbf) X(oscena) X(placer) X(router) -X(step) +X(step) \ No newline at end of file diff --git a/mistral/m10k.cc b/mistral/m10k.cc new file mode 100644 index 00000000..4ab35096 --- /dev/null +++ b/mistral/m10k.cc @@ -0,0 +1,69 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2021 Lofty + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "nextpnr.h" +#include "util.h" + +NEXTPNR_NAMESPACE_BEGIN + +void Arch::create_m10k(int x, int y) +{ + BelId bel = add_bel(x, y, id_MISTRAL_M10K, id_MISTRAL_M10K); + add_bel_pin(bel, id_ADDRSTALLA, PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRSTALLA, 0)); + add_bel_pin(bel, id_ADDRSTALLB, PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRSTALLB, 0)); + for (int z = 0; z < 2; z++) { + add_bel_pin(bel, id(stringf("BYTEENABLEA[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::BYTEENABLEA, z)); + add_bel_pin(bel, id(stringf("BYTEENABLEB[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::BYTEENABLEB, z)); + add_bel_pin(bel, id(stringf("ACLR[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::ACLR, z)); + add_bel_pin(bel, id(stringf("RDEN[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::RDEN, z)); + add_bel_pin(bel, id(stringf("WREN[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::WREN, z)); + add_bel_pin(bel, id(stringf("CLKIN[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::CLKIN, z)); + add_bel_pin(bel, id(stringf("CLKIN[%d]", z+6)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::CLKIN, z+6)); + } + for (int z = 0; z < 4; z++) { + add_bel_pin(bel, id(stringf("ENABLE[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::ENABLE, 0)); + } + for (int z = 0; z < 12; z++) { + add_bel_pin(bel, id(stringf("ADDRA[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRA, z)); + add_bel_pin(bel, id(stringf("ADDRB[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRB, z)); + } + for (int z = 0; z < 20; z++) { + add_bel_pin(bel, id(stringf("DATAAIN[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::DATAAIN, z)); + add_bel_pin(bel, id(stringf("DATABIN[%d]", z)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::DATABIN, z)); + add_bel_pin(bel, id(stringf("DATAAOUT[%d]", z)), PORT_OUT, + get_port(CycloneV::M10K, x, y, -1, CycloneV::DATAAOUT, z)); + add_bel_pin(bel, id(stringf("DATABOUT[%d]", z)), PORT_OUT, + get_port(CycloneV::M10K, x, y, -1, CycloneV::DATABOUT, z)); + } +} + +NEXTPNR_NAMESPACE_END \ No newline at end of file -- cgit v1.2.3 From 33e031a2841de813cae420becd8ece4286e08e0a Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 21 Dec 2021 21:04:05 +0000 Subject: mistral: M10K cell function --- mistral/constids.inc | 4 ++- mistral/m10k.cc | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/mistral/constids.inc b/mistral/constids.inc index 82cd9ecc..e032bf53 100644 --- a/mistral/constids.inc +++ b/mistral/constids.inc @@ -101,6 +101,8 @@ X(cyclonev_hps_interface_mpu_general_purpose) X(MISTRAL_M10K) X(ADDRSTALLA) X(ADDRSTALLB) +X(CFG_ABITS) +X(CFG_DBITS) X(clkout) X(clkout1) @@ -108,4 +110,4 @@ X(compress_rbf) X(oscena) X(placer) X(router) -X(step) \ No newline at end of file +X(step) diff --git a/mistral/m10k.cc b/mistral/m10k.cc index 4ab35096..d6aa1ed2 100644 --- a/mistral/m10k.cc +++ b/mistral/m10k.cc @@ -46,7 +46,7 @@ void Arch::create_m10k(int x, int y) } for (int z = 0; z < 4; z++) { add_bel_pin(bel, id(stringf("ENABLE[%d]", z)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::ENABLE, 0)); + get_port(CycloneV::M10K, x, y, -1, CycloneV::ENABLE, z)); } for (int z = 0; z < 12; z++) { add_bel_pin(bel, id(stringf("ADDRA[%d]", z)), PORT_IN, @@ -66,4 +66,75 @@ void Arch::create_m10k(int x, int y) } } +static void assign_lab_pins(Context *ctx, CellInfo *cell) +{ + auto abits = cell->attrs[id_CFG_ABITS].as_int64(); + auto dbits = cell->attrs[id_CFG_DBITS].as_int64(); + NPNR_ASSERT(abits >= 7 && abits <= 13); + NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20); + + // Quartus doesn't seem to generate ADDRSTALL[AB], BYTEENABLE[AB][01]. + + // It *does* generate ACLR[01] but leaves them unconnected if unused. + + // Enables. + // RDEN[0] and WREN[1] are left unconnected. + cell->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("RDEN[1]")}; + cell->pin_data[ctx->id("B1EN")].bel_pins = {ctx->id("WREN[0]")}; + + // Clocks. + cell->pin_data[ctx->id("CLK1")].bel_pins = {ctx->id("CLKIN[0]")}; + + // Enables left unconnected. + + // Address lines. + int addr_offset = std::max(12 - std::max(abits, int64_t{9}), 0l); + int bit_offset = 0; + if (abits == 13) { + cell->pin_data[ctx->id("A1ADDR[0]")].bel_pins = {ctx->id("DATAAIN[4]")}; + cell->pin_data[ctx->id("B1ADDR[0]")].bel_pins = {ctx->id("DATABIN[19]")}; + bit_offset = 1; + } + for (int bit = bit_offset; bit < abits; bit++) { + cell->pin_data[ctx->id(stringf("A1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRA[%d]", bit + addr_offset))}; + cell->pin_data[ctx->id(stringf("B1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRB[%d]", bit + addr_offset))}; + } + + // Data lines + std::vector offsets; + offsets.push_back(0); + if (abits >= 10 && dbits <= 10) { + offsets.push_back(10); + } + if (abits >= 11 && dbits <= 5) { + offsets.push_back(5); + offsets.push_back(15); + } + if (abits >= 12 && dbits <= 2) { + offsets.push_back(2); + offsets.push_back(7); + offsets.push_back(12); + offsets.push_back(17); + } + if (abits == 13 && dbits == 1) { + offsets.push_back(1); + offsets.push_back(3); + offsets.push_back(6); + offsets.push_back(8); + offsets.push_back(11); + offsets.push_back(13); + offsets.push_back(16); + offsets.push_back(18); + } + for (int bit = 0; bit < dbits; bit++) { + for (int offset : offsets) { + cell->pin_data[ctx->id(stringf("A1DATA[%d]", bit))].bel_pins.push_back(ctx->id(stringf("DATAAIN[%d]", bit + offset))); + } + } + + for (int bit = 0; bit < dbits; bit++) { + cell->pin_data[ctx->id(stringf("B1DATA[%d]", bit))].bel_pins = {ctx->id(stringf("DATABOUT[%d]", bit))}; + } +} + NEXTPNR_NAMESPACE_END \ No newline at end of file -- cgit v1.2.3 From 34b7cdb5338dd25637b6b8491ea29ac38af0f5b7 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 21 Dec 2021 21:34:28 +0000 Subject: mistral: move M10K code to pack --- mistral/m10k.cc | 71 ---------------------------------------------------- mistral/pack.cc | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 71 deletions(-) diff --git a/mistral/m10k.cc b/mistral/m10k.cc index d6aa1ed2..6d51625e 100644 --- a/mistral/m10k.cc +++ b/mistral/m10k.cc @@ -66,75 +66,4 @@ void Arch::create_m10k(int x, int y) } } -static void assign_lab_pins(Context *ctx, CellInfo *cell) -{ - auto abits = cell->attrs[id_CFG_ABITS].as_int64(); - auto dbits = cell->attrs[id_CFG_DBITS].as_int64(); - NPNR_ASSERT(abits >= 7 && abits <= 13); - NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20); - - // Quartus doesn't seem to generate ADDRSTALL[AB], BYTEENABLE[AB][01]. - - // It *does* generate ACLR[01] but leaves them unconnected if unused. - - // Enables. - // RDEN[0] and WREN[1] are left unconnected. - cell->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("RDEN[1]")}; - cell->pin_data[ctx->id("B1EN")].bel_pins = {ctx->id("WREN[0]")}; - - // Clocks. - cell->pin_data[ctx->id("CLK1")].bel_pins = {ctx->id("CLKIN[0]")}; - - // Enables left unconnected. - - // Address lines. - int addr_offset = std::max(12 - std::max(abits, int64_t{9}), 0l); - int bit_offset = 0; - if (abits == 13) { - cell->pin_data[ctx->id("A1ADDR[0]")].bel_pins = {ctx->id("DATAAIN[4]")}; - cell->pin_data[ctx->id("B1ADDR[0]")].bel_pins = {ctx->id("DATABIN[19]")}; - bit_offset = 1; - } - for (int bit = bit_offset; bit < abits; bit++) { - cell->pin_data[ctx->id(stringf("A1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRA[%d]", bit + addr_offset))}; - cell->pin_data[ctx->id(stringf("B1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRB[%d]", bit + addr_offset))}; - } - - // Data lines - std::vector offsets; - offsets.push_back(0); - if (abits >= 10 && dbits <= 10) { - offsets.push_back(10); - } - if (abits >= 11 && dbits <= 5) { - offsets.push_back(5); - offsets.push_back(15); - } - if (abits >= 12 && dbits <= 2) { - offsets.push_back(2); - offsets.push_back(7); - offsets.push_back(12); - offsets.push_back(17); - } - if (abits == 13 && dbits == 1) { - offsets.push_back(1); - offsets.push_back(3); - offsets.push_back(6); - offsets.push_back(8); - offsets.push_back(11); - offsets.push_back(13); - offsets.push_back(16); - offsets.push_back(18); - } - for (int bit = 0; bit < dbits; bit++) { - for (int offset : offsets) { - cell->pin_data[ctx->id(stringf("A1DATA[%d]", bit))].bel_pins.push_back(ctx->id(stringf("DATAAIN[%d]", bit + offset))); - } - } - - for (int bit = 0; bit < dbits; bit++) { - cell->pin_data[ctx->id(stringf("B1DATA[%d]", bit))].bel_pins = {ctx->id(stringf("DATABOUT[%d]", bit))}; - } -} - NEXTPNR_NAMESPACE_END \ No newline at end of file diff --git a/mistral/pack.cc b/mistral/pack.cc index 703fa386..da1589f0 100644 --- a/mistral/pack.cc +++ b/mistral/pack.cc @@ -382,6 +382,83 @@ struct MistralPacker } } + void setup_m10ks() + { + for (auto& cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + if (ci->type != id_MISTRAL_M10K) + continue; + + auto abits = ci->attrs[id_CFG_ABITS].as_int64(); + auto dbits = ci->attrs[id_CFG_DBITS].as_int64(); + NPNR_ASSERT(abits >= 7 && abits <= 13); + NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20); + + // Quartus doesn't seem to generate ADDRSTALL[AB], BYTEENABLE[AB][01]. + + // It *does* generate ACLR[01] but leaves them unconnected if unused. + + // Enables. + // RDEN[0] and WREN[1] are left unconnected. + ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("RDEN[1]")}; + ci->pin_data[ctx->id("B1EN")].bel_pins = {ctx->id("WREN[0]")}; + + // Clocks. + ci->pin_data[ctx->id("CLK1")].bel_pins = {ctx->id("CLKIN[0]")}; + + // Enables left unconnected. + + // Address lines. + int addr_offset = std::max(12 - std::max(abits, int64_t{9}), 0l); + int bit_offset = 0; + if (abits == 13) { + ci->pin_data[ctx->id("A1ADDR[0]")].bel_pins = {ctx->id("DATAAIN[4]")}; + ci->pin_data[ctx->id("B1ADDR[0]")].bel_pins = {ctx->id("DATABIN[19]")}; + bit_offset = 1; + } + for (int bit = bit_offset; bit < abits; bit++) { + ci->pin_data[ctx->id(stringf("A1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRA[%d]", bit + addr_offset))}; + ci->pin_data[ctx->id(stringf("B1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRB[%d]", bit + addr_offset))}; + } + + // Data lines + std::vector offsets; + offsets.push_back(0); + if (abits >= 10 && dbits <= 10) { + offsets.push_back(10); + } + if (abits >= 11 && dbits <= 5) { + offsets.push_back(5); + offsets.push_back(15); + } + if (abits >= 12 && dbits <= 2) { + offsets.push_back(2); + offsets.push_back(7); + offsets.push_back(12); + offsets.push_back(17); + } + if (abits == 13 && dbits == 1) { + offsets.push_back(1); + offsets.push_back(3); + offsets.push_back(6); + offsets.push_back(8); + offsets.push_back(11); + offsets.push_back(13); + offsets.push_back(16); + offsets.push_back(18); + } + for (int bit = 0; bit < dbits; bit++) { + for (int offset : offsets) { + ci->pin_data[ctx->id(stringf("A1DATA[%d]", bit))].bel_pins.push_back(ctx->id(stringf("DATAAIN[%d]", bit + offset))); + } + } + + for (int bit = 0; bit < dbits; bit++) { + ci->pin_data[ctx->id(stringf("B1DATA[%d]", bit))].bel_pins = {ctx->id(stringf("DATABOUT[%d]", bit))}; + } + } + } + void run() { init_constant_nets(); -- cgit v1.2.3 From 78474a5dec13236214c8e15906c40a05ae6ed4af Mon Sep 17 00:00:00 2001 From: Lofty Date: Wed, 22 Dec 2021 12:01:24 +0000 Subject: mistral: preliminary bitstream info --- mistral/bitstream.cc | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc index 35c1303a..3490a3d7 100644 --- a/mistral/bitstream.cc +++ b/mistral/bitstream.cc @@ -118,6 +118,45 @@ struct MistralBitgen cv->bmux_m_set(CycloneV::CMUXHG, pos, CycloneV::TESTSYN_ENOUT_SELECT, bi, CycloneV::PRE_SYNENB); } + void write_m10k_cell(CellInfo* ci, int x, int y, int bi) + { + auto pos = CycloneV::xy2pos(x, y); + + // Notes: + // DATA_FLOW_THRU is probably transparent reads. + + cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::A_DATA_FLOW_THRU, bi, 1); + cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, ci->attrs[id_CFG_DBITS].as_int64()); + cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_FAST_WRITE, bi, CycloneV::FAST); + cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_OUTPUT_SEL, bi, CycloneV::REG); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SA_WREN_DELAY, bi, 1); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SAEN_DELAY, bi, 2); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WL_DELAY, bi, 2); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WR_TIMER_PULSE, bi, 0x0b); + + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_DATA_FLOW_THRU, bi, 1); + cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, ci->attrs[id_CFG_DBITS].as_int64()); + cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_FAST_WRITE, bi, CycloneV::FAST); + cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_OUTPUT_SEL, bi, CycloneV::REG); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SA_WREN_DELAY, bi, 1); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SAEN_DELAY, bi, 2); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_WL_DELAY, bi, 2); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_WR_TIMER_PULSE, bi, 0x0b); + + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::TOP_CLK_SEL, bi, 1); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::TOP_W_INV, bi, 1); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::TOP_W_SEL, bi, 1); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::BOT_CLK_INV, bi, 1); + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::BOT_W_SEL, bi, 1); + + cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TRUE_DUAL_PORT, bi, 1); + + cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::DISABLE_UNUSED, bi, 0); + + for (int bi = 0; bi < 256; bi++) + cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::RAM, bi, 0xffffffffff); + } + void write_cells() { for (auto &cell : ctx->cells) { @@ -128,6 +167,8 @@ struct MistralBitgen write_io_cell(ci, loc.x, loc.y, bi); else if (ctx->is_clkbuf_cell(ci->type)) write_clkbuf_cell(ci, loc.x, loc.y, bi); + else if (ci->type == id_MISTRAL_M10K) + write_m10k_cell(ci, loc.x, loc.y, bi); } } -- cgit v1.2.3 From da65afc83b83f02efa96e9a7735f7044a1f1e6d1 Mon Sep 17 00:00:00 2001 From: gatecat Date: Wed, 22 Dec 2021 13:54:30 +0000 Subject: mistral: M10K pack fixes Signed-off-by: gatecat --- mistral/arch.cc | 2 ++ mistral/pack.cc | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mistral/arch.cc b/mistral/arch.cc index 6ba16939..46ed4f62 100644 --- a/mistral/arch.cc +++ b/mistral/arch.cc @@ -410,6 +410,8 @@ void Arch::add_bel_pin(BelId bel, IdString pin, PortType dir, WireId wire) void Arch::assign_default_pinmap(CellInfo *cell) { + if (cell->type == id_MISTRAL_M10K) + return; // M10Ks always have a custom pinmap for (auto &port : cell->ports) { auto &pinmap = cell->pin_data[port.first].bel_pins; if (!pinmap.empty()) diff --git a/mistral/pack.cc b/mistral/pack.cc index da1589f0..09fedf10 100644 --- a/mistral/pack.cc +++ b/mistral/pack.cc @@ -384,13 +384,13 @@ struct MistralPacker void setup_m10ks() { - for (auto& cell : ctx->cells) { + for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); if (ci->type != id_MISTRAL_M10K) continue; - auto abits = ci->attrs[id_CFG_ABITS].as_int64(); - auto dbits = ci->attrs[id_CFG_DBITS].as_int64(); + auto abits = ci->params.at(id_CFG_ABITS).as_int64(); + auto dbits = ci->params.at(id_CFG_DBITS).as_int64(); NPNR_ASSERT(abits >= 7 && abits <= 13); NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20); @@ -417,8 +417,10 @@ struct MistralPacker bit_offset = 1; } for (int bit = bit_offset; bit < abits; bit++) { - ci->pin_data[ctx->id(stringf("A1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRA[%d]", bit + addr_offset))}; - ci->pin_data[ctx->id(stringf("B1ADDR[%d]", bit))].bel_pins = {ctx->id(stringf("ADDRB[%d]", bit + addr_offset))}; + ci->pin_data[ctx->id(stringf("A1ADDR[%d]", bit))].bel_pins = { + ctx->id(stringf("ADDRA[%d]", bit + addr_offset))}; + ci->pin_data[ctx->id(stringf("B1ADDR[%d]", bit))].bel_pins = { + ctx->id(stringf("ADDRB[%d]", bit + addr_offset))}; } // Data lines @@ -449,7 +451,10 @@ struct MistralPacker } for (int bit = 0; bit < dbits; bit++) { for (int offset : offsets) { - ci->pin_data[ctx->id(stringf("A1DATA[%d]", bit))].bel_pins.push_back(ctx->id(stringf("DATAAIN[%d]", bit + offset))); + log_info("%s %s\n", ctx->nameOf(ctx->id(stringf("A1DATA[%d]", bit))), + ctx->nameOf(ctx->id(stringf("DATAAIN[%d]", bit + offset)))); + ci->pin_data[ctx->id(stringf("A1DATA[%d]", bit))].bel_pins.push_back( + ctx->id(stringf("DATAAIN[%d]", bit + offset))); } } @@ -466,6 +471,7 @@ struct MistralPacker pack_io(); constrain_carries(); constrain_lutram(); + setup_m10ks(); } }; }; // namespace -- cgit v1.2.3 From 9be65cd67c6a40ddc35460b97a014bbcd0af2f85 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 18 Jan 2022 12:15:01 +0000 Subject: mistral: some more M10K fixes --- mistral/bitstream.cc | 4 ++-- mistral/pack.cc | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc index 3490a3d7..660e3671 100644 --- a/mistral/bitstream.cc +++ b/mistral/bitstream.cc @@ -126,7 +126,7 @@ struct MistralBitgen // DATA_FLOW_THRU is probably transparent reads. cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::A_DATA_FLOW_THRU, bi, 1); - cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, ci->attrs[id_CFG_DBITS].as_int64()); + cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64()); cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_FAST_WRITE, bi, CycloneV::FAST); cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_OUTPUT_SEL, bi, CycloneV::REG); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SA_WREN_DELAY, bi, 1); @@ -135,7 +135,7 @@ struct MistralBitgen cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WR_TIMER_PULSE, bi, 0x0b); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_DATA_FLOW_THRU, bi, 1); - cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, ci->attrs[id_CFG_DBITS].as_int64()); + cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64()); cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_FAST_WRITE, bi, CycloneV::FAST); cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_OUTPUT_SEL, bi, CycloneV::REG); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SA_WREN_DELAY, bi, 1); diff --git a/mistral/pack.cc b/mistral/pack.cc index 09fedf10..27ad3c92 100644 --- a/mistral/pack.cc +++ b/mistral/pack.cc @@ -399,9 +399,9 @@ struct MistralPacker // It *does* generate ACLR[01] but leaves them unconnected if unused. // Enables. - // RDEN[0] and WREN[1] are left unconnected. - ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("RDEN[1]")}; - ci->pin_data[ctx->id("B1EN")].bel_pins = {ctx->id("WREN[0]")}; + // RDEN[1] and WREN[0] are left unconnected. + ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("WREN[1]")}; + ci->pin_data[ctx->id("B1EN")].bel_pins = {ctx->id("RDEN[0]")}; // Clocks. ci->pin_data[ctx->id("CLK1")].bel_pins = {ctx->id("CLKIN[0]")}; @@ -451,8 +451,6 @@ struct MistralPacker } for (int bit = 0; bit < dbits; bit++) { for (int offset : offsets) { - log_info("%s %s\n", ctx->nameOf(ctx->id(stringf("A1DATA[%d]", bit))), - ctx->nameOf(ctx->id(stringf("DATAAIN[%d]", bit + offset)))); ci->pin_data[ctx->id(stringf("A1DATA[%d]", bit))].bel_pins.push_back( ctx->id(stringf("DATAAIN[%d]", bit + offset))); } -- cgit v1.2.3 From 3e688a3ac9ae35a894d5c2c19f2d9591b746d8da Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 7 Mar 2022 18:22:56 +0000 Subject: mistral: fixes and debug info --- mistral/bitstream.cc | 21 +++++++++++---------- mistral/constids.inc | 1 + mistral/delay.cc | 36 ++++++++++++++++++++++++++++++++++++ mistral/m10k.cc | 30 +++++++++++------------------- 4 files changed, 59 insertions(+), 29 deletions(-) diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc index 660e3671..6a2c3825 100644 --- a/mistral/bitstream.cc +++ b/mistral/bitstream.cc @@ -118,7 +118,7 @@ struct MistralBitgen cv->bmux_m_set(CycloneV::CMUXHG, pos, CycloneV::TESTSYN_ENOUT_SELECT, bi, CycloneV::PRE_SYNENB); } - void write_m10k_cell(CellInfo* ci, int x, int y, int bi) + void write_m10k_cell(CellInfo *ci, int x, int y, int bi) { auto pos = CycloneV::xy2pos(x, y); @@ -128,31 +128,32 @@ struct MistralBitgen cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::A_DATA_FLOW_THRU, bi, 1); cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64()); cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_FAST_WRITE, bi, CycloneV::FAST); - cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_OUTPUT_SEL, bi, CycloneV::REG); + cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_OUTPUT_SEL, bi, CycloneV::ASYNC); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SA_WREN_DELAY, bi, 1); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SAEN_DELAY, bi, 2); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WL_DELAY, bi, 2); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WR_TIMER_PULSE, bi, 0x0b); - cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_DATA_FLOW_THRU, bi, 1); + cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::B_DATA_FLOW_THRU, bi, 1); cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64()); cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_FAST_WRITE, bi, CycloneV::FAST); - cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_OUTPUT_SEL, bi, CycloneV::REG); + cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_OUTPUT_SEL, bi, CycloneV::ASYNC); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SA_WREN_DELAY, bi, 1); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SAEN_DELAY, bi, 2); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_WL_DELAY, bi, 2); cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_WR_TIMER_PULSE, bi, 0x0b); - cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::TOP_CLK_SEL, bi, 1); - cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::TOP_W_INV, bi, 1); - cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::TOP_W_SEL, bi, 1); - cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::BOT_CLK_INV, bi, 1); - cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::BOT_W_SEL, bi, 1); + cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_CLK_SEL, bi, 1); + cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TOP_W_INV, bi, 1); + cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_W_SEL, bi, 1); + cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::BOT_CLK_INV, bi, 1); + cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::BOT_W_SEL, bi, 1); - cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TRUE_DUAL_PORT, bi, 1); + cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TRUE_DUAL_PORT, bi, 0); cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::DISABLE_UNUSED, bi, 0); + // Note for future us: the RAM init contents are inverted. for (int bi = 0; bi < 256; bi++) cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::RAM, bi, 0xffffffffff); } diff --git a/mistral/constids.inc b/mistral/constids.inc index e032bf53..262fd12a 100644 --- a/mistral/constids.inc +++ b/mistral/constids.inc @@ -90,6 +90,7 @@ X(WE) X(MISTRAL_MLAB) X(CLK1) X(A1EN) +X(B1EN) X(A1DATA) X(B1DATA) X(WCLK_INV) diff --git a/mistral/delay.cc b/mistral/delay.cc index 4d123249..c40ac3f0 100644 --- a/mistral/delay.cc +++ b/mistral/delay.cc @@ -57,6 +57,17 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in } else if (port.in(id_B1DATA)) { return TMG_COMB_OUTPUT; } + } else if (cell->type == id_MISTRAL_M10K) { + if (port == id_CLK1) { + return TMG_CLOCK_INPUT; + } else if (port.in(id_A1DATA, id_A1EN, id_B1EN) || port.str(this).find("A1ADDR") == 0) { + clockInfoCount = 1; + return TMG_REGISTER_INPUT; + } else if (port.str(this).find("B1ADDR") == 0) { + return TMG_REGISTER_INPUT; + } else if (port.in(id_B1DATA)) { + return TMG_REGISTER_OUTPUT; + } } return TMG_IGNORE; } @@ -87,6 +98,31 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port timing.clockToQ = DelayQuad{}; } return timing; + } else if (cell->type == id_MISTRAL_M10K) { + timing.clock_port = id_CLK1; + timing.edge = RISING_EDGE; + if (port.str(this).find("A1ADDR") == 0 || port.str(this).find("B1ADDR") == 0) { + timing.setup = DelayPair{125, 125}; + timing.hold = DelayPair{42, 42}; + timing.clockToQ = DelayQuad{}; + } else if (port == id_A1DATA) { + timing.setup = DelayPair{97, 97}; + timing.hold = DelayPair{42, 42}; + timing.clockToQ = DelayQuad{}; + } else if (port == id_A1EN) { + timing.setup = DelayPair{140, 140}; + timing.hold = DelayPair{42, 42}; + timing.clockToQ = DelayQuad{}; + } else if (port == id_B1EN) { + timing.setup = DelayPair{161, 161}; + timing.hold = DelayPair{42, 42}; + timing.clockToQ = DelayQuad{}; + } else if (port == id_B1DATA) { + timing.setup = DelayPair{}; + timing.hold = DelayPair{}; + timing.clockToQ = DelayQuad{1004}; + } + return timing; } NPNR_ASSERT_FALSE("unreachable"); } diff --git a/mistral/m10k.cc b/mistral/m10k.cc index 6d51625e..4da1204f 100644 --- a/mistral/m10k.cc +++ b/mistral/m10k.cc @@ -24,35 +24,27 @@ NEXTPNR_NAMESPACE_BEGIN void Arch::create_m10k(int x, int y) { BelId bel = add_bel(x, y, id_MISTRAL_M10K, id_MISTRAL_M10K); - add_bel_pin(bel, id_ADDRSTALLA, PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRSTALLA, 0)); - add_bel_pin(bel, id_ADDRSTALLB, PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRSTALLB, 0)); + add_bel_pin(bel, id_ADDRSTALLA, PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRSTALLA, 0)); + add_bel_pin(bel, id_ADDRSTALLB, PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRSTALLB, 0)); for (int z = 0; z < 2; z++) { add_bel_pin(bel, id(stringf("BYTEENABLEA[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::BYTEENABLEA, z)); add_bel_pin(bel, id(stringf("BYTEENABLEB[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::BYTEENABLEB, z)); - add_bel_pin(bel, id(stringf("ACLR[%d]", z)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::ACLR, z)); - add_bel_pin(bel, id(stringf("RDEN[%d]", z)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::RDEN, z)); - add_bel_pin(bel, id(stringf("WREN[%d]", z)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::WREN, z)); - add_bel_pin(bel, id(stringf("CLKIN[%d]", z)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::CLKIN, z)); - add_bel_pin(bel, id(stringf("CLKIN[%d]", z+6)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::CLKIN, z+6)); + add_bel_pin(bel, id(stringf("ACLR[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::ACLR, z)); + add_bel_pin(bel, id(stringf("RDEN[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::RDEN, z)); + add_bel_pin(bel, id(stringf("WREN[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::WREN, z)); + add_bel_pin(bel, id(stringf("CLKIN[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::CLKIN, z)); + add_bel_pin(bel, id(stringf("CLKIN[%d]", z + 6)), PORT_IN, + get_port(CycloneV::M10K, x, y, -1, CycloneV::CLKIN, z + 6)); } for (int z = 0; z < 4; z++) { add_bel_pin(bel, id(stringf("ENABLE[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::ENABLE, z)); } for (int z = 0; z < 12; z++) { - add_bel_pin(bel, id(stringf("ADDRA[%d]", z)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRA, z)); - add_bel_pin(bel, id(stringf("ADDRB[%d]", z)), PORT_IN, - get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRB, z)); + add_bel_pin(bel, id(stringf("ADDRA[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRA, z)); + add_bel_pin(bel, id(stringf("ADDRB[%d]", z)), PORT_IN, get_port(CycloneV::M10K, x, y, -1, CycloneV::ADDRB, z)); } for (int z = 0; z < 20; z++) { add_bel_pin(bel, id(stringf("DATAAIN[%d]", z)), PORT_IN, @@ -66,4 +58,4 @@ void Arch::create_m10k(int x, int y) } } -NEXTPNR_NAMESPACE_END \ No newline at end of file +NEXTPNR_NAMESPACE_END -- cgit v1.2.3