Merge remote-tracking branch 'origin/diego/memattr' into eddie/exp
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index aa8f941..cd8c9c5 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc
@@ -134,6 +134,8 @@ dict<string, int> min_limits, max_limits; bool or_next_if_better, make_transp, make_outreg; char shuffle_enable; + IdString attr; + Const value; }; dict<IdString, vector<bram_t>> brams; @@ -327,6 +329,13 @@ continue; } + if (GetSize(tokens) >= 2 && tokens[0] == "attribute") { + data.attr = RTLIL::escape_id(tokens[1]); + if (GetSize(tokens) > 2) + data.value = tokens[2]; + continue; + } + syntax_error(); } } @@ -813,6 +822,23 @@ return false; } + if (!match.attr.empty()) { + auto it = cell->attributes.find(match.attr); + if (it == cell->attributes.end()) { + if (!match.value.empty()) + log(" Rule for bram type %s rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(match.attr), match.value.decode_string().c_str()); + return false; + } + else { + if (it->second != match.value) { + log(" Rule for bram type %s rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(match.attr), match.value.decode_string().c_str()); + return false; + } + } + } + if (mode == 1) return true; } @@ -1100,6 +1126,24 @@ goto next_match_rule; } + if (!match.attr.empty()) { + auto it = cell->attributes.find(match.attr); + if (it == cell->attributes.end()) { + if (!match.value.empty()) { + log(" Rule for bram type %s rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(match.attr), match.value.decode_string().c_str()); + goto next_match_rule; + } + } + else { + if (it->second != match.value) { + log(" Rule for bram type %s rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(match.attr), match.value.decode_string().c_str()); + goto next_match_rule; + } + } + } + log(" Rule #%d for bram type %s (variant %d) accepted.\n", i+1, log_id(bram.name), bram.variant); if (or_next_if_better || !best_rule_cache.empty()) @@ -1225,6 +1269,11 @@ log(" dcells ....... number of cells in 'data-direction'\n"); log(" cells ........ total number of cells (acells*dcells*dups)\n"); log("\n"); + log("A match containing the condition 'attribute' followed by a name and optional\n"); + log("value requires that the memory contains the given attribute name and value\n"); + log("(if specified) or that the attribute is not present or the value is empty (if\n"); + log("value is not specified\n)."); + log("\n"); log("The interface for the created bram instances is derived from the bram\n"); log("description. Use 'techmap' to convert the created bram instances into\n"); log("instances of the actual bram cells of your target architecture.\n");
diff --git a/techlibs/xilinx/xc7_xcu_brams.txt b/techlibs/xilinx/xc7_xcu_brams.txt index ca71924..7d3d997 100644 --- a/techlibs/xilinx/xc7_xcu_brams.txt +++ b/techlibs/xilinx/xc7_xcu_brams.txt
@@ -85,6 +85,14 @@ min efficiency 5 shuffle_enable B make_transp + attribute ram_style + or_next_if_better +endmatch + +match $__XILINX_RAMB18_SDP + shuffle_enable B + make_transp + attribute ram_style block or_next_if_better endmatch