From 09471846c553855c43224ce32d855c46f4df5140 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 21 Nov 2013 13:49:00 +0100 Subject: Major improvements in mem2reg and added "init" sync rules --- passes/proc/proc_init.cc | 114 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 passes/proc/proc_init.cc (limited to 'passes/proc/proc_init.cc') diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc new file mode 100644 index 00000000..fca20fda --- /dev/null +++ b/passes/proc/proc_init.cc @@ -0,0 +1,114 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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/log.h" +#include +#include + +static void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule) +{ + assert(rule.compare.size() == 0); + + while (1) { + sig.optimize(); + RTLIL::SigSpec tmp = sig; + for (auto &it : rule.actions) + tmp.replace(it.first, it.second); + if (tmp == sig) + break; + sig = tmp; + } +} + +static void proc_init(RTLIL::Module *mod, RTLIL::Process *proc) +{ + bool found_init = false; + + for (auto &sync : proc->syncs) + if (sync->type == RTLIL::SyncType::STi) + { + found_init = true; + log("Found init rule in `%s.%s'.\n", mod->name.c_str(), proc->name.c_str()); + + for (auto &action : sync->actions) + { + RTLIL::SigSpec lhs = action.first; + RTLIL::SigSpec rhs = action.second; + + lhs.optimize(); + proc_get_const(rhs, proc->root_case); + + if (!rhs.is_fully_const()) + log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs)); + + int offset = 0; + for (size_t i = 0; i < lhs.chunks.size(); i++) { + if (lhs.chunks[i].wire == NULL) + continue; + RTLIL::Wire *wire = lhs.chunks[i].wire; + RTLIL::SigSpec value = rhs.extract(offset, lhs.chunks[i].width); + if (value.width != wire->width) + log_cmd_error("Init value is not for the entire wire: %s = %s\n", log_signal(lhs.chunks[i]), log_signal(value)); + log(" Setting init value: %s = %s\n", log_signal(wire), log_signal(value)); + wire->attributes["\\init"] = value.as_const(); + offset += wire->width; + } + } + } + + if (found_init) { + std::vector 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 { + ProcInitPass() : Pass("proc_init", "convert initial block to init attributes") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" proc_init [selection]\n"); + log("\n"); + log("This pass extracts the 'init' actions from processes (generated from verilog\n"); + log("'initial' blocks) and sets the initial value to the 'init' attribute on the\n"); + log("respective wire.\n"); + log("\n"); + } + virtual void execute(std::vector args, RTLIL::Design *design) + { + log_header("Executing PROC_INIT pass (extract init attributes).\n"); + + extra_args(args, 1, design); + + for (auto &mod_it : design->modules) + if (design->selected(mod_it.second)) + for (auto &proc_it : mod_it.second->processes) + if (design->selected(mod_it.second, proc_it.second)) + proc_init(mod_it.second, proc_it.second); + } +} ProcInitPass; + -- cgit v1.2.3