]>
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");
27 RTLIL::Cell
*f2b
= module
->addCell(NEW_ID
, "\\fp3_to_bit");
28 b2fA
->setPort("\\A", cell
->getPort("\\A"));
29 b2fA
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
30 b2fB
->setPort("\\A", cell
->getPort("\\B"));
31 b2fB
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
32 f2b
->setPort("\\A", module
->addWire(NEW_ID
, 3));
33 f2b
->setPort("\\Y", cell
->getPort("\\Y"));
34 nan
->setPort("\\A", b2fA
->getPort("\\Y"));
35 nan
->setPort("\\B", b2fB
->getPort("\\Y"));
36 nan
->setPort("\\Y", f2b
->getPort("\\A"));
37 module
->swap_names(cell
, nan
);
39 } else if (cell
->type
== "$_NOT_") {
43 RTLIL::Cell
*b2f
= module
->addCell(NEW_ID
, "\\bit_to_fp3");
44 RTLIL::Cell
*nan
= module
->addCell(NEW_ID
, "\\nan");
45 RTLIL::Cell
*f2b
= module
->addCell(NEW_ID
, "\\fp3_to_bit");
46 b2f
->setPort("\\A", cell
->getPort("\\A"));
47 b2f
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
48 f2b
->setPort("\\A", module
->addWire(NEW_ID
, 3));
49 f2b
->setPort("\\Y", cell
->getPort("\\Y"));
50 nan
->setPort("\\A", b2f
->getPort("\\Y"));
51 nan
->setPort("\\B", b2f
->getPort("\\Y"));
52 nan
->setPort("\\Y", f2b
->getPort("\\A"));
53 module
->swap_names(cell
, nan
);
60 struct NandToNaNPass
: public Pass
{
61 NandToNaNPass() : Pass("nand_to_nan") {}
62 void execute(vector
<string
> args
, Design
*design
) override
{
63 log_header(design
, "Executing NAND_TO_NaN pass (implementing tom7 logic)\n");
65 Pass::call(design
, "read_verilog -lib -sv gateware.sv");
69 for (auto module
: design
->selected_modules()) {
70 log("Replacing NAND with NaN in module %s...\n", log_id(module
));
71 NandToNaNWorker
worker(design
, module
);
72 log("Replaced %d NAND gates and %d NOT gates.\n",
73 worker
.nand_count
, worker
.not_count
);
74 log("Inserted:\n nan: %5d\n bit_to_fp3: %5d\n fp3_to_bit: %5d\n",
75 worker
.nand_count
+ worker
.not_count
,
76 worker
.b2f_count
, worker
.f2b_count
);
81 struct DffToFp3Pass
: public Pass
{
82 DffToFp3Pass() : Pass("dff_nan") {}
83 void execute(vector
<string
> args
, Design
*design
) override
{
84 log_header(design
, "Executing DFF_NaN pass (widening flipflops to hold floats)\n");
86 for (auto module
: design
->selected_modules()) {
87 log(" Module %s\n", log_id(module
));
88 dff_nan_pm
pm(module
, module
->selected_cells());
89 pool
<RTLIL::Cell
*> dffs
;
90 pm
.run([&]() { dffs
.insert(pm
.st
.dff
); });
91 for (auto &dff
: dffs
) {
92 RTLIL::Cell
*f2b
= module
->addCell(NEW_ID
, "\\fp3_to_bit");
93 f2b
->setPort("\\A", module
->addWire(NEW_ID
, 3));
94 f2b
->setPort("\\Y", dff
->getPort("\\Q"));
95 RTLIL::Cell
*b2f
= module
->addCell(NEW_ID
, "\\bit_to_fp3");
96 b2f
->setPort("\\A", dff
->getPort("\\D"));
97 b2f
->setPort("\\Y", module
->addWire(NEW_ID
, 3));
98 for (int i
= 0; i
< 3; i
++) {
99 // @TODO: Support more DFF types
100 assert(dff
->type
== "$_DFF_P_");
101 RTLIL::Cell
*new_ff
= module
->addCell(NEW_ID
, "$_DFF_P_");
102 new_ff
->setPort("\\C", dff
->getPort("\\C"));
103 new_ff
->setPort("\\D", b2f
->getPort("\\Y")[i
]);
104 new_ff
->setPort("\\Q", f2b
->getPort("\\A")[i
]);
108 log("Converted %d flip-flops to hold floats\n", GetSize(dffs
));
113 struct EraseFpBitPass
: public Pass
{
114 EraseFpBitPass() : Pass("simplify_nan") {}
115 void execute(vector
<string
> args
, Design
*design
) override
{
116 log_header(design
, "Executing SIMPLIFY_NaN pass (erasing useless conversion chains)\n");
118 for (auto module
: design
->selected_modules()) {
119 log("Simplifying NaN conversions in module %s\n", log_id(module
));
120 erase_b2f_pm
pm(module
, module
->selected_cells());
121 pool
<RTLIL::Cell
*> eraseCells
;
123 module
->connect(pm
.st
.base
->getPort("\\A"), pm
.st
.target
->getPort("\\Y"));
124 eraseCells
.insert(pm
.st
.target
);
126 for (auto cell
: eraseCells
) {
127 module
->remove(cell
);
129 log("Removed %d bit_to_fp3 nodes\n", GetSize(eraseCells
));
134 struct ShareNaN
: public Pass
{
135 ShareNaN() : Pass("share_nan") {}
136 void execute(vector
<string
> args
, Design
*design
) override
{
137 log_header(design
, "Executing SHARE_NAN pass (merging conversion cells).\n");
139 for (auto module
: design
->selected_modules()) {
140 log("Module %s\n", log_id(module
));
141 share_nan_pm
pm(module
, module
->selected_cells());
142 mfp
<RTLIL::Cell
*> sharedCells
;
143 pm
.run([&]() { sharedCells
.merge(pm
.st
.cvt_a
, pm
.st
.cvt_b
); });
145 for (auto &entry
: sharedCells
) {
146 auto &main
= sharedCells
.find(entry
);
147 if (entry
== main
) continue;
149 module
->connect(main
->getPort("\\Y"), entry
->getPort("\\Y"));
150 module
->remove(entry
);
152 log("Merged %d conversion cells\n", merged
);
157 struct TechmapNaN
: public Pass
{
158 TechmapNaN() : Pass("techmap_nan", "techmap NaN gates") {}
159 void execute(vector
<string
>, Design
*design
) override
{
160 Pass::call(design
, "techmap -autoproc -extern -map gateware.sv");
164 struct SynthNaN
: public Pass
{
165 SynthNaN() : Pass("synth_nan", "synthesize to tom7 logic") {}
166 void help() override
{
167 log("synth_nan [options]\n\n");
168 log("Runs the equivalent of the following script:\n\n");
169 log(" synth [-top <module>]\n");
170 log(" abc -g NAND\n");
171 log(" nand_to_nan\n");
174 log(" nan_simplify\n");
177 void execute(vector
<string
> args
, Design
*design
) override
{
179 log_header(design
, "Executing SYNTH_NaN pass (synthesizing to tom7 logic).\n");
181 for (size_t i
= 0; i
< args
.size(); i
++) {
182 if (args
[i
] == "-top") {
183 synth_args
+= " -top ";
184 synth_args
+= args
[i
+1];
189 Pass::call(design
, "synth" + synth_args
);
190 Pass::call(design
, "abc -g NAND");
191 Pass::call(design
, "nand_to_nan");
192 Pass::call(design
, "share_nan");
193 Pass::call(design
, "dff_nan");
194 Pass::call(design
, "simplify_nan");
195 Pass::call(design
, "clean");
196 Pass::call(design
, "techmap_nan");
201 PRIVATE_NAMESPACE_END