From 18806f1ef653f29654533ee47fd8a1b0cf1d645a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Tue, 25 May 2021 19:31:53 +0200 Subject: [PATCH] memory_bram: Reuse extract_rdff helper for make_outreg. Also properly skip read ports with init value or reset when not making use of make_outreg. Proper support for matching those will land later. --- passes/memory/memory_bram.cc | 61 +++++++++++++++++++++------------- tests/arch/anlogic/lutram.ys | 9 +++-- tests/arch/ecp5/lutram.ys | 8 ++--- tests/arch/intel_alm/lutram.ys | 10 +++--- tests/arch/nexus/lutram.ys | 4 +-- 5 files changed, 52 insertions(+), 40 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 6ec3dc2e9..b70864766 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -19,6 +19,7 @@ #include "kernel/yosys.h" #include "kernel/mem.h" +#include "kernel/ffinit.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -401,7 +402,7 @@ struct rules_t } }; -bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &bram, const rules_t::match_t &match, dict &match_properties, int mode) +bool replace_memory(Mem &orig_mem, const rules_t &rules, FfInitVals *initvals, const rules_t::bram_t &bram, const rules_t::match_t &match, dict &match_properties, int mode) { // We will modify ports — make a copy of the structure. Mem mem(orig_mem); @@ -727,7 +728,18 @@ grow_read_ports:; log(" Bram port %c%d.%d has no read enable input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } - skip_bram_rport_clkcheck: + if (port.arst != State::S0) { + log(" Bram port %c%d.%d has no async reset input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + goto skip_bram_rport; + } + if (port.srst != State::S0) { + log(" Bram port %c%d.%d has no sync reset input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + goto skip_bram_rport; + } + if (!port.init_value.is_fully_undef()) { + log(" Bram port %c%d.%d has no initial value support.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + goto skip_bram_rport; + } if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) { if (match.make_transp && GetSize(mem.wr_ports) <= 1) { pi.make_transp = true; @@ -750,10 +762,11 @@ grow_read_ports:; } } + skip_bram_rport_clkcheck: log(" Mapped to bram port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); pi.mapped_port = cell_port_i; - if (port.clk_enable) { + if (port.clk_enable && !pi.make_outreg) { clock_domains[pi.clocks] = clkdom; clock_polarities[pi.clkpol] = clkdom.second; if (!pi.make_transp) @@ -868,6 +881,16 @@ grow_read_ports:; for (auto &other_bram : rules.brams.at(bram.name)) bram.find_variant_params(variant_params, other_bram); + // Apply make_outreg where necessary. + for (auto &pi : portinfos) { + if (pi.make_outreg) { + mem.extract_rdff(pi.mapped_port, initvals); + auto &port = mem.rd_ports[pi.mapped_port]; + pi.sig_addr = port.addr; + pi.sig_data = port.data; + } + } + // actually replace that memory cell dict> dout_cache; @@ -970,18 +993,7 @@ grow_read_ports:; } else { SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits); c->setPort(stringf("\\%sDATA", pf), bram_dout); - if (pi.make_outreg && pi.make_transp) { - log(" Moving output register to address for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); - SigSpec sig_addr_q = module->addWire(NEW_ID, bram.abits); - module->addDff(NEW_ID, pi.sig_clock, sig_addr, sig_addr_q, pi.effective_clkpol); - c->setPort(stringf("\\%sADDR", pf), sig_addr_q); - } else if (pi.make_outreg) { - SigSpec bram_dout_q = module->addWire(NEW_ID, bram.dbits); - if (!pi.sig_en.empty()) - bram_dout = module->Mux(NEW_ID, bram_dout_q, bram_dout, pi.sig_en); - module->addDff(NEW_ID, pi.sig_clock, bram_dout, bram_dout_q, pi.effective_clkpol); - bram_dout = bram_dout_q; - } else if (pi.make_transp) { + if (pi.make_transp) { log(" Adding extra logic for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); SigSpec transp_en_d = module->Mux(NEW_ID, SigSpec(0, make_transp_enbits), @@ -1005,7 +1017,7 @@ grow_read_ports:; } SigSpec addr_ok_q = addr_ok; - if ((pi.clocks || pi.make_outreg) && !addr_ok.empty()) { + if (pi.clocks && !addr_ok.empty()) { addr_ok_q = module->addWire(NEW_ID); if (!pi.sig_en.empty()) addr_ok = module->Mux(NEW_ID, addr_ok_q, addr_ok, pi.sig_en); @@ -1037,7 +1049,7 @@ grow_read_ports:; return true; } -void handle_memory(Mem &mem, const rules_t &rules) +void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) { log("Processing %s.%s:\n", log_id(mem.module), log_id(mem.memid)); @@ -1217,7 +1229,7 @@ void handle_memory(Mem &mem, const rules_t &rules) if (or_next_if_better && i+1 == GetSize(rules.matches) && vi+1 == GetSize(rules.brams.at(match.name))) log_error("Found 'or_next_if_better' in last match rule.\n"); - if (!replace_memory(mem, rules, bram, match, match_properties, 1)) { + if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 1)) { log(" Mapping to bram type %s failed.\n", log_id(match.name)); failed_brams.insert(pair(bram.name, bram.variant)); goto next_match_rule; @@ -1244,12 +1256,12 @@ void handle_memory(Mem &mem, const rules_t &rules) best_rule_cache.clear(); auto &best_bram = rules.brams.at(rules.matches.at(best_rule.first).name).at(best_rule.second); - if (!replace_memory(mem, rules, best_bram, rules.matches.at(best_rule.first), match_properties, 2)) + if (!replace_memory(mem, rules, initvals, best_bram, rules.matches.at(best_rule.first), match_properties, 2)) log_error("Mapping to bram type %s (variant %d) after pre-selection failed.\n", log_id(best_bram.name), best_bram.variant); return; } - if (!replace_memory(mem, rules, bram, match, match_properties, 0)) { + if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 0)) { log(" Mapping to bram type %s failed.\n", log_id(match.name)); failed_brams.insert(pair(bram.name, bram.variant)); goto next_match_rule; @@ -1381,9 +1393,12 @@ struct MemoryBramPass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->selected_modules()) - for (auto &mem : Mem::get_selected_memories(mod)) - handle_memory(mem, rules); + for (auto mod : design->selected_modules()) { + SigMap sigmap(mod); + FfInitVals initvals(&sigmap, mod); + for (auto &mem : Mem::get_selected_memories(mod)) + handle_memory(mem, rules, &initvals); + } } } MemoryBramPass; diff --git a/tests/arch/anlogic/lutram.ys b/tests/arch/anlogic/lutram.ys index 9ebb75443..6dbdbdac3 100644 --- a/tests/arch/anlogic/lutram.ys +++ b/tests/arch/anlogic/lutram.ys @@ -13,9 +13,8 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter design -load postopt cd lutram_1w1r -select -assert-count 8 t:AL_MAP_LUT2 -select -assert-count 8 t:AL_MAP_LUT4 -select -assert-count 8 t:AL_MAP_LUT5 -select -assert-count 36 t:AL_MAP_SEQ +select -assert-count 4 t:AL_MAP_LUT3 +select -assert-count 8 t:AL_MAP_LUT6 +select -assert-count 8 t:AL_MAP_SEQ select -assert-count 8 t:EG_LOGIC_DRAM16X4 #Why not AL_LOGIC_BRAM? -select -assert-none t:AL_MAP_LUT2 t:AL_MAP_LUT4 t:AL_MAP_LUT5 t:AL_MAP_SEQ t:EG_LOGIC_DRAM16X4 %% t:* %D +select -assert-none t:AL_MAP_LUT3 t:AL_MAP_LUT6 t:AL_MAP_SEQ t:EG_LOGIC_DRAM16X4 %% t:* %D diff --git a/tests/arch/ecp5/lutram.ys b/tests/arch/ecp5/lutram.ys index e1ae7abd5..9bef37c68 100644 --- a/tests/arch/ecp5/lutram.ys +++ b/tests/arch/ecp5/lutram.ys @@ -11,9 +11,9 @@ sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r -select -assert-count 24 t:L6MUX21 -select -assert-count 71 t:LUT4 -select -assert-count 32 t:PFUMX +select -assert-count 8 t:L6MUX21 +select -assert-count 36 t:LUT4 +select -assert-count 16 t:PFUMX select -assert-count 8 t:TRELLIS_DPR16X4 -select -assert-count 35 t:TRELLIS_FF +select -assert-count 8 t:TRELLIS_FF select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D diff --git a/tests/arch/intel_alm/lutram.ys b/tests/arch/intel_alm/lutram.ys index 5d33b8e12..9ddb1ec87 100644 --- a/tests/arch/intel_alm/lutram.ys +++ b/tests/arch/intel_alm/lutram.ys @@ -12,11 +12,10 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r select -assert-count 16 t:MISTRAL_MLAB -select -assert-count 1 t:MISTRAL_NOT select -assert-count 2 t:MISTRAL_ALUT2 select -assert-count 8 t:MISTRAL_ALUT3 -select -assert-count 17 t:MISTRAL_FF -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D +select -assert-count 8 t:MISTRAL_FF +select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D design -reset @@ -34,8 +33,7 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r select -assert-count 16 t:MISTRAL_MLAB -select -assert-count 1 t:MISTRAL_NOT select -assert-count 2 t:MISTRAL_ALUT2 select -assert-count 8 t:MISTRAL_ALUT3 -select -assert-count 17 t:MISTRAL_FF -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D +select -assert-count 8 t:MISTRAL_FF +select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D diff --git a/tests/arch/nexus/lutram.ys b/tests/arch/nexus/lutram.ys index cd645f717..6e33431b6 100644 --- a/tests/arch/nexus/lutram.ys +++ b/tests/arch/nexus/lutram.ys @@ -13,7 +13,7 @@ design -load postopt cd lutram_1w1r stat select -assert-count 8 t:WIDEFN9 -select -assert-count 16 t:LUT4 +select -assert-count 12 t:LUT4 select -assert-count 8 t:DPR16X4 -select -assert-count 36 t:FD1P3IX +select -assert-count 8 t:FD1P3IX select -assert-none t:DPR16X4 t:FD1P3IX t:WIDEFN9 t:LUT4 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D -- 2.30.2