Merge remote-tracking branch 'origin/xaig_dff' into eddie/exp
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index aa8f941..52e7ac7 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(); } } @@ -788,7 +797,6 @@ match_properties["dcells"] = ((mem_width + bram.dbits - 1) / bram.dbits); match_properties["acells"] = ((mem_size + (1 << bram.abits) - 1) / (1 << bram.abits)); match_properties["cells"] = match_properties["dcells"] * match_properties["acells"] * match_properties["dups"]; - log(" Updated properties: dups=%d waste=%d efficiency=%d\n", match_properties["dups"], match_properties["waste"], match_properties["efficiency"]); @@ -806,13 +814,28 @@ if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", it.first.c_str(), log_id(match.name)); - if (match_properties[it.first] <= it.second) - continue; log(" Rule for bram type %s rejected: requirement 'max %s %d' not met.\n", log_id(match.name), it.first.c_str(), it.second); 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 +1123,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()) @@ -1242,6 +1283,9 @@ log("A match containing the command 'shuffle_enable A' will re-organize\n"); log("the data bits to accommodate the enable pattern of port A.\n"); log("\n"); + log("A match containing the command 'attribute' will bypass min bits/efficiency\n"); + log("to select the type of memory.\n"); + log("\n"); } void execute(vector<string> args, Design *design) YS_OVERRIDE {
diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 145d2eb..a4d9d42 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc
@@ -45,3 +45,9 @@ OBJS += passes/pmgen/xilinx_srl.o passes/pmgen/xilinx_srl.o: passes/pmgen/xilinx_srl_pm.h $(eval $(call add_extra_objs,passes/pmgen/xilinx_srl_pm.h)) + +# -------------------------------------- + +OBJS += passes/pmgen/xilinx_dff.o +passes/pmgen/xilinx_dff.o: passes/pmgen/xilinx_dff_pm.h +$(eval $(call add_extra_objs,passes/pmgen/xilinx_dff_pm.h))
diff --git a/passes/pmgen/xilinx_dff.cc b/passes/pmgen/xilinx_dff.cc new file mode 100644 index 0000000..bf0c735 --- /dev/null +++ b/passes/pmgen/xilinx_dff.cc
@@ -0,0 +1,62 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * 2019 Eddie Hung <eddie@fpgeh.com> + * + * 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/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#include "passes/pmgen/xilinx_dff_pm.h" + +struct XilinxDffPass : public Pass { + XilinxDffPass() : Pass("xilinx_dff", "Xilinx: TODO") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" xilinx_dff [options] [selection]\n"); + log("\n"); + log("TODO\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing XILINX_DFF pass (TODO).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) { + xilinx_dff_pm pm(module, module->selected_cells()); + pm.run_xilinx_dff(); + } + } +} XilinxDffPass; + +PRIVATE_NAMESPACE_END
diff --git a/passes/pmgen/xilinx_dff.pmg b/passes/pmgen/xilinx_dff.pmg new file mode 100644 index 0000000..f5637d4 --- /dev/null +++ b/passes/pmgen/xilinx_dff.pmg
@@ -0,0 +1,26 @@ +pattern xilinx_dff + +match fd + select fd->type.in(\FDRE) + select port(fd, \R).is_fully_zero() + select port(fd, \CE).is_fully_ones() +endmatch + +match lut + select lut->type.in(\LUT2) + index <SigSpec> port(lut, \O) === port(fd, \D) +endmatch + +code + if (lut->type == \LUT2) { + if (param(lut, \INIT) == Const::from_string("0100")) { + fd->setPort(\D, port(lut, \I0)); + fd->setPort(\R, port(lut, \I1)); + } + else if (param(lut, \INIT) == Const::from_string("0010")) { + fd->setPort(\R, port(lut, \I0)); + fd->setPort(\D, port(lut, \I1)); + } + } + else log_abort(); +endcode
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 5bc5538..239937f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc
@@ -561,6 +561,7 @@ else techmap_args += " -map " + ff_map_file; run("techmap " + techmap_args); + run("xilinx_dff"); } if (check_label("finalize")) {
diff --git a/techlibs/xilinx/xc7_xcu_brams.txt b/techlibs/xilinx/xc7_xcu_brams.txt index f116111..7d3d997 100644 --- a/techlibs/xilinx/xc7_xcu_brams.txt +++ b/techlibs/xilinx/xc7_xcu_brams.txt
@@ -81,10 +81,18 @@ endmatch match $__XILINX_RAMB18_SDP - min bits 4096 + min bits 1024 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 @@ -97,7 +105,7 @@ endmatch match $__XILINX_RAMB18_TDP - min bits 4096 + min bits 1024 min efficiency 5 shuffle_enable B make_transp