Add support for memory writes in processes.
authorMarcelina Kościelnicka <mwk@0x04.net>
Mon, 22 Feb 2021 23:21:46 +0000 (00:21 +0100)
committerMarcelina Kościelnicka <mwk@0x04.net>
Mon, 8 Mar 2021 19:16:29 +0000 (20:16 +0100)
16 files changed:
backends/rtlil/rtlil_backend.cc
frontends/rtlil/rtlil_lexer.l
frontends/rtlil/rtlil_parser.y
kernel/rtlil.cc
kernel/rtlil.h
manual/CHAPTER_Overview.tex
passes/cmds/bugpoint.cc
passes/cmds/check.cc
passes/cmds/show.cc
passes/proc/Makefile.inc
passes/proc/proc.cc
passes/proc/proc_arst.cc
passes/proc/proc_clean.cc
passes/proc/proc_dlatch.cc
passes/proc/proc_init.cc
passes/proc/proc_memwr.cc [new file with mode: 0644]

index 01b4bde53300428fec858080dcf2c087855cd491..cfdf3efc5bf5d4d5a83e1090bc57abdf577d61e0 100644 (file)
@@ -242,11 +242,28 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
        case RTLIL::STi: f << stringf("init\n"); break;
        }
 
-       for (auto it = sy->actions.begin(); it != sy->actions.end(); ++it) {
+       for (auto &it: sy->actions) {
                f << stringf("%s  update ", indent.c_str());
-               dump_sigspec(f, it->first);
+               dump_sigspec(f, it.first);
                f << stringf(" ");
-               dump_sigspec(f, it->second);
+               dump_sigspec(f, it.second);
+               f << stringf("\n");
+       }
+
+       for (auto &it: sy->mem_write_actions) {
+               for (auto it2 = it.attributes.begin(); it2 != it.attributes.end(); ++it2) {
+                       f << stringf("%s  attribute %s ", indent.c_str(), it2->first.c_str());
+                       dump_const(f, it2->second);
+                       f << stringf("\n");
+               }
+               f << stringf("%s  memwr %s ", indent.c_str(), it.memid.c_str());
+               dump_sigspec(f, it.address);
+               f << stringf(" ");
+               dump_sigspec(f, it.data);
+               f << stringf(" ");
+               dump_sigspec(f, it.enable);
+               f << stringf(" ");
+               dump_sigspec(f, it.priority_mask);
                f << stringf("\n");
        }
 }
index beef220f6f0aab84febfae9479cc63abe68cf0da..897ebf66784172e0ec3f96c2d7fc995c1d982c9d 100644 (file)
@@ -79,6 +79,7 @@ USING_YOSYS_NAMESPACE
 "global"       { return TOK_GLOBAL; }
 "init"         { return TOK_INIT; }
 "update"       { return TOK_UPDATE; }
+"memwr"                { return TOK_MEMWR; }
 "process"      { return TOK_PROCESS; }
 "end"          { return TOK_END; }
 
index 646489196239398581d81d7393cef0dcd79dd357..7a8f508bf131e93ec49aa331decb0ea095519dde 100644 (file)
@@ -69,7 +69,7 @@ USING_YOSYS_NAMESPACE
 %token TOK_AUTOIDX TOK_MODULE TOK_WIRE TOK_WIDTH TOK_INPUT TOK_OUTPUT TOK_INOUT
 %token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC
 %token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT
-%token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
+%token TOK_UPDATE TOK_MEMWR TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
 %token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_REAL TOK_UPTO
 
 %type <rsigspec> sigspec_list_reversed
@@ -155,6 +155,7 @@ param_defval_stmt:
        TOK_PARAMETER TOK_ID constant EOL {
                current_module->avail_parameters($2);
                current_module->parameter_default_values[$2] = *$3;
+               delete $3;
                free($2);
        };
 
@@ -389,6 +390,22 @@ update_list:
                delete $3;
                delete $4;
        } |
+       update_list attr_list TOK_MEMWR TOK_ID sigspec sigspec sigspec constant EOL {
+               RTLIL::MemWriteAction act;
+               act.attributes = attrbuf;
+               act.memid = $4;
+               act.address = *$5;
+               act.data = *$6;
+               act.enable = *$7;
+               act.priority_mask = *$8;
+               current_process->syncs.back()->mem_write_actions.push_back(std::move(act));
+               attrbuf.clear();
+               free($4);
+               delete $5;
+               delete $6;
+               delete $7;
+               delete $8;
+       } |
        /* empty */;
 
 constant:
index 40079ffc5f88f23a44febdf21767284da08ce618..c3ae5d2438ea62610e0fab41e78b3f756277b732 100644 (file)
@@ -4538,6 +4538,7 @@ RTLIL::SyncRule *RTLIL::SyncRule::clone() const
        new_syncrule->type = type;
        new_syncrule->signal = signal;
        new_syncrule->actions = actions;
+       new_syncrule->mem_write_actions = mem_write_actions;
        return new_syncrule;
 }
 
index f03f27617eca37d398b8813588ac3965b0619e42..10cb039d5d720008ca6ac8bc61c46dd318c438b8 100644 (file)
@@ -69,6 +69,7 @@ namespace RTLIL
        struct SigSpec;
        struct CaseRule;
        struct SwitchRule;
+       struct MemWriteAction;
        struct SyncRule;
        struct Process;
 
@@ -1541,11 +1542,21 @@ struct RTLIL::SwitchRule : public RTLIL::AttrObject
        RTLIL::SwitchRule *clone() const;
 };
 
+struct RTLIL::MemWriteAction : RTLIL::AttrObject
+{
+       RTLIL::IdString memid;
+       RTLIL::SigSpec address;
+       RTLIL::SigSpec data;
+       RTLIL::SigSpec enable;
+       RTLIL::Const priority_mask;
+};
+
 struct RTLIL::SyncRule
 {
        RTLIL::SyncType type;
        RTLIL::SigSpec signal;
        std::vector<RTLIL::SigSig> actions;
+       std::vector<RTLIL::MemWriteAction> mem_write_actions;
 
        template<typename T> void rewrite_sigspecs(T &functor);
        template<typename T> void rewrite_sigspecs2(T &functor);
@@ -1693,6 +1704,11 @@ void RTLIL::SyncRule::rewrite_sigspecs(T &functor)
                functor(it.first);
                functor(it.second);
        }
+       for (auto &it : mem_write_actions) {
+               functor(it.address);
+               functor(it.data);
+               functor(it.enable);
+       }
 }
 
 template<typename T>
@@ -1702,6 +1718,11 @@ void RTLIL::SyncRule::rewrite_sigspecs2(T &functor)
        for (auto &it : actions) {
                functor(it.first, it.second);
        }
+       for (auto &it : mem_write_actions) {
+               functor(it.address);
+               functor(it.data);
+               functor(it.enable);
+       }
 }
 
 template<typename T>
index 83db5aac7aa84c767bb9404e1b3052b0c77b82f8..50a56137cb05a1e21bd18ab8910a4c8969ecc740 100644 (file)
@@ -350,8 +350,9 @@ to update {\tt \textbackslash{}q}.
 An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and
 exactly one RTLIL::CaseRule object, which is called the {\it root case}.
 
-An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type) and zero or
-more assignments (RTLIL::SigSig). The {\tt always} synchronization condition is used to break combinatorial
+An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type), zero or
+more assignments (RTLIL::SigSig), and zero or more memory writes (RTLIL::MemWriteAction).
+The {\tt always} synchronization condition is used to break combinatorial
 loops when a latch should be inferred instead.
 
 An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig)
index da81e7f0915be10e53625307d379a075c55a3908..40207b1fc598a682b5d62ef7fecd4bf18500aeb8 100644 (file)
@@ -339,6 +339,23 @@ struct BugpointPass : public Pass {
                                                                return design_copy;
                                                        }
                                                }
+                                               int i = 0;
+                                               for (auto it = sy->mem_write_actions.begin(); it != sy->mem_write_actions.end(); ++it, ++i)
+                                               {
+                                                       if (index++ == seed)
+                                                       {
+                                                               log_header(design, "Trying to remove sync %s memwr %s %s %s %s in %s.%s.\n", log_signal(sy->signal), log_id(it->memid), log_signal(it->address), log_signal(it->data), log_signal(it->enable), log_id(mod), log_id(pr.first));
+                                                               sy->mem_write_actions.erase(it);
+                                                               // Remove the bit for removed action from other actions' priority masks.
+                                                               for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) {
+                                                                       auto &mask = it2->priority_mask;
+                                                                       if (GetSize(mask) > i) {
+                                                                               mask.bits.erase(mask.bits.begin() + i);
+                                                                       }
+                                                               }
+                                                               return design_copy;
+                                                       }
+                                               }
                                        }
                                }
                        }
index 36febb98ac61cfedc52e24e743b5970b294a8b27..b502b07887158defaac5b587e90bafce07331d13 100644 (file)
@@ -141,6 +141,14 @@ struct CheckPass : public Pass {
                                                for (auto bit : sigmap(action.second))
                                                        if (bit.wire) used_wires.insert(bit);
                                        }
+                                       for (auto memwr : sync->mem_write_actions) {
+                                               for (auto bit : sigmap(memwr.address))
+                                                       if (bit.wire) used_wires.insert(bit);
+                                               for (auto bit : sigmap(memwr.data))
+                                                       if (bit.wire) used_wires.insert(bit);
+                                               for (auto bit : sigmap(memwr.enable))
+                                                       if (bit.wire) used_wires.insert(bit);
+                                       }
                                }
                        }
 
index 0c96f8c5d4dedeefba8904340c0fd91608862f23..a389c3179340058791124ffd66a3f0510880f332 100644 (file)
@@ -339,6 +339,11 @@ struct ShowWorker
        {
                input_signals.insert(obj->signal);
                collect_proc_signals(obj->actions, input_signals, output_signals);
+               for (auto it : obj->mem_write_actions) {
+                       input_signals.insert(it.address);
+                       input_signals.insert(it.data);
+                       input_signals.insert(it.enable);
+               }
        }
 
        void collect_proc_signals(RTLIL::Process *obj, std::set<RTLIL::SigSpec> &input_signals, std::set<RTLIL::SigSpec> &output_signals)
index 4b56979f8340e29b51db2bc56edef35d76718fee..50244bf33defa64791d76a551cb8d6d9a0c9f3e2 100644 (file)
@@ -8,3 +8,4 @@ OBJS += passes/proc/proc_arst.o
 OBJS += passes/proc/proc_mux.o
 OBJS += passes/proc/proc_dlatch.o
 OBJS += passes/proc/proc_dff.o
+OBJS += passes/proc/proc_memwr.o
index 09cf0af82dc2c63be4731d2aacff08f62f9122e3..2151b0ce7f6c8cda2add144d000120a22cd91556 100644 (file)
@@ -43,6 +43,7 @@ struct ProcPass : public Pass {
                log("    proc_mux\n");
                log("    proc_dlatch\n");
                log("    proc_dff\n");
+               log("    proc_memwr\n");
                log("    proc_clean\n");
                log("\n");
                log("This replaces the processes in the design with multiplexers,\n");
@@ -102,6 +103,7 @@ struct ProcPass : public Pass {
                        Pass::call(design, ifxmode ? "proc_mux -ifx" : "proc_mux");
                Pass::call(design, "proc_dlatch");
                Pass::call(design, "proc_dff");
+               Pass::call(design, "proc_memwr");
                Pass::call(design, "proc_clean");
 
                log_pop();
index 16db461b2585244451aa657d8a113a79a2d62e06..4351321e02ccdfba20a1de2845b87eb489cb1c77 100644 (file)
@@ -153,6 +153,30 @@ void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigSpec con
        }
 }
 
+RTLIL::SigSpec apply_reset(RTLIL::Module *mod, RTLIL::Process *proc, RTLIL::SyncRule *sync, SigMap &assign_map, RTLIL::SigSpec root_sig, bool polarity, RTLIL::SigSpec sig, RTLIL::SigSpec log_sig) {
+       RTLIL::SigSpec rspec = assign_map(sig);
+       RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size());
+       for (int i = 0; i < GetSize(rspec); i++)
+               if (rspec[i].wire == NULL)
+                       rval[i] = rspec[i];
+       RTLIL::SigSpec last_rval;
+       for (int count = 0; rval != last_rval; count++) {
+               last_rval = rval;
+               apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
+               assign_map.apply(rval);
+               if (rval.is_fully_const())
+                       break;
+               if (count > 100)
+                       log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
+                                       log_signal(sync->signal), log_signal(rval), log_signal(log_sig));
+               rspec = rval;
+       }
+       if (rval.has_marked_bits())
+               log_error("Async reset %s yields non-constant value %s for signal %s.\n",
+                               log_signal(sync->signal), log_signal(rval), log_signal(log_sig));
+       return rval;
+}
+
 void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
 {
 restart_proc_arst:
@@ -172,28 +196,18 @@ restart_proc_arst:
                                        sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0;
                                }
                                for (auto &action : sync->actions) {
-                                       RTLIL::SigSpec rspec = assign_map(action.second);
-                                       RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size());
-                                       for (int i = 0; i < GetSize(rspec); i++)
-                                               if (rspec[i].wire == NULL)
-                                                       rval[i] = rspec[i];
-                                       RTLIL::SigSpec last_rval;
-                                       for (int count = 0; rval != last_rval; count++) {
-                                               last_rval = rval;
-                                               apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
-                                               assign_map.apply(rval);
-                                               if (rval.is_fully_const())
-                                                       break;
-                                               if (count > 100)
-                                                       log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
-                                                                       log_signal(sync->signal), log_signal(rval), log_signal(action.first));
-                                               rspec = rval;
+                                       action.second = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.second, action.first);
+                               }
+                               for (auto &memwr : sync->mem_write_actions) {
+                                       RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable);
+                                       if (!en.is_fully_zero()) {
+                                               log_error("Async reset %s causes memory write to %s.\n",
+                                                               log_signal(sync->signal), log_id(memwr.memid));
                                        }
-                                       if (rval.has_marked_bits())
-                                               log_error("Async reset %s yields non-constant value %s for signal %s.\n",
-                                                               log_signal(sync->signal), log_signal(rval), log_signal(action.first));
-                                       action.second = rval;
+                                       apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.address, memwr.address);
+                                       apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.data, memwr.data);
                                }
+                               sync->mem_write_actions.clear();
                                eliminate_const(mod, &proc->root_case, root_sig, polarity);
                                goto restart_proc_arst;
                        }
index 54d5a81ff22a75584f16641e7a27bdc04ae09f4b..9e0b671f4c4e3ddee8af78f70c1d7ebc8b040922 100644 (file)
@@ -161,7 +161,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool
                for (size_t j = 0; j < proc->syncs[i]->actions.size(); j++)
                        if (proc->syncs[i]->actions[j].first.size() == 0)
                                proc->syncs[i]->actions.erase(proc->syncs[i]->actions.begin() + (j--));
-               if (proc->syncs[i]->actions.size() == 0) {
+               if (proc->syncs[i]->actions.size() == 0 && proc->syncs[i]->mem_write_actions.size() == 0) {
                        delete proc->syncs[i];
                        proc->syncs.erase(proc->syncs.begin() + (i--));
                }
index 7b8c05b21f7d6697e3ea058ea460c84f7ce2d797..03d072cf4c4ac8eeb15b7b5dd3ce84bd23449dcb 100644 (file)
@@ -342,7 +342,6 @@ struct proc_dlatch_db_t
 
 void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
 {
-       std::vector<RTLIL::SyncRule*> new_syncs;
        RTLIL::SigSig latches_bits, nolatches_bits;
        dict<SigBit, SigBit> latches_out_in;
        dict<SigBit, int> latches_hold;
@@ -351,7 +350,6 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
        for (auto sr : proc->syncs)
        {
                if (sr->type != RTLIL::SyncType::STa) {
-                       new_syncs.push_back(sr);
                        continue;
                }
 
@@ -373,8 +371,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
                        for (int i = 0; i < GetSize(ss.first); i++)
                                latches_out_in[ss.first[i]] = ss.second[i];
                }
-
-               delete sr;
+               sr->actions.clear();
        }
 
        latches_out_in.sort();
@@ -441,8 +438,6 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
 
                offset += width;
        }
-
-       new_syncs.swap(proc->syncs);
 }
 
 struct ProcDlatchPass : public Pass {
index eb323038d1d4ff0785b7e7d1a916cbbc476b9c3d..b705251ddce649fe6d27381594815148bd3027b0 100644 (file)
@@ -71,17 +71,8 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc)
                                        offset += lhs_c.width;
                                }
                        }
+                       sync->actions.clear();
                }
-
-       if (found_init) {
-               std::vector<RTLIL::SyncRule*> new_syncs;
-               for (auto &sync : proc->syncs)
-                       if (sync->type == RTLIL::SyncType::STi)
-                               delete sync;
-                       else
-                               new_syncs.push_back(sync);
-               proc->syncs.swap(new_syncs);
-       }
 }
 
 struct ProcInitPass : public Pass {
diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc
new file mode 100644 (file)
index 0000000..f898979
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2021  Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ *  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 "kernel/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
+#include "kernel/consteval.h"
+#include "kernel/log.h"
+#include <sstream>
+#include <stdlib.h>
+#include <stdio.h>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict<IdString, int> &next_priority)
+{
+       for (auto sr : proc->syncs)
+       {
+               for (auto memwr : sr->mem_write_actions) {
+                       RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr));
+                       cell->attributes = memwr.attributes;
+                       cell->setParam(ID::MEMID, Const(memwr.memid.str()));
+                       cell->setParam(ID::ABITS, GetSize(memwr.address));
+                       cell->setParam(ID::WIDTH, GetSize(memwr.data));
+                       cell->setParam(ID::PRIORITY, next_priority[memwr.memid]++);
+                       cell->setPort(ID::ADDR, memwr.address);
+                       cell->setPort(ID::DATA, memwr.data);
+                       SigSpec enable = memwr.enable;
+                       for (auto sr2 : proc->syncs) {
+                               if (sr2->type == RTLIL::SyncType::ST0) {
+                                       log_assert(sr2->mem_write_actions.empty());
+                                       enable = mod->Mux(NEW_ID, Const(State::S0, GetSize(enable)), enable, sr2->signal);
+                               } else if (sr2->type == RTLIL::SyncType::ST1) {
+                                       log_assert(sr2->mem_write_actions.empty());
+                                       enable = mod->Mux(NEW_ID, enable, Const(State::S0, GetSize(enable)), sr2->signal);
+                               }
+                       }
+                       cell->setPort(ID::EN, enable);
+                       if (sr->type == RTLIL::SyncType::STa) {
+                               cell->setPort(ID::CLK, State::Sx);
+                               cell->setParam(ID::CLK_ENABLE, State::S0);
+                               cell->setParam(ID::CLK_POLARITY, State::Sx);
+                       } else if (sr->type == RTLIL::SyncType::STp) {
+                               cell->setPort(ID::CLK, sr->signal);
+                               cell->setParam(ID::CLK_ENABLE, State::S1);
+                               cell->setParam(ID::CLK_POLARITY, State::S1);
+                       } else if (sr->type == RTLIL::SyncType::STn) {
+                               cell->setPort(ID::CLK, sr->signal);
+                               cell->setParam(ID::CLK_ENABLE, State::S1);
+                               cell->setParam(ID::CLK_POLARITY, State::S0);
+                       } else {
+                               log_error("process memory write with unsupported sync type in %s.%s", log_id(mod), log_id(proc));
+                       }
+               }
+               sr->mem_write_actions.clear();
+       }
+}
+
+struct ProcMemWrPass : public Pass {
+       ProcMemWrPass() : Pass("proc_memwr", "extract memory writes from processes") { }
+       void help() override
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    proc_memwr [selection]\n");
+               log("\n");
+               log("This pass converts memory writes in processes into $memwr cells.\n");
+               log("\n");
+       }
+       void execute(std::vector<std::string> args, RTLIL::Design *design) override
+       {
+               log_header(design, "Executing PROC_MEMWR pass (convert process memory writes to cells).\n");
+
+               extra_args(args, 1, design);
+
+               for (auto module : design->selected_modules()) {
+                       dict<IdString, int> next_priority;
+                       for (auto cell : module->cells()) {
+                               if (cell->type == ID($memwr)) {
+                                       IdString memid = cell->parameters.at(ID::MEMID).decode_string();
+                                       int priority = cell->parameters.at(ID::PRIORITY).as_int();
+                                       if (priority >= next_priority[memid])
+                                               next_priority[memid] = priority + 1;
+                               }
+                       }
+                       for (auto &proc_it : module->processes)
+                               if (design->selected(module, proc_it.second))
+                                       proc_memwr(module, proc_it.second, next_priority);
+               }
+       }
+} ProcMemWrPass;
+
+PRIVATE_NAMESPACE_END
+