From d69395ca084266eb60832d89665238c85b289479 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 2 Feb 2016 17:19:01 +0100 Subject: [PATCH] Added dffsr2dff --- passes/techmap/Makefile.inc | 1 + passes/techmap/dffsr2dff.cc | 168 ++++++++++++++++++++++++++++++++++ techlibs/ice40/synth_ice40.cc | 2 + 3 files changed, 171 insertions(+) create mode 100644 passes/techmap/dffsr2dff.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index fa9388686..8112516c6 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -22,6 +22,7 @@ OBJS += passes/techmap/aigmap.o OBJS += passes/techmap/tribuf.o OBJS += passes/techmap/lut2mux.o OBJS += passes/techmap/nlutmap.o +OBJS += passes/techmap/dffsr2dff.o endif GENFILES += passes/techmap/techmap.inc diff --git a/passes/techmap/dffsr2dff.cc b/passes/techmap/dffsr2dff.cc new file mode 100644 index 000000000..a9c90a9e6 --- /dev/null +++ b/passes/techmap/dffsr2dff.cc @@ -0,0 +1,168 @@ +/* + * 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/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void dffsr2dff_worker(SigMap &sigmap, Module *module, Cell *cell) +{ + if (cell->type == "$dffsr") + { + int width = cell->getParam("\\WIDTH").as_int(); + bool setpol = cell->getParam("\\SET_POLARITY").as_bool(); + bool clrpol = cell->getParam("\\CLR_POLARITY").as_bool(); + + SigBit setunused = setpol ? State::S0 : State::S1; + SigBit clrunused = clrpol ? State::S0 : State::S1; + + SigSpec setsig = sigmap(cell->getPort("\\SET")); + SigSpec clrsig = sigmap(cell->getPort("\\CLR")); + + Const reset_val; + SigSpec setctrl, clrctrl; + + for (int i = 0; i < width; i++) + { + SigBit setbit = setsig[i], clrbit = clrsig[i]; + + if (setbit == setunused) { + clrctrl.append(clrbit); + reset_val.bits.push_back(State::S0); + continue; + } + + if (clrbit == clrunused) { + setctrl.append(setbit); + reset_val.bits.push_back(State::S1); + continue; + } + + return; + } + + setctrl.sort_and_unify(); + clrctrl.sort_and_unify(); + + if (GetSize(setctrl) > 1 || GetSize(clrctrl) > 1) + return; + + if (GetSize(setctrl) == 0 && GetSize(clrctrl) == 0) + return; + + if (GetSize(setctrl) == 1 && GetSize(clrctrl) == 1) { + if (setpol != clrpol) + return; + if (setctrl != clrctrl) + return; + } + + log("Converting %s cell %s.%s to $adff.\n", log_id(cell->type), log_id(module), log_id(cell)); + + if (GetSize(setctrl) == 1) { + cell->setPort("\\ARST", setctrl); + cell->setParam("\\ARST_POLARITY", setpol); + } else { + cell->setPort("\\ARST", clrctrl); + cell->setParam("\\ARST_POLARITY", clrpol); + } + + cell->type = "$adff"; + cell->unsetPort("\\SET"); + cell->unsetPort("\\CLR"); + cell->setParam("\\ARST_VALUE", reset_val); + cell->unsetParam("\\SET_POLARITY"); + cell->unsetParam("\\CLR_POLARITY"); + + return; + } + + if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_", + "$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_")) + { + char clkpol = cell->type.c_str()[8]; + char setpol = cell->type.c_str()[9]; + char clrpol = cell->type.c_str()[10]; + + SigBit setbit = sigmap(cell->getPort("\\S")); + SigBit clrbit = sigmap(cell->getPort("\\R")); + + SigBit setunused = setpol == 'P' ? State::S0 : State::S1; + SigBit clrunused = clrpol == 'P' ? State::S0 : State::S1; + + IdString oldtype = cell->type; + + if (setbit == setunused) { + cell->type = stringf("$_DFF_%c%c0_", clkpol, clrpol); + cell->unsetPort("\\S"); + goto converted_gate; + } + + if (clrbit == clrunused) { + cell->type = stringf("$_DFF_%c%c1_", clkpol, setpol); + cell->setPort("\\R", cell->getPort("\\S")); + cell->unsetPort("\\S"); + goto converted_gate; + } + + return; + + converted_gate: + log("Converting %s cell %s.%s to %s.\n", log_id(oldtype), log_id(module), log_id(cell), log_id(cell->type)); + return; + } +} + +struct Dffsr2dffPass : public Pass { + Dffsr2dffPass() : Pass("dffsr2dff", "convert DFFSR cells to simpler FF cell types") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" dffsr2dff [options] [selection]\n"); + log("\n"); + log("This pass converts DFFSR cells ($dffsr, $_DFFSR_???_) to simpler FF cell types\n"); + log("when one or both of the set/reset inputs is unused.\n"); + log("\n"); + } + virtual void execute(std::vector args, RTLIL::Design *design) + { + log_header("Executing DFFSR2DFF pass (mapping DFFSR cells to simpler FFs).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-v") { + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) { + SigMap sigmap(module); + for (auto cell : module->selected_cells()) + dffsr2dff_worker(sigmap, module, cell); + } + } +} Dffsr2dffPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 36aca4072..92d53f4ab 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -103,6 +103,7 @@ struct SynthIce40Pass : public Pass { log(" ice40_opt\n"); log("\n"); log(" map_ffs:\n"); + log(" dffsr2dff\n"); log(" dff2dffe -direct-match $_DFF_*\n"); log(" techmap -map +/ice40/cells_map.v\n"); log(" opt_const -mux_undef\n"); @@ -243,6 +244,7 @@ struct SynthIce40Pass : public Pass { if (check_label(active, run_from, run_to, "map_ffs")) { + Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe -direct-match $_DFF_*"); Pass::call(design, "techmap -map +/ice40/cells_map.v"); Pass::call(design, "opt_const -mux_undef");