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 #include "passes/pmgen/ice40_wrapcarry_pm.h"
28 void create_ice40_wrapcarry(ice40_wrapcarry_pm
&pm
)
30 auto &st
= pm
.st_ice40_wrapcarry
;
34 log("carry: %s\n", log_id(st
.carry
, "--"));
35 log("lut: %s\n", log_id(st
.lut
, "--"));
38 log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n");
40 Cell
*cell
= pm
.module
->addCell(NEW_ID
, ID($__ICE40_CARRY_WRAPPER
));
41 pm
.module
->swap_names(cell
, st
.carry
);
43 cell
->setPort(ID::A
, st
.carry
->getPort(ID(I0
)));
44 cell
->setPort(ID::B
, st
.carry
->getPort(ID(I1
)));
45 auto CI
= st
.carry
->getPort(ID::CI
);
46 cell
->setPort(ID::CI
, CI
);
47 cell
->setPort(ID::CO
, st
.carry
->getPort(ID::CO
));
49 cell
->setPort(ID(I0
), st
.lut
->getPort(ID(I0
)));
50 auto I3
= st
.lut
->getPort(ID(I3
));
51 if (pm
.sigmap(CI
) == pm
.sigmap(I3
)) {
52 cell
->setParam(ID(I3_IS_CI
), State::S1
);
56 cell
->setParam(ID(I3_IS_CI
), State::S0
);
57 cell
->setPort(ID(I3
), I3
);
58 cell
->setPort(ID::O
, st
.lut
->getPort(ID::O
));
59 cell
->setParam(ID::LUT
, st
.lut
->getParam(ID(LUT_INIT
)));
61 for (const auto &a
: st
.carry
->attributes
)
62 cell
->attributes
[stringf("\\SB_CARRY.%s", a
.first
.c_str())] = a
.second
;
63 for (const auto &a
: st
.lut
->attributes
)
64 cell
->attributes
[stringf("\\SB_LUT4.%s", a
.first
.c_str())] = a
.second
;
65 cell
->attributes
[ID(SB_LUT4
.name
)] = Const(st
.lut
->name
.str());
66 if (st
.carry
->get_bool_attribute(ID::keep
) || st
.lut
->get_bool_attribute(ID::keep
))
67 cell
->attributes
[ID::keep
] = true;
69 pm
.autoremove(st
.carry
);
70 pm
.autoremove(st
.lut
);
73 struct Ice40WrapCarryPass
: public Pass
{
74 Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { }
75 void help() YS_OVERRIDE
77 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
79 log(" ice40_wrapcarry [selection]\n");
81 log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUT4s,\n");
82 log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n");
85 log("Attributes on both cells will have their names prefixed with 'SB_CARRY.' or\n");
86 log("'SB_LUT4.' and attached to the wrapping cell.\n");
87 log("A (* keep *) attribute on either cell will be logically OR-ed together.\n");
90 log(" unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s,\n");
91 log(" including restoring their attributes.\n");
94 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
98 log_header(design
, "Executing ICE40_WRAPCARRY pass (wrap carries).\n");
101 for (argidx
= 1; argidx
< args
.size(); argidx
++)
103 if (args
[argidx
] == "-unwrap") {
109 extra_args(args
, argidx
, design
);
111 for (auto module
: design
->selected_modules()) {
113 ice40_wrapcarry_pm(module
, module
->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry
);
115 for (auto cell
: module
->selected_cells()) {
116 if (cell
->type
!= ID($__ICE40_CARRY_WRAPPER
))
119 auto carry
= module
->addCell(NEW_ID
, ID(SB_CARRY
));
120 carry
->setPort(ID(I0
), cell
->getPort(ID::A
));
121 carry
->setPort(ID(I1
), cell
->getPort(ID::B
));
122 carry
->setPort(ID::CI
, cell
->getPort(ID::CI
));
123 carry
->setPort(ID::CO
, cell
->getPort(ID::CO
));
124 module
->swap_names(carry
, cell
);
125 auto lut_name
= cell
->attributes
.at(ID(SB_LUT4
.name
), Const(NEW_ID
.str())).decode_string();
126 auto lut
= module
->addCell(lut_name
, ID($lut
));
127 lut
->setParam(ID::WIDTH
, 4);
128 lut
->setParam(ID::LUT
, cell
->getParam(ID::LUT
));
129 auto I3
= cell
->getPort(cell
->getParam(ID(I3_IS_CI
)).as_bool() ? ID::CI
: ID(I3
));
130 lut
->setPort(ID::A
, { I3
, cell
->getPort(ID::B
), cell
->getPort(ID::A
), cell
->getPort(ID(I0
)) });
131 lut
->setPort(ID::Y
, cell
->getPort(ID::O
));
134 for (const auto &a
: cell
->attributes
)
135 if (a
.first
.begins_with("\\SB_CARRY.\\"))
136 carry
->attributes
[a
.first
.c_str() + strlen("\\SB_CARRY.")] = a
.second
;
137 else if (a
.first
.begins_with("\\SB_LUT4.\\"))
138 lut
->attributes
[a
.first
.c_str() + strlen("\\SB_LUT4.")] = a
.second
;
139 else if (a
.first
== ID::src
)
141 else if (a
.first
.in(ID(SB_LUT4
.name
), ID::keep
, ID::module_not_derived
))
147 carry
->attributes
.insert(std::make_pair(ID::src
, src
));
148 lut
->attributes
.insert(std::make_pair(ID::src
, src
));
151 module
->remove(cell
);
156 } Ice40WrapCarryPass
;
158 PRIVATE_NAMESPACE_END