From 0793f1b196df536975a044a4ce53025c81d00c7f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 26 Nov 2015 18:11:06 +0100 Subject: [PATCH] Added ice40_ffinit pass --- techlibs/ice40/Makefile.inc | 1 + techlibs/ice40/ice40_ffinit.cc | 142 +++++++++++++++++++++++++++++++++ techlibs/ice40/synth_ice40.cc | 2 + 3 files changed, 145 insertions(+) create mode 100644 techlibs/ice40/ice40_ffinit.cc diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 63d6086a7..83009d176 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -1,6 +1,7 @@ OBJS += techlibs/ice40/synth_ice40.o OBJS += techlibs/ice40/ice40_ffssr.o +OBJS += techlibs/ice40/ice40_ffinit.o OBJS += techlibs/ice40/ice40_opt.o GENFILES += techlibs/ice40/brams_init1.vh diff --git a/techlibs/ice40/ice40_ffinit.cc b/techlibs/ice40/ice40_ffinit.cc new file mode 100644 index 000000000..50400be80 --- /dev/null +++ b/techlibs/ice40/ice40_ffinit.cc @@ -0,0 +1,142 @@ +/* + * 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 + +struct Ice40FfinitPass : public Pass { + Ice40FfinitPass() : Pass("ice40_ffinit", "iCE40: handle FF init values") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" ice40_ffinit [options] [selection]\n"); + log("\n"); + log("Remove zero init values for FF output signals. Add inverters to implement\n"); + log("nonzero init values.\n"); + log("\n"); + } + virtual void execute(std::vector args, RTLIL::Design *design) + { + log_header("Executing ICE40_FFINIT pass (implement FF init values).\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()) + { + log("Handling FF init values in %s.\n", log_id(module)); + + SigMap sigmap(module); + pool init_wires; + dict initbits; + pool handled_initbits; + + for (auto wire : module->selected_wires()) + { + if (wire->attributes.count("\\init") == 0) + continue; + + SigSpec wirebits = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + init_wires.insert(wire); + + for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) + { + SigBit bit = wirebits[i]; + State val = initval[i]; + + if (val != State::S0 && val != State::S1) + continue; + + if (initbits.count(bit)) { + if (initbits.at(bit) != val) + log_error("Conflicting init values for signal %s.\n", log_signal(bit)); + continue; + } + + initbits[bit] = val; + } + } + + for (auto cell : module->selected_cells()) + { + if (!cell->type.in("\\SB_DFF", "\\SB_DFFE", "\\SB_DFFN", "\\SB_DFFNE")) + continue; + + SigBit sig_d = sigmap(cell->getPort("\\D")); + SigBit sig_q = sigmap(cell->getPort("\\Q")); + + if (!initbits.count(sig_q)) + continue; + + State val = initbits.at(sig_q); + handled_initbits.insert(sig_q); + + log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type), + log_signal(sig_q), val != State::S0 ? '1' : '0'); + + if (val == State::S0) + continue; + + Wire *new_sig_d = module->addWire(NEW_ID); + Wire *new_sig_q = module->addWire(NEW_ID); + + module->addNotGate(NEW_ID, sig_d, new_sig_d); + module->addNotGate(NEW_ID, new_sig_q, sig_q); + + cell->setPort("\\D", new_sig_d); + cell->setPort("\\Q", new_sig_q); + } + + for (auto wire : init_wires) + { + if (wire->attributes.count("\\init") == 0) + continue; + + SigSpec wirebits = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); + bool remove_attribute = true; + + for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { + if (handled_initbits.count(wirebits[i])) + wirebits[i] = State::Sx; + else + remove_attribute = false; + } + + if (remove_attribute) + wire->attributes.erase("\\init"); + } + } + } +} Ice40FfinitPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 788835f1d..75cab7bda 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -104,6 +104,7 @@ struct SynthIce40Pass : public Pass { log(" techmap -map +/ice40/cells_map.v\n"); log(" opt_const -mux_undef\n"); log(" simplemap\n"); + log(" ice40_ffinit\n"); log(" ice40_ffssr\n"); log(" ice40_opt -full\n"); log("\n"); @@ -236,6 +237,7 @@ struct SynthIce40Pass : public Pass { Pass::call(design, "techmap -map +/ice40/cells_map.v"); Pass::call(design, "opt_const -mux_undef"); Pass::call(design, "simplemap"); + Pass::call(design, "ice40_ffinit"); Pass::call(design, "ice40_ffssr"); Pass::call(design, "ice40_opt -full"); } -- 2.30.2