From 18ad56ef416437f60d166919c1e439a234953e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Mon, 27 Jul 2020 15:24:57 +0200 Subject: [PATCH] Add dffunmap pass. To be used with backends that cannot deal with fancy FF types (like blif or smt). --- passes/techmap/Makefile.inc | 1 + passes/techmap/dffunmap.cc | 107 ++++++++++++++++++++++++++++++++++++ tests/techmap/dffunmap.ys | 100 +++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 passes/techmap/dffunmap.cc create mode 100644 tests/techmap/dffunmap.ys diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index e3b3d8dea..5a4d84f94 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -43,6 +43,7 @@ OBJS += passes/techmap/attrmap.o OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dfflegalize.o OBJS += passes/techmap/dff2dffs.o +OBJS += passes/techmap/dffunmap.o OBJS += passes/techmap/flowmap.o OBJS += passes/techmap/extractinv.o endif diff --git a/passes/techmap/dffunmap.cc b/passes/techmap/dffunmap.cc new file mode 100644 index 000000000..fb107ff75 --- /dev/null +++ b/passes/techmap/dffunmap.cc @@ -0,0 +1,107 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2020 Marcelina Koƛcielnicka + * + * 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" +#include "kernel/ff.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct DffunmapPass : public Pass { + DffunmapPass() : Pass("dffunmap", "unmap clock enable and synchronous reset from FFs") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" dffunmap [options] [selection]\n"); + log("\n"); + log("This pass transforms FF types with clock enable and/or synchronous reset into\n"); + log("their base type (with neither clock enable nor sync reset) by emulating the clock\n"); + log("enable and synchronous reset with multiplexers on the cell input.\n"); + log("\n"); + log(" -ce-only\n"); + log(" unmap only clock enables, leave synchronous resets alone.\n"); + log("\n"); + log(" -srst-only\n"); + log(" unmap only synchronous resets, leave clock enables alone.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing DFFUNMAP pass (unmap clock enable and synchronous reset from FFs).\n"); + + bool ce_only = false; + bool srst_only = false; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-ce-only") { + ce_only = true; + continue; + } + if (args[argidx] == "-srst-only") { + srst_only = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (ce_only && srst_only) + log_cmd_error("Options -ce-only and -srst-only are mutually exclusive!\n"); + + for (auto mod : design->selected_modules()) + { + SigMap sigmap(mod); + FfInitVals initvals(&sigmap, mod); + + for (auto cell : mod->selected_cells()) + { + if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + continue; + + FfData ff(&initvals, cell); + IdString name = cell->name; + + if (!ff.has_clk) + continue; + + if (ce_only) { + if (!ff.has_en) + continue; + ff.unmap_ce(mod); + } else if (srst_only) { + if (!ff.has_srst) + continue; + ff.unmap_srst(mod); + } else { + if (!ff.has_en && !ff.has_srst) + continue; + ff.unmap_ce_srst(mod); + } + + mod->remove(cell); + ff.emit(mod, name); + } + } + } +} DffunmapPass; + +PRIVATE_NAMESPACE_END diff --git a/tests/techmap/dffunmap.ys b/tests/techmap/dffunmap.ys new file mode 100644 index 000000000..b813078ee --- /dev/null +++ b/tests/techmap/dffunmap.ys @@ -0,0 +1,100 @@ +read_verilog -icells << EOT + +module top(...); + +input C, R, E, S; +input [1:0] D; +output [20:0] Q; + +$dff #(.CLK_POLARITY(1'b0), .WIDTH(2)) ff0 (.CLK(C), .D(D), .Q(Q[1:0])); +$dffe #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b0), .WIDTH(2)) ff1 (.CLK(C), .EN(E), .D(D), .Q(Q[3:2])); +$sdff #(.CLK_POLARITY(1'b0), .WIDTH(2), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2)) ff2 (.CLK(C), .SRST(R), .D(D), .Q(Q[5:4])); +$sdffe #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2)) ff3 (.CLK(C), .EN(E), .SRST(R), .D(D), .Q(Q[7:6])); +$sdffce #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2)) ff4 (.CLK(C), .EN(E), .SRST(R), .D(D), .Q(Q[9:8])); +$adff #(.CLK_POLARITY(1'b0), .WIDTH(2), .ARST_POLARITY(1'b0), .ARST_VALUE(2'h2)) ff5 (.CLK(C), .ARST(R), .D(D), .Q(Q[11:10])); +$adffe #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2)) ff6 (.CLK(C), .EN(E), .ARST(R), .D(D), .Q(Q[13:12])); +$dffsr #(.CLK_POLARITY(1'b0), .WIDTH(2), .CLR_POLARITY(1'b0), .SET_POLARITY(1'b1)) ff7 (.CLK(C), .CLR({R, S}), .SET({S, R}), .D(D), .Q(Q[15:14])); +$dffsre #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0)) ff8 (.CLK(C), .EN(E), .CLR({R, R}), .SET({S, S}), .D(D), .Q(Q[17:16])); + +endmodule + +EOT + +design -save orig + +equiv_opt -assert -async2sync dffunmap +design -load postopt +select -assert-none t:$sdff t:$dffe t:$adffe t:$sdffe t:$sdffce t:$dffsre +select -assert-count 5 t:$dff +select -assert-count 2 t:$adff +select -assert-count 2 t:$dffsr + +design -load orig + +equiv_opt -assert -async2sync dffunmap -ce-only +design -load postopt +select -assert-none t:$dffe t:$adffe t:$sdffe t:$sdffce t:$dffsre +select -assert-count 3 t:$dff +select -assert-count 2 t:$sdff +select -assert-count 2 t:$adff +select -assert-count 2 t:$dffsr + +design -load orig + +equiv_opt -assert -async2sync dffunmap -srst-only +design -load postopt +select -assert-none t:$sdff t:$sdffe t:$sdffce +select -assert-count 3 t:$dff +select -assert-count 2 t:$dffe +select -assert-count 1 t:$adff +select -assert-count 1 t:$adffe +select -assert-count 1 t:$dffsr +select -assert-count 1 t:$dffsre + +design -load orig +simplemap + +equiv_opt -assert -async2sync dffunmap +design -load postopt +select -assert-none t:$_SDFF* t:$_DFFE_* t:$_DFFSRE_* +select -assert-count 10 t:$_DFF_N_ +select -assert-count 1 t:$_DFF_NP0_ +select -assert-count 1 t:$_DFF_NN0_ +select -assert-count 1 t:$_DFF_NP1_ +select -assert-count 1 t:$_DFF_NN1_ +select -assert-count 2 t:$_DFFSR_NPN_ +select -assert-count 2 t:$_DFFSR_NNP_ + +design -load orig +simplemap + +equiv_opt -assert -async2sync dffunmap -ce-only +design -load postopt +select -assert-none t:$_SDFFE_* t:$_SDFFCE_* t:$_DFFE_* t:$_DFFSRE_* +select -assert-count 6 t:$_DFF_N_ +select -assert-count 1 t:$_SDFF_NP0_ +select -assert-count 1 t:$_SDFF_NN0_ +select -assert-count 1 t:$_SDFF_NP1_ +select -assert-count 1 t:$_SDFF_NN1_ +select -assert-count 1 t:$_DFF_NP0_ +select -assert-count 1 t:$_DFF_NN0_ +select -assert-count 1 t:$_DFF_NP1_ +select -assert-count 1 t:$_DFF_NN1_ +select -assert-count 2 t:$_DFFSR_NPN_ +select -assert-count 2 t:$_DFFSR_NNP_ + +design -load orig +simplemap + +equiv_opt -assert -async2sync dffunmap -srst-only +design -load postopt +select -assert-none t:$sdff t:$sdffe t:$sdffce +select -assert-count 6 t:$_DFF_N_ +select -assert-count 2 t:$_DFFE_NP_ +select -assert-count 2 t:$_DFFE_NN_ +select -assert-count 1 t:$_DFF_NN0_ +select -assert-count 1 t:$_DFF_NN1_ +select -assert-count 1 t:$_DFFE_NP0P_ +select -assert-count 1 t:$_DFFE_NP1P_ +select -assert-count 2 t:$_DFFSR_NPN_ +select -assert-count 2 t:$_DFFSRE_NNPP_