diff options
Diffstat (limited to 'fpga_interchange/cell_parameters.cc')
| -rw-r--r-- | fpga_interchange/cell_parameters.cc | 222 | 
1 files changed, 222 insertions, 0 deletions
| diff --git a/fpga_interchange/cell_parameters.cc b/fpga_interchange/cell_parameters.cc new file mode 100644 index 00000000..e008fea8 --- /dev/null +++ b/fpga_interchange/cell_parameters.cc @@ -0,0 +1,222 @@ +/* + *  nextpnr -- Next Generation Place and Route + * + *  Copyright (C) 2021  Symbiflow Authors + * + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "cell_parameters.h" + +#include <limits> + +#include "DeviceResources.capnp.h" +#include "context.h" +#include "log.h" +#include "nextpnr_assertions.h" + +NEXTPNR_NAMESPACE_BEGIN + +CellParameters::CellParameters() +        // 1'b0 +        : verilog_binary_re("([1-9][0-9]*)'b([01]+)$"), +          // 8'hF +          verilog_hex_re("([1-9][0-9]*)'h([0-9a-fA-F]+)$"), +          // 0b10 +          c_binary_re("0b([01]+)$"), +          // 0xF +          c_hex_re("0x([0-9a-fA-F]+)$") +{ +} + +void CellParameters::init(const Context *ctx) +{ +    for (const CellParameterPOD &cell_parameter : ctx->chip_info->cell_map->cell_parameters) { +        IdString cell_type(cell_parameter.cell_type); +        IdString parameter(cell_parameter.parameter); +        auto result = parameters.emplace(std::make_pair(cell_type, parameter), &cell_parameter); +        NPNR_ASSERT(result.second); +    } +} + +static bool parse_int(const std::string &data, int64_t *result) +{ +    NPNR_ASSERT(result != nullptr); +    try { +        *result = boost::lexical_cast<int64_t>(data); +        return true; +    } catch (boost::bad_lexical_cast &e) { +        return false; +    } +} + +DynamicBitarray<> CellParameters::parse_int_like(const Context *ctx, IdString cell_type, IdString parameter, +                                                 const Property &property) const +{ +    const CellParameterPOD *definition = parameters.at(std::make_pair(cell_type, parameter)); +    DeviceResources::Device::ParameterFormat format; +    format = static_cast<DeviceResources::Device::ParameterFormat>(definition->format); + +    DynamicBitarray<> result; +    switch (format) { +    case DeviceResources::Device::ParameterFormat::BOOLEAN: +        result.resize(1); +        if (property.is_string) { +            if (property.as_string() == "TRUE" || property.as_string() == "1") { +                result.set(0, true); +            } else if (property.as_string() == "FALSE" || property.as_string() == "0") { +                result.set(0, false); +            } else { +                log_error("Property value %s not expected for BOOLEAN type.\n", property.c_str()); +            } +        } else { +            if (property.intval == 1) { +                result.set(0, true); +            } else if (property.intval == 0) { +                result.set(0, false); +            } else { +                log_error("Property value %lu not expected for BOOLEAN type.\n", property.intval); +            } +        } + +        return result; +    case DeviceResources::Device::ParameterFormat::INTEGER: +        if (property.is_string) { +            char *endptr; +            std::uintmax_t value = strtoumax(property.c_str(), &endptr, /*base=*/10); +            if (endptr != (property.c_str() + property.size())) { +                log_error("Property value %s not expected for INTEGER type.\n", property.c_str()); +            } + +            return DynamicBitarray<>::to_bitarray(value); +        } else { +            return DynamicBitarray<>::to_bitarray(property.intval); +        } +        break; +    case DeviceResources::Device::ParameterFormat::VERILOG_BINARY: +        if (property.is_string) { +            std::smatch m; +            if (!std::regex_match(property.as_string(), m, verilog_binary_re)) { +                log_error("Property value %s not expected for VERILOG_BINARY type.\n", property.c_str()); +            } + +            int64_t width; +            if (!parse_int(m[1], &width)) { +                log_error("Failed to parse width from property value %s of type VERILOG_BINARY.\n", property.c_str()); +            } +            if (width < 0) { +                log_error("Expected width to be positive for property value %s\n", property.c_str()); +            } + +            return DynamicBitarray<>::parse_binary_bitstring(width, m[2]); +        } else { +            return DynamicBitarray<>::to_bitarray(property.intval); +        } +        break; +    case DeviceResources::Device::ParameterFormat::VERILOG_HEX: +        if (property.is_string) { +            std::smatch m; +            if (!std::regex_match(property.as_string(), m, verilog_hex_re)) { +                log_error("Property value %s not expected for VERILOG_HEX type.\n", property.c_str()); +            } + +            int64_t width; +            if (!parse_int(m[1], &width)) { +                log_error("Failed to parse width from property value %s of type VERILOG_HEX.\n", property.c_str()); +            } +            if (width < 0) { +                log_error("Expected width to be positive for property value %s\n", property.c_str()); +            } + +            return DynamicBitarray<>::parse_hex_bitstring(width, m[2]); +        } else { +            return DynamicBitarray<>::to_bitarray(property.intval); +        } +        break; +    case DeviceResources::Device::ParameterFormat::C_BINARY: +        if (property.is_string) { +            std::smatch m; +            if (!std::regex_match(property.as_string(), m, c_binary_re)) { +                log_error("Property value %s not expected for C_BINARY type.\n", property.c_str()); +            } + +            return DynamicBitarray<>::parse_binary_bitstring(/*width=*/-1, m[1]); +        } else { +            return DynamicBitarray<>::to_bitarray(property.intval); +        } +        break; +    case DeviceResources::Device::ParameterFormat::C_HEX: +        if (property.is_string) { +            std::smatch m; +            if (!std::regex_match(property.as_string(), m, c_hex_re)) { +                log_error("Property value %s not expected for C_HEX type.\n", property.c_str()); +            } + +            return DynamicBitarray<>::parse_hex_bitstring(/*width=*/-1, m[1]); +        } else { +            return DynamicBitarray<>::to_bitarray(property.intval); +        } +        break; +    default: +        log_error("Format %d is not int-like\n", definition->format); +    } + +    // Unreachable! +    NPNR_ASSERT(false); +} + +bool CellParameters::compare_property(const Context *ctx, IdString cell_type, IdString parameter, +                                      const Property &property, IdString value_to_compare) const +{ +    const CellParameterPOD *definition = parameters.at(std::make_pair(cell_type, parameter)); +    DeviceResources::Device::ParameterFormat format; +    format = static_cast<DeviceResources::Device::ParameterFormat>(definition->format); + +    switch (format) { +    case DeviceResources::Device::ParameterFormat::STRING: +        return value_to_compare.c_str(ctx) == property.as_string(); +    case DeviceResources::Device::ParameterFormat::FLOATING_POINT: +        // Note: Comparing floating point is pretty weird +        log_warning("Doing direct comparisions on floating points values is pretty weird, double check this.  Cell " +                    "type %s parameter %s\n", +                    cell_type.c_str(ctx), parameter.c_str(ctx)); +        return value_to_compare.c_str(ctx) == property.as_string(); +    case DeviceResources::Device::ParameterFormat::BOOLEAN: +    case DeviceResources::Device::ParameterFormat::INTEGER: +    case DeviceResources::Device::ParameterFormat::VERILOG_BINARY: +    case DeviceResources::Device::ParameterFormat::VERILOG_HEX: +    case DeviceResources::Device::ParameterFormat::C_BINARY: +    case DeviceResources::Device::ParameterFormat::C_HEX: { +        if (property.is_string) { +            // Given that string presentations should be equivalent if +            // formatted consistently, this should work most and or all of +            // the time.  If there are important exceptions, revisit this. +            return property.as_string() == value_to_compare.c_str(ctx); +        } else { +            int64_t int_to_compare; +            if (!parse_int(value_to_compare.c_str(ctx), &int_to_compare)) { +                log_error("Comparision failed, to compare value %s is not int-like\n", value_to_compare.c_str(ctx)); +            } + +            return property.intval == int_to_compare; +        } +    } +    } + +    // Unreachable! +    NPNR_ASSERT(false); +} + +NEXTPNR_NAMESPACE_END | 
