From 4c7cda1c8b8a782da90f6bbd00e0a98aa1817f6e Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Thu, 12 Dec 2019 16:14:20 +0100 Subject: add a command to read/modify scratchpad contents --- passes/cmds/Makefile.inc | 1 + passes/cmds/scratchpad.cc | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 passes/cmds/scratchpad.cc (limited to 'passes') diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index c7edc30fb..07a5d3ddc 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -32,3 +32,4 @@ OBJS += passes/cmds/chtype.o OBJS += passes/cmds/blackbox.o OBJS += passes/cmds/ltp.o OBJS += passes/cmds/bugpoint.o +OBJS += passes/cmds/scratchpad.o diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc new file mode 100644 index 000000000..7d53c8a4f --- /dev/null +++ b/passes/cmds/scratchpad.cc @@ -0,0 +1,86 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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 "kernel/register.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct ScratchpadPass : public Pass { + ScratchpadPass() : Pass("scratchpad", "get/set values in the scratchpad") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" scratchpad [ -get id | -set id val | -unset id | -copy id1 id2 ]\n"); + log("\n"); + log("This pass allows to read and modify values from the scratchpad of the current\n"); + log("design. Options:\n"); + log(" -get \n"); + log(" -set \n"); + log(" -unset \n"); + log(" -copy \n"); + log("The identifier may not contain whitespace. By convention, it is usually prefixed\n"); + log("by the name of the pass that uses it, e.g. 'opt.did_something'. If the value\n"); + log("contains whitespace, it must be enclosed in double quotes.\n"); + log("\n"); + } + + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-get" && argidx+1 < args.size()) { + string identifier = args[++argidx]; + if (design->scratchpad.count(identifier)){ + log("%s\n", design->scratchpad_get_string(identifier).c_str()); + } else { + log("\"%s\" not set\n", identifier.c_str()); + } + continue; + } + if (args[argidx] == "-set" && argidx+2 < args.size()) { + string identifier = args[++argidx]; + string value = args[++argidx]; + if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2); + design->scratchpad_set_string(identifier, value); + continue; + } + if (args[argidx] == "-unset" && argidx+1 < args.size()) { + string identifier = args[++argidx]; + design->scratchpad_unset(identifier); + continue; + } + if (args[argidx] == "-copy" && argidx+2 < args.size()) { + string identifier_from = args[++argidx]; + string identifier_to = args[++argidx]; + if (design->scratchpad.count(identifier_from) == 0) log_error("\"%s\" not set\n", identifier_from.c_str()); + string value = design->scratchpad_get_string(identifier_from); + design->scratchpad_set_string(identifier_to, value); + continue; + } + log("Unrecognized argument: %s\n", args[argidx].c_str()); + break; + } + } +} ScratchpadPass; +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 1187e91c2f2684cb204c555cb3d53b68c7381c40 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Thu, 12 Dec 2019 20:51:59 +0100 Subject: add test and make help message more verbose --- passes/cmds/scratchpad.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc index 7d53c8a4f..c11c41caf 100644 --- a/passes/cmds/scratchpad.cc +++ b/passes/cmds/scratchpad.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * 2019 Nina Engelhardt * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -30,14 +31,18 @@ struct ScratchpadPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" scratchpad [ -get id | -set id val | -unset id | -copy id1 id2 ]\n"); + log(" scratchpad [options]\n"); log("\n"); log("This pass allows to read and modify values from the scratchpad of the current\n"); log("design. Options:\n"); log(" -get \n"); + log(" print the value saved in the scratchpad under the given identifier\n"); log(" -set \n"); + log(" save the given value in the scratchpad under the given identifier\n"); log(" -unset \n"); + log(" remove the entry for the given identifier from the scratchpad\n"); log(" -copy \n"); + log(" copy the value of the first identifier to the second identifier\n"); log("The identifier may not contain whitespace. By convention, it is usually prefixed\n"); log("by the name of the pass that uses it, e.g. 'opt.did_something'. If the value\n"); log("contains whitespace, it must be enclosed in double quotes.\n"); -- cgit v1.2.3 From ce3615b3670b942ae281db425b290023b1395b69 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Fri, 13 Dec 2019 10:28:34 +0100 Subject: add periods and newlines to help message --- passes/cmds/scratchpad.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'passes') diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc index c11c41caf..6bf14a6bd 100644 --- a/passes/cmds/scratchpad.cc +++ b/passes/cmds/scratchpad.cc @@ -34,15 +34,15 @@ struct ScratchpadPass : public Pass { log(" scratchpad [options]\n"); log("\n"); log("This pass allows to read and modify values from the scratchpad of the current\n"); - log("design. Options:\n"); + log("design. Options:\n\n"); log(" -get \n"); - log(" print the value saved in the scratchpad under the given identifier\n"); + log(" print the value saved in the scratchpad under the given identifier.\n\n"); log(" -set \n"); - log(" save the given value in the scratchpad under the given identifier\n"); + log(" save the given value in the scratchpad under the given identifier.\n\n"); log(" -unset \n"); - log(" remove the entry for the given identifier from the scratchpad\n"); + log(" remove the entry for the given identifier from the scratchpad.\n\n"); log(" -copy \n"); - log(" copy the value of the first identifier to the second identifier\n"); + log(" copy the value of the first identifier to the second identifier.\n\n"); log("The identifier may not contain whitespace. By convention, it is usually prefixed\n"); log("by the name of the pass that uses it, e.g. 'opt.did_something'. If the value\n"); log("contains whitespace, it must be enclosed in double quotes.\n"); -- cgit v1.2.3 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 e709fd3da1c7e3ae36ee43a997fbd413909c764e Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Sun, 15 Dec 2019 20:40:38 +0100 Subject: Fix opt_expr.eqneq.cmpzero debug print --- passes/opt/opt_expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 6cf66fb95..4a2f170b8 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -978,7 +978,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), - log_id(module), "$eq" ? "$logic_not" : "$reduce_bool"); + log_id(module), cell->type == ID($eq) ? "$logic_not" : "$reduce_bool"); cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool); if (assign_map(cell->getPort(ID::A)).is_fully_zero()) { cell->setPort(ID::A, cell->getPort(ID::B)); -- 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 abcd82dacadc8b5af6b2b7f6d7cbdb635d276440 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Mon, 16 Dec 2019 13:09:31 +0100 Subject: add assert option to scratchpad command --- passes/cmds/scratchpad.cc | 49 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) (limited to 'passes') diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc index 6bf14a6bd..805badc7e 100644 --- a/passes/cmds/scratchpad.cc +++ b/passes/cmds/scratchpad.cc @@ -34,15 +34,29 @@ struct ScratchpadPass : public Pass { log(" scratchpad [options]\n"); log("\n"); log("This pass allows to read and modify values from the scratchpad of the current\n"); - log("design. Options:\n\n"); + log("design. Options:\n"); + log("\n"); log(" -get \n"); - log(" print the value saved in the scratchpad under the given identifier.\n\n"); + log(" print the value saved in the scratchpad under the given identifier.\n"); + log("\n"); log(" -set \n"); - log(" save the given value in the scratchpad under the given identifier.\n\n"); + log(" save the given value in the scratchpad under the given identifier.\n"); + log("\n"); log(" -unset \n"); - log(" remove the entry for the given identifier from the scratchpad.\n\n"); + log(" remove the entry for the given identifier from the scratchpad.\n"); + log("\n"); log(" -copy \n"); - log(" copy the value of the first identifier to the second identifier.\n\n"); + log(" copy the value of the first identifier to the second identifier.\n"); + log("\n"); + log(" -assert \n"); + log(" assert that the entry for the given identifier is set to the given value.\n"); + log("\n"); + log(" -assert-set \n"); + log(" assert that the entry for the given identifier exists.\n"); + log("\n"); + log(" -assert-unset \n"); + log(" assert that the entry for the given identifier does not exist.\n"); + log("\n"); log("The identifier may not contain whitespace. By convention, it is usually prefixed\n"); log("by the name of the pass that uses it, e.g. 'opt.did_something'. If the value\n"); log("contains whitespace, it must be enclosed in double quotes.\n"); @@ -83,6 +97,31 @@ struct ScratchpadPass : public Pass { design->scratchpad_set_string(identifier_to, value); continue; } + if (args[argidx] == "-assert" && argidx+2 < args.size()) { + string identifier = args[++argidx]; + string expected = args[++argidx]; + if (expected.front() == '\"' && expected.back() == '\"') expected = expected.substr(1, expected.size() - 2); + if (design->scratchpad.count(identifier) == 0) + log_error("Assertion failed: scratchpad entry '%s' is not defined\n", identifier.c_str()); + string value = design->scratchpad_get_string(identifier); + if (value != expected) { + log_error("Assertion failed: scratchpad entry '%s' is set to '%s' instead of the asserted '%s'\n", + identifier.c_str(), value.c_str(), expected.c_str()); + } + continue; + } + if (args[argidx] == "-assert-set" && argidx+1 < args.size()) { + string identifier = args[++argidx]; + if (design->scratchpad.count(identifier) == 0) + log_error("Assertion failed: scratchpad entry '%s' is not defined\n", identifier.c_str()); + continue; + } + if (args[argidx] == "-assert-unset" && argidx+1 < args.size()) { + string identifier = args[++argidx]; + if (design->scratchpad.count(identifier) > 0) + log_error("Assertion failed: scratchpad entry '%s' is defined\n", identifier.c_str()); + continue; + } log("Unrecognized argument: %s\n", args[argidx].c_str()); break; } -- 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 From 503d1db551b5ab91a6ed262d011f5b9b2fa78d8e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 12:58:13 -0800 Subject: Implement 'attributes' grammar --- passes/memory/memory_bram.cc | 168 ++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 80 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 703e87f05..a1353e56d 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -134,9 +134,7 @@ 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; + vector>> attributes; }; dict> brams; @@ -331,29 +329,20 @@ struct rules_t } if (GetSize(tokens) >= 2 && tokens[0] == "attribute") { - 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; + data.attributes.emplace_back(); + for (int idx = 1; idx <= GetSize(tokens)-1; idx++) { + size_t c1 = tokens[1][0] == '!' ? 1 : 0; + size_t c2 = tokens[1].find("="); + if (c2 != std::string::npos) + c2--; + + bool exists = (c1 == 0); + IdString key = RTLIL::escape_id(tokens[1].substr(c1, c2)); + Const val = c2 != std::string::npos ? tokens[1].substr(c2) : RTLIL::Const(1); + + data.attributes.back().emplace_back(exists, key, val); } + continue; } syntax_error(); @@ -821,27 +810,6 @@ 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", @@ -863,6 +831,43 @@ grow_read_ports:; return false; } + for (const auto &sums : match.attributes) { + bool found = false; + for (const auto &term : sums) { + bool exists = std::get<0>(term); + IdString key = std::get<1>(term); + const Const &value = std::get<2>(term); + auto it = cell->attributes.find(key); + if (it == cell->attributes.end()) { + if (exists) + continue; + found = true; + break; + } + if (it->second != value) + continue; + found = true; + break; + } + if (!found) { + std::stringstream ss; + bool exists = std::get<0>(sums.front()); + if (!exists) + ss << "!"; + IdString key = std::get<1>(sums.front()); + ss << key.str(); + const Const &value = std::get<2>(sums.front()); + if (exists) + ss << "="; + if (value != Const(1)) + ss << "\"" << value.decode_string() << "\""; + + log(" Rule for bram type %s rejected: requirement 'attribute %s ...' not met.\n", + log_id(match.name), ss.str().c_str()); + return false; + } + } + if (mode == 1) return true; } @@ -1124,39 +1129,6 @@ 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; @@ -1183,7 +1155,43 @@ void handle_cell(Cell *cell, const rules_t &rules) goto next_match_rule; } - attribute_matched: + for (const auto &sums : match.attributes) { + bool found = false; + for (const auto &term : sums) { + bool exists = std::get<0>(term); + IdString key = std::get<1>(term); + const Const &value = std::get<2>(term); + auto it = cell->attributes.find(key); + if (it == cell->attributes.end()) { + if (exists) + continue; + found = true; + break; + } + if (it->second != value) + continue; + found = true; + break; + } + if (!found) { + std::stringstream ss; + bool exists = std::get<0>(sums.front()); + if (!exists) + ss << "!"; + IdString key = std::get<1>(sums.front()); + ss << key.str(); + const Const &value = std::get<2>(sums.front()); + if (exists) + ss << "="; + if (value != Const(1)) + ss << "\"" << value.decode_string() << "\""; + + log(" Rule for bram type %s (variant %d) rejected: requirement 'attribute %s ...' not met.\n", + log_id(bram.name), bram.variant, ss.str().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()) -- cgit v1.2.3 From 6b384861e4b1e02b24bf11d266cf11f461115cd8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 13:31:05 -0800 Subject: Oops --- passes/memory/memory_bram.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index a1353e56d..7ce5e80e1 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -333,12 +333,9 @@ struct rules_t for (int idx = 1; idx <= GetSize(tokens)-1; idx++) { size_t c1 = tokens[1][0] == '!' ? 1 : 0; size_t c2 = tokens[1].find("="); - if (c2 != std::string::npos) - c2--; - bool exists = (c1 == 0); IdString key = RTLIL::escape_id(tokens[1].substr(c1, c2)); - Const val = c2 != std::string::npos ? tokens[1].substr(c2) : RTLIL::Const(1); + Const val = c2 != std::string::npos ? tokens[1].substr(c2+1) : RTLIL::Const(1); data.attributes.back().emplace_back(exists, key, val); } -- cgit v1.2.3 From 4158ce4eda4853e89187824daa32fcb57f6dfa27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 13:56:45 -0800 Subject: More sloppiness, thanks @dh73 for spotting --- passes/memory/memory_bram.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 7ce5e80e1..29dc4ce07 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -331,11 +331,11 @@ struct rules_t if (GetSize(tokens) >= 2 && tokens[0] == "attribute") { data.attributes.emplace_back(); for (int idx = 1; idx <= GetSize(tokens)-1; idx++) { - size_t c1 = tokens[1][0] == '!' ? 1 : 0; - size_t c2 = tokens[1].find("="); + size_t c1 = tokens[idx][0] == '!' ? 1 : 0; + size_t c2 = tokens[idx].find("="); bool exists = (c1 == 0); - IdString key = RTLIL::escape_id(tokens[1].substr(c1, c2)); - Const val = c2 != std::string::npos ? tokens[1].substr(c2+1) : RTLIL::Const(1); + IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2)); + Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1); data.attributes.back().emplace_back(exists, key, val); } -- cgit v1.2.3 From 187e1c46e61dc910bf591625f7034b052ba928a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 14:48:53 -0800 Subject: Update doc --- passes/memory/memory_bram.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 29dc4ce07..7f551134a 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -1314,10 +1314,12 @@ 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("A match containing the command 'attribute' followed by a list of space\n"); + log("separated 'name[=string_value]' values requires that the memory contains any\n"); + log("one of the given attribute name and string values (where specified), or name\n"); + log("and integer 1 value (if no string_value given, since Verilog will interpret\n"); + log("'(* attr *)' as '(* attr=1 *)').\n"); + log("A name prefixed with '!' indicates that the attribute must not exist.\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"); -- cgit v1.2.3 From 33e6d0558500d14e6711f7fc4ded1ebdb296bcaa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 16 Dec 2019 17:06:30 -0800 Subject: Enforce non-existence --- passes/memory/memory_bram.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 7f551134a..e0970d192 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -841,6 +841,8 @@ grow_read_ports:; found = true; break; } + else if (!exists) + continue; if (it->second != value) continue; found = true; @@ -1165,6 +1167,8 @@ void handle_cell(Cell *cell, const rules_t &rules) found = true; break; } + else if (!exists) + continue; if (it->second != value) continue; found = true; -- cgit v1.2.3 From dccd7eb39f897f7fb04b038ee8ac11e676a8ea77 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 17 Dec 2019 00:25:08 -0800 Subject: Cleanup --- passes/memory/memory_bram.cc | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index e0970d192..24478f2ee 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -330,7 +330,7 @@ struct rules_t if (GetSize(tokens) >= 2 && tokens[0] == "attribute") { data.attributes.emplace_back(); - for (int idx = 1; idx <= GetSize(tokens)-1; idx++) { + for (int idx = 1; idx < GetSize(tokens); idx++) { size_t c1 = tokens[idx][0] == '!' ? 1 : 0; size_t c2 = tokens[idx].find("="); bool exists = (c1 == 0); @@ -854,12 +854,10 @@ grow_read_ports:; if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << key.str(); + ss << log_id(key); const Const &value = std::get<2>(sums.front()); - if (exists) - ss << "="; - if (value != Const(1)) - ss << "\"" << value.decode_string() << "\""; + if (exists && value != Const(1)) + ss << "=\"" << value.decode_string() << "\""; log(" Rule for bram type %s rejected: requirement 'attribute %s ...' not met.\n", log_id(match.name), ss.str().c_str()); @@ -1180,12 +1178,10 @@ void handle_cell(Cell *cell, const rules_t &rules) if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << key.str(); + ss << log_id(key); const Const &value = std::get<2>(sums.front()); - if (exists) - ss << "="; - if (value != Const(1)) - ss << "\"" << value.decode_string() << "\""; + if (exists && value != Const(1)) + ss << "=\"" << value.decode_string() << "\""; log(" Rule for bram type %s (variant %d) rejected: requirement 'attribute %s ...' not met.\n", log_id(bram.name), bram.variant, ss.str().c_str()); -- cgit v1.2.3 From 3671ecc7d0b3792c61ceee858435b3b75ad4739c Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Wed, 18 Dec 2019 12:30:30 +0100 Subject: use extra_args --- passes/cmds/scratchpad.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes') diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc index 805badc7e..7ec55b78e 100644 --- a/passes/cmds/scratchpad.cc +++ b/passes/cmds/scratchpad.cc @@ -122,9 +122,9 @@ struct ScratchpadPass : public Pass { log_error("Assertion failed: scratchpad entry '%s' is defined\n", identifier.c_str()); continue; } - log("Unrecognized argument: %s\n", args[argidx].c_str()); break; } + extra_args(args, argidx, design, false); } } ScratchpadPass; PRIVATE_NAMESPACE_END -- cgit v1.2.3 From a2352504031ee69efd0aac214fc947737303eb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= Date: Wed, 18 Dec 2019 13:42:26 +0100 Subject: xilinx: Add xilinx_dffopt pass (#1557) --- passes/equiv/equiv_opt.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'passes') diff --git a/passes/equiv/equiv_opt.cc b/passes/equiv/equiv_opt.cc index c7e6d71a6..7c6c2e685 100644 --- a/passes/equiv/equiv_opt.cc +++ b/passes/equiv/equiv_opt.cc @@ -44,6 +44,10 @@ struct EquivOptPass:public ScriptPass log(" expand the modules in this file before proving equivalence. this is\n"); log(" useful for handling architecture-specific primitives.\n"); log("\n"); + log(" -blacklist \n"); + log(" Do not match cells or signals that match the names in the file\n"); + log(" (passed to equiv_make).\n"); + log("\n"); log(" -assert\n"); log(" produce an error if the circuits are not equivalent.\n"); log("\n"); @@ -61,13 +65,14 @@ struct EquivOptPass:public ScriptPass log("\n"); } - std::string command, techmap_opts; + std::string command, techmap_opts, make_opts; bool assert, undef, multiclock, async2sync; void clear_flags() YS_OVERRIDE { command = ""; techmap_opts = ""; + make_opts = ""; assert = false; undef = false; multiclock = false; @@ -93,6 +98,10 @@ struct EquivOptPass:public ScriptPass techmap_opts += " -map " + args[++argidx]; continue; } + if (args[argidx] == "-blacklist" && argidx + 1 < args.size()) { + make_opts += " -blacklist " + args[++argidx]; + continue; + } if (args[argidx] == "-assert") { assert = true; continue; @@ -170,7 +179,12 @@ struct EquivOptPass:public ScriptPass run("clk2fflogic", "(only with -multiclock)"); if (async2sync || help_mode) run("async2sync", " (only with -async2sync)"); - run("equiv_make gold gate equiv"); + string opts; + if (help_mode) + opts = " -blacklist ..."; + else + opts = make_opts; + run("equiv_make" + opts + " gold gate equiv"); if (help_mode) run("equiv_induct [-undef] equiv"); else if (undef) -- cgit v1.2.3