PandA-2024.02
flopoco_wrapper.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
33 
48 #include "config_SKIP_WARNING_SECTIONS.hpp"
50 #include "config_WPEDANTIC.hpp"
51 
53 #include "structural_objects.hpp"
54 
56 #include "flopoco_wrapper.hpp"
57 
59 #include "dbgPrintHelper.hpp"
60 #include "exceptions.hpp"
61 #include "utility.hpp"
62 
64 #include <cerrno>
65 #include <unistd.h>
66 
68 #include <fstream>
69 #include <iosfwd>
70 
72 #include "custom_map.hpp"
73 #include "custom_set.hpp"
74 #include <vector>
75 
76 #include "fileIO.hpp"
77 
78 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
79 #pragma GCC diagnostic push
80 #pragma GCC diagnostic ignored "-Wshadow"
81 #pragma GCC diagnostic ignored "-Wconversion"
82 #pragma GCC diagnostic ignored "-Wold-style-cast"
83 #pragma GCC diagnostic ignored "-Wsign-conversion"
84 #pragma GCC diagnostic ignored "-Wredundant-decls"
85 #pragma GCC diagnostic ignored "-Wunused-parameter"
86 #if WPEDANTIC
87 #pragma GCC diagnostic ignored "-Wpedantic"
88 #endif
89 #else
90 #pragma GCC diagnostic warning "-Wshadow"
91 #pragma GCC diagnostic warning "-Wconversion"
92 #pragma GCC diagnostic warning "-Wold-style-cast"
93 #pragma GCC diagnostic warning "-Wsign-conversion"
94 #pragma GCC diagnostic warning "-Wredundant-decls"
95 #pragma GCC diagnostic warning "-Wunused-parameter"
96 #if WPEDANTIC
97 #pragma GCC diagnostic warning "-Wpedantic"
98 #endif
99 #endif
100 
102 #undef DEBUG
103 #include "FP2Fix.hpp"
104 #include "FPAdderSinglePath.hpp"
105 #include "FPAssign.hpp"
106 #include "FPDiv.hpp"
107 #include "FPExp.hpp"
108 #include "FPLog.hpp"
109 #include "FPMultiplier.hpp"
110 #include "FPPow.hpp"
111 #include "FPSqrt.hpp"
112 #include "FPSqrtPoly.hpp"
113 #include "FPge_expr.hpp"
114 #include "FPgt_expr.hpp"
115 #include "FPle_expr.hpp"
116 #include "FPlt_expr.hpp"
117 #include "Fix2FP.hpp"
118 #include "InputIEEE.hpp"
119 #include "Operator.hpp"
120 #include "OutputIEEE.hpp"
121 #include "Target.hpp"
122 #include "Targets/CycloneII.hpp"
123 #include "Targets/CycloneV.hpp"
124 #include "Targets/Spartan3.hpp"
125 #include "Targets/StratixII.hpp"
126 #include "Targets/StratixIII.hpp"
127 #include "Targets/StratixIV.hpp"
128 #include "Targets/Virtex4.hpp"
129 #include "Targets/Virtex5.hpp"
130 #include "Targets/Virtex6.hpp"
131 
132 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
133 #pragma GCC diagnostic pop
134 #endif
135 
138 
139 #define OPLIST oplist
140 
141 namespace flopoco
142 {
143  std::string filename = "flopoco.vhdl";
144  std::string cl_name = "";
145  int LongAccN = 0;
146  /* flex vars */
148  vector<pair<string, int>> theUseTable;
150 } // namespace flopoco
151 
153 #ifndef NDEBUG
154  _debug_level
155 #endif
156  ,
157  const std::string& FU_target)
158  :
159 #ifndef NDEBUG
160  debug_level(_debug_level),
161 #endif
163  type(UT_UNKNOWN),
164  signed_p(false)
165 {
166  // Get the target architecture
167  if("Spartan-3" == FU_target)
168  {
169  target = new flopoco::Spartan3();
170  }
171  else if("Virtex-4" == FU_target)
172  {
173  target = new flopoco::Virtex4();
174  }
175  else if("Virtex-5" == FU_target)
176  {
177  target = new flopoco::Virtex5();
178  }
179  else if("Virtex-6" == FU_target)
180  {
181  target = new flopoco::Virtex6();
182  }
183  else if(FU_target.find("Virtex-7") != std::string::npos)
184  {
185  target = new flopoco::Virtex6();
186  }
187  else if(FU_target.find("Ultrascale") != std::string::npos)
188  {
189  target = new flopoco::Virtex6();
190  }
191  else if(FU_target.find("Zynq") != std::string::npos)
192  {
193  target = new flopoco::Virtex6();
194  }
195  else if(FU_target.find("Artix-7") != std::string::npos)
196  {
197  target = new flopoco::Virtex6();
198  }
199  else if(FU_target.find("CycloneII") != std::string::npos)
200  {
201  target = new flopoco::CycloneII();
202  }
203  else if(FU_target.find("CycloneV") != std::string::npos)
204  {
205  target = new flopoco::CycloneV();
206  }
207  else if(FU_target.find("StratixII") != std::string::npos)
208  {
209  target = new flopoco::StratixII();
210  }
211  else if(FU_target.find("StratixIII") != std::string::npos)
212  {
213  target = new flopoco::StratixIII();
214  }
215  else if(FU_target.find("StratixIV") != std::string::npos)
216  {
217  target = new flopoco::StratixIV();
218  }
219  else if(FU_target.find("StratixV") != std::string::npos)
220  {
221  target = new flopoco::StratixIV();
222  }
223  else if(FU_target.find("LatticeECP3") != std::string::npos)
224  {
225  target = new flopoco::CycloneII();
226  }
227  else if(FU_target.find("LatticeECP5") != std::string::npos)
228  {
229  target = new flopoco::CycloneII();
230  }
231  else if("NG-MEDIUM" == FU_target)
232  {
233  target = new flopoco::Virtex5();
234  }
235  else if("NG-LARGE" == FU_target)
236  {
237  target = new flopoco::Virtex5();
238  }
239  else if("NG-ULTRA" == FU_target)
240  {
241  target = new flopoco::Virtex6();
242  }
243  else if(FU_target.find("Generic") != std::string::npos)
244  {
245  target = new flopoco::Virtex5();
246  }
247  else
248  {
249  THROW_UNREACHABLE("Non supported target architecture: " + FU_target);
250  }
251 
253  jmp_buf recover;
254 
255  initTool();
256  if(setjmp(recover))
257  {
258  /* If we are here, we have come back from an error in the library */
259  THROW_ERROR("An error occurred somewhere");
260  }
261  setRecoverEnvironment(&recover);
262  extern int recoverEnvironmentReady;
263  recoverEnvironmentReady = 1;
264 }
265 
267 {
268  // finishTool();
269 }
270 
271 void flopoco_wrapper::add_FU(const std::string& FU_type, unsigned int FU_prec_in, unsigned int FU_prec_out,
272  const std::string& FU_name, const std::string& pipe_parameter)
273 {
274  // Get the number of bits for the number representation
275  unsigned int n_mant_in, n_exp_in;
276  unsigned int n_mant_out, n_exp_out;
277  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
278  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
279  signed_p = false;
280  double freq;
281 
283  "Creating FloPoCo operator for unit " + FU_type + "(" + STR(FU_prec_in) + "-" + STR(FU_prec_out) +
284  "-" + pipe_parameter + ")");
285 
286  if(pipe_parameter != "" && pipe_parameter != "0")
287  {
288  target->setPipelined();
289  freq = std::stod(pipe_parameter);
290  }
291  else
292  {
293  target->setNotPipelined();
295  }
296 
298  target->setFrequency(1e6 * freq);
299 
300  flopoco::Operator* op = nullptr;
301  THROW_ASSERT(n_mant_in > 0 && n_exp_in > 0, "Unsupported significand and exponent values.");
302  THROW_ASSERT(n_mant_out > 0 && n_exp_out > 0, "Unsupported significand and exponent values.");
303 
304  // Get the Functional Unit, sets correct name, then adds to resources
305  type = flopoco_wrapper::UT_UNKNOWN;
306  if("FPAdder" == FU_type)
307  {
308  type = flopoco_wrapper::UT_ADD;
309  op = new flopoco::FPAdderSinglePath(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
310  static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
311  static_cast<int>(n_exp_out), static_cast<int>(n_mant_out));
312  }
313  else if("FPSub" == FU_type)
314  {
315  type = flopoco_wrapper::UT_SUB;
316  op = new flopoco::FPAdderSinglePath(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
317  static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
318  static_cast<int>(n_exp_out), static_cast<int>(n_mant_out));
319  }
320  else if("FPAddSub" == FU_type)
321  {
322  type = flopoco_wrapper::UT_ADDSUB;
323  op = new flopoco::FPAdderSinglePath(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
324  static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
325  static_cast<int>(n_exp_out), static_cast<int>(n_mant_out));
326  }
327  else if("FPMultiplier" == FU_type)
328  {
329  type = flopoco_wrapper::UT_MULT;
330  op = new flopoco::FPMultiplier(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
331  static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
332  static_cast<int>(n_exp_out), static_cast<int>(n_mant_out));
333  }
334  else if("FPDiv" == FU_type)
335  {
336  type = flopoco_wrapper::UT_DIV;
337  op = new flopoco::FPDiv(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in));
338  }
339  else if("FPExp" == FU_type)
340  {
341  type = flopoco_wrapper::UT_EXP;
342  op = new flopoco::FPExp(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in), 0, 0, -1, false, 0.7f);
343  }
344  else if("FPSqrtPoly" == FU_type)
345  {
346  type = flopoco_wrapper::UT_SQRT;
347  op =
348  new flopoco::FPSqrtPoly(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in), false, 3 /*degree*/);
349  }
350  else if("FPSqrt" == FU_type)
351  {
352  type = flopoco_wrapper::UT_SQRT;
353  op = new flopoco::FPSqrt(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in));
354  }
355  else if("Fix2FP_32_32" == FU_type)
356  {
357  signed_p = true;
358  type = flopoco_wrapper::UT_IFIX2FP;
359  FU_prec_out = 32;
360  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
361  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 1, static_cast<int>(n_exp_out),
362  static_cast<int>(n_mant_out));
363  }
364  else if("Fix2FP_32_64" == FU_type)
365  {
366  signed_p = true;
367  type = flopoco_wrapper::UT_IFIX2FP;
368  FU_prec_out = 64;
369  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
370  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 1, static_cast<int>(n_exp_out),
371  static_cast<int>(n_mant_out));
372  }
373  else if("Fix2FP_64_32" == FU_type)
374  {
375  signed_p = true;
376  FU_prec_out = 32;
377  type = flopoco_wrapper::UT_IFIX2FP;
378  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
379  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 1, static_cast<int>(n_exp_out),
380  static_cast<int>(n_mant_out));
381  }
382  else if("Fix2FP_64_64" == FU_type)
383  {
384  signed_p = true;
385  type = flopoco_wrapper::UT_IFIX2FP;
386  FU_prec_out = 64;
387  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
388  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 1, static_cast<int>(n_exp_out),
389  static_cast<int>(n_mant_out));
390  }
391  else if("UFix2FP_32_32" == FU_type)
392  {
393  type = flopoco_wrapper::UT_UFIX2FP;
394  FU_prec_out = 32;
395  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
396  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 0, static_cast<int>(n_exp_out),
397  static_cast<int>(n_mant_out));
398  }
399  else if("UFix2FP_32_64" == FU_type)
400  {
401  type = flopoco_wrapper::UT_UFIX2FP;
402  FU_prec_out = 64;
403  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
404  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 0, static_cast<int>(n_exp_out),
405  static_cast<int>(n_mant_out));
406  }
407  else if("UFix2FP_64_32" == FU_type)
408  {
409  type = flopoco_wrapper::UT_UFIX2FP;
410  FU_prec_out = 32;
411  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
412  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 0, static_cast<int>(n_exp_out),
413  static_cast<int>(n_mant_out));
414  }
415  else if("UFix2FP_64_64" == FU_type)
416  {
417  type = flopoco_wrapper::UT_UFIX2FP;
418  FU_prec_out = 64;
419  DECODE_BITS(FU_prec_out, n_mant_out, n_exp_out);
420  op = new flopoco::Fix2FP(target, 0, static_cast<int>(FU_prec_in) - 1, 0, static_cast<int>(n_exp_out),
421  static_cast<int>(n_mant_out));
422  }
423  else if("FP2Fix_32_32" == FU_type)
424  {
425  type = flopoco_wrapper::UT_FP2IFIX;
426  FU_prec_in = 32;
427  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
428  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 1, static_cast<int>(n_exp_in),
429  static_cast<int>(n_mant_in), true);
430  }
431  else if("FP2Fix_32_u32" == FU_type)
432  {
433  type = flopoco_wrapper::UT_FP2UFIX;
434  FU_prec_in = 32;
435  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
436  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 0, static_cast<int>(n_exp_in),
437  static_cast<int>(n_mant_in), true);
438  }
439  else if("FP2Fix_32_64" == FU_type)
440  {
441  type = flopoco_wrapper::UT_FP2IFIX;
442  FU_prec_in = 32;
443  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
444  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 1, static_cast<int>(n_exp_in),
445  static_cast<int>(n_mant_in), true);
446  }
447  else if("FP2Fix_32_u64" == FU_type)
448  {
449  type = flopoco_wrapper::UT_FP2UFIX;
450  FU_prec_in = 32;
451  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
452  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 0, static_cast<int>(n_exp_in),
453  static_cast<int>(n_mant_in), true);
454  }
455  else if("FP2Fix_64_32" == FU_type)
456  {
457  type = flopoco_wrapper::UT_FP2IFIX;
458  FU_prec_in = 64;
459  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
460  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 1, static_cast<int>(n_exp_in),
461  static_cast<int>(n_mant_in), true);
462  }
463  else if("FP2Fix_64_u32" == FU_type)
464  {
465  type = flopoco_wrapper::UT_FP2UFIX;
466  FU_prec_in = 64;
467  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
468  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 0, static_cast<int>(n_exp_in),
469  static_cast<int>(n_mant_in), true);
470  }
471  else if("FP2Fix_64_64" == FU_type)
472  {
473  type = flopoco_wrapper::UT_FP2IFIX;
474  FU_prec_in = 64;
475  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
476  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 1, static_cast<int>(n_exp_in),
477  static_cast<int>(n_mant_in), true);
478  }
479  else if("FP2Fix_64_u64" == FU_type)
480  {
481  type = flopoco_wrapper::UT_FP2UFIX;
482  FU_prec_in = 64;
483  DECODE_BITS(FU_prec_in, n_mant_in, n_exp_in);
484  op = new flopoco::FP2Fix(target, 0, static_cast<int>(FU_prec_out) - 1, 0, static_cast<int>(n_exp_in),
485  static_cast<int>(n_mant_in), true);
486  }
487  else if("FF_CONV" == FU_type)
488  {
489  type = flopoco_wrapper::UT_FF_CONV;
490  op = new flopoco::FPAssign(target, static_cast<int>(n_exp_out), static_cast<int>(n_mant_out));
491  }
492  else if("FPgt_expr" == FU_type)
493  {
494  type = flopoco_wrapper::UT_compare_expr;
495  op = new flopoco::FPgt_expr(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in));
496  }
497  else if("FPlt_expr" == FU_type)
498  {
499  type = flopoco_wrapper::UT_compare_expr;
500  op = new flopoco::FPlt_expr(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in));
501  }
502  else if("FPge_expr" == FU_type)
503  {
504  type = flopoco_wrapper::UT_compare_expr;
505  op = new flopoco::FPge_expr(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in));
506  }
507  else if("FPle_expr" == FU_type)
508  {
509  type = flopoco_wrapper::UT_compare_expr;
510  op = new flopoco::FPle_expr(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in));
511  }
512  else if("FPLog" == FU_type)
513  {
514  type = flopoco_wrapper::UT_LOG;
515  op = new flopoco::FPLog(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in), 0);
516  }
517  else if("FPPow" == FU_type)
518  {
519  type = flopoco_wrapper::UT_POW;
520  op = new flopoco::FPPow(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in), 0);
521  }
522  else
523  {
524  THROW_UNREACHABLE("Not supported FU: " + FU_type);
525  }
526  OPLIST.push_back(op);
527  std::string FU_name_stored;
528  FU_name_stored = ENCODE_NAME(FU_name, FU_prec_in, FU_prec_out, pipe_parameter);
529  op->changeName(WRAPPED_PREFIX + FU_name_stored);
530  FUs[WRAPPED_PREFIX + FU_name_stored] = op;
531  FU_to_prec.insert(make_pair(FU_name_stored, std::pair<unsigned int, unsigned int>(FU_prec_in, FU_prec_out)));
532 
533  // Adds two additional Functional Units to perform conversion
534  // from FloCoCo encoding to IEEE-754 number format and viceversa
535  if(type != flopoco_wrapper::UT_IFIX2FP and type != flopoco_wrapper::UT_UFIX2FP)
536  {
537  if(type == flopoco_wrapper::UT_FF_CONV)
538  {
539  op = new flopoco::InputIEEE(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
540  static_cast<int>(n_exp_out), static_cast<int>(n_mant_out));
541  }
542  else
543  {
544  op = new flopoco::InputIEEE(target, static_cast<int>(n_exp_in), static_cast<int>(n_mant_in),
545  static_cast<int>(n_exp_in), static_cast<int>(n_mant_in));
546  }
547  OPLIST.push_back(op);
548  op->changeName(IN_WRAP_PREFIX + FU_name_stored);
549  FUs[IN_WRAP_PREFIX + FU_name_stored] = op;
550  }
551  if(type != flopoco_wrapper::UT_FP2UFIX and type != flopoco_wrapper::UT_FP2IFIX and
552  type != flopoco_wrapper::UT_compare_expr)
553  {
554  op = new flopoco::OutputIEEE(target, static_cast<int>(n_exp_out), static_cast<int>(n_mant_out),
555  static_cast<int>(n_exp_out), static_cast<int>(n_mant_out), true);
556  OPLIST.push_back(op);
557  op->changeName(OUT_WRAP_PREFIX + FU_name_stored);
558  FUs[OUT_WRAP_PREFIX + FU_name_stored] = op;
559  }
560 }
561 
562 unsigned int flopoco_wrapper::get_FUPipelineDepth(const std::string& FU_name, const unsigned int FU_prec_in,
563  const unsigned int FU_prec_out,
564  const std::string& pipe_parameter) const
565 {
566  std::string FU_name_stored = ENCODE_NAME(FU_name, FU_prec_in, FU_prec_out, pipe_parameter);
567  unsigned int fu_pipe_depth = static_cast<unsigned int>(get_FU(WRAPPED_PREFIX + FU_name_stored)->getPipelineDepth());
568  if(type != flopoco_wrapper::UT_IFIX2FP and type != flopoco_wrapper::UT_UFIX2FP)
569  {
570  fu_pipe_depth += static_cast<unsigned int>(get_FU(IN_WRAP_PREFIX + FU_name_stored)->getPipelineDepth());
571  }
572  if(type != flopoco_wrapper::UT_FP2UFIX and type != flopoco_wrapper::UT_FP2IFIX and
573  type != flopoco_wrapper::UT_compare_expr)
574  {
575  fu_pipe_depth += static_cast<unsigned int>(get_FU(OUT_WRAP_PREFIX + FU_name_stored)->getPipelineDepth());
576  }
577  return fu_pipe_depth;
578 }
579 
580 flopoco::Operator* flopoco_wrapper::get_FU(std::string FU_name_stored) const
581 {
582  auto op_found = FUs.find(FU_name_stored);
583  THROW_ASSERT(op_found != FUs.end(), "Functional unit " + FU_name_stored + " not found (maybe not yet generated)");
584  return op_found->second;
585 }
586 
587 void flopoco_wrapper::outputWrapVHDL(const std::string& FU_name_stored, std::ostream& os,
588  const std::string& pipe_parameter)
589 {
590  outputHeaderVHDL(FU_name_stored, os);
591  // Write library declaration
592  PP(os, "library ieee;\n");
593  PP(os, "use ieee.std_logic_1164.all;\n");
594  PP(os, "use ieee.numeric_std.all;\n");
595  PP(os, "\n");
596  PP(os, "entity " + FU_name_stored + " is\n");
597  PP.indent();
598  PP(os, "generic(");
600  FU_to_prec.find(FU_name_stored);
601  // Write input port(s) generics
602  const std::vector<std::string> p_in = get_ports(WRAPPED_PREFIX + FU_name_stored, 0, port_in, false);
603  for(const auto& p_in_it : p_in)
604  {
605  PP(os, "BITSIZE_" + p_in_it + ": integer := " + STR(FU_to_prec_it->second.first) + "; ");
606  }
607  // Write output port(s) generics
608  const std::vector<std::string> p_out = get_ports(WRAPPED_PREFIX + FU_name_stored, 0, port_out, false);
609  for(auto p_out_it = p_out.begin(); p_out_it != p_out.end(); ++p_out_it)
610  {
611  if(p_out_it + 1 != p_out.end())
612  {
613  PP(os, "BITSIZE_" + *p_out_it + ": integer := " + STR(FU_to_prec_it->second.second) + ";");
614  }
615  else
616  {
617  PP(os, "BITSIZE_" + *p_out_it + ": integer := " + STR(FU_to_prec_it->second.second));
618  }
619  }
620  PP(os, ");\n");
621  PP(os, "port (\n");
622  PP.indent();
623  // Write port declaration for top entity
624  outputPortDeclaration(WRAPPED_PREFIX, FU_name_stored, os, top, pipe_parameter);
625  // Begin writing the architecture of top entity
626  PP.deindent();
627  PP(os, ");\n");
628  PP.deindent();
629  PP(os, "end entity;\n");
630  PP(os, "\n");
631  PP(os, "architecture arch of " + FU_name_stored + " is\n");
632  PP.indent();
633  // Write declaration for each of entity's components
634  std::string prefixes[] = {WRAPPED_PREFIX, IN_WRAP_PREFIX, OUT_WRAP_PREFIX};
635  for(const auto& prefixe : prefixes)
636  {
637  if(!(((type == flopoco_wrapper::UT_UFIX2FP or type == flopoco_wrapper::UT_IFIX2FP) &&
638  prefixe == IN_WRAP_PREFIX) ||
639  (((type == flopoco_wrapper::UT_FP2UFIX or type == flopoco_wrapper::UT_FP2IFIX) ||
640  type == flopoco_wrapper::UT_compare_expr) &&
641  prefixe == OUT_WRAP_PREFIX)))
642  {
643  PP(os, "component " + prefixe + FU_name_stored + "\n");
644  PP.indent();
645  PP(os, "port (\n");
646  PP.indent();
647  if(WRAPPED_PREFIX == prefixe)
648  {
649  outputPortDeclaration(prefixe, FU_name_stored, os, wrapped, pipe_parameter);
650  }
651  else if(IN_WRAP_PREFIX == prefixe)
652  {
653  outputPortDeclaration(prefixe, FU_name_stored, os, in_wrap, pipe_parameter);
654  }
655  else if(OUT_WRAP_PREFIX == prefixe)
656  {
657  outputPortDeclaration(prefixe, FU_name_stored, os, out_wrap, pipe_parameter);
658  }
659  else
660  {
661  THROW_UNREACHABLE("Something wrong happened");
662  }
663  PP.deindent();
664  PP(os, ");\n");
665  PP.deindent();
666  PP(os, "end component;\n");
667  }
668  }
669  // Write the declaration of needed signals
670  outputSignals(FU_name_stored, os);
671  // Begin behavioral description
672  PP(os, "begin\n");
673  PP.indent();
674  // Write port mapping
675  if(type == flopoco_wrapper::UT_FP2UFIX)
676  {
677  PP(os, "O <= unsigned(wireOut1);\n");
678  }
679  else if(type == flopoco_wrapper::UT_FP2IFIX)
680  {
681  PP(os, "O <= signed(wireOut1);\n");
682  }
683  outputPortMap(FU_name_stored, os, pipe_parameter);
684  // End with architecture
685  PP.deindent();
686  PP.deindent();
687  PP(os, "end architecture;\n");
688  PP(os, "\n");
689 }
690 
691 void flopoco_wrapper::outputPortMap(const std::string& FU_name_stored, std::ostream& os,
692  const std::string& pipe_parameter)
693 {
694  std::string mapping;
695  const std::vector<std::string> p_wrapped_in = get_ports(WRAPPED_PREFIX + FU_name_stored, 0, port_in, false);
696  const std::vector<std::string> p_wrapped_out = get_ports(WRAPPED_PREFIX + FU_name_stored, 0, port_out, false);
697  std::vector<std::string> p_in_wrap_in;
698  std::vector<std::string> p_in_wrap_out;
699  if(type != flopoco_wrapper::UT_IFIX2FP and type != flopoco_wrapper::UT_UFIX2FP)
700  {
701  p_in_wrap_in = get_ports(IN_WRAP_PREFIX + FU_name_stored, 0, port_in, false);
702  p_in_wrap_out = get_ports(IN_WRAP_PREFIX + FU_name_stored, 0, port_out, false);
703  }
704  std::vector<std::string> p_out_wrap_in;
705  std::vector<std::string> p_out_wrap_out;
706  if(type != flopoco_wrapper::UT_FP2UFIX and type != flopoco_wrapper::UT_FP2IFIX and
707  type != flopoco_wrapper::UT_compare_expr)
708  {
709  p_out_wrap_in = get_ports(OUT_WRAP_PREFIX + FU_name_stored, 0, port_in, false);
710  p_out_wrap_out = get_ports(OUT_WRAP_PREFIX + FU_name_stored, 0, port_out, false);
711  }
712 
714  FU_to_prec.find(FU_name_stored);
715  unsigned int n_bits_in /*, n_bits_out*/;
716  unsigned int prec_in /*, prec_out*/;
717  prec_in = FU_to_prec_it->second.first;
718  // prec_out = FU_to_prec_it->second.second;
719  n_bits_in = prec_in;
720  // n_bits_out=prec_out;
721 
722  // Write mapping for wrapped component
723  mapping = "";
724  for(unsigned int i = 0; i < p_wrapped_in.size(); i++)
725  {
726  if(type == flopoco_wrapper::UT_ADDSUB && i == 1)
727  {
728  mapping += p_wrapped_in.at(i) + " => wire_ADDSUB, ";
729  }
730  else if(type == flopoco_wrapper::UT_SUB && i == 1)
731  {
732  mapping += p_wrapped_in.at(i) + " => wire_SUB, ";
733  }
734  else if(type == flopoco_wrapper::UT_IFIX2FP)
735  {
736  mapping += p_wrapped_in.at(i) + " => std_logic_vector(" + p_wrapped_in.at(i) + "), ";
737  }
738  else if(type == flopoco_wrapper::UT_UFIX2FP)
739  {
740  mapping += p_wrapped_in.at(i) + " => std_logic_vector(" + p_wrapped_in.at(i) + "), ";
741  }
742  else
743  {
744  mapping += p_wrapped_in.at(i) + " => wireIn" + STR(i + 1) + ", ";
745  }
746  }
747  for(unsigned int j = 0; j < p_wrapped_out.size(); j++)
748  {
749  if(type == flopoco_wrapper::UT_compare_expr)
750  {
751  mapping += p_wrapped_out.at(j) + " => " + p_wrapped_out.at(j) + "(0 downto 0)";
752  }
753  else
754  {
755  mapping += p_wrapped_out.at(j) + " => wireOut" + STR(j + 1);
756  }
757  }
758  if(pipe_parameter != "" && pipe_parameter != "0")
759  {
760  const std::string p_clock = get_port(clk);
761  const std::string p_reset = get_port(rst);
762  mapping +=
763  ", " + p_clock + "=> " + std::string(CLOCK_PORT_NAME) + ", " + p_reset + "=> " + std::string(RESET_PORT_NAME);
764  }
765 
766  if(type == flopoco_wrapper::UT_ADDSUB)
767  {
768  PP(os, "wire_ADDSUB <= wireIn2(" + STR(n_bits_in + 1) + " downto " + STR(n_bits_in) + ") & (wireIn2(" +
769  STR(n_bits_in - 1) + ") xor sel_minus_expr) & wireIn2(" + STR(n_bits_in - 2) + " downto 0);\n");
770  }
771  else if(type == flopoco_wrapper::UT_SUB)
772  {
773  PP(os, "wire_SUB <= wireIn2(" + STR(n_bits_in + 1) + " downto " + STR(n_bits_in) + ") & (wireIn2(" +
774  STR(n_bits_in - 1) + ") xor '1') & wireIn2(" + STR(n_bits_in - 2) + " downto 0);\n");
775  }
776  else if(type == flopoco_wrapper::UT_EXP || type == flopoco_wrapper::UT_SQRT || type == flopoco_wrapper::UT_LOG ||
777  type == flopoco_wrapper::UT_POW)
778  {
779  PP(os, std::string(DONE_PORT_NAME) + " <= '0';\n");
780  }
781  PP(os, "fu : " + STR(WRAPPED_PREFIX + FU_name_stored) + " port map (" + mapping + ");\n");
782  // Write mapping for input converters
783  if(type != flopoco_wrapper::UT_IFIX2FP and type != flopoco_wrapper::UT_UFIX2FP)
784  {
785  for(unsigned int i = 0; i < p_wrapped_in.size(); i++)
786  {
787  mapping = "";
788  mapping += p_in_wrap_in.at(0) + "=>" + p_wrapped_in.at(i) + ", ";
789  mapping += p_in_wrap_out.at(0) + "=>wireIn" + STR(i + 1);
790  if(pipe_parameter != "" && pipe_parameter != "0")
791  {
792  const std::string p_clock = get_port(clk);
793  const std::string p_reset = get_port(rst);
794  mapping += ", " + p_clock + "=> " + std::string(CLOCK_PORT_NAME) + ", " + p_reset + "=> " +
795  std::string(RESET_PORT_NAME);
796  }
797  PP(os, "in" + STR(i + 1) + " : " + STR(IN_WRAP_PREFIX + FU_name_stored) + " port map (" + mapping + ");\n");
798  }
799  }
800  // Write mapping for output converters
801  if(type != flopoco_wrapper::UT_FP2UFIX and type != flopoco_wrapper::UT_FP2IFIX and
802  type != flopoco_wrapper::UT_compare_expr)
803  {
804  for(unsigned int i = 0; i < p_wrapped_out.size(); i++)
805  {
806  mapping = "";
807  mapping += p_out_wrap_in.at(0) + "=>wireOut" + STR(i + 1) + ", ";
808  mapping += p_out_wrap_out.at(0) + "=>" + p_wrapped_out.at(i);
809  if(pipe_parameter != "" && pipe_parameter != "0")
810  {
811  const std::string p_clock = get_port(clk);
812  const std::string p_reset = get_port(rst);
813  mapping += ", " + p_clock + "=> " + std::string(CLOCK_PORT_NAME) + ", " + p_reset + "=> " +
814  std::string(RESET_PORT_NAME);
815  }
816  PP(os, "out" + STR(i + 1) + " : " + STR(OUT_WRAP_PREFIX + FU_name_stored) + " port map (" + mapping + ");\n");
817  }
818  }
819 }
820 
821 void flopoco_wrapper::outputSignals(const std::string& FU_name_stored, std::ostream& os)
822 {
823  std::string Signals = "";
824  const std::vector<std::string> p_in = get_ports(WRAPPED_PREFIX + FU_name_stored, 0, port_in, false);
825  const std::vector<std::string> p_out = get_ports(WRAPPED_PREFIX + FU_name_stored, 0, port_out, false);
827  FU_to_prec.find(FU_name_stored);
828  unsigned int n_bits_in, n_bits_out;
829  unsigned int prec_in, prec_out;
830  prec_in = FU_to_prec_it->second.first;
831  prec_out = FU_to_prec_it->second.second;
832  n_bits_in = prec_in;
833  n_bits_out = prec_out;
834 
835  if(type == flopoco_wrapper::UT_ADDSUB)
836  {
837  Signals += "wire_ADDSUB, ";
838  }
839  else if(type == flopoco_wrapper::UT_SUB)
840  {
841  Signals += "wire_SUB, ";
842  }
843  else if(type == flopoco_wrapper::UT_FF_CONV)
844  {
845  n_bits_in = prec_out;
846  }
847 
848  if(type == flopoco_wrapper::UT_IFIX2FP or type == flopoco_wrapper::UT_UFIX2FP)
849  {
850  if(prec_in != prec_out)
851  {
852  PP(os, "signal I_temp : std_logic_vector(" + STR(std::max(prec_in, prec_out) - 1) + " downto 0);\n");
853  }
854  }
855  else
856  {
857  size_t n_in_elements = p_in.size();
858  for(unsigned int i = 0; i < n_in_elements; i++)
859  {
860  Signals += "wireIn" + STR(i + 1) + (i + 1 != n_in_elements ? ", " : "");
861  }
862  PP(os, "signal " + Signals + " : std_logic_vector(" + STR(n_bits_in + 1) + " downto 0);\n");
863  }
864  if(type == flopoco_wrapper::UT_FP2UFIX or type == flopoco_wrapper::UT_FP2IFIX)
865  {
866  Signals = "";
867  for(unsigned int j = 0; j < p_out.size(); j++)
868  {
869  Signals += "wireOut" + STR(j + 1) + (j + 1 != p_out.size() ? ", " : "");
870  }
871  PP(os, "signal " + Signals + " : std_logic_vector(" + STR(n_bits_out - 1) + " downto 0);\n");
872  }
873  else if(type != flopoco_wrapper::UT_compare_expr)
874  {
875  Signals = "";
876  for(unsigned int j = 0; j < p_out.size(); j++)
877  {
878  Signals += "wireOut" + STR(j + 1) + (j + 1 != p_out.size() ? ", " : "");
879  }
880  PP(os, "signal " + Signals + " : std_logic_vector(" + STR(n_bits_out + 1) + " downto 0);\n");
881  }
882 }
883 
884 void flopoco_wrapper::outputPortDeclaration(const std::string& FU_prefix, const std::string& FU_name_stored,
885  std::ostream& os, component_type c_type, const std::string& pipe_parameter)
886 {
887  // Compute offsets for addition bits' handling
888  int in_offset, out_offset;
889  unsigned int n_bits_in, n_bits_out;
890  unsigned int prec_in, prec_out;
892  FU_to_prec.find(FU_name_stored);
893  in_offset = out_offset = -1;
894  n_bits_in = n_bits_out = 0;
895  prec_in = FU_to_prec_it->second.first;
896  prec_out = FU_to_prec_it->second.second;
897  if(wrapped == c_type)
898  {
899  if(type != flopoco_wrapper::UT_IFIX2FP and type != flopoco_wrapper::UT_UFIX2FP)
900  {
901  in_offset += FLOPOCO_ADDITIONAL_BITS;
902  }
903  if(type != flopoco_wrapper::UT_FP2UFIX and type != flopoco_wrapper::UT_FP2IFIX and
904  type != flopoco_wrapper::UT_compare_expr)
905  {
906  out_offset += FLOPOCO_ADDITIONAL_BITS;
907  }
908  if(type == flopoco_wrapper::UT_FF_CONV)
909  {
910  n_bits_in = n_bits_out = prec_out;
911  }
912  else if(type == flopoco_wrapper::UT_compare_expr)
913  {
914  n_bits_in = prec_in;
915  n_bits_out = 1;
916  }
917  else
918  {
919  n_bits_in = prec_in;
920  n_bits_out = prec_out;
921  }
922  }
923  else if(in_wrap == c_type)
924  {
925  out_offset += FLOPOCO_ADDITIONAL_BITS;
926  if(type == flopoco_wrapper::UT_FF_CONV)
927  {
928  n_bits_in = prec_in;
929  n_bits_out = prec_out;
930  }
931  else
932  {
933  n_bits_in = n_bits_out = prec_in;
934  }
935  }
936  else if(out_wrap == c_type)
937  {
938  in_offset += FLOPOCO_ADDITIONAL_BITS;
939  n_bits_in = n_bits_out = prec_out;
940  }
941  if(pipe_parameter != "" && pipe_parameter != "0")
942  {
943  if(wrapped == c_type || in_wrap == c_type || out_wrap == c_type)
944  {
945  PP(os, get_port(clk) + " : in std_logic;\n");
946  PP(os, get_port(rst) + " : in std_logic;\n");
947  }
948  }
949  const std::vector<std::string> p_in = get_ports(FU_prefix + FU_name_stored, 0, port_in, false);
950  for(const auto& p_in_it : p_in)
951  {
952  if(top == c_type)
953  {
954  if(type == flopoco_wrapper::UT_IFIX2FP)
955  {
956  PP(os, p_in_it + " : in signed(BITSIZE_" + p_in_it + "-1 downto 0);\n");
957  }
958  else if(type == flopoco_wrapper::UT_UFIX2FP)
959  {
960  PP(os, p_in_it + " : in unsigned(BITSIZE_" + p_in_it + "-1 downto 0);\n");
961  }
962  else
963  {
964  PP(os, p_in_it + " : in std_logic_vector(BITSIZE_" + p_in_it + "-1 downto 0);\n");
965  }
966  }
967  else if(static_cast<int>(n_bits_in) + in_offset > 0)
968  {
969  PP(os, p_in_it + " : in std_logic_vector(" + STR(static_cast<int>(n_bits_in) + in_offset) + " downto 0);\n");
970  }
971  else
972  {
973  PP(os, p_in_it + " : in std_logic;\n");
974  }
975  }
976  // Write clock and reset ports declaration, only for top and wrapped entities
977  if(top == c_type)
978  {
979  PP(os, std::string(CLOCK_PORT_NAME) + " : in std_logic;\n");
980  PP(os, std::string(RESET_PORT_NAME) + " : in std_logic;\n");
981 
982  if(type == flopoco_wrapper::UT_ADDSUB)
983  {
984  PP(os, std::string("sel_plus_expr") + " : in std_logic;\n");
985  PP(os, std::string("sel_minus_expr") + " : in std_logic;\n");
986  }
987  else if(type == flopoco_wrapper::UT_EXP || type == flopoco_wrapper::UT_SQRT || type == flopoco_wrapper::UT_LOG ||
988  type == flopoco_wrapper::UT_POW)
989  {
990  PP(os, std::string(START_PORT_NAME) + " : in std_logic;\n");
991  PP(os, std::string(DONE_PORT_NAME) + " : out std_logic;\n");
992  }
993  }
994  // Write output port(s) declaration
995  const std::vector<std::string> p_out = get_ports(FU_prefix + FU_name_stored, 0, port_out, false);
996  for(auto p_out_it = p_out.begin(); p_out_it != p_out.end(); ++p_out_it)
997  {
998  if(top == c_type)
999  {
1000  if(type == flopoco_wrapper::UT_FP2IFIX)
1001  {
1002  PP(os, *p_out_it + " : out signed(BITSIZE_" + *p_out_it + "-1 downto 0)\n");
1003  }
1004  else if(type == flopoco_wrapper::UT_FP2UFIX)
1005  {
1006  PP(os, *p_out_it + " : out unsigned(BITSIZE_" + *p_out_it + "-1 downto 0)\n");
1007  }
1008  else
1009  {
1010  PP(os, *p_out_it + " : out std_logic_vector(BITSIZE_" + *p_out_it + "-1 downto 0)\n");
1011  }
1012  }
1013  else
1014  {
1015  PP(os,
1016  *p_out_it + " : out std_logic_vector(" + STR(static_cast<int>(n_bits_out) + out_offset) + " downto 0)\n");
1017  }
1018  if(p_out_it + 1 != p_out.end())
1019  {
1020  PP(os, ";\n");
1021  }
1022  else
1023  {
1024  PP(os, "\n");
1025  }
1026  }
1027 }
1028 
1029 void flopoco_wrapper::outputHeaderVHDL(const std::string& FU_name_stored, std::ostream& os) const
1030 {
1031  os << "--------------------------------------------------------------------------------" << endl;
1032  os << "-- " << FU_name_stored << endl;
1033  os << "-- Operator automatically generated by " << PACKAGE_NAME << " framework version " << PACKAGE_VERSION << endl;
1034  os << "-- assemblying operators generated by the Infinite Virtual Library FloPoCoLib" << endl;
1035  os << "-- Send any bug to: " << PACKAGE_BUGREPORT << endl;
1036  os << "--------------------------------------------------------------------------------" << endl;
1037 }
1038 
1039 int flopoco_wrapper::InternalWriteVHDL(const std::string& FU_name, const unsigned int FU_prec_in,
1040  const unsigned int FU_prec_out, const std::string& filename,
1041  const std::string& pipe_parameter)
1042 {
1043  std::string FU_name_stored = ENCODE_NAME(FU_name, FU_prec_in, FU_prec_out, pipe_parameter);
1045  "Writing VHDL code for unit " + FU_name_stored + " to file " + filename);
1046  if(FU_files.find(FU_name_stored) != FU_files.end())
1047  {
1048  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "- Code for unit has already been generated");
1049  return 1;
1050  }
1051  std::ofstream file(filename.c_str());
1052  if(!file.is_open())
1053  {
1054  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "- Something went wrong in file creation");
1055  return -1;
1056  }
1057  // Call FloPoCo method to generate VHDL for Functional Unit and Conversion Units
1058  {
1059  try
1060  {
1061  flopoco::Operator::outputVHDLToFile(OPLIST, file);
1062  }
1063  catch(const std::string& s)
1064  {
1065  cerr << "Exception while generating '" << s << endl;
1066  }
1067  }
1068 
1069  // Generate VHDL for Functional Unit wrapper entity
1070  outputWrapVHDL(FU_name_stored, file, pipe_parameter);
1071  // Mark the file as generated
1072  FU_files.insert(filename);
1073  file.close();
1074  OPLIST.clear();
1075  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "- Successfully written to file!");
1076  return 0;
1077 }
1078 
1079 int flopoco_wrapper::writeVHDL(const std::string& FU_name, const unsigned int FU_prec_in,
1080  const unsigned int FU_prec_out, std::string pipe_parameter, std::string& filename)
1081 {
1082  filename = GetPath(ENCODE_NAME(FU_name, FU_prec_in, FU_prec_out, pipe_parameter) + FILE_EXT);
1083  return this->InternalWriteVHDL(FU_name, FU_prec_in, FU_prec_out, filename, pipe_parameter);
1084 }
1085 
1087 {
1088  std::vector<flopoco::Operator*>* common_oplist = target->getGlobalOpListRef();
1089  if(!common_oplist || common_oplist->empty())
1090  {
1091  return "";
1092  }
1093  std::string filename = GetPath("FloPoCo_common" FILE_EXT);
1094  std::ofstream file(filename.c_str());
1095  if(!file.is_open())
1096  {
1097  THROW_UNREACHABLE("Something went wrong in file creation");
1098  return "";
1099  }
1100  // Call FloPoCo method to generate VHDL for all common units
1101  {
1102  try
1103  {
1104  flopoco::Operator::outputVHDLToFile(*common_oplist, file);
1105  }
1106  catch(const std::string& s)
1107  {
1108  THROW_UNREACHABLE("Exception while generating " + s);
1109  }
1110  }
1111  // Mark the file as generated
1112  return filename;
1113 }
1114 
1115 const std::vector<std::string> flopoco_wrapper::get_ports(const std::string& FU_name_stored,
1116  unsigned int ASSERT_PARAMETER(expected_ports),
1117  port_type local_type,
1118  bool ASSERT_PARAMETER(check_ports)) const
1119 {
1120  std::vector<std::string> ports;
1121  flopoco::Operator* op = get_FU(FU_name_stored);
1122  for(int i = 0; i < op->getIOListSize(); i++)
1123  {
1124  flopoco::Signal* sig = op->getIOListSignal(i);
1125  if(local_type == port_in && sig->type() == flopoco::Signal::in)
1126  {
1127  ports.push_back(sig->getName());
1128  }
1129  else if(local_type == port_out && sig->type() == flopoco::Signal::out)
1130  {
1131  ports.push_back(sig->getName());
1132  }
1133  }
1134  THROW_ASSERT(!check_ports || expected_ports == ports.size(),
1135  "Expected a different number of " +
1136  (local_type == port_in ? std::string("input") : std::string("output")) + " ports");
1137  return ports;
1138 }
1139 
1140 const std::string flopoco_wrapper::get_port(port_type local_type) const
1141 {
1142  if(local_type == rst)
1143  {
1144  return "rst";
1145  }
1146  else if(local_type == clk)
1147  {
1148  return "clk";
1149  }
1150  THROW_UNREACHABLE("Something went wrong!");
1151  return "";
1152 }
1153 
1154 void flopoco_wrapper::DECODE_BITS(unsigned int FU_prec, unsigned int& n_mant, unsigned int& n_exp)
1155 {
1156  switch(FU_prec)
1157  {
1158  case 16: // IEEE-754 half precision
1159  {
1160  n_exp = 5;
1161  n_mant = 10;
1162  break;
1163  }
1164  case 32: // IEEE-754 single precision
1165  {
1166  n_exp = 8;
1167  n_mant = 23;
1168  break;
1169  }
1170  case 64: // IEEE-754 double precision
1171  {
1172  n_exp = 11;
1173  n_mant = 52;
1174  break;
1175  }
1176  case 96:
1177  {
1178  THROW_ERROR("Intel Extended Precision not currently supported");
1179  n_exp = 15;
1180  n_mant = 64;
1181  break;
1182  }
1183  case 128: // IEEE-754 quad precision
1184  {
1185  n_exp = 15;
1186  n_mant = 112;
1187  break;
1188  }
1189  default: // Linear growth for exponent number of bits
1190  {
1191  n_exp = 8 + (3u * (FU_prec - 32) / 32);
1192  n_mant = FU_prec - n_exp - 1;
1193  break;
1194  }
1195  }
1196 }
Forward declarations of FloPoCo classes.
vector< pair< string, int > > theUseTable
const std::string get_port(port_type type) const
Returns the name of a port, according to the needed port type (clock or reset)
int InternalWriteVHDL(const std::string &FU_name, const unsigned int FU_prec_in, const unsigned int FU_prec_out, const std::string &filename, const std::string &pipe_parameter)
Writes the VHDL for a Functional Unit to the desired file name Returns -1 if some problem occurred...
void * top(node_stack *head)
Definition: tree.c:75
FPge_expr module for flopoco.
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
int writeVHDL(const std::string &FU_name, const unsigned int FU_prec_in, const unsigned int FU_prec_out, std::string pipe_parameter, std::string &filename)
Writes the VHDL for a Functional Unit to the default file name, which is "FU_name.vhdl" Returns -1 if some problem occurred, 0 if the file was successfully written, 1 if the FU was already written to a file.
The FPlt_expr class.
Definition: FPlt_expr.hpp:57
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define START_PORT_NAME
std::string filename
simple_indent PP
Pretty print functor object used to indent the generated code.
The FPAssign class.
Definition: FPAssign.hpp:57
The FPge_expr class.
Definition: FPge_expr.hpp:57
exceptions managed by PandA
flopoco::Target * target
enum { port_in, port_out, clk, rst } port_type
Port types.
#define IN_WRAP_PREFIX
Prefix for the wrapper to the inputs.
std::string cl_name
void outputWrapVHDL(const std::string &FU_name_stored, std::ostream &os, const std::string &pipe_parameter)
#define ENCODE_NAME(FU_name, FU_prec_in, FU_prec_out, pipe_parameter)
Name of the stored Functional Unit.
FPlt_expr module for flopoco.
redefinition of map to manage ordered/unordered structures
The FPle_expr class.
Definition: FPle_expr.hpp:57
int debug_level
Current debug level.
#define STR(s)
Macro which performs a lexical_cast to a string.
#define max
Definition: backprop.h:17
void deindent()
Manually reduce the indenting of the code.
#define WRAPPED_PREFIX
Suffix appended to the internal (wrapped) Functional Unit.
FPgt_expr module for flopoco.
std::string writeVHDLcommon()
write the common components
#define CLOCK_PORT_NAME
standard name for ports
CustomUnorderedSet< std::string > FU_files
Set of Functional Units written to a .vhdl file.
CustomUnorderedMap< std::string, std::pair< unsigned int, unsigned int > > FU_to_prec
Maps a Functional Unit to its precision.
#define ASSERT_PARAMETER(parameter)
Definition: utility.hpp:96
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void indent()
Manually increase the indenting of the code.
CustomUnorderedMap< std::string, flopoco::Operator * > FUs
Generated Functional Units.
#define FILE_EXT
Default extension for generated files.
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
#define DONE_PORT_NAME
static void DECODE_BITS(unsigned int FU_prec, unsigned int &n_mant, unsigned int &n_exp)
Retrieve mantissa and exponent for a given precision.
FPAssign module for flopoco.
redefinition of set to manage ordered/unordered structures
utility function used to read files.
#define FLOPOCO_ADDITIONAL_BITS
Additional bits in FloPoCo encoding with reference to IEEE-754 standard.
void add_FU(const std::string &FU_type, unsigned int FU_prec_in, unsigned int FU_prec_out, const std::string &FU_name, const std::string &pipe_parameter)
Adds a Functional Unit to the wrapper.
This file collects some utility functions and macros.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
#define STD_OPENING_CHAR
STD include.
void outputPortMap(const std::string &FU_name_stored, std::ostream &os, const std::string &pipe_parameter)
const std::vector< std::string > get_ports(const std::string &FU_name_stored, unsigned int expected_ports, port_type type, bool check_ports=true) const
Returns the names of ports, according to the needed port type (port_in or port_out) ...
bool combinatorialOperator
#define STD_CLOSING_CHAR
Special closing character used to close the current nested level.
This class describes all classes used to represent a structural object.
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
void outputPortDeclaration(const std::string &FU_prefix, const std::string &FU_name_stored, std::ostream &os, component_type type, const std::string &pipe_parameter)
flopoco_wrapper(int _debug_level, const std::string &FU_target)
Constructor.
#define OPLIST
Autoheader include.
static constexpr double DEFAULT_TARGET_FREQUENCY
enum { top, wrapped, in_wrap, out_wrap } component_type
Component types.
Wrapper to FloPoCo for VHDL code generation.
~flopoco_wrapper()
Destructor.
void outputHeaderVHDL(const std::string &FU_name_stored, std::ostream &os) const
Helper methods for automatic VHDL code generation:
FPle_expr module for flopoco.
#define OUT_WRAP_PREFIX
Prefix for the wrapper to the inputs.
#define RESET_PORT_NAME
unsigned int get_FUPipelineDepth(const std::string &FU_name, const unsigned int FU_prec_in, const unsigned int FU_prec_out, const std::string &pipe_parameter) const
Returns the Functional Unit&#39;s Pipeline Depth.
The FPgt_expr class.
Definition: FPgt_expr.hpp:57
void outputSignals(const std::string &FU_name_stored, std::ostream &os)
flopoco::Operator * get_FU(std::string FU_name_stored) const
Returns one of the generated Functional Units.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:56 for PandA-2024.02 by doxygen 1.8.13