2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/register.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/log.h"
27 PRIVATE_NAMESPACE_BEGIN
29 void proc_get_const(RTLIL::SigSpec
&sig
, RTLIL::CaseRule
&rule
)
31 log_assert(rule
.compare
.size() == 0);
34 RTLIL::SigSpec tmp
= sig
;
35 for (auto &it
: rule
.actions
)
36 tmp
.replace(it
.first
, it
.second
);
43 void proc_init(RTLIL::Module
*mod
, RTLIL::Process
*proc
)
45 bool found_init
= false;
47 for (auto &sync
: proc
->syncs
)
48 if (sync
->type
== RTLIL::SyncType::STi
)
51 log("Found init rule in `%s.%s'.\n", mod
->name
.c_str(), proc
->name
.c_str());
53 for (auto &action
: sync
->actions
)
55 RTLIL::SigSpec lhs
= action
.first
;
56 RTLIL::SigSpec rhs
= action
.second
;
58 proc_get_const(rhs
, proc
->root_case
);
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
));
64 for (auto &lhs_c
: lhs
.chunks())
66 if (lhs_c
.wire
!= nullptr)
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
));
72 Const value
= valuesig
.as_const();
73 Const
&wireinit
= lhs_c
.wire
->attributes
["\\init"];
75 while (GetSize(wireinit
.bits
) < lhs_c
.wire
->width
)
76 wireinit
.bits
.push_back(State::Sx
);
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
));
85 log(" Set init value: %s = %s\n", log_signal(lhs_c
.wire
), log_signal(wireinit
));
87 offset
+= lhs_c
.width
;
93 std::vector
<RTLIL::SyncRule
*> new_syncs
;
94 for (auto &sync
: proc
->syncs
)
95 if (sync
->type
== RTLIL::SyncType::STi
)
98 new_syncs
.push_back(sync
);
99 proc
->syncs
.swap(new_syncs
);
103 struct ProcInitPass
: public Pass
{
104 ProcInitPass() : Pass("proc_init", "convert initial block to init attributes") { }
105 void help() YS_OVERRIDE
107 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
109 log(" proc_init [selection]\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");
116 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
118 log_header(design
, "Executing PROC_INIT pass (extract init attributes).\n");
120 extra_args(args
, 1, design
);
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
);
130 PRIVATE_NAMESPACE_END