]>
Witch of Git - nan-gate/blob - nangate.cc
1 #include "kernel/yosys.h"
2 #include "kernel/celltypes.h"
3 #include "erase_b2f_pm.h"
4 #include "dff_nan_pm.h"
5 #include "share_nan_pm.h"
8 PRIVATE_NAMESPACE_BEGIN
10 struct NandToNaNWorker
12 int nand_count
= 0, not_count
= 0, b2f_count
= 0, f2b_count
= 0;
13 RTLIL::Design
*design
;
14 RTLIL::Module
*module
;
16 NandToNaNWorker(RTLIL::Design
*design
, RTLIL::Module
*module
) :
17 design(design
), module(module
)
19 for (auto cell
: module
->selected_cells()) {
20 if (cell
->type
== "$_NAND_") {
24 RTLIL::Cell
*b2fA
= module
->addCell(NEW_ID
, "\\bit_to_fp3");
25 RTLIL::Cell
*b2fB
= module
->addCell(NEW_ID
, "\\bit_to_fp3");
26 RTLIL::Cell
*nan
= module
->addCell(NEW_ID
, "\\nan_fp3");
27 RTLIL::Cell
*f2b
= module
->addCell(NEW_ID
, "\\fp3_to_bit");
28 b2fA
->attributes
[ID(nan_b2f
)] = 3;
29 b2fB
->attributes
[ID(nan_b2f
)] = 3;
30 nan
->attributes
[ID(nan_cell
)] = 3;
31 f2b
->attributes
[ID(nan_f2b
)] = 3;
32 b2fA
->setPort("\\A", cell
->getPort("\\A"));
33 b2fA
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
34 b2fB
->setPort("\\A", cell
->getPort("\\B"));
35 b2fB
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
36 f2b
->setPort("\\A", module
->addWire(NEW_ID
, 3));
37 f2b
->setPort("\\Y", cell
->getPort("\\Y"));
38 nan
->setPort("\\A", b2fA
->getPort("\\Y"));
39 nan
->setPort("\\B", b2fB
->getPort("\\Y"));
40 nan
->setPort("\\Y", f2b
->getPort("\\A"));
41 module
->swap_names(cell
, nan
);
43 } else if (cell
->type
== "$_NOT_") {
47 RTLIL::Cell
*b2f
= module
->addCell(NEW_ID
, "\\bit_to_fp3");
48 RTLIL::Cell
*nan
= module
->addCell(NEW_ID
, "\\nan_fp3");
49 RTLIL::Cell
*f2b
= module
->addCell(NEW_ID
, "\\fp3_to_bit");
50 b2f
->attributes
[ID(nan_b2f
)] = 3;
51 nan
->attributes
[ID(nan_cell
)] = 3;
52 f2b
->attributes
[ID(nan_f2b
)] = 3;
53 b2f
->setPort("\\A", cell
->getPort("\\A"));
54 b2f
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
55 f2b
->setPort("\\A", module
->addWire(NEW_ID
, 3));
56 f2b
->setPort("\\Y", cell
->getPort("\\Y"));
57 nan
->setPort("\\A", b2f
->getPort("\\Y"));
58 nan
->setPort("\\B", b2f
->getPort("\\Y"));
59 nan
->setPort("\\Y", f2b
->getPort("\\A"));
60 module
->swap_names(cell
, nan
);
67 struct NandToNaNPass
: public Pass
{
68 NandToNaNPass() : Pass("nand_to_nan") {}
69 void execute(vector
<string
> args
, Design
*design
) override
{
70 log_header(design
, "Executing NAND_TO_NaN pass (implementing tom7 logic)\n");
72 Pass::call(design
, "read_verilog -lib -sv +/nangate/techlib.sv");
76 for (auto module
: design
->selected_modules()) {
77 log("Replacing NAND with NaN in module %s...\n", log_id(module
));
78 NandToNaNWorker
worker(design
, module
);
79 log("Replaced %d NAND gates and %d NOT gates.\n",
80 worker
.nand_count
, worker
.not_count
);
81 log("Inserted:\n nan_fp3: %5d\n bit_to_fp3: %5d\n fp3_to_bit: %5d\n",
82 worker
.nand_count
+ worker
.not_count
,
83 worker
.b2f_count
, worker
.f2b_count
);
88 struct DffToFp3Pass
: public Pass
{
89 DffToFp3Pass() : Pass("dff_nan") {}
90 void execute(vector
<string
> args
, Design
*design
) override
{
91 log_header(design
, "Executing DFF_NaN pass (widening flipflops to hold floats)\n");
93 for (auto module
: design
->selected_modules()) {
94 log(" Module %s\n", log_id(module
));
95 dff_nan_pm
pm(module
, module
->selected_cells());
96 pool
<RTLIL::Cell
*> dffs
;
97 pm
.run([&]() { dffs
.insert(pm
.st
.dff
); });
98 for (auto &dff
: dffs
) {
99 RTLIL::Cell
*f2b
= module
->addCell(NEW_ID
, "\\fp3_to_bit");
100 f2b
->attributes
[ID(nan_f2b
)] = 3;
101 f2b
->setPort("\\A", module
->addWire(NEW_ID
, 3));
102 f2b
->setPort("\\Y", dff
->getPort("\\Q"));
103 RTLIL::Cell
*b2f
= module
->addCell(NEW_ID
, "\\bit_to_fp3");
104 b2f
->attributes
[ID(nan_b2f
)] = 3;
105 b2f
->setPort("\\A", dff
->getPort("\\D"));
106 b2f
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
107 for (int i
= 0; i
< 3; i
++) {
108 // @TODO: Support more DFF types
109 assert(dff
->type
== "$_DFF_P_");
110 RTLIL::Cell
*new_ff
= module
->addCell(NEW_ID
, "$_DFF_P_");
111 new_ff
->setPort("\\C", dff
->getPort("\\C"));
112 new_ff
->setPort("\\D", b2f
->getPort("\\Y")[i
]);
113 new_ff
->setPort("\\Q", f2b
->getPort("\\A")[i
]);
117 log("Converted %d flip-flops to hold floats\n", GetSize(dffs
));
122 struct EraseFpBitPass
: public Pass
{
123 EraseFpBitPass() : Pass("simplify_nan") {}
124 void execute(vector
<string
> args
, Design
*design
) override
{
125 log_header(design
, "Executing SIMPLIFY_NaN pass (erasing useless conversion chains)\n");
127 for (auto module
: design
->selected_modules()) {
128 log("Simplifying NaN conversions in module %s\n", log_id(module
));
129 erase_b2f_pm
pm(module
, module
->selected_cells());
130 pool
<RTLIL::Cell
*> eraseCells
;
132 module
->connect(pm
.st
.base
->getPort("\\A"), pm
.st
.target
->getPort("\\Y"));
133 eraseCells
.insert(pm
.st
.target
);
135 for (auto cell
: eraseCells
) {
136 module
->remove(cell
);
138 log("Removed %d bit_to_fp3 nodes\n", GetSize(eraseCells
));
143 struct ShareNaN
: public Pass
{
144 ShareNaN() : Pass("share_nan") {}
145 void execute(vector
<string
> args
, Design
*design
) override
{
146 log_header(design
, "Executing SHARE_NAN pass (merging conversion cells).\n");
148 for (auto module
: design
->selected_modules()) {
149 log("Module %s\n", log_id(module
));
150 share_nan_pm
pm(module
, module
->selected_cells());
151 mfp
<RTLIL::Cell
*> sharedCells
;
152 pm
.run([&]() { sharedCells
.merge(pm
.st
.cvt_a
, pm
.st
.cvt_b
); });
154 for (auto &entry
: sharedCells
) {
155 auto &main
= sharedCells
.find(entry
);
156 if (entry
== main
) continue;
158 module
->connect(main
->getPort("\\Y"), entry
->getPort("\\Y"));
159 module
->remove(entry
);
161 log("Merged %d conversion cells\n", merged
);
166 struct TechmapNaN
: public Pass
{
167 TechmapNaN() : Pass("techmap_nan", "techmap NaN gates") {}
168 void execute(vector
<string
>, Design
*design
) override
{
169 Pass::call(design
, "techmap -autoproc -extern -map +/nangate/techlib.sv");
173 struct SynthNaN
: public Pass
{
174 SynthNaN() : Pass("synth_nan", "synthesize to tom7 logic") {}
175 void help() override
{
176 log("synth_nan [options]\n\n");
177 log("Runs the equivalent of the following script:\n\n");
178 log(" synth [-top <module>]\n");
179 log(" abc -g NAND\n");
180 log(" nand_to_nan\n");
183 log(" simplify_nan\n");
185 log(" techmap_nan\n");
187 void execute(vector
<string
> args
, Design
*design
) override
{
189 log_header(design
, "Executing SYNTH_NaN pass (synthesizing to tom7 logic).\n");
191 for (size_t i
= 0; i
< args
.size(); i
++) {
192 if (args
[i
] == "-top") {
193 synth_args
+= " -top ";
194 synth_args
+= args
[i
+1];
199 Pass::call(design
, "synth" + synth_args
);
200 Pass::call(design
, "abc -g NAND");
201 Pass::call(design
, "nand_to_nan");
202 Pass::call(design
, "share_nan");
203 Pass::call(design
, "dff_nan");
204 Pass::call(design
, "simplify_nan");
205 Pass::call(design
, "clean");
206 Pass::call(design
, "techmap_nan");
211 PRIVATE_NAMESPACE_END