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/yosys.h"
21 #include "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
26 struct Async2syncPass
: public Pass
{
27 Async2syncPass() : Pass("async2sync", "convert async FF inputs to sync circuits") { }
28 void help() YS_OVERRIDE
30 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
32 log(" async2sync [options] [selection]\n");
34 log("This command replaces async FF inputs with sync circuits emulating the same\n");
35 log("behavior for when the async signals are actually synchronized to the clock.\n");
37 log("This pass assumes negative hold time for the async FF inputs. For example when\n");
38 log("a reset deasserts with the clock edge, then the FF output will still drive the\n");
39 log("reset value in the next cycle regardless of the data-in value at the time of\n");
40 log("the clock edge.\n");
42 log("Currently only $adff cells are supported by this pass.\n");
45 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
47 // bool flag_noinit = false;
49 log_header(design
, "Executing ASYNC2SYNC pass.\n");
52 for (argidx
= 1; argidx
< args
.size(); argidx
++)
54 // if (args[argidx] == "-noinit") {
55 // flag_noinit = true;
60 extra_args(args
, argidx
, design
);
62 for (auto module
: design
->selected_modules())
64 SigMap
sigmap(module
);
65 dict
<SigBit
, State
> initbits
;
66 pool
<SigBit
> del_initbits
;
68 for (auto wire
: module
->wires())
69 if (wire
->attributes
.count("\\init") > 0)
71 Const initval
= wire
->attributes
.at("\\init");
72 SigSpec initsig
= sigmap(wire
);
74 for (int i
= 0; i
< GetSize(initval
) && i
< GetSize(initsig
); i
++)
75 if (initval
[i
] == State::S0
|| initval
[i
] == State::S1
)
76 initbits
[initsig
[i
]] = initval
[i
];
79 for (auto cell
: vector
<Cell
*>(module
->selected_cells()))
81 if (cell
->type
.in("$adff"))
83 // bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool();
84 bool arst_pol
= cell
->parameters
["\\ARST_POLARITY"].as_bool();
85 Const arst_val
= cell
->parameters
["\\ARST_VALUE"];
87 SigSpec sig_clk
= cell
->getPort("\\CLK");
88 SigSpec sig_arst
= cell
->getPort("\\ARST");
89 SigSpec sig_d
= cell
->getPort("\\D");
90 SigSpec sig_q
= cell
->getPort("\\Q");
92 log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
93 log_id(module
), log_id(cell
), log_id(cell
->type
),
94 log_signal(sig_arst
), log_signal(sig_d
), log_signal(sig_q
));
97 for (int i
= 0; i
< GetSize(sig_q
); i
++) {
98 SigBit bit
= sigmap(sig_q
[i
]);
99 init_val
.bits
.push_back(initbits
.count(bit
) ? initbits
.at(bit
) : State::Sx
);
100 del_initbits
.insert(bit
);
103 Wire
*new_d
= module
->addWire(NEW_ID
, GetSize(sig_d
));
104 Wire
*new_q
= module
->addWire(NEW_ID
, GetSize(sig_q
));
105 new_q
->attributes
["\\init"] = init_val
;
108 module
->addMux(NEW_ID
, sig_d
, arst_val
, sig_arst
, new_d
);
109 module
->addMux(NEW_ID
, new_q
, arst_val
, sig_arst
, sig_q
);
111 module
->addMux(NEW_ID
, arst_val
, sig_d
, sig_arst
, new_d
);
112 module
->addMux(NEW_ID
, arst_val
, new_q
, sig_arst
, sig_q
);
115 cell
->setPort("\\D", new_d
);
116 cell
->setPort("\\Q", new_q
);
117 cell
->unsetPort("\\ARST");
118 cell
->unsetParam("\\ARST_POLARITY");
119 cell
->unsetParam("\\ARST_VALUE");
125 for (auto wire
: module
->wires())
126 if (wire
->attributes
.count("\\init") > 0)
128 bool delete_initattr
= true;
129 Const initval
= wire
->attributes
.at("\\init");
130 SigSpec initsig
= sigmap(wire
);
132 for (int i
= 0; i
< GetSize(initval
) && i
< GetSize(initsig
); i
++)
133 if (del_initbits
.count(initsig
[i
]) > 0)
134 initval
[i
] = State::Sx
;
135 else if (initval
[i
] != State::Sx
)
136 delete_initattr
= false;
139 wire
->attributes
.erase("\\init");
141 wire
->attributes
.at("\\init") = initval
;
147 PRIVATE_NAMESPACE_END