Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Himbaechel xilinx : Add support of DSP packing for 7-series #1363

Merged
merged 11 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions common/kernel/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename KeyType>
bool boolstr_or_default(const dict<KeyType, Property> &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 <typename KeyType>
bool boolvec_populate(const dict<KeyType, Property> &ct, const KeyType &key, std::vector<bool>& 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.
Expand Down
29 changes: 21 additions & 8 deletions common/place/placer_heap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -301,30 +301,43 @@ class HeAPPlacer
++iter;
}

// Apply saved solution
// Remove any previous binding
for (auto &sc : solution) {
CellInfo *cell = std::get<0>(sc);
if (cell->bel != BelId())
ctx->unbindBel(cell->bel);
}
// Apply saved solution
for (auto &sc : solution) {
CellInfo *cell;
BelId bel;
PlaceStrength strength;
std::tie(cell, bel, strength) = sc;
// Just skip unbound cells here, these errors are handled just after
if (bel == BelId())
continue;
ctx->bindBel(bel, cell, strength);
}

// Find and display all errors to help in finding the root cause of issues
unsigned num_errors = 0;
for (auto &cell : ctx->cells) {
if (cell.second->isPseudo())
continue;
if (cell.second->bel == BelId())
log_error("Found unbound cell %s\n", cell.first.c_str(ctx));
if (ctx->getBoundBelCell(cell.second->bel) != cell.second.get())
log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx));
if (ctx->debug)
if (cell.second->bel == BelId()) {
log_nonfatal_error("Found unbound cell '%s' of type '%s'\n", cell.first.c_str(ctx), cell.second->type.c_str(ctx));
num_errors++;
}
else if (ctx->getBoundBelCell(cell.second->bel) != cell.second.get()) {
log_nonfatal_error("Found mismatched binding for '%s' or type '%s'\n", cell.first.c_str(ctx), cell.second->type.c_str(ctx));
num_errors++;
}
else if (ctx->debug)
log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel));
}
if (num_errors > 0) {
log_error("Stopping the program after %u errors found\n", num_errors);
}

bool any_bad_placements = false;
for (auto bel : ctx->getBels()) {
Expand Down Expand Up @@ -886,10 +899,10 @@ class HeAPPlacer

while (!placed) {
if (cfg.cell_placement_timeout > 0 && total_iters_for_cell > cfg.cell_placement_timeout)
log_error("Unable to find legal placement for cell '%s' after %d attempts, check constraints and "
log_error("Unable to find legal placement for cell '%s' of type '%s' after %d attempts, check constraints and "
"utilisation. Use `--placer-heap-cell-placement-timeout` to change the number of "
"attempts.\n",
ctx->nameOf(ci), total_iters_for_cell);
ctx->nameOf(ci), ci->type.c_str(ctx), total_iters_for_cell);

// Determine a search radius around the solver location (which increases over time) that is clamped to
// the region constraint for the cell (if applicable)
Expand Down
4 changes: 4 additions & 0 deletions himbaechel/uarch/xilinx/constids.inc
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ X(BUFMRCE)
X(C)
X(CARRYIN)
X(CARRY_TYPE)
X(CARRYCASCIN)
X(CARRYCASCOUT)
X(CB)
X(CDDCREQ)
X(CE0)
Expand Down Expand Up @@ -531,6 +533,8 @@ X(MMCME3_ADV)
X(MMCME3_BASE)
X(MMCME4_ADV)
X(MMCME4_BASIC)
X(MULTSIGNIN)
X(MULTSIGNOUT)
X(MUXCY)
X(MUXF7)
X(MUXF8)
Expand Down
30 changes: 13 additions & 17 deletions himbaechel/uarch/xilinx/fasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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<bool> 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<bool> 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);
}

Expand All @@ -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<bool> 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")
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion himbaechel/uarch/xilinx/pack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ void XilinxImpl::pack()
packer.pack_luts();
packer.pack_dram();
packer.pack_bram();
// packer.pack_dsps();
packer.pack_dsps();
packer.pack_ffs();
packer.finalise_muxfs();
packer.pack_lutffs();
Expand Down
2 changes: 1 addition & 1 deletion himbaechel/uarch/xilinx/pack.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ struct XC7Packer : public XilinxPacker
void pack_dsps();

private:
void walk_dsp(CellInfo *root, CellInfo *ci, int constr_z);
unsigned walk_dsp(CellInfo *root, CellInfo *ci, int constr_z);
void check_valid_pad(CellInfo *ci, std::string type);
};

Expand Down
Loading