2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
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 static SigBit
get_bit_or_zero(const SigSpec
&sig
)
28 if (GetSize(sig
) == 0)
33 static void fix_carry_chain(Module
*module
)
35 SigMap
sigmap(module
);
38 dict
<SigBit
, SigBit
> mapping_bits
;
40 for (auto cell
: module
->cells())
42 if (cell
->type
== ID(EFX_ADD
)) {
43 SigBit bit_i0
= get_bit_or_zero(cell
->getPort(ID(I0
)));
44 SigBit bit_i1
= get_bit_or_zero(cell
->getPort(ID(I1
)));
45 if (bit_i0
== State::S0
&& bit_i1
== State::S0
) {
46 SigBit bit_ci
= get_bit_or_zero(cell
->getPort(ID::CI
));
47 SigBit bit_o
= sigmap(cell
->getPort(ID::O
));
48 ci_bits
.insert(bit_ci
);
49 mapping_bits
[bit_ci
] = bit_o
;
54 vector
<Cell
*> adders_to_fix_cells
;
55 for (auto cell
: module
->cells())
57 if (cell
->type
== ID(EFX_ADD
)) {
58 SigBit bit_ci
= get_bit_or_zero(cell
->getPort(ID::CI
));
59 SigBit bit_i0
= get_bit_or_zero(cell
->getPort(ID(I0
)));
60 SigBit bit_i1
= get_bit_or_zero(cell
->getPort(ID(I1
)));
61 SigBit canonical_bit
= sigmap(bit_ci
);
62 if (!ci_bits
.count(canonical_bit
))
64 if (bit_i0
== State::S0
&& bit_i1
== State::S0
)
67 adders_to_fix_cells
.push_back(cell
);
68 log("Found %s cell named %s with invalid CI signal.\n", log_id(cell
->type
), log_id(cell
));
72 for (auto cell
: adders_to_fix_cells
)
74 SigBit bit_ci
= get_bit_or_zero(cell
->getPort(ID::CI
));
75 SigBit canonical_bit
= sigmap(bit_ci
);
76 auto bit
= mapping_bits
.at(canonical_bit
);
77 log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell
->type
), log_id(cell
));
78 Cell
*c
= module
->addCell(NEW_ID
, ID(EFX_ADD
));
79 SigBit new_bit
= module
->addWire(NEW_ID
);
80 c
->setParam(ID(I0_POLARITY
), State::S1
);
81 c
->setParam(ID(I1_POLARITY
), State::S1
);
82 c
->setPort(ID(I0
), bit
);
83 c
->setPort(ID(I1
), State::S1
);
84 c
->setPort(ID::CI
, State::S0
);
85 c
->setPort(ID::CO
, new_bit
);
87 cell
->setPort(ID::CI
, new_bit
);
91 struct EfinixCarryFixPass
: public Pass
{
92 EfinixCarryFixPass() : Pass("efinix_fixcarry", "Efinix: fix carry chain") { }
93 void help() YS_OVERRIDE
95 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
97 log(" efinix_fixcarry [options] [selection]\n");
99 log("Add Efinix adders to fix carry chain if needed.\n");
102 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
104 log_header(design
, "Executing EFINIX_FIXCARRY pass (fix invalid carry chain).\n");
107 for (argidx
= 1; argidx
< args
.size(); argidx
++)
111 extra_args(args
, argidx
, design
);
113 Module
*module
= design
->top_module();
115 if (module
== nullptr)
116 log_cmd_error("No top module found.\n");
118 fix_carry_chain(module
);
120 } EfinixCarryFixPass
;
122 PRIVATE_NAMESPACE_END