diff options
Diffstat (limited to 'common/nextpnr.h')
-rw-r--r-- | common/nextpnr.h | 115 |
1 files changed, 88 insertions, 27 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h index 1f22e65a..efa326c0 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -32,6 +32,7 @@ #include <boost/functional/hash.hpp> #include <boost/lexical_cast.hpp> +#include <boost/range/adaptor/reversed.hpp> #include <boost/thread.hpp> #ifndef NEXTPNR_H @@ -289,42 +290,98 @@ struct PipMap struct Property { + enum State : char + { + S0 = '0', + S1 = '1', + Sx = 'x', + Sz = 'z' + }; + + Property(); + Property(int64_t intval, int width = 32); + Property(const std::string &strval); + Property(State bit); + Property &operator=(const Property &other) = default; + bool is_string; + // The string literal (for string values), or a string of [01xz] (for numeric values) std::string str; - int num; - - std::string::iterator begin() { return str.begin(); } - std::string::iterator end() { return str.end(); } + // The lower 64 bits (for numeric values), unused for string values + int64_t intval; - bool isString() const { return is_string; } + void update_intval() + { + intval = 0; + for (int i = 0; i < int(str.size()); i++) { + NPNR_ASSERT(str[i] == S0 || str[i] == S1 || str[i] == Sx || str[i] == Sz); + if ((str[i] == S1) && i < 64) + intval |= (1ULL << i); + } + } - void setNumber(int val) + int64_t as_int64() const { - is_string = false; - num = val; - str = std::to_string(val); + NPNR_ASSERT(!is_string); + return intval; } - void setString(std::string val) + std::vector<bool> as_bits() const { - is_string = true; - str = val; + std::vector<bool> result; + result.reserve(str.size()); + NPNR_ASSERT(!is_string); + for (auto c : str) + result.push_back(c == S1); } - - const char *c_str() const { return str.c_str(); } - operator std::string() const { return str; } - - bool operator==(const std::string other) const { return str == other; } - bool operator!=(const std::string other) const { return str != other; } - - Property &operator=(std::string other) + std::string as_string() const + { + NPNR_ASSERT(is_string); + return str; + } + const char *c_str() const { - is_string = true; - str = other; - return *this; + NPNR_ASSERT(is_string); + return str.c_str(); } + size_t size() const { return is_string ? 8 * str.size() : str.size(); } + double as_double() const + { + NPNR_ASSERT(is_string); + return std::stod(str); + } + bool as_bool() const + { + if (int(str.size()) <= 64) + return intval != 0; + else + return std::any_of(str.begin(), str.end(), [](char c) { return c == S1; }); + } + bool is_fully_def() const + { + return !is_string && std::all_of(str.begin(), str.end(), [](char c) { return c == S0 || c == S1; }); + } + Property extract(int offset, int len, State padding = State::S0) const + { + Property ret; + ret.is_string = false; + ret.str.reserve(len); + for (int i = offset; i < offset + len; i++) + ret.str.push_back(i < int(str.size()) ? str[i] : padding); + ret.update_intval(); + return ret; + } + // Convert to a string representation, escaping literal strings matching /^[01xz]* *$/ by adding a space at the end, + // to disambiguate from binary strings + std::string to_string() const; + // Convert a string of four-value binary [01xz], or a literal string escaped according to the above rule + // to a Property + static Property from_string(const std::string &s); }; +inline bool operator==(const Property &a, const Property &b) { return a.is_string == b.is_string && a.str == b.str; } +inline bool operator!=(const Property &a, const Property &b) { return a.is_string != b.is_string || a.str != b.str; } + struct ClockConstraint; struct NetInfo : ArchNetInfo @@ -731,8 +788,10 @@ struct Context : Arch, DeterministicRNG template <typename T> T setting(const char *name, T defaultValue) { IdString new_id = id(name); - if (settings.find(new_id) != settings.end()) - return boost::lexical_cast<T>(settings.find(new_id)->second.str); + auto found = settings.find(new_id); + if (found != settings.end()) + return boost::lexical_cast<T>(found->second.is_string ? found->second.as_string() + : std::to_string(found->second.as_int64())); else settings[id(name)] = std::to_string(defaultValue); @@ -742,8 +801,10 @@ struct Context : Arch, DeterministicRNG template <typename T> T setting(const char *name) const { IdString new_id = id(name); - if (settings.find(new_id) != settings.end()) - return boost::lexical_cast<T>(settings.find(new_id)->second.str); + auto found = settings.find(new_id); + if (found != settings.end()) + return boost::lexical_cast<T>(found->second.is_string ? found->second.as_string() + : std::to_string(found->second.as_int64())); else throw std::runtime_error("settings does not exists"); } |