From 8a50b02b9bbaf292fb6294eda5df162f3295f149 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Mon, 22 Mar 2021 15:55:34 -0700 Subject: Use new parameter definition data in FPGA interchange processing. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fpga_interchange/arch.cc | 46 +------- fpga_interchange/arch.h | 2 + fpga_interchange/cell_parameters.cc | 222 ++++++++++++++++++++++++++++++++++++ fpga_interchange/cell_parameters.h | 55 +++++++++ 4 files changed, 284 insertions(+), 41 deletions(-) create mode 100644 fpga_interchange/cell_parameters.cc create mode 100644 fpga_interchange/cell_parameters.h (limited to 'fpga_interchange') diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index 476801aa..b5bcc7c5 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -280,6 +280,7 @@ void Arch::init() lookahead.init(getCtx(), getCtx()); #endif dedicated_interconnect.init(getCtx()); + cell_parameters.init(getCtx()); } // ----------------------------------------------------------------------- @@ -1095,14 +1096,14 @@ void Arch::map_cell_pins(CellInfo *cell, int32_t mapping, bool bind_constants) for (const auto ¶meter_pin_map : cell_pin_map.parameter_pins) { IdString param_key(parameter_pin_map.key); - std::string param_value = IdString(parameter_pin_map.value).c_str(this); + IdString param_value(parameter_pin_map.value); auto iter = cell->params.find(param_key); if (iter == cell->params.end()) { continue; } - if (param_value != iter->second.as_string()) { + if (!cell_parameters.compare_property(getCtx(), cell->type, param_key, iter->second, param_value)) { continue; } @@ -1383,44 +1384,6 @@ void Arch::report_invalid_bel(BelId bel, CellInfo *cell) const nameOfBel(bel), mapping); } -void Arch::read_lut_equation(DynamicBitarray<> *equation, const Property &equation_parameter) const -{ - equation->fill(false); - std::string eq_str = equation_parameter.as_string(); - std::smatch results; - if (std::regex_match(eq_str, results, raw_bin_constant)) { - size_t bit_idx = 0; - const std::string &bits = results[0]; - NPNR_ASSERT(bits.size() <= equation->size()); - for (auto bit = bits.rbegin(); bit != bits.rend(); ++bit) { - if (*bit == '0') { - equation->set(bit_idx++, false); - } else { - NPNR_ASSERT(*bit == '1'); - equation->set(bit_idx++, true); - } - } - } else if (std::regex_match(eq_str, results, verilog_bin_constant)) { - int iwidth = std::stoi(results[1]); - NPNR_ASSERT(iwidth >= 0); - size_t width = iwidth; - std::string bits = results[2]; - NPNR_ASSERT(width <= equation->size()); - NPNR_ASSERT(bits.size() <= width); - size_t bit_idx = 0; - for (auto bit = bits.rbegin(); bit != bits.rend(); ++bit) { - if (*bit == '0') { - equation->set(bit_idx++, false); - } else { - NPNR_ASSERT(*bit == '1'); - equation->set(bit_idx++, true); - } - } - } else { - NPNR_ASSERT(false); - } -} - void Arch::decode_lut_cells() { for (auto &cell_pair : cells) { @@ -1443,7 +1406,8 @@ void Arch::decode_lut_cells() IdString equation_parameter(lut_cell.parameter); const Property &equation = cell->params.at(equation_parameter); cell->lut_cell.equation.resize(1 << cell->lut_cell.pins.size()); - read_lut_equation(&cell->lut_cell.equation, equation); + + cell->lut_cell.equation = cell_parameters.parse_int_like(getCtx(), cell->type, equation_parameter, equation); } } diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index d167f797..8e08f17b 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -34,6 +34,7 @@ #include "relptr.h" #include "arch_iterators.h" +#include "cell_parameters.h" #include "chipdb.h" #include "dedicated_interconnect.h" #include "lookahead.h" @@ -1045,6 +1046,7 @@ struct Arch : ArchAPI Lookahead lookahead; mutable RouteNodeStorage node_storage; mutable SiteRoutingCache site_routing_cache; + CellParameters cell_parameters; std::string chipdb_hash; std::string get_chipdb_hash() const; 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 + +#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(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(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(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 diff --git a/fpga_interchange/cell_parameters.h b/fpga_interchange/cell_parameters.h new file mode 100644 index 00000000..3507a81f --- /dev/null +++ b/fpga_interchange/cell_parameters.h @@ -0,0 +1,55 @@ +/* + * 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. + * + */ + +#ifndef CELL_PARAMETERS_H +#define CELL_PARAMETERS_H + +#include + +#include "chipdb.h" +#include "dynamic_bitarray.h" +#include "hash_table.h" +#include "nextpnr_namespaces.h" +#include "property.h" + +NEXTPNR_NAMESPACE_BEGIN + +struct Context; + +struct CellParameters +{ + CellParameters(); + void init(const Context *ctx); + DynamicBitarray<> parse_int_like(const Context *ctx, IdString cell_type, IdString parameter, + const Property &property) const; + bool compare_property(const Context *ctx, IdString cell_type, IdString parameter, const Property &property, + IdString value_to_compare) const; + + HashTables::HashMap, const CellParameterPOD *> parameters; + + std::regex verilog_binary_re; + std::regex verilog_hex_re; + std::regex c_binary_re; + std::regex c_hex_re; +}; + +NEXTPNR_NAMESPACE_END + +#endif /* CELL_PARAMETERS_H */ -- cgit v1.2.3