OpenFPGA/libs/libopenfpgautil/src/openfpga_scale.cpp

183 lines
5.6 KiB
C++
Raw Normal View History

/********************************************************************
* This file includes functions that convert time/resistance/capacitance
* units to string or vice versa
*******************************************************************/
#include <cmath>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_scale.h"
namespace openfpga {
/* A small ratio for float number comparison
* If the float number B is in the range of the referance A +/- epsilon
* we regard A == B
* A - A * EPSILON <= B <= A + A * EPSILON
*/
#define EPSILON_RATIO 1e-3
bool same_float_number(const float& a, const float& b, const float& epsilon) {
/* Always use a positive epsilon */
if ((a - a * std::abs(epsilon) <= b) && (b <= a + a * std::abs(epsilon))) {
return true;
}
return false;
}
/********************************************************************
* Convert numeric unit to string:
* - 1e12 -> T
* - 1e9 -> B
* - 1e6 -> M
* - 1e3 -> k
* - 1. ->
* - 1e-3 -> m
* - 1e-6 -> u
* - 1e-9 -> n
* - 1e-12 -> p
* - 1e-15 -> f
* - 1e-18 -> a
*******************************************************************/
std::string unit_to_string(const float& unit) {
if (true == same_float_number(unit, 1., EPSILON_RATIO)) {
return std::string();
/* Larger than 1 unit */
} else if (true == same_float_number(unit, 1e3, EPSILON_RATIO)) {
return std::string("k");
} else if (true == same_float_number(unit, 1e6, EPSILON_RATIO)) {
return std::string("M");
} else if (true == same_float_number(unit, 1e9, EPSILON_RATIO)) {
return std::string("B");
} else if (true == same_float_number(unit, 1e12, EPSILON_RATIO)) {
return std::string("T");
/* Less than 1 unit */
} else if (true == same_float_number(unit, 1e-3, EPSILON_RATIO)) {
return std::string("m");
} else if (true == same_float_number(unit, 1e-6, EPSILON_RATIO)) {
return std::string("u");
} else if (true == same_float_number(unit, 1e-9, EPSILON_RATIO)) {
return std::string("n");
} else if (true == same_float_number(unit, 1e-12, EPSILON_RATIO)) {
return std::string("p");
} else if (true == same_float_number(unit, 1e-15, EPSILON_RATIO)) {
return std::string("f");
} else if (true == same_float_number(unit, 1e-18, EPSILON_RATIO)) {
return std::string("a");
}
/* Invalid unit report error */
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid unit %g!\nAcceptable units are "
"[1e12|1e9|1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n",
unit);
exit(1);
}
/********************************************************************
* Convert numeric time unit to string
* e.g. 1e-12 -> ps
*******************************************************************/
std::string time_unit_to_string(const float& unit, const std::string& postfix) {
/* For larger than 1 unit, we do not accept */
if (1e6 < unit) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid time unit %g!\nAcceptable units are "
"[1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n",
unit);
exit(1);
}
return unit_to_string(unit) + postfix;
}
/********************************************************************
* Convert string unit to numeric:
* - T -> 1e12
* - B -> 1e9
* - M -> 1e6
* - k -> 1e3
* - "" -> 1.
* - m -> 1e-3
* - u -> 1e-6
* - n -> 1e-9
* - p -> 1e-12
* - f -> 1e-15
* - a -> 1e-18
*******************************************************************/
float string_to_unit(const std::string& scale) {
if (true == scale.empty()) {
return 1.;
/* Larger than 1 unit */
} else if (std::string("T") == scale) {
return 1e12;
} else if (std::string("B") == scale) {
return 1e9;
} else if (std::string("M") == scale) {
return 1e6;
} else if (std::string("k") == scale) {
return 1e3;
/* Less than 1 unit */
} else if (std::string("m") == scale) {
return 1e-3;
} else if (std::string("u") == scale) {
return 1e-6;
} else if (std::string("n") == scale) {
return 1e-9;
} else if (std::string("p") == scale) {
return 1e-12;
} else if (std::string("f") == scale) {
return 1e-15;
} else if (std::string("a") == scale) {
return 1e-18;
}
/* Invalid unit report error */
VTR_LOGF_ERROR(
__FILE__, __LINE__,
"Invalid unit %s!\nAcceptable units are [a|f|p|n|u|k|M|B|T] or empty\n",
scale.c_str());
exit(1);
}
/********************************************************************
* Convert string time unit to numeric
* e.g. ps -> 1e-12
*******************************************************************/
float string_to_time_unit(const std::string& scale) {
if ((1 != scale.length()) && (2 != scale.length())) {
VTR_LOGF_ERROR(
__FILE__, __LINE__,
"Time unit (='%s') must contain only one or two characters!\n",
scale.c_str());
}
/* The last character must be 's' */
if ('s' != scale.back()) {
VTR_LOGF_ERROR(__FILE__, __LINE__, "Time unit (='%s') must end with 's'!\n",
scale.c_str());
}
float unit = 1.;
VTR_ASSERT((1 == scale.length()) || (2 == scale.length()));
if (2 == scale.length()) {
unit = string_to_unit(scale.substr(0, 1));
}
/* For larger than 1 unit, we do not accept */
if (1e6 < unit) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid time unit %g!\nAcceptable units are "
"[1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n",
unit);
exit(1);
}
return unit;
}
} // namespace openfpga