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/consteval.h"
23 #include "kernel/log.h"
29 static RTLIL::SigSpec
find_any_lvalue(const RTLIL::Process
*proc
)
31 RTLIL::SigSpec lvalue
;
33 for (auto sync
: proc
->syncs
)
34 for (auto &action
: sync
->actions
)
35 if (action
.first
.width
> 0) {
36 lvalue
= action
.first
;
37 lvalue
.sort_and_unify();
41 for (auto sync
: proc
->syncs
) {
42 RTLIL::SigSpec this_lvalue
;
43 for (auto &action
: sync
->actions
)
44 this_lvalue
.append(action
.first
);
45 this_lvalue
.sort_and_unify();
46 RTLIL::SigSpec common_sig
= this_lvalue
.extract(lvalue
);
47 if (common_sig
.width
> 0)
54 static void gen_dff(RTLIL::Module
*mod
, RTLIL::SigSpec sig_in
, RTLIL::Const val_rst
, RTLIL::SigSpec sig_out
,
55 bool clk_polarity
, bool arst_polarity
, RTLIL::SigSpec clk
, RTLIL::SigSpec
*arst
, RTLIL::Process
*proc
)
57 std::stringstream sstr
;
58 sstr
<< "$procdff$" << (RTLIL::autoidx
++);
60 RTLIL::Cell
*cell
= new RTLIL::Cell
;
61 cell
->name
= sstr
.str();
62 cell
->type
= arst
? "$adff" : "$dff";
63 cell
->attributes
= proc
->attributes
;
64 mod
->cells
[cell
->name
] = cell
;
66 cell
->parameters
["\\WIDTH"] = RTLIL::Const(sig_in
.width
);
68 cell
->parameters
["\\ARST_POLARITY"] = RTLIL::Const(arst_polarity
, 1);
69 cell
->parameters
["\\ARST_VALUE"] = val_rst
;
71 cell
->parameters
["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity
, 1);
73 cell
->connections
["\\D"] = sig_in
;
74 cell
->connections
["\\Q"] = sig_out
;
76 cell
->connections
["\\ARST"] = *arst
;
77 cell
->connections
["\\CLK"] = clk
;
79 log(" created %s cell `%s' with %s edge clock", cell
->type
.c_str(), cell
->name
.c_str(), clk_polarity
? "positive" : "negative");
81 log(" and %s level reset", arst_polarity
? "positive" : "negative");
85 static void proc_dff(RTLIL::Module
*mod
, RTLIL::Process
*proc
, ConstEval
&ce
)
89 RTLIL::SigSpec sig
= find_any_lvalue(proc
);
94 log("Creating register for signal `%s.%s' using process `%s.%s'.\n",
95 mod
->name
.c_str(), log_signal(sig
), mod
->name
.c_str(), proc
->name
.c_str());
97 RTLIL::SigSpec insig
= RTLIL::SigSpec(RTLIL::State::Sz
, sig
.width
);
98 RTLIL::SigSpec rstval
= RTLIL::SigSpec(RTLIL::State::Sz
, sig
.width
);
99 RTLIL::SyncRule
*sync_level
= NULL
;
100 RTLIL::SyncRule
*sync_edge
= NULL
;
101 RTLIL::SyncRule
*sync_always
= NULL
;
103 for (auto sync
: proc
->syncs
)
104 for (auto &action
: sync
->actions
)
106 if (action
.first
.extract(sig
).width
== 0)
109 if (sync
->type
== RTLIL::SyncType::ST0
|| sync
->type
== RTLIL::SyncType::ST1
) {
110 if (sync_level
!= NULL
&& sync_level
!= sync
)
111 log_error("Multiple level sensitive events found for this signal!\n");
112 sig
.replace(action
.first
, action
.second
, &rstval
);
115 else if (sync
->type
== RTLIL::SyncType::STp
|| sync
->type
== RTLIL::SyncType::STn
) {
116 if (sync_edge
!= NULL
&& sync_edge
!= sync
)
117 log_error("Multiple edge sensitive events found for this signal!\n");
118 sig
.replace(action
.first
, action
.second
, &insig
);
121 else if (sync
->type
== RTLIL::SyncType::STa
) {
122 if (sync_always
!= NULL
&& sync_always
!= sync
)
123 log_error("Multiple always events found for this signal!\n");
124 sig
.replace(action
.first
, action
.second
, &insig
);
128 log_error("Event with any-edge sensitivity found for this signal!\n");
131 action
.first
.remove2(sig
, &action
.second
);
134 ce
.assign_map
.apply(insig
);
135 ce
.assign_map
.apply(rstval
);
136 ce
.assign_map
.apply(sig
);
143 if (sync_edge
|| sync_level
)
144 log_error("Mixed always event with edge and/or level sensitive events!\n");
145 log(" created direct connection (no actual register cell created).\n");
146 mod
->connections
.push_back(RTLIL::SigSig(sig
, insig
));
151 log_error("Missing edge-sensitive event for this signal!\n");
153 if (!rstval
.is_fully_const() && !ce
.eval(rstval
))
154 log_error("Async reset value `%s' is not constant!\n", log_signal(rstval
));
156 gen_dff(mod
, insig
, rstval
.chunks
[0].data
, sig
,
157 sync_edge
->type
== RTLIL::SyncType::STp
,
158 sync_level
&& sync_level
->type
== RTLIL::SyncType::ST1
,
159 sync_edge
->signal
, sync_level
? &sync_level
->signal
: NULL
, proc
);
163 struct ProcDffPass
: public Pass
{
164 ProcDffPass() : Pass("proc_dff", "extract flip-flops from processes") { }
167 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
169 log(" proc_dff [selection]\n");
171 log("This pass identifies flip-flops in the processes and converts then to\n");
172 log("flip-flop cells.\n");
175 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
177 log_header("Executing PROC_DFF pass (convert process syncs to FFs).\n");
179 extra_args(args
, 1, design
);
181 for (auto &mod_it
: design
->modules
)
182 if (design
->selected(mod_it
.second
)) {
183 ConstEval
ce(mod_it
.second
);
184 for (auto &proc_it
: mod_it
.second
->processes
)
185 if (design
->selected(mod_it
.second
, proc_it
.second
))
186 proc_dff(mod_it
.second
, proc_it
.second
, ce
);