aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
authorMarcelina Kościelnicka <mwk@0x04.net>2021-02-23 00:21:46 +0100
committerMarcelina Kościelnicka <mwk@0x04.net>2021-03-08 20:16:29 +0100
commit4e03865d5bf3fafe0bd3735c88431675d53d2663 (patch)
tree7ef637bd0526b498d32386bc1c79c671a02af7f0 /passes
parentc00a29296c8d3446c7cfe253080c7e33358219b0 (diff)
downloadyosys-4e03865d5bf3fafe0bd3735c88431675d53d2663.tar.gz
yosys-4e03865d5bf3fafe0bd3735c88431675d53d2663.tar.bz2
yosys-4e03865d5bf3fafe0bd3735c88431675d53d2663.zip
Add support for memory writes in processes.
Diffstat (limited to 'passes')
-rw-r--r--passes/cmds/bugpoint.cc17
-rw-r--r--passes/cmds/check.cc8
-rw-r--r--passes/cmds/show.cc5
-rw-r--r--passes/proc/Makefile.inc1
-rw-r--r--passes/proc/proc.cc2
-rw-r--r--passes/proc/proc_arst.cc54
-rw-r--r--passes/proc/proc_clean.cc2
-rw-r--r--passes/proc/proc_dlatch.cc7
-rw-r--r--passes/proc/proc_init.cc11
-rw-r--r--passes/proc/proc_memwr.cc111
10 files changed, 181 insertions, 37 deletions
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index da81e7f09..40207b1fc 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -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;
+ }
+ }
}
}
}
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index 36febb98a..b502b0788 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -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);
+ }
}
}
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 0c96f8c5d..a389c3179 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -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)
diff --git a/passes/proc/Makefile.inc b/passes/proc/Makefile.inc
index 4b56979f8..50244bf33 100644
--- a/passes/proc/Makefile.inc
+++ b/passes/proc/Makefile.inc
@@ -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
diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc
index 09cf0af82..2151b0ce7 100644
--- a/passes/proc/proc.cc
+++ b/passes/proc/proc.cc
@@ -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();
diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc
index 16db461b2..4351321e0 100644
--- a/passes/proc/proc_arst.cc
+++ b/passes/proc/proc_arst.cc
@@ -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;
}
diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc
index 54d5a81ff..9e0b671f4 100644
--- a/passes/proc/proc_clean.cc
+++ b/passes/proc/proc_clean.cc
@@ -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--));
}
diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc
index 7b8c05b21..03d072cf4 100644
--- a/passes/proc/proc_dlatch.cc
+++ b/passes/proc/proc_dlatch.cc
@@ -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 {
diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc
index eb323038d..b705251dd 100644
--- a/passes/proc/proc_init.cc
+++ b/passes/proc/proc_init.cc
@@ -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
index 000000000..f898979d8
--- /dev/null
+++ b/passes/proc/proc_memwr.cc
@@ -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
+