From 4a3155efaf13c2265f880ffa1a969d6a620e8fa7 Mon Sep 17 00:00:00 2001 From: Adrien Prost-Boucle Date: Thu, 19 Sep 2024 16:09:05 +0200 Subject: [PATCH] Himbaechel xilinx : More flexibility about types of DSP parameters --- common/kernel/util.h | 45 +++++++++++++++++++++++++++++++++ himbaechel/uarch/xilinx/fasm.cc | 30 ++++++++++------------ 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/common/kernel/util.h b/common/kernel/util.h index f04a956b..0223470a 100644 --- a/common/kernel/util.h +++ b/common/kernel/util.h @@ -102,6 +102,51 @@ bool bool_or_default(const Container &ct, const KeyType &key, bool def = false) return bool(int_or_default(ct, key, int(def))); }; +// Get a bool from a map-style container, returning default if value is not found +// Also tolerate string representation of boolean for interoperability purposes +template +bool boolstr_or_default(const dict &ct, const KeyType &key, bool def = false) +{ + auto found = ct.find(key); + if (found == ct.end()) + return def; + if (!found->second.is_string) + bool(found->second.as_int64()); + const char* str = found->second.as_string().c_str(); + if(!strcmp(str, "0") || !strcasecmp(str, "false")) + return false; + else if(!strcmp(str, "1") || !strcasecmp(str, "true")) + return true; + else + log_error("Expecting bool-compatible value but got '%s'.\n", found->second.as_string().c_str()); + return false; +}; + +// Get a vector of bool from a map-style container, returning default if value is not found +// Also tolerate string representation of vector for interoperability purposes +template +bool boolvec_populate(const dict &ct, const KeyType &key, std::vector& vec) +{ + auto found = ct.find(key); + if (found == ct.end()) + return false; + if (!found->second.is_string) + { + size_t val = found->second.as_int64(); + for (size_t i = 0; i < vec.size(); ++i, val>>=1) { + vec[i] = (val & 0x1) != 0; + } + } + else { + const std::string& str = found->second.as_string(); + size_t i = 0; + for (auto it = str.crbegin(); it != str.crend() && i < vec.size(); ++i, ++it) { + vec[i] = *it == '1'; + } + } + return true; +}; + // Get only value from a forward iterator begin/end pair. // // Generates assertion failure if std::distance(begin, end) != 1. diff --git a/himbaechel/uarch/xilinx/fasm.cc b/himbaechel/uarch/xilinx/fasm.cc index 2c9dced7..f59a3fe4 100644 --- a/himbaechel/uarch/xilinx/fasm.cc +++ b/himbaechel/uarch/xilinx/fasm.cc @@ -1536,8 +1536,9 @@ struct FasmBackend if (binput == "CASCADE") write_bit("B_INPUT[0]"); - auto use_dport = str_or_default(ci->params, ctx->id("USE_DPORT"), "FALSE"); - if (use_dport == "TRUE") + // Tolerate both int and string types for interoperability purposes + auto use_dport = boolstr_or_default(ci->params, ctx->id("USE_DPORT"), false); + if (use_dport == true) write_bit("USE_DPORT[0]"); auto use_simd = str_or_default(ci->params, ctx->id("USE_SIMD"), "ONE48"); @@ -1547,14 +1548,10 @@ struct FasmBackend write_bit("USE_SIMD_FOUR12"); // PATTERN - auto pattern_str = str_or_default(ci->params, ctx->id("PATTERN"), ""); - if (!boost::empty(pattern_str)) { - const size_t pattern_size = 48; - std::vector pattern_vector(pattern_size, true); - size_t i = 0; - for (auto it = pattern_str.crbegin(); it != pattern_str.crend() && i < pattern_size; ++i, ++it) { - pattern_vector[i] = *it == '1'; - } + const size_t pattern_size = 48; + std::vector pattern_vector(pattern_size, false); + bool pattern_found = boolvec_populate(ci->params, ctx->id("PATTERN"), pattern_vector); + if (pattern_found) { write_vector("PATTERN[47:0]", pattern_vector); } @@ -1565,16 +1562,15 @@ struct FasmBackend write_bit("AUTORESET_PATDET_RESET_NOT_MATCH"); // MASK - auto mask_str = str_or_default(ci->params, ctx->id("MASK"), "001111111111111111111111111111111111111111111111"); // Yosys gives us 48 bit, but prjxray only recognizes 46 bits // The most significant two bits seem to be zero, so let us just truncate them - const size_t mask_size = 46; + const size_t mask_size = 48; std::vector mask_vector(mask_size, true); - size_t i = 0; - for (auto it = mask_str.crbegin(); it != mask_str.crend() && i < mask_size; ++i, ++it) { - mask_vector[i] = *it == '1'; + bool mask_found = boolvec_populate(ci->params, ctx->id("MASK"), mask_vector); + if (mask_found) { + mask_vector.resize(46); + write_vector("MASK[45:0]", mask_vector); } - write_vector("MASK[45:0]", mask_vector); auto sel_mask = str_or_default(ci->params, ctx->id("SEL_MASK"), "MASK"); if (sel_mask == "C") @@ -1599,7 +1595,7 @@ struct FasmBackend write_bit("ZMREG[0]", !bool_or_default(ci->params, ctx->id("MREG"))); write_bit("ZOPMODEREG[0]", !bool_or_default(ci->params, ctx->id("OPMODEREG"))); write_bit("ZPREG[0]", !bool_or_default(ci->params, ctx->id("PREG"))); - write_bit("USE_DPORT[0]", str_or_default(ci->params, ctx->id("USE_DPORT"), "FALSE") == "TRUE"); + write_bit("USE_DPORT[0]", boolstr_or_default(ci->params, ctx->id("USE_DPORT"), false)); write_bit("ZIS_CLK_INVERTED", !bool_or_default(ci->params, ctx->id("IS_CLK_INVERTED"))); write_bit("ZIS_CARRYIN_INVERTED", !bool_or_default(ci->params, ctx->id("IS_CARRYIN_INVERTED"))); pop(2);