aboutsummaryrefslogtreecommitdiffstats
path: root/fpga_interchange
diff options
context:
space:
mode:
authorKeith Rothman <537074+litghost@users.noreply.github.com>2021-03-22 15:55:34 -0700
committerKeith Rothman <537074+litghost@users.noreply.github.com>2021-03-23 09:01:43 -0700
commit8a50b02b9bbaf292fb6294eda5df162f3295f149 (patch)
tree5caa463594b7e2468b4d17ec33aa019ec42cb22d /fpga_interchange
parentaf1fba9f5232706af4ae31ad5b0186b44de03cfa (diff)
downloadnextpnr-8a50b02b9bbaf292fb6294eda5df162f3295f149.tar.gz
nextpnr-8a50b02b9bbaf292fb6294eda5df162f3295f149.tar.bz2
nextpnr-8a50b02b9bbaf292fb6294eda5df162f3295f149.zip
Use new parameter definition data in FPGA interchange processing.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
Diffstat (limited to 'fpga_interchange')
-rw-r--r--fpga_interchange/arch.cc46
-rw-r--r--fpga_interchange/arch.h2
-rw-r--r--fpga_interchange/cell_parameters.cc222
-rw-r--r--fpga_interchange/cell_parameters.h55
4 files changed, 284 insertions, 41 deletions
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 &parameter_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<ArchRanges>
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 <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
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 <regex>
+
+#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<std::pair<IdString, IdString>, 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 */