From 266993408a2b926ffefcf536feb92b36b11e398e Mon Sep 17 00:00:00 2001 From: Diego H Date: Fri, 13 Dec 2019 15:43:24 -0600 Subject: Refactoring memory attribute matching based on IEEE 1364.1 and Tool specific --- passes/memory/memory_bram.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index aa8f94149..35cd0647a 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -327,6 +327,20 @@ struct rules_t continue; } + if (GetSize(tokens) >= 2 && tokens[0] == "attribute") { + for (int idx=1; idx<= GetSize(tokens)-1; idx++) { + size_t val = tokens[idx].find_first_of("!="); + if (val != std::string::npos) { + if (val == 0) { + data.attr_unmatch[RTLIL::escape_id(tokens[idx].substr(val+1))]; + } + else { + data.attr_match[RTLIL::escape_id(tokens[idx].substr(0, val))] = tokens[idx].substr(val+1); + } + } + } + continue; + } syntax_error(); } } @@ -813,6 +827,27 @@ grow_read_ports:; return false; } + if (!match.attr_match.empty()) { + for (auto iter: match.attr_match) { + auto it = cell->attributes.find(iter.first); + + if (iter.second.empty()) { + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); + return false; + } + + if (it != cell->attributes.end()) { + if (it->second == iter.second) + continue; + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); + return false; + } + continue; + } + } + if (mode == 1) return true; } @@ -997,6 +1032,7 @@ void handle_cell(Cell *cell, const rules_t &rules) log("Processing %s.%s:\n", log_id(cell->module), log_id(cell)); bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef(); + int access = 0; dict match_properties; match_properties["words"] = cell->getParam("\\SIZE").as_int(); @@ -1100,6 +1136,42 @@ void handle_cell(Cell *cell, const rules_t &rules) goto next_match_rule; } + for (auto iter: match.attr_unmatch) { + auto it = cell->attributes.find(iter.first); + + if (it != cell->attributes.end()) { + log(" Rule for bram type %s is rejected: requirement 'attribute %s' is met.\n", + log_id(match.name), iter.first.c_str()); + goto next_match_rule; + } + continue; + } + + if (!match.attr_match.empty()) { + for (auto iter: match.attr_match) { + int len=std::tuple_size::value; + auto it = cell->attributes.find(iter.first); + + if (iter.second.empty()) { + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); + continue; + } + + if (it != cell->attributes.end()) { + if (it->second == iter.second) + continue; + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); + } + access ++; + if (access == len) { + access = 0; + 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 +1297,11 @@ struct MemoryBramPass : public Pass { 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 (prepending a '!')\n"); + log("or the value is empty (if 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"); -- cgit v1.2.3 From b35559fc335181d7c8f8046fa17bf05550c21ba7 Mon Sep 17 00:00:00 2001 From: Diego H Date: Sun, 15 Dec 2019 23:33:09 -0600 Subject: Merging attribute rules into a single match block; Adding tests --- passes/memory/memory_bram.cc | 148 +++++++++++++++++++++++-------------------- 1 file changed, 80 insertions(+), 68 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 35cd0647a..10b48e321 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -134,6 +134,9 @@ struct rules_t dict min_limits, max_limits; bool or_next_if_better, make_transp, make_outreg; char shuffle_enable; + dict>> attr_match; + pair attr_val; + dict attr_unmatch; }; dict> brams; @@ -328,19 +331,31 @@ struct rules_t } if (GetSize(tokens) >= 2 && tokens[0] == "attribute") { - for (int idx=1; idx<= GetSize(tokens)-1; idx++) { - size_t val = tokens[idx].find_first_of("!="); - if (val != std::string::npos) { - if (val == 0) { - data.attr_unmatch[RTLIL::escape_id(tokens[idx].substr(val+1))]; - } - else { - data.attr_match[RTLIL::escape_id(tokens[idx].substr(0, val))] = tokens[idx].substr(val+1); + if (GetSize(tokens) <=2) { + size_t notval = tokens[1].find("!"); + size_t val = tokens[1].find("="); + + if (notval != std::string::npos) { + if (val != std::string::npos) + data.attr_unmatch[RTLIL::escape_id(tokens[1].substr(1, val-1))] = tokens[1].substr(val+1); + else + data.attr_unmatch[RTLIL::escape_id(tokens[1].substr(notval+1))] = RTLIL::Const('1'); + } + continue; + } + + else if (GetSize(tokens) > 2) { + for (int idx=1; idx<= GetSize(tokens)-1; idx++) { + size_t val = tokens[idx].find("="); + if (val != std::string::npos) { + data.attr_val = make_pair(RTLIL::escape_id(tokens[idx].substr(0, val)), tokens[idx].substr(val+1)); + data.attr_match[RTLIL::escape_id(tokens[0])].push_back(data.attr_val); } } + continue; } - continue; } + syntax_error(); } } @@ -738,7 +753,7 @@ grow_read_ports:; if (match.make_transp && wr_ports <= 1) { pi.make_transp = true; if (pi.clocks != 0) { - if (wr_ports == 1 && wr_clkdom != clkdom) { + if (wr_ports == 1 && wr_clkdom != clkdom) { log(" Bram port %c%d.%d cannot have soft transparency logic added as read and write clock domains differ.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } @@ -806,6 +821,27 @@ grow_read_ports:; log(" Updated properties: dups=%d waste=%d efficiency=%d\n", match_properties["dups"], match_properties["waste"], match_properties["efficiency"]); + for (auto& iter: match.attr_match) { + for (auto& iter: iter.second) { + auto it = cell->attributes.find(iter.first); + + if (iter.second.empty()) { + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(iter.first), iter.second.decode_string().c_str()); + return false; + } + + if (it != cell->attributes.end()) { + if (it->second == iter.second) + continue; + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(iter.first), iter.second.decode_string().c_str()); + return false; + } + return true; + } + } + for (auto it : match.min_limits) { if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", @@ -827,27 +863,6 @@ grow_read_ports:; return false; } - if (!match.attr_match.empty()) { - for (auto iter: match.attr_match) { - auto it = cell->attributes.find(iter.first); - - if (iter.second.empty()) { - log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", - log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); - return false; - } - - if (it != cell->attributes.end()) { - if (it->second == iter.second) - continue; - log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", - log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); - return false; - } - continue; - } - } - if (mode == 1) return true; } @@ -1032,7 +1047,6 @@ void handle_cell(Cell *cell, const rules_t &rules) log("Processing %s.%s:\n", log_id(cell->module), log_id(cell)); bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef(); - int access = 0; dict match_properties; match_properties["words"] = cell->getParam("\\SIZE").as_int(); @@ -1110,6 +1124,39 @@ void handle_cell(Cell *cell, const rules_t &rules) goto next_match_rule; } + for (auto& iter: match.attr_match) { + for (auto& iter: iter.second) { + auto it = cell->attributes.find(iter.first); + + if (it != cell->attributes.end()) { + if (!it->second.empty()) { + if (it->second.decode_string().length() == 1) + it->second = it->second.as_string().back(); + if (!it->second.decode_string().compare(iter.second.decode_string())) + goto attribute_matched; + else + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(iter.first), iter.second.decode_string().c_str()); + } + } + } + } + + for (auto& iter: match.attr_unmatch) { + auto it = cell->attributes.find(iter.first); + + if (it != cell->attributes.end()) { + if (!it->second.empty()) { + if (it->second.decode_string().length() == 1) + it->second = it->second.as_string().back(); + if (!it->second.decode_string().compare(iter.second.decode_string())) + goto next_match_rule; + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(iter.first), iter.second.decode_string().c_str()); + } + } + } + for (auto it : match.min_limits) { if (it.first == "waste" || it.first == "dups" || it.first == "acells" || it.first == "dcells" || it.first == "cells") continue; @@ -1136,42 +1183,7 @@ void handle_cell(Cell *cell, const rules_t &rules) goto next_match_rule; } - for (auto iter: match.attr_unmatch) { - auto it = cell->attributes.find(iter.first); - - if (it != cell->attributes.end()) { - log(" Rule for bram type %s is rejected: requirement 'attribute %s' is met.\n", - log_id(match.name), iter.first.c_str()); - goto next_match_rule; - } - continue; - } - - if (!match.attr_match.empty()) { - for (auto iter: match.attr_match) { - int len=std::tuple_size::value; - auto it = cell->attributes.find(iter.first); - - if (iter.second.empty()) { - log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", - log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); - continue; - } - - if (it != cell->attributes.end()) { - if (it->second == iter.second) - continue; - log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", - log_id(match.name), iter.first.c_str(), iter.second.decode_string().c_str()); - } - access ++; - if (access == len) { - access = 0; - goto next_match_rule; - } - } - } - + attribute_matched: 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()) -- cgit v1.2.3 From 87e21b0122bd682db8aeffae3e1ac503c9cea2d2 Mon Sep 17 00:00:00 2001 From: Diego H Date: Mon, 16 Dec 2019 10:23:45 -0600 Subject: Fixing compiler warning/issues. Moving test script to the correct place --- passes/memory/memory_bram.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 10b48e321..703e87f05 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -821,8 +821,8 @@ grow_read_ports:; log(" Updated properties: dups=%d waste=%d efficiency=%d\n", match_properties["dups"], match_properties["waste"], match_properties["efficiency"]); - for (auto& iter: match.attr_match) { - for (auto& iter: iter.second) { + for (auto iter: match.attr_match) { + for (auto iter: iter.second) { auto it = cell->attributes.find(iter.first); if (iter.second.empty()) { @@ -1124,8 +1124,8 @@ void handle_cell(Cell *cell, const rules_t &rules) goto next_match_rule; } - for (auto& iter: match.attr_match) { - for (auto& iter: iter.second) { + for (auto iter: match.attr_match) { + for (auto iter: iter.second) { auto it = cell->attributes.find(iter.first); if (it != cell->attributes.end()) { @@ -1149,10 +1149,10 @@ void handle_cell(Cell *cell, const rules_t &rules) if (!it->second.empty()) { if (it->second.decode_string().length() == 1) it->second = it->second.as_string().back(); - if (!it->second.decode_string().compare(iter.second.decode_string())) - goto next_match_rule; - log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", - log_id(match.name), log_id(iter.first), iter.second.decode_string().c_str()); + if (!it->second.decode_string().compare(iter.second.decode_string())) + goto next_match_rule; + log(" Rule for bram type %s is rejected: requirement 'attribute %s=\"%s\"' not met.\n", + log_id(match.name), log_id(iter.first), iter.second.decode_string().c_str()); } } } -- cgit v1.2.3