Merge pull request #3 from YosysHQ/master
[yosys.git] / passes / proc / proc_init.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/register.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/log.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 USING_YOSYS_NAMESPACE
27 PRIVATE_NAMESPACE_BEGIN
28
29 void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule)
30 {
31 log_assert(rule.compare.size() == 0);
32
33 while (1) {
34 RTLIL::SigSpec tmp = sig;
35 for (auto &it : rule.actions)
36 tmp.replace(it.first, it.second);
37 if (tmp == sig)
38 break;
39 sig = tmp;
40 }
41 }
42
43 void proc_init(RTLIL::Module *mod, RTLIL::Process *proc)
44 {
45 bool found_init = false;
46
47 for (auto &sync : proc->syncs)
48 if (sync->type == RTLIL::SyncType::STi)
49 {
50 found_init = true;
51 log("Found init rule in `%s.%s'.\n", mod->name.c_str(), proc->name.c_str());
52
53 for (auto &action : sync->actions)
54 {
55 RTLIL::SigSpec lhs = action.first;
56 RTLIL::SigSpec rhs = action.second;
57
58 proc_get_const(rhs, proc->root_case);
59
60 if (!rhs.is_fully_const())
61 log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs));
62
63 int offset = 0;
64 for (auto &lhs_c : lhs.chunks())
65 {
66 if (lhs_c.wire != nullptr)
67 {
68 SigSpec valuesig = rhs.extract(offset, lhs_c.width);
69 if (!valuesig.is_fully_const())
70 log_cmd_error("Non-const initialization value: %s = %s\n", log_signal(lhs_c), log_signal(valuesig));
71
72 Const value = valuesig.as_const();
73 Const &wireinit = lhs_c.wire->attributes["\\init"];
74
75 while (GetSize(wireinit.bits) < lhs_c.wire->width)
76 wireinit.bits.push_back(State::Sx);
77
78 for (int i = 0; i < lhs_c.width; i++) {
79 auto &initbit = wireinit.bits[i + lhs_c.offset];
80 if (initbit != State::Sx && initbit != value[i])
81 log_cmd_error("Conflicting initialization values for %s.\n", log_signal(lhs_c));
82 initbit = value[i];
83 }
84
85 log(" Set init value: %s = %s\n", log_signal(lhs_c.wire), log_signal(wireinit));
86 }
87 offset += lhs_c.width;
88 }
89 }
90 }
91
92 if (found_init) {
93 std::vector<RTLIL::SyncRule*> new_syncs;
94 for (auto &sync : proc->syncs)
95 if (sync->type == RTLIL::SyncType::STi)
96 delete sync;
97 else
98 new_syncs.push_back(sync);
99 proc->syncs.swap(new_syncs);
100 }
101 }
102
103 struct ProcInitPass : public Pass {
104 ProcInitPass() : Pass("proc_init", "convert initial block to init attributes") { }
105 void help() YS_OVERRIDE
106 {
107 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
108 log("\n");
109 log(" proc_init [selection]\n");
110 log("\n");
111 log("This pass extracts the 'init' actions from processes (generated from Verilog\n");
112 log("'initial' blocks) and sets the initial value to the 'init' attribute on the\n");
113 log("respective wire.\n");
114 log("\n");
115 }
116 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
117 {
118 log_header(design, "Executing PROC_INIT pass (extract init attributes).\n");
119
120 extra_args(args, 1, design);
121
122 for (auto mod : design->modules())
123 if (design->selected(mod))
124 for (auto &proc_it : mod->processes)
125 if (design->selected(mod, proc_it.second))
126 proc_init(mod, proc_it.second);
127 }
128 } ProcInitPass;
129
130 PRIVATE_NAMESPACE_END