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_init(RTLIL::Module
*mod
, SigMap
&sigmap
, RTLIL::Process
*proc
)
31 bool found_init
= false;
33 for (auto &sync
: proc
->syncs
)
34 if (sync
->type
== RTLIL::SyncType::STi
)
37 log("Found init rule in `%s.%s'.\n", mod
->name
.c_str(), proc
->name
.c_str());
39 for (auto &action
: sync
->actions
)
41 RTLIL::SigSpec lhs
= action
.first
;
42 RTLIL::SigSpec rhs
= sigmap(action
.second
);
44 if (!rhs
.is_fully_const())
45 log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs
), log_signal(rhs
));
48 for (auto &lhs_c
: lhs
.chunks())
50 if (lhs_c
.wire
!= nullptr)
52 SigSpec valuesig
= rhs
.extract(offset
, lhs_c
.width
);
53 if (!valuesig
.is_fully_const())
54 log_cmd_error("Non-const initialization value: %s = %s\n", log_signal(lhs_c
), log_signal(valuesig
));
56 Const value
= valuesig
.as_const();
57 Const
&wireinit
= lhs_c
.wire
->attributes
["\\init"];
59 while (GetSize(wireinit
.bits
) < lhs_c
.wire
->width
)
60 wireinit
.bits
.push_back(State::Sx
);
62 for (int i
= 0; i
< lhs_c
.width
; i
++) {
63 auto &initbit
= wireinit
.bits
[i
+ lhs_c
.offset
];
64 if (initbit
!= State::Sx
&& initbit
!= value
[i
])
65 log_cmd_error("Conflicting initialization values for %s.\n", log_signal(lhs_c
));
69 log(" Set init value: %s = %s\n", log_signal(lhs_c
.wire
), log_signal(wireinit
));
71 offset
+= lhs_c
.width
;
77 std::vector
<RTLIL::SyncRule
*> new_syncs
;
78 for (auto &sync
: proc
->syncs
)
79 if (sync
->type
== RTLIL::SyncType::STi
)
82 new_syncs
.push_back(sync
);
83 proc
->syncs
.swap(new_syncs
);
87 struct ProcInitPass
: public Pass
{
88 ProcInitPass() : Pass("proc_init", "convert initial block to init attributes") { }
89 void help() YS_OVERRIDE
91 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
93 log(" proc_init [selection]\n");
95 log("This pass extracts the 'init' actions from processes (generated from Verilog\n");
96 log("'initial' blocks) and sets the initial value to the 'init' attribute on the\n");
97 log("respective wire.\n");
100 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
102 log_header(design
, "Executing PROC_INIT pass (extract init attributes).\n");
104 extra_args(args
, 1, design
);
106 for (auto mod
: design
->modules())
107 if (design
->selected(mod
)) {
109 for (auto &proc_it
: mod
->processes
)
110 if (design
->selected(mod
, proc_it
.second
))
111 proc_init(mod
, sigmap
, proc_it
.second
);
116 PRIVATE_NAMESPACE_END