Merge pull request #639 from litghost/parameter_iteration
Update parameter processing based on new DeviceResources metadata
This commit is contained in:
commit
8c85e648df
2
.github/ci/build_interchange.sh
vendored
2
.github/ci/build_interchange.sh
vendored
@ -26,7 +26,7 @@ popd
|
|||||||
RAPIDWRIGHT_PATH="`pwd`/RapidWright"
|
RAPIDWRIGHT_PATH="`pwd`/RapidWright"
|
||||||
INTERCHANGE_SCHEMA_PATH="`pwd`/3rdparty/fpga-interchange-schema/interchange"
|
INTERCHANGE_SCHEMA_PATH="`pwd`/3rdparty/fpga-interchange-schema/interchange"
|
||||||
PYTHON_INTERCHANGE_PATH="`pwd`/python-fpga-interchange"
|
PYTHON_INTERCHANGE_PATH="`pwd`/python-fpga-interchange"
|
||||||
PYTHON_INTERCHANGE_TAG="v0.0.2"
|
PYTHON_INTERCHANGE_TAG="v0.0.3"
|
||||||
|
|
||||||
# Install python-fpga-interchange libraries
|
# Install python-fpga-interchange libraries
|
||||||
git clone -b $PYTHON_INTERCHANGE_TAG https://github.com/SymbiFlow/python-fpga-interchange.git $PYTHON_INTERCHANGE_PATH
|
git clone -b $PYTHON_INTERCHANGE_TAG https://github.com/SymbiFlow/python-fpga-interchange.git $PYTHON_INTERCHANGE_PATH
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "nextpnr_assertions.h"
|
||||||
#include "nextpnr_namespaces.h"
|
#include "nextpnr_namespaces.h"
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
@ -73,6 +75,133 @@ template <typename Storage = std::vector<uint8_t>> class DynamicBitarray
|
|||||||
|
|
||||||
void clear() { return storage.clear(); }
|
void clear() { return storage.clear(); }
|
||||||
|
|
||||||
|
// Convert IntType to a DynamicBitarray of sufficent width
|
||||||
|
template <typename IntType> static DynamicBitarray<Storage> to_bitarray(const IntType &value)
|
||||||
|
{
|
||||||
|
if (std::numeric_limits<IntType>::is_signed) {
|
||||||
|
if (value < 0) {
|
||||||
|
log_error("Expected position value, got %s\n", std::to_string(value).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicBitarray<Storage> result;
|
||||||
|
result.resize(std::numeric_limits<IntType>::digits);
|
||||||
|
result.fill(false);
|
||||||
|
|
||||||
|
// Use a 1 of the right type (for shifting)
|
||||||
|
IntType one(1);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < std::numeric_limits<IntType>::digits; ++i) {
|
||||||
|
if ((value & (one << i)) != 0) {
|
||||||
|
result.set(i, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert binary bitstring to a DynamicBitarray of sufficent width
|
||||||
|
//
|
||||||
|
// string must be satisfy the following regex:
|
||||||
|
//
|
||||||
|
// [01]+
|
||||||
|
//
|
||||||
|
// width can either be specified explicitly, or -1 to use a size wide
|
||||||
|
// enough to store the given string.
|
||||||
|
//
|
||||||
|
// If the width is specified and the width is insufficent it will result
|
||||||
|
// in an error.
|
||||||
|
static DynamicBitarray<Storage> parse_binary_bitstring(int width, const std::string &bits)
|
||||||
|
{
|
||||||
|
NPNR_ASSERT(width == -1 || width > 0);
|
||||||
|
|
||||||
|
DynamicBitarray<Storage> result;
|
||||||
|
// If no width was supplied, use the width from the input data.
|
||||||
|
if (width == -1) {
|
||||||
|
width = bits.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
NPNR_ASSERT(width >= 0);
|
||||||
|
if ((size_t)width < bits.size()) {
|
||||||
|
log_error("String '%s' is wider than specified width %d\n", bits.c_str(), width);
|
||||||
|
}
|
||||||
|
result.resize(width);
|
||||||
|
result.fill(false);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < bits.size(); ++i) {
|
||||||
|
// bits[0] is the MSB!
|
||||||
|
size_t index = width - 1 - i;
|
||||||
|
if (!(bits[i] == '1' || bits[i] == '0')) {
|
||||||
|
log_error("String '%s' is not a valid binary bitstring?\n", bits.c_str());
|
||||||
|
}
|
||||||
|
result.set(index, bits[i] == '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert hex bitstring to a DynamicBitarray of sufficent width
|
||||||
|
//
|
||||||
|
// string must be satisfy the following regex:
|
||||||
|
//
|
||||||
|
// [0-9a-fA-F]+
|
||||||
|
//
|
||||||
|
// width can either be specified explicitly, or -1 to use a size wide
|
||||||
|
// enough to store the given string.
|
||||||
|
//
|
||||||
|
// If the width is specified and the width is insufficent it will result
|
||||||
|
// in an error.
|
||||||
|
static DynamicBitarray<Storage> parse_hex_bitstring(int width, const std::string &bits)
|
||||||
|
{
|
||||||
|
NPNR_ASSERT(width == -1 || width > 0);
|
||||||
|
|
||||||
|
DynamicBitarray<Storage> result;
|
||||||
|
// If no width was supplied, use the width from the input data.
|
||||||
|
if (width == -1) {
|
||||||
|
// Each character is 4 bits!
|
||||||
|
width = bits.size() * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
NPNR_ASSERT(width >= 0);
|
||||||
|
int rem = width % 4;
|
||||||
|
size_t check_width = width;
|
||||||
|
if (rem != 0) {
|
||||||
|
check_width += (4 - rem);
|
||||||
|
}
|
||||||
|
if (check_width < bits.size() * 4) {
|
||||||
|
log_error("String '%s' is wider than specified width %d (check_width = %zu)\n", bits.c_str(), width,
|
||||||
|
check_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.resize(width);
|
||||||
|
result.fill(false);
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
for (auto nibble_iter = bits.rbegin(); nibble_iter != bits.rend(); ++nibble_iter) {
|
||||||
|
char nibble = *nibble_iter;
|
||||||
|
|
||||||
|
int value;
|
||||||
|
if (nibble >= '0' && nibble <= '9') {
|
||||||
|
value = nibble - '0';
|
||||||
|
} else if (nibble >= 'a' && nibble <= 'f') {
|
||||||
|
value = 10 + (nibble - 'a');
|
||||||
|
} else if (nibble >= 'A' && nibble <= 'F') {
|
||||||
|
value = 10 + (nibble - 'A');
|
||||||
|
} else {
|
||||||
|
log_error("Invalid hex string '%s'?\n", bits.c_str());
|
||||||
|
}
|
||||||
|
NPNR_ASSERT(value >= 0);
|
||||||
|
NPNR_ASSERT(value < 16);
|
||||||
|
|
||||||
|
// Insert nibble into bitarray.
|
||||||
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
|
result.set(index++, (value & (1 << i)) != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Storage storage;
|
Storage storage;
|
||||||
};
|
};
|
||||||
|
@ -78,7 +78,7 @@ struct Property
|
|||||||
result.push_back(c == S1);
|
result.push_back(c == S1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
std::string as_string() const
|
const std::string &as_string() const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(is_string);
|
NPNR_ASSERT(is_string);
|
||||||
return str;
|
return str;
|
||||||
|
@ -280,6 +280,7 @@ void Arch::init()
|
|||||||
lookahead.init(getCtx(), getCtx());
|
lookahead.init(getCtx(), getCtx());
|
||||||
#endif
|
#endif
|
||||||
dedicated_interconnect.init(getCtx());
|
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) {
|
for (const auto ¶meter_pin_map : cell_pin_map.parameter_pins) {
|
||||||
IdString param_key(parameter_pin_map.key);
|
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);
|
auto iter = cell->params.find(param_key);
|
||||||
if (iter == cell->params.end()) {
|
if (iter == cell->params.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param_value != iter->second.as_string()) {
|
if (!cell_parameters.compare_property(getCtx(), cell->type, param_key, iter->second, param_value)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1383,44 +1384,6 @@ void Arch::report_invalid_bel(BelId bel, CellInfo *cell) const
|
|||||||
nameOfBel(bel), mapping);
|
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()
|
void Arch::decode_lut_cells()
|
||||||
{
|
{
|
||||||
for (auto &cell_pair : cells) {
|
for (auto &cell_pair : cells) {
|
||||||
@ -1443,7 +1406,8 @@ void Arch::decode_lut_cells()
|
|||||||
IdString equation_parameter(lut_cell.parameter);
|
IdString equation_parameter(lut_cell.parameter);
|
||||||
const Property &equation = cell->params.at(equation_parameter);
|
const Property &equation = cell->params.at(equation_parameter);
|
||||||
cell->lut_cell.equation.resize(1 << cell->lut_cell.pins.size());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "relptr.h"
|
#include "relptr.h"
|
||||||
|
|
||||||
#include "arch_iterators.h"
|
#include "arch_iterators.h"
|
||||||
|
#include "cell_parameters.h"
|
||||||
#include "chipdb.h"
|
#include "chipdb.h"
|
||||||
#include "dedicated_interconnect.h"
|
#include "dedicated_interconnect.h"
|
||||||
#include "lookahead.h"
|
#include "lookahead.h"
|
||||||
@ -1045,6 +1046,7 @@ struct Arch : ArchAPI<ArchRanges>
|
|||||||
Lookahead lookahead;
|
Lookahead lookahead;
|
||||||
mutable RouteNodeStorage node_storage;
|
mutable RouteNodeStorage node_storage;
|
||||||
mutable SiteRoutingCache site_routing_cache;
|
mutable SiteRoutingCache site_routing_cache;
|
||||||
|
CellParameters cell_parameters;
|
||||||
|
|
||||||
std::string chipdb_hash;
|
std::string chipdb_hash;
|
||||||
std::string get_chipdb_hash() const;
|
std::string get_chipdb_hash() const;
|
||||||
|
222
fpga_interchange/cell_parameters.cc
Normal file
222
fpga_interchange/cell_parameters.cc
Normal file
@ -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
|
55
fpga_interchange/cell_parameters.h
Normal file
55
fpga_interchange/cell_parameters.h
Normal file
@ -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 */
|
@ -34,7 +34,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
* kExpectedChipInfoVersion
|
* kExpectedChipInfoVersion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static constexpr int32_t kExpectedChipInfoVersion = 2;
|
static constexpr int32_t kExpectedChipInfoVersion = 4;
|
||||||
|
|
||||||
// Flattened site indexing.
|
// Flattened site indexing.
|
||||||
//
|
//
|
||||||
@ -71,6 +71,15 @@ NPNR_PACKED_STRUCT(struct BelInfoPOD {
|
|||||||
int8_t lut_element;
|
int8_t lut_element;
|
||||||
|
|
||||||
RelPtr<int32_t> pin_map; // Index into CellMapPOD::cell_bel_map
|
RelPtr<int32_t> pin_map; // Index into CellMapPOD::cell_bel_map
|
||||||
|
|
||||||
|
// If this BEL is a site routing BEL with inverting pins, these values
|
||||||
|
// will be [0, num_bel_wires). If this BEL is either not a site routing
|
||||||
|
// BEL or this site routing has no inversion capabilities, then these will
|
||||||
|
// both be -1.
|
||||||
|
int8_t non_inverting_pin;
|
||||||
|
int8_t inverting_pin;
|
||||||
|
|
||||||
|
int16_t padding;
|
||||||
});
|
});
|
||||||
|
|
||||||
enum BELCategory
|
enum BELCategory
|
||||||
@ -198,6 +207,14 @@ NPNR_PACKED_STRUCT(struct CellConstraintPOD {
|
|||||||
RelSlice<int32_t> states; // State indicies
|
RelSlice<int32_t> states; // State indicies
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Cell parameters metadata
|
||||||
|
NPNR_PACKED_STRUCT(struct CellParameterPOD {
|
||||||
|
int32_t cell_type; // constid
|
||||||
|
int32_t parameter; // constid
|
||||||
|
int32_t format; // ParameterFormat enum
|
||||||
|
int32_t default_value; // constid
|
||||||
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct CellBelMapPOD {
|
NPNR_PACKED_STRUCT(struct CellBelMapPOD {
|
||||||
RelSlice<CellBelPinPOD> common_pins;
|
RelSlice<CellBelPinPOD> common_pins;
|
||||||
RelSlice<ParameterPinsPOD> parameter_pins;
|
RelSlice<ParameterPinsPOD> parameter_pins;
|
||||||
@ -218,6 +235,7 @@ NPNR_PACKED_STRUCT(struct CellMapPOD {
|
|||||||
RelSlice<CellBelMapPOD> cell_bel_map;
|
RelSlice<CellBelMapPOD> cell_bel_map;
|
||||||
|
|
||||||
RelSlice<LutCellPOD> lut_cells;
|
RelSlice<LutCellPOD> lut_cells;
|
||||||
|
RelSlice<CellParameterPOD> cell_parameters;
|
||||||
});
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct PackagePinPOD {
|
NPNR_PACKED_STRUCT(struct PackagePinPOD {
|
||||||
@ -252,6 +270,10 @@ NPNR_PACKED_STRUCT(struct ConstantsPOD {
|
|||||||
|
|
||||||
// Name to use for the global VCC constant net
|
// Name to use for the global VCC constant net
|
||||||
int32_t vcc_net_name; // constid
|
int32_t vcc_net_name; // constid
|
||||||
|
|
||||||
|
// If a choice is available, which constant net should be used?
|
||||||
|
// Can be ''/0 if either constant net are equivilent.
|
||||||
|
int32_t best_constant_net; // constid
|
||||||
});
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||||
@ -306,6 +328,14 @@ inline const SiteInstInfoPOD &site_inst_info(const ChipInfoPOD *chip_info, int32
|
|||||||
return chip_info->sites[chip_info->tiles[tile].sites[site]];
|
return chip_info->sites[chip_info->tiles[tile].sites[site]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SyntheticType
|
||||||
|
{
|
||||||
|
NOT_SYNTH = 0,
|
||||||
|
SYNTH_SIGNAL = 1,
|
||||||
|
SYNTH_GND = 2,
|
||||||
|
SYNTH_VCC = 3,
|
||||||
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* CHIPDB_H */
|
#endif /* CHIPDB_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user