mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/master' into xaig_arrival
This commit is contained in:
commit
d672b1ddec
1
Brewfile
1
Brewfile
|
@ -6,3 +6,4 @@ brew "git"
|
||||||
brew "graphviz"
|
brew "graphviz"
|
||||||
brew "pkg-config"
|
brew "pkg-config"
|
||||||
brew "python3"
|
brew "python3"
|
||||||
|
brew "tcl-tk"
|
||||||
|
|
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at>
|
Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -91,8 +91,10 @@ PLUGIN_LDFLAGS += -undefined dynamic_lookup
|
||||||
ifneq ($(shell which brew),)
|
ifneq ($(shell which brew),)
|
||||||
BREW_PREFIX := $(shell brew --prefix)/opt
|
BREW_PREFIX := $(shell brew --prefix)/opt
|
||||||
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
|
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
|
||||||
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost
|
CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost
|
||||||
LDFLAGS += -L$(BREW_PREFIX)/boost/lib
|
LDFLAGS += -L$(BREW_PREFIX)/boost/lib
|
||||||
|
endif
|
||||||
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
||||||
LDFLAGS += -L$(BREW_PREFIX)/readline/lib
|
LDFLAGS += -L$(BREW_PREFIX)/readline/lib
|
||||||
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
|
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
```
|
```
|
||||||
yosys -- Yosys Open SYnthesis Suite
|
yosys -- Yosys Open SYnthesis Suite
|
||||||
|
|
||||||
Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at>
|
Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -69,11 +69,14 @@ prerequisites for building yosys:
|
||||||
graphviz xdot pkg-config python3 libboost-system-dev \
|
graphviz xdot pkg-config python3 libboost-system-dev \
|
||||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
||||||
|
|
||||||
Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
|
Similarily, on Mac OS X Homebrew can be used to install dependencies:
|
||||||
|
|
||||||
$ brew tap Homebrew/bundle && brew bundle
|
$ brew tap Homebrew/bundle && brew bundle
|
||||||
|
|
||||||
|
or MacPorts:
|
||||||
|
|
||||||
$ sudo port install bison flex readline gawk libffi \
|
$ sudo port install bison flex readline gawk libffi \
|
||||||
git graphviz pkgconfig python36 boost zlib
|
git graphviz pkgconfig python36 boost zlib tcl
|
||||||
|
|
||||||
On FreeBSD use the following command to install all prerequisites:
|
On FreeBSD use the following command to install all prerequisites:
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
reg->str = stringf("%s[%d]", node->str.c_str(), i);
|
reg->str = stringf("%s[%d]", node->str.c_str(), i);
|
||||||
reg->is_reg = true;
|
reg->is_reg = true;
|
||||||
reg->is_signed = node->is_signed;
|
reg->is_signed = node->is_signed;
|
||||||
|
for (auto &it : node->attributes)
|
||||||
|
if (it.first != ID(mem2reg))
|
||||||
|
reg->attributes.emplace(it.first, it.second->clone());
|
||||||
|
reg->filename = node->filename;
|
||||||
|
reg->linenum = node->linenum;
|
||||||
children.push_back(reg);
|
children.push_back(reg);
|
||||||
while (reg->simplify(true, false, false, 1, -1, false, false)) { }
|
while (reg->simplify(true, false, false, 1, -1, false, false)) { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ void yosys_banner()
|
||||||
log(" | |\n");
|
log(" | |\n");
|
||||||
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
|
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
|
||||||
log(" | |\n");
|
log(" | |\n");
|
||||||
log(" | Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at> |\n");
|
log(" | Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at> |\n");
|
||||||
log(" | |\n");
|
log(" | |\n");
|
||||||
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
|
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
|
||||||
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
|
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
|
||||||
|
|
|
@ -532,10 +532,10 @@ struct EquivMakePass : public Pass {
|
||||||
log_cmd_error("Equiv module %s already exists.\n", args[argidx+2].c_str());
|
log_cmd_error("Equiv module %s already exists.\n", args[argidx+2].c_str());
|
||||||
|
|
||||||
if (worker.gold_mod->has_memories() || worker.gold_mod->has_processes())
|
if (worker.gold_mod->has_memories() || worker.gold_mod->has_processes())
|
||||||
log_cmd_error("Gold module contains memories or procresses. Run 'memory' or 'proc' respectively.\n");
|
log_cmd_error("Gold module contains memories or processes. Run 'memory' or 'proc' respectively.\n");
|
||||||
|
|
||||||
if (worker.gate_mod->has_memories() || worker.gate_mod->has_processes())
|
if (worker.gate_mod->has_memories() || worker.gate_mod->has_processes())
|
||||||
log_cmd_error("Gate module contains memories or procresses. Run 'memory' or 'proc' respectively.\n");
|
log_cmd_error("Gate module contains memories or processes. Run 'memory' or 'proc' respectively.\n");
|
||||||
|
|
||||||
worker.read_blacklists();
|
worker.read_blacklists();
|
||||||
worker.read_encfiles();
|
worker.read_encfiles();
|
||||||
|
|
|
@ -369,7 +369,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
if (design->selected(module, cell) && cell->type[0] == '$') {
|
if (design->selected(module, cell) && cell->type[0] == '$') {
|
||||||
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) &&
|
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) &&
|
||||||
cell->getPort(ID::A).size() == 1 && cell->getPort(ID::Y).size() == 1)
|
GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1)
|
||||||
invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A));
|
invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A));
|
||||||
if (cell->type.in(ID($mux), ID($_MUX_)) &&
|
if (cell->type.in(ID($mux), ID($_MUX_)) &&
|
||||||
cell->getPort(ID::A) == SigSpec(State::S1) && cell->getPort(ID::B) == SigSpec(State::S0))
|
cell->getPort(ID::A) == SigSpec(State::S1) && cell->getPort(ID::B) == SigSpec(State::S0))
|
||||||
|
@ -740,12 +740,34 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
|
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
|
||||||
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx);
|
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx);
|
||||||
else
|
else
|
||||||
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort(ID::Y).size()));
|
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::SigSpec(RTLIL::State::Sx, GetSize(cell->getPort(ID::Y))));
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID::Y).size() == 1 &&
|
if (cell->type.in(ID($shiftx), ID($shift))) {
|
||||||
|
SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
|
int width;
|
||||||
|
bool trim_x = cell->type == ID($shiftx) || !keepdc;
|
||||||
|
bool trim_0 = cell->type == ID($shift);
|
||||||
|
for (width = GetSize(sig_a); width > 1; width--) {
|
||||||
|
if ((trim_x && sig_a[width-1] == State::Sx) ||
|
||||||
|
(trim_0 && sig_a[width-1] == State::S0))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width < GetSize(sig_a)) {
|
||||||
|
cover_list("opt.opt_expr.trim", "$shiftx", "$shift", cell->type.str());
|
||||||
|
sig_a.remove(width, GetSize(sig_a)-width);
|
||||||
|
cell->setPort(ID::A, sig_a);
|
||||||
|
cell->setParam(ID(A_WIDTH), width);
|
||||||
|
did_something = true;
|
||||||
|
goto next_cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && GetSize(cell->getPort(ID::Y)) == 1 &&
|
||||||
invert_map.count(assign_map(cell->getPort(ID::A))) != 0) {
|
invert_map.count(assign_map(cell->getPort(ID::A))) != 0) {
|
||||||
cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
|
cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
|
||||||
replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A))));
|
replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A))));
|
||||||
|
@ -1142,7 +1164,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (mux_undef && cell->type.in(ID($mux), ID($pmux))) {
|
if (mux_undef && cell->type.in(ID($mux), ID($pmux))) {
|
||||||
RTLIL::SigSpec new_a, new_b, new_s;
|
RTLIL::SigSpec new_a, new_b, new_s;
|
||||||
int width = cell->getPort(ID::A).size();
|
int width = GetSize(cell->getPort(ID::A));
|
||||||
if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) ||
|
if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) ||
|
||||||
cell->getPort(ID(S)).is_fully_undef()) {
|
cell->getPort(ID(S)).is_fully_undef()) {
|
||||||
cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str());
|
cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str());
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
||||||
OBJS += passes/pmgen/test_pmgen.o
|
OBJS += passes/pmgen/test_pmgen.o
|
||||||
passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h
|
passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h
|
||||||
$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
|
$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
|
||||||
|
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
OBJS += techlibs/anlogic/synth_anlogic.o
|
OBJS += techlibs/anlogic/synth_anlogic.o
|
||||||
OBJS += techlibs/anlogic/anlogic_eqn.o
|
OBJS += techlibs/anlogic/anlogic_eqn.o
|
||||||
OBJS += techlibs/anlogic/anlogic_determine_init.o
|
OBJS += techlibs/anlogic/anlogic_fixcarry.o
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
|
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
|
||||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
|
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* yosys -- Yosys Open SYnthesis Suite
|
|
||||||
*
|
|
||||||
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
|
|
||||||
*
|
|
||||||
* 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 AnlogicDetermineInitPass : public Pass {
|
|
||||||
AnlogicDetermineInitPass() : Pass("anlogic_determine_init", "Anlogic: Determine the init value of cells") { }
|
|
||||||
void help() YS_OVERRIDE
|
|
||||||
{
|
|
||||||
log("\n");
|
|
||||||
log(" anlogic_determine_init [selection]\n");
|
|
||||||
log("\n");
|
|
||||||
log("Determine the init value of cells that doesn't allow unknown init value.\n");
|
|
||||||
log("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
Const determine_init(Const init)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < GetSize(init); i++) {
|
|
||||||
if (init[i] != State::S0 && init[i] != State::S1)
|
|
||||||
init[i] = State::S0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return init;
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
|
||||||
{
|
|
||||||
log_header(design, "Executing ANLOGIC_DETERMINE_INIT pass (determine init value for cells).\n");
|
|
||||||
|
|
||||||
extra_args(args, args.size(), design);
|
|
||||||
|
|
||||||
int cnt = 0;
|
|
||||||
for (auto module : design->selected_modules())
|
|
||||||
{
|
|
||||||
for (auto cell : module->selected_cells())
|
|
||||||
{
|
|
||||||
if (cell->type == "\\EG_LOGIC_DRAM16X4")
|
|
||||||
{
|
|
||||||
cell->setParam("\\INIT_D0", determine_init(cell->getParam("\\INIT_D0")));
|
|
||||||
cell->setParam("\\INIT_D1", determine_init(cell->getParam("\\INIT_D1")));
|
|
||||||
cell->setParam("\\INIT_D2", determine_init(cell->getParam("\\INIT_D2")));
|
|
||||||
cell->setParam("\\INIT_D3", determine_init(cell->getParam("\\INIT_D3")));
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log_header(design, "Updated %d cells with determined init value.\n", cnt);
|
|
||||||
}
|
|
||||||
} AnlogicDetermineInitPass;
|
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_END
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.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
|
||||||
|
|
||||||
|
static SigBit get_bit_or_zero(const SigSpec &sig)
|
||||||
|
{
|
||||||
|
if (GetSize(sig) == 0)
|
||||||
|
return State::S0;
|
||||||
|
return sig[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fix_carry_chain(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> ci_bits;
|
||||||
|
dict<SigBit, SigBit> mapping_bits;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\AL_MAP_ADDER") {
|
||||||
|
if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0) {
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigSpec o = cell->getPort("\\o");
|
||||||
|
if (GetSize(o) == 2) {
|
||||||
|
SigBit bit_o = o[0];
|
||||||
|
ci_bits.insert(bit_ci);
|
||||||
|
mapping_bits[bit_ci] = bit_o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<Cell*> adders_to_fix_cells;
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\AL_MAP_ADDER") {
|
||||||
|
if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
if (!ci_bits.count(canonical_bit))
|
||||||
|
continue;
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
adders_to_fix_cells.push_back(cell);
|
||||||
|
log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto cell : adders_to_fix_cells)
|
||||||
|
{
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
auto bit = mapping_bits.at(canonical_bit);
|
||||||
|
log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
SigBit dummy_bit = module->addWire(NEW_ID);
|
||||||
|
SigSpec bits;
|
||||||
|
bits.append(dummy_bit);
|
||||||
|
bits.append(new_bit);
|
||||||
|
c->setParam("\\ALUTYPE", Const("ADD_CARRY"));
|
||||||
|
c->setPort("\\a", bit);
|
||||||
|
c->setPort("\\b", State::S0);
|
||||||
|
c->setPort("\\c", State::S0);
|
||||||
|
c->setPort("\\o", bits);
|
||||||
|
|
||||||
|
cell->setPort("\\c", new_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AnlogicCarryFixPass : public Pass {
|
||||||
|
AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" anlogic_fixcarry [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Add Anlogic adders to fix carry chain if needed.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
Module *module = design->top_module();
|
||||||
|
|
||||||
|
if (module == nullptr)
|
||||||
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
|
fix_carry_chain(module);
|
||||||
|
}
|
||||||
|
} AnlogicCarryFixPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -31,7 +31,10 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
output [Y_WIDTH-1:0] X, Y;
|
output [Y_WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
input CI, BI;
|
input CI, BI;
|
||||||
output CO;
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
|
wire CIx;
|
||||||
|
wire [Y_WIDTH-1:0] COx;
|
||||||
|
|
||||||
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||||
|
|
||||||
|
@ -41,15 +44,16 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
|
||||||
wire [Y_WIDTH-1:0] AA = A_buf;
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
wire [Y_WIDTH+1:0] COx;
|
wire [Y_WIDTH-1:0] C = { COx, CIx };
|
||||||
wire [Y_WIDTH+2:0] C = {COx, CI};
|
|
||||||
|
|
||||||
wire dummy;
|
wire dummy;
|
||||||
AL_MAP_ADDER #(
|
AL_MAP_ADDER #(
|
||||||
.ALUTYPE("ADD_CARRY"))
|
.ALUTYPE("ADD_CARRY"))
|
||||||
adder_cin (
|
adder_cin (
|
||||||
.a(C[0]),
|
.a(CI),
|
||||||
.o({COx[0], dummy})
|
.b(1'b0),
|
||||||
|
.c(1'b0),
|
||||||
|
.o({CIx, dummy})
|
||||||
);
|
);
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
|
@ -59,18 +63,22 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
) adder_i (
|
) adder_i (
|
||||||
.a(AA[i]),
|
.a(AA[i]),
|
||||||
.b(BB[i]),
|
.b(BB[i]),
|
||||||
.c(C[i+1]),
|
.c(C[i]),
|
||||||
.o({COx[i+1],Y[i]})
|
.o({COx[i],Y[i]})
|
||||||
);
|
);
|
||||||
end: slice
|
|
||||||
|
wire cout;
|
||||||
|
AL_MAP_ADDER #(
|
||||||
|
.ALUTYPE("ADD"))
|
||||||
|
adder_cout (
|
||||||
|
.a(1'b0),
|
||||||
|
.b(1'b0),
|
||||||
|
.c(COx[i]),
|
||||||
|
.o({cout, CO[i]})
|
||||||
|
);
|
||||||
|
end: slice
|
||||||
endgenerate
|
endgenerate
|
||||||
/* End implementation */
|
|
||||||
AL_MAP_ADDER #(
|
/* End implementation */
|
||||||
.ALUTYPE("ADD"))
|
assign X = AA ^ BB;
|
||||||
adder_cout (
|
endmodule
|
||||||
.c(C[Y_WIDTH+1]),
|
|
||||||
.o(COx[Y_WIDTH+1])
|
|
||||||
);
|
|
||||||
assign CO = COx[Y_WIDTH+1];
|
|
||||||
assign X = AA ^ BB;
|
|
||||||
endmodule
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ struct SynthAnlogicPass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("memory_bram -rules +/anlogic/drams.txt");
|
run("memory_bram -rules +/anlogic/drams.txt");
|
||||||
run("techmap -map +/anlogic/drams_map.v");
|
run("techmap -map +/anlogic/drams_map.v");
|
||||||
run("anlogic_determine_init");
|
run("setundef -zero -params t:EG_LOGIC_DRAM16X4");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("fine"))
|
if (check_label("fine"))
|
||||||
|
@ -186,6 +186,11 @@ struct SynthAnlogicPass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("techmap -map +/anlogic/cells_map.v");
|
run("techmap -map +/anlogic/cells_map.v");
|
||||||
run("clean");
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_anlogic"))
|
||||||
|
{
|
||||||
|
run("anlogic_fixcarry");
|
||||||
run("anlogic_eqn");
|
run("anlogic_eqn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,12 @@ endmodule
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
(* abc_box_id=1, lib_whitebox *)
|
(* abc_box_id=1, lib_whitebox *)
|
||||||
module CCU2C(
|
module CCU2C(
|
||||||
(* abc_carry *) input CIN,
|
(* abc_carry *)
|
||||||
|
input CIN,
|
||||||
input A0, B0, C0, D0, A1, B1, C1, D1,
|
input A0, B0, C0, D0, A1, B1, C1, D1,
|
||||||
output S0, S1,
|
output S0, S1,
|
||||||
(* abc_carry *) output COUT
|
(* abc_carry *)
|
||||||
|
output COUT
|
||||||
);
|
);
|
||||||
parameter [15:0] INIT0 = 16'h0000;
|
parameter [15:0] INIT0 = 16'h0000;
|
||||||
parameter [15:0] INIT1 = 16'h0000;
|
parameter [15:0] INIT1 = 16'h0000;
|
||||||
|
@ -113,7 +115,8 @@ module TRELLIS_DPR16X4 (
|
||||||
input WRE,
|
input WRE,
|
||||||
input WCK,
|
input WCK,
|
||||||
input [3:0] RAD,
|
input [3:0] RAD,
|
||||||
/* (* abc_arrival=<TODO> *) */ output [3:0] DO
|
/* (* abc_arrival=<TODO> *) */
|
||||||
|
output [3:0] DO
|
||||||
);
|
);
|
||||||
parameter WCKMUX = "WCK";
|
parameter WCKMUX = "WCK";
|
||||||
parameter WREMUX = "WRE";
|
parameter WREMUX = "WRE";
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
OBJS += techlibs/efinix/synth_efinix.o
|
||||||
|
OBJS += techlibs/efinix/efinix_gbuf.o
|
||||||
|
OBJS += techlibs/efinix/efinix_fixcarry.o
|
||||||
|
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams_map.v))
|
||||||
|
$(eval $(call add_share_file,share/efinix,techlibs/efinix/bram.txt))
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(* techmap_celltype = "$alu" *)
|
||||||
|
module _80_efinix_alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
parameter A_SIGNED = 0;
|
||||||
|
parameter B_SIGNED = 0;
|
||||||
|
parameter A_WIDTH = 1;
|
||||||
|
parameter B_WIDTH = 1;
|
||||||
|
parameter Y_WIDTH = 1;
|
||||||
|
|
||||||
|
input [A_WIDTH-1:0] A;
|
||||||
|
input [B_WIDTH-1:0] B;
|
||||||
|
output [Y_WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
|
input CI, BI;
|
||||||
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
|
wire CIx;
|
||||||
|
wire [Y_WIDTH-1:0] COx;
|
||||||
|
|
||||||
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
||||||
|
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
||||||
|
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
|
wire [Y_WIDTH-1:0] C = { COx, CIx };
|
||||||
|
|
||||||
|
EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
|
||||||
|
adder_cin (
|
||||||
|
.I0(CI),
|
||||||
|
.I1(1'b1),
|
||||||
|
.CI(1'b0),
|
||||||
|
.CO(CIx)
|
||||||
|
);
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
|
||||||
|
EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
|
||||||
|
adder_i (
|
||||||
|
.I0(AA[i]),
|
||||||
|
.I1(BB[i]),
|
||||||
|
.CI(C[i]),
|
||||||
|
.O(Y[i]),
|
||||||
|
.CO(COx[i])
|
||||||
|
);
|
||||||
|
EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1))
|
||||||
|
adder_cout (
|
||||||
|
.I0(1'b0),
|
||||||
|
.I1(1'b0),
|
||||||
|
.CI(COx[i]),
|
||||||
|
.O(CO[i])
|
||||||
|
);
|
||||||
|
end: slice
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
/* End implementation */
|
||||||
|
assign X = AA ^ BB;
|
||||||
|
endmodule
|
|
@ -0,0 +1,32 @@
|
||||||
|
bram $__EFINIX_5K
|
||||||
|
init 1
|
||||||
|
|
||||||
|
abits 8 @a8d16
|
||||||
|
dbits 16 @a8d16
|
||||||
|
abits 9 @a9d8
|
||||||
|
dbits 8 @a9d8
|
||||||
|
abits 10 @a10d4
|
||||||
|
dbits 4 @a10d4
|
||||||
|
abits 11 @a11d2
|
||||||
|
dbits 2 @a11d2
|
||||||
|
abits 12 @a12d1
|
||||||
|
dbits 1 @a12d1
|
||||||
|
abits 8 @a8d20
|
||||||
|
dbits 20 @a8d20
|
||||||
|
abits 9 @a9d10
|
||||||
|
dbits 10 @a9d10
|
||||||
|
|
||||||
|
groups 2
|
||||||
|
ports 1 1
|
||||||
|
wrmode 1 0
|
||||||
|
enable 1 1
|
||||||
|
transp 0 2
|
||||||
|
clocks 2 3
|
||||||
|
clkpol 2 3
|
||||||
|
endbram
|
||||||
|
|
||||||
|
match $__EFINIX_5K
|
||||||
|
min bits 256
|
||||||
|
min efficiency 5
|
||||||
|
shuffle_enable B
|
||||||
|
endmatch
|
|
@ -0,0 +1,65 @@
|
||||||
|
module \$__EFINIX_5K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
|
||||||
|
parameter CFG_ABITS = 8;
|
||||||
|
parameter CFG_DBITS = 20;
|
||||||
|
parameter CFG_ENABLE_A = 1;
|
||||||
|
|
||||||
|
parameter CLKPOL2 = 1;
|
||||||
|
parameter CLKPOL3 = 1;
|
||||||
|
parameter [5119:0] INIT = 5119'bx;
|
||||||
|
parameter TRANSP2 = 0;
|
||||||
|
|
||||||
|
input CLK2;
|
||||||
|
input CLK3;
|
||||||
|
|
||||||
|
input [CFG_ABITS-1:0] A1ADDR;
|
||||||
|
input [CFG_DBITS-1:0] A1DATA;
|
||||||
|
input [CFG_ENABLE_A-1:0] A1EN;
|
||||||
|
|
||||||
|
input [CFG_ABITS-1:0] B1ADDR;
|
||||||
|
output [CFG_DBITS-1:0] B1DATA;
|
||||||
|
input B1EN;
|
||||||
|
|
||||||
|
localparam WRITEMODE_A = TRANSP2 ? "WRITE_FIRST" : "READ_FIRST";
|
||||||
|
|
||||||
|
EFX_RAM_5K #(
|
||||||
|
.READ_WIDTH(CFG_DBITS),
|
||||||
|
.WRITE_WIDTH(CFG_DBITS),
|
||||||
|
.OUTPUT_REG(1'b0),
|
||||||
|
.RCLK_POLARITY(1'b1),
|
||||||
|
.RE_POLARITY(1'b1),
|
||||||
|
.WCLK_POLARITY(1'b1),
|
||||||
|
.WE_POLARITY(1'b1),
|
||||||
|
.WCLKE_POLARITY(1'b1),
|
||||||
|
.WRITE_MODE(WRITEMODE_A),
|
||||||
|
.INIT_0(INIT[ 0*256 +: 256]),
|
||||||
|
.INIT_1(INIT[ 1*256 +: 256]),
|
||||||
|
.INIT_2(INIT[ 2*256 +: 256]),
|
||||||
|
.INIT_3(INIT[ 3*256 +: 256]),
|
||||||
|
.INIT_4(INIT[ 4*256 +: 256]),
|
||||||
|
.INIT_5(INIT[ 5*256 +: 256]),
|
||||||
|
.INIT_6(INIT[ 6*256 +: 256]),
|
||||||
|
.INIT_7(INIT[ 7*256 +: 256]),
|
||||||
|
.INIT_8(INIT[ 8*256 +: 256]),
|
||||||
|
.INIT_9(INIT[ 9*256 +: 256]),
|
||||||
|
.INIT_A(INIT[10*256 +: 256]),
|
||||||
|
.INIT_B(INIT[11*256 +: 256]),
|
||||||
|
.INIT_C(INIT[12*256 +: 256]),
|
||||||
|
.INIT_D(INIT[13*256 +: 256]),
|
||||||
|
.INIT_E(INIT[14*256 +: 256]),
|
||||||
|
.INIT_F(INIT[15*256 +: 256]),
|
||||||
|
.INIT_10(INIT[16*256 +: 256]),
|
||||||
|
.INIT_11(INIT[17*256 +: 256]),
|
||||||
|
.INIT_12(INIT[18*256 +: 256]),
|
||||||
|
.INIT_13(INIT[19*256 +: 256])
|
||||||
|
) _TECHMAP_REPLACE_ (
|
||||||
|
.WDATA(A1DATA),
|
||||||
|
.WADDR(A1ADDR),
|
||||||
|
.WE(A1EN),
|
||||||
|
.WCLK(CLK2),
|
||||||
|
.WCLKE(1'b1),
|
||||||
|
.RDATA(B1DATA),
|
||||||
|
.RADDR(B1ADDR),
|
||||||
|
.RE(B1EN),
|
||||||
|
.RCLK(CLK3)
|
||||||
|
);
|
||||||
|
endmodule
|
|
@ -0,0 +1,45 @@
|
||||||
|
module \$_DFF_N_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_P_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_NN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
module \$_DFFE_NP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_PN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
module \$_DFFE_PP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_NN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
`ifndef NO_LUT
|
||||||
|
module \$lut (A, Y);
|
||||||
|
parameter WIDTH = 0;
|
||||||
|
parameter LUT = 0;
|
||||||
|
|
||||||
|
input [WIDTH-1:0] A;
|
||||||
|
output Y;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (WIDTH == 1) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 2) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 3) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 4) begin
|
||||||
|
EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
|
||||||
|
end else begin
|
||||||
|
wire _TECHMAP_FAIL_ = 1;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
`endif
|
|
@ -0,0 +1,107 @@
|
||||||
|
module EFX_LUT4(
|
||||||
|
output O,
|
||||||
|
input I0,
|
||||||
|
input I1,
|
||||||
|
input I2,
|
||||||
|
input I3
|
||||||
|
);
|
||||||
|
parameter LUTMASK = 16'h0000;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_ADD(
|
||||||
|
output O,
|
||||||
|
output CO,
|
||||||
|
input I0,
|
||||||
|
input I1,
|
||||||
|
input CI
|
||||||
|
);
|
||||||
|
parameter I0_POLARITY = 1;
|
||||||
|
parameter I1_POLARITY = 1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_FF(
|
||||||
|
output Q,
|
||||||
|
input D,
|
||||||
|
input CE,
|
||||||
|
input CLK,
|
||||||
|
input SR
|
||||||
|
);
|
||||||
|
parameter CLK_POLARITY = 1;
|
||||||
|
parameter CE_POLARITY = 1;
|
||||||
|
parameter SR_POLARITY = 1;
|
||||||
|
parameter SR_SYNC = 0;
|
||||||
|
parameter SR_VALUE = 0;
|
||||||
|
parameter SR_SYNC_PRIORITY = 0;
|
||||||
|
parameter D_POLARITY = 1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_GBUFCE(
|
||||||
|
input CE,
|
||||||
|
input I,
|
||||||
|
output O
|
||||||
|
);
|
||||||
|
parameter CE_POLARITY = 1'b1;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module EFX_RAM_5K(
|
||||||
|
input [WRITE_WIDTH-1:0] WDATA,
|
||||||
|
input [WRITE_ADDR_WIDTH-1:0] WADDR,
|
||||||
|
input WE,
|
||||||
|
input WCLK,
|
||||||
|
input WCLKE,
|
||||||
|
output [READ_WIDTH-1:0] RDATA,
|
||||||
|
input [READ_ADDR_WIDTH-1:0] RADDR,
|
||||||
|
input RE,
|
||||||
|
input RCLK
|
||||||
|
);
|
||||||
|
parameter READ_WIDTH = 20;
|
||||||
|
parameter WRITE_WIDTH = 20;
|
||||||
|
parameter OUTPUT_REG = 1'b0;
|
||||||
|
parameter RCLK_POLARITY = 1'b1;
|
||||||
|
parameter RE_POLARITY = 1'b1;
|
||||||
|
parameter WCLK_POLARITY = 1'b1;
|
||||||
|
parameter WE_POLARITY = 1'b1;
|
||||||
|
parameter WCLKE_POLARITY = 1'b1;
|
||||||
|
parameter WRITE_MODE = "READ_FIRST";
|
||||||
|
parameter INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
|
||||||
|
localparam READ_ADDR_WIDTH =
|
||||||
|
(READ_WIDTH == 16) ? 8 : // 256x16
|
||||||
|
(READ_WIDTH == 8) ? 9 : // 512x8
|
||||||
|
(READ_WIDTH == 4) ? 10 : // 1024x4
|
||||||
|
(READ_WIDTH == 2) ? 11 : // 2048x2
|
||||||
|
(READ_WIDTH == 1) ? 12 : // 4096x1
|
||||||
|
(READ_WIDTH == 20) ? 8 : // 256x20
|
||||||
|
(READ_WIDTH == 10) ? 9 : // 512x10
|
||||||
|
(READ_WIDTH == 5) ? 10 : -1; // 1024x5
|
||||||
|
|
||||||
|
localparam WRITE_ADDR_WIDTH =
|
||||||
|
(WRITE_WIDTH == 16) ? 8 : // 256x16
|
||||||
|
(WRITE_WIDTH == 8) ? 9 : // 512x8
|
||||||
|
(WRITE_WIDTH == 4) ? 10 : // 1024x4
|
||||||
|
(WRITE_WIDTH == 2) ? 11 : // 2048x2
|
||||||
|
(WRITE_WIDTH == 1) ? 12 : // 4096x1
|
||||||
|
(WRITE_WIDTH == 20) ? 8 : // 256x20
|
||||||
|
(WRITE_WIDTH == 10) ? 9 : // 512x10
|
||||||
|
(WRITE_WIDTH == 5) ? 10 : -1; // 1024x5
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.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
|
||||||
|
|
||||||
|
static SigBit get_bit_or_zero(const SigSpec &sig)
|
||||||
|
{
|
||||||
|
if (GetSize(sig) == 0)
|
||||||
|
return State::S0;
|
||||||
|
return sig[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fix_carry_chain(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> ci_bits;
|
||||||
|
dict<SigBit, SigBit> mapping_bits;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\EFX_ADD") {
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0) {
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
|
||||||
|
SigBit bit_o = sigmap(cell->getPort("\\O"));
|
||||||
|
ci_bits.insert(bit_ci);
|
||||||
|
mapping_bits[bit_ci] = bit_o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Cell*> adders_to_fix_cells;
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\EFX_ADD") {
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
|
||||||
|
SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0"));
|
||||||
|
SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
if (!ci_bits.count(canonical_bit))
|
||||||
|
continue;
|
||||||
|
if (bit_i0 == State::S0 && bit_i1== State::S0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
adders_to_fix_cells.push_back(cell);
|
||||||
|
log("Found %s cell named %s with invalid CI signal.\n", log_id(cell->type), log_id(cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto cell : adders_to_fix_cells)
|
||||||
|
{
|
||||||
|
SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI"));
|
||||||
|
SigBit canonical_bit = sigmap(bit_ci);
|
||||||
|
auto bit = mapping_bits.at(canonical_bit);
|
||||||
|
log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\EFX_ADD");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
c->setParam("\\I0_POLARITY", State::S1);
|
||||||
|
c->setParam("\\I1_POLARITY", State::S1);
|
||||||
|
c->setPort("\\I0", bit);
|
||||||
|
c->setPort("\\I1", State::S1);
|
||||||
|
c->setPort("\\CI", State::S0);
|
||||||
|
c->setPort("\\CO", new_bit);
|
||||||
|
|
||||||
|
cell->setPort("\\CI", new_bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EfinixCarryFixPass : public Pass {
|
||||||
|
EfinixCarryFixPass() : Pass("efinix_fixcarry", "Efinix: fix carry chain") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" efinix_fixcarry [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Add Efinix adders to fix carry chain if needed.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing efinix_fixcarry pass (fix invalid carry chain).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
Module *module = design->top_module();
|
||||||
|
|
||||||
|
if (module == nullptr)
|
||||||
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
|
fix_carry_chain(module);
|
||||||
|
}
|
||||||
|
} EfinixCarryFixPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
static void handle_gbufs(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> clk_bits;
|
||||||
|
dict<SigBit, SigBit> rewrite_bits;
|
||||||
|
vector<pair<Cell*, SigBit>> pad_bits;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\EFX_FF") {
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\CLK")))
|
||||||
|
clk_bits.insert(bit);
|
||||||
|
}
|
||||||
|
if (cell->type == "\\EFX_RAM_5K") {
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\RCLK")))
|
||||||
|
clk_bits.insert(bit);
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\WCLK")))
|
||||||
|
clk_bits.insert(bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto wire : vector<Wire*>(module->wires()))
|
||||||
|
{
|
||||||
|
if (!wire->port_input)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int index = 0; index < GetSize(wire); index++)
|
||||||
|
{
|
||||||
|
SigBit bit(wire, index);
|
||||||
|
SigBit canonical_bit = sigmap(bit);
|
||||||
|
|
||||||
|
if (!clk_bits.count(canonical_bit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\EFX_GBUFCE");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
c->setParam("\\CE_POLARITY", State::S1);
|
||||||
|
c->setPort("\\O", new_bit);
|
||||||
|
c->setPort("\\CE", State::S1);
|
||||||
|
pad_bits.push_back(make_pair(c, bit));
|
||||||
|
rewrite_bits[canonical_bit] = new_bit;
|
||||||
|
|
||||||
|
log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rewrite_function = [&](SigSpec &s) {
|
||||||
|
for (auto &bit : s) {
|
||||||
|
SigBit canonical_bit = sigmap(bit);
|
||||||
|
if (rewrite_bits.count(canonical_bit))
|
||||||
|
bit = rewrite_bits.at(canonical_bit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module->rewrite_sigspecs(rewrite_function);
|
||||||
|
|
||||||
|
for (auto &it : pad_bits)
|
||||||
|
it.first->setPort("\\I", it.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EfinixGbufPass : public Pass {
|
||||||
|
EfinixGbufPass() : Pass("efinix_gbuf", "Efinix: insert global clock buffers") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" efinix_gbuf [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Add Efinix global clock buffers to top module as needed.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing efinix_gbuf pass (insert global clock buffers).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
Module *module = design->top_module();
|
||||||
|
|
||||||
|
if (module == nullptr)
|
||||||
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
|
handle_gbufs(module);
|
||||||
|
}
|
||||||
|
} EfinixGbufPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
|
||||||
|
* Copyright (C) 2019 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* 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/celltypes.h"
|
||||||
|
#include "kernel/rtlil.h"
|
||||||
|
#include "kernel/log.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct SynthEfinixPass : public ScriptPass
|
||||||
|
{
|
||||||
|
SynthEfinixPass() : ScriptPass("synth_efinix", "synthesis for Efinix FPGAs") { }
|
||||||
|
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" synth_efinix [options]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This command runs synthesis for Efinix FPGAs.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -top <module>\n");
|
||||||
|
log(" use the specified module as top module\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -edif <file>\n");
|
||||||
|
log(" write the design to the specified EDIF file. writing of an output file\n");
|
||||||
|
log(" is omitted if this parameter is not specified.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -json <file>\n");
|
||||||
|
log(" write the design to the specified JSON file. writing of an output file\n");
|
||||||
|
log(" is omitted if this parameter is not specified.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -run <from_label>:<to_label>\n");
|
||||||
|
log(" only run the commands between the labels (see below). an empty\n");
|
||||||
|
log(" from label is synonymous to 'begin', and empty to label is\n");
|
||||||
|
log(" synonymous to the end of the command list.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -noflatten\n");
|
||||||
|
log(" do not flatten design before synthesis\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -retime\n");
|
||||||
|
log(" run 'abc' with -dff option\n");
|
||||||
|
log("\n");
|
||||||
|
log("\n");
|
||||||
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
help_script();
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
string top_opt, edif_file, json_file;
|
||||||
|
bool flatten, retime;
|
||||||
|
|
||||||
|
void clear_flags() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
top_opt = "-auto-top";
|
||||||
|
edif_file = "";
|
||||||
|
json_file = "";
|
||||||
|
flatten = true;
|
||||||
|
retime = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
string run_from, run_to;
|
||||||
|
clear_flags();
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
if (args[argidx] == "-top" && argidx+1 < args.size()) {
|
||||||
|
top_opt = "-top " + args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-edif" && argidx+1 < args.size()) {
|
||||||
|
edif_file = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-json" && argidx+1 < args.size()) {
|
||||||
|
json_file = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-run" && argidx+1 < args.size()) {
|
||||||
|
size_t pos = args[argidx+1].find(':');
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
break;
|
||||||
|
run_from = args[++argidx].substr(0, pos);
|
||||||
|
run_to = args[argidx].substr(pos+1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noflatten") {
|
||||||
|
flatten = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-retime") {
|
||||||
|
retime = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
if (!design->full_selection())
|
||||||
|
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||||
|
|
||||||
|
log_header(design, "Executing SYNTH_EFINIX pass.\n");
|
||||||
|
log_push();
|
||||||
|
|
||||||
|
run_script(design, run_from, run_to);
|
||||||
|
|
||||||
|
log_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void script() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
if (check_label("begin"))
|
||||||
|
{
|
||||||
|
run("read_verilog -lib +/efinix/cells_sim.v");
|
||||||
|
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flatten && check_label("flatten", "(unless -noflatten)"))
|
||||||
|
{
|
||||||
|
run("proc");
|
||||||
|
run("flatten");
|
||||||
|
run("tribuf -logic");
|
||||||
|
run("deminout");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("coarse"))
|
||||||
|
{
|
||||||
|
run("synth -run coarse");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_bram", "(skip if -nobram)"))
|
||||||
|
{
|
||||||
|
run("memory_bram -rules +/efinix/bram.txt");
|
||||||
|
run("techmap -map +/efinix/brams_map.v");
|
||||||
|
run("setundef -zero -params t:EFX_RAM_5K");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("fine"))
|
||||||
|
{
|
||||||
|
run("opt -fast -mux_undef -undriven -fine");
|
||||||
|
run("memory_map");
|
||||||
|
run("opt -undriven -fine");
|
||||||
|
run("techmap -map +/techmap.v -map +/efinix/arith_map.v");
|
||||||
|
if (retime || help_mode)
|
||||||
|
run("abc -dff", "(only if -retime)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_ffs"))
|
||||||
|
{
|
||||||
|
run("dffsr2dff");
|
||||||
|
run("techmap -D NO_LUT -map +/efinix/cells_map.v");
|
||||||
|
run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
|
||||||
|
run("opt_expr -mux_undef");
|
||||||
|
run("simplemap");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_luts"))
|
||||||
|
{
|
||||||
|
run("abc -lut 4");
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_cells"))
|
||||||
|
{
|
||||||
|
run("techmap -map +/efinix/cells_map.v");
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_gbuf"))
|
||||||
|
{
|
||||||
|
run("efinix_gbuf");
|
||||||
|
run("efinix_fixcarry");
|
||||||
|
run("clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("check"))
|
||||||
|
{
|
||||||
|
run("hierarchy -check");
|
||||||
|
run("stat");
|
||||||
|
run("check -noinit");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("edif"))
|
||||||
|
{
|
||||||
|
if (!edif_file.empty() || help_mode)
|
||||||
|
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("json"))
|
||||||
|
{
|
||||||
|
if (!json_file.empty() || help_mode)
|
||||||
|
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} SynthEfinixPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -143,11 +143,13 @@ endmodule
|
||||||
|
|
||||||
(* abc_box_id = 1, lib_whitebox *)
|
(* abc_box_id = 1, lib_whitebox *)
|
||||||
module \$__ICE40_FULL_ADDER (
|
module \$__ICE40_FULL_ADDER (
|
||||||
(* abc_carry *) output CO,
|
(* abc_carry *)
|
||||||
|
output CO,
|
||||||
output O,
|
output O,
|
||||||
input A,
|
input A,
|
||||||
input B,
|
input B,
|
||||||
(* abc_carry *) input CI
|
(* abc_carry *)
|
||||||
|
input CI
|
||||||
);
|
);
|
||||||
SB_CARRY carry (
|
SB_CARRY carry (
|
||||||
.I0(A),
|
.I0(A),
|
||||||
|
|
|
@ -175,9 +175,11 @@ endmodule
|
||||||
|
|
||||||
(* abc_box_id = 4, lib_whitebox *)
|
(* abc_box_id = 4, lib_whitebox *)
|
||||||
module CARRY4(
|
module CARRY4(
|
||||||
(* abc_carry *) output [3:0] CO,
|
(* abc_carry *)
|
||||||
|
output [3:0] CO,
|
||||||
output [3:0] O,
|
output [3:0] O,
|
||||||
(* abc_carry *) input CI,
|
(* abc_carry *)
|
||||||
|
input CI,
|
||||||
input CYINIT,
|
input CYINIT,
|
||||||
input [3:0] DI, S
|
input [3:0] DI, S
|
||||||
);
|
);
|
||||||
|
@ -299,7 +301,8 @@ endmodule
|
||||||
|
|
||||||
module RAM32X1D (
|
module RAM32X1D (
|
||||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
|
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
|
||||||
(* abc_arrival=1153 *) output DPO, SPO,
|
(* abc_arrival=1153 *)
|
||||||
|
output DPO, SPO,
|
||||||
input D,
|
input D,
|
||||||
input WCLK,
|
input WCLK,
|
||||||
input WE,
|
input WE,
|
||||||
|
@ -319,7 +322,8 @@ endmodule
|
||||||
|
|
||||||
module RAM64X1D (
|
module RAM64X1D (
|
||||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
|
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
|
||||||
(* abc_arrival=1153 *) output DPO, SPO,
|
(* abc_arrival=1153 *)
|
||||||
|
output DPO, SPO,
|
||||||
input D,
|
input D,
|
||||||
input WCLK,
|
input WCLK,
|
||||||
input WE,
|
input WE,
|
||||||
|
@ -339,7 +343,8 @@ endmodule
|
||||||
|
|
||||||
module RAM128X1D (
|
module RAM128X1D (
|
||||||
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
|
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
|
||||||
(* abc_arrival=1153 *) output DPO, SPO,
|
(* abc_arrival=1153 *)
|
||||||
|
output DPO, SPO,
|
||||||
input D,
|
input D,
|
||||||
input WCLK,
|
input WCLK,
|
||||||
input WE,
|
input WE,
|
||||||
|
|
|
@ -221,3 +221,73 @@ check
|
||||||
equiv_opt opt_expr -fine
|
equiv_opt opt_expr -fine
|
||||||
design -load postopt
|
design -load postopt
|
||||||
select -assert-count 1 t:$alu r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
|
select -assert-count 1 t:$alu r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shiftx_1bit(input [2:0] a, input [1:0] b, output y);
|
||||||
|
\$shiftx #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) shiftx (.A({1'bx,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shiftx r:A_WIDTH=3 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shiftx_3bit(input [9:0] a, input [3:0] b, output [2:0] y);
|
||||||
|
\$shiftx #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shiftx (.A({4'bxx00,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shiftx r:A_WIDTH=12 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shift_1bit(input [2:0] a, input [1:0] b, output y);
|
||||||
|
\$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) shift (.A({1'b0,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shift r:A_WIDTH=3 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shift_3bit(input [9:0] a, input [3:0] b, output [2:0] y);
|
||||||
|
\$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shift (.A({4'b0x0x,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shift r:A_WIDTH=10 %i
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -icells <<EOT
|
||||||
|
module opt_expr_shift_3bit_keepdc(input [9:0] a, input [3:0] b, output [2:0] y);
|
||||||
|
\$shift #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(14), .B_WIDTH(4), .Y_WIDTH(3)) shift (.A({4'b0x0x,a}), .B(b), .Y(y));
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
check
|
||||||
|
|
||||||
|
equiv_opt opt_expr -keepdc
|
||||||
|
design -load postopt
|
||||||
|
select -assert-count 1 t:$shift r:A_WIDTH=13 %i
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top;
|
||||||
|
parameter DATADEPTH=2;
|
||||||
|
parameter DATAWIDTH=1;
|
||||||
|
(* keep, nomem2reg *) reg [DATAWIDTH-1:0] data1 [DATADEPTH-1:0];
|
||||||
|
(* keep, mem2reg *) reg [DATAWIDTH-1:0] data2 [DATADEPTH-1:0];
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
proc
|
||||||
|
cd top
|
||||||
|
select -assert-count 1 m:data1 a:src=<<EOT:4 %i
|
||||||
|
select -assert-count 2 w:data2[*] a:src=<<EOT:5 %i
|
||||||
|
select -assert-none a:mem2reg
|
Loading…
Reference in New Issue