mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/master' into mwk/xilinx_bufgmap
This commit is contained in:
commit
6872805a3e
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"
|
||||||
|
|
|
@ -14,6 +14,10 @@ Yosys 0.9 .. Yosys 0.9-dev
|
||||||
- Added "synth -abc9" (experimental)
|
- Added "synth -abc9" (experimental)
|
||||||
- Added "script -scriptwire
|
- Added "script -scriptwire
|
||||||
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable)
|
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable)
|
||||||
|
- Renamed labels/options in synth_ice40 (e.g. dram -> map_lutram; -nodram -> -nolutram)
|
||||||
|
- Renamed labels/options in synth_ecp5 (e.g. dram -> map_lutram; -nodram -> -nolutram)
|
||||||
|
- Renamed labels in synth_intel (e.g. bram -> map_bram)
|
||||||
|
- Renamed labels/options in synth_xilinx (e.g. dram -> map_lutram; -nodram -> -nolutram)
|
||||||
- Added automatic gzip decompression for frontends
|
- Added automatic gzip decompression for frontends
|
||||||
- Added $_NMUX_ cell type
|
- Added $_NMUX_ cell type
|
||||||
- Added automatic gzip compression (based on filename extension) for backends
|
- Added automatic gzip compression (based on filename extension) for backends
|
||||||
|
@ -24,6 +28,10 @@ Yosys 0.9 .. Yosys 0.9-dev
|
||||||
- Added "synth_xilinx -ise" (experimental)
|
- Added "synth_xilinx -ise" (experimental)
|
||||||
- Added "synth_xilinx -iopad"
|
- Added "synth_xilinx -iopad"
|
||||||
- "synth_xilinx" now automatically inserts clock buffers (add -noclkbuf to disable)
|
- "synth_xilinx" now automatically inserts clock buffers (add -noclkbuf to disable)
|
||||||
|
- Improvements in pmgen: subpattern and recursive matches
|
||||||
|
- Added "opt_share" pass, run as part of "opt -full"
|
||||||
|
- Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
|
||||||
|
- Removed "ice40_unlut"
|
||||||
|
|
||||||
Yosys 0.8 .. Yosys 0.8-dev
|
Yosys 0.8 .. Yosys 0.8-dev
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
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
|
||||||
|
|
11
Makefile
11
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)
|
||||||
|
@ -487,6 +489,11 @@ define add_include_file
|
||||||
$(eval $(call add_share_file,$(dir share/include/$(1)),$(1)))
|
$(eval $(call add_share_file,$(dir share/include/$(1)),$(1)))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define add_extra_objs
|
||||||
|
EXTRA_OBJS += $(1)
|
||||||
|
.SECONDARY: $(1)
|
||||||
|
endef
|
||||||
|
|
||||||
ifeq ($(PRETTY), 1)
|
ifeq ($(PRETTY), 1)
|
||||||
P_STATUS = 0
|
P_STATUS = 0
|
||||||
P_OFFSET = 0
|
P_OFFSET = 0
|
||||||
|
@ -682,10 +689,12 @@ endif
|
||||||
|
|
||||||
test: $(TARGETS) $(EXTRA_TARGETS)
|
test: $(TARGETS) $(EXTRA_TARGETS)
|
||||||
+cd tests/simple && bash run-test.sh $(SEEDOPT)
|
+cd tests/simple && bash run-test.sh $(SEEDOPT)
|
||||||
|
+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/hana && bash run-test.sh $(SEEDOPT)
|
+cd tests/hana && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/asicworld && bash run-test.sh $(SEEDOPT)
|
+cd tests/asicworld && bash run-test.sh $(SEEDOPT)
|
||||||
# +cd tests/realmath && bash run-test.sh $(SEEDOPT)
|
# +cd tests/realmath && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/share && bash run-test.sh $(SEEDOPT)
|
+cd tests/share && bash run-test.sh $(SEEDOPT)
|
||||||
|
+cd tests/opt_share && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/fsm && bash run-test.sh $(SEEDOPT)
|
+cd tests/fsm && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/techmap && bash run-test.sh
|
+cd tests/techmap && bash run-test.sh
|
||||||
+cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT)
|
+cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT)
|
||||||
|
@ -693,10 +702,10 @@ test: $(TARGETS) $(EXTRA_TARGETS)
|
||||||
+cd tests/various && bash run-test.sh
|
+cd tests/various && bash run-test.sh
|
||||||
+cd tests/sat && bash run-test.sh
|
+cd tests/sat && bash run-test.sh
|
||||||
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
|
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
|
||||||
|
+cd tests/proc && bash run-test.sh
|
||||||
+cd tests/opt && bash run-test.sh
|
+cd tests/opt && bash run-test.sh
|
||||||
+cd tests/aiger && bash run-test.sh $(ABCOPT)
|
+cd tests/aiger && bash run-test.sh $(ABCOPT)
|
||||||
+cd tests/arch && bash run-test.sh
|
+cd tests/arch && bash run-test.sh
|
||||||
+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT)
|
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " Passed \"make test\"."
|
@echo " Passed \"make test\"."
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
26
README.md
26
README.md
|
@ -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:
|
||||||
|
|
||||||
|
@ -419,6 +422,23 @@ Verilog Attributes and non-standard features
|
||||||
blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this
|
blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this
|
||||||
functionality. (By default specify .. endspecify blocks are ignored.)
|
functionality. (By default specify .. endspecify blocks are ignored.)
|
||||||
|
|
||||||
|
- The module attribute ``abc_box_id`` specifies a positive integer linking a
|
||||||
|
blackbox or whitebox definition to a corresponding entry in a `abc9`
|
||||||
|
box-file.
|
||||||
|
|
||||||
|
- The port attribute ``abc_scc_break`` indicates a module input port that will
|
||||||
|
be treated as a primary output during `abc9` techmapping. Doing so eliminates
|
||||||
|
the possibility of a strongly-connected component (i.e. a combinatorial loop)
|
||||||
|
existing. Typically, this is specified for sequential inputs on otherwise
|
||||||
|
combinatorial boxes -- for example, applying ``abc_scc_break`` onto the `D`
|
||||||
|
port of a LUTRAM cell prevents `abc9` from interpreting any `Q` -> `D` paths
|
||||||
|
as a combinatorial loop.
|
||||||
|
|
||||||
|
- The port attribute ``abc_carry`` marks the carry-in (if an input port) and
|
||||||
|
carry-out (if output port) ports of a box. This information is necessary for
|
||||||
|
`abc9` to preserve the integrity of carry-chains. Specifying this attribute
|
||||||
|
onto a bus port will affect only its most significant bit.
|
||||||
|
|
||||||
|
|
||||||
Non-standard or SystemVerilog features for formal verification
|
Non-standard or SystemVerilog features for formal verification
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
|
@ -312,7 +312,7 @@ struct XAigerWriter
|
||||||
#if 0
|
#if 0
|
||||||
toposort.analyze_loops = true;
|
toposort.analyze_loops = true;
|
||||||
#endif
|
#endif
|
||||||
bool no_loops = toposort.sort();
|
bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
|
||||||
#if 0
|
#if 0
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (auto &it : toposort.loops) {
|
for (auto &it : toposort.loops) {
|
||||||
|
@ -326,7 +326,6 @@ struct XAigerWriter
|
||||||
#endif
|
#endif
|
||||||
log_assert(no_loops);
|
log_assert(no_loops);
|
||||||
|
|
||||||
pool<IdString> seen_boxes;
|
|
||||||
for (auto cell_name : toposort.sorted) {
|
for (auto cell_name : toposort.sorted) {
|
||||||
RTLIL::Cell *cell = module->cell(cell_name);
|
RTLIL::Cell *cell = module->cell(cell_name);
|
||||||
log_assert(cell);
|
log_assert(cell);
|
||||||
|
@ -335,47 +334,6 @@ struct XAigerWriter
|
||||||
if (!box_module || !box_module->attributes.count("\\abc_box_id"))
|
if (!box_module || !box_module->attributes.count("\\abc_box_id"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (seen_boxes.insert(cell->type).second) {
|
|
||||||
auto it = box_module->attributes.find("\\abc_carry");
|
|
||||||
if (it != box_module->attributes.end()) {
|
|
||||||
RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr;
|
|
||||||
auto carry_in_out = it->second.decode_string();
|
|
||||||
auto pos = carry_in_out.find(',');
|
|
||||||
if (pos == std::string::npos)
|
|
||||||
log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type));
|
|
||||||
auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos));
|
|
||||||
carry_in = box_module->wire(carry_in_name);
|
|
||||||
if (!carry_in || !carry_in->port_input)
|
|
||||||
log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str());
|
|
||||||
|
|
||||||
auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1));
|
|
||||||
carry_out = box_module->wire(carry_out_name);
|
|
||||||
if (!carry_out || !carry_out->port_output)
|
|
||||||
log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str());
|
|
||||||
|
|
||||||
auto &ports = box_module->ports;
|
|
||||||
for (auto jt = ports.begin(); jt != ports.end(); ) {
|
|
||||||
RTLIL::Wire* w = box_module->wire(*jt);
|
|
||||||
log_assert(w);
|
|
||||||
if (w == carry_in || w == carry_out) {
|
|
||||||
jt = ports.erase(jt);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (w->port_id > carry_in->port_id)
|
|
||||||
--w->port_id;
|
|
||||||
if (w->port_id > carry_out->port_id)
|
|
||||||
--w->port_id;
|
|
||||||
log_assert(w->port_input || w->port_output);
|
|
||||||
log_assert(ports[w->port_id-1] == w->name);
|
|
||||||
++jt;
|
|
||||||
}
|
|
||||||
ports.push_back(carry_in->name);
|
|
||||||
carry_in->port_id = ports.size();
|
|
||||||
ports.push_back(carry_out->name);
|
|
||||||
carry_out->port_id = ports.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fully pad all unused input connections of this box cell with S0
|
// Fully pad all unused input connections of this box cell with S0
|
||||||
// Fully pad all undriven output connections of this box cell with anonymous wires
|
// Fully pad all undriven output connections of this box cell with anonymous wires
|
||||||
// NB: Assume box_module->ports are sorted alphabetically
|
// NB: Assume box_module->ports are sorted alphabetically
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct ConstEvalAig
|
||||||
continue;
|
continue;
|
||||||
for (auto &it2 : it.second->connections())
|
for (auto &it2 : it.second->connections())
|
||||||
if (yosys_celltypes.cell_output(it.second->type, it2.first)) {
|
if (yosys_celltypes.cell_output(it.second->type, it2.first)) {
|
||||||
auto r = sig2driver.insert(std::make_pair(it2.second, it.second));
|
auto r YS_ATTRIBUTE(unused) = sig2driver.insert(std::make_pair(it2.second, it.second));
|
||||||
log_assert(r.second);
|
log_assert(r.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,9 +389,9 @@ void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
|
||||||
f.ignore(1);
|
f.ignore(1);
|
||||||
// XAIGER extensions
|
// XAIGER extensions
|
||||||
if (c == 'm') {
|
if (c == 'm') {
|
||||||
uint32_t dataSize = parse_xaiger_literal(f);
|
uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||||
uint32_t lutNum = parse_xaiger_literal(f);
|
uint32_t lutNum = parse_xaiger_literal(f);
|
||||||
uint32_t lutSize = parse_xaiger_literal(f);
|
uint32_t lutSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||||
log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
|
log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
|
||||||
ConstEvalAig ce(module);
|
ConstEvalAig ce(module);
|
||||||
for (unsigned i = 0; i < lutNum; ++i) {
|
for (unsigned i = 0; i < lutNum; ++i) {
|
||||||
|
@ -416,7 +416,7 @@ void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
|
||||||
int gray = j ^ (j >> 1);
|
int gray = j ^ (j >> 1);
|
||||||
ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast<int>(cutLeavesM)});
|
ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast<int>(cutLeavesM)});
|
||||||
RTLIL::SigBit o(output_sig);
|
RTLIL::SigBit o(output_sig);
|
||||||
bool success = ce.eval(o);
|
bool success YS_ATTRIBUTE(unused) = ce.eval(o);
|
||||||
log_assert(success);
|
log_assert(success);
|
||||||
log_assert(o.wire == nullptr);
|
log_assert(o.wire == nullptr);
|
||||||
lut_mask[gray] = o.data;
|
lut_mask[gray] = o.data;
|
||||||
|
@ -428,7 +428,7 @@ void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == 'r') {
|
else if (c == 'r') {
|
||||||
uint32_t dataSize = parse_xaiger_literal(f);
|
uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||||
flopNum = parse_xaiger_literal(f);
|
flopNum = parse_xaiger_literal(f);
|
||||||
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
|
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
|
||||||
f.ignore(flopNum * sizeof(uint32_t));
|
f.ignore(flopNum * sizeof(uint32_t));
|
||||||
|
@ -440,18 +440,18 @@ void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
|
||||||
}
|
}
|
||||||
else if (c == 'h') {
|
else if (c == 'h') {
|
||||||
f.ignore(sizeof(uint32_t));
|
f.ignore(sizeof(uint32_t));
|
||||||
uint32_t version = parse_xaiger_literal(f);
|
uint32_t version YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||||
log_assert(version == 1);
|
log_assert(version == 1);
|
||||||
uint32_t ciNum = parse_xaiger_literal(f);
|
uint32_t ciNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||||
log_debug("ciNum = %u\n", ciNum);
|
log_debug("ciNum = %u\n", ciNum);
|
||||||
uint32_t coNum = parse_xaiger_literal(f);
|
uint32_t coNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||||
log_debug("coNum = %u\n", coNum);
|
log_debug("coNum = %u\n", coNum);
|
||||||
piNum = parse_xaiger_literal(f);
|
piNum = parse_xaiger_literal(f);
|
||||||
log_debug("piNum = %u\n", piNum);
|
log_debug("piNum = %u\n", piNum);
|
||||||
uint32_t poNum = parse_xaiger_literal(f);
|
uint32_t poNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
|
||||||
log_debug("poNum = %u\n", poNum);
|
log_debug("poNum = %u\n", poNum);
|
||||||
uint32_t boxNum = parse_xaiger_literal(f);
|
uint32_t boxNum = parse_xaiger_literal(f);
|
||||||
log_debug("boxNum = %u\n", poNum);
|
log_debug("boxNum = %u\n", boxNum);
|
||||||
for (unsigned i = 0; i < boxNum; i++) {
|
for (unsigned i = 0; i < boxNum; i++) {
|
||||||
f.ignore(2*sizeof(uint32_t));
|
f.ignore(2*sizeof(uint32_t));
|
||||||
uint32_t boxUniqueId = parse_xaiger_literal(f);
|
uint32_t boxUniqueId = parse_xaiger_literal(f);
|
||||||
|
@ -901,9 +901,6 @@ void AigerReader::post_process()
|
||||||
RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
|
RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
|
||||||
if (cell) { // ABC could have optimised this box away
|
if (cell) { // ABC could have optimised this box away
|
||||||
module->rename(cell, escaped_s);
|
module->rename(cell, escaped_s);
|
||||||
RTLIL::Module* box_module = design->module(cell->type);
|
|
||||||
log_assert(box_module);
|
|
||||||
|
|
||||||
for (const auto &i : cell->connections()) {
|
for (const auto &i : cell->connections()) {
|
||||||
RTLIL::IdString port_name = i.first;
|
RTLIL::IdString port_name = i.first;
|
||||||
RTLIL::SigSpec rhs = i.second;
|
RTLIL::SigSpec rhs = i.second;
|
||||||
|
|
|
@ -1172,7 +1172,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
||||||
|
|
||||||
if (design->has((*it)->str)) {
|
if (design->has((*it)->str)) {
|
||||||
RTLIL::Module *existing_mod = design->module((*it)->str);
|
RTLIL::Module *existing_mod = design->module((*it)->str);
|
||||||
if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
|
if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
|
||||||
log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
|
log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
|
||||||
} else if (nooverwrite) {
|
} else if (nooverwrite) {
|
||||||
log("Ignoring re-definition of module `%s' at %s:%d.\n",
|
log("Ignoring re-definition of module `%s' at %s:%d.\n",
|
||||||
|
@ -1502,7 +1502,10 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
|
||||||
rewrite_parameter:
|
rewrite_parameter:
|
||||||
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
|
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
|
||||||
delete child->children.at(0);
|
delete child->children.at(0);
|
||||||
if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
|
if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) {
|
||||||
|
child->children[0] = new AstNode(AST_REALVALUE);
|
||||||
|
child->children[0]->realvalue = std::stod(parameters[para_id].decode_string());
|
||||||
|
} else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
|
||||||
child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
|
child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
|
||||||
else
|
else
|
||||||
child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
|
child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
|
||||||
|
|
|
@ -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)) { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1789,7 +1789,7 @@ struct VerificExtNets
|
||||||
new_net = new Net(name.c_str());
|
new_net = new Net(name.c_str());
|
||||||
nl->Add(new_net);
|
nl->Add(new_net);
|
||||||
|
|
||||||
Net *n = route_up(new_net, port->IsOutput(), ca_nl, ca_net);
|
Net *n YS_ATTRIBUTE(unused) = route_up(new_net, port->IsOutput(), ca_nl, ca_net);
|
||||||
log_assert(n == ca_net);
|
log_assert(n == ca_net);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,19 +292,19 @@ Aig::Aig(Cell *cell)
|
||||||
|
|
||||||
if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($_BUF_)))
|
if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($_BUF_)))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < GetSize(cell->getPort(ID(Y))); i++) {
|
for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
|
||||||
int A = mk.inport(ID(A), i);
|
int A = mk.inport(ID::A, i);
|
||||||
int Y = cell->type.in(ID($not), ID($_NOT_)) ? mk.not_gate(A) : A;
|
int Y = cell->type.in(ID($not), ID($_NOT_)) ? mk.not_gate(A) : A;
|
||||||
mk.outport(Y, ID(Y), i);
|
mk.outport(Y, ID::Y, i);
|
||||||
}
|
}
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_), ID($or), ID($_OR_), ID($_NOR_), ID($xor), ID($xnor), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
|
if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_), ID($or), ID($_OR_), ID($_NOR_), ID($xor), ID($xnor), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < GetSize(cell->getPort(ID(Y))); i++) {
|
for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
|
||||||
int A = mk.inport(ID(A), i);
|
int A = mk.inport(ID::A, i);
|
||||||
int B = mk.inport(ID(B), i);
|
int B = mk.inport(ID::B, i);
|
||||||
int Y = cell->type.in(ID($and), ID($_AND_)) ? mk.and_gate(A, B) :
|
int Y = cell->type.in(ID($and), ID($_AND_)) ? mk.and_gate(A, B) :
|
||||||
cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
|
cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
|
||||||
cell->type.in(ID($or), ID($_OR_)) ? mk.or_gate(A, B) :
|
cell->type.in(ID($or), ID($_OR_)) ? mk.or_gate(A, B) :
|
||||||
|
@ -313,7 +313,7 @@ Aig::Aig(Cell *cell)
|
||||||
cell->type.in(ID($xnor), ID($_XNOR_)) ? mk.xnor_gate(A, B) :
|
cell->type.in(ID($xnor), ID($_XNOR_)) ? mk.xnor_gate(A, B) :
|
||||||
cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
|
cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
|
||||||
cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
|
cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
|
||||||
mk.outport(Y, ID(Y), i);
|
mk.outport(Y, ID::Y, i);
|
||||||
}
|
}
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
@ -321,22 +321,22 @@ Aig::Aig(Cell *cell)
|
||||||
if (cell->type.in(ID($mux), ID($_MUX_)))
|
if (cell->type.in(ID($mux), ID($_MUX_)))
|
||||||
{
|
{
|
||||||
int S = mk.inport(ID(S));
|
int S = mk.inport(ID(S));
|
||||||
for (int i = 0; i < GetSize(cell->getPort(ID(Y))); i++) {
|
for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
|
||||||
int A = mk.inport(ID(A), i);
|
int A = mk.inport(ID::A, i);
|
||||||
int B = mk.inport(ID(B), i);
|
int B = mk.inport(ID::B, i);
|
||||||
int Y = mk.mux_gate(A, B, S);
|
int Y = mk.mux_gate(A, B, S);
|
||||||
if (cell->type == ID($_NMUX_))
|
if (cell->type == ID($_NMUX_))
|
||||||
Y = mk.not_gate(Y);
|
Y = mk.not_gate(Y);
|
||||||
mk.outport(Y, ID(Y), i);
|
mk.outport(Y, ID::Y, i);
|
||||||
}
|
}
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)))
|
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)))
|
||||||
{
|
{
|
||||||
int Y = mk.inport(ID(A), 0);
|
int Y = mk.inport(ID::A, 0);
|
||||||
for (int i = 1; i < GetSize(cell->getPort(ID(A))); i++) {
|
for (int i = 1; i < GetSize(cell->getPort(ID::A)); i++) {
|
||||||
int A = mk.inport(ID(A), i);
|
int A = mk.inport(ID::A, i);
|
||||||
if (cell->type == ID($reduce_and)) Y = mk.and_gate(A, Y);
|
if (cell->type == ID($reduce_and)) Y = mk.and_gate(A, Y);
|
||||||
if (cell->type == ID($reduce_or)) Y = mk.or_gate(A, Y);
|
if (cell->type == ID($reduce_or)) Y = mk.or_gate(A, Y);
|
||||||
if (cell->type == ID($reduce_bool)) Y = mk.or_gate(A, Y);
|
if (cell->type == ID($reduce_bool)) Y = mk.or_gate(A, Y);
|
||||||
|
@ -345,35 +345,35 @@ Aig::Aig(Cell *cell)
|
||||||
}
|
}
|
||||||
if (cell->type == ID($reduce_xnor))
|
if (cell->type == ID($reduce_xnor))
|
||||||
Y = mk.not_gate(Y);
|
Y = mk.not_gate(Y);
|
||||||
mk.outport(Y, ID(Y), 0);
|
mk.outport(Y, ID::Y, 0);
|
||||||
for (int i = 1; i < GetSize(cell->getPort(ID(Y))); i++)
|
for (int i = 1; i < GetSize(cell->getPort(ID::Y)); i++)
|
||||||
mk.outport(mk.bool_node(false), ID(Y), i);
|
mk.outport(mk.bool_node(false), ID::Y, i);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or)))
|
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or)))
|
||||||
{
|
{
|
||||||
int A = mk.inport(ID(A), 0), Y = -1;
|
int A = mk.inport(ID::A, 0), Y = -1;
|
||||||
for (int i = 1; i < GetSize(cell->getPort(ID(A))); i++)
|
for (int i = 1; i < GetSize(cell->getPort(ID::A)); i++)
|
||||||
A = mk.or_gate(mk.inport(ID(A), i), A);
|
A = mk.or_gate(mk.inport(ID::A, i), A);
|
||||||
if (cell->type.in(ID($logic_and), ID($logic_or))) {
|
if (cell->type.in(ID($logic_and), ID($logic_or))) {
|
||||||
int B = mk.inport(ID(B), 0);
|
int B = mk.inport(ID::B, 0);
|
||||||
for (int i = 1; i < GetSize(cell->getPort(ID(B))); i++)
|
for (int i = 1; i < GetSize(cell->getPort(ID::B)); i++)
|
||||||
B = mk.or_gate(mk.inport(ID(B), i), B);
|
B = mk.or_gate(mk.inport(ID::B, i), B);
|
||||||
if (cell->type == ID($logic_and)) Y = mk.and_gate(A, B);
|
if (cell->type == ID($logic_and)) Y = mk.and_gate(A, B);
|
||||||
if (cell->type == ID($logic_or)) Y = mk.or_gate(A, B);
|
if (cell->type == ID($logic_or)) Y = mk.or_gate(A, B);
|
||||||
} else {
|
} else {
|
||||||
if (cell->type == ID($logic_not)) Y = mk.not_gate(A);
|
if (cell->type == ID($logic_not)) Y = mk.not_gate(A);
|
||||||
}
|
}
|
||||||
mk.outport_bool(Y, ID(Y));
|
mk.outport_bool(Y, ID::Y);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($add), ID($sub)))
|
if (cell->type.in(ID($add), ID($sub)))
|
||||||
{
|
{
|
||||||
int width = GetSize(cell->getPort(ID(Y)));
|
int width = GetSize(cell->getPort(ID::Y));
|
||||||
vector<int> A = mk.inport_vec(ID(A), width);
|
vector<int> A = mk.inport_vec(ID::A, width);
|
||||||
vector<int> B = mk.inport_vec(ID(B), width);
|
vector<int> B = mk.inport_vec(ID::B, width);
|
||||||
int carry = mk.bool_node(false);
|
int carry = mk.bool_node(false);
|
||||||
if (cell->type == ID($sub)) {
|
if (cell->type == ID($sub)) {
|
||||||
for (auto &n : B)
|
for (auto &n : B)
|
||||||
|
@ -381,15 +381,15 @@ Aig::Aig(Cell *cell)
|
||||||
carry = mk.not_gate(carry);
|
carry = mk.not_gate(carry);
|
||||||
}
|
}
|
||||||
vector<int> Y = mk.adder(A, B, carry);
|
vector<int> Y = mk.adder(A, B, carry);
|
||||||
mk.outport_vec(Y, ID(Y));
|
mk.outport_vec(Y, ID::Y);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($alu))
|
if (cell->type == ID($alu))
|
||||||
{
|
{
|
||||||
int width = GetSize(cell->getPort(ID(Y)));
|
int width = GetSize(cell->getPort(ID::Y));
|
||||||
vector<int> A = mk.inport_vec(ID(A), width);
|
vector<int> A = mk.inport_vec(ID::A, width);
|
||||||
vector<int> B = mk.inport_vec(ID(B), width);
|
vector<int> B = mk.inport_vec(ID::B, width);
|
||||||
int carry = mk.inport(ID(CI));
|
int carry = mk.inport(ID(CI));
|
||||||
int binv = mk.inport(ID(BI));
|
int binv = mk.inport(ID(BI));
|
||||||
for (auto &n : B)
|
for (auto &n : B)
|
||||||
|
@ -398,7 +398,7 @@ Aig::Aig(Cell *cell)
|
||||||
vector<int> Y = mk.adder(A, B, carry, &X, &CO);
|
vector<int> Y = mk.adder(A, B, carry, &X, &CO);
|
||||||
for (int i = 0; i < width; i++)
|
for (int i = 0; i < width; i++)
|
||||||
X[i] = mk.xor_gate(A[i], B[i]);
|
X[i] = mk.xor_gate(A[i], B[i]);
|
||||||
mk.outport_vec(Y, ID(Y));
|
mk.outport_vec(Y, ID::Y);
|
||||||
mk.outport_vec(X, ID(X));
|
mk.outport_vec(X, ID(X));
|
||||||
mk.outport_vec(CO, ID(CO));
|
mk.outport_vec(CO, ID(CO));
|
||||||
goto optimize;
|
goto optimize;
|
||||||
|
@ -406,57 +406,57 @@ Aig::Aig(Cell *cell)
|
||||||
|
|
||||||
if (cell->type.in(ID($eq), ID($ne)))
|
if (cell->type.in(ID($eq), ID($ne)))
|
||||||
{
|
{
|
||||||
int width = max(GetSize(cell->getPort(ID(A))), GetSize(cell->getPort(ID(B))));
|
int width = max(GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::B)));
|
||||||
vector<int> A = mk.inport_vec(ID(A), width);
|
vector<int> A = mk.inport_vec(ID::A, width);
|
||||||
vector<int> B = mk.inport_vec(ID(B), width);
|
vector<int> B = mk.inport_vec(ID::B, width);
|
||||||
int Y = mk.bool_node(false);
|
int Y = mk.bool_node(false);
|
||||||
for (int i = 0; i < width; i++)
|
for (int i = 0; i < width; i++)
|
||||||
Y = mk.or_gate(Y, mk.xor_gate(A[i], B[i]));
|
Y = mk.or_gate(Y, mk.xor_gate(A[i], B[i]));
|
||||||
if (cell->type == ID($eq))
|
if (cell->type == ID($eq))
|
||||||
Y = mk.not_gate(Y);
|
Y = mk.not_gate(Y);
|
||||||
mk.outport_bool(Y, ID(Y));
|
mk.outport_bool(Y, ID::Y);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_AOI3_))
|
if (cell->type == ID($_AOI3_))
|
||||||
{
|
{
|
||||||
int A = mk.inport(ID(A));
|
int A = mk.inport(ID::A);
|
||||||
int B = mk.inport(ID(B));
|
int B = mk.inport(ID::B);
|
||||||
int C = mk.inport(ID(C));
|
int C = mk.inport(ID(C));
|
||||||
int Y = mk.nor_gate(mk.and_gate(A, B), C);
|
int Y = mk.nor_gate(mk.and_gate(A, B), C);
|
||||||
mk.outport(Y, ID(Y));
|
mk.outport(Y, ID::Y);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_OAI3_))
|
if (cell->type == ID($_OAI3_))
|
||||||
{
|
{
|
||||||
int A = mk.inport(ID(A));
|
int A = mk.inport(ID::A);
|
||||||
int B = mk.inport(ID(B));
|
int B = mk.inport(ID::B);
|
||||||
int C = mk.inport(ID(C));
|
int C = mk.inport(ID(C));
|
||||||
int Y = mk.nand_gate(mk.or_gate(A, B), C);
|
int Y = mk.nand_gate(mk.or_gate(A, B), C);
|
||||||
mk.outport(Y, ID(Y));
|
mk.outport(Y, ID::Y);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_AOI4_))
|
if (cell->type == ID($_AOI4_))
|
||||||
{
|
{
|
||||||
int A = mk.inport(ID(A));
|
int A = mk.inport(ID::A);
|
||||||
int B = mk.inport(ID(B));
|
int B = mk.inport(ID::B);
|
||||||
int C = mk.inport(ID(C));
|
int C = mk.inport(ID(C));
|
||||||
int D = mk.inport(ID(D));
|
int D = mk.inport(ID(D));
|
||||||
int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
|
int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
|
||||||
mk.outport(Y, ID(Y));
|
mk.outport(Y, ID::Y);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_OAI4_))
|
if (cell->type == ID($_OAI4_))
|
||||||
{
|
{
|
||||||
int A = mk.inport(ID(A));
|
int A = mk.inport(ID::A);
|
||||||
int B = mk.inport(ID(B));
|
int B = mk.inport(ID::B);
|
||||||
int C = mk.inport(ID(C));
|
int C = mk.inport(ID(C));
|
||||||
int D = mk.inport(ID(D));
|
int D = mk.inport(ID(D));
|
||||||
int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D));
|
int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D));
|
||||||
mk.outport(Y, ID(Y));
|
mk.outport(Y, ID::Y);
|
||||||
goto optimize;
|
goto optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
IdString A = ID(A), Y = ID(Y);
|
IdString A = ID::A, Y = ID::Y;
|
||||||
|
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
int a_width = GetSize(cell->getPort(A));
|
int a_width = GetSize(cell->getPort(A));
|
||||||
|
@ -41,7 +41,7 @@ void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
IdString A = ID(A), B = ID(B), Y = ID(Y);
|
IdString A = ID::A, B = ID::B, Y = ID::Y;
|
||||||
|
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
int a_width = GetSize(cell->getPort(A));
|
int a_width = GetSize(cell->getPort(A));
|
||||||
|
@ -71,7 +71,7 @@ void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
IdString A = ID(A), Y = ID(Y);
|
IdString A = ID::A, Y = ID::Y;
|
||||||
|
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
int a_width = GetSize(cell->getPort(A));
|
int a_width = GetSize(cell->getPort(A));
|
||||||
|
@ -87,7 +87,7 @@ void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
IdString A = ID(A), B = ID(B), Y = ID(Y);
|
IdString A = ID::A, B = ID::B, Y = ID::Y;
|
||||||
|
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
int a_width = GetSize(cell->getPort(A));
|
int a_width = GetSize(cell->getPort(A));
|
||||||
|
@ -114,7 +114,7 @@ void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
IdString A = ID(A), Y = ID(Y);
|
IdString A = ID::A, Y = ID::Y;
|
||||||
|
|
||||||
int a_width = GetSize(cell->getPort(A));
|
int a_width = GetSize(cell->getPort(A));
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
IdString A = ID(A), B = ID(B), Y = ID(Y);
|
IdString A = ID::A, B = ID::B, Y = ID::Y;
|
||||||
|
|
||||||
int a_width = GetSize(cell->getPort(A));
|
int a_width = GetSize(cell->getPort(A));
|
||||||
int b_width = GetSize(cell->getPort(B));
|
int b_width = GetSize(cell->getPort(B));
|
||||||
|
@ -138,7 +138,7 @@ void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void mux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
void mux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
IdString A = ID(A), B = ID(B), S = ID(S), Y = ID(Y);
|
IdString A = ID::A, B = ID::B, S = ID(S), Y = ID::Y;
|
||||||
|
|
||||||
int a_width = GetSize(cell->getPort(A));
|
int a_width = GetSize(cell->getPort(A));
|
||||||
int b_width = GetSize(cell->getPort(B));
|
int b_width = GetSize(cell->getPort(B));
|
||||||
|
|
|
@ -84,7 +84,7 @@ struct CellTypes
|
||||||
{
|
{
|
||||||
setup_internals_eval();
|
setup_internals_eval();
|
||||||
|
|
||||||
IdString A = ID(A), B = ID(B), EN = ID(EN), Y = ID(Y);
|
IdString A = ID::A, B = ID::B, EN = ID(EN), Y = ID::Y;
|
||||||
IdString SRC = ID(SRC), DST = ID(DST), DAT = ID(DAT);
|
IdString SRC = ID(SRC), DST = ID(DST), DAT = ID(DAT);
|
||||||
IdString EN_SRC = ID(EN_SRC), EN_DST = ID(EN_DST);
|
IdString EN_SRC = ID(EN_SRC), EN_DST = ID(EN_DST);
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ struct CellTypes
|
||||||
ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow),
|
ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow),
|
||||||
ID($logic_and), ID($logic_or), ID($concat), ID($macc)
|
ID($logic_and), ID($logic_or), ID($concat), ID($macc)
|
||||||
};
|
};
|
||||||
IdString A = ID(A), B = ID(B), S = ID(S), Y = ID(Y);
|
IdString A = ID::A, B = ID::B, S = ID(S), Y = ID::Y;
|
||||||
IdString P = ID(P), G = ID(G), C = ID(C), X = ID(X);
|
IdString P = ID(P), G = ID(G), C = ID(C), X = ID(X);
|
||||||
IdString BI = ID(BI), CI = ID(CI), CO = ID(CO), EN = ID(EN);
|
IdString BI = ID(BI), CI = ID(CI), CO = ID(CO), EN = ID(EN);
|
||||||
|
|
||||||
|
@ -177,19 +177,19 @@ struct CellTypes
|
||||||
{
|
{
|
||||||
setup_stdcells_eval();
|
setup_stdcells_eval();
|
||||||
|
|
||||||
IdString A = ID(A), E = ID(E), Y = ID(Y);
|
IdString A = ID::A, E = ID(E), Y = ID::Y;
|
||||||
|
|
||||||
setup_type(ID($_TBUF_), {A, E}, {Y}, true);
|
setup_type(ID($_TBUF_), {A, E}, {Y}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_stdcells_eval()
|
void setup_stdcells_eval()
|
||||||
{
|
{
|
||||||
IdString A = ID(A), B = ID(B), C = ID(C), D = ID(D);
|
IdString A = ID::A, B = ID::B, C = ID(C), D = ID(D);
|
||||||
IdString E = ID(E), F = ID(F), G = ID(G), H = ID(H);
|
IdString E = ID(E), F = ID(F), G = ID(G), H = ID(H);
|
||||||
IdString I = ID(I), J = ID(J), K = ID(K), L = ID(L);
|
IdString I = ID(I), J = ID(J), K = ID(K), L = ID(L);
|
||||||
IdString M = ID(M), N = ID(N), O = ID(O), P = ID(P);
|
IdString M = ID(M), N = ID(N), O = ID(O), P = ID(P);
|
||||||
IdString S = ID(S), T = ID(T), U = ID(U), V = ID(V);
|
IdString S = ID(S), T = ID(T), U = ID(U), V = ID(V);
|
||||||
IdString Y = ID(Y);
|
IdString Y = ID::Y;
|
||||||
|
|
||||||
setup_type(ID($_BUF_), {A}, {Y}, true);
|
setup_type(ID($_BUF_), {A}, {Y}, true);
|
||||||
setup_type(ID($_NOT_), {A}, {Y}, true);
|
setup_type(ID($_NOT_), {A}, {Y}, true);
|
||||||
|
|
|
@ -128,8 +128,8 @@ struct ConstEval
|
||||||
|
|
||||||
RTLIL::SigSpec sig_a, sig_b, sig_s, sig_y;
|
RTLIL::SigSpec sig_a, sig_b, sig_s, sig_y;
|
||||||
|
|
||||||
log_assert(cell->hasPort(ID(Y)));
|
log_assert(cell->hasPort(ID::Y));
|
||||||
sig_y = values_map(assign_map(cell->getPort(ID(Y))));
|
sig_y = values_map(assign_map(cell->getPort(ID::Y)));
|
||||||
if (sig_y.is_fully_const())
|
if (sig_y.is_fully_const())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -139,11 +139,11 @@ struct ConstEval
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->hasPort(ID(A)))
|
if (cell->hasPort(ID::A))
|
||||||
sig_a = cell->getPort(ID(A));
|
sig_a = cell->getPort(ID::A);
|
||||||
|
|
||||||
if (cell->hasPort(ID(B)))
|
if (cell->hasPort(ID::B))
|
||||||
sig_b = cell->getPort(ID(B));
|
sig_b = cell->getPort(ID::B);
|
||||||
|
|
||||||
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_NMUX_)))
|
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_NMUX_)))
|
||||||
{
|
{
|
||||||
|
@ -298,11 +298,11 @@ struct ConstEval
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLIL::Const result(0, GetSize(cell->getPort(ID(Y))));
|
RTLIL::Const result(0, GetSize(cell->getPort(ID::Y)));
|
||||||
if (!macc.eval(result))
|
if (!macc.eval(result))
|
||||||
log_abort();
|
log_abort();
|
||||||
|
|
||||||
set(cell->getPort(ID(Y)), result);
|
set(cell->getPort(ID::Y), result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,7 +91,7 @@ YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(prin
|
||||||
static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; }
|
static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; }
|
||||||
# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
|
# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
|
||||||
#else
|
#else
|
||||||
static inline bool ys_debug(int n = 0) { return false; }
|
static inline bool ys_debug(int = 0) { return false; }
|
||||||
# define log_debug(_fmt, ...) do { } while (0)
|
# define log_debug(_fmt, ...) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -99,10 +99,10 @@ struct Macc
|
||||||
|
|
||||||
void from_cell(RTLIL::Cell *cell)
|
void from_cell(RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec port_a = cell->getPort(ID(A));
|
RTLIL::SigSpec port_a = cell->getPort(ID::A);
|
||||||
|
|
||||||
ports.clear();
|
ports.clear();
|
||||||
bit_ports = cell->getPort(ID(B));
|
bit_ports = cell->getPort(ID::B);
|
||||||
|
|
||||||
std::vector<RTLIL::State> config_bits = cell->getParam(ID(CONFIG)).bits;
|
std::vector<RTLIL::State> config_bits = cell->getParam(ID(CONFIG)).bits;
|
||||||
int config_cursor = 0;
|
int config_cursor = 0;
|
||||||
|
@ -191,8 +191,8 @@ struct Macc
|
||||||
port_a.append(port.in_b);
|
port_a.append(port.in_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->setPort(ID(A), port_a);
|
cell->setPort(ID::A, port_a);
|
||||||
cell->setPort(ID(B), bit_ports);
|
cell->setPort(ID::B, bit_ports);
|
||||||
cell->setParam(ID(CONFIG), config_bits);
|
cell->setParam(ID(CONFIG), config_bits);
|
||||||
cell->setParam(ID(CONFIG_WIDTH), GetSize(config_bits));
|
cell->setParam(ID(CONFIG_WIDTH), GetSize(config_bits));
|
||||||
cell->setParam(ID(A_WIDTH), GetSize(port_a));
|
cell->setParam(ID(A_WIDTH), GetSize(port_a));
|
||||||
|
|
192
kernel/rtlil.cc
192
kernel/rtlil.cc
|
@ -717,7 +717,7 @@ void RTLIL::Module::makeblackbox()
|
||||||
processes.clear();
|
processes.clear();
|
||||||
|
|
||||||
remove(delwires);
|
remove(delwires);
|
||||||
set_bool_attribute(ID(blackbox));
|
set_bool_attribute(ID::blackbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL::Module::reprocess_module(RTLIL::Design *, dict<RTLIL::IdString, RTLIL::Module *>)
|
void RTLIL::Module::reprocess_module(RTLIL::Design *, dict<RTLIL::IdString, RTLIL::Module *>)
|
||||||
|
@ -845,8 +845,8 @@ namespace {
|
||||||
|
|
||||||
if (cell->type.in(ID($not), ID($pos), ID($neg))) {
|
if (cell->type.in(ID($not), ID($pos), ID($neg))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -854,17 +854,17 @@ namespace {
|
||||||
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) {
|
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
param_bool(ID(B_SIGNED));
|
param_bool(ID(B_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool))) {
|
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -872,9 +872,9 @@ namespace {
|
||||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
|
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
param_bool(ID(B_SIGNED));
|
param_bool(ID(B_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected(false);
|
check_expected(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -882,9 +882,9 @@ namespace {
|
||||||
if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) {
|
if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
param_bool(ID(B_SIGNED));
|
param_bool(ID(B_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -892,19 +892,19 @@ namespace {
|
||||||
if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) {
|
if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
param_bool(ID(B_SIGNED));
|
param_bool(ID(B_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected(cell->type != ID($pow));
|
check_expected(cell->type != ID($pow));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($fa)) {
|
if (cell->type == ID($fa)) {
|
||||||
port(ID(A), param(ID(WIDTH)));
|
port(ID::A, param(ID(WIDTH)));
|
||||||
port(ID(B), param(ID(WIDTH)));
|
port(ID::B, param(ID(WIDTH)));
|
||||||
port(ID(C), param(ID(WIDTH)));
|
port(ID(C), param(ID(WIDTH)));
|
||||||
port(ID(X), param(ID(WIDTH)));
|
port(ID(X), param(ID(WIDTH)));
|
||||||
port(ID(Y), param(ID(WIDTH)));
|
port(ID::Y, param(ID(WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -921,12 +921,12 @@ namespace {
|
||||||
if (cell->type == ID($alu)) {
|
if (cell->type == ID($alu)) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
param_bool(ID(B_SIGNED));
|
param_bool(ID(B_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(CI), 1);
|
port(ID(CI), 1);
|
||||||
port(ID(BI), 1);
|
port(ID(BI), 1);
|
||||||
port(ID(X), param(ID(Y_WIDTH)));
|
port(ID(X), param(ID(Y_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
port(ID(CO), param(ID(Y_WIDTH)));
|
port(ID(CO), param(ID(Y_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
|
@ -935,9 +935,9 @@ namespace {
|
||||||
if (cell->type == ID($macc)) {
|
if (cell->type == ID($macc)) {
|
||||||
param(ID(CONFIG));
|
param(ID(CONFIG));
|
||||||
param(ID(CONFIG_WIDTH));
|
param(ID(CONFIG_WIDTH));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
Macc().from_cell(cell);
|
Macc().from_cell(cell);
|
||||||
return;
|
return;
|
||||||
|
@ -945,8 +945,8 @@ namespace {
|
||||||
|
|
||||||
if (cell->type == ID($logic_not)) {
|
if (cell->type == ID($logic_not)) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -954,17 +954,17 @@ namespace {
|
||||||
if (cell->type.in(ID($logic_and), ID($logic_or))) {
|
if (cell->type.in(ID($logic_and), ID($logic_or))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
param_bool(ID(B_SIGNED));
|
param_bool(ID(B_SIGNED));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected(false);
|
check_expected(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($slice)) {
|
if (cell->type == ID($slice)) {
|
||||||
param(ID(OFFSET));
|
param(ID(OFFSET));
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(Y), param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
if (param(ID(OFFSET)) + param(ID(Y_WIDTH)) > param(ID(A_WIDTH)))
|
if (param(ID(OFFSET)) + param(ID(Y_WIDTH)) > param(ID(A_WIDTH)))
|
||||||
error(__LINE__);
|
error(__LINE__);
|
||||||
check_expected();
|
check_expected();
|
||||||
|
@ -972,35 +972,35 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($concat)) {
|
if (cell->type == ID($concat)) {
|
||||||
port(ID(A), param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID(B), param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID(Y), param(ID(A_WIDTH)) + param(ID(B_WIDTH)));
|
port(ID::Y, param(ID(A_WIDTH)) + param(ID(B_WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($mux)) {
|
if (cell->type == ID($mux)) {
|
||||||
port(ID(A), param(ID(WIDTH)));
|
port(ID::A, param(ID(WIDTH)));
|
||||||
port(ID(B), param(ID(WIDTH)));
|
port(ID::B, param(ID(WIDTH)));
|
||||||
port(ID(S), 1);
|
port(ID(S), 1);
|
||||||
port(ID(Y), param(ID(WIDTH)));
|
port(ID::Y, param(ID(WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($pmux)) {
|
if (cell->type == ID($pmux)) {
|
||||||
port(ID(A), param(ID(WIDTH)));
|
port(ID::A, param(ID(WIDTH)));
|
||||||
port(ID(B), param(ID(WIDTH)) * param(ID(S_WIDTH)));
|
port(ID::B, param(ID(WIDTH)) * param(ID(S_WIDTH)));
|
||||||
port(ID(S), param(ID(S_WIDTH)));
|
port(ID(S), param(ID(S_WIDTH)));
|
||||||
port(ID(Y), param(ID(WIDTH)));
|
port(ID::Y, param(ID(WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($lut)) {
|
if (cell->type == ID($lut)) {
|
||||||
param(ID(LUT));
|
param(ID(LUT));
|
||||||
port(ID(A), param(ID(WIDTH)));
|
port(ID::A, param(ID(WIDTH)));
|
||||||
port(ID(Y), 1);
|
port(ID::Y, 1);
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1008,8 +1008,8 @@ namespace {
|
||||||
if (cell->type == ID($sop)) {
|
if (cell->type == ID($sop)) {
|
||||||
param(ID(DEPTH));
|
param(ID(DEPTH));
|
||||||
param(ID(TABLE));
|
param(ID(TABLE));
|
||||||
port(ID(A), param(ID(WIDTH)));
|
port(ID::A, param(ID(WIDTH)));
|
||||||
port(ID(Y), 1);
|
port(ID::Y, 1);
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1175,36 +1175,36 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($tribuf)) {
|
if (cell->type == ID($tribuf)) {
|
||||||
port(ID(A), param(ID(WIDTH)));
|
port(ID::A, param(ID(WIDTH)));
|
||||||
port(ID(Y), param(ID(WIDTH)));
|
port(ID::Y, param(ID(WIDTH)));
|
||||||
port(ID(EN), 1);
|
port(ID(EN), 1);
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) {
|
if (cell->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) {
|
||||||
port(ID(A), 1);
|
port(ID::A, 1);
|
||||||
port(ID(EN), 1);
|
port(ID(EN), 1);
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($initstate)) {
|
if (cell->type == ID($initstate)) {
|
||||||
port(ID(Y), 1);
|
port(ID::Y, 1);
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($anyconst), ID($anyseq), ID($allconst), ID($allseq))) {
|
if (cell->type.in(ID($anyconst), ID($anyseq), ID($allconst), ID($allseq))) {
|
||||||
port(ID(Y), param(ID(WIDTH)));
|
port(ID::Y, param(ID(WIDTH)));
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($equiv)) {
|
if (cell->type == ID($equiv)) {
|
||||||
port(ID(A), 1);
|
port(ID::A, 1);
|
||||||
port(ID(B), 1);
|
port(ID::B, 1);
|
||||||
port(ID(Y), 1);
|
port(ID::Y, 1);
|
||||||
check_expected();
|
check_expected();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1831,8 +1831,8 @@ RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, const RTLIL::Cell *oth
|
||||||
cell->parameters[ID(A_SIGNED)] = is_signed; \
|
cell->parameters[ID(A_SIGNED)] = is_signed; \
|
||||||
cell->parameters[ID(A_WIDTH)] = sig_a.size(); \
|
cell->parameters[ID(A_WIDTH)] = sig_a.size(); \
|
||||||
cell->parameters[ID(Y_WIDTH)] = sig_y.size(); \
|
cell->parameters[ID(Y_WIDTH)] = sig_y.size(); \
|
||||||
cell->setPort(ID(A), sig_a); \
|
cell->setPort(ID::A, sig_a); \
|
||||||
cell->setPort(ID(Y), sig_y); \
|
cell->setPort(ID::Y, sig_y); \
|
||||||
cell->set_src_attribute(src); \
|
cell->set_src_attribute(src); \
|
||||||
return cell; \
|
return cell; \
|
||||||
} \
|
} \
|
||||||
|
@ -1860,9 +1860,9 @@ DEF_METHOD(LogicNot, 1, ID($logic_not))
|
||||||
cell->parameters[ID(A_WIDTH)] = sig_a.size(); \
|
cell->parameters[ID(A_WIDTH)] = sig_a.size(); \
|
||||||
cell->parameters[ID(B_WIDTH)] = sig_b.size(); \
|
cell->parameters[ID(B_WIDTH)] = sig_b.size(); \
|
||||||
cell->parameters[ID(Y_WIDTH)] = sig_y.size(); \
|
cell->parameters[ID(Y_WIDTH)] = sig_y.size(); \
|
||||||
cell->setPort(ID(A), sig_a); \
|
cell->setPort(ID::A, sig_a); \
|
||||||
cell->setPort(ID(B), sig_b); \
|
cell->setPort(ID::B, sig_b); \
|
||||||
cell->setPort(ID(Y), sig_y); \
|
cell->setPort(ID::Y, sig_y); \
|
||||||
cell->set_src_attribute(src); \
|
cell->set_src_attribute(src); \
|
||||||
return cell; \
|
return cell; \
|
||||||
} \
|
} \
|
||||||
|
@ -1903,10 +1903,10 @@ DEF_METHOD(LogicOr, 1, ID($logic_or))
|
||||||
RTLIL::Cell *cell = addCell(name, _type); \
|
RTLIL::Cell *cell = addCell(name, _type); \
|
||||||
cell->parameters[ID(WIDTH)] = sig_a.size(); \
|
cell->parameters[ID(WIDTH)] = sig_a.size(); \
|
||||||
if (_pmux) cell->parameters[ID(S_WIDTH)] = sig_s.size(); \
|
if (_pmux) cell->parameters[ID(S_WIDTH)] = sig_s.size(); \
|
||||||
cell->setPort(ID(A), sig_a); \
|
cell->setPort(ID::A, sig_a); \
|
||||||
cell->setPort(ID(B), sig_b); \
|
cell->setPort(ID::B, sig_b); \
|
||||||
cell->setPort(ID(S), sig_s); \
|
cell->setPort(ID(S), sig_s); \
|
||||||
cell->setPort(ID(Y), sig_y); \
|
cell->setPort(ID::Y, sig_y); \
|
||||||
cell->set_src_attribute(src); \
|
cell->set_src_attribute(src); \
|
||||||
return cell; \
|
return cell; \
|
||||||
} \
|
} \
|
||||||
|
@ -2006,9 +2006,9 @@ RTLIL::Cell* RTLIL::Module::addPow(RTLIL::IdString name, RTLIL::SigSpec sig_a, R
|
||||||
cell->parameters[ID(A_WIDTH)] = sig_a.size();
|
cell->parameters[ID(A_WIDTH)] = sig_a.size();
|
||||||
cell->parameters[ID(B_WIDTH)] = sig_b.size();
|
cell->parameters[ID(B_WIDTH)] = sig_b.size();
|
||||||
cell->parameters[ID(Y_WIDTH)] = sig_y.size();
|
cell->parameters[ID(Y_WIDTH)] = sig_y.size();
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(B), sig_b);
|
cell->setPort(ID::B, sig_b);
|
||||||
cell->setPort(ID(Y), sig_y);
|
cell->setPort(ID::Y, sig_y);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
@ -2019,8 +2019,8 @@ RTLIL::Cell* RTLIL::Module::addSlice(RTLIL::IdString name, RTLIL::SigSpec sig_a,
|
||||||
cell->parameters[ID(A_WIDTH)] = sig_a.size();
|
cell->parameters[ID(A_WIDTH)] = sig_a.size();
|
||||||
cell->parameters[ID(Y_WIDTH)] = sig_y.size();
|
cell->parameters[ID(Y_WIDTH)] = sig_y.size();
|
||||||
cell->parameters[ID(OFFSET)] = offset;
|
cell->parameters[ID(OFFSET)] = offset;
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(Y), sig_y);
|
cell->setPort(ID::Y, sig_y);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
@ -2030,9 +2030,9 @@ RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, RTLIL::SigSpec sig_a
|
||||||
RTLIL::Cell *cell = addCell(name, ID($concat));
|
RTLIL::Cell *cell = addCell(name, ID($concat));
|
||||||
cell->parameters[ID(A_WIDTH)] = sig_a.size();
|
cell->parameters[ID(A_WIDTH)] = sig_a.size();
|
||||||
cell->parameters[ID(B_WIDTH)] = sig_b.size();
|
cell->parameters[ID(B_WIDTH)] = sig_b.size();
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(B), sig_b);
|
cell->setPort(ID::B, sig_b);
|
||||||
cell->setPort(ID(Y), sig_y);
|
cell->setPort(ID::Y, sig_y);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
@ -2042,8 +2042,8 @@ RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, RTLIL::SigSpec sig_a, R
|
||||||
RTLIL::Cell *cell = addCell(name, ID($lut));
|
RTLIL::Cell *cell = addCell(name, ID($lut));
|
||||||
cell->parameters[ID(LUT)] = lut;
|
cell->parameters[ID(LUT)] = lut;
|
||||||
cell->parameters[ID(WIDTH)] = sig_a.size();
|
cell->parameters[ID(WIDTH)] = sig_a.size();
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(Y), sig_y);
|
cell->setPort(ID::Y, sig_y);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
@ -2052,9 +2052,9 @@ RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, RTLIL::SigSpec sig_a
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = addCell(name, ID($tribuf));
|
RTLIL::Cell *cell = addCell(name, ID($tribuf));
|
||||||
cell->parameters[ID(WIDTH)] = sig_a.size();
|
cell->parameters[ID(WIDTH)] = sig_a.size();
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(EN), sig_en);
|
cell->setPort(ID(EN), sig_en);
|
||||||
cell->setPort(ID(Y), sig_y);
|
cell->setPort(ID::Y, sig_y);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
@ -2062,7 +2062,7 @@ RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, RTLIL::SigSpec sig_a
|
||||||
RTLIL::Cell* RTLIL::Module::addAssert(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
RTLIL::Cell* RTLIL::Module::addAssert(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = addCell(name, ID($assert));
|
RTLIL::Cell *cell = addCell(name, ID($assert));
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(EN), sig_en);
|
cell->setPort(ID(EN), sig_en);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
|
@ -2071,7 +2071,7 @@ RTLIL::Cell* RTLIL::Module::addAssert(RTLIL::IdString name, RTLIL::SigSpec sig_a
|
||||||
RTLIL::Cell* RTLIL::Module::addAssume(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
RTLIL::Cell* RTLIL::Module::addAssume(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = addCell(name, ID($assume));
|
RTLIL::Cell *cell = addCell(name, ID($assume));
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(EN), sig_en);
|
cell->setPort(ID(EN), sig_en);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
|
@ -2080,7 +2080,7 @@ RTLIL::Cell* RTLIL::Module::addAssume(RTLIL::IdString name, RTLIL::SigSpec sig_a
|
||||||
RTLIL::Cell* RTLIL::Module::addLive(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
RTLIL::Cell* RTLIL::Module::addLive(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = addCell(name, ID($live));
|
RTLIL::Cell *cell = addCell(name, ID($live));
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(EN), sig_en);
|
cell->setPort(ID(EN), sig_en);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
|
@ -2089,7 +2089,7 @@ RTLIL::Cell* RTLIL::Module::addLive(RTLIL::IdString name, RTLIL::SigSpec sig_a,
|
||||||
RTLIL::Cell* RTLIL::Module::addFair(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
RTLIL::Cell* RTLIL::Module::addFair(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = addCell(name, ID($fair));
|
RTLIL::Cell *cell = addCell(name, ID($fair));
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(EN), sig_en);
|
cell->setPort(ID(EN), sig_en);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
|
@ -2098,7 +2098,7 @@ RTLIL::Cell* RTLIL::Module::addFair(RTLIL::IdString name, RTLIL::SigSpec sig_a,
|
||||||
RTLIL::Cell* RTLIL::Module::addCover(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
RTLIL::Cell* RTLIL::Module::addCover(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = addCell(name, ID($cover));
|
RTLIL::Cell *cell = addCell(name, ID($cover));
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(EN), sig_en);
|
cell->setPort(ID(EN), sig_en);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
|
@ -2107,9 +2107,9 @@ RTLIL::Cell* RTLIL::Module::addCover(RTLIL::IdString name, RTLIL::SigSpec sig_a,
|
||||||
RTLIL::Cell* RTLIL::Module::addEquiv(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src)
|
RTLIL::Cell* RTLIL::Module::addEquiv(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *cell = addCell(name, ID($equiv));
|
RTLIL::Cell *cell = addCell(name, ID($equiv));
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(B), sig_b);
|
cell->setPort(ID::B, sig_b);
|
||||||
cell->setPort(ID(Y), sig_y);
|
cell->setPort(ID::Y, sig_y);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
@ -2308,7 +2308,7 @@ RTLIL::SigSpec RTLIL::Module::Anyconst(RTLIL::IdString name, int width, const st
|
||||||
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
||||||
Cell *cell = addCell(name, ID($anyconst));
|
Cell *cell = addCell(name, ID($anyconst));
|
||||||
cell->setParam(ID(WIDTH), width);
|
cell->setParam(ID(WIDTH), width);
|
||||||
cell->setPort(ID(Y), sig);
|
cell->setPort(ID::Y, sig);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
@ -2318,7 +2318,7 @@ RTLIL::SigSpec RTLIL::Module::Anyseq(RTLIL::IdString name, int width, const std:
|
||||||
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
||||||
Cell *cell = addCell(name, ID($anyseq));
|
Cell *cell = addCell(name, ID($anyseq));
|
||||||
cell->setParam(ID(WIDTH), width);
|
cell->setParam(ID(WIDTH), width);
|
||||||
cell->setPort(ID(Y), sig);
|
cell->setPort(ID::Y, sig);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
@ -2328,7 +2328,7 @@ RTLIL::SigSpec RTLIL::Module::Allconst(RTLIL::IdString name, int width, const st
|
||||||
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
||||||
Cell *cell = addCell(name, ID($allconst));
|
Cell *cell = addCell(name, ID($allconst));
|
||||||
cell->setParam(ID(WIDTH), width);
|
cell->setParam(ID(WIDTH), width);
|
||||||
cell->setPort(ID(Y), sig);
|
cell->setPort(ID::Y, sig);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
@ -2338,7 +2338,7 @@ RTLIL::SigSpec RTLIL::Module::Allseq(RTLIL::IdString name, int width, const std:
|
||||||
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
RTLIL::SigSpec sig = addWire(NEW_ID, width);
|
||||||
Cell *cell = addCell(name, ID($allseq));
|
Cell *cell = addCell(name, ID($allseq));
|
||||||
cell->setParam(ID(WIDTH), width);
|
cell->setParam(ID(WIDTH), width);
|
||||||
cell->setPort(ID(Y), sig);
|
cell->setPort(ID::Y, sig);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
@ -2347,7 +2347,7 @@ RTLIL::SigSpec RTLIL::Module::Initstate(RTLIL::IdString name, const std::string
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig = addWire(NEW_ID);
|
RTLIL::SigSpec sig = addWire(NEW_ID);
|
||||||
Cell *cell = addCell(name, ID($initstate));
|
Cell *cell = addCell(name, ID($initstate));
|
||||||
cell->setPort(ID(Y), sig);
|
cell->setPort(ID::Y, sig);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
@ -2569,7 +2569,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (type == ID($mux) || type == ID($pmux)) {
|
if (type == ID($mux) || type == ID($pmux)) {
|
||||||
parameters[ID(WIDTH)] = GetSize(connections_[ID(Y)]);
|
parameters[ID(WIDTH)] = GetSize(connections_[ID::Y]);
|
||||||
if (type == ID($pmux))
|
if (type == ID($pmux))
|
||||||
parameters[ID(S_WIDTH)] = GetSize(connections_[ID(S)]);
|
parameters[ID(S_WIDTH)] = GetSize(connections_[ID(S)]);
|
||||||
check();
|
check();
|
||||||
|
@ -2577,12 +2577,12 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == ID($lut) || type == ID($sop)) {
|
if (type == ID($lut) || type == ID($sop)) {
|
||||||
parameters[ID(WIDTH)] = GetSize(connections_[ID(A)]);
|
parameters[ID(WIDTH)] = GetSize(connections_[ID::A]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == ID($fa)) {
|
if (type == ID($fa)) {
|
||||||
parameters[ID(WIDTH)] = GetSize(connections_[ID(Y)]);
|
parameters[ID(WIDTH)] = GetSize(connections_[ID::Y]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2593,28 +2593,28 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
|
||||||
|
|
||||||
bool signedness_ab = !type.in(ID($slice), ID($concat), ID($macc));
|
bool signedness_ab = !type.in(ID($slice), ID($concat), ID($macc));
|
||||||
|
|
||||||
if (connections_.count(ID(A))) {
|
if (connections_.count(ID::A)) {
|
||||||
if (signedness_ab) {
|
if (signedness_ab) {
|
||||||
if (set_a_signed)
|
if (set_a_signed)
|
||||||
parameters[ID(A_SIGNED)] = true;
|
parameters[ID(A_SIGNED)] = true;
|
||||||
else if (parameters.count(ID(A_SIGNED)) == 0)
|
else if (parameters.count(ID(A_SIGNED)) == 0)
|
||||||
parameters[ID(A_SIGNED)] = false;
|
parameters[ID(A_SIGNED)] = false;
|
||||||
}
|
}
|
||||||
parameters[ID(A_WIDTH)] = GetSize(connections_[ID(A)]);
|
parameters[ID(A_WIDTH)] = GetSize(connections_[ID::A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connections_.count(ID(B))) {
|
if (connections_.count(ID::B)) {
|
||||||
if (signedness_ab) {
|
if (signedness_ab) {
|
||||||
if (set_b_signed)
|
if (set_b_signed)
|
||||||
parameters[ID(B_SIGNED)] = true;
|
parameters[ID(B_SIGNED)] = true;
|
||||||
else if (parameters.count(ID(B_SIGNED)) == 0)
|
else if (parameters.count(ID(B_SIGNED)) == 0)
|
||||||
parameters[ID(B_SIGNED)] = false;
|
parameters[ID(B_SIGNED)] = false;
|
||||||
}
|
}
|
||||||
parameters[ID(B_WIDTH)] = GetSize(connections_[ID(B)]);
|
parameters[ID(B_WIDTH)] = GetSize(connections_[ID::B]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connections_.count(ID(Y)))
|
if (connections_.count(ID::Y))
|
||||||
parameters[ID(Y_WIDTH)] = GetSize(connections_[ID(Y)]);
|
parameters[ID(Y_WIDTH)] = GetSize(connections_[ID::Y]);
|
||||||
|
|
||||||
if (connections_.count(ID(Q)))
|
if (connections_.count(ID(Q)))
|
||||||
parameters[ID(WIDTH)] = GetSize(connections_[ID(Q)]);
|
parameters[ID(WIDTH)] = GetSize(connections_[ID(Q)]);
|
||||||
|
|
236
kernel/satgen.h
236
kernel/satgen.h
|
@ -281,9 +281,9 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod)) || is_arith_compare))
|
if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod)) || is_arith_compare))
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
if (is_arith_compare)
|
if (is_arith_compare)
|
||||||
extendSignalWidth(undef_a, undef_b, cell, true);
|
extendSignalWidth(undef_a, undef_b, cell, true);
|
||||||
else
|
else
|
||||||
|
@ -294,7 +294,7 @@ struct SatGen
|
||||||
int undef_y_bit = ez->OR(undef_any_a, undef_any_b);
|
int undef_y_bit = ez->OR(undef_any_a, undef_any_b);
|
||||||
|
|
||||||
if (cell->type.in(ID($div), ID($mod))) {
|
if (cell->type.in(ID($div), ID($mod))) {
|
||||||
std::vector<int> b = importSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importSigSpec(cell->getPort(ID::B), timestep);
|
||||||
undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b)));
|
undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,9 +313,9 @@ struct SatGen
|
||||||
if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_),
|
if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_),
|
||||||
ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($sub)))
|
ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($sub)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidth(a, b, y, cell);
|
extendSignalWidth(a, b, y, cell);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
@ -343,9 +343,9 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef && !arith_undef_handled)
|
if (model_undef && !arith_undef_handled)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidth(undef_a, undef_b, undef_y, cell, false);
|
extendSignalWidth(undef_a, undef_b, undef_y, cell, false);
|
||||||
|
|
||||||
if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_))) {
|
if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_))) {
|
||||||
|
@ -384,7 +384,7 @@ struct SatGen
|
||||||
}
|
}
|
||||||
else if (model_undef)
|
else if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
undefGating(y, yy, undef_y);
|
undefGating(y, yy, undef_y);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -395,11 +395,11 @@ struct SatGen
|
||||||
bool aoi_mode = cell->type.in(ID($_AOI3_), ID($_AOI4_));
|
bool aoi_mode = cell->type.in(ID($_AOI3_), ID($_AOI4_));
|
||||||
bool three_mode = cell->type.in(ID($_AOI3_), ID($_OAI3_));
|
bool three_mode = cell->type.in(ID($_AOI3_), ID($_OAI3_));
|
||||||
|
|
||||||
int a = importDefSigSpec(cell->getPort(ID(A)), timestep).at(0);
|
int a = importDefSigSpec(cell->getPort(ID::A), timestep).at(0);
|
||||||
int b = importDefSigSpec(cell->getPort(ID(B)), timestep).at(0);
|
int b = importDefSigSpec(cell->getPort(ID::B), timestep).at(0);
|
||||||
int c = importDefSigSpec(cell->getPort(ID(C)), timestep).at(0);
|
int c = importDefSigSpec(cell->getPort(ID(C)), timestep).at(0);
|
||||||
int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort(ID(D)), timestep).at(0);
|
int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort(ID(D)), timestep).at(0);
|
||||||
int y = importDefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
|
int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0);
|
||||||
int yy = model_undef ? ez->literal() : y;
|
int yy = model_undef ? ez->literal() : y;
|
||||||
|
|
||||||
if (cell->type.in(ID($_AOI3_), ID($_AOI4_)))
|
if (cell->type.in(ID($_AOI3_), ID($_AOI4_)))
|
||||||
|
@ -409,11 +409,11 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
int undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep).at(0);
|
int undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep).at(0);
|
||||||
int undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep).at(0);
|
int undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep).at(0);
|
||||||
int undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep).at(0);
|
int undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep).at(0);
|
||||||
int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort(ID(D)), timestep).at(0);
|
int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort(ID(D)), timestep).at(0);
|
||||||
int undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
|
int undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep).at(0);
|
||||||
|
|
||||||
if (aoi_mode)
|
if (aoi_mode)
|
||||||
{
|
{
|
||||||
|
@ -458,16 +458,16 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($_NOT_), ID($not)))
|
if (cell->type.in(ID($_NOT_), ID($not)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidthUnary(a, y, cell);
|
extendSignalWidthUnary(a, y, cell);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
ez->assume(ez->vec_eq(ez->vec_not(a), yy));
|
ez->assume(ez->vec_eq(ez->vec_not(a), yy));
|
||||||
|
|
||||||
if (model_undef) {
|
if (model_undef) {
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidthUnary(undef_a, undef_y, cell, false);
|
extendSignalWidthUnary(undef_a, undef_y, cell, false);
|
||||||
ez->assume(ez->vec_eq(undef_a, undef_y));
|
ez->assume(ez->vec_eq(undef_a, undef_y));
|
||||||
undefGating(y, yy, undef_y);
|
undefGating(y, yy, undef_y);
|
||||||
|
@ -477,10 +477,10 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($_MUX_), ID($mux), ID($_NMUX_)))
|
if (cell->type.in(ID($_MUX_), ID($mux), ID($_NMUX_)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> s = importDefSigSpec(cell->getPort(ID(S)), timestep);
|
std::vector<int> s = importDefSigSpec(cell->getPort(ID(S)), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
if (cell->type == ID($_NMUX_))
|
if (cell->type == ID($_NMUX_))
|
||||||
|
@ -490,10 +490,10 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep);
|
std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a, b));
|
std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a, b));
|
||||||
std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a, undef_b));
|
std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a, undef_b));
|
||||||
|
@ -506,10 +506,10 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($pmux))
|
if (cell->type == ID($pmux))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> s = importDefSigSpec(cell->getPort(ID(S)), timestep);
|
std::vector<int> s = importDefSigSpec(cell->getPort(ID(S)), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
|
||||||
|
@ -522,10 +522,10 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep);
|
std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
int maybe_a = ez->CONST_TRUE;
|
int maybe_a = ez->CONST_TRUE;
|
||||||
|
|
||||||
|
@ -557,8 +557,8 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($pos), ID($neg)))
|
if (cell->type.in(ID($pos), ID($neg)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidthUnary(a, y, cell);
|
extendSignalWidthUnary(a, y, cell);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
@ -572,8 +572,8 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidthUnary(undef_a, undef_y, cell);
|
extendSignalWidthUnary(undef_a, undef_y, cell);
|
||||||
|
|
||||||
if (cell->type == ID($pos)) {
|
if (cell->type == ID($pos)) {
|
||||||
|
@ -591,8 +591,8 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($logic_not)))
|
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($logic_not)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
|
||||||
|
@ -611,8 +611,8 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
int aX = ez->expression(ezSAT::OpOr, undef_a);
|
int aX = ez->expression(ezSAT::OpOr, undef_a);
|
||||||
|
|
||||||
if (cell->type == ID($reduce_and)) {
|
if (cell->type == ID($reduce_and)) {
|
||||||
|
@ -638,12 +638,12 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($logic_and), ID($logic_or)))
|
if (cell->type.in(ID($logic_and), ID($logic_or)))
|
||||||
{
|
{
|
||||||
std::vector<int> vec_a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> vec_a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> vec_b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> vec_b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
|
|
||||||
int a = ez->expression(ez->OpOr, vec_a);
|
int a = ez->expression(ez->OpOr, vec_a);
|
||||||
int b = ez->expression(ez->OpOr, vec_b);
|
int b = ez->expression(ez->OpOr, vec_b);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
|
||||||
|
@ -656,9 +656,9 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
int a0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_a), ez->expression(ezSAT::OpOr, undef_a)));
|
int a0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_a), ez->expression(ezSAT::OpOr, undef_a)));
|
||||||
int b0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_b), ez->expression(ezSAT::OpOr, undef_b)));
|
int b0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_b), ez->expression(ezSAT::OpOr, undef_b)));
|
||||||
|
@ -685,16 +685,16 @@ struct SatGen
|
||||||
if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt)))
|
if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt)))
|
||||||
{
|
{
|
||||||
bool is_signed = cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool();
|
bool is_signed = cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool();
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidth(a, b, cell);
|
extendSignalWidth(a, b, cell);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
|
||||||
if (model_undef && cell->type.in(ID($eqx), ID($nex))) {
|
if (model_undef && cell->type.in(ID($eqx), ID($nex))) {
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
extendSignalWidth(undef_a, undef_b, cell, true);
|
extendSignalWidth(undef_a, undef_b, cell, true);
|
||||||
a = ez->vec_or(a, undef_a);
|
a = ez->vec_or(a, undef_a);
|
||||||
b = ez->vec_or(b, undef_b);
|
b = ez->vec_or(b, undef_b);
|
||||||
|
@ -717,9 +717,9 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef && cell->type.in(ID($eqx), ID($nex)))
|
if (model_undef && cell->type.in(ID($eqx), ID($nex)))
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidth(undef_a, undef_b, cell, true);
|
extendSignalWidth(undef_a, undef_b, cell, true);
|
||||||
|
|
||||||
if (cell->type == ID($eqx))
|
if (cell->type == ID($eqx))
|
||||||
|
@ -734,9 +734,9 @@ struct SatGen
|
||||||
}
|
}
|
||||||
else if (model_undef && cell->type.in(ID($eq), ID($ne)))
|
else if (model_undef && cell->type.in(ID($eq), ID($ne)))
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidth(undef_a, undef_b, cell, true);
|
extendSignalWidth(undef_a, undef_b, cell, true);
|
||||||
|
|
||||||
int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
|
int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
|
||||||
|
@ -758,7 +758,7 @@ struct SatGen
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (model_undef) {
|
if (model_undef) {
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
undefGating(y, yy, undef_y);
|
undefGating(y, yy, undef_y);
|
||||||
}
|
}
|
||||||
log_assert(!model_undef || arith_undef_handled);
|
log_assert(!model_undef || arith_undef_handled);
|
||||||
|
@ -768,9 +768,9 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
int extend_bit = ez->CONST_FALSE;
|
int extend_bit = ez->CONST_FALSE;
|
||||||
|
|
||||||
|
@ -801,9 +801,9 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
std::vector<int> undef_a_shifted;
|
std::vector<int> undef_a_shifted;
|
||||||
|
|
||||||
extend_bit = cell->type == ID($shiftx) ? ez->CONST_TRUE : ez->CONST_FALSE;
|
extend_bit = cell->type == ID($shiftx) ? ez->CONST_TRUE : ez->CONST_FALSE;
|
||||||
|
@ -840,9 +840,9 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($mul))
|
if (cell->type == ID($mul))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidth(a, b, y, cell);
|
extendSignalWidth(a, b, y, cell);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
@ -859,7 +859,7 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef) {
|
if (model_undef) {
|
||||||
log_assert(arith_undef_handled);
|
log_assert(arith_undef_handled);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
undefGating(y, yy, undef_y);
|
undefGating(y, yy, undef_y);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -867,9 +867,9 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($macc))
|
if (cell->type == ID($macc))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
Macc macc;
|
Macc macc;
|
||||||
macc.from_cell(cell);
|
macc.from_cell(cell);
|
||||||
|
@ -918,13 +918,13 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
|
|
||||||
int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
|
int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
|
||||||
int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
|
int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
|
||||||
|
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
ez->assume(ez->vec_eq(undef_y, std::vector<int>(GetSize(y), ez->OR(undef_any_a, undef_any_b))));
|
ez->assume(ez->vec_eq(undef_y, std::vector<int>(GetSize(y), ez->OR(undef_any_a, undef_any_b))));
|
||||||
|
|
||||||
undefGating(y, tmp, undef_y);
|
undefGating(y, tmp, undef_y);
|
||||||
|
@ -937,9 +937,9 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($div), ID($mod)))
|
if (cell->type.in(ID($div), ID($mod)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidth(a, b, y, cell);
|
extendSignalWidth(a, b, y, cell);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
@ -993,11 +993,11 @@ struct SatGen
|
||||||
only_first_one.at(0) = ez->CONST_TRUE;
|
only_first_one.at(0) = ez->CONST_TRUE;
|
||||||
div_zero_result = ez->vec_ite(a.back(), only_first_one, all_ones);
|
div_zero_result = ez->vec_ite(a.back(), only_first_one, all_ones);
|
||||||
} else {
|
} else {
|
||||||
div_zero_result.insert(div_zero_result.end(), cell->getPort(ID(A)).size(), ez->CONST_TRUE);
|
div_zero_result.insert(div_zero_result.end(), cell->getPort(ID::A).size(), ez->CONST_TRUE);
|
||||||
div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
|
div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int copy_a_bits = min(cell->getPort(ID(A)).size(), cell->getPort(ID(B)).size());
|
int copy_a_bits = min(cell->getPort(ID::A).size(), cell->getPort(ID::B).size());
|
||||||
div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits);
|
div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits);
|
||||||
if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool())
|
if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool())
|
||||||
div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back());
|
div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back());
|
||||||
|
@ -1009,7 +1009,7 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef) {
|
if (model_undef) {
|
||||||
log_assert(arith_undef_handled);
|
log_assert(arith_undef_handled);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
undefGating(y, yy, undef_y);
|
undefGating(y, yy, undef_y);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1017,8 +1017,8 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($lut))
|
if (cell->type == ID($lut))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
std::vector<int> lut;
|
std::vector<int> lut;
|
||||||
for (auto bit : cell->getParam(ID(LUT)).bits)
|
for (auto bit : cell->getParam(ID(LUT)).bits)
|
||||||
|
@ -1029,7 +1029,7 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> t(lut), u(GetSize(t), ez->CONST_FALSE);
|
std::vector<int> t(lut), u(GetSize(t), ez->CONST_FALSE);
|
||||||
|
|
||||||
for (int i = GetSize(a)-1; i >= 0; i--)
|
for (int i = GetSize(a)-1; i >= 0; i--)
|
||||||
|
@ -1047,7 +1047,7 @@ struct SatGen
|
||||||
log_assert(GetSize(t) == 1);
|
log_assert(GetSize(t) == 1);
|
||||||
log_assert(GetSize(u) == 1);
|
log_assert(GetSize(u) == 1);
|
||||||
undefGating(y, t, u);
|
undefGating(y, t, u);
|
||||||
ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort(ID(Y)), timestep), u));
|
ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort(ID::Y), timestep), u));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1067,8 +1067,8 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($sop))
|
if (cell->type == ID($sop))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
int y = importDefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
|
int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0);
|
||||||
|
|
||||||
int width = cell->getParam(ID(WIDTH)).as_int();
|
int width = cell->getParam(ID(WIDTH)).as_int();
|
||||||
int depth = cell->getParam(ID(DEPTH)).as_int();
|
int depth = cell->getParam(ID(DEPTH)).as_int();
|
||||||
|
@ -1096,8 +1096,8 @@ struct SatGen
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> products, undef_products;
|
std::vector<int> products, undef_products;
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
int undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
|
int undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep).at(0);
|
||||||
|
|
||||||
for (int i = 0; i < depth; i++)
|
for (int i = 0; i < depth; i++)
|
||||||
{
|
{
|
||||||
|
@ -1149,10 +1149,10 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($fa))
|
if (cell->type == ID($fa))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> c = importDefSigSpec(cell->getPort(ID(C)), timestep);
|
std::vector<int> c = importDefSigSpec(cell->getPort(ID(C)), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
std::vector<int> x = importDefSigSpec(cell->getPort(ID(X)), timestep);
|
std::vector<int> x = importDefSigSpec(cell->getPort(ID(X)), timestep);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
|
@ -1167,11 +1167,11 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep);
|
std::vector<int> undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep);
|
||||||
|
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep);
|
std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep);
|
||||||
|
|
||||||
ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c)));
|
ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c)));
|
||||||
|
@ -1217,9 +1217,9 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($alu))
|
if (cell->type == ID($alu))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
std::vector<int> x = importDefSigSpec(cell->getPort(ID(X)), timestep);
|
std::vector<int> x = importDefSigSpec(cell->getPort(ID(X)), timestep);
|
||||||
std::vector<int> ci = importDefSigSpec(cell->getPort(ID(CI)), timestep);
|
std::vector<int> ci = importDefSigSpec(cell->getPort(ID(CI)), timestep);
|
||||||
std::vector<int> bi = importDefSigSpec(cell->getPort(ID(BI)), timestep);
|
std::vector<int> bi = importDefSigSpec(cell->getPort(ID(BI)), timestep);
|
||||||
|
@ -1248,12 +1248,12 @@ struct SatGen
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
|
std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
|
||||||
std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID(CI)), timestep);
|
std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID(CI)), timestep);
|
||||||
std::vector<int> undef_bi = importUndefSigSpec(cell->getPort(ID(BI)), timestep);
|
std::vector<int> undef_bi = importUndefSigSpec(cell->getPort(ID(BI)), timestep);
|
||||||
|
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep);
|
std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep);
|
||||||
std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID(CO)), timestep);
|
std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID(CO)), timestep);
|
||||||
|
|
||||||
|
@ -1283,17 +1283,17 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type == ID($slice))
|
if (cell->type == ID($slice))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec a = cell->getPort(ID(A));
|
RTLIL::SigSpec a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec y = cell->getPort(ID(Y));
|
RTLIL::SigSpec y = cell->getPort(ID::Y);
|
||||||
ez->assume(signals_eq(a.extract(cell->parameters.at(ID(OFFSET)).as_int(), y.size()), y, timestep));
|
ez->assume(signals_eq(a.extract(cell->parameters.at(ID(OFFSET)).as_int(), y.size()), y, timestep));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($concat))
|
if (cell->type == ID($concat))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec a = cell->getPort(ID(A));
|
RTLIL::SigSpec a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec b = cell->getPort(ID(B));
|
RTLIL::SigSpec b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec y = cell->getPort(ID(Y));
|
RTLIL::SigSpec y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
RTLIL::SigSpec ab = a;
|
RTLIL::SigSpec ab = a;
|
||||||
ab.append(b);
|
ab.append(b);
|
||||||
|
@ -1333,16 +1333,16 @@ struct SatGen
|
||||||
if (timestep < 2)
|
if (timestep < 2)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
std::vector<int> d = importDefSigSpec(cell->getPort(ID(Y)), timestep-1);
|
std::vector<int> d = importDefSigSpec(cell->getPort(ID::Y), timestep-1);
|
||||||
std::vector<int> q = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> q = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
|
std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
|
||||||
ez->assume(ez->vec_eq(d, qq));
|
ez->assume(ez->vec_eq(d, qq));
|
||||||
|
|
||||||
if (model_undef)
|
if (model_undef)
|
||||||
{
|
{
|
||||||
std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID(Y)), timestep-1);
|
std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID::Y), timestep-1);
|
||||||
std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
|
|
||||||
ez->assume(ez->vec_eq(undef_d, undef_q));
|
ez->assume(ez->vec_eq(undef_d, undef_q));
|
||||||
undefGating(q, qq, undef_q);
|
undefGating(q, qq, undef_q);
|
||||||
|
@ -1357,16 +1357,16 @@ struct SatGen
|
||||||
|
|
||||||
if (cell->type.in(ID($_BUF_), ID($equiv)))
|
if (cell->type.in(ID($_BUF_), ID($equiv)))
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidthUnary(a, y, cell);
|
extendSignalWidthUnary(a, y, cell);
|
||||||
|
|
||||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||||
ez->assume(ez->vec_eq(a, yy));
|
ez->assume(ez->vec_eq(a, yy));
|
||||||
|
|
||||||
if (model_undef) {
|
if (model_undef) {
|
||||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
|
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
extendSignalWidthUnary(undef_a, undef_y, cell, false);
|
extendSignalWidthUnary(undef_a, undef_y, cell, false);
|
||||||
ez->assume(ez->vec_eq(undef_a, undef_y));
|
ez->assume(ez->vec_eq(undef_a, undef_y));
|
||||||
undefGating(y, yy, undef_y);
|
undefGating(y, yy, undef_y);
|
||||||
|
@ -1380,12 +1380,12 @@ struct SatGen
|
||||||
if (initstates.count(key) == 0)
|
if (initstates.count(key) == 0)
|
||||||
initstates[key] = false;
|
initstates[key] = false;
|
||||||
|
|
||||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
log_assert(GetSize(y) == 1);
|
log_assert(GetSize(y) == 1);
|
||||||
ez->SET(y[0], initstates[key] ? ez->CONST_TRUE : ez->CONST_FALSE);
|
ez->SET(y[0], initstates[key] ? ez->CONST_TRUE : ez->CONST_FALSE);
|
||||||
|
|
||||||
if (model_undef) {
|
if (model_undef) {
|
||||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
|
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||||
log_assert(GetSize(undef_y) == 1);
|
log_assert(GetSize(undef_y) == 1);
|
||||||
ez->SET(undef_y[0], ez->CONST_FALSE);
|
ez->SET(undef_y[0], ez->CONST_FALSE);
|
||||||
}
|
}
|
||||||
|
@ -1396,7 +1396,7 @@ struct SatGen
|
||||||
if (cell->type == ID($assert))
|
if (cell->type == ID($assert))
|
||||||
{
|
{
|
||||||
std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
|
std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
|
||||||
asserts_a[pf].append((*sigmap)(cell->getPort(ID(A))));
|
asserts_a[pf].append((*sigmap)(cell->getPort(ID::A)));
|
||||||
asserts_en[pf].append((*sigmap)(cell->getPort(ID(EN))));
|
asserts_en[pf].append((*sigmap)(cell->getPort(ID(EN))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1404,7 +1404,7 @@ struct SatGen
|
||||||
if (cell->type == ID($assume))
|
if (cell->type == ID($assume))
|
||||||
{
|
{
|
||||||
std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
|
std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
|
||||||
assumes_a[pf].append((*sigmap)(cell->getPort(ID(A))));
|
assumes_a[pf].append((*sigmap)(cell->getPort(ID::A)));
|
||||||
assumes_en[pf].append((*sigmap)(cell->getPort(ID(EN))));
|
assumes_en[pf].append((*sigmap)(cell->getPort(ID(EN))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -315,6 +315,7 @@ RTLIL::IdString new_id(std::string file, int line, std::string func);
|
||||||
//
|
//
|
||||||
#define ID(_id) ([]() { const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
|
#define ID(_id) ([]() { const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
|
||||||
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
|
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
|
||||||
|
namespace ID = RTLIL::ID;
|
||||||
|
|
||||||
RTLIL::Design *yosys_get_design();
|
RTLIL::Design *yosys_get_design();
|
||||||
std::string proc_self_dirname();
|
std::string proc_self_dirname();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -4,6 +4,7 @@ OBJS += passes/opt/opt_merge.o
|
||||||
OBJS += passes/opt/opt_muxtree.o
|
OBJS += passes/opt/opt_muxtree.o
|
||||||
OBJS += passes/opt/opt_reduce.o
|
OBJS += passes/opt/opt_reduce.o
|
||||||
OBJS += passes/opt/opt_rmdff.o
|
OBJS += passes/opt/opt_rmdff.o
|
||||||
|
OBJS += passes/opt/opt_share.o
|
||||||
OBJS += passes/opt/opt_clean.o
|
OBJS += passes/opt/opt_clean.o
|
||||||
OBJS += passes/opt/opt_expr.o
|
OBJS += passes/opt/opt_expr.o
|
||||||
|
|
||||||
|
@ -16,4 +17,3 @@ OBJS += passes/opt/opt_lut.o
|
||||||
OBJS += passes/opt/pmux2shiftx.o
|
OBJS += passes/opt/pmux2shiftx.o
|
||||||
OBJS += passes/opt/muxpack.o
|
OBJS += passes/opt/muxpack.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -38,19 +38,19 @@ struct ExclusiveDatabase
|
||||||
pool<Cell*> reduce_or;
|
pool<Cell*> reduce_or;
|
||||||
for (auto cell : module->cells()) {
|
for (auto cell : module->cells()) {
|
||||||
if (cell->type == ID($eq)) {
|
if (cell->type == ID($eq)) {
|
||||||
nonconst_sig = sigmap(cell->getPort(ID(A)));
|
nonconst_sig = sigmap(cell->getPort(ID::A));
|
||||||
const_sig = sigmap(cell->getPort(ID(B)));
|
const_sig = sigmap(cell->getPort(ID::B));
|
||||||
if (!const_sig.is_fully_const()) {
|
if (!const_sig.is_fully_const()) {
|
||||||
if (!nonconst_sig.is_fully_const())
|
if (!nonconst_sig.is_fully_const())
|
||||||
continue;
|
continue;
|
||||||
std::swap(nonconst_sig, const_sig);
|
std::swap(nonconst_sig, const_sig);
|
||||||
}
|
}
|
||||||
y_port = sigmap(cell->getPort(ID(Y)));
|
y_port = sigmap(cell->getPort(ID::Y));
|
||||||
}
|
}
|
||||||
else if (cell->type == ID($logic_not)) {
|
else if (cell->type == ID($logic_not)) {
|
||||||
nonconst_sig = sigmap(cell->getPort(ID(A)));
|
nonconst_sig = sigmap(cell->getPort(ID::A));
|
||||||
const_sig = Const(State::S0, GetSize(nonconst_sig));
|
const_sig = Const(State::S0, GetSize(nonconst_sig));
|
||||||
y_port = sigmap(cell->getPort(ID(Y)));
|
y_port = sigmap(cell->getPort(ID::Y));
|
||||||
}
|
}
|
||||||
else if (cell->type == ID($reduce_or)) {
|
else if (cell->type == ID($reduce_or)) {
|
||||||
reduce_or.insert(cell);
|
reduce_or.insert(cell);
|
||||||
|
@ -66,7 +66,7 @@ struct ExclusiveDatabase
|
||||||
for (auto cell : reduce_or) {
|
for (auto cell : reduce_or) {
|
||||||
nonconst_sig = SigSpec();
|
nonconst_sig = SigSpec();
|
||||||
std::vector<Const> values;
|
std::vector<Const> values;
|
||||||
SigSpec a_port = sigmap(cell->getPort(ID(A)));
|
SigSpec a_port = sigmap(cell->getPort(ID::A));
|
||||||
for (auto bit : a_port) {
|
for (auto bit : a_port) {
|
||||||
auto it = sig_cmp_prev.find(bit);
|
auto it = sig_cmp_prev.find(bit);
|
||||||
if (it == sig_cmp_prev.end()) {
|
if (it == sig_cmp_prev.end()) {
|
||||||
|
@ -84,7 +84,7 @@ struct ExclusiveDatabase
|
||||||
}
|
}
|
||||||
if (nonconst_sig.empty())
|
if (nonconst_sig.empty())
|
||||||
continue;
|
continue;
|
||||||
y_port = sigmap(cell->getPort(ID(Y)));
|
y_port = sigmap(cell->getPort(ID::Y));
|
||||||
sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values));
|
sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ struct MuxpackWorker
|
||||||
{
|
{
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
{
|
{
|
||||||
if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
|
if (wire->port_output || wire->get_bool_attribute(ID::keep)) {
|
||||||
for (auto bit : sigmap(wire))
|
for (auto bit : sigmap(wire))
|
||||||
sigbit_with_non_chain_users.insert(bit);
|
sigbit_with_non_chain_users.insert(bit);
|
||||||
}
|
}
|
||||||
|
@ -143,13 +143,13 @@ struct MuxpackWorker
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
{
|
{
|
||||||
if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID(keep)))
|
if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID::keep))
|
||||||
{
|
{
|
||||||
SigSpec a_sig = sigmap(cell->getPort(ID(A)));
|
SigSpec a_sig = sigmap(cell->getPort(ID::A));
|
||||||
SigSpec b_sig;
|
SigSpec b_sig;
|
||||||
if (cell->type == ID($mux))
|
if (cell->type == ID($mux))
|
||||||
b_sig = sigmap(cell->getPort(ID(B)));
|
b_sig = sigmap(cell->getPort(ID::B));
|
||||||
SigSpec y_sig = sigmap(cell->getPort(ID(Y)));
|
SigSpec y_sig = sigmap(cell->getPort(ID::Y));
|
||||||
|
|
||||||
if (sig_chain_next.count(a_sig))
|
if (sig_chain_next.count(a_sig))
|
||||||
for (auto a_bit : a_sig.bits())
|
for (auto a_bit : a_sig.bits())
|
||||||
|
@ -186,9 +186,9 @@ struct MuxpackWorker
|
||||||
{
|
{
|
||||||
log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
|
log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
|
||||||
|
|
||||||
SigSpec a_sig = sigmap(cell->getPort(ID(A)));
|
SigSpec a_sig = sigmap(cell->getPort(ID::A));
|
||||||
if (cell->type == ID($mux)) {
|
if (cell->type == ID($mux)) {
|
||||||
SigSpec b_sig = sigmap(cell->getPort(ID(B)));
|
SigSpec b_sig = sigmap(cell->getPort(ID::B));
|
||||||
if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
|
if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
|
||||||
goto start_cell;
|
goto start_cell;
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ struct MuxpackWorker
|
||||||
{
|
{
|
||||||
chain.push_back(c);
|
chain.push_back(c);
|
||||||
|
|
||||||
SigSpec y_sig = sigmap(c->getPort(ID(Y)));
|
SigSpec y_sig = sigmap(c->getPort(ID::Y));
|
||||||
|
|
||||||
if (sig_chain_next.count(y_sig) == 0)
|
if (sig_chain_next.count(y_sig) == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -270,28 +270,28 @@ struct MuxpackWorker
|
||||||
pmux_count += 1;
|
pmux_count += 1;
|
||||||
|
|
||||||
first_cell->type = ID($pmux);
|
first_cell->type = ID($pmux);
|
||||||
SigSpec b_sig = first_cell->getPort(ID(B));
|
SigSpec b_sig = first_cell->getPort(ID::B);
|
||||||
SigSpec s_sig = first_cell->getPort(ID(S));
|
SigSpec s_sig = first_cell->getPort(ID(S));
|
||||||
|
|
||||||
for (int i = 1; i < cases; i++) {
|
for (int i = 1; i < cases; i++) {
|
||||||
Cell* prev_cell = chain[cursor+i-1];
|
Cell* prev_cell = chain[cursor+i-1];
|
||||||
Cell* cursor_cell = chain[cursor+i];
|
Cell* cursor_cell = chain[cursor+i];
|
||||||
if (sigmap(prev_cell->getPort(ID(Y))) == sigmap(cursor_cell->getPort(ID(A)))) {
|
if (sigmap(prev_cell->getPort(ID::Y)) == sigmap(cursor_cell->getPort(ID::A))) {
|
||||||
b_sig.append(cursor_cell->getPort(ID(B)));
|
b_sig.append(cursor_cell->getPort(ID::B));
|
||||||
s_sig.append(cursor_cell->getPort(ID(S)));
|
s_sig.append(cursor_cell->getPort(ID(S)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log_assert(cursor_cell->type == ID($mux));
|
log_assert(cursor_cell->type == ID($mux));
|
||||||
b_sig.append(cursor_cell->getPort(ID(A)));
|
b_sig.append(cursor_cell->getPort(ID::A));
|
||||||
s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S))));
|
s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S))));
|
||||||
}
|
}
|
||||||
remove_cells.insert(cursor_cell);
|
remove_cells.insert(cursor_cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
first_cell->setPort(ID(B), b_sig);
|
first_cell->setPort(ID::B, b_sig);
|
||||||
first_cell->setPort(ID(S), s_sig);
|
first_cell->setPort(ID(S), s_sig);
|
||||||
first_cell->setParam(ID(S_WIDTH), GetSize(s_sig));
|
first_cell->setParam(ID(S_WIDTH), GetSize(s_sig));
|
||||||
first_cell->setPort(ID(Y), last_cell->getPort(ID(Y)));
|
first_cell->setPort(ID::Y, last_cell->getPort(ID::Y));
|
||||||
|
|
||||||
cursor += cases;
|
cursor += cases;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ struct OptPass : public Pass {
|
||||||
log(" opt_muxtree\n");
|
log(" opt_muxtree\n");
|
||||||
log(" opt_reduce [-fine] [-full]\n");
|
log(" opt_reduce [-fine] [-full]\n");
|
||||||
log(" opt_merge [-share_all]\n");
|
log(" opt_merge [-share_all]\n");
|
||||||
|
log(" opt_share (-full only)\n");
|
||||||
log(" opt_rmdff [-keepdc] [-sat]\n");
|
log(" opt_rmdff [-keepdc] [-sat]\n");
|
||||||
log(" opt_clean [-purge]\n");
|
log(" opt_clean [-purge]\n");
|
||||||
log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
|
log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
|
||||||
|
@ -70,6 +71,7 @@ struct OptPass : public Pass {
|
||||||
std::string opt_reduce_args;
|
std::string opt_reduce_args;
|
||||||
std::string opt_merge_args;
|
std::string opt_merge_args;
|
||||||
std::string opt_rmdff_args;
|
std::string opt_rmdff_args;
|
||||||
|
bool opt_share = false;
|
||||||
bool fast_mode = false;
|
bool fast_mode = false;
|
||||||
|
|
||||||
log_header(design, "Executing OPT pass (performing simple optimizations).\n");
|
log_header(design, "Executing OPT pass (performing simple optimizations).\n");
|
||||||
|
@ -105,6 +107,7 @@ struct OptPass : public Pass {
|
||||||
if (args[argidx] == "-full") {
|
if (args[argidx] == "-full") {
|
||||||
opt_expr_args += " -full";
|
opt_expr_args += " -full";
|
||||||
opt_reduce_args += " -full";
|
opt_reduce_args += " -full";
|
||||||
|
opt_share = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-keepdc") {
|
if (args[argidx] == "-keepdc") {
|
||||||
|
@ -151,6 +154,8 @@ struct OptPass : public Pass {
|
||||||
Pass::call(design, "opt_muxtree");
|
Pass::call(design, "opt_muxtree");
|
||||||
Pass::call(design, "opt_reduce" + opt_reduce_args);
|
Pass::call(design, "opt_reduce" + opt_reduce_args);
|
||||||
Pass::call(design, "opt_merge" + opt_merge_args);
|
Pass::call(design, "opt_merge" + opt_merge_args);
|
||||||
|
if (opt_share)
|
||||||
|
Pass::call(design, "opt_share");
|
||||||
Pass::call(design, "opt_rmdff" + opt_rmdff_args);
|
Pass::call(design, "opt_rmdff" + opt_rmdff_args);
|
||||||
Pass::call(design, "opt_clean" + opt_clean_args);
|
Pass::call(design, "opt_clean" + opt_clean_args);
|
||||||
Pass::call(design, "opt_expr" + opt_expr_args);
|
Pass::call(design, "opt_expr" + opt_expr_args);
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct keep_cache_t
|
||||||
return cache.at(module);
|
return cache.at(module);
|
||||||
|
|
||||||
cache[module] = true;
|
cache[module] = true;
|
||||||
if (!module->get_bool_attribute(ID(keep))) {
|
if (!module->get_bool_attribute(ID::keep)) {
|
||||||
bool found_keep = false;
|
bool found_keep = false;
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
if (query(cell)) found_keep = true;
|
if (query(cell)) found_keep = true;
|
||||||
|
@ -122,7 +122,7 @@ void rmunused_module_cells(Module *module, bool verbose)
|
||||||
|
|
||||||
for (auto &it : module->wires_) {
|
for (auto &it : module->wires_) {
|
||||||
Wire *wire = it.second;
|
Wire *wire = it.second;
|
||||||
if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
|
if (wire->port_output || wire->get_bool_attribute(ID::keep)) {
|
||||||
for (auto bit : sigmap(wire))
|
for (auto bit : sigmap(wire))
|
||||||
for (auto c : wire2driver[bit])
|
for (auto c : wire2driver[bit])
|
||||||
queue.insert(c), unused.erase(c);
|
queue.insert(c), unused.erase(c);
|
||||||
|
@ -297,7 +297,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
||||||
if (!wire->port_input)
|
if (!wire->port_input)
|
||||||
used_signals_nodrivers.add(sig);
|
used_signals_nodrivers.add(sig);
|
||||||
}
|
}
|
||||||
if (wire->get_bool_attribute(ID(keep))) {
|
if (wire->get_bool_attribute(ID::keep)) {
|
||||||
RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
|
RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
|
||||||
assign_map.apply(sig);
|
assign_map.apply(sig);
|
||||||
used_signals.add(sig);
|
used_signals.add(sig);
|
||||||
|
@ -323,7 +323,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
||||||
if (wire->port_id == 0)
|
if (wire->port_id == 0)
|
||||||
goto delete_this_wire;
|
goto delete_this_wire;
|
||||||
} else
|
} else
|
||||||
if (wire->port_id != 0 || wire->get_bool_attribute(ID(keep)) || !initval.is_fully_undef()) {
|
if (wire->port_id != 0 || wire->get_bool_attribute(ID::keep) || !initval.is_fully_undef()) {
|
||||||
// do not delete anything with "keep" or module ports or initialized wires
|
// do not delete anything with "keep" or module ports or initialized wires
|
||||||
} else
|
} else
|
||||||
if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) {
|
if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) {
|
||||||
|
@ -482,8 +482,8 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) {
|
if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) {
|
||||||
bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
RTLIL::SigSpec a = cell->getPort(ID(A));
|
RTLIL::SigSpec a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec y = cell->getPort(ID(Y));
|
RTLIL::SigSpec y = cell->getPort(ID::Y);
|
||||||
a.extend_u0(GetSize(y), is_signed);
|
a.extend_u0(GetSize(y), is_signed);
|
||||||
module->connect(y, a);
|
module->connect(y, a);
|
||||||
delcells.push_back(cell);
|
delcells.push_back(cell);
|
||||||
|
@ -491,7 +491,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
|
||||||
for (auto cell : delcells) {
|
for (auto cell : delcells) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
|
log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
|
||||||
log_signal(cell->getPort(ID(Y))), log_signal(cell->getPort(ID(A))));
|
log_signal(cell->getPort(ID::Y)), log_signal(cell->getPort(ID::A)));
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
}
|
}
|
||||||
if (!delcells.empty())
|
if (!delcells.empty())
|
||||||
|
|
|
@ -38,7 +38,7 @@ void demorgan_worker(
|
||||||
if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) )
|
if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto insig = sigmap(cell->getPort(ID(A)));
|
auto insig = sigmap(cell->getPort(ID::A));
|
||||||
log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig));
|
log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig));
|
||||||
int num_inverted = 0;
|
int num_inverted = 0;
|
||||||
for(int i=0; i<GetSize(insig); i++)
|
for(int i=0; i<GetSize(insig); i++)
|
||||||
|
@ -51,7 +51,7 @@ void demorgan_worker(
|
||||||
bool inverted = false;
|
bool inverted = false;
|
||||||
for(auto x : ports)
|
for(auto x : ports)
|
||||||
{
|
{
|
||||||
if(x.port == ID(Y) && x.cell->type == ID($_NOT_))
|
if(x.port == ID::Y && x.cell->type == ID($_NOT_))
|
||||||
{
|
{
|
||||||
inverted = true;
|
inverted = true;
|
||||||
break;
|
break;
|
||||||
|
@ -85,7 +85,7 @@ void demorgan_worker(
|
||||||
RTLIL::Cell* srcinv = NULL;
|
RTLIL::Cell* srcinv = NULL;
|
||||||
for(auto x : ports)
|
for(auto x : ports)
|
||||||
{
|
{
|
||||||
if(x.port == ID(Y) && x.cell->type == ID($_NOT_))
|
if(x.port == ID::Y && x.cell->type == ID($_NOT_))
|
||||||
{
|
{
|
||||||
srcinv = x.cell;
|
srcinv = x.cell;
|
||||||
break;
|
break;
|
||||||
|
@ -103,7 +103,7 @@ void demorgan_worker(
|
||||||
//We ARE inverted - bypass it
|
//We ARE inverted - bypass it
|
||||||
//Don't automatically delete the inverter since other stuff might still use it
|
//Don't automatically delete the inverter since other stuff might still use it
|
||||||
else
|
else
|
||||||
insig[i] = srcinv->getPort(ID(A));
|
insig[i] = srcinv->getPort(ID::A);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Cosmetic fixup: If our input is just a scrambled version of one bus, rearrange it
|
//Cosmetic fixup: If our input is just a scrambled version of one bus, rearrange it
|
||||||
|
@ -151,7 +151,7 @@ void demorgan_worker(
|
||||||
}
|
}
|
||||||
|
|
||||||
//Push the new input signal back to the reduction (after bypassing/adding inverters)
|
//Push the new input signal back to the reduction (after bypassing/adding inverters)
|
||||||
cell->setPort(ID(A), insig);
|
cell->setPort(ID::A, insig);
|
||||||
|
|
||||||
//Change the cell type
|
//Change the cell type
|
||||||
if(cell->type == ID($reduce_and))
|
if(cell->type == ID($reduce_and))
|
||||||
|
@ -161,10 +161,10 @@ void demorgan_worker(
|
||||||
//don't change XOR
|
//don't change XOR
|
||||||
|
|
||||||
//Add an inverter to the output
|
//Add an inverter to the output
|
||||||
auto inverted_output = cell->getPort(ID(Y));
|
auto inverted_output = cell->getPort(ID::Y);
|
||||||
auto uninverted_output = m->addWire(NEW_ID);
|
auto uninverted_output = m->addWire(NEW_ID);
|
||||||
m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output);
|
m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output);
|
||||||
cell->setPort(ID(Y), uninverted_output);
|
cell->setPort(ID::Y, uninverted_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OptDemorganPass : public Pass {
|
struct OptDemorganPass : public Pass {
|
||||||
|
|
|
@ -61,7 +61,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
|
||||||
}
|
}
|
||||||
if (wire->port_input)
|
if (wire->port_input)
|
||||||
driven_signals.add(sigmap(wire));
|
driven_signals.add(sigmap(wire));
|
||||||
if (wire->port_output || wire->get_bool_attribute(ID(keep)))
|
if (wire->port_output || wire->get_bool_attribute(ID::keep))
|
||||||
used_signals.add(sigmap(wire));
|
used_signals.add(sigmap(wire));
|
||||||
all_signals.add(sigmap(wire));
|
all_signals.add(sigmap(wire));
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,8 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, IdString out_port, RTLIL::SigSpec out_val)
|
void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
|
||||||
|
const std::string &info YS_ATTRIBUTE(unused), IdString out_port, RTLIL::SigSpec out_val)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec Y = cell->getPort(out_port);
|
RTLIL::SigSpec Y = cell->getPort(out_port);
|
||||||
out_val.extend_u0(Y.size(), false);
|
out_val.extend_u0(Y.size(), false);
|
||||||
|
@ -134,14 +135,14 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
|
||||||
|
|
||||||
bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap)
|
bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap)
|
||||||
{
|
{
|
||||||
IdString b_name = cell->hasPort(ID(B)) ? ID(B) : ID(A);
|
IdString b_name = cell->hasPort(ID::B) ? ID::B : ID::A;
|
||||||
|
|
||||||
bool a_signed = cell->parameters.at(ID(A_SIGNED)).as_bool();
|
bool a_signed = cell->parameters.at(ID(A_SIGNED)).as_bool();
|
||||||
bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool();
|
bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool();
|
||||||
|
|
||||||
RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = sigmap(cell->getPort(b_name));
|
RTLIL::SigSpec sig_b = sigmap(cell->getPort(b_name));
|
||||||
RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID(Y)));
|
RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y));
|
||||||
|
|
||||||
sig_a.extend_u0(sig_y.size(), a_signed);
|
sig_a.extend_u0(sig_y.size(), a_signed);
|
||||||
sig_b.extend_u0(sig_y.size(), b_signed);
|
sig_b.extend_u0(sig_y.size(), b_signed);
|
||||||
|
@ -208,24 +209,24 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
||||||
|
|
||||||
RTLIL::Cell *c = module->addCell(NEW_ID, cell->type);
|
RTLIL::Cell *c = module->addCell(NEW_ID, cell->type);
|
||||||
|
|
||||||
c->setPort(ID(A), new_a);
|
c->setPort(ID::A, new_a);
|
||||||
c->parameters[ID(A_WIDTH)] = new_a.size();
|
c->parameters[ID(A_WIDTH)] = new_a.size();
|
||||||
c->parameters[ID(A_SIGNED)] = false;
|
c->parameters[ID(A_SIGNED)] = false;
|
||||||
|
|
||||||
if (b_name == ID(B)) {
|
if (b_name == ID::B) {
|
||||||
c->setPort(ID(B), new_b);
|
c->setPort(ID::B, new_b);
|
||||||
c->parameters[ID(B_WIDTH)] = new_b.size();
|
c->parameters[ID(B_WIDTH)] = new_b.size();
|
||||||
c->parameters[ID(B_SIGNED)] = false;
|
c->parameters[ID(B_SIGNED)] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->setPort(ID(Y), new_y);
|
c->setPort(ID::Y, new_y);
|
||||||
c->parameters[ID(Y_WIDTH)] = new_y->width;
|
c->parameters[ID(Y_WIDTH)] = new_y->width;
|
||||||
c->check();
|
c->check();
|
||||||
|
|
||||||
module->connect(new_conn);
|
module->connect(new_conn);
|
||||||
|
|
||||||
log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a));
|
log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a));
|
||||||
if (b_name == ID(B))
|
if (b_name == ID::B)
|
||||||
log_debug(", B=%s", log_signal(new_b));
|
log_debug(", B=%s", log_signal(new_b));
|
||||||
log_debug("\n");
|
log_debug("\n");
|
||||||
}
|
}
|
||||||
|
@ -368,11 +369,11 @@ 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))
|
||||||
invert_map[assign_map(cell->getPort(ID(Y)))] = assign_map(cell->getPort(ID(S)));
|
invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID(S)));
|
||||||
if (ct_combinational.cell_known(cell->type))
|
if (ct_combinational.cell_known(cell->type))
|
||||||
for (auto &conn : cell->connections()) {
|
for (auto &conn : cell->connections()) {
|
||||||
RTLIL::SigSpec sig = assign_map(conn.second);
|
RTLIL::SigSpec sig = assign_map(conn.second);
|
||||||
|
@ -396,7 +397,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
for (auto cell : cells.sorted)
|
for (auto cell : cells.sorted)
|
||||||
{
|
{
|
||||||
#define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
|
#define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
|
||||||
#define ACTION_DO_Y(_v_) ACTION_DO(ID(Y), RTLIL::SigSpec(RTLIL::State::S ## _v_))
|
#define ACTION_DO_Y(_v_) ACTION_DO(ID::Y, RTLIL::SigSpec(RTLIL::State::S ## _v_))
|
||||||
|
|
||||||
if (clkinv)
|
if (clkinv)
|
||||||
{
|
{
|
||||||
|
@ -439,23 +440,23 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (cell->type.in(ID($reduce_and), ID($_AND_)))
|
if (cell->type.in(ID($reduce_and), ID($_AND_)))
|
||||||
detect_const_and = true;
|
detect_const_and = true;
|
||||||
|
|
||||||
if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())
|
if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())
|
||||||
detect_const_and = true;
|
detect_const_and = true;
|
||||||
|
|
||||||
if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($_OR_)))
|
if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($_OR_)))
|
||||||
detect_const_or = true;
|
detect_const_or = true;
|
||||||
|
|
||||||
if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())
|
if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())
|
||||||
detect_const_or = true;
|
detect_const_or = true;
|
||||||
|
|
||||||
if (detect_const_and || detect_const_or)
|
if (detect_const_and || detect_const_or)
|
||||||
{
|
{
|
||||||
pool<SigBit> input_bits = assign_map(cell->getPort(ID(A))).to_sigbit_pool();
|
pool<SigBit> input_bits = assign_map(cell->getPort(ID::A)).to_sigbit_pool();
|
||||||
bool found_zero = false, found_one = false, found_undef = false, found_inv = false, many_conconst = false;
|
bool found_zero = false, found_one = false, found_undef = false, found_inv = false, many_conconst = false;
|
||||||
SigBit non_const_input = State::Sm;
|
SigBit non_const_input = State::Sm;
|
||||||
|
|
||||||
if (cell->hasPort(ID(B))) {
|
if (cell->hasPort(ID::B)) {
|
||||||
vector<SigBit> more_bits = assign_map(cell->getPort(ID(B))).to_sigbit_vector();
|
vector<SigBit> more_bits = assign_map(cell->getPort(ID::B)).to_sigbit_vector();
|
||||||
input_bits.insert(more_bits.begin(), more_bits.end());
|
input_bits.insert(more_bits.begin(), more_bits.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,25 +479,25 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (detect_const_and && (found_zero || found_inv)) {
|
if (detect_const_and && (found_zero || found_inv)) {
|
||||||
cover("opt.opt_expr.const_and");
|
cover("opt.opt_expr.const_and");
|
||||||
replace_cell(assign_map, module, cell, "const_and", ID(Y), RTLIL::State::S0);
|
replace_cell(assign_map, module, cell, "const_and", ID::Y, RTLIL::State::S0);
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detect_const_or && (found_one || found_inv)) {
|
if (detect_const_or && (found_one || found_inv)) {
|
||||||
cover("opt.opt_expr.const_or");
|
cover("opt.opt_expr.const_or");
|
||||||
replace_cell(assign_map, module, cell, "const_or", ID(Y), RTLIL::State::S1);
|
replace_cell(assign_map, module, cell, "const_or", ID::Y, RTLIL::State::S1);
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (non_const_input != State::Sm && !found_undef) {
|
if (non_const_input != State::Sm && !found_undef) {
|
||||||
cover("opt.opt_expr.and_or_buffer");
|
cover("opt.opt_expr.and_or_buffer");
|
||||||
replace_cell(assign_map, module, cell, "and_or_buffer", ID(Y), non_const_input);
|
replace_cell(assign_map, module, cell, "and_or_buffer", ID::Y, non_const_input);
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) &&
|
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) &&
|
||||||
GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(Y))) == 1)
|
GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1)
|
||||||
{
|
{
|
||||||
if (cell->type == ID($reduce_xnor)) {
|
if (cell->type == ID($reduce_xnor)) {
|
||||||
cover("opt.opt_expr.reduce_xnor_not");
|
cover("opt.opt_expr.reduce_xnor_not");
|
||||||
|
@ -506,7 +507,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
did_something = true;
|
did_something = true;
|
||||||
} else {
|
} else {
|
||||||
cover("opt.opt_expr.unary_buffer");
|
cover("opt.opt_expr.unary_buffer");
|
||||||
replace_cell(assign_map, module, cell, "unary_buffer", ID(Y), cell->getPort(ID(A)));
|
replace_cell(assign_map, module, cell, "unary_buffer", ID::Y, cell->getPort(ID::A));
|
||||||
}
|
}
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
@ -521,7 +522,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
{
|
{
|
||||||
SigBit neutral_bit = cell->type == ID($reduce_and) ? State::S1 : State::S0;
|
SigBit neutral_bit = cell->type == ID($reduce_and) ? State::S1 : State::S0;
|
||||||
|
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec new_sig_a;
|
RTLIL::SigSpec new_sig_a;
|
||||||
|
|
||||||
for (auto bit : sig_a)
|
for (auto bit : sig_a)
|
||||||
|
@ -534,7 +535,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str());
|
cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str());
|
||||||
log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
||||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a));
|
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a));
|
||||||
cell->setPort(ID(A), new_sig_a);
|
cell->setPort(ID::A, new_sig_a);
|
||||||
cell->parameters.at(ID(A_WIDTH)) = GetSize(new_sig_a);
|
cell->parameters.at(ID(A_WIDTH)) = GetSize(new_sig_a);
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +545,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
{
|
{
|
||||||
SigBit neutral_bit = State::S0;
|
SigBit neutral_bit = State::S0;
|
||||||
|
|
||||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
RTLIL::SigSpec new_sig_b;
|
RTLIL::SigSpec new_sig_b;
|
||||||
|
|
||||||
for (auto bit : sig_b)
|
for (auto bit : sig_b)
|
||||||
|
@ -557,7 +558,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str());
|
cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str());
|
||||||
log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
|
||||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b));
|
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b));
|
||||||
cell->setPort(ID(B), new_sig_b);
|
cell->setPort(ID::B, new_sig_b);
|
||||||
cell->parameters.at(ID(B_WIDTH)) = GetSize(new_sig_b);
|
cell->parameters.at(ID(B_WIDTH)) = GetSize(new_sig_b);
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
@ -565,7 +566,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type == ID($reduce_and))
|
if (cell->type == ID($reduce_and))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
|
|
||||||
RTLIL::State new_a = RTLIL::State::S1;
|
RTLIL::State new_a = RTLIL::State::S1;
|
||||||
for (auto &bit : sig_a.to_sigbit_vector())
|
for (auto &bit : sig_a.to_sigbit_vector())
|
||||||
|
@ -583,7 +584,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover("opt.opt_expr.fine.$reduce_and");
|
cover("opt.opt_expr.fine.$reduce_and");
|
||||||
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
|
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
|
||||||
cell->setPort(ID(A), sig_a = new_a);
|
cell->setPort(ID::A, sig_a = new_a);
|
||||||
cell->parameters.at(ID(A_WIDTH)) = 1;
|
cell->parameters.at(ID(A_WIDTH)) = 1;
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
@ -591,7 +592,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_bool)))
|
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_bool)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
|
|
||||||
RTLIL::State new_a = RTLIL::State::S0;
|
RTLIL::State new_a = RTLIL::State::S0;
|
||||||
for (auto &bit : sig_a.to_sigbit_vector())
|
for (auto &bit : sig_a.to_sigbit_vector())
|
||||||
|
@ -609,7 +610,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
|
cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
|
||||||
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
|
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
|
||||||
cell->setPort(ID(A), sig_a = new_a);
|
cell->setPort(ID::A, sig_a = new_a);
|
||||||
cell->parameters.at(ID(A_WIDTH)) = 1;
|
cell->parameters.at(ID(A_WIDTH)) = 1;
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
@ -617,7 +618,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type.in(ID($logic_and), ID($logic_or)))
|
if (cell->type.in(ID($logic_and), ID($logic_or)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
|
|
||||||
RTLIL::State new_b = RTLIL::State::S0;
|
RTLIL::State new_b = RTLIL::State::S0;
|
||||||
for (auto &bit : sig_b.to_sigbit_vector())
|
for (auto &bit : sig_b.to_sigbit_vector())
|
||||||
|
@ -635,7 +636,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
|
cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
|
||||||
log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
|
||||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
|
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
|
||||||
cell->setPort(ID(B), sig_b = new_b);
|
cell->setPort(ID::B, sig_b = new_b);
|
||||||
cell->parameters.at(ID(B_WIDTH)) = 1;
|
cell->parameters.at(ID(B_WIDTH)) = 1;
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
@ -643,9 +644,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type.in(ID($add), ID($sub)))
|
if (cell->type.in(ID($add), ID($sub)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
bool sub = cell->type == ID($sub);
|
bool sub = cell->type == ID($sub);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
@ -659,9 +660,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
}
|
}
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str());
|
cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str());
|
||||||
cell->setPort(ID(A), sig_a.extract_end(i));
|
cell->setPort(ID::A, sig_a.extract_end(i));
|
||||||
cell->setPort(ID(B), sig_b.extract_end(i));
|
cell->setPort(ID::B, sig_b.extract_end(i));
|
||||||
cell->setPort(ID(Y), sig_y.extract_end(i));
|
cell->setPort(ID::Y, sig_y.extract_end(i));
|
||||||
cell->fixup_parameters();
|
cell->fixup_parameters();
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
@ -669,12 +670,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type == "$alu")
|
if (cell->type == "$alu")
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID(CI)));
|
RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID(CI)));
|
||||||
RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID(BI)));
|
RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID(BI)));
|
||||||
RTLIL::SigSpec sig_x = cell->getPort(ID(X));
|
RTLIL::SigSpec sig_x = cell->getPort(ID(X));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
RTLIL::SigSpec sig_co = cell->getPort(ID(CO));
|
RTLIL::SigSpec sig_co = cell->getPort(ID(CO));
|
||||||
|
|
||||||
if (sig_ci.wire || sig_bi.wire)
|
if (sig_ci.wire || sig_bi.wire)
|
||||||
|
@ -704,10 +705,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
}
|
}
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
cover("opt.opt_expr.fine.$alu");
|
cover("opt.opt_expr.fine.$alu");
|
||||||
cell->setPort(ID(A), sig_a.extract_end(i));
|
cell->setPort(ID::A, sig_a.extract_end(i));
|
||||||
cell->setPort(ID(B), sig_b.extract_end(i));
|
cell->setPort(ID::B, sig_b.extract_end(i));
|
||||||
cell->setPort(ID(X), sig_x.extract_end(i));
|
cell->setPort(ID(X), sig_x.extract_end(i));
|
||||||
cell->setPort(ID(Y), sig_y.extract_end(i));
|
cell->setPort(ID::Y, sig_y.extract_end(i));
|
||||||
cell->setPort(ID(CO), sig_co.extract_end(i));
|
cell->setPort(ID(CO), sig_co.extract_end(i));
|
||||||
cell->fixup_parameters();
|
cell->fixup_parameters();
|
||||||
did_something = true;
|
did_something = true;
|
||||||
|
@ -718,8 +719,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr),
|
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr),
|
||||||
ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow)))
|
ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = cell->hasPort(ID(B)) ? assign_map(cell->getPort(ID(B))) : RTLIL::SigSpec();
|
RTLIL::SigSpec sig_b = cell->hasPort(ID::B) ? assign_map(cell->getPort(ID::B)) : RTLIL::SigSpec();
|
||||||
|
|
||||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
||||||
sig_a = RTLIL::SigSpec();
|
sig_a = RTLIL::SigSpec();
|
||||||
|
@ -737,33 +738,55 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
|
cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
|
||||||
"$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str());
|
"$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str());
|
||||||
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))) {
|
||||||
invert_map.count(assign_map(cell->getPort(ID(A)))) != 0) {
|
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) {
|
||||||
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))));
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID(S)))) != 0) {
|
if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID(S)))) != 0) {
|
||||||
cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
|
cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
|
||||||
log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
|
log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||||
RTLIL::SigSpec tmp = cell->getPort(ID(A));
|
RTLIL::SigSpec tmp = cell->getPort(ID::A);
|
||||||
cell->setPort(ID(A), cell->getPort(ID(B)));
|
cell->setPort(ID::A, cell->getPort(ID::B));
|
||||||
cell->setPort(ID(B), tmp);
|
cell->setPort(ID::B, tmp);
|
||||||
cell->setPort(ID(S), invert_map.at(assign_map(cell->getPort(ID(S)))));
|
cell->setPort(ID(S), invert_map.at(assign_map(cell->getPort(ID(S)))));
|
||||||
did_something = true;
|
did_something = true;
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_NOT_)) {
|
if (cell->type == ID($_NOT_)) {
|
||||||
RTLIL::SigSpec input = cell->getPort(ID(A));
|
RTLIL::SigSpec input = cell->getPort(ID::A);
|
||||||
assign_map.apply(input);
|
assign_map.apply(input);
|
||||||
if (input.match("1")) ACTION_DO_Y(0);
|
if (input.match("1")) ACTION_DO_Y(0);
|
||||||
if (input.match("0")) ACTION_DO_Y(1);
|
if (input.match("0")) ACTION_DO_Y(1);
|
||||||
|
@ -772,8 +795,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type == ID($_AND_)) {
|
if (cell->type == ID($_AND_)) {
|
||||||
RTLIL::SigSpec input;
|
RTLIL::SigSpec input;
|
||||||
input.append(cell->getPort(ID(B)));
|
input.append(cell->getPort(ID::B));
|
||||||
input.append(cell->getPort(ID(A)));
|
input.append(cell->getPort(ID::A));
|
||||||
assign_map.apply(input);
|
assign_map.apply(input);
|
||||||
if (input.match(" 0")) ACTION_DO_Y(0);
|
if (input.match(" 0")) ACTION_DO_Y(0);
|
||||||
if (input.match("0 ")) ACTION_DO_Y(0);
|
if (input.match("0 ")) ACTION_DO_Y(0);
|
||||||
|
@ -785,14 +808,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (input.match(" *")) ACTION_DO_Y(0);
|
if (input.match(" *")) ACTION_DO_Y(0);
|
||||||
if (input.match("* ")) ACTION_DO_Y(0);
|
if (input.match("* ")) ACTION_DO_Y(0);
|
||||||
}
|
}
|
||||||
if (input.match(" 1")) ACTION_DO(ID(Y), input.extract(1, 1));
|
if (input.match(" 1")) ACTION_DO(ID::Y, input.extract(1, 1));
|
||||||
if (input.match("1 ")) ACTION_DO(ID(Y), input.extract(0, 1));
|
if (input.match("1 ")) ACTION_DO(ID::Y, input.extract(0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_OR_)) {
|
if (cell->type == ID($_OR_)) {
|
||||||
RTLIL::SigSpec input;
|
RTLIL::SigSpec input;
|
||||||
input.append(cell->getPort(ID(B)));
|
input.append(cell->getPort(ID::B));
|
||||||
input.append(cell->getPort(ID(A)));
|
input.append(cell->getPort(ID::A));
|
||||||
assign_map.apply(input);
|
assign_map.apply(input);
|
||||||
if (input.match(" 1")) ACTION_DO_Y(1);
|
if (input.match(" 1")) ACTION_DO_Y(1);
|
||||||
if (input.match("1 ")) ACTION_DO_Y(1);
|
if (input.match("1 ")) ACTION_DO_Y(1);
|
||||||
|
@ -804,14 +827,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (input.match(" *")) ACTION_DO_Y(1);
|
if (input.match(" *")) ACTION_DO_Y(1);
|
||||||
if (input.match("* ")) ACTION_DO_Y(1);
|
if (input.match("* ")) ACTION_DO_Y(1);
|
||||||
}
|
}
|
||||||
if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1));
|
if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(1, 1));
|
||||||
if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1));
|
if (input.match("0 ")) ACTION_DO(ID::Y, input.extract(0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_XOR_)) {
|
if (cell->type == ID($_XOR_)) {
|
||||||
RTLIL::SigSpec input;
|
RTLIL::SigSpec input;
|
||||||
input.append(cell->getPort(ID(B)));
|
input.append(cell->getPort(ID::B));
|
||||||
input.append(cell->getPort(ID(A)));
|
input.append(cell->getPort(ID::A));
|
||||||
assign_map.apply(input);
|
assign_map.apply(input);
|
||||||
if (input.match("00")) ACTION_DO_Y(0);
|
if (input.match("00")) ACTION_DO_Y(0);
|
||||||
if (input.match("01")) ACTION_DO_Y(1);
|
if (input.match("01")) ACTION_DO_Y(1);
|
||||||
|
@ -819,26 +842,26 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (input.match("11")) ACTION_DO_Y(0);
|
if (input.match("11")) ACTION_DO_Y(0);
|
||||||
if (input.match(" *")) ACTION_DO_Y(x);
|
if (input.match(" *")) ACTION_DO_Y(x);
|
||||||
if (input.match("* ")) ACTION_DO_Y(x);
|
if (input.match("* ")) ACTION_DO_Y(x);
|
||||||
if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1));
|
if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(1, 1));
|
||||||
if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1));
|
if (input.match("0 ")) ACTION_DO(ID::Y, input.extract(0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_MUX_)) {
|
if (cell->type == ID($_MUX_)) {
|
||||||
RTLIL::SigSpec input;
|
RTLIL::SigSpec input;
|
||||||
input.append(cell->getPort(ID(S)));
|
input.append(cell->getPort(ID(S)));
|
||||||
input.append(cell->getPort(ID(B)));
|
input.append(cell->getPort(ID::B));
|
||||||
input.append(cell->getPort(ID(A)));
|
input.append(cell->getPort(ID::A));
|
||||||
assign_map.apply(input);
|
assign_map.apply(input);
|
||||||
if (input.extract(2, 1) == input.extract(1, 1))
|
if (input.extract(2, 1) == input.extract(1, 1))
|
||||||
ACTION_DO(ID(Y), input.extract(2, 1));
|
ACTION_DO(ID::Y, input.extract(2, 1));
|
||||||
if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(2, 1));
|
if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(2, 1));
|
||||||
if (input.match(" 1")) ACTION_DO(ID(Y), input.extract(1, 1));
|
if (input.match(" 1")) ACTION_DO(ID::Y, input.extract(1, 1));
|
||||||
if (input.match("01 ")) ACTION_DO(ID(Y), input.extract(0, 1));
|
if (input.match("01 ")) ACTION_DO(ID::Y, input.extract(0, 1));
|
||||||
if (input.match("10 ")) {
|
if (input.match("10 ")) {
|
||||||
cover("opt.opt_expr.mux_to_inv");
|
cover("opt.opt_expr.mux_to_inv");
|
||||||
cell->type = ID($_NOT_);
|
cell->type = ID($_NOT_);
|
||||||
cell->setPort(ID(A), input.extract(0, 1));
|
cell->setPort(ID::A, input.extract(0, 1));
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
cell->unsetPort(ID(S));
|
cell->unsetPort(ID(S));
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
@ -848,24 +871,24 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (input.match("01*")) ACTION_DO_Y(x);
|
if (input.match("01*")) ACTION_DO_Y(x);
|
||||||
if (input.match("10*")) ACTION_DO_Y(x);
|
if (input.match("10*")) ACTION_DO_Y(x);
|
||||||
if (mux_undef) {
|
if (mux_undef) {
|
||||||
if (input.match("* ")) ACTION_DO(ID(Y), input.extract(1, 1));
|
if (input.match("* ")) ACTION_DO(ID::Y, input.extract(1, 1));
|
||||||
if (input.match(" * ")) ACTION_DO(ID(Y), input.extract(2, 1));
|
if (input.match(" * ")) ACTION_DO(ID::Y, input.extract(2, 1));
|
||||||
if (input.match(" *")) ACTION_DO(ID(Y), input.extract(2, 1));
|
if (input.match(" *")) ACTION_DO(ID::Y, input.extract(2, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($_TBUF_), ID($tribuf))) {
|
if (cell->type.in(ID($_TBUF_), ID($tribuf))) {
|
||||||
RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? ID(E) : ID(EN));
|
RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? ID(E) : ID(EN));
|
||||||
RTLIL::SigSpec a = cell->getPort(ID(A));
|
RTLIL::SigSpec a = cell->getPort(ID::A);
|
||||||
assign_map.apply(input);
|
assign_map.apply(input);
|
||||||
assign_map.apply(a);
|
assign_map.apply(a);
|
||||||
if (input == State::S1)
|
if (input == State::S1)
|
||||||
ACTION_DO(ID(Y), cell->getPort(ID(A)));
|
ACTION_DO(ID::Y, cell->getPort(ID::A));
|
||||||
if (input == State::S0 && !a.is_fully_undef()) {
|
if (input == State::S0 && !a.is_fully_undef()) {
|
||||||
cover("opt.opt_expr.action_" S__LINE__);
|
cover("opt.opt_expr.action_" S__LINE__);
|
||||||
log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
|
log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
|
||||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str());
|
cell->type.c_str(), cell->name.c_str(), module->name.c_str());
|
||||||
cell->setPort(ID(A), SigSpec(State::Sx, GetSize(a)));
|
cell->setPort(ID::A, SigSpec(State::Sx, GetSize(a)));
|
||||||
did_something = true;
|
did_something = true;
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
@ -873,8 +896,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
|
if (cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec a = cell->getPort(ID(A));
|
RTLIL::SigSpec a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec b = cell->getPort(ID(B));
|
RTLIL::SigSpec b = cell->getPort(ID::B);
|
||||||
|
|
||||||
if (cell->parameters[ID(A_WIDTH)].as_int() != cell->parameters[ID(B_WIDTH)].as_int()) {
|
if (cell->parameters[ID(A_WIDTH)].as_int() != cell->parameters[ID(B_WIDTH)].as_int()) {
|
||||||
int width = max(cell->parameters[ID(A_WIDTH)].as_int(), cell->parameters[ID(B_WIDTH)].as_int());
|
int width = max(cell->parameters[ID(A_WIDTH)].as_int(), cell->parameters[ID(B_WIDTH)].as_int());
|
||||||
|
@ -890,7 +913,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
|
cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
|
||||||
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1);
|
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1);
|
||||||
new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false);
|
new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false);
|
||||||
replace_cell(assign_map, module, cell, "isneq", ID(Y), new_y);
|
replace_cell(assign_map, module, cell, "isneq", ID::Y, new_y);
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
if (a[i] == b[i])
|
if (a[i] == b[i])
|
||||||
|
@ -903,14 +926,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
|
cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
|
||||||
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0);
|
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0);
|
||||||
new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false);
|
new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false);
|
||||||
replace_cell(assign_map, module, cell, "empty", ID(Y), new_y);
|
replace_cell(assign_map, module, cell, "empty", ID::Y, new_y);
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_a.size() < a.size() || new_b.size() < b.size()) {
|
if (new_a.size() < a.size() || new_b.size() < b.size()) {
|
||||||
cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
|
cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
|
||||||
cell->setPort(ID(A), new_a);
|
cell->setPort(ID::A, new_a);
|
||||||
cell->setPort(ID(B), new_b);
|
cell->setPort(ID::B, new_b);
|
||||||
cell->parameters[ID(A_WIDTH)] = new_a.size();
|
cell->parameters[ID(A_WIDTH)] = new_a.size();
|
||||||
cell->parameters[ID(B_WIDTH)] = new_b.size();
|
cell->parameters[ID(B_WIDTH)] = new_b.size();
|
||||||
}
|
}
|
||||||
|
@ -919,27 +942,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID(Y_WIDTH)].as_int() == 1 &&
|
if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID(Y_WIDTH)].as_int() == 1 &&
|
||||||
cell->parameters[ID(A_WIDTH)].as_int() == 1 && cell->parameters[ID(B_WIDTH)].as_int() == 1)
|
cell->parameters[ID(A_WIDTH)].as_int() == 1 && cell->parameters[ID(B_WIDTH)].as_int() == 1)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec b = assign_map(cell->getPort(ID::B));
|
||||||
|
|
||||||
if (a.is_fully_const() && !b.is_fully_const()) {
|
if (a.is_fully_const() && !b.is_fully_const()) {
|
||||||
cover_list("opt.opt_expr.eqneq.swapconst", "$eq", "$ne", cell->type.str());
|
cover_list("opt.opt_expr.eqneq.swapconst", "$eq", "$ne", cell->type.str());
|
||||||
cell->setPort(ID(A), b);
|
cell->setPort(ID::A, b);
|
||||||
cell->setPort(ID(B), a);
|
cell->setPort(ID::B, a);
|
||||||
std::swap(a, b);
|
std::swap(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.is_fully_const()) {
|
if (b.is_fully_const()) {
|
||||||
if (b.as_bool() == (cell->type == ID($eq))) {
|
if (b.as_bool() == (cell->type == ID($eq))) {
|
||||||
RTLIL::SigSpec input = b;
|
RTLIL::SigSpec input = b;
|
||||||
ACTION_DO(ID(Y), cell->getPort(ID(A)));
|
ACTION_DO(ID::Y, cell->getPort(ID::A));
|
||||||
} else {
|
} else {
|
||||||
cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
|
cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
|
||||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||||
cell->type = ID($not);
|
cell->type = ID($not);
|
||||||
cell->parameters.erase(ID(B_WIDTH));
|
cell->parameters.erase(ID(B_WIDTH));
|
||||||
cell->parameters.erase(ID(B_SIGNED));
|
cell->parameters.erase(ID(B_SIGNED));
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
|
@ -947,33 +970,33 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($eq), ID($ne)) &&
|
if (cell->type.in(ID($eq), ID($ne)) &&
|
||||||
(assign_map(cell->getPort(ID(A))).is_fully_zero() || assign_map(cell->getPort(ID(B))).is_fully_zero()))
|
(assign_map(cell->getPort(ID::A)).is_fully_zero() || assign_map(cell->getPort(ID::B)).is_fully_zero()))
|
||||||
{
|
{
|
||||||
cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
|
cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
|
||||||
log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
|
log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
|
||||||
log_id(module), "$eq" ? "$logic_not" : "$reduce_bool");
|
log_id(module), "$eq" ? "$logic_not" : "$reduce_bool");
|
||||||
cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool);
|
cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool);
|
||||||
if (assign_map(cell->getPort(ID(A))).is_fully_zero()) {
|
if (assign_map(cell->getPort(ID::A)).is_fully_zero()) {
|
||||||
cell->setPort(ID(A), cell->getPort(ID(B)));
|
cell->setPort(ID::A, cell->getPort(ID::B));
|
||||||
cell->setParam(ID(A_SIGNED), cell->getParam(ID(B_SIGNED)));
|
cell->setParam(ID(A_SIGNED), cell->getParam(ID(B_SIGNED)));
|
||||||
cell->setParam(ID(A_WIDTH), cell->getParam(ID(B_WIDTH)));
|
cell->setParam(ID(A_WIDTH), cell->getParam(ID(B_WIDTH)));
|
||||||
}
|
}
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
cell->unsetParam(ID(B_SIGNED));
|
cell->unsetParam(ID(B_SIGNED));
|
||||||
cell->unsetParam(ID(B_WIDTH));
|
cell->unsetParam(ID(B_WIDTH));
|
||||||
did_something = true;
|
did_something = true;
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID(B))).is_fully_const())
|
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID::B)).is_fully_const())
|
||||||
{
|
{
|
||||||
bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID(A_SIGNED)).as_bool();
|
bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
int shift_bits = assign_map(cell->getPort(ID(B))).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID(B_SIGNED)).as_bool());
|
int shift_bits = assign_map(cell->getPort(ID::B)).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID(B_SIGNED)).as_bool());
|
||||||
|
|
||||||
if (cell->type.in(ID($shl), ID($sshl)))
|
if (cell->type.in(ID($shl), ID($sshl)))
|
||||||
shift_bits *= -1;
|
shift_bits *= -1;
|
||||||
|
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID(Y_WIDTH)).as_int());
|
RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID(Y_WIDTH)).as_int());
|
||||||
|
|
||||||
if (GetSize(sig_a) < GetSize(sig_y))
|
if (GetSize(sig_a) < GetSize(sig_y))
|
||||||
|
@ -990,9 +1013,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
|
cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
|
||||||
|
|
||||||
log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
|
log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
|
||||||
log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID(B)))), shift_bits, log_id(module), log_signal(sig_y));
|
log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID::B))), shift_bits, log_id(module), log_signal(sig_y));
|
||||||
|
|
||||||
module->connect(cell->getPort(ID(Y)), sig_y);
|
module->connect(cell->getPort(ID::Y), sig_y);
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
|
|
||||||
did_something = true;
|
did_something = true;
|
||||||
|
@ -1007,8 +1030,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type.in(ID($add), ID($sub), ID($or), ID($xor)))
|
if (cell->type.in(ID($add), ID($sub), ID($or), ID($xor)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec b = assign_map(cell->getPort(ID::B));
|
||||||
|
|
||||||
if (cell->type != ID($sub) && a.is_fully_const() && a.as_bool() == false)
|
if (cell->type != ID($sub) && a.is_fully_const() && a.as_bool() == false)
|
||||||
identity_wrt_b = true;
|
identity_wrt_b = true;
|
||||||
|
@ -1019,7 +1042,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec b = assign_map(cell->getPort(ID::B));
|
||||||
|
|
||||||
if (b.is_fully_const() && b.as_bool() == false)
|
if (b.is_fully_const() && b.as_bool() == false)
|
||||||
identity_wrt_a = true;
|
identity_wrt_a = true;
|
||||||
|
@ -1027,8 +1050,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type == ID($mul))
|
if (cell->type == ID($mul))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec b = assign_map(cell->getPort(ID::B));
|
||||||
|
|
||||||
if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam(ID(A_SIGNED)).as_bool(), arith_inverse))
|
if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam(ID(A_SIGNED)).as_bool(), arith_inverse))
|
||||||
identity_wrt_b = true;
|
identity_wrt_b = true;
|
||||||
|
@ -1039,7 +1062,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (cell->type == ID($div))
|
if (cell->type == ID($div))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec b = assign_map(cell->getPort(ID::B));
|
||||||
|
|
||||||
if (b.is_fully_const() && b.size() <= 32 && b.as_int() == 1)
|
if (b.is_fully_const() && b.size() <= 32 && b.as_int() == 1)
|
||||||
identity_wrt_a = true;
|
identity_wrt_a = true;
|
||||||
|
@ -1056,13 +1079,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
|
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
|
||||||
|
|
||||||
if (!identity_wrt_a) {
|
if (!identity_wrt_a) {
|
||||||
cell->setPort(ID(A), cell->getPort(ID(B)));
|
cell->setPort(ID::A, cell->getPort(ID::B));
|
||||||
cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH));
|
cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH));
|
||||||
cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED));
|
cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED));
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->type = arith_inverse ? ID($neg) : ID($pos);
|
cell->type = arith_inverse ? ID($neg) : ID($pos);
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
cell->parameters.erase(ID(B_WIDTH));
|
cell->parameters.erase(ID(B_WIDTH));
|
||||||
cell->parameters.erase(ID(B_SIGNED));
|
cell->parameters.erase(ID(B_SIGNED));
|
||||||
cell->check();
|
cell->check();
|
||||||
|
@ -1073,18 +1096,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
|
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
|
||||||
cell->getPort(ID(A)) == State::S0 && cell->getPort(ID(B)) == State::S1) {
|
cell->getPort(ID::A) == State::S0 && cell->getPort(ID::B) == State::S1) {
|
||||||
cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str());
|
cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str());
|
||||||
replace_cell(assign_map, module, cell, "mux_bool", ID(Y), cell->getPort(ID(S)));
|
replace_cell(assign_map, module, cell, "mux_bool", ID::Y, cell->getPort(ID(S)));
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
|
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
|
||||||
cell->getPort(ID(A)) == State::S1 && cell->getPort(ID(B)) == State::S0) {
|
cell->getPort(ID::A) == State::S1 && cell->getPort(ID::B) == State::S0) {
|
||||||
cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
|
cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
|
||||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||||
cell->setPort(ID(A), cell->getPort(ID(S)));
|
cell->setPort(ID::A, cell->getPort(ID(S)));
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
cell->unsetPort(ID(S));
|
cell->unsetPort(ID(S));
|
||||||
if (cell->type == ID($mux)) {
|
if (cell->type == ID($mux)) {
|
||||||
Const width = cell->parameters[ID(WIDTH)];
|
Const width = cell->parameters[ID(WIDTH)];
|
||||||
|
@ -1099,10 +1122,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(A)) == State::S0) {
|
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S0) {
|
||||||
cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
|
cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
|
||||||
log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||||
cell->setPort(ID(A), cell->getPort(ID(S)));
|
cell->setPort(ID::A, cell->getPort(ID(S)));
|
||||||
cell->unsetPort(ID(S));
|
cell->unsetPort(ID(S));
|
||||||
if (cell->type == ID($mux)) {
|
if (cell->type == ID($mux)) {
|
||||||
Const width = cell->parameters[ID(WIDTH)];
|
Const width = cell->parameters[ID(WIDTH)];
|
||||||
|
@ -1119,10 +1142,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(B)) == State::S1) {
|
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S1) {
|
||||||
cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
|
cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
|
||||||
log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
|
||||||
cell->setPort(ID(B), cell->getPort(ID(S)));
|
cell->setPort(ID::B, cell->getPort(ID(S)));
|
||||||
cell->unsetPort(ID(S));
|
cell->unsetPort(ID(S));
|
||||||
if (cell->type == ID($mux)) {
|
if (cell->type == ID($mux)) {
|
||||||
Const width = cell->parameters[ID(WIDTH)];
|
Const width = cell->parameters[ID(WIDTH)];
|
||||||
|
@ -1141,22 +1164,22 @@ 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());
|
||||||
replace_cell(assign_map, module, cell, "mux_undef", ID(Y), cell->getPort(ID(A)));
|
replace_cell(assign_map, module, cell, "mux_undef", ID::Y, cell->getPort(ID::A));
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < cell->getPort(ID(S)).size(); i++) {
|
for (int i = 0; i < cell->getPort(ID(S)).size(); i++) {
|
||||||
RTLIL::SigSpec old_b = cell->getPort(ID(B)).extract(i*width, width);
|
RTLIL::SigSpec old_b = cell->getPort(ID::B).extract(i*width, width);
|
||||||
RTLIL::SigSpec old_s = cell->getPort(ID(S)).extract(i, 1);
|
RTLIL::SigSpec old_s = cell->getPort(ID(S)).extract(i, 1);
|
||||||
if (old_b.is_fully_undef() || old_s.is_fully_undef())
|
if (old_b.is_fully_undef() || old_s.is_fully_undef())
|
||||||
continue;
|
continue;
|
||||||
new_b.append(old_b);
|
new_b.append(old_b);
|
||||||
new_s.append(old_s);
|
new_s.append(old_s);
|
||||||
}
|
}
|
||||||
new_a = cell->getPort(ID(A));
|
new_a = cell->getPort(ID::A);
|
||||||
if (new_a.is_fully_undef() && new_s.size() > 0) {
|
if (new_a.is_fully_undef() && new_s.size() > 0) {
|
||||||
new_a = new_b.extract((new_s.size()-1)*width, width);
|
new_a = new_b.extract((new_s.size()-1)*width, width);
|
||||||
new_b = new_b.extract(0, (new_s.size()-1)*width);
|
new_b = new_b.extract(0, (new_s.size()-1)*width);
|
||||||
|
@ -1164,20 +1187,20 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
}
|
}
|
||||||
if (new_s.size() == 0) {
|
if (new_s.size() == 0) {
|
||||||
cover_list("opt.opt_expr.mux_empty", "$mux", "$pmux", cell->type.str());
|
cover_list("opt.opt_expr.mux_empty", "$mux", "$pmux", cell->type.str());
|
||||||
replace_cell(assign_map, module, cell, "mux_empty", ID(Y), new_a);
|
replace_cell(assign_map, module, cell, "mux_empty", ID::Y, new_a);
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
if (new_a == RTLIL::SigSpec(RTLIL::State::S0) && new_b == RTLIL::SigSpec(RTLIL::State::S1)) {
|
if (new_a == RTLIL::SigSpec(RTLIL::State::S0) && new_b == RTLIL::SigSpec(RTLIL::State::S1)) {
|
||||||
cover_list("opt.opt_expr.mux_sel01", "$mux", "$pmux", cell->type.str());
|
cover_list("opt.opt_expr.mux_sel01", "$mux", "$pmux", cell->type.str());
|
||||||
replace_cell(assign_map, module, cell, "mux_sel01", ID(Y), new_s);
|
replace_cell(assign_map, module, cell, "mux_sel01", ID::Y, new_s);
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
if (cell->getPort(ID(S)).size() != new_s.size()) {
|
if (cell->getPort(ID(S)).size() != new_s.size()) {
|
||||||
cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
|
cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
|
||||||
log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
|
log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
|
||||||
GetSize(cell->getPort(ID(S))) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
|
GetSize(cell->getPort(ID(S))) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
|
||||||
cell->setPort(ID(A), new_a);
|
cell->setPort(ID::A, new_a);
|
||||||
cell->setPort(ID(B), new_b);
|
cell->setPort(ID::B, new_b);
|
||||||
cell->setPort(ID(S), new_s);
|
cell->setPort(ID(S), new_s);
|
||||||
if (new_s.size() > 1) {
|
if (new_s.size() > 1) {
|
||||||
cell->type = ID($pmux);
|
cell->type = ID($pmux);
|
||||||
|
@ -1192,7 +1215,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
#define FOLD_1ARG_CELL(_t) \
|
#define FOLD_1ARG_CELL(_t) \
|
||||||
if (cell->type == "$" #_t) { \
|
if (cell->type == "$" #_t) { \
|
||||||
RTLIL::SigSpec a = cell->getPort(ID(A)); \
|
RTLIL::SigSpec a = cell->getPort(ID::A); \
|
||||||
assign_map.apply(a); \
|
assign_map.apply(a); \
|
||||||
if (a.is_fully_const()) { \
|
if (a.is_fully_const()) { \
|
||||||
RTLIL::Const dummy_arg(RTLIL::State::S0, 1); \
|
RTLIL::Const dummy_arg(RTLIL::State::S0, 1); \
|
||||||
|
@ -1200,14 +1223,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cell->parameters[ID(A_SIGNED)].as_bool(), false, \
|
cell->parameters[ID(A_SIGNED)].as_bool(), false, \
|
||||||
cell->parameters[ID(Y_WIDTH)].as_int())); \
|
cell->parameters[ID(Y_WIDTH)].as_int())); \
|
||||||
cover("opt.opt_expr.const.$" #_t); \
|
cover("opt.opt_expr.const.$" #_t); \
|
||||||
replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID(Y), y); \
|
replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID::Y, y); \
|
||||||
goto next_cell; \
|
goto next_cell; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#define FOLD_2ARG_CELL(_t) \
|
#define FOLD_2ARG_CELL(_t) \
|
||||||
if (cell->type == "$" #_t) { \
|
if (cell->type == "$" #_t) { \
|
||||||
RTLIL::SigSpec a = cell->getPort(ID(A)); \
|
RTLIL::SigSpec a = cell->getPort(ID::A); \
|
||||||
RTLIL::SigSpec b = cell->getPort(ID(B)); \
|
RTLIL::SigSpec b = cell->getPort(ID::B); \
|
||||||
assign_map.apply(a), assign_map.apply(b); \
|
assign_map.apply(a), assign_map.apply(b); \
|
||||||
if (a.is_fully_const() && b.is_fully_const()) { \
|
if (a.is_fully_const() && b.is_fully_const()) { \
|
||||||
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), \
|
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), \
|
||||||
|
@ -1215,7 +1238,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cell->parameters[ID(B_SIGNED)].as_bool(), \
|
cell->parameters[ID(B_SIGNED)].as_bool(), \
|
||||||
cell->parameters[ID(Y_WIDTH)].as_int())); \
|
cell->parameters[ID(Y_WIDTH)].as_int())); \
|
||||||
cover("opt.opt_expr.const.$" #_t); \
|
cover("opt.opt_expr.const.$" #_t); \
|
||||||
replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID(Y), y); \
|
replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID::Y, y); \
|
||||||
goto next_cell; \
|
goto next_cell; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
@ -1263,12 +1286,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
// be very conservative with optimizing $mux cells as we do not want to break mux trees
|
// be very conservative with optimizing $mux cells as we do not want to break mux trees
|
||||||
if (cell->type == ID($mux)) {
|
if (cell->type == ID($mux)) {
|
||||||
RTLIL::SigSpec input = assign_map(cell->getPort(ID(S)));
|
RTLIL::SigSpec input = assign_map(cell->getPort(ID(S)));
|
||||||
RTLIL::SigSpec inA = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec inA = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec inB = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec inB = assign_map(cell->getPort(ID::B));
|
||||||
if (input.is_fully_const())
|
if (input.is_fully_const())
|
||||||
ACTION_DO(ID(Y), input.as_bool() ? cell->getPort(ID(B)) : cell->getPort(ID(A)));
|
ACTION_DO(ID::Y, input.as_bool() ? cell->getPort(ID::B) : cell->getPort(ID::A));
|
||||||
else if (inA == inB)
|
else if (inA == inB)
|
||||||
ACTION_DO(ID(Y), cell->getPort(ID(A)));
|
ACTION_DO(ID::Y, cell->getPort(ID::A));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keepdc && cell->type == ID($mul))
|
if (!keepdc && cell->type == ID($mul))
|
||||||
|
@ -1277,9 +1300,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool();
|
bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool();
|
||||||
bool swapped_ab = false;
|
bool swapped_ab = false;
|
||||||
|
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID(Y)));
|
RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
|
||||||
|
|
||||||
if (sig_b.is_fully_const() && sig_b.size() <= 32)
|
if (sig_b.is_fully_const() && sig_b.size() <= 32)
|
||||||
std::swap(sig_a, sig_b), std::swap(a_signed, b_signed), swapped_ab = true;
|
std::swap(sig_a, sig_b), std::swap(a_signed, b_signed), swapped_ab = true;
|
||||||
|
@ -1314,7 +1337,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
a_val, cell->name.c_str(), module->name.c_str(), i);
|
a_val, cell->name.c_str(), module->name.c_str(), i);
|
||||||
|
|
||||||
if (!swapped_ab) {
|
if (!swapped_ab) {
|
||||||
cell->setPort(ID(A), cell->getPort(ID(B)));
|
cell->setPort(ID::A, cell->getPort(ID::B));
|
||||||
cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH));
|
cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH));
|
||||||
cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED));
|
cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED));
|
||||||
}
|
}
|
||||||
|
@ -1327,7 +1350,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cell->type = ID($shl);
|
cell->type = ID($shl);
|
||||||
cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
|
cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
|
||||||
cell->parameters[ID(B_SIGNED)] = false;
|
cell->parameters[ID(B_SIGNED)] = false;
|
||||||
cell->setPort(ID(B), new_b);
|
cell->setPort(ID::B, new_b);
|
||||||
cell->check();
|
cell->check();
|
||||||
|
|
||||||
did_something = true;
|
did_something = true;
|
||||||
|
@ -1339,8 +1362,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (!keepdc && cell->type.in(ID($div), ID($mod)))
|
if (!keepdc && cell->type.in(ID($div), ID($mod)))
|
||||||
{
|
{
|
||||||
bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool();
|
bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool();
|
||||||
SigSpec sig_b = assign_map(cell->getPort(ID(B)));
|
SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
SigSpec sig_y = assign_map(cell->getPort(ID(Y)));
|
SigSpec sig_y = assign_map(cell->getPort(ID::Y));
|
||||||
|
|
||||||
if (sig_b.is_fully_def() && sig_b.size() <= 32)
|
if (sig_b.is_fully_def() && sig_b.size() <= 32)
|
||||||
{
|
{
|
||||||
|
@ -1378,7 +1401,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
cell->type = ID($shr);
|
cell->type = ID($shr);
|
||||||
cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
|
cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
|
||||||
cell->parameters[ID(B_SIGNED)] = false;
|
cell->parameters[ID(B_SIGNED)] = false;
|
||||||
cell->setPort(ID(B), new_b);
|
cell->setPort(ID::B, new_b);
|
||||||
cell->check();
|
cell->check();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1395,7 +1418,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
cell->type = ID($and);
|
cell->type = ID($and);
|
||||||
cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
|
cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
|
||||||
cell->setPort(ID(B), new_b);
|
cell->setPort(ID::B, new_b);
|
||||||
cell->check();
|
cell->check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1421,8 +1444,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
int width = is_signed ? std::min(a_width, b_width) : std::max(a_width, b_width);
|
int width = is_signed ? std::min(a_width, b_width) : std::max(a_width, b_width);
|
||||||
|
|
||||||
SigSpec sig_a = cell->getPort(ID(A));
|
SigSpec sig_a = cell->getPort(ID::A);
|
||||||
SigSpec sig_b = cell->getPort(ID(B));
|
SigSpec sig_b = cell->getPort(ID::B);
|
||||||
|
|
||||||
int redundant_bits = 0;
|
int redundant_bits = 0;
|
||||||
|
|
||||||
|
@ -1452,7 +1475,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
|
|
||||||
if (contradiction_cache.find(State::S0) == contradiction_cache.find(State::S1))
|
if (contradiction_cache.find(State::S0) == contradiction_cache.find(State::S1))
|
||||||
{
|
{
|
||||||
SigSpec y_sig = cell->getPort(ID(Y));
|
SigSpec y_sig = cell->getPort(ID::Y);
|
||||||
Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig));
|
Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig));
|
||||||
|
|
||||||
log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n",
|
log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n",
|
||||||
|
@ -1470,8 +1493,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
|
log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
|
||||||
redundant_bits, log_id(cell->type), log_id(cell), log_id(module));
|
redundant_bits, log_id(cell->type), log_id(cell), log_id(module));
|
||||||
|
|
||||||
cell->setPort(ID(A), sig_a);
|
cell->setPort(ID::A, sig_a);
|
||||||
cell->setPort(ID(B), sig_b);
|
cell->setPort(ID::B, sig_b);
|
||||||
cell->setParam(ID(A_WIDTH), GetSize(sig_a));
|
cell->setParam(ID(A_WIDTH), GetSize(sig_a));
|
||||||
cell->setParam(ID(B_WIDTH), GetSize(sig_b));
|
cell->setParam(ID(B_WIDTH), GetSize(sig_b));
|
||||||
|
|
||||||
|
@ -1484,8 +1507,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (do_fine && cell->type.in(ID($lt), ID($ge), ID($gt), ID($le)))
|
if (do_fine && cell->type.in(ID($lt), ID($ge), ID($gt), ID($le)))
|
||||||
{
|
{
|
||||||
IdString cmp_type = cell->type;
|
IdString cmp_type = cell->type;
|
||||||
SigSpec var_sig = cell->getPort(ID(A));
|
SigSpec var_sig = cell->getPort(ID::A);
|
||||||
SigSpec const_sig = cell->getPort(ID(B));
|
SigSpec const_sig = cell->getPort(ID::B);
|
||||||
int var_width = cell->parameters[ID(A_WIDTH)].as_int();
|
int var_width = cell->parameters[ID(A_WIDTH)].as_int();
|
||||||
int const_width = cell->parameters[ID(B_WIDTH)].as_int();
|
int const_width = cell->parameters[ID(B_WIDTH)].as_int();
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
|
@ -1507,7 +1530,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
if (const_sig.is_fully_def() && const_sig.is_fully_const())
|
if (const_sig.is_fully_def() && const_sig.is_fully_const())
|
||||||
{
|
{
|
||||||
std::string condition, replacement;
|
std::string condition, replacement;
|
||||||
SigSpec replace_sig(State::S0, GetSize(cell->getPort(ID(Y))));
|
SigSpec replace_sig(State::S0, GetSize(cell->getPort(ID::Y)));
|
||||||
bool replace = false;
|
bool replace = false;
|
||||||
bool remove = false;
|
bool remove = false;
|
||||||
|
|
||||||
|
@ -1550,14 +1573,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
{
|
{
|
||||||
condition = stringf("unsigned X<%s", log_signal(const_sig));
|
condition = stringf("unsigned X<%s", log_signal(const_sig));
|
||||||
replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot);
|
replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot);
|
||||||
module->addLogicNot(NEW_ID, var_high_sig, cell->getPort(ID(Y)));
|
module->addLogicNot(NEW_ID, var_high_sig, cell->getPort(ID::Y));
|
||||||
remove = true;
|
remove = true;
|
||||||
}
|
}
|
||||||
if (cmp_type == ID($ge))
|
if (cmp_type == ID($ge))
|
||||||
{
|
{
|
||||||
condition = stringf("unsigned X>=%s", log_signal(const_sig));
|
condition = stringf("unsigned X>=%s", log_signal(const_sig));
|
||||||
replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot);
|
replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot);
|
||||||
module->addReduceOr(NEW_ID, var_high_sig, cell->getPort(ID(Y)));
|
module->addReduceOr(NEW_ID, var_high_sig, cell->getPort(ID::Y));
|
||||||
remove = true;
|
remove = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1599,7 +1622,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
{
|
{
|
||||||
condition = "signed X>=0";
|
condition = "signed X>=0";
|
||||||
replacement = stringf("X[%d]", var_width - 1);
|
replacement = stringf("X[%d]", var_width - 1);
|
||||||
module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort(ID(Y)));
|
module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort(ID::Y));
|
||||||
remove = true;
|
remove = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1609,7 +1632,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
||||||
log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n",
|
log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n",
|
||||||
log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
|
log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
|
||||||
if (replace)
|
if (replace)
|
||||||
module->connect(cell->getPort(ID(Y)), replace_sig);
|
module->connect(cell->getPort(ID::Y), replace_sig);
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
did_something = true;
|
did_something = true;
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct OptLutWorker
|
||||||
|
|
||||||
bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
|
bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
|
||||||
{
|
{
|
||||||
SigSpec lut_input = sigmap(lut->getPort(ID(A)));
|
SigSpec lut_input = sigmap(lut->getPort(ID::A));
|
||||||
int lut_width = lut->getParam(ID(WIDTH)).as_int();
|
int lut_width = lut->getParam(ID(WIDTH)).as_int();
|
||||||
Const lut_table = lut->getParam(ID(LUT));
|
Const lut_table = lut->getParam(ID(LUT));
|
||||||
int lut_index = 0;
|
int lut_index = 0;
|
||||||
|
@ -103,12 +103,12 @@ struct OptLutWorker
|
||||||
{
|
{
|
||||||
if (cell->has_keep_attr())
|
if (cell->has_keep_attr())
|
||||||
continue;
|
continue;
|
||||||
SigBit lut_output = cell->getPort(ID(Y));
|
SigBit lut_output = cell->getPort(ID::Y);
|
||||||
if (lut_output.wire->get_bool_attribute(ID(keep)))
|
if (lut_output.wire->get_bool_attribute(ID::keep))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int lut_width = cell->getParam(ID(WIDTH)).as_int();
|
int lut_width = cell->getParam(ID(WIDTH)).as_int();
|
||||||
SigSpec lut_input = cell->getPort(ID(A));
|
SigSpec lut_input = cell->getPort(ID::A);
|
||||||
int lut_arity = 0;
|
int lut_arity = 0;
|
||||||
|
|
||||||
log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
|
log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
|
||||||
|
@ -205,7 +205,7 @@ struct OptLutWorker
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lut = worklist.pop();
|
auto lut = worklist.pop();
|
||||||
SigSpec lut_input = sigmap(lut->getPort(ID(A)));
|
SigSpec lut_input = sigmap(lut->getPort(ID::A));
|
||||||
pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
|
pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
|
||||||
|
|
||||||
vector<SigBit> lut_inputs;
|
vector<SigBit> lut_inputs;
|
||||||
|
@ -267,7 +267,7 @@ struct OptLutWorker
|
||||||
log_debug(" Not eliminating cell (connected to dedicated logic).\n");
|
log_debug(" Not eliminating cell (connected to dedicated logic).\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SigSpec lut_output = lut->getPort(ID(Y));
|
SigSpec lut_output = lut->getPort(ID::Y);
|
||||||
for (auto &port : index.query_ports(lut_output))
|
for (auto &port : index.query_ports(lut_output))
|
||||||
{
|
{
|
||||||
if (port.cell != lut && luts.count(port.cell))
|
if (port.cell != lut && luts.count(port.cell))
|
||||||
|
@ -303,13 +303,13 @@ struct OptLutWorker
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lutA = worklist.pop();
|
auto lutA = worklist.pop();
|
||||||
SigSpec lutA_input = sigmap(lutA->getPort(ID(A)));
|
SigSpec lutA_input = sigmap(lutA->getPort(ID::A));
|
||||||
SigSpec lutA_output = sigmap(lutA->getPort(ID(Y))[0]);
|
SigSpec lutA_output = sigmap(lutA->getPort(ID::Y)[0]);
|
||||||
int lutA_width = lutA->getParam(ID(WIDTH)).as_int();
|
int lutA_width = lutA->getParam(ID(WIDTH)).as_int();
|
||||||
int lutA_arity = luts_arity[lutA];
|
int lutA_arity = luts_arity[lutA];
|
||||||
pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[lutA];
|
pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[lutA];
|
||||||
|
|
||||||
auto lutA_output_ports = index.query_ports(lutA->getPort(ID(Y)));
|
auto lutA_output_ports = index.query_ports(lutA->getPort(ID::Y));
|
||||||
if (lutA_output_ports.size() != 2)
|
if (lutA_output_ports.size() != 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -321,15 +321,15 @@ struct OptLutWorker
|
||||||
if (luts.count(port.cell))
|
if (luts.count(port.cell))
|
||||||
{
|
{
|
||||||
auto lutB = port.cell;
|
auto lutB = port.cell;
|
||||||
SigSpec lutB_input = sigmap(lutB->getPort(ID(A)));
|
SigSpec lutB_input = sigmap(lutB->getPort(ID::A));
|
||||||
SigSpec lutB_output = sigmap(lutB->getPort(ID(Y))[0]);
|
SigSpec lutB_output = sigmap(lutB->getPort(ID::Y)[0]);
|
||||||
int lutB_width = lutB->getParam(ID(WIDTH)).as_int();
|
int lutB_width = lutB->getParam(ID(WIDTH)).as_int();
|
||||||
int lutB_arity = luts_arity[lutB];
|
int lutB_arity = luts_arity[lutB];
|
||||||
pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
|
pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
|
||||||
|
|
||||||
log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
|
log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
|
||||||
|
|
||||||
if (index.query_is_output(lutA->getPort(ID(Y))))
|
if (index.query_is_output(lutA->getPort(ID::Y)))
|
||||||
{
|
{
|
||||||
log_debug(" Not combining LUTs (cascade connection feeds module output).\n");
|
log_debug(" Not combining LUTs (cascade connection feeds module output).\n");
|
||||||
continue;
|
continue;
|
||||||
|
@ -441,7 +441,7 @@ struct OptLutWorker
|
||||||
}
|
}
|
||||||
|
|
||||||
int lutM_width = lutM->getParam(ID(WIDTH)).as_int();
|
int lutM_width = lutM->getParam(ID(WIDTH)).as_int();
|
||||||
SigSpec lutM_input = sigmap(lutM->getPort(ID(A)));
|
SigSpec lutM_input = sigmap(lutM->getPort(ID::A));
|
||||||
std::vector<SigBit> lutM_new_inputs;
|
std::vector<SigBit> lutM_new_inputs;
|
||||||
for (int i = 0; i < lutM_width; i++)
|
for (int i = 0; i < lutM_width; i++)
|
||||||
{
|
{
|
||||||
|
@ -487,8 +487,8 @@ struct OptLutWorker
|
||||||
log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
|
log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
|
||||||
|
|
||||||
lutM->setParam(ID(LUT), lutM_new_table);
|
lutM->setParam(ID(LUT), lutM_new_table);
|
||||||
lutM->setPort(ID(A), lutM_new_inputs);
|
lutM->setPort(ID::A, lutM_new_inputs);
|
||||||
lutM->setPort(ID(Y), lutB_output);
|
lutM->setPort(ID::Y, lutB_output);
|
||||||
|
|
||||||
luts_arity[lutM] = lutM_arity;
|
luts_arity[lutM] = lutM_arity;
|
||||||
luts.erase(lutR);
|
luts.erase(lutR);
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct OptMergeWorker
|
||||||
static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
|
static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
|
||||||
{
|
{
|
||||||
SigSpec sig_s = conn.at(ID(S));
|
SigSpec sig_s = conn.at(ID(S));
|
||||||
SigSpec sig_b = conn.at(ID(B));
|
SigSpec sig_b = conn.at(ID::B);
|
||||||
|
|
||||||
int s_width = GetSize(sig_s);
|
int s_width = GetSize(sig_s);
|
||||||
int width = GetSize(sig_b) / s_width;
|
int width = GetSize(sig_b) / s_width;
|
||||||
|
@ -60,11 +60,11 @@ struct OptMergeWorker
|
||||||
std::sort(sb_pairs.begin(), sb_pairs.end());
|
std::sort(sb_pairs.begin(), sb_pairs.end());
|
||||||
|
|
||||||
conn[ID(S)] = SigSpec();
|
conn[ID(S)] = SigSpec();
|
||||||
conn[ID(B)] = SigSpec();
|
conn[ID::B] = SigSpec();
|
||||||
|
|
||||||
for (auto &it : sb_pairs) {
|
for (auto &it : sb_pairs) {
|
||||||
conn[ID(S)].append(it.first);
|
conn[ID(S)].append(it.first);
|
||||||
conn[ID(B)].append(it.second);
|
conn[ID::B].append(it.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,28 +97,28 @@ struct OptMergeWorker
|
||||||
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
|
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
|
||||||
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
|
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
|
||||||
alt_conn = *conn;
|
alt_conn = *conn;
|
||||||
if (assign_map(alt_conn.at(ID(A))) < assign_map(alt_conn.at(ID(B)))) {
|
if (assign_map(alt_conn.at(ID::A)) < assign_map(alt_conn.at(ID::B))) {
|
||||||
alt_conn[ID(A)] = conn->at(ID(B));
|
alt_conn[ID::A] = conn->at(ID::B);
|
||||||
alt_conn[ID(B)] = conn->at(ID(A));
|
alt_conn[ID::B] = conn->at(ID::A);
|
||||||
}
|
}
|
||||||
conn = &alt_conn;
|
conn = &alt_conn;
|
||||||
} else
|
} else
|
||||||
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
|
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
|
||||||
alt_conn = *conn;
|
alt_conn = *conn;
|
||||||
assign_map.apply(alt_conn.at(ID(A)));
|
assign_map.apply(alt_conn.at(ID::A));
|
||||||
alt_conn.at(ID(A)).sort();
|
alt_conn.at(ID::A).sort();
|
||||||
conn = &alt_conn;
|
conn = &alt_conn;
|
||||||
} else
|
} else
|
||||||
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
|
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
|
||||||
alt_conn = *conn;
|
alt_conn = *conn;
|
||||||
assign_map.apply(alt_conn.at(ID(A)));
|
assign_map.apply(alt_conn.at(ID::A));
|
||||||
alt_conn.at(ID(A)).sort_and_unify();
|
alt_conn.at(ID::A).sort_and_unify();
|
||||||
conn = &alt_conn;
|
conn = &alt_conn;
|
||||||
} else
|
} else
|
||||||
if (cell->type == ID($pmux)) {
|
if (cell->type == ID($pmux)) {
|
||||||
alt_conn = *conn;
|
alt_conn = *conn;
|
||||||
assign_map.apply(alt_conn.at(ID(A)));
|
assign_map.apply(alt_conn.at(ID::A));
|
||||||
assign_map.apply(alt_conn.at(ID(B)));
|
assign_map.apply(alt_conn.at(ID::B));
|
||||||
assign_map.apply(alt_conn.at(ID(S)));
|
assign_map.apply(alt_conn.at(ID(S)));
|
||||||
sort_pmux_conn(alt_conn);
|
sort_pmux_conn(alt_conn);
|
||||||
conn = &alt_conn;
|
conn = &alt_conn;
|
||||||
|
@ -191,24 +191,24 @@ struct OptMergeWorker
|
||||||
|
|
||||||
if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) ||
|
if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) ||
|
||||||
cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) {
|
cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) {
|
||||||
if (conn1.at(ID(A)) < conn1.at(ID(B))) {
|
if (conn1.at(ID::A) < conn1.at(ID::B)) {
|
||||||
RTLIL::SigSpec tmp = conn1[ID(A)];
|
RTLIL::SigSpec tmp = conn1[ID::A];
|
||||||
conn1[ID(A)] = conn1[ID(B)];
|
conn1[ID::A] = conn1[ID::B];
|
||||||
conn1[ID(B)] = tmp;
|
conn1[ID::B] = tmp;
|
||||||
}
|
}
|
||||||
if (conn2.at(ID(A)) < conn2.at(ID(B))) {
|
if (conn2.at(ID::A) < conn2.at(ID::B)) {
|
||||||
RTLIL::SigSpec tmp = conn2[ID(A)];
|
RTLIL::SigSpec tmp = conn2[ID::A];
|
||||||
conn2[ID(A)] = conn2[ID(B)];
|
conn2[ID::A] = conn2[ID::B];
|
||||||
conn2[ID(B)] = tmp;
|
conn2[ID::B] = tmp;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) {
|
if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) {
|
||||||
conn1[ID(A)].sort();
|
conn1[ID::A].sort();
|
||||||
conn2[ID(A)].sort();
|
conn2[ID::A].sort();
|
||||||
} else
|
} else
|
||||||
if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) {
|
if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) {
|
||||||
conn1[ID(A)].sort_and_unify();
|
conn1[ID::A].sort_and_unify();
|
||||||
conn2[ID(A)].sort_and_unify();
|
conn2[ID::A].sort_and_unify();
|
||||||
} else
|
} else
|
||||||
if (cell1->type == ID($pmux)) {
|
if (cell1->type == ID($pmux)) {
|
||||||
sort_pmux_conn(conn1);
|
sort_pmux_conn(conn1);
|
||||||
|
|
|
@ -86,10 +86,10 @@ struct OptMuxtreeWorker
|
||||||
{
|
{
|
||||||
if (cell->type.in(ID($mux), ID($pmux)))
|
if (cell->type.in(ID($mux), ID($pmux)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_s = cell->getPort(ID(S));
|
RTLIL::SigSpec sig_s = cell->getPort(ID(S));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
muxinfo_t muxinfo;
|
muxinfo_t muxinfo;
|
||||||
muxinfo.cell = cell;
|
muxinfo.cell = cell;
|
||||||
|
@ -137,7 +137,7 @@ struct OptMuxtreeWorker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto wire : module->wires()) {
|
for (auto wire : module->wires()) {
|
||||||
if (wire->port_output || wire->get_bool_attribute(ID(keep)))
|
if (wire->port_output || wire->get_bool_attribute(ID::keep))
|
||||||
for (int idx : sig2bits(RTLIL::SigSpec(wire)))
|
for (int idx : sig2bits(RTLIL::SigSpec(wire)))
|
||||||
bit2info[idx].seen_non_mux = true;
|
bit2info[idx].seen_non_mux = true;
|
||||||
}
|
}
|
||||||
|
@ -227,10 +227,10 @@ struct OptMuxtreeWorker
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLIL::SigSpec sig_a = mi.cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = mi.cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = mi.cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = mi.cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S));
|
RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S));
|
||||||
RTLIL::SigSpec sig_y = mi.cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = mi.cell->getPort(ID::Y);
|
||||||
|
|
||||||
RTLIL::SigSpec sig_ports = sig_b;
|
RTLIL::SigSpec sig_ports = sig_b;
|
||||||
sig_ports.append(sig_a);
|
sig_ports.append(sig_a);
|
||||||
|
@ -255,8 +255,8 @@ struct OptMuxtreeWorker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.cell->setPort(ID(A), new_sig_a);
|
mi.cell->setPort(ID::A, new_sig_a);
|
||||||
mi.cell->setPort(ID(B), new_sig_b);
|
mi.cell->setPort(ID::B, new_sig_b);
|
||||||
mi.cell->setPort(ID(S), new_sig_s);
|
mi.cell->setPort(ID(S), new_sig_s);
|
||||||
if (GetSize(new_sig_s) == 1) {
|
if (GetSize(new_sig_s) == 1) {
|
||||||
mi.cell->type = ID($mux);
|
mi.cell->type = ID($mux);
|
||||||
|
@ -364,8 +364,8 @@ struct OptMuxtreeWorker
|
||||||
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
idict<int> ctrl_bits;
|
idict<int> ctrl_bits;
|
||||||
if (portname == ID(B))
|
if (portname == ID::B)
|
||||||
width = GetSize(muxinfo.cell->getPort(ID(A)));
|
width = GetSize(muxinfo.cell->getPort(ID::A));
|
||||||
for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false))
|
for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false))
|
||||||
ctrl_bits(bit);
|
ctrl_bits(bit);
|
||||||
|
|
||||||
|
@ -414,8 +414,8 @@ struct OptMuxtreeWorker
|
||||||
|
|
||||||
// set input ports to constants if we find known active or inactive signals
|
// set input ports to constants if we find known active or inactive signals
|
||||||
if (do_replace_known) {
|
if (do_replace_known) {
|
||||||
replace_known(knowledge, muxinfo, ID(A));
|
replace_known(knowledge, muxinfo, ID::A);
|
||||||
replace_known(knowledge, muxinfo, ID(B));
|
replace_known(knowledge, muxinfo, ID::B);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there is a constant activated port we just use it
|
// if there is a constant activated port we just use it
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct OptReduceWorker
|
||||||
return;
|
return;
|
||||||
cells.erase(cell);
|
cells.erase(cell);
|
||||||
|
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
pool<RTLIL::SigBit> new_sig_a_bits;
|
pool<RTLIL::SigBit> new_sig_a_bits;
|
||||||
|
|
||||||
for (auto &bit : sig_a.to_sigbit_set())
|
for (auto &bit : sig_a.to_sigbit_set())
|
||||||
|
@ -73,8 +73,8 @@ struct OptReduceWorker
|
||||||
for (auto child_cell : drivers.find(bit)) {
|
for (auto child_cell : drivers.find(bit)) {
|
||||||
if (child_cell->type == cell->type) {
|
if (child_cell->type == cell->type) {
|
||||||
opt_reduce(cells, drivers, child_cell);
|
opt_reduce(cells, drivers, child_cell);
|
||||||
if (child_cell->getPort(ID(Y))[0] == bit) {
|
if (child_cell->getPort(ID::Y)[0] == bit) {
|
||||||
pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort(ID(A))).to_sigbit_pool();
|
pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort(ID::A)).to_sigbit_pool();
|
||||||
new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end());
|
new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end());
|
||||||
} else
|
} else
|
||||||
new_sig_a_bits.insert(RTLIL::State::S0);
|
new_sig_a_bits.insert(RTLIL::State::S0);
|
||||||
|
@ -87,21 +87,21 @@ struct OptReduceWorker
|
||||||
|
|
||||||
RTLIL::SigSpec new_sig_a(new_sig_a_bits);
|
RTLIL::SigSpec new_sig_a(new_sig_a_bits);
|
||||||
|
|
||||||
if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID(A)).size()) {
|
if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID::A).size()) {
|
||||||
log(" New input vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_a));
|
log(" New input vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_a));
|
||||||
did_something = true;
|
did_something = true;
|
||||||
total_count++;
|
total_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->setPort(ID(A), new_sig_a);
|
cell->setPort(ID::A, new_sig_a);
|
||||||
cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size());
|
cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_mux(RTLIL::Cell *cell)
|
void opt_mux(RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S)));
|
RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S)));
|
||||||
|
|
||||||
RTLIL::SigSpec new_sig_b, new_sig_s;
|
RTLIL::SigSpec new_sig_b, new_sig_s;
|
||||||
|
@ -124,14 +124,14 @@ struct OptReduceWorker
|
||||||
if (this_s.size() > 1)
|
if (this_s.size() > 1)
|
||||||
{
|
{
|
||||||
RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or));
|
RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or));
|
||||||
reduce_or_cell->setPort(ID(A), this_s);
|
reduce_or_cell->setPort(ID::A, this_s);
|
||||||
reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0);
|
reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0);
|
||||||
reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size());
|
reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size());
|
||||||
reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1);
|
reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1);
|
||||||
|
|
||||||
RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID);
|
RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID);
|
||||||
this_s = RTLIL::SigSpec(reduce_or_wire);
|
this_s = RTLIL::SigSpec(reduce_or_wire);
|
||||||
reduce_or_cell->setPort(ID(Y), this_s);
|
reduce_or_cell->setPort(ID::Y, this_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_sig_b.append(this_b);
|
new_sig_b.append(this_b);
|
||||||
|
@ -147,13 +147,13 @@ struct OptReduceWorker
|
||||||
|
|
||||||
if (new_sig_s.size() == 0)
|
if (new_sig_s.size() == 0)
|
||||||
{
|
{
|
||||||
module->connect(RTLIL::SigSig(cell->getPort(ID(Y)), cell->getPort(ID(A))));
|
module->connect(RTLIL::SigSig(cell->getPort(ID::Y), cell->getPort(ID::A)));
|
||||||
assign_map.add(cell->getPort(ID(Y)), cell->getPort(ID(A)));
|
assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A));
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cell->setPort(ID(B), new_sig_b);
|
cell->setPort(ID::B, new_sig_b);
|
||||||
cell->setPort(ID(S), new_sig_s);
|
cell->setPort(ID(S), new_sig_s);
|
||||||
if (new_sig_s.size() > 1) {
|
if (new_sig_s.size() > 1) {
|
||||||
cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size());
|
cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size());
|
||||||
|
@ -166,9 +166,9 @@ struct OptReduceWorker
|
||||||
|
|
||||||
void opt_mux_bits(RTLIL::Cell *cell)
|
void opt_mux_bits(RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID(A))).to_sigbit_vector();
|
std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID::A)).to_sigbit_vector();
|
||||||
std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID(B))).to_sigbit_vector();
|
std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID::B)).to_sigbit_vector();
|
||||||
std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID(Y))).to_sigbit_vector();
|
std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID::Y)).to_sigbit_vector();
|
||||||
|
|
||||||
std::vector<RTLIL::SigBit> new_sig_y;
|
std::vector<RTLIL::SigBit> new_sig_y;
|
||||||
RTLIL::SigSig old_sig_conn;
|
RTLIL::SigSig old_sig_conn;
|
||||||
|
@ -209,29 +209,29 @@ struct OptReduceWorker
|
||||||
if (new_sig_y.size() != sig_y.size())
|
if (new_sig_y.size() != sig_y.size())
|
||||||
{
|
{
|
||||||
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
|
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
|
||||||
log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))),
|
log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y))));
|
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
|
||||||
|
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec());
|
cell->setPort(ID::A, RTLIL::SigSpec());
|
||||||
for (auto &in_tuple : consolidated_in_tuples) {
|
for (auto &in_tuple : consolidated_in_tuples) {
|
||||||
RTLIL::SigSpec new_a = cell->getPort(ID(A));
|
RTLIL::SigSpec new_a = cell->getPort(ID::A);
|
||||||
new_a.append(in_tuple.at(0));
|
new_a.append(in_tuple.at(0));
|
||||||
cell->setPort(ID(A), new_a);
|
cell->setPort(ID::A, new_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec());
|
cell->setPort(ID::B, RTLIL::SigSpec());
|
||||||
for (int i = 1; i <= cell->getPort(ID(S)).size(); i++)
|
for (int i = 1; i <= cell->getPort(ID(S)).size(); i++)
|
||||||
for (auto &in_tuple : consolidated_in_tuples) {
|
for (auto &in_tuple : consolidated_in_tuples) {
|
||||||
RTLIL::SigSpec new_b = cell->getPort(ID(B));
|
RTLIL::SigSpec new_b = cell->getPort(ID::B);
|
||||||
new_b.append(in_tuple.at(i));
|
new_b.append(in_tuple.at(i));
|
||||||
cell->setPort(ID(B), new_b);
|
cell->setPort(ID::B, new_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size());
|
cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size());
|
||||||
cell->setPort(ID(Y), new_sig_y);
|
cell->setPort(ID::Y, new_sig_y);
|
||||||
|
|
||||||
log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))),
|
log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y))));
|
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
|
||||||
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
|
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
|
||||||
|
|
||||||
module->connect(old_sig_conn);
|
module->connect(old_sig_conn);
|
||||||
|
@ -269,12 +269,12 @@ struct OptReduceWorker
|
||||||
keep_expanding_mem_wren_sigs = false;
|
keep_expanding_mem_wren_sigs = false;
|
||||||
for (auto &cell_it : module->cells_) {
|
for (auto &cell_it : module->cells_) {
|
||||||
RTLIL::Cell *cell = cell_it.second;
|
RTLIL::Cell *cell = cell_it.second;
|
||||||
if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y))))) {
|
if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y)))) {
|
||||||
if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(A)))) ||
|
if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID::A))) ||
|
||||||
!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(B)))))
|
!mem_wren_sigs.check_all(assign_map(cell->getPort(ID::B))))
|
||||||
keep_expanding_mem_wren_sigs = true;
|
keep_expanding_mem_wren_sigs = true;
|
||||||
mem_wren_sigs.add(assign_map(cell->getPort(ID(A))));
|
mem_wren_sigs.add(assign_map(cell->getPort(ID::A)));
|
||||||
mem_wren_sigs.add(assign_map(cell->getPort(ID(B))));
|
mem_wren_sigs.add(assign_map(cell->getPort(ID::B)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,7 @@ struct OptReduceWorker
|
||||||
RTLIL::Cell *cell = cell_it.second;
|
RTLIL::Cell *cell = cell_it.second;
|
||||||
if (cell->type != type || !design->selected(module, cell))
|
if (cell->type != type || !design->selected(module, cell))
|
||||||
continue;
|
continue;
|
||||||
drivers.insert(assign_map(cell->getPort(ID(Y))), cell);
|
drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
|
||||||
cells.insert(cell);
|
cells.insert(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ struct OptReduceWorker
|
||||||
{
|
{
|
||||||
// this optimization is to aggressive for most coarse-grain applications.
|
// this optimization is to aggressive for most coarse-grain applications.
|
||||||
// but we always want it for multiplexers driving write enable ports.
|
// but we always want it for multiplexers driving write enable ports.
|
||||||
if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y)))))
|
if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y))))
|
||||||
opt_mux_bits(cell);
|
opt_mux_bits(cell);
|
||||||
|
|
||||||
opt_mux(cell);
|
opt_mux(cell);
|
||||||
|
|
|
@ -347,8 +347,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
|
||||||
std::set<RTLIL::Cell*> muxes;
|
std::set<RTLIL::Cell*> muxes;
|
||||||
mux_drivers.find(sig_d, muxes);
|
mux_drivers.find(sig_d, muxes);
|
||||||
for (auto mux : muxes) {
|
for (auto mux : muxes) {
|
||||||
RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID::B));
|
||||||
if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) {
|
if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) {
|
||||||
mod->connect(sig_q, sig_b);
|
mod->connect(sig_q, sig_b);
|
||||||
goto delete_dff;
|
goto delete_dff;
|
||||||
|
@ -625,8 +625,8 @@ struct OptRmdffPass : public Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($mux), ID($pmux))) {
|
if (cell->type.in(ID($mux), ID($pmux))) {
|
||||||
if (cell->getPort(ID(A)).size() == cell->getPort(ID(B)).size())
|
if (cell->getPort(ID::A).size() == cell->getPort(ID::B).size())
|
||||||
mux_drivers.insert(assign_map(cell->getPort(ID(Y))), cell);
|
mux_drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,649 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
* 2019 Bogdan Vukobratovic <bogdan.vukobratovic@gmail.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/log.h"
|
||||||
|
#include "kernel/register.h"
|
||||||
|
#include "kernel/rtlil.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
SigMap assign_map;
|
||||||
|
|
||||||
|
struct OpMuxConn {
|
||||||
|
RTLIL::SigSpec sig;
|
||||||
|
RTLIL::Cell *mux;
|
||||||
|
RTLIL::Cell *op;
|
||||||
|
int mux_port_id;
|
||||||
|
int mux_port_offset;
|
||||||
|
int op_outsig_offset;
|
||||||
|
|
||||||
|
bool operator<(const OpMuxConn &other) const
|
||||||
|
{
|
||||||
|
if (mux != other.mux)
|
||||||
|
return mux < other.mux;
|
||||||
|
|
||||||
|
if (mux_port_id != other.mux_port_id)
|
||||||
|
return mux_port_id < other.mux_port_id;
|
||||||
|
|
||||||
|
return mux_port_offset < other.mux_port_offset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper class to track additiona information about a SigSpec, like whether it is signed and the semantics of the port it is connected to
|
||||||
|
struct ExtSigSpec {
|
||||||
|
RTLIL::SigSpec sig;
|
||||||
|
RTLIL::SigSpec sign;
|
||||||
|
bool is_signed;
|
||||||
|
RTLIL::IdString semantics;
|
||||||
|
|
||||||
|
ExtSigSpec() {}
|
||||||
|
|
||||||
|
ExtSigSpec(RTLIL::SigSpec s, RTLIL::SigSpec sign = RTLIL::Const(0, 1), bool is_signed = false, RTLIL::IdString semantics = RTLIL::IdString()) : sig(s), sign(sign), is_signed(is_signed), semantics(semantics) {}
|
||||||
|
|
||||||
|
bool empty() const { return sig.empty(); }
|
||||||
|
|
||||||
|
bool operator<(const ExtSigSpec &other) const
|
||||||
|
{
|
||||||
|
if (sig != other.sig)
|
||||||
|
return sig < other.sig;
|
||||||
|
|
||||||
|
if (sign != other.sign)
|
||||||
|
return sign < other.sign;
|
||||||
|
|
||||||
|
if (is_signed != other.is_signed)
|
||||||
|
return is_signed < other.is_signed;
|
||||||
|
|
||||||
|
return semantics < other.semantics;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const RTLIL::SigSpec &other) const { return (sign != RTLIL::Const(0, 1)) ? false : sig == other; }
|
||||||
|
bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($and), ID($or), ID($xor), ID($xnor)
|
||||||
|
|
||||||
|
#define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand)
|
||||||
|
|
||||||
|
#define LOGICAL_OPS ID($logic_and), ID($logic_or)
|
||||||
|
|
||||||
|
#define SHIFT_OPS ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)
|
||||||
|
|
||||||
|
#define RELATIONAL_OPS ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt)
|
||||||
|
|
||||||
|
bool cell_supported(RTLIL::Cell *cell)
|
||||||
|
{
|
||||||
|
if (cell->type.in(ID($alu))) {
|
||||||
|
RTLIL::SigSpec sig_bi = cell->getPort(ID(BI));
|
||||||
|
RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
|
||||||
|
|
||||||
|
if (sig_bi.is_fully_const() && sig_ci.is_fully_const() && sig_bi == sig_ci)
|
||||||
|
return true;
|
||||||
|
} else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($concat))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<IdString, IdString> mergeable_type_map{
|
||||||
|
{ID($sub), ID($add)},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b)
|
||||||
|
{
|
||||||
|
auto a_type = a->type;
|
||||||
|
if (mergeable_type_map.count(a_type))
|
||||||
|
a_type = mergeable_type_map.at(a_type);
|
||||||
|
|
||||||
|
auto b_type = b->type;
|
||||||
|
if (mergeable_type_map.count(b_type))
|
||||||
|
b_type = mergeable_type_map.at(b_type);
|
||||||
|
|
||||||
|
return a_type == b_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_name)
|
||||||
|
{
|
||||||
|
if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($concat), SHIFT_OPS) && port_name == ID::B)
|
||||||
|
return port_name;
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) {
|
||||||
|
|
||||||
|
if (cell->type == ID($alu) && port_name == ID::B)
|
||||||
|
return cell->getPort(ID(BI));
|
||||||
|
else if (cell->type == ID($sub) && port_name == ID::B)
|
||||||
|
return RTLIL::Const(1, 1);
|
||||||
|
|
||||||
|
return RTLIL::Const(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool decode_port_signed(RTLIL::Cell *cell, RTLIL::IdString port_name)
|
||||||
|
{
|
||||||
|
if (cell->type.in(BITWISE_OPS, LOGICAL_OPS))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cell->hasParam(port_name.str() + "_SIGNED"))
|
||||||
|
return cell->getParam(port_name.str() + "_SIGNED").as_bool();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap)
|
||||||
|
{
|
||||||
|
auto sig = (*sigmap)(cell->getPort(port_name));
|
||||||
|
|
||||||
|
RTLIL::SigSpec sign = decode_port_sign(cell, port_name);
|
||||||
|
RTLIL::IdString semantics = decode_port_semantics(cell, port_name);
|
||||||
|
|
||||||
|
bool is_signed = decode_port_signed(cell, port_name);
|
||||||
|
|
||||||
|
return ExtSigSpec(sig, sign, is_signed, semantics);
|
||||||
|
}
|
||||||
|
|
||||||
|
void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<OpMuxConn> &ports, const ExtSigSpec &operand)
|
||||||
|
{
|
||||||
|
std::vector<ExtSigSpec> muxed_operands;
|
||||||
|
int max_width = 0;
|
||||||
|
for (const auto& p : ports) {
|
||||||
|
auto op = p.op;
|
||||||
|
|
||||||
|
RTLIL::IdString muxed_port_name = ID::A;
|
||||||
|
if (decode_port(op, ID::A, &assign_map) == operand)
|
||||||
|
muxed_port_name = ID::B;
|
||||||
|
|
||||||
|
auto operand = decode_port(op, muxed_port_name, &assign_map);
|
||||||
|
if (operand.sig.size() > max_width)
|
||||||
|
max_width = operand.sig.size();
|
||||||
|
|
||||||
|
muxed_operands.push_back(operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shared_op = ports[0].op;
|
||||||
|
|
||||||
|
if (std::any_of(muxed_operands.begin(), muxed_operands.end(), [&](ExtSigSpec &op) { return op.sign != muxed_operands[0].sign; }))
|
||||||
|
max_width = std::max(max_width, shared_op->getParam(ID(Y_WIDTH)).as_int());
|
||||||
|
|
||||||
|
|
||||||
|
for (auto &operand : muxed_operands)
|
||||||
|
operand.sig.extend_u0(max_width, operand.is_signed);
|
||||||
|
|
||||||
|
for (const auto& p : ports) {
|
||||||
|
auto op = p.op;
|
||||||
|
if (op == shared_op)
|
||||||
|
continue;
|
||||||
|
module->remove(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &muxed_op : muxed_operands)
|
||||||
|
if (muxed_op.sign != muxed_operands[0].sign)
|
||||||
|
muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed));
|
||||||
|
|
||||||
|
RTLIL::SigSpec mux_y = mux->getPort(ID::Y);
|
||||||
|
RTLIL::SigSpec mux_a = mux->getPort(ID::A);
|
||||||
|
RTLIL::SigSpec mux_b = mux->getPort(ID::B);
|
||||||
|
RTLIL::SigSpec mux_s = mux->getPort(ID(S));
|
||||||
|
|
||||||
|
RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width);
|
||||||
|
RTLIL::SigSpec shared_pmux_b;
|
||||||
|
RTLIL::SigSpec shared_pmux_s;
|
||||||
|
|
||||||
|
int conn_width = ports[0].sig.size();
|
||||||
|
int conn_offset = ports[0].mux_port_offset;
|
||||||
|
|
||||||
|
shared_op->setPort(ID::Y, shared_op->getPort(ID::Y).extract(0, conn_width));
|
||||||
|
|
||||||
|
if (mux->type == ID($pmux)) {
|
||||||
|
shared_pmux_s = RTLIL::SigSpec();
|
||||||
|
|
||||||
|
for (const auto &p : ports) {
|
||||||
|
shared_pmux_s.append(mux_s[p.mux_port_id]);
|
||||||
|
mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort(ID::Y));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)};
|
||||||
|
mux_a.replace(conn_offset, shared_op->getPort(ID::Y));
|
||||||
|
mux_b.replace(conn_offset, shared_op->getPort(ID::Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
mux->setPort(ID::A, mux_a);
|
||||||
|
mux->setPort(ID::B, mux_b);
|
||||||
|
mux->setPort(ID::Y, mux_y);
|
||||||
|
mux->setPort(ID(S), mux_s);
|
||||||
|
|
||||||
|
for (const auto &op : muxed_operands)
|
||||||
|
shared_pmux_b.append(op.sig);
|
||||||
|
|
||||||
|
auto mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s);
|
||||||
|
|
||||||
|
if (shared_op->type.in(ID($alu))) {
|
||||||
|
RTLIL::SigSpec alu_x = shared_op->getPort(ID(X));
|
||||||
|
RTLIL::SigSpec alu_co = shared_op->getPort(ID(CO));
|
||||||
|
|
||||||
|
shared_op->setPort(ID(X), alu_x.extract(0, conn_width));
|
||||||
|
shared_op->setPort(ID(CO), alu_co.extract(0, conn_width));
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_op->setParam(ID(Y_WIDTH), conn_width);
|
||||||
|
|
||||||
|
if (decode_port(shared_op, ID::A, &assign_map) == operand) {
|
||||||
|
shared_op->setPort(ID::B, mux_to_oper);
|
||||||
|
shared_op->setParam(ID(B_WIDTH), max_width);
|
||||||
|
} else {
|
||||||
|
shared_op->setPort(ID::A, mux_to_oper);
|
||||||
|
shared_op->setParam(ID(A_WIDTH), max_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
RTLIL::Cell *mux;
|
||||||
|
std::vector<OpMuxConn> ports;
|
||||||
|
ExtSigSpec shared_operand;
|
||||||
|
} merged_op_t;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T> void remove_val(std::vector<T> &v, const std::vector<T> &vals)
|
||||||
|
{
|
||||||
|
auto val_iter = vals.rbegin();
|
||||||
|
for (auto i = v.rbegin(); i != v.rend(); ++i)
|
||||||
|
if ((val_iter != vals.rend()) && (*i == *val_iter)) {
|
||||||
|
v.erase(i.base() - 1);
|
||||||
|
++val_iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_muxed_operands(std::vector<const OpMuxConn *> &ports, const ExtSigSpec &shared_operand)
|
||||||
|
{
|
||||||
|
auto it = ports.begin();
|
||||||
|
ExtSigSpec seed;
|
||||||
|
|
||||||
|
while (it != ports.end()) {
|
||||||
|
auto p = *it;
|
||||||
|
auto op = p->op;
|
||||||
|
|
||||||
|
RTLIL::IdString muxed_port_name = ID::A;
|
||||||
|
if (decode_port(op, ID::A, &assign_map) == shared_operand) {
|
||||||
|
muxed_port_name = ID::B;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operand = decode_port(op, muxed_port_name, &assign_map);
|
||||||
|
|
||||||
|
if (seed.empty())
|
||||||
|
seed = operand;
|
||||||
|
|
||||||
|
if (operand.is_signed != seed.is_signed) {
|
||||||
|
ports.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector<const OpMuxConn *> &ports, const std::map<ExtSigSpec, std::set<RTLIL::Cell *>> &operand_to_users)
|
||||||
|
{
|
||||||
|
std::set<RTLIL::Cell *> ops_using_operand;
|
||||||
|
std::set<RTLIL::Cell *> ops_set;
|
||||||
|
for(const auto& p: ports)
|
||||||
|
ops_set.insert(p->op);
|
||||||
|
|
||||||
|
ExtSigSpec oper;
|
||||||
|
|
||||||
|
auto op_a = seed->op;
|
||||||
|
|
||||||
|
for (RTLIL::IdString port_name : {ID::A, ID::B}) {
|
||||||
|
oper = decode_port(op_a, port_name, &assign_map);
|
||||||
|
auto operand_users = operand_to_users.at(oper);
|
||||||
|
|
||||||
|
if (operand_users.size() == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ops_using_operand.clear();
|
||||||
|
for (auto mux_ops: ops_set)
|
||||||
|
if (operand_users.count(mux_ops))
|
||||||
|
ops_using_operand.insert(mux_ops);
|
||||||
|
|
||||||
|
if (ops_using_operand.size() > 1) {
|
||||||
|
ports.erase(std::remove_if(ports.begin(), ports.end(), [&](const OpMuxConn *p) { return !ops_using_operand.count(p->op); }),
|
||||||
|
ports.end());
|
||||||
|
return oper;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExtSigSpec();
|
||||||
|
}
|
||||||
|
|
||||||
|
dict<RTLIL::SigSpec, OpMuxConn> find_valid_op_mux_conns(RTLIL::Module *module, dict<RTLIL::SigBit, RTLIL::SigSpec> &op_outbit_to_outsig,
|
||||||
|
dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator,
|
||||||
|
dict<RTLIL::SigBit, RTLIL::SigSpec> &op_aux_to_outsig)
|
||||||
|
{
|
||||||
|
dict<RTLIL::SigSpec, int> op_outsig_user_track;
|
||||||
|
dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map;
|
||||||
|
|
||||||
|
std::function<void(RTLIL::SigSpec)> remove_outsig = [&](RTLIL::SigSpec outsig) {
|
||||||
|
for (auto op_outbit : outsig)
|
||||||
|
op_outbit_to_outsig.erase(op_outbit);
|
||||||
|
|
||||||
|
if (op_mux_conn_map.count(outsig))
|
||||||
|
op_mux_conn_map.erase(outsig);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<void(RTLIL::SigBit)> remove_outsig_from_aux_bit = [&](RTLIL::SigBit auxbit) {
|
||||||
|
auto aux_outsig = op_aux_to_outsig.at(auxbit);
|
||||||
|
auto op = outsig_to_operator.at(aux_outsig);
|
||||||
|
auto op_outsig = assign_map(op->getPort(ID::Y));
|
||||||
|
remove_outsig(op_outsig);
|
||||||
|
|
||||||
|
for (auto aux_outbit : aux_outsig)
|
||||||
|
op_aux_to_outsig.erase(aux_outbit);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<void(RTLIL::Cell *)> find_op_mux_conns = [&](RTLIL::Cell *mux) {
|
||||||
|
RTLIL::SigSpec sig;
|
||||||
|
int mux_port_size;
|
||||||
|
|
||||||
|
if (mux->type.in(ID($mux), ID($_MUX_))) {
|
||||||
|
mux_port_size = mux->getPort(ID::A).size();
|
||||||
|
sig = RTLIL::SigSpec{mux->getPort(ID::B), mux->getPort(ID::A)};
|
||||||
|
} else {
|
||||||
|
mux_port_size = mux->getPort(ID::A).size();
|
||||||
|
sig = mux->getPort(ID::B);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mux_insig = assign_map(sig);
|
||||||
|
|
||||||
|
for (int i = 0; i < mux_insig.size(); ++i) {
|
||||||
|
if (op_aux_to_outsig.count(mux_insig[i])) {
|
||||||
|
remove_outsig_from_aux_bit(mux_insig[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!op_outbit_to_outsig.count(mux_insig[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto op_outsig = op_outbit_to_outsig.at(mux_insig[i]);
|
||||||
|
|
||||||
|
if (op_mux_conn_map.count(op_outsig)) {
|
||||||
|
remove_outsig(op_outsig);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mux_port_id = i / mux_port_size;
|
||||||
|
int mux_port_offset = i % mux_port_size;
|
||||||
|
|
||||||
|
int op_outsig_offset;
|
||||||
|
for (op_outsig_offset = 0; op_outsig[op_outsig_offset] != mux_insig[i]; ++op_outsig_offset)
|
||||||
|
;
|
||||||
|
|
||||||
|
int j = op_outsig_offset;
|
||||||
|
do {
|
||||||
|
if (!op_outbit_to_outsig.count(mux_insig[i]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (op_outbit_to_outsig.at(mux_insig[i]) != op_outsig)
|
||||||
|
break;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
} while ((i / mux_port_size == mux_port_id) && (j < op_outsig.size()));
|
||||||
|
|
||||||
|
int op_conn_width = j - op_outsig_offset;
|
||||||
|
OpMuxConn inp = {
|
||||||
|
op_outsig.extract(op_outsig_offset, op_conn_width),
|
||||||
|
mux,
|
||||||
|
outsig_to_operator.at(op_outsig),
|
||||||
|
mux_port_id,
|
||||||
|
mux_port_offset,
|
||||||
|
op_outsig_offset,
|
||||||
|
};
|
||||||
|
|
||||||
|
op_mux_conn_map[op_outsig] = inp;
|
||||||
|
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<void(RTLIL::SigSpec)> remove_connected_ops = [&](RTLIL::SigSpec sig) {
|
||||||
|
auto mux_insig = assign_map(sig);
|
||||||
|
for (auto outbit : mux_insig) {
|
||||||
|
if (op_aux_to_outsig.count(outbit)) {
|
||||||
|
remove_outsig_from_aux_bit(outbit);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!op_outbit_to_outsig.count(outbit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
remove_outsig(op_outbit_to_outsig.at(outbit));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto cell : module->cells()) {
|
||||||
|
if (cell->type.in(ID($mux), ID($_MUX_), ID($pmux))) {
|
||||||
|
remove_connected_ops(cell->getPort(ID(S)));
|
||||||
|
find_op_mux_conns(cell);
|
||||||
|
} else {
|
||||||
|
for (auto &conn : cell->connections())
|
||||||
|
if (cell->input(conn.first))
|
||||||
|
remove_connected_ops(conn.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto w : module->wires()) {
|
||||||
|
if (!w->port_output)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
remove_connected_ops(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_mux_conn_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OptSharePass : public Pass {
|
||||||
|
OptSharePass() : Pass("opt_share", "merge mutually exclusive cells of the same type that share an input signal") {}
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" opt_share [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
|
||||||
|
log("This pass identifies mutually exclusive cells of the same type that:\n");
|
||||||
|
log(" (a) share an input signal,\n");
|
||||||
|
log(" (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell,\n");
|
||||||
|
log("\n");
|
||||||
|
log("allowing the cell to be merged and the multiplexer to be moved from\n");
|
||||||
|
log("multiplexing its output to multiplexing the non-shared input signals.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
|
||||||
|
log_header(design, "Executing OPT_SHARE pass.\n");
|
||||||
|
|
||||||
|
extra_args(args, 1, design);
|
||||||
|
for (auto module : design->selected_modules()) {
|
||||||
|
assign_map.clear();
|
||||||
|
assign_map.set(module);
|
||||||
|
|
||||||
|
std::map<ExtSigSpec, std::set<RTLIL::Cell *>> operand_to_users;
|
||||||
|
dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator;
|
||||||
|
dict<RTLIL::SigBit, RTLIL::SigSpec> op_outbit_to_outsig;
|
||||||
|
dict<RTLIL::SigBit, RTLIL::SigSpec> op_aux_to_outsig;
|
||||||
|
bool any_shared_operands = false;
|
||||||
|
std::vector<ExtSigSpec> op_insigs;
|
||||||
|
|
||||||
|
for (auto cell : module->cells()) {
|
||||||
|
if (!cell_supported(cell))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cell->type == ID($alu)) {
|
||||||
|
for (RTLIL::IdString port_name : {ID(X), ID(CO)}) {
|
||||||
|
auto mux_insig = assign_map(cell->getPort(port_name));
|
||||||
|
outsig_to_operator[mux_insig] = cell;
|
||||||
|
for (auto outbit : mux_insig)
|
||||||
|
op_aux_to_outsig[outbit] = mux_insig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mux_insig = assign_map(cell->getPort(ID::Y));
|
||||||
|
outsig_to_operator[mux_insig] = cell;
|
||||||
|
for (auto outbit : mux_insig)
|
||||||
|
op_outbit_to_outsig[outbit] = mux_insig;
|
||||||
|
|
||||||
|
for (RTLIL::IdString port_name : {ID::A, ID::B}) {
|
||||||
|
auto op_insig = decode_port(cell, port_name, &assign_map);
|
||||||
|
op_insigs.push_back(op_insig);
|
||||||
|
operand_to_users[op_insig].insert(cell);
|
||||||
|
if (operand_to_users[op_insig].size() > 1)
|
||||||
|
any_shared_operands = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!any_shared_operands)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Operator outputs need to be exclusively connected to the $mux inputs in order to be mergeable. Hence we count to
|
||||||
|
// how many points are operator output bits connected.
|
||||||
|
dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map =
|
||||||
|
find_valid_op_mux_conns(module, op_outbit_to_outsig, outsig_to_operator, op_aux_to_outsig);
|
||||||
|
|
||||||
|
// Group op connections connected to same ports of the same $mux. Sort them in ascending order of their port offset
|
||||||
|
dict<RTLIL::Cell*, std::vector<std::set<OpMuxConn>>> mux_port_op_conns;
|
||||||
|
for (auto& val: op_mux_conn_map) {
|
||||||
|
OpMuxConn p = val.second;
|
||||||
|
auto& mux_port_conns = mux_port_op_conns[p.mux];
|
||||||
|
|
||||||
|
if (mux_port_conns.size() == 0) {
|
||||||
|
int mux_port_num;
|
||||||
|
|
||||||
|
if (p.mux->type.in(ID($mux), ID($_MUX_)))
|
||||||
|
mux_port_num = 2;
|
||||||
|
else
|
||||||
|
mux_port_num = p.mux->getPort(ID(S)).size();
|
||||||
|
|
||||||
|
mux_port_conns.resize(mux_port_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
mux_port_conns[p.mux_port_id].insert(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<merged_op_t> merged_ops;
|
||||||
|
for (auto& val: mux_port_op_conns) {
|
||||||
|
|
||||||
|
RTLIL::Cell* cell = val.first;
|
||||||
|
auto &mux_port_conns = val.second;
|
||||||
|
|
||||||
|
const OpMuxConn *seed = NULL;
|
||||||
|
|
||||||
|
// Look through the bits of the $mux inputs and see which of them are connected to the operator
|
||||||
|
// results. Operator results can be concatenated with other signals before led to the $mux.
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
// Remove either the merged ports from the last iteration or the seed that failed to yield a merger
|
||||||
|
if (seed != NULL) {
|
||||||
|
mux_port_conns[seed->mux_port_id].erase(*seed);
|
||||||
|
seed = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For a new merger, find the seed op connection that starts at lowest port offset among port connections
|
||||||
|
for (auto &port_conns : mux_port_conns) {
|
||||||
|
if (!port_conns.size())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const OpMuxConn *next_p = &(*port_conns.begin());
|
||||||
|
|
||||||
|
if ((seed == NULL) || (seed->mux_port_offset > next_p->mux_port_offset))
|
||||||
|
seed = next_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot find the seed -> nothing to do for this $mux anymore
|
||||||
|
if (seed == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Find all other op connections that start from the same port offset, and whose ops can be merged with the seed op
|
||||||
|
std::vector<const OpMuxConn *> mergeable_conns;
|
||||||
|
for (auto &port_conns : mux_port_conns) {
|
||||||
|
if (!port_conns.size())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const OpMuxConn *next_p = &(*port_conns.begin());
|
||||||
|
|
||||||
|
if ((next_p->op_outsig_offset == seed->op_outsig_offset) &&
|
||||||
|
(next_p->mux_port_offset == seed->mux_port_offset) && mergeable(next_p->op, seed->op) &&
|
||||||
|
next_p->sig.size() == seed->sig.size())
|
||||||
|
mergeable_conns.push_back(next_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need at least two mergeable connections for the merger
|
||||||
|
if (mergeable_conns.size() < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Filter mergeable connections whose ops share an operand with seed connection's op
|
||||||
|
auto shared_operand = find_shared_operand(seed, mergeable_conns, operand_to_users);
|
||||||
|
|
||||||
|
if (shared_operand.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
check_muxed_operands(mergeable_conns, shared_operand);
|
||||||
|
|
||||||
|
if (mergeable_conns.size() < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Remember the combination for the merger
|
||||||
|
std::vector<OpMuxConn> merged_ports;
|
||||||
|
for (auto p : mergeable_conns) {
|
||||||
|
merged_ports.push_back(*p);
|
||||||
|
mux_port_conns[p->mux_port_id].erase(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
seed = NULL;
|
||||||
|
|
||||||
|
merged_ops.push_back(merged_op_t{cell, merged_ports, shared_operand});
|
||||||
|
|
||||||
|
design->scratchpad_set_bool("opt.did_something", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &shared : merged_ops) {
|
||||||
|
log(" Found cells that share an operand and can be merged by moving the %s %s in front "
|
||||||
|
"of "
|
||||||
|
"them:\n",
|
||||||
|
log_id(shared.mux->type), log_id(shared.mux));
|
||||||
|
for (const auto& op : shared.ports)
|
||||||
|
log(" %s\n", log_id(op.op));
|
||||||
|
log("\n");
|
||||||
|
|
||||||
|
merge_operators(module, shared.mux, shared.ports, shared.shared_operand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} OptSharePass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -73,9 +73,9 @@ struct OnehotDatabase
|
||||||
|
|
||||||
if (cell->type.in(ID($mux), ID($pmux)))
|
if (cell->type.in(ID($mux), ID($pmux)))
|
||||||
{
|
{
|
||||||
output = cell->getPort(ID(Y));
|
output = cell->getPort(ID::Y);
|
||||||
inputs.push_back(cell->getPort(ID(A)));
|
inputs.push_back(cell->getPort(ID::A));
|
||||||
SigSpec B = cell->getPort(ID(B));
|
SigSpec B = cell->getPort(ID::B);
|
||||||
for (int i = 0; i < GetSize(B); i += GetSize(output))
|
for (int i = 0; i < GetSize(B); i += GetSize(output))
|
||||||
inputs.push_back(B.extract(i, GetSize(output)));
|
inputs.push_back(B.extract(i, GetSize(output)));
|
||||||
}
|
}
|
||||||
|
@ -296,8 +296,8 @@ struct Pmux2ShiftxPass : public Pass {
|
||||||
{
|
{
|
||||||
dict<SigBit, State> bits;
|
dict<SigBit, State> bits;
|
||||||
|
|
||||||
SigSpec A = sigmap(cell->getPort(ID(A)));
|
SigSpec A = sigmap(cell->getPort(ID::A));
|
||||||
SigSpec B = sigmap(cell->getPort(ID(B)));
|
SigSpec B = sigmap(cell->getPort(ID::B));
|
||||||
|
|
||||||
int a_width = cell->getParam(ID(A_WIDTH)).as_int();
|
int a_width = cell->getParam(ID(A_WIDTH)).as_int();
|
||||||
int b_width = cell->getParam(ID(B_WIDTH)).as_int();
|
int b_width = cell->getParam(ID(B_WIDTH)).as_int();
|
||||||
|
@ -335,7 +335,7 @@ struct Pmux2ShiftxPass : public Pass {
|
||||||
entry.second.bits.push_back(it.second);
|
entry.second.bits.push_back(it.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry;
|
eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry;
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ struct Pmux2ShiftxPass : public Pass {
|
||||||
{
|
{
|
||||||
dict<SigBit, State> bits;
|
dict<SigBit, State> bits;
|
||||||
|
|
||||||
SigSpec A = sigmap(cell->getPort(ID(A)));
|
SigSpec A = sigmap(cell->getPort(ID::A));
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(A); i++)
|
for (int i = 0; i < GetSize(A); i++)
|
||||||
bits[A[i]] = State::S0;
|
bits[A[i]] = State::S0;
|
||||||
|
@ -356,7 +356,7 @@ struct Pmux2ShiftxPass : public Pass {
|
||||||
entry.second.bits.push_back(it.second);
|
entry.second.bits.push_back(it.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry;
|
eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry;
|
||||||
goto next_cell;
|
goto next_cell;
|
||||||
}
|
}
|
||||||
next_cell:;
|
next_cell:;
|
||||||
|
@ -377,8 +377,8 @@ struct Pmux2ShiftxPass : public Pass {
|
||||||
|
|
||||||
dict<SigSpec, pool<int>> seldb;
|
dict<SigSpec, pool<int>> seldb;
|
||||||
|
|
||||||
SigSpec A = cell->getPort(ID(A));
|
SigSpec A = cell->getPort(ID::A);
|
||||||
SigSpec B = cell->getPort(ID(B));
|
SigSpec B = cell->getPort(ID::B);
|
||||||
SigSpec S = sigmap(cell->getPort(ID(S)));
|
SigSpec S = sigmap(cell->getPort(ID(S)));
|
||||||
for (int i = 0; i < GetSize(S); i++)
|
for (int i = 0; i < GetSize(S); i++)
|
||||||
{
|
{
|
||||||
|
@ -401,7 +401,7 @@ struct Pmux2ShiftxPass : public Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
SigSpec updated_S = cell->getPort(ID(S));
|
SigSpec updated_S = cell->getPort(ID(S));
|
||||||
SigSpec updated_B = cell->getPort(ID(B));
|
SigSpec updated_B = cell->getPort(ID::B);
|
||||||
|
|
||||||
while (!seldb.empty())
|
while (!seldb.empty())
|
||||||
{
|
{
|
||||||
|
@ -728,7 +728,7 @@ struct Pmux2ShiftxPass : public Pass {
|
||||||
|
|
||||||
// update $pmux cell
|
// update $pmux cell
|
||||||
cell->setPort(ID(S), updated_S);
|
cell->setPort(ID(S), updated_S);
|
||||||
cell->setPort(ID(B), updated_B);
|
cell->setPort(ID::B, updated_B);
|
||||||
cell->setParam(ID(S_WIDTH), GetSize(updated_S));
|
cell->setParam(ID(S_WIDTH), GetSize(updated_S));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -782,8 +782,8 @@ struct OnehotPass : public Pass {
|
||||||
if (cell->type != ID($eq))
|
if (cell->type != ID($eq))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SigSpec A = sigmap(cell->getPort(ID(A)));
|
SigSpec A = sigmap(cell->getPort(ID::A));
|
||||||
SigSpec B = sigmap(cell->getPort(ID(B)));
|
SigSpec B = sigmap(cell->getPort(ID::B));
|
||||||
|
|
||||||
int a_width = cell->getParam(ID(A_WIDTH)).as_int();
|
int a_width = cell->getParam(ID(A_WIDTH)).as_int();
|
||||||
int b_width = cell->getParam(ID(B_WIDTH)).as_int();
|
int b_width = cell->getParam(ID(B_WIDTH)).as_int();
|
||||||
|
@ -830,7 +830,7 @@ struct OnehotPass : public Pass {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SigSpec Y = cell->getPort(ID(Y));
|
SigSpec Y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
if (not_onehot)
|
if (not_onehot)
|
||||||
{
|
{
|
||||||
|
|
|
@ -128,7 +128,7 @@ struct ShareWorker
|
||||||
static int bits_macc(RTLIL::Cell *c)
|
static int bits_macc(RTLIL::Cell *c)
|
||||||
{
|
{
|
||||||
Macc m(c);
|
Macc m(c);
|
||||||
int width = GetSize(c->getPort(ID(Y)));
|
int width = GetSize(c->getPort(ID::Y));
|
||||||
return bits_macc(m, width);
|
return bits_macc(m, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ struct ShareWorker
|
||||||
{
|
{
|
||||||
Macc m1(c1), m2(c2), supermacc;
|
Macc m1(c1), m2(c2), supermacc;
|
||||||
|
|
||||||
int w1 = GetSize(c1->getPort(ID(Y))), w2 = GetSize(c2->getPort(ID(Y)));
|
int w1 = GetSize(c1->getPort(ID::Y)), w2 = GetSize(c2->getPort(ID::Y));
|
||||||
int width = max(w1, w2);
|
int width = max(w1, w2);
|
||||||
|
|
||||||
m1.optimize(w1);
|
m1.optimize(w1);
|
||||||
|
@ -328,11 +328,11 @@ struct ShareWorker
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width);
|
RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width);
|
||||||
|
|
||||||
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID(Y))));
|
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID::Y)));
|
||||||
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID(Y))));
|
supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID::Y)));
|
||||||
|
|
||||||
supercell->setParam(ID(Y_WIDTH), width);
|
supercell->setParam(ID(Y_WIDTH), width);
|
||||||
supercell->setPort(ID(Y), sig_y);
|
supercell->setPort(ID::Y, sig_y);
|
||||||
|
|
||||||
supermacc.optimize(width);
|
supermacc.optimize(width);
|
||||||
supermacc.to_cell(supercell);
|
supermacc.to_cell(supercell);
|
||||||
|
@ -513,11 +513,11 @@ struct ShareWorker
|
||||||
if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
|
if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
|
||||||
{
|
{
|
||||||
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
|
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
|
||||||
if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) {
|
if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) {
|
||||||
unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
|
unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
|
||||||
RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A));
|
RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A);
|
||||||
new_a.append_bit(RTLIL::State::S0);
|
new_a.append_bit(RTLIL::State::S0);
|
||||||
unsigned_cell->setPort(ID(A), new_a);
|
unsigned_cell->setPort(ID::A, new_a);
|
||||||
}
|
}
|
||||||
unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
|
unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
|
||||||
unsigned_cell->check();
|
unsigned_cell->check();
|
||||||
|
@ -526,11 +526,11 @@ struct ShareWorker
|
||||||
bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
|
bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
|
||||||
log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
|
log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
|
||||||
|
|
||||||
RTLIL::SigSpec a1 = c1->getPort(ID(A));
|
RTLIL::SigSpec a1 = c1->getPort(ID::A);
|
||||||
RTLIL::SigSpec y1 = c1->getPort(ID(Y));
|
RTLIL::SigSpec y1 = c1->getPort(ID::Y);
|
||||||
|
|
||||||
RTLIL::SigSpec a2 = c2->getPort(ID(A));
|
RTLIL::SigSpec a2 = c2->getPort(ID::A);
|
||||||
RTLIL::SigSpec y2 = c2->getPort(ID(Y));
|
RTLIL::SigSpec y2 = c2->getPort(ID::Y);
|
||||||
|
|
||||||
int a_width = max(a1.size(), a2.size());
|
int a_width = max(a1.size(), a2.size());
|
||||||
int y_width = max(y1.size(), y2.size());
|
int y_width = max(y1.size(), y2.size());
|
||||||
|
@ -547,8 +547,8 @@ struct ShareWorker
|
||||||
supercell->parameters[ID(A_SIGNED)] = a_signed;
|
supercell->parameters[ID(A_SIGNED)] = a_signed;
|
||||||
supercell->parameters[ID(A_WIDTH)] = a_width;
|
supercell->parameters[ID(A_WIDTH)] = a_width;
|
||||||
supercell->parameters[ID(Y_WIDTH)] = y_width;
|
supercell->parameters[ID(Y_WIDTH)] = y_width;
|
||||||
supercell->setPort(ID(A), a);
|
supercell->setPort(ID::A, a);
|
||||||
supercell->setPort(ID(Y), y);
|
supercell->setPort(ID::Y, y);
|
||||||
|
|
||||||
supercell_aux.insert(module->addPos(NEW_ID, y, y1));
|
supercell_aux.insert(module->addPos(NEW_ID, y, y1));
|
||||||
supercell_aux.insert(module->addPos(NEW_ID, y, y2));
|
supercell_aux.insert(module->addPos(NEW_ID, y, y2));
|
||||||
|
@ -571,9 +571,9 @@ struct ShareWorker
|
||||||
|
|
||||||
if (score_flipped < score_unflipped)
|
if (score_flipped < score_unflipped)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec tmp = c2->getPort(ID(A));
|
RTLIL::SigSpec tmp = c2->getPort(ID::A);
|
||||||
c2->setPort(ID(A), c2->getPort(ID(B)));
|
c2->setPort(ID::A, c2->getPort(ID::B));
|
||||||
c2->setPort(ID(B), tmp);
|
c2->setPort(ID::B, tmp);
|
||||||
|
|
||||||
std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH)));
|
std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH)));
|
||||||
std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED)));
|
std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED)));
|
||||||
|
@ -585,11 +585,11 @@ struct ShareWorker
|
||||||
|
|
||||||
{
|
{
|
||||||
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
|
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
|
||||||
if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) {
|
if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) {
|
||||||
unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
|
unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
|
||||||
RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A));
|
RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A);
|
||||||
new_a.append_bit(RTLIL::State::S0);
|
new_a.append_bit(RTLIL::State::S0);
|
||||||
unsigned_cell->setPort(ID(A), new_a);
|
unsigned_cell->setPort(ID::A, new_a);
|
||||||
}
|
}
|
||||||
unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
|
unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
|
||||||
modified_src_cells = true;
|
modified_src_cells = true;
|
||||||
|
@ -598,11 +598,11 @@ struct ShareWorker
|
||||||
if (c1->parameters.at(ID(B_SIGNED)).as_bool() != c2->parameters.at(ID(B_SIGNED)).as_bool())
|
if (c1->parameters.at(ID(B_SIGNED)).as_bool() != c2->parameters.at(ID(B_SIGNED)).as_bool())
|
||||||
{
|
{
|
||||||
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1;
|
RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1;
|
||||||
if (unsigned_cell->getPort(ID(B)).to_sigbit_vector().back() != RTLIL::State::S0) {
|
if (unsigned_cell->getPort(ID::B).to_sigbit_vector().back() != RTLIL::State::S0) {
|
||||||
unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1;
|
unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1;
|
||||||
RTLIL::SigSpec new_b = unsigned_cell->getPort(ID(B));
|
RTLIL::SigSpec new_b = unsigned_cell->getPort(ID::B);
|
||||||
new_b.append_bit(RTLIL::State::S0);
|
new_b.append_bit(RTLIL::State::S0);
|
||||||
unsigned_cell->setPort(ID(B), new_b);
|
unsigned_cell->setPort(ID::B, new_b);
|
||||||
}
|
}
|
||||||
unsigned_cell->parameters.at(ID(B_SIGNED)) = true;
|
unsigned_cell->parameters.at(ID(B_SIGNED)) = true;
|
||||||
modified_src_cells = true;
|
modified_src_cells = true;
|
||||||
|
@ -622,13 +622,13 @@ struct ShareWorker
|
||||||
if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr))
|
if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr))
|
||||||
b_signed = false;
|
b_signed = false;
|
||||||
|
|
||||||
RTLIL::SigSpec a1 = c1->getPort(ID(A));
|
RTLIL::SigSpec a1 = c1->getPort(ID::A);
|
||||||
RTLIL::SigSpec b1 = c1->getPort(ID(B));
|
RTLIL::SigSpec b1 = c1->getPort(ID::B);
|
||||||
RTLIL::SigSpec y1 = c1->getPort(ID(Y));
|
RTLIL::SigSpec y1 = c1->getPort(ID::Y);
|
||||||
|
|
||||||
RTLIL::SigSpec a2 = c2->getPort(ID(A));
|
RTLIL::SigSpec a2 = c2->getPort(ID::A);
|
||||||
RTLIL::SigSpec b2 = c2->getPort(ID(B));
|
RTLIL::SigSpec b2 = c2->getPort(ID::B);
|
||||||
RTLIL::SigSpec y2 = c2->getPort(ID(Y));
|
RTLIL::SigSpec y2 = c2->getPort(ID::Y);
|
||||||
|
|
||||||
int a_width = max(a1.size(), a2.size());
|
int a_width = max(a1.size(), a2.size());
|
||||||
int b_width = max(b1.size(), b2.size());
|
int b_width = max(b1.size(), b2.size());
|
||||||
|
@ -669,9 +669,9 @@ struct ShareWorker
|
||||||
supercell->parameters[ID(A_WIDTH)] = a_width;
|
supercell->parameters[ID(A_WIDTH)] = a_width;
|
||||||
supercell->parameters[ID(B_WIDTH)] = b_width;
|
supercell->parameters[ID(B_WIDTH)] = b_width;
|
||||||
supercell->parameters[ID(Y_WIDTH)] = y_width;
|
supercell->parameters[ID(Y_WIDTH)] = y_width;
|
||||||
supercell->setPort(ID(A), a);
|
supercell->setPort(ID::A, a);
|
||||||
supercell->setPort(ID(B), b);
|
supercell->setPort(ID::B, b);
|
||||||
supercell->setPort(ID(Y), y);
|
supercell->setPort(ID::Y, y);
|
||||||
if (c1->type == ID($alu)) {
|
if (c1->type == ID($alu)) {
|
||||||
RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID);
|
RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID);
|
||||||
supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci));
|
supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci));
|
||||||
|
@ -874,7 +874,7 @@ struct ShareWorker
|
||||||
}
|
}
|
||||||
for (auto &pbit : modwalker.signal_consumers[bit]) {
|
for (auto &pbit : modwalker.signal_consumers[bit]) {
|
||||||
log_assert(fwd_ct.cell_known(pbit.cell->type));
|
log_assert(fwd_ct.cell_known(pbit.cell->type));
|
||||||
if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID(A) || pbit.port == ID(B)))
|
if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID::A || pbit.port == ID::B))
|
||||||
driven_data_muxes.insert(pbit.cell);
|
driven_data_muxes.insert(pbit.cell);
|
||||||
else
|
else
|
||||||
driven_cells.insert(pbit.cell);
|
driven_cells.insert(pbit.cell);
|
||||||
|
@ -891,8 +891,8 @@ struct ShareWorker
|
||||||
std::set<int> used_in_b_parts;
|
std::set<int> used_in_b_parts;
|
||||||
|
|
||||||
int width = c->parameters.at(ID(WIDTH)).as_int();
|
int width = c->parameters.at(ID(WIDTH)).as_int();
|
||||||
std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort(ID(A)));
|
std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort(ID::A));
|
||||||
std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort(ID(B)));
|
std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort(ID::B));
|
||||||
std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort(ID(S)));
|
std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort(ID(S)));
|
||||||
|
|
||||||
for (auto &bit : sig_a)
|
for (auto &bit : sig_a)
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "kernel/modtools.h"
|
#include "kernel/modtools.h"
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
using namespace RTLIL;
|
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -64,10 +63,10 @@ struct WreduceWorker
|
||||||
{
|
{
|
||||||
// Reduce size of MUX if inputs agree on a value for a bit or a output bit is unused
|
// Reduce size of MUX if inputs agree on a value for a bit or a output bit is unused
|
||||||
|
|
||||||
SigSpec sig_a = mi.sigmap(cell->getPort(ID(A)));
|
SigSpec sig_a = mi.sigmap(cell->getPort(ID::A));
|
||||||
SigSpec sig_b = mi.sigmap(cell->getPort(ID(B)));
|
SigSpec sig_b = mi.sigmap(cell->getPort(ID::B));
|
||||||
SigSpec sig_s = mi.sigmap(cell->getPort(ID(S)));
|
SigSpec sig_s = mi.sigmap(cell->getPort(ID(S)));
|
||||||
SigSpec sig_y = mi.sigmap(cell->getPort(ID(Y)));
|
SigSpec sig_y = mi.sigmap(cell->getPort(ID::Y));
|
||||||
std::vector<SigBit> bits_removed;
|
std::vector<SigBit> bits_removed;
|
||||||
|
|
||||||
if (sig_y.has_const())
|
if (sig_y.has_const())
|
||||||
|
@ -77,15 +76,15 @@ struct WreduceWorker
|
||||||
{
|
{
|
||||||
auto info = mi.query(sig_y[i]);
|
auto info = mi.query(sig_y[i]);
|
||||||
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_y[i]))) {
|
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_y[i]))) {
|
||||||
bits_removed.push_back(Sx);
|
bits_removed.push_back(State::Sx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SigBit ref = sig_a[i];
|
SigBit ref = sig_a[i];
|
||||||
for (int k = 0; k < GetSize(sig_s); k++) {
|
for (int k = 0; k < GetSize(sig_s); k++) {
|
||||||
if ((config->keepdc || (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx)) && ref != sig_b[k*GetSize(sig_a) + i])
|
if ((config->keepdc || (ref != State::Sx && sig_b[k*GetSize(sig_a) + i] != State::Sx)) && ref != sig_b[k*GetSize(sig_a) + i])
|
||||||
goto no_match_ab;
|
goto no_match_ab;
|
||||||
if (sig_b[k*GetSize(sig_a) + i] != Sx)
|
if (sig_b[k*GetSize(sig_a) + i] != State::Sx)
|
||||||
ref = sig_b[k*GetSize(sig_a) + i];
|
ref = sig_b[k*GetSize(sig_a) + i];
|
||||||
}
|
}
|
||||||
if (0)
|
if (0)
|
||||||
|
@ -130,9 +129,9 @@ struct WreduceWorker
|
||||||
for (auto bit : new_work_queue_bits)
|
for (auto bit : new_work_queue_bits)
|
||||||
work_queue_bits.insert(bit);
|
work_queue_bits.insert(bit);
|
||||||
|
|
||||||
cell->setPort(ID(A), new_sig_a);
|
cell->setPort(ID::A, new_sig_a);
|
||||||
cell->setPort(ID(B), new_sig_b);
|
cell->setPort(ID::B, new_sig_b);
|
||||||
cell->setPort(ID(Y), new_sig_y);
|
cell->setPort(ID::Y, new_sig_y);
|
||||||
cell->fixup_parameters();
|
cell->fixup_parameters();
|
||||||
|
|
||||||
module->connect(sig_y.extract(n_kept, n_removed), sig_removed);
|
module->connect(sig_y.extract(n_kept, n_removed), sig_removed);
|
||||||
|
@ -245,7 +244,7 @@ struct WreduceWorker
|
||||||
while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == sig[GetSize(sig)-2])
|
while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == sig[GetSize(sig)-2])
|
||||||
work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++;
|
work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++;
|
||||||
} else {
|
} else {
|
||||||
while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == S0)
|
while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == State::S0)
|
||||||
work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++;
|
work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +269,7 @@ struct WreduceWorker
|
||||||
if (cell->type.in(ID($dff), ID($adff)))
|
if (cell->type.in(ID($dff), ID($adff)))
|
||||||
return run_cell_dff(cell);
|
return run_cell_dff(cell);
|
||||||
|
|
||||||
SigSpec sig = mi.sigmap(cell->getPort(ID(Y)));
|
SigSpec sig = mi.sigmap(cell->getPort(ID::Y));
|
||||||
|
|
||||||
if (sig.has_const())
|
if (sig.has_const())
|
||||||
return;
|
return;
|
||||||
|
@ -278,8 +277,8 @@ struct WreduceWorker
|
||||||
|
|
||||||
// Reduce size of ports A and B based on constant input bits and size of output port
|
// Reduce size of ports A and B based on constant input bits and size of output port
|
||||||
|
|
||||||
int max_port_a_size = cell->hasPort(ID(A)) ? GetSize(cell->getPort(ID(A))) : -1;
|
int max_port_a_size = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : -1;
|
||||||
int max_port_b_size = cell->hasPort(ID(B)) ? GetSize(cell->getPort(ID(B))) : -1;
|
int max_port_b_size = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : -1;
|
||||||
|
|
||||||
if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) {
|
if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) {
|
||||||
max_port_a_size = min(max_port_a_size, GetSize(sig));
|
max_port_a_size = min(max_port_a_size, GetSize(sig));
|
||||||
|
@ -295,8 +294,8 @@ struct WreduceWorker
|
||||||
if (max_port_b_size >= 0)
|
if (max_port_b_size >= 0)
|
||||||
run_reduce_inport(cell, 'B', max_port_b_size, port_b_signed, did_something);
|
run_reduce_inport(cell, 'B', max_port_b_size, port_b_signed, did_something);
|
||||||
|
|
||||||
if (cell->hasPort(ID(A)) && cell->hasPort(ID(B)) && port_a_signed && port_b_signed) {
|
if (cell->hasPort(ID::A) && cell->hasPort(ID::B) && port_a_signed && port_b_signed) {
|
||||||
SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))), sig_b = mi.sigmap(cell->getPort(ID(B)));
|
SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)), sig_b = mi.sigmap(cell->getPort(ID::B));
|
||||||
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 &&
|
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 &&
|
||||||
GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) {
|
GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) {
|
||||||
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
|
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
|
||||||
|
@ -309,8 +308,8 @@ struct WreduceWorker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->hasPort(ID(A)) && !cell->hasPort(ID(B)) && port_a_signed) {
|
if (cell->hasPort(ID::A) && !cell->hasPort(ID::B) && port_a_signed) {
|
||||||
SigSpec sig_a = mi.sigmap(cell->getPort(ID(A)));
|
SigSpec sig_a = mi.sigmap(cell->getPort(ID::A));
|
||||||
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) {
|
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) {
|
||||||
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
|
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
|
||||||
log_id(module), log_id(cell), log_id(cell->type));
|
log_id(module), log_id(cell), log_id(cell->type));
|
||||||
|
@ -347,8 +346,8 @@ struct WreduceWorker
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub);
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub);
|
||||||
|
|
||||||
int a_size = 0, b_size = 0;
|
int a_size = 0, b_size = 0;
|
||||||
if (cell->hasPort(ID(A))) a_size = GetSize(cell->getPort(ID(A)));
|
if (cell->hasPort(ID::A)) a_size = GetSize(cell->getPort(ID::A));
|
||||||
if (cell->hasPort(ID(B))) b_size = GetSize(cell->getPort(ID(B)));
|
if (cell->hasPort(ID::B)) b_size = GetSize(cell->getPort(ID::B));
|
||||||
|
|
||||||
int max_y_size = max(a_size, b_size);
|
int max_y_size = max(a_size, b_size);
|
||||||
|
|
||||||
|
@ -359,7 +358,7 @@ struct WreduceWorker
|
||||||
max_y_size = a_size + b_size;
|
max_y_size = a_size + b_size;
|
||||||
|
|
||||||
while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) {
|
while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) {
|
||||||
module->connect(sig[GetSize(sig)-1], is_signed ? sig[GetSize(sig)-2] : S0);
|
module->connect(sig[GetSize(sig)-1], is_signed ? sig[GetSize(sig)-2] : State::S0);
|
||||||
sig.remove(GetSize(sig)-1);
|
sig.remove(GetSize(sig)-1);
|
||||||
bits_removed++;
|
bits_removed++;
|
||||||
}
|
}
|
||||||
|
@ -374,7 +373,7 @@ struct WreduceWorker
|
||||||
if (bits_removed) {
|
if (bits_removed) {
|
||||||
log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n",
|
log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n",
|
||||||
bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type));
|
bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type));
|
||||||
cell->setPort(ID(Y), sig);
|
cell->setPort(ID::Y, sig);
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +397,7 @@ struct WreduceWorker
|
||||||
SigMap init_attr_sigmap = mi.sigmap;
|
SigMap init_attr_sigmap = mi.sigmap;
|
||||||
|
|
||||||
for (auto w : module->wires()) {
|
for (auto w : module->wires()) {
|
||||||
if (w->get_bool_attribute(ID(keep)))
|
if (w->get_bool_attribute(ID::keep))
|
||||||
for (auto bit : mi.sigmap(w))
|
for (auto bit : mi.sigmap(w))
|
||||||
keep_bits.insert(bit);
|
keep_bits.insert(bit);
|
||||||
if (w->attributes.count(ID(init))) {
|
if (w->attributes.count(ID(init))) {
|
||||||
|
@ -530,10 +529,10 @@ struct WreducePass : public Pass {
|
||||||
{
|
{
|
||||||
if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
|
if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
|
||||||
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
|
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
|
||||||
ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID(Y))) > 1) {
|
ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID::Y)) > 1) {
|
||||||
SigSpec sig = c->getPort(ID(Y));
|
SigSpec sig = c->getPort(ID::Y);
|
||||||
if (!sig.has_const()) {
|
if (!sig.has_const()) {
|
||||||
c->setPort(ID(Y), sig[0]);
|
c->setPort(ID::Y, sig[0]);
|
||||||
c->setParam(ID(Y_WIDTH), 1);
|
c->setParam(ID(Y_WIDTH), 1);
|
||||||
sig.remove(0);
|
sig.remove(0);
|
||||||
module->connect(sig, Const(0, GetSize(sig)));
|
module->connect(sig, Const(0, GetSize(sig)));
|
||||||
|
@ -542,7 +541,7 @@ struct WreducePass : public Pass {
|
||||||
|
|
||||||
if (c->type.in(ID($div), ID($mod), ID($pow)))
|
if (c->type.in(ID($div), ID($mod), ID($pow)))
|
||||||
{
|
{
|
||||||
SigSpec A = c->getPort(ID(A));
|
SigSpec A = c->getPort(ID::A);
|
||||||
int original_a_width = GetSize(A);
|
int original_a_width = GetSize(A);
|
||||||
if (c->getParam(ID(A_SIGNED)).as_bool()) {
|
if (c->getParam(ID(A_SIGNED)).as_bool()) {
|
||||||
while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0)
|
while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0)
|
||||||
|
@ -554,11 +553,11 @@ struct WreducePass : public Pass {
|
||||||
if (original_a_width != GetSize(A)) {
|
if (original_a_width != GetSize(A)) {
|
||||||
log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
|
log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
|
||||||
original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type));
|
original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type));
|
||||||
c->setPort(ID(A), A);
|
c->setPort(ID::A, A);
|
||||||
c->setParam(ID(A_WIDTH), GetSize(A));
|
c->setParam(ID(A_WIDTH), GetSize(A));
|
||||||
}
|
}
|
||||||
|
|
||||||
SigSpec B = c->getPort(ID(B));
|
SigSpec B = c->getPort(ID::B);
|
||||||
int original_b_width = GetSize(B);
|
int original_b_width = GetSize(B);
|
||||||
if (c->getParam(ID(B_SIGNED)).as_bool()) {
|
if (c->getParam(ID(B_SIGNED)).as_bool()) {
|
||||||
while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0)
|
while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0)
|
||||||
|
@ -570,7 +569,7 @@ struct WreducePass : public Pass {
|
||||||
if (original_b_width != GetSize(B)) {
|
if (original_b_width != GetSize(B)) {
|
||||||
log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
|
log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
|
||||||
original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type));
|
original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type));
|
||||||
c->setPort(ID(B), B);
|
c->setPort(ID::B, B);
|
||||||
c->setParam(ID(B_WIDTH), GetSize(B));
|
c->setParam(ID(B_WIDTH), GetSize(B));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
/ice40_dsp_pm.h
|
/*_pm.h
|
||||||
/peepopt_pm.h
|
|
|
@ -1,20 +1,29 @@
|
||||||
|
%_pm.h: passes/pmgen/pmgen.py %.pmg
|
||||||
|
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p $(subst _pm.h,,$(notdir $@)) $(filter-out $<,$^)
|
||||||
|
|
||||||
|
# --------------------------------------
|
||||||
|
|
||||||
|
OBJS += passes/pmgen/test_pmgen.o
|
||||||
|
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))
|
||||||
|
|
||||||
|
# --------------------------------------
|
||||||
|
|
||||||
OBJS += passes/pmgen/ice40_dsp.o
|
OBJS += passes/pmgen/ice40_dsp.o
|
||||||
OBJS += passes/pmgen/peepopt.o
|
|
||||||
|
|
||||||
# --------------------------------------
|
|
||||||
|
|
||||||
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
|
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
|
||||||
EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
|
$(eval $(call add_extra_objs,passes/pmgen/ice40_dsp_pm.h))
|
||||||
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
|
|
||||||
|
|
||||||
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
|
|
||||||
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_dsp $(filter-out $<,$^)
|
|
||||||
|
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
||||||
|
OBJS += passes/pmgen/ice40_wrapcarry.o
|
||||||
|
passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h
|
||||||
|
$(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h))
|
||||||
|
|
||||||
|
# --------------------------------------
|
||||||
|
|
||||||
|
OBJS += passes/pmgen/peepopt.o
|
||||||
passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
|
passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
|
||||||
EXTRA_OBJS += passes/pmgen/peepopt_pm.h
|
$(eval $(call add_extra_objs,passes/pmgen/peepopt_pm.h))
|
||||||
.SECONDARY: passes/pmgen/peepopt_pm.h
|
|
||||||
|
|
||||||
PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg
|
PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg
|
||||||
PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
|
PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
|
||||||
|
|
|
@ -45,9 +45,9 @@ of type `foobar_pm::state_<pattern_name>_t`.)
|
||||||
Similarly the `.pmg` file declares user data variables that become members of
|
Similarly the `.pmg` file declares user data variables that become members of
|
||||||
`.ud_<pattern_name>`, a struct of type `foobar_pm::udata_<pattern_name>_t`.
|
`.ud_<pattern_name>`, a struct of type `foobar_pm::udata_<pattern_name>_t`.
|
||||||
|
|
||||||
There are four versions of the `run_<pattern_name>()` method: Without callback,
|
There are three versions of the `run_<pattern_name>()` method: Without callback,
|
||||||
callback without arguments, callback with reference to `pm`, and callback with
|
callback without arguments, and callback with reference to `pm`. All versions
|
||||||
reference to `pm.st_<pattern_name>`.
|
of the `run_<pattern_name>()` method return the number of found matches.
|
||||||
|
|
||||||
|
|
||||||
The .pmg File Format
|
The .pmg File Format
|
||||||
|
@ -118,8 +118,8 @@ write matchers:
|
||||||
connected to any of the given signal bits, plus one if any of the signal
|
connected to any of the given signal bits, plus one if any of the signal
|
||||||
bits is also a primary input or primary output.
|
bits is also a primary input or primary output.
|
||||||
|
|
||||||
- In `code..endcode` blocks there exist `accept`, `reject`, and `branch`
|
- In `code..endcode` blocks there exist `accept`, `reject`, `branch`,
|
||||||
statements.
|
`finish`, and `subpattern` statements.
|
||||||
|
|
||||||
- In `index` statements there is a special `===` operator for the index
|
- In `index` statements there is a special `===` operator for the index
|
||||||
lookup.
|
lookup.
|
||||||
|
@ -175,6 +175,9 @@ explore the case where `mul` is set to `nullptr`. Without the `optional`
|
||||||
statement a match may only be assigned nullptr when one of the `if` expressions
|
statement a match may only be assigned nullptr when one of the `if` expressions
|
||||||
evaluates to `false`.
|
evaluates to `false`.
|
||||||
|
|
||||||
|
The `semioptional` statement marks matches that must match if at least one
|
||||||
|
matching cell exists, but if no matching cell exists it is set to `nullptr`.
|
||||||
|
|
||||||
Additional code
|
Additional code
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -232,5 +235,108 @@ But in some cases it is more natural to utilize the implicit branch statement:
|
||||||
portAB = \B;
|
portAB = \B;
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
There is an implicit `code..endcode` block at the end of each `.pmg` file
|
There is an implicit `code..endcode` block at the end of each (sub)pattern
|
||||||
that just accepts everything that gets all the way there.
|
that just rejects.
|
||||||
|
|
||||||
|
A `code..finally..endcode` block executes the code after `finally` during
|
||||||
|
back-tracking. This is useful for maintaining user data state or printing
|
||||||
|
debug messages. For example:
|
||||||
|
|
||||||
|
udata <vector<Cell*>> stack
|
||||||
|
|
||||||
|
code
|
||||||
|
stack.push_back(addAB);
|
||||||
|
...
|
||||||
|
finally
|
||||||
|
stack.pop_back();
|
||||||
|
endcode
|
||||||
|
|
||||||
|
`accept` and `finish` statements can be used inside the `finally` section,
|
||||||
|
but not `reject`, `branch`, or `subpattern`.
|
||||||
|
|
||||||
|
Declaring a subpattern
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
A subpattern starts with a line containing the `subpattern` keyword followed
|
||||||
|
by the name of the subpattern. Subpatterns can be called from a `code` block
|
||||||
|
using a `subpattern(<subpattern_name>);` C statement.
|
||||||
|
|
||||||
|
Arguments may be passed to subpattern via state variables. The `subpattern`
|
||||||
|
line must be followed by a `arg <arg1> <arg2> ...` line that lists the
|
||||||
|
state variables used to pass arguments.
|
||||||
|
|
||||||
|
state <IdString> foobar_type
|
||||||
|
state <bool> foobar_state
|
||||||
|
|
||||||
|
code foobar_type foobar_state
|
||||||
|
foobar_state = false;
|
||||||
|
foobar_type = $add;
|
||||||
|
subpattern(foo);
|
||||||
|
foobar_type = $sub;
|
||||||
|
subpattern(bar);
|
||||||
|
endcode
|
||||||
|
|
||||||
|
subpattern foo
|
||||||
|
arg foobar_type foobar_state
|
||||||
|
|
||||||
|
match addsub
|
||||||
|
index <IdString> addsub->type === foobar_type
|
||||||
|
...
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
if (foobar_state) {
|
||||||
|
subpattern(tail);
|
||||||
|
} else {
|
||||||
|
foobar_state = true;
|
||||||
|
subpattern(bar);
|
||||||
|
}
|
||||||
|
endcode
|
||||||
|
|
||||||
|
subpattern bar
|
||||||
|
arg foobar_type foobar_state
|
||||||
|
|
||||||
|
match addsub
|
||||||
|
index <IdString> addsub->type === foobar_type
|
||||||
|
...
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
if (foobar_state) {
|
||||||
|
subpattern(tail);
|
||||||
|
} else {
|
||||||
|
foobar_state = true;
|
||||||
|
subpattern(foo);
|
||||||
|
}
|
||||||
|
endcode
|
||||||
|
|
||||||
|
subpattern tail
|
||||||
|
...
|
||||||
|
|
||||||
|
Subpatterns cann be called recursively.
|
||||||
|
|
||||||
|
If a `subpattern` statement is preceded by a `fallthrough` statement, this is
|
||||||
|
equivalent to calling the subpattern at the end of the preceding block.
|
||||||
|
|
||||||
|
Generate Blocks
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Match blocks may contain an optional `generate` section that is used for automatic
|
||||||
|
test-case generation. For example:
|
||||||
|
|
||||||
|
match mul
|
||||||
|
...
|
||||||
|
generate 10
|
||||||
|
SigSpec Y = port(ff, \D);
|
||||||
|
SigSpec A = module->addWire(NEW_ID, GetSize(Y) - rng(GetSize(Y)/2));
|
||||||
|
SigSpec B = module->addWire(NEW_ID, GetSize(Y) - rng(GetSize(Y)/2));
|
||||||
|
module->addMul(NEW_ID, A, B, Y, rng(2));
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
The expression `rng(n)` returns a non-negative integer less than `n`.
|
||||||
|
|
||||||
|
The argument to `generate` is the chance of this generate block being executed
|
||||||
|
when the match block did not match anything, in percent.
|
||||||
|
|
||||||
|
The special statement `finish` can be used within generate blocks to terminate
|
||||||
|
the current pattern matcher run.
|
||||||
|
|
|
@ -159,4 +159,5 @@ code clock clock_pol clock_vld
|
||||||
clock_pol = cp;
|
clock_pol = cp;
|
||||||
clock_vld = true;
|
clock_vld = true;
|
||||||
}
|
}
|
||||||
|
accept;
|
||||||
endcode
|
endcode
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#include "passes/pmgen/ice40_wrapcarry_pm.h"
|
||||||
|
|
||||||
|
void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
|
||||||
|
{
|
||||||
|
auto &st = pm.st_ice40_wrapcarry;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
log("\n");
|
||||||
|
log("carry: %s\n", log_id(st.carry, "--"));
|
||||||
|
log("lut: %s\n", log_id(st.lut, "--"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n");
|
||||||
|
|
||||||
|
Cell *cell = pm.module->addCell(NEW_ID, "$__ICE40_CARRY_WRAPPER");
|
||||||
|
pm.module->swap_names(cell, st.carry);
|
||||||
|
|
||||||
|
cell->setPort("\\A", st.carry->getPort("\\I0"));
|
||||||
|
cell->setPort("\\B", st.carry->getPort("\\I1"));
|
||||||
|
cell->setPort("\\CI", st.carry->getPort("\\CI"));
|
||||||
|
cell->setPort("\\CO", st.carry->getPort("\\CO"));
|
||||||
|
|
||||||
|
cell->setPort("\\I0", st.lut->getPort("\\I0"));
|
||||||
|
cell->setPort("\\I3", st.lut->getPort("\\I3"));
|
||||||
|
cell->setPort("\\O", st.lut->getPort("\\O"));
|
||||||
|
cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT"));
|
||||||
|
|
||||||
|
pm.autoremove(st.carry);
|
||||||
|
pm.autoremove(st.lut);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Ice40WrapCarryPass : public Pass {
|
||||||
|
Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" ice40_wrapcarry [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n");
|
||||||
|
log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n");
|
||||||
|
log("mapping.");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\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())
|
||||||
|
ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
|
||||||
|
}
|
||||||
|
} Ice40WrapCarryPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,11 @@
|
||||||
|
pattern ice40_wrapcarry
|
||||||
|
|
||||||
|
match carry
|
||||||
|
select carry->type.in(\SB_CARRY)
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
match lut
|
||||||
|
select lut->type.in(\SB_LUT4)
|
||||||
|
index <SigSpec> port(lut, \I1) === port(carry, \I0)
|
||||||
|
index <SigSpec> port(lut, \I2) === port(carry, \I1)
|
||||||
|
endmatch
|
|
@ -32,5 +32,5 @@ code
|
||||||
log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div));
|
log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div));
|
||||||
module->connect(div_y, val_y);
|
module->connect(div_y, val_y);
|
||||||
autoremove(div);
|
autoremove(div);
|
||||||
reject;
|
accept;
|
||||||
endcode
|
endcode
|
||||||
|
|
|
@ -34,6 +34,7 @@ match mul
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
code
|
code
|
||||||
|
{
|
||||||
IdString const_factor_port = port(mul, \A).is_fully_const() ? \A : \B;
|
IdString const_factor_port = port(mul, \A).is_fully_const() ? \A : \B;
|
||||||
IdString const_factor_signed = const_factor_port == \A ? \A_SIGNED : \B_SIGNED;
|
IdString const_factor_signed = const_factor_port == \A ? \A_SIGNED : \B_SIGNED;
|
||||||
Const const_factor_cnst = port(mul, const_factor_port).as_const();
|
Const const_factor_cnst = port(mul, const_factor_port).as_const();
|
||||||
|
@ -90,5 +91,6 @@ code
|
||||||
shift->setParam(\B_WIDTH, GetSize(new_b));
|
shift->setParam(\B_WIDTH, GetSize(new_b));
|
||||||
|
|
||||||
blacklist(shift);
|
blacklist(shift);
|
||||||
reject;
|
accept;
|
||||||
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
|
@ -38,7 +38,10 @@ for a in args:
|
||||||
assert prefix is not None
|
assert prefix is not None
|
||||||
|
|
||||||
current_pattern = None
|
current_pattern = None
|
||||||
|
current_subpattern = None
|
||||||
patterns = dict()
|
patterns = dict()
|
||||||
|
subpatterns = dict()
|
||||||
|
subpattern_args = dict()
|
||||||
state_types = dict()
|
state_types = dict()
|
||||||
udata_types = dict()
|
udata_types = dict()
|
||||||
blocks = list()
|
blocks = list()
|
||||||
|
@ -104,9 +107,12 @@ def rewrite_cpp(s):
|
||||||
|
|
||||||
return "".join(t)
|
return "".join(t)
|
||||||
|
|
||||||
def process_pmgfile(f):
|
def process_pmgfile(f, filename):
|
||||||
|
linenr = 0
|
||||||
global current_pattern
|
global current_pattern
|
||||||
|
global current_subpattern
|
||||||
while True:
|
while True:
|
||||||
|
linenr += 1
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
if line == "": break
|
if line == "": break
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
|
@ -119,19 +125,52 @@ def process_pmgfile(f):
|
||||||
if current_pattern is not None:
|
if current_pattern is not None:
|
||||||
block = dict()
|
block = dict()
|
||||||
block["type"] = "final"
|
block["type"] = "final"
|
||||||
block["pattern"] = current_pattern
|
block["pattern"] = (current_pattern, current_subpattern)
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
line = line.split()
|
line = line.split()
|
||||||
assert len(line) == 2
|
assert len(line) == 2
|
||||||
assert line[1] not in patterns
|
assert line[1] not in patterns
|
||||||
current_pattern = line[1]
|
current_pattern = line[1]
|
||||||
|
current_subpattern = ""
|
||||||
patterns[current_pattern] = len(blocks)
|
patterns[current_pattern] = len(blocks)
|
||||||
|
subpatterns[(current_pattern, current_subpattern)] = len(blocks)
|
||||||
|
subpattern_args[(current_pattern, current_subpattern)] = list()
|
||||||
state_types[current_pattern] = dict()
|
state_types[current_pattern] = dict()
|
||||||
udata_types[current_pattern] = dict()
|
udata_types[current_pattern] = dict()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
assert current_pattern is not None
|
assert current_pattern is not None
|
||||||
|
|
||||||
|
if cmd == "fallthrough":
|
||||||
|
block = dict()
|
||||||
|
block["type"] = "fallthrough"
|
||||||
|
blocks.append(block)
|
||||||
|
line = line.split()
|
||||||
|
assert len(line) == 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if cmd == "subpattern":
|
||||||
|
if len(blocks) == 0 or blocks[-1]["type"] != "fallthrough":
|
||||||
|
block = dict()
|
||||||
|
block["type"] = "final"
|
||||||
|
block["pattern"] = (current_pattern, current_subpattern)
|
||||||
|
blocks.append(block)
|
||||||
|
elif len(blocks) and blocks[-1]["type"] == "fallthrough":
|
||||||
|
del blocks[-1]
|
||||||
|
line = line.split()
|
||||||
|
assert len(line) == 2
|
||||||
|
current_subpattern = line[1]
|
||||||
|
subpattern_args[(current_pattern, current_subpattern)] = list()
|
||||||
|
assert (current_pattern, current_subpattern) not in subpatterns
|
||||||
|
subpatterns[(current_pattern, current_subpattern)] = len(blocks)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if cmd == "arg":
|
||||||
|
line = line.split()
|
||||||
|
assert len(line) > 1
|
||||||
|
subpattern_args[(current_pattern, current_subpattern)] += line[1:]
|
||||||
|
continue
|
||||||
|
|
||||||
if cmd == "state":
|
if cmd == "state":
|
||||||
m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)
|
m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)
|
||||||
assert m
|
assert m
|
||||||
|
@ -155,11 +194,15 @@ def process_pmgfile(f):
|
||||||
if cmd == "match":
|
if cmd == "match":
|
||||||
block = dict()
|
block = dict()
|
||||||
block["type"] = "match"
|
block["type"] = "match"
|
||||||
block["pattern"] = current_pattern
|
block["src"] = "%s:%d" % (filename, linenr)
|
||||||
|
block["pattern"] = (current_pattern, current_subpattern)
|
||||||
|
|
||||||
|
block["genargs"] = None
|
||||||
|
block["gencode"] = None
|
||||||
|
|
||||||
line = line.split()
|
line = line.split()
|
||||||
assert len(line) == 2
|
assert len(line) == 2
|
||||||
assert line[1] not in state_types[current_pattern]
|
assert (line[1] not in state_types[current_pattern]) or (state_types[current_pattern][line[1]] == "Cell*")
|
||||||
block["cell"] = line[1]
|
block["cell"] = line[1]
|
||||||
state_types[current_pattern][line[1]] = "Cell*";
|
state_types[current_pattern][line[1]] = "Cell*";
|
||||||
|
|
||||||
|
@ -168,8 +211,10 @@ def process_pmgfile(f):
|
||||||
block["index"] = list()
|
block["index"] = list()
|
||||||
block["filter"] = list()
|
block["filter"] = list()
|
||||||
block["optional"] = False
|
block["optional"] = False
|
||||||
|
block["semioptional"] = False
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
linenr += 1
|
||||||
l = f.readline()
|
l = f.readline()
|
||||||
assert l != ""
|
assert l != ""
|
||||||
a = l.split()
|
a = l.split()
|
||||||
|
@ -201,31 +246,60 @@ def process_pmgfile(f):
|
||||||
block["optional"] = True
|
block["optional"] = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if a[0] == "semioptional":
|
||||||
|
block["semioptional"] = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
if a[0] == "generate":
|
||||||
|
block["genargs"] = list([int(s) for s in a[1:]])
|
||||||
|
block["gencode"] = list()
|
||||||
|
assert len(block["genargs"]) < 2
|
||||||
|
while True:
|
||||||
|
linenr += 1
|
||||||
|
l = f.readline()
|
||||||
|
assert l != ""
|
||||||
|
a = l.split()
|
||||||
|
if a[0] == "endmatch": break
|
||||||
|
block["gencode"].append(rewrite_cpp(l.rstrip()))
|
||||||
|
break
|
||||||
|
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
if block["optional"]:
|
||||||
|
assert not block["semioptional"]
|
||||||
|
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if cmd == "code":
|
if cmd == "code":
|
||||||
block = dict()
|
block = dict()
|
||||||
block["type"] = "code"
|
block["type"] = "code"
|
||||||
block["pattern"] = current_pattern
|
block["src"] = "%s:%d" % (filename, linenr)
|
||||||
|
block["pattern"] = (current_pattern, current_subpattern)
|
||||||
|
|
||||||
block["code"] = list()
|
block["code"] = list()
|
||||||
|
block["fcode"] = list()
|
||||||
block["states"] = set()
|
block["states"] = set()
|
||||||
|
|
||||||
for s in line.split()[1:]:
|
for s in line.split()[1:]:
|
||||||
assert s in state_types[current_pattern]
|
assert s in state_types[current_pattern]
|
||||||
block["states"].add(s)
|
block["states"].add(s)
|
||||||
|
|
||||||
|
codetype = "code"
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
linenr += 1
|
||||||
l = f.readline()
|
l = f.readline()
|
||||||
assert l != ""
|
assert l != ""
|
||||||
a = l.split()
|
a = l.split()
|
||||||
if len(a) == 0: continue
|
if len(a) == 0: continue
|
||||||
if a[0] == "endcode": break
|
if a[0] == "endcode": break
|
||||||
|
|
||||||
block["code"].append(rewrite_cpp(l.rstrip()))
|
if a[0] == "finally":
|
||||||
|
codetype = "fcode"
|
||||||
|
continue
|
||||||
|
|
||||||
|
block[codetype].append(rewrite_cpp(l.rstrip()))
|
||||||
|
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
continue
|
continue
|
||||||
|
@ -234,15 +308,16 @@ def process_pmgfile(f):
|
||||||
|
|
||||||
for fn in pmgfiles:
|
for fn in pmgfiles:
|
||||||
with open(fn, "r") as f:
|
with open(fn, "r") as f:
|
||||||
process_pmgfile(f)
|
process_pmgfile(f, fn)
|
||||||
|
|
||||||
if current_pattern is not None:
|
if current_pattern is not None:
|
||||||
block = dict()
|
block = dict()
|
||||||
block["type"] = "final"
|
block["type"] = "final"
|
||||||
block["pattern"] = current_pattern
|
block["pattern"] = (current_pattern, current_subpattern)
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
|
|
||||||
current_pattern = None
|
current_pattern = None
|
||||||
|
current_subpattern = None
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
pp.pprint(blocks)
|
pp.pprint(blocks)
|
||||||
|
@ -262,7 +337,18 @@ with open(outfile, "w") as f:
|
||||||
print("struct {}_pm {{".format(prefix), file=f)
|
print("struct {}_pm {{".format(prefix), file=f)
|
||||||
print(" Module *module;", file=f)
|
print(" Module *module;", file=f)
|
||||||
print(" SigMap sigmap;", file=f)
|
print(" SigMap sigmap;", file=f)
|
||||||
print(" std::function<void()> on_accept;".format(prefix), file=f)
|
print(" std::function<void()> on_accept;", file=f)
|
||||||
|
print(" bool generate_mode;", file=f)
|
||||||
|
print(" int accept_cnt;", file=f)
|
||||||
|
print("", file=f)
|
||||||
|
|
||||||
|
print(" uint32_t rngseed;", file=f)
|
||||||
|
print(" int rng(unsigned int n) {", file=f)
|
||||||
|
print(" rngseed ^= rngseed << 13;", file=f)
|
||||||
|
print(" rngseed ^= rngseed >> 17;", file=f)
|
||||||
|
print(" rngseed ^= rngseed << 5;", file=f)
|
||||||
|
print(" return rngseed % n;", file=f)
|
||||||
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
for index in range(len(blocks)):
|
for index in range(len(blocks)):
|
||||||
|
@ -276,7 +362,7 @@ with open(outfile, "w") as f:
|
||||||
print(" dict<SigBit, pool<Cell*>> sigusers;", file=f)
|
print(" dict<SigBit, pool<Cell*>> sigusers;", file=f)
|
||||||
print(" pool<Cell*> blacklist_cells;", file=f)
|
print(" pool<Cell*> blacklist_cells;", file=f)
|
||||||
print(" pool<Cell*> autoremove_cells;", file=f)
|
print(" pool<Cell*> autoremove_cells;", file=f)
|
||||||
print(" bool blacklist_dirty;", file=f)
|
print(" dict<Cell*,int> rollback_cache;", file=f)
|
||||||
print(" int rollback;", file=f)
|
print(" int rollback;", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
|
@ -312,39 +398,24 @@ with open(outfile, "w") as f:
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print(" void blacklist(Cell *cell) {", file=f)
|
print(" void blacklist(Cell *cell) {", file=f)
|
||||||
print(" if (cell != nullptr) {", file=f)
|
print(" if (cell != nullptr && blacklist_cells.insert(cell).second) {", file=f)
|
||||||
print(" if (blacklist_cells.insert(cell).second)", file=f)
|
print(" auto ptr = rollback_cache.find(cell);", file=f)
|
||||||
print(" blacklist_dirty = true;", file=f)
|
print(" if (ptr == rollback_cache.end()) return;", file=f)
|
||||||
|
print(" int rb = ptr->second;", file=f)
|
||||||
|
print(" if (rollback == 0 || rollback > rb)", file=f)
|
||||||
|
print(" rollback = rb;", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print(" void autoremove(Cell *cell) {", file=f)
|
print(" void autoremove(Cell *cell) {", file=f)
|
||||||
print(" if (cell != nullptr) {", file=f)
|
print(" if (cell != nullptr) {", file=f)
|
||||||
print(" if (blacklist_cells.insert(cell).second)", file=f)
|
|
||||||
print(" blacklist_dirty = true;", file=f)
|
|
||||||
print(" autoremove_cells.insert(cell);", file=f)
|
print(" autoremove_cells.insert(cell);", file=f)
|
||||||
|
print(" blacklist(cell);", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
for current_pattern in sorted(patterns.keys()):
|
|
||||||
print(" void check_blacklist_{}() {{".format(current_pattern), file=f)
|
|
||||||
print(" if (!blacklist_dirty)", file=f)
|
|
||||||
print(" return;", file=f)
|
|
||||||
print(" blacklist_dirty = false;", file=f)
|
|
||||||
for index in range(len(blocks)):
|
|
||||||
block = blocks[index]
|
|
||||||
if block["pattern"] != current_pattern:
|
|
||||||
continue
|
|
||||||
if block["type"] == "match":
|
|
||||||
print(" if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern, block["cell"], current_pattern, block["cell"]), file=f)
|
|
||||||
print(" rollback = {};".format(index+1), file=f)
|
|
||||||
print(" return;", file=f)
|
|
||||||
print(" }", file=f)
|
|
||||||
print(" rollback = 0;", file=f)
|
|
||||||
print(" }", file=f)
|
|
||||||
print("", file=f)
|
|
||||||
current_pattern = None
|
current_pattern = None
|
||||||
|
|
||||||
print(" SigSpec port(Cell *cell, IdString portname) {", file=f)
|
print(" SigSpec port(Cell *cell, IdString portname) {", file=f)
|
||||||
|
@ -367,7 +438,7 @@ with open(outfile, "w") as f:
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f)
|
print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f)
|
||||||
print(" module(module), sigmap(module) {", file=f)
|
print(" module(module), sigmap(module), generate_mode(false), rngseed(12345678) {", file=f)
|
||||||
for current_pattern in sorted(patterns.keys()):
|
for current_pattern in sorted(patterns.keys()):
|
||||||
for s, t in sorted(udata_types[current_pattern].items()):
|
for s, t in sorted(udata_types[current_pattern].items()):
|
||||||
if t.endswith("*"):
|
if t.endswith("*"):
|
||||||
|
@ -405,41 +476,47 @@ with open(outfile, "w") as f:
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
for current_pattern in sorted(patterns.keys()):
|
for current_pattern in sorted(patterns.keys()):
|
||||||
print(" void run_{}(std::function<void()> on_accept_f) {{".format(current_pattern), file=f)
|
print(" int run_{}(std::function<void()> on_accept_f) {{".format(current_pattern), file=f)
|
||||||
|
print(" accept_cnt = 0;", file=f)
|
||||||
print(" on_accept = on_accept_f;", file=f)
|
print(" on_accept = on_accept_f;", file=f)
|
||||||
print(" rollback = 0;", file=f)
|
print(" rollback = 0;", file=f)
|
||||||
print(" blacklist_dirty = false;", file=f)
|
|
||||||
for s, t in sorted(state_types[current_pattern].items()):
|
for s, t in sorted(state_types[current_pattern].items()):
|
||||||
if t.endswith("*"):
|
if t.endswith("*"):
|
||||||
print(" st_{}.{} = nullptr;".format(current_pattern, s), file=f)
|
print(" st_{}.{} = nullptr;".format(current_pattern, s), file=f)
|
||||||
else:
|
else:
|
||||||
print(" st_{}.{} = {}();".format(current_pattern, s, t), file=f)
|
print(" st_{}.{} = {}();".format(current_pattern, s, t), file=f)
|
||||||
print(" block_{}();".format(patterns[current_pattern]), file=f)
|
print(" block_{}(1);".format(patterns[current_pattern]), file=f)
|
||||||
|
print(" log_assert(rollback_cache.empty());", file=f)
|
||||||
|
print(" return accept_cnt;", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" void run_{}(std::function<void({}_pm&)> on_accept_f) {{".format(current_pattern, prefix), file=f)
|
print(" int run_{}(std::function<void({}_pm&)> on_accept_f) {{".format(current_pattern, prefix), file=f)
|
||||||
print(" run_{}([&](){{on_accept_f(*this);}});".format(current_pattern), file=f)
|
print(" return run_{}([&](){{on_accept_f(*this);}});".format(current_pattern), file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" void run_{}(std::function<void(state_{}_t&)> on_accept_f) {{".format(current_pattern, current_pattern), file=f)
|
print(" int run_{}() {{".format(current_pattern), file=f)
|
||||||
print(" run_{}([&](){{on_accept_f(st_{});}});".format(current_pattern, current_pattern), file=f)
|
print(" return run_{}([](){{}});".format(current_pattern, current_pattern), file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" void run_{}() {{".format(current_pattern), file=f)
|
|
||||||
print(" run_{}([](){{}});".format(current_pattern, current_pattern), file=f)
|
if len(subpatterns):
|
||||||
print(" }", file=f)
|
for p, s in sorted(subpatterns.keys()):
|
||||||
|
print(" void block_subpattern_{}_{}(int recursion) {{ block_{}(recursion); }}".format(p, s, subpatterns[(p, s)]), file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
current_pattern = None
|
current_pattern = None
|
||||||
|
current_subpattern = None
|
||||||
|
|
||||||
for index in range(len(blocks)):
|
for index in range(len(blocks)):
|
||||||
block = blocks[index]
|
block = blocks[index]
|
||||||
|
|
||||||
print(" void block_{}() {{".format(index), file=f)
|
if block["type"] in ("match", "code"):
|
||||||
current_pattern = block["pattern"]
|
print(" // {}".format(block["src"]), file=f)
|
||||||
|
|
||||||
|
print(" void block_{}(int recursion YS_ATTRIBUTE(unused)) {{".format(index), file=f)
|
||||||
|
current_pattern, current_subpattern = block["pattern"]
|
||||||
|
|
||||||
if block["type"] == "final":
|
if block["type"] == "final":
|
||||||
print(" on_accept();", file=f)
|
|
||||||
print(" check_blacklist_{}();".format(current_pattern), file=f)
|
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
if index+1 != len(blocks):
|
if index+1 != len(blocks):
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
@ -449,7 +526,10 @@ with open(outfile, "w") as f:
|
||||||
nonconst_st = set()
|
nonconst_st = set()
|
||||||
restore_st = set()
|
restore_st = set()
|
||||||
|
|
||||||
for i in range(patterns[current_pattern], index):
|
for s in subpattern_args[(current_pattern, current_subpattern)]:
|
||||||
|
const_st.add(s)
|
||||||
|
|
||||||
|
for i in range(subpatterns[(current_pattern, current_subpattern)], index):
|
||||||
if blocks[i]["type"] == "code":
|
if blocks[i]["type"] == "code":
|
||||||
for s in blocks[i]["states"]:
|
for s in blocks[i]["states"]:
|
||||||
const_st.add(s)
|
const_st.add(s)
|
||||||
|
@ -482,6 +562,10 @@ with open(outfile, "w") as f:
|
||||||
t = state_types[current_pattern][s]
|
t = state_types[current_pattern][s]
|
||||||
print(" {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
|
print(" {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
|
||||||
|
|
||||||
|
for u in sorted(udata_types[current_pattern].keys()):
|
||||||
|
t = udata_types[current_pattern][u]
|
||||||
|
print(" {} &{} YS_ATTRIBUTE(unused) = ud_{}.{};".format(t, u, current_pattern, u), file=f)
|
||||||
|
|
||||||
if len(restore_st):
|
if len(restore_st):
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
for s in sorted(restore_st):
|
for s in sorted(restore_st):
|
||||||
|
@ -490,24 +574,38 @@ with open(outfile, "w") as f:
|
||||||
|
|
||||||
if block["type"] == "code":
|
if block["type"] == "code":
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" do {", file=f)
|
print("#define reject do { goto rollback_label; } while(0)", file=f)
|
||||||
print("#define reject do {{ check_blacklist_{}(); goto rollback_label; }} while(0)".format(current_pattern), file=f)
|
print("#define accept do { accept_cnt++; on_accept(); if (rollback) goto rollback_label; } while(0)", file=f)
|
||||||
print("#define accept do {{ on_accept(); check_blacklist_{}(); if (rollback) goto rollback_label; }} while(0)".format(current_pattern), file=f)
|
print("#define finish do { rollback = -1; goto rollback_label; } while(0)", file=f)
|
||||||
print("#define branch do {{ block_{}(); if (rollback) goto rollback_label; }} while(0)".format(index+1), file=f)
|
print("#define branch do {{ block_{}(recursion+1); if (rollback) goto rollback_label; }} while(0)".format(index+1), file=f)
|
||||||
|
print("#define subpattern(pattern_name) do {{ block_subpattern_{}_ ## pattern_name (recursion+1); if (rollback) goto rollback_label; }} while(0)".format(current_pattern), file=f)
|
||||||
|
|
||||||
for line in block["code"]:
|
for line in block["code"]:
|
||||||
print(" " + line, file=f)
|
print(" " + line, file=f)
|
||||||
|
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" block_{}();".format(index+1), file=f)
|
print(" block_{}(recursion+1);".format(index+1), file=f)
|
||||||
|
|
||||||
print("#undef reject", file=f)
|
print("#undef reject", file=f)
|
||||||
print("#undef accept", file=f)
|
print("#undef accept", file=f)
|
||||||
|
print("#undef finish", file=f)
|
||||||
print("#undef branch", file=f)
|
print("#undef branch", file=f)
|
||||||
print(" } while (0);", file=f)
|
print("#undef subpattern", file=f)
|
||||||
|
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print("rollback_label:", file=f)
|
print("rollback_label:", file=f)
|
||||||
print(" YS_ATTRIBUTE(unused);", file=f)
|
print(" YS_ATTRIBUTE(unused);", file=f)
|
||||||
|
|
||||||
|
if len(block["fcode"]):
|
||||||
|
print("#define accept do { accept_cnt++; on_accept(); } while(0)", file=f)
|
||||||
|
print("#define finish do { rollback = -1; goto finish_label; } while(0)", file=f)
|
||||||
|
for line in block["fcode"]:
|
||||||
|
print(" " + line, file=f)
|
||||||
|
print("finish_label:", file=f)
|
||||||
|
print(" YS_ATTRIBUTE(unused);", file=f)
|
||||||
|
print("#undef accept", file=f)
|
||||||
|
print("#undef finish", file=f)
|
||||||
|
|
||||||
if len(restore_st) or len(nonconst_st):
|
if len(restore_st) or len(nonconst_st):
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
for s in sorted(restore_st):
|
for s in sorted(restore_st):
|
||||||
|
@ -524,12 +622,15 @@ with open(outfile, "w") as f:
|
||||||
elif block["type"] == "match":
|
elif block["type"] == "match":
|
||||||
assert len(restore_st) == 0
|
assert len(restore_st) == 0
|
||||||
|
|
||||||
|
print(" Cell* backup_{} = {};".format(block["cell"], block["cell"]), file=f)
|
||||||
|
|
||||||
if len(block["if"]):
|
if len(block["if"]):
|
||||||
for expr in block["if"]:
|
for expr in block["if"]:
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" if (!({})) {{".format(expr), file=f)
|
print(" if (!({})) {{".format(expr), file=f)
|
||||||
print(" {} = nullptr;".format(block["cell"]), file=f)
|
print(" {} = nullptr;".format(block["cell"]), file=f)
|
||||||
print(" block_{}();".format(index+1), file=f)
|
print(" block_{}(recursion+1);".format(index+1), file=f)
|
||||||
|
print(" {} = backup_{};".format(block["cell"], block["cell"]), file=f)
|
||||||
print(" return;", file=f)
|
print(" return;", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
|
|
||||||
|
@ -537,21 +638,32 @@ with open(outfile, "w") as f:
|
||||||
print(" index_{}_key_type key;".format(index), file=f)
|
print(" index_{}_key_type key;".format(index), file=f)
|
||||||
for field, entry in enumerate(block["index"]):
|
for field, entry in enumerate(block["index"]):
|
||||||
print(" std::get<{}>(key) = {};".format(field, entry[2]), file=f)
|
print(" std::get<{}>(key) = {};".format(field, entry[2]), file=f)
|
||||||
print(" const vector<Cell*> &cells = index_{}[key];".format(index), file=f)
|
print(" auto cells_ptr = index_{}.find(key);".format(index), file=f)
|
||||||
|
|
||||||
|
if block["semioptional"] or block["genargs"] is not None:
|
||||||
|
print(" bool found_any_match = false;", file=f)
|
||||||
|
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
print(" for (int idx = 0; idx < GetSize(cells); idx++) {", file=f)
|
print(" if (cells_ptr != index_{}.end()) {{".format(index), file=f)
|
||||||
print(" {} = cells[idx];".format(block["cell"]), file=f)
|
print(" const vector<Cell*> &cells = cells_ptr->second;".format(index), file=f)
|
||||||
print(" if (blacklist_cells.count({})) continue;".format(block["cell"]), file=f)
|
print(" for (int idx = 0; idx < GetSize(cells); idx++) {", file=f)
|
||||||
|
print(" {} = cells[idx];".format(block["cell"]), file=f)
|
||||||
|
print(" if (blacklist_cells.count({})) continue;".format(block["cell"]), file=f)
|
||||||
for expr in block["filter"]:
|
for expr in block["filter"]:
|
||||||
print(" if (!({})) continue;".format(expr), file=f)
|
print(" if (!({})) continue;".format(expr), file=f)
|
||||||
print(" block_{}();".format(index+1), file=f)
|
if block["semioptional"] or block["genargs"] is not None:
|
||||||
print(" if (rollback) {", file=f)
|
print(" found_any_match = true;", file=f)
|
||||||
print(" if (rollback != {}) {{".format(index+1), file=f)
|
print(" auto rollback_ptr = rollback_cache.insert(make_pair(cells[idx], recursion));", file=f)
|
||||||
print(" {} = nullptr;".format(block["cell"]), file=f)
|
print(" block_{}(recursion+1);".format(index+1), file=f)
|
||||||
print(" return;", file=f)
|
print(" if (rollback_ptr.second)", file=f)
|
||||||
|
print(" rollback_cache.erase(rollback_ptr.first);", file=f)
|
||||||
|
print(" if (rollback) {", file=f)
|
||||||
|
print(" if (rollback != recursion) {{".format(index+1), file=f)
|
||||||
|
print(" {} = backup_{};".format(block["cell"], block["cell"]), file=f)
|
||||||
|
print(" return;", file=f)
|
||||||
|
print(" }", file=f)
|
||||||
|
print(" rollback = 0;", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print(" rollback = 0;", file=f)
|
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
print(" }", file=f)
|
print(" }", file=f)
|
||||||
|
|
||||||
|
@ -559,8 +671,22 @@ with open(outfile, "w") as f:
|
||||||
print(" {} = nullptr;".format(block["cell"]), file=f)
|
print(" {} = nullptr;".format(block["cell"]), file=f)
|
||||||
|
|
||||||
if block["optional"]:
|
if block["optional"]:
|
||||||
print(" block_{}();".format(index+1), file=f)
|
print(" block_{}(recursion+1);".format(index+1), file=f)
|
||||||
|
|
||||||
|
if block["semioptional"]:
|
||||||
|
print(" if (!found_any_match) block_{}(recursion+1);".format(index+1), file=f)
|
||||||
|
|
||||||
|
print(" {} = backup_{};".format(block["cell"], block["cell"]), file=f)
|
||||||
|
|
||||||
|
if block["genargs"] is not None:
|
||||||
|
print("#define finish do { rollback = -1; return; } while(0)", file=f)
|
||||||
|
print(" if (generate_mode && !found_any_match) {", file=f)
|
||||||
|
if len(block["genargs"]) == 1:
|
||||||
|
print(" if (rng(100) >= {}) return;".format(block["genargs"][0]), file=f)
|
||||||
|
for line in block["gencode"]:
|
||||||
|
print(" " + line, file=f)
|
||||||
|
print(" }", file=f)
|
||||||
|
print("#undef finish", file=f)
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,330 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
// for peepopt_pm
|
||||||
|
bool did_something;
|
||||||
|
|
||||||
|
#include "passes/pmgen/test_pmgen_pm.h"
|
||||||
|
#include "passes/pmgen/ice40_dsp_pm.h"
|
||||||
|
#include "passes/pmgen/peepopt_pm.h"
|
||||||
|
|
||||||
|
void reduce_chain(test_pmgen_pm &pm)
|
||||||
|
{
|
||||||
|
auto &st = pm.st_reduce;
|
||||||
|
auto &ud = pm.ud_reduce;
|
||||||
|
|
||||||
|
if (ud.longest_chain.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type));
|
||||||
|
|
||||||
|
SigSpec A;
|
||||||
|
SigSpec Y = ud.longest_chain.front().first->getPort(ID(Y));
|
||||||
|
auto last_cell = ud.longest_chain.back().first;
|
||||||
|
|
||||||
|
for (auto it : ud.longest_chain) {
|
||||||
|
auto cell = it.first;
|
||||||
|
if (cell == last_cell) {
|
||||||
|
A.append(cell->getPort(ID(A)));
|
||||||
|
A.append(cell->getPort(ID(B)));
|
||||||
|
} else {
|
||||||
|
A.append(cell->getPort(it.second == ID(A) ? ID(B) : ID(A)));
|
||||||
|
}
|
||||||
|
log(" %s\n", log_id(cell));
|
||||||
|
pm.autoremove(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell *c;
|
||||||
|
|
||||||
|
if (last_cell->type == ID($_AND_))
|
||||||
|
c = pm.module->addReduceAnd(NEW_ID, A, Y);
|
||||||
|
else if (last_cell->type == ID($_OR_))
|
||||||
|
c = pm.module->addReduceOr(NEW_ID, A, Y);
|
||||||
|
else if (last_cell->type == ID($_XOR_))
|
||||||
|
c = pm.module->addReduceXor(NEW_ID, A, Y);
|
||||||
|
else
|
||||||
|
log_abort();
|
||||||
|
|
||||||
|
log(" -> %s (%s)\n", log_id(c), log_id(c->type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reduce_tree(test_pmgen_pm &pm)
|
||||||
|
{
|
||||||
|
auto &st = pm.st_reduce;
|
||||||
|
auto &ud = pm.ud_reduce;
|
||||||
|
|
||||||
|
if (ud.longest_chain.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
SigSpec A = ud.leaves;
|
||||||
|
SigSpec Y = st.first->getPort(ID(Y));
|
||||||
|
pm.autoremove(st.first);
|
||||||
|
|
||||||
|
log("Found %s tree with %d leaves for %s (%s).\n", log_id(st.first->type),
|
||||||
|
GetSize(A), log_signal(Y), log_id(st.first));
|
||||||
|
|
||||||
|
Cell *c;
|
||||||
|
|
||||||
|
if (st.first->type == ID($_AND_))
|
||||||
|
c = pm.module->addReduceAnd(NEW_ID, A, Y);
|
||||||
|
else if (st.first->type == ID($_OR_))
|
||||||
|
c = pm.module->addReduceOr(NEW_ID, A, Y);
|
||||||
|
else if (st.first->type == ID($_XOR_))
|
||||||
|
c = pm.module->addReduceXor(NEW_ID, A, Y);
|
||||||
|
else
|
||||||
|
log_abort();
|
||||||
|
|
||||||
|
log(" -> %s (%s)\n", log_id(c), log_id(c->type));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GENERATE_PATTERN(pmclass, pattern) \
|
||||||
|
generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)
|
||||||
|
|
||||||
|
void pmtest_addports(Module *module)
|
||||||
|
{
|
||||||
|
pool<SigBit> driven_bits, used_bits;
|
||||||
|
SigMap sigmap(module);
|
||||||
|
int icnt = 0, ocnt = 0;
|
||||||
|
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
for (auto conn : cell->connections())
|
||||||
|
{
|
||||||
|
if (cell->input(conn.first))
|
||||||
|
for (auto bit : sigmap(conn.second))
|
||||||
|
used_bits.insert(bit);
|
||||||
|
if (cell->output(conn.first))
|
||||||
|
for (auto bit : sigmap(conn.second))
|
||||||
|
driven_bits.insert(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto wire : vector<Wire*>(module->wires()))
|
||||||
|
{
|
||||||
|
SigSpec ibits, obits;
|
||||||
|
for (auto bit : sigmap(wire)) {
|
||||||
|
if (!used_bits.count(bit))
|
||||||
|
obits.append(bit);
|
||||||
|
if (!driven_bits.count(bit))
|
||||||
|
ibits.append(bit);
|
||||||
|
}
|
||||||
|
if (!ibits.empty()) {
|
||||||
|
Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits));
|
||||||
|
w->port_input = true;
|
||||||
|
module->connect(ibits, w);
|
||||||
|
}
|
||||||
|
if (!obits.empty()) {
|
||||||
|
Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits));
|
||||||
|
w->port_output = true;
|
||||||
|
module->connect(w, obits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module->fixup_ports();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class pm>
|
||||||
|
void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design)
|
||||||
|
{
|
||||||
|
log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);
|
||||||
|
|
||||||
|
int modcnt = 0;
|
||||||
|
int maxsubcnt = 4;
|
||||||
|
int timeout = 0;
|
||||||
|
vector<Module*> mods;
|
||||||
|
|
||||||
|
while (modcnt < 100)
|
||||||
|
{
|
||||||
|
int submodcnt = 0, itercnt = 0, cellcnt = 0;
|
||||||
|
Module *mod = design->addModule(NEW_ID);
|
||||||
|
|
||||||
|
while (modcnt < 100 && submodcnt < maxsubcnt && itercnt++ < 1000)
|
||||||
|
{
|
||||||
|
if (timeout++ > 10000)
|
||||||
|
log_error("pmgen generator is stuck: 10000 iterations an no matching module generated.\n");
|
||||||
|
|
||||||
|
pm matcher(mod, mod->cells());
|
||||||
|
|
||||||
|
matcher.rng(1);
|
||||||
|
matcher.rngseed += modcnt;
|
||||||
|
matcher.rng(1);
|
||||||
|
matcher.rngseed += submodcnt;
|
||||||
|
matcher.rng(1);
|
||||||
|
matcher.rngseed += itercnt;
|
||||||
|
matcher.rng(1);
|
||||||
|
matcher.rngseed += cellcnt;
|
||||||
|
matcher.rng(1);
|
||||||
|
|
||||||
|
if (GetSize(mod->cells()) != cellcnt)
|
||||||
|
{
|
||||||
|
bool found_match = false;
|
||||||
|
run(matcher, [&](){ found_match = true; });
|
||||||
|
cellcnt = GetSize(mod->cells());
|
||||||
|
|
||||||
|
if (found_match) {
|
||||||
|
Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d",
|
||||||
|
pmclass, pattern, modcnt++));
|
||||||
|
log("Creating module %s with %d cells.\n", log_id(m), cellcnt);
|
||||||
|
mod->cloneInto(m);
|
||||||
|
pmtest_addports(m);
|
||||||
|
mods.push_back(m);
|
||||||
|
submodcnt++;
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher.generate_mode = true;
|
||||||
|
run(matcher, [](){});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (submodcnt)
|
||||||
|
maxsubcnt *= 2;
|
||||||
|
|
||||||
|
design->remove(mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern));
|
||||||
|
log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods));
|
||||||
|
for (auto mod : mods) {
|
||||||
|
Cell *c = m->addCell(mod->name, mod->name);
|
||||||
|
for (auto port : mod->ports) {
|
||||||
|
Wire *w = m->addWire(NEW_ID, GetSize(mod->wire(port)));
|
||||||
|
c->setPort(port, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pmtest_addports(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestPmgenPass : public Pass {
|
||||||
|
TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" test_pmgen -reduce_chain [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.\n");
|
||||||
|
log("\n");
|
||||||
|
|
||||||
|
log("\n");
|
||||||
|
log(" test_pmgen -reduce_tree [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n");
|
||||||
|
log("\n");
|
||||||
|
|
||||||
|
log("\n");
|
||||||
|
log(" test_pmgen -generate [options] <pattern_name>\n");
|
||||||
|
log("\n");
|
||||||
|
log("Create modules that match the specified pattern.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_reduce_chain(std::vector<std::string> args, RTLIL::Design *design)
|
||||||
|
{
|
||||||
|
log_header(design, "Executing TEST_PMGEN pass (-reduce_chain).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 2; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
// if (args[argidx] == "-singleton") {
|
||||||
|
// singleton_mode = true;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
while (test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_chain)) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_reduce_tree(std::vector<std::string> args, RTLIL::Design *design)
|
||||||
|
{
|
||||||
|
log_header(design, "Executing TEST_PMGEN pass (-reduce_tree).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 2; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
// if (args[argidx] == "-singleton") {
|
||||||
|
// singleton_mode = true;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_generate(std::vector<std::string> args, RTLIL::Design *design)
|
||||||
|
{
|
||||||
|
log_header(design, "Executing TEST_PMGEN pass (-generate).\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 2; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
// if (args[argidx] == "-singleton") {
|
||||||
|
// singleton_mode = true;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argidx+1 != args.size())
|
||||||
|
log_cmd_error("Expected exactly one pattern.\n");
|
||||||
|
|
||||||
|
string pattern = args[argidx];
|
||||||
|
|
||||||
|
if (pattern == "reduce")
|
||||||
|
return GENERATE_PATTERN(test_pmgen_pm, reduce);
|
||||||
|
|
||||||
|
if (pattern == "ice40_dsp")
|
||||||
|
return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);
|
||||||
|
|
||||||
|
if (pattern == "peepopt-muldiv")
|
||||||
|
return GENERATE_PATTERN(peepopt_pm, muldiv);
|
||||||
|
|
||||||
|
if (pattern == "peepopt-shiftmul")
|
||||||
|
return GENERATE_PATTERN(peepopt_pm, shiftmul);
|
||||||
|
|
||||||
|
log_cmd_error("Unkown pattern: %s\n", pattern.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
if (GetSize(args) > 1)
|
||||||
|
{
|
||||||
|
if (args[1] == "-reduce_chain")
|
||||||
|
return execute_reduce_chain(args, design);
|
||||||
|
if (args[1] == "-reduce_tree")
|
||||||
|
return execute_reduce_tree(args, design);
|
||||||
|
if (args[1] == "-generate")
|
||||||
|
return execute_generate(args, design);
|
||||||
|
}
|
||||||
|
help();
|
||||||
|
log_cmd_error("Missing or unsupported mode parameter.\n");
|
||||||
|
}
|
||||||
|
} TestPmgenPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,106 @@
|
||||||
|
pattern reduce
|
||||||
|
|
||||||
|
state <IdString> portname
|
||||||
|
udata <vector<pair<Cell*, IdString>>> chain longest_chain
|
||||||
|
udata <pool<Cell*>> non_first_cells
|
||||||
|
udata <SigSpec> leaves
|
||||||
|
|
||||||
|
code
|
||||||
|
non_first_cells.clear();
|
||||||
|
subpattern(setup);
|
||||||
|
endcode
|
||||||
|
|
||||||
|
match first
|
||||||
|
select first->type.in($_AND_, $_OR_, $_XOR_)
|
||||||
|
filter !non_first_cells.count(first)
|
||||||
|
generate
|
||||||
|
SigSpec A = module->addWire(NEW_ID);
|
||||||
|
SigSpec B = module->addWire(NEW_ID);
|
||||||
|
SigSpec Y = module->addWire(NEW_ID);
|
||||||
|
switch (rng(3))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
module->addAndGate(NEW_ID, A, B, Y);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
module->addOrGate(NEW_ID, A, B, Y);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
module->addXorGate(NEW_ID, A, B, Y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
leaves = SigSpec();
|
||||||
|
longest_chain.clear();
|
||||||
|
chain.push_back(make_pair(first, \A));
|
||||||
|
subpattern(tail);
|
||||||
|
chain.back().second = \B;
|
||||||
|
subpattern(tail);
|
||||||
|
finally
|
||||||
|
chain.pop_back();
|
||||||
|
log_assert(chain.empty());
|
||||||
|
if (GetSize(longest_chain) > 1)
|
||||||
|
accept;
|
||||||
|
endcode
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
subpattern setup
|
||||||
|
|
||||||
|
match first
|
||||||
|
select first->type.in($_AND_, $_OR_, $_XOR_)
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code portname
|
||||||
|
portname = \A;
|
||||||
|
branch;
|
||||||
|
portname = \B;
|
||||||
|
endcode
|
||||||
|
|
||||||
|
match next
|
||||||
|
select nusers(port(next, \Y)) == 2
|
||||||
|
select next->type.in($_AND_, $_OR_, $_XOR_)
|
||||||
|
index <IdString> next->type === first->type
|
||||||
|
index <SigSpec> port(next, \Y) === port(first, portname)
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
non_first_cells.insert(next);
|
||||||
|
endcode
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
subpattern tail
|
||||||
|
arg first
|
||||||
|
|
||||||
|
match next
|
||||||
|
semioptional
|
||||||
|
select nusers(port(next, \Y)) == 2
|
||||||
|
select next->type.in($_AND_, $_OR_, $_XOR_)
|
||||||
|
index <IdString> next->type === chain.back().first->type
|
||||||
|
index <SigSpec> port(next, \Y) === port(chain.back().first, chain.back().second)
|
||||||
|
generate 10
|
||||||
|
SigSpec A = module->addWire(NEW_ID);
|
||||||
|
SigSpec B = module->addWire(NEW_ID);
|
||||||
|
SigSpec Y = port(chain.back().first, chain.back().second);
|
||||||
|
Cell *c = module->addAndGate(NEW_ID, A, B, Y);
|
||||||
|
c->type = chain.back().first->type;
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
if (next) {
|
||||||
|
chain.push_back(make_pair(next, \A));
|
||||||
|
subpattern(tail);
|
||||||
|
chain.back().second = \B;
|
||||||
|
subpattern(tail);
|
||||||
|
} else {
|
||||||
|
if (GetSize(chain) > GetSize(longest_chain))
|
||||||
|
longest_chain = chain;
|
||||||
|
leaves.append(port(chain.back().first, chain.back().second));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
if (next)
|
||||||
|
chain.pop_back();
|
||||||
|
endcode
|
|
@ -69,8 +69,7 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did
|
||||||
did_something = true;
|
did_something = true;
|
||||||
for (auto &action : sw->cases[0]->actions)
|
for (auto &action : sw->cases[0]->actions)
|
||||||
parent->actions.push_back(action);
|
parent->actions.push_back(action);
|
||||||
for (auto sw2 : sw->cases[0]->switches)
|
parent->switches.insert(parent->switches.begin(), sw->cases[0]->switches.begin(), sw->cases[0]->switches.end());
|
||||||
parent->switches.push_back(sw2);
|
|
||||||
sw->cases[0]->switches.clear();
|
sw->cases[0]->switches.clear();
|
||||||
delete sw->cases[0];
|
delete sw->cases[0];
|
||||||
sw->cases.clear();
|
sw->cases.clear();
|
||||||
|
|
|
@ -198,7 +198,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
||||||
if (keepff)
|
if (keepff)
|
||||||
for (auto &c : sig_q.chunks())
|
for (auto &c : sig_q.chunks())
|
||||||
if (c.wire != NULL)
|
if (c.wire != NULL)
|
||||||
c.wire->attributes[ID(keep)] = 1;
|
c.wire->attributes[ID::keep] = 1;
|
||||||
|
|
||||||
assign_map.apply(sig_d);
|
assign_map.apply(sig_d);
|
||||||
assign_map.apply(sig_q);
|
assign_map.apply(sig_q);
|
||||||
|
@ -211,8 +211,8 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
||||||
|
|
||||||
if (cell->type.in(ID($_BUF_), ID($_NOT_)))
|
if (cell->type.in(ID($_BUF_), ID($_NOT_)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
assign_map.apply(sig_a);
|
assign_map.apply(sig_a);
|
||||||
assign_map.apply(sig_y);
|
assign_map.apply(sig_y);
|
||||||
|
@ -225,9 +225,9 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
||||||
|
|
||||||
if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
|
if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
assign_map.apply(sig_a);
|
assign_map.apply(sig_a);
|
||||||
assign_map.apply(sig_b);
|
assign_map.apply(sig_b);
|
||||||
|
@ -261,10 +261,10 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
||||||
|
|
||||||
if (cell->type.in(ID($_MUX_), ID($_NMUX_)))
|
if (cell->type.in(ID($_MUX_), ID($_NMUX_)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_s = cell->getPort(ID(S));
|
RTLIL::SigSpec sig_s = cell->getPort(ID(S));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
assign_map.apply(sig_a);
|
assign_map.apply(sig_a);
|
||||||
assign_map.apply(sig_b);
|
assign_map.apply(sig_b);
|
||||||
|
@ -283,10 +283,10 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
||||||
|
|
||||||
if (cell->type.in(ID($_AOI3_), ID($_OAI3_)))
|
if (cell->type.in(ID($_AOI3_), ID($_OAI3_)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_c = cell->getPort(ID(C));
|
RTLIL::SigSpec sig_c = cell->getPort(ID(C));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
assign_map.apply(sig_a);
|
assign_map.apply(sig_a);
|
||||||
assign_map.apply(sig_b);
|
assign_map.apply(sig_b);
|
||||||
|
@ -305,11 +305,11 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
|
||||||
|
|
||||||
if (cell->type.in(ID($_AOI4_), ID($_OAI4_)))
|
if (cell->type.in(ID($_AOI4_), ID($_OAI4_)))
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_c = cell->getPort(ID(C));
|
RTLIL::SigSpec sig_c = cell->getPort(ID(C));
|
||||||
RTLIL::SigSpec sig_d = cell->getPort(ID(D));
|
RTLIL::SigSpec sig_d = cell->getPort(ID(D));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
assign_map.apply(sig_a);
|
assign_map.apply(sig_a);
|
||||||
assign_map.apply(sig_b);
|
assign_map.apply(sig_b);
|
||||||
|
@ -787,7 +787,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
extract_cell(c, keepff);
|
extract_cell(c, keepff);
|
||||||
|
|
||||||
for (auto &wire_it : module->wires_) {
|
for (auto &wire_it : module->wires_) {
|
||||||
if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute(ID(keep)))
|
if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute(ID::keep))
|
||||||
mark_port(RTLIL::SigSpec(wire_it.second));
|
mark_port(RTLIL::SigSpec(wire_it.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,63 +1042,63 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
cell_stats[RTLIL::unescape_id(c->type)]++;
|
cell_stats[RTLIL::unescape_id(c->type)]++;
|
||||||
if (c->type.in(ID(ZERO), ID(ONE))) {
|
if (c->type.in(ID(ZERO), ID(ONE))) {
|
||||||
RTLIL::SigSig conn;
|
RTLIL::SigSig conn;
|
||||||
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]);
|
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]);
|
||||||
conn.second = RTLIL::SigSpec(c->type == ID(ZERO) ? 0 : 1, 1);
|
conn.second = RTLIL::SigSpec(c->type == ID(ZERO) ? 0 : 1, 1);
|
||||||
module->connect(conn);
|
module->connect(conn);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type == ID(BUF)) {
|
if (c->type == ID(BUF)) {
|
||||||
RTLIL::SigSig conn;
|
RTLIL::SigSig conn;
|
||||||
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]);
|
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]);
|
||||||
conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]);
|
conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]);
|
||||||
module->connect(conn);
|
module->connect(conn);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type == ID(NOT)) {
|
if (c->type == ID(NOT)) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) {
|
if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
|
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type.in(ID(MUX), ID(NMUX))) {
|
if (c->type.in(ID(MUX), ID(NMUX))) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
|
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
|
||||||
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
|
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type == ID(MUX4)) {
|
if (c->type == ID(MUX4)) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX4_));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX4_));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
|
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
|
||||||
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
||||||
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
||||||
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
|
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
|
||||||
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
|
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type == ID(MUX8)) {
|
if (c->type == ID(MUX8)) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX8_));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX8_));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
|
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
|
||||||
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
||||||
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
||||||
cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
|
cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
|
||||||
|
@ -1108,15 +1108,15 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
|
cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
|
||||||
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
|
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
|
||||||
cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
|
cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type == ID(MUX16)) {
|
if (c->type == ID(MUX16)) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX16_));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX16_));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
|
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
|
||||||
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
||||||
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
||||||
cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
|
cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
|
||||||
|
@ -1135,28 +1135,28 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
|
cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
|
||||||
cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
|
cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
|
||||||
cell->setPort(ID(V), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(V)).as_wire()->name)]));
|
cell->setPort(ID(V), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(V)).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type.in(ID(AOI3), ID(OAI3))) {
|
if (c->type.in(ID(AOI3), ID(OAI3))) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
|
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
|
||||||
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c->type.in(ID(AOI4), ID(OAI4))) {
|
if (c->type.in(ID(AOI4), ID(OAI4))) {
|
||||||
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
|
||||||
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
|
cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
|
||||||
cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
|
cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
|
||||||
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
|
||||||
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
|
||||||
cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
|
cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
|
||||||
design->select(module, cell);
|
design->select(module, cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1207,9 +1207,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->type == ID($lut) && GetSize(c->getPort(ID(A))) == 1 && c->getParam(ID(LUT)).as_int() == 2) {
|
if (c->type == ID($lut) && GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)).as_int() == 2) {
|
||||||
SigSpec my_a = module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)];
|
SigSpec my_a = module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)];
|
||||||
SigSpec my_y = module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)];
|
SigSpec my_y = module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)];
|
||||||
module->connect(my_y, my_a);
|
module->connect(my_y, my_a);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,12 +76,11 @@ inline std::string remap_name(RTLIL::IdString abc_name)
|
||||||
return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
|
return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_loops(RTLIL::Design *design)
|
void handle_loops(RTLIL::Design *design,
|
||||||
|
const dict<IdString,pool<IdString>> &scc_break_inputs)
|
||||||
{
|
{
|
||||||
Pass::call(design, "scc -set_attr abc_scc_id {}");
|
Pass::call(design, "scc -set_attr abc_scc_id {}");
|
||||||
|
|
||||||
dict<IdString, vector<IdString>> abc_scc_break;
|
|
||||||
|
|
||||||
// For every unique SCC found, (arbitrarily) find the first
|
// For every unique SCC found, (arbitrarily) find the first
|
||||||
// cell in the component, and select (and mark) all its output
|
// cell in the component, and select (and mark) all its output
|
||||||
// wires
|
// wires
|
||||||
|
@ -116,44 +115,29 @@ void handle_loops(RTLIL::Design *design)
|
||||||
cell->attributes.erase(it);
|
cell->attributes.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto jt = abc_scc_break.find(cell->type);
|
auto jt = scc_break_inputs.find(cell->type);
|
||||||
if (jt == abc_scc_break.end()) {
|
if (jt != scc_break_inputs.end())
|
||||||
std::vector<IdString> ports;
|
for (auto port_name : jt->second) {
|
||||||
RTLIL::Module* box_module = design->module(cell->type);
|
RTLIL::SigSpec sig;
|
||||||
if (box_module) {
|
auto &rhs = cell->connections_.at(port_name);
|
||||||
auto ports_csv = box_module->attributes.at(ID(abc_scc_break), RTLIL::Const::from_string("")).decode_string();
|
for (auto b : rhs) {
|
||||||
for (const auto &port_name : split_tokens(ports_csv, ",")) {
|
Wire *w = b.wire;
|
||||||
auto port_id = RTLIL::escape_id(port_name);
|
if (!w) continue;
|
||||||
auto kt = cell->connections_.find(port_id);
|
w->port_output = true;
|
||||||
if (kt == cell->connections_.end())
|
w->set_bool_attribute(ID(abc_scc_break));
|
||||||
log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", port_name.c_str(), log_id(box_module));
|
w = module->wire(stringf("%s.abci", w->name.c_str()));
|
||||||
ports.push_back(port_id);
|
if (!w) {
|
||||||
|
w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
|
||||||
|
w->port_input = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log_assert(b.offset < GetSize(w));
|
||||||
|
log_assert(w->port_input);
|
||||||
|
}
|
||||||
|
sig.append(RTLIL::SigBit(w, b.offset));
|
||||||
}
|
}
|
||||||
|
rhs = sig;
|
||||||
}
|
}
|
||||||
jt = abc_scc_break.insert(std::make_pair(cell->type, std::move(ports))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto port_name : jt->second) {
|
|
||||||
RTLIL::SigSpec sig;
|
|
||||||
auto &rhs = cell->connections_.at(port_name);
|
|
||||||
for (auto b : rhs) {
|
|
||||||
Wire *w = b.wire;
|
|
||||||
if (!w) continue;
|
|
||||||
w->port_output = true;
|
|
||||||
w->set_bool_attribute(ID(abc_scc_break));
|
|
||||||
w = module->wire(stringf("%s.abci", w->name.c_str()));
|
|
||||||
if (!w) {
|
|
||||||
w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
|
|
||||||
w->port_input = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log_assert(b.offset < GetSize(w));
|
|
||||||
log_assert(w->port_input);
|
|
||||||
}
|
|
||||||
sig.append(RTLIL::SigBit(w, b.offset));
|
|
||||||
}
|
|
||||||
rhs = sig;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module->fixup_ports();
|
module->fixup_ports();
|
||||||
|
@ -288,7 +272,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
|
bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
|
||||||
bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
|
bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
|
||||||
bool show_tempdir, std::string box_file, std::string lut_file,
|
bool show_tempdir, std::string box_file, std::string lut_file,
|
||||||
std::string wire_delay, const dict<int,IdString> &box_lookup)
|
std::string wire_delay, const dict<int,IdString> &box_lookup,
|
||||||
|
const dict<IdString,pool<IdString>> &scc_break_inputs
|
||||||
|
)
|
||||||
{
|
{
|
||||||
module = current_module;
|
module = current_module;
|
||||||
map_autoidx = autoidx++;
|
map_autoidx = autoidx++;
|
||||||
|
@ -427,7 +413,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
RTLIL::Selection& sel = design->selection_stack.back();
|
RTLIL::Selection& sel = design->selection_stack.back();
|
||||||
sel.select(module);
|
sel.select(module);
|
||||||
|
|
||||||
handle_loops(design);
|
handle_loops(design, scc_break_inputs);
|
||||||
|
|
||||||
Pass::call(design, "aigmap");
|
Pass::call(design, "aigmap");
|
||||||
|
|
||||||
|
@ -582,13 +568,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
|
|
||||||
RTLIL::Cell *cell = nullptr;
|
RTLIL::Cell *cell = nullptr;
|
||||||
if (c->type == ID($_NOT_)) {
|
if (c->type == ID($_NOT_)) {
|
||||||
RTLIL::SigBit a_bit = c->getPort(ID(A));
|
RTLIL::SigBit a_bit = c->getPort(ID::A);
|
||||||
RTLIL::SigBit y_bit = c->getPort(ID(Y));
|
RTLIL::SigBit y_bit = c->getPort(ID::Y);
|
||||||
bit_users[a_bit].insert(c->name);
|
bit_users[a_bit].insert(c->name);
|
||||||
bit_drivers[y_bit].insert(c->name);
|
bit_drivers[y_bit].insert(c->name);
|
||||||
|
|
||||||
if (!a_bit.wire) {
|
if (!a_bit.wire) {
|
||||||
c->setPort(ID(Y), module->addWire(NEW_ID));
|
c->setPort(ID::Y, module->addWire(NEW_ID));
|
||||||
RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
|
RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
|
||||||
log_assert(wire);
|
log_assert(wire);
|
||||||
module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
|
module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
|
||||||
|
@ -616,7 +602,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
|
RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
|
||||||
RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
|
RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
|
||||||
RTLIL::Const::from_string("01"));
|
RTLIL::Const::from_string("01"));
|
||||||
bit2sinks[cell->getPort(ID(A))].push_back(cell);
|
bit2sinks[cell->getPort(ID::A)].push_back(cell);
|
||||||
cell_stats[ID($lut)]++;
|
cell_stats[ID($lut)]++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -632,9 +618,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
|
|
||||||
RTLIL::Cell *existing_cell = nullptr;
|
RTLIL::Cell *existing_cell = nullptr;
|
||||||
if (c->type == ID($lut)) {
|
if (c->type == ID($lut)) {
|
||||||
if (GetSize(c->getPort(ID(A))) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
|
if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
|
||||||
SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID(A)).as_wire()->name));
|
SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name));
|
||||||
SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID(Y)).as_wire()->name));
|
SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name));
|
||||||
module->connect(my_y, my_a);
|
module->connect(my_y, my_a);
|
||||||
if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx;
|
if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx;
|
||||||
log_abort();
|
log_abort();
|
||||||
|
@ -739,7 +725,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
for (auto driver_cell : bit_drivers.at(it.first))
|
for (auto driver_cell : bit_drivers.at(it.first))
|
||||||
for (auto user_cell : it.second)
|
for (auto user_cell : it.second)
|
||||||
toposort.edge(driver_cell, user_cell);
|
toposort.edge(driver_cell, user_cell);
|
||||||
bool no_loops = toposort.sort();
|
bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
|
||||||
log_assert(no_loops);
|
log_assert(no_loops);
|
||||||
|
|
||||||
for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
|
for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
|
||||||
|
@ -751,8 +737,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
if (it == not2drivers.end())
|
if (it == not2drivers.end())
|
||||||
continue;
|
continue;
|
||||||
RTLIL::Cell *driver_lut = it->second;
|
RTLIL::Cell *driver_lut = it->second;
|
||||||
RTLIL::SigBit a_bit = not_cell->getPort(ID(A));
|
RTLIL::SigBit a_bit = not_cell->getPort(ID::A);
|
||||||
RTLIL::SigBit y_bit = not_cell->getPort(ID(Y));
|
RTLIL::SigBit y_bit = not_cell->getPort(ID::Y);
|
||||||
RTLIL::Const driver_mask;
|
RTLIL::Const driver_mask;
|
||||||
|
|
||||||
a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
|
a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
|
||||||
|
@ -768,7 +754,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
|
|
||||||
// Push downstream LUTs past inverter
|
// Push downstream LUTs past inverter
|
||||||
for (auto sink_cell : jt->second) {
|
for (auto sink_cell : jt->second) {
|
||||||
SigSpec A = sink_cell->getPort(ID(A));
|
SigSpec A = sink_cell->getPort(ID::A);
|
||||||
RTLIL::Const mask = sink_cell->getParam(ID(LUT));
|
RTLIL::Const mask = sink_cell->getParam(ID(LUT));
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (; index < GetSize(A); index++)
|
for (; index < GetSize(A); index++)
|
||||||
|
@ -782,7 +768,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
|
||||||
i += 1 << (index+1);
|
i += 1 << (index+1);
|
||||||
}
|
}
|
||||||
A[index] = y_bit;
|
A[index] = y_bit;
|
||||||
sink_cell->setPort(ID(A), A);
|
sink_cell->setPort(ID::A, A);
|
||||||
sink_cell->setParam(ID(LUT), mask);
|
sink_cell->setParam(ID(LUT), mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,10 +784,10 @@ clone_lut:
|
||||||
else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
|
else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
|
||||||
}
|
}
|
||||||
auto cell = module->addLut(NEW_ID,
|
auto cell = module->addLut(NEW_ID,
|
||||||
driver_lut->getPort(ID(A)),
|
driver_lut->getPort(ID::A),
|
||||||
y_bit,
|
y_bit,
|
||||||
driver_mask);
|
driver_mask);
|
||||||
for (auto &bit : cell->connections_.at(ID(A))) {
|
for (auto &bit : cell->connections_.at(ID::A)) {
|
||||||
bit.wire = module->wires_.at(remap_name(bit.wire->name));
|
bit.wire = module->wires_.at(remap_name(bit.wire->name));
|
||||||
bit2sinks[bit].push_back(cell);
|
bit2sinks[bit].push_back(cell);
|
||||||
}
|
}
|
||||||
|
@ -1081,6 +1067,7 @@ struct Abc9Pass : public Pass {
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
dict<int,IdString> box_lookup;
|
dict<int,IdString> box_lookup;
|
||||||
|
dict<IdString,pool<IdString>> scc_break_inputs;
|
||||||
for (auto m : design->modules()) {
|
for (auto m : design->modules()) {
|
||||||
auto it = m->attributes.find(ID(abc_box_id));
|
auto it = m->attributes.find(ID(abc_box_id));
|
||||||
if (it == m->attributes.end())
|
if (it == m->attributes.end())
|
||||||
|
@ -1093,6 +1080,56 @@ struct Abc9Pass : public Pass {
|
||||||
log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
|
log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
|
||||||
log_id(m), id, log_id(r.first->second));
|
log_id(m), id, log_id(r.first->second));
|
||||||
log_assert(r.second);
|
log_assert(r.second);
|
||||||
|
|
||||||
|
RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr;
|
||||||
|
for (auto p : m->ports) {
|
||||||
|
auto w = m->wire(p);
|
||||||
|
log_assert(w);
|
||||||
|
if (w->port_input) {
|
||||||
|
if (w->attributes.count(ID(abc_scc_break)))
|
||||||
|
scc_break_inputs[m->name].insert(p);
|
||||||
|
if (w->attributes.count(ID(abc_carry))) {
|
||||||
|
if (carry_in)
|
||||||
|
log_error("Module '%s' contains more than one 'abc_carry' input port.\n", log_id(m));
|
||||||
|
carry_in = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (w->port_output) {
|
||||||
|
if (w->attributes.count(ID(abc_carry))) {
|
||||||
|
if (carry_out)
|
||||||
|
log_error("Module '%s' contains more than one 'abc_carry' input port.\n", log_id(m));
|
||||||
|
carry_out = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (carry_in || carry_out) {
|
||||||
|
if (carry_in && !carry_out)
|
||||||
|
log_error("Module '%s' contains an 'abc_carry' input port but no output port.\n", log_id(m));
|
||||||
|
if (!carry_in && carry_out)
|
||||||
|
log_error("Module '%s' contains an 'abc_carry' output port but no input port.\n", log_id(m));
|
||||||
|
// Make carry_in the last PI, and carry_out the last PO
|
||||||
|
// since ABC requires it this way
|
||||||
|
auto &ports = m->ports;
|
||||||
|
for (auto it = ports.begin(); it != ports.end(); ) {
|
||||||
|
RTLIL::Wire* w = m->wire(*it);
|
||||||
|
log_assert(w);
|
||||||
|
if (w == carry_in || w == carry_out) {
|
||||||
|
it = ports.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (w->port_id > carry_in->port_id)
|
||||||
|
--w->port_id;
|
||||||
|
if (w->port_id > carry_out->port_id)
|
||||||
|
--w->port_id;
|
||||||
|
log_assert(w->port_input || w->port_output);
|
||||||
|
log_assert(ports[w->port_id-1] == w->name);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
ports.push_back(carry_in->name);
|
||||||
|
carry_in->port_id = ports.size();
|
||||||
|
ports.push_back(carry_out->name);
|
||||||
|
carry_out->port_id = ports.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto mod : design->selected_modules())
|
for (auto mod : design->selected_modules())
|
||||||
|
@ -1110,7 +1147,7 @@ struct Abc9Pass : public Pass {
|
||||||
if (!dff_mode || !clk_str.empty()) {
|
if (!dff_mode || !clk_str.empty()) {
|
||||||
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
|
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
|
||||||
delay_target, lutin_shared, fast_mode, show_tempdir,
|
delay_target, lutin_shared, fast_mode, show_tempdir,
|
||||||
box_file, lut_file, wire_delay, box_lookup);
|
box_file, lut_file, wire_delay, box_lookup, scc_break_inputs);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,7 +1293,7 @@ struct Abc9Pass : public Pass {
|
||||||
en_sig = assign_map(std::get<3>(it.first));
|
en_sig = assign_map(std::get<3>(it.first));
|
||||||
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
|
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
|
||||||
keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
|
keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
|
||||||
box_file, lut_file, wire_delay, box_lookup);
|
box_file, lut_file, wire_delay, box_lookup, scc_break_inputs);
|
||||||
assign_map.set(mod);
|
assign_map.set(mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ struct AlumaccWorker
|
||||||
|
|
||||||
RTLIL::SigSpec get_sf() {
|
RTLIL::SigSpec get_sf() {
|
||||||
if (GetSize(cached_sf) == 0) {
|
if (GetSize(cached_sf) == 0) {
|
||||||
cached_sf = alu_cell->getPort(ID(Y));
|
cached_sf = alu_cell->getPort(ID::Y);
|
||||||
cached_sf = cached_sf[GetSize(cached_sf)-1];
|
cached_sf = cached_sf[GetSize(cached_sf)-1];
|
||||||
}
|
}
|
||||||
return cached_sf;
|
return cached_sf;
|
||||||
|
@ -134,7 +134,7 @@ struct AlumaccWorker
|
||||||
Macc::port_t new_port;
|
Macc::port_t new_port;
|
||||||
|
|
||||||
n->cell = cell;
|
n->cell = cell;
|
||||||
n->y = sigmap(cell->getPort(ID(Y)));
|
n->y = sigmap(cell->getPort(ID::Y));
|
||||||
n->users = 0;
|
n->users = 0;
|
||||||
|
|
||||||
for (auto bit : n->y)
|
for (auto bit : n->y)
|
||||||
|
@ -142,7 +142,7 @@ struct AlumaccWorker
|
||||||
|
|
||||||
if (cell->type.in(ID($pos), ID($neg)))
|
if (cell->type.in(ID($pos), ID($neg)))
|
||||||
{
|
{
|
||||||
new_port.in_a = sigmap(cell->getPort(ID(A)));
|
new_port.in_a = sigmap(cell->getPort(ID::A));
|
||||||
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
new_port.do_subtract = cell->type == ID($neg);
|
new_port.do_subtract = cell->type == ID($neg);
|
||||||
n->macc.ports.push_back(new_port);
|
n->macc.ports.push_back(new_port);
|
||||||
|
@ -150,12 +150,12 @@ struct AlumaccWorker
|
||||||
|
|
||||||
if (cell->type.in(ID($add), ID($sub)))
|
if (cell->type.in(ID($add), ID($sub)))
|
||||||
{
|
{
|
||||||
new_port.in_a = sigmap(cell->getPort(ID(A)));
|
new_port.in_a = sigmap(cell->getPort(ID::A));
|
||||||
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
new_port.do_subtract = false;
|
new_port.do_subtract = false;
|
||||||
n->macc.ports.push_back(new_port);
|
n->macc.ports.push_back(new_port);
|
||||||
|
|
||||||
new_port.in_a = sigmap(cell->getPort(ID(B)));
|
new_port.in_a = sigmap(cell->getPort(ID::B));
|
||||||
new_port.is_signed = cell->getParam(ID(B_SIGNED)).as_bool();
|
new_port.is_signed = cell->getParam(ID(B_SIGNED)).as_bool();
|
||||||
new_port.do_subtract = cell->type == ID($sub);
|
new_port.do_subtract = cell->type == ID($sub);
|
||||||
n->macc.ports.push_back(new_port);
|
n->macc.ports.push_back(new_port);
|
||||||
|
@ -163,8 +163,8 @@ struct AlumaccWorker
|
||||||
|
|
||||||
if (cell->type.in(ID($mul)))
|
if (cell->type.in(ID($mul)))
|
||||||
{
|
{
|
||||||
new_port.in_a = sigmap(cell->getPort(ID(A)));
|
new_port.in_a = sigmap(cell->getPort(ID::A));
|
||||||
new_port.in_b = sigmap(cell->getPort(ID(B)));
|
new_port.in_b = sigmap(cell->getPort(ID::B));
|
||||||
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
new_port.do_subtract = false;
|
new_port.do_subtract = false;
|
||||||
n->macc.ports.push_back(new_port);
|
n->macc.ports.push_back(new_port);
|
||||||
|
@ -361,7 +361,7 @@ struct AlumaccWorker
|
||||||
|
|
||||||
n->macc.optimize(GetSize(n->y));
|
n->macc.optimize(GetSize(n->y));
|
||||||
n->macc.to_cell(cell);
|
n->macc.to_cell(cell);
|
||||||
cell->setPort(ID(Y), n->y);
|
cell->setPort(ID::Y, n->y);
|
||||||
cell->fixup_parameters();
|
cell->fixup_parameters();
|
||||||
module->remove(n->cell);
|
module->remove(n->cell);
|
||||||
delete n;
|
delete n;
|
||||||
|
@ -390,9 +390,9 @@ struct AlumaccWorker
|
||||||
bool cmp_equal = cell->type.in(ID($le), ID($ge));
|
bool cmp_equal = cell->type.in(ID($le), ID($ge));
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
|
|
||||||
RTLIL::SigSpec A = sigmap(cell->getPort(ID(A)));
|
RTLIL::SigSpec A = sigmap(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec B = sigmap(cell->getPort(ID(B)));
|
RTLIL::SigSpec B = sigmap(cell->getPort(ID::B));
|
||||||
RTLIL::SigSpec Y = sigmap(cell->getPort(ID(Y)));
|
RTLIL::SigSpec Y = sigmap(cell->getPort(ID::Y));
|
||||||
|
|
||||||
if (B < A && GetSize(B)) {
|
if (B < A && GetSize(B)) {
|
||||||
cmp_less = !cmp_less;
|
cmp_less = !cmp_less;
|
||||||
|
@ -430,9 +430,9 @@ struct AlumaccWorker
|
||||||
bool cmp_equal = cell->type.in(ID($eq), ID($eqx));
|
bool cmp_equal = cell->type.in(ID($eq), ID($eqx));
|
||||||
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
|
||||||
|
|
||||||
RTLIL::SigSpec A = sigmap(cell->getPort(ID(A)));
|
RTLIL::SigSpec A = sigmap(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec B = sigmap(cell->getPort(ID(B)));
|
RTLIL::SigSpec B = sigmap(cell->getPort(ID::B));
|
||||||
RTLIL::SigSpec Y = sigmap(cell->getPort(ID(Y)));
|
RTLIL::SigSpec Y = sigmap(cell->getPort(ID::Y));
|
||||||
|
|
||||||
if (B < A && GetSize(B))
|
if (B < A && GetSize(B))
|
||||||
std::swap(A, B);
|
std::swap(A, B);
|
||||||
|
@ -482,11 +482,11 @@ struct AlumaccWorker
|
||||||
if (n->cells.size() > 0)
|
if (n->cells.size() > 0)
|
||||||
n->alu_cell->set_src_attribute(n->cells[0]->get_src_attribute());
|
n->alu_cell->set_src_attribute(n->cells[0]->get_src_attribute());
|
||||||
|
|
||||||
n->alu_cell->setPort(ID(A), n->a);
|
n->alu_cell->setPort(ID::A, n->a);
|
||||||
n->alu_cell->setPort(ID(B), n->b);
|
n->alu_cell->setPort(ID::B, n->b);
|
||||||
n->alu_cell->setPort(ID(CI), GetSize(n->c) ? n->c : State::S0);
|
n->alu_cell->setPort(ID(CI), GetSize(n->c) ? n->c : State::S0);
|
||||||
n->alu_cell->setPort(ID(BI), n->invert_b ? State::S1 : State::S0);
|
n->alu_cell->setPort(ID(BI), n->invert_b ? State::S1 : State::S0);
|
||||||
n->alu_cell->setPort(ID(Y), n->y);
|
n->alu_cell->setPort(ID::Y, n->y);
|
||||||
n->alu_cell->setPort(ID(X), module->addWire(NEW_ID, GetSize(n->y)));
|
n->alu_cell->setPort(ID(X), module->addWire(NEW_ID, GetSize(n->y)));
|
||||||
n->alu_cell->setPort(ID(CO), module->addWire(NEW_ID, GetSize(n->y)));
|
n->alu_cell->setPort(ID(CO), module->addWire(NEW_ID, GetSize(n->y)));
|
||||||
n->alu_cell->fixup_parameters(n->is_signed, n->is_signed);
|
n->alu_cell->fixup_parameters(n->is_signed, n->is_signed);
|
||||||
|
|
|
@ -83,13 +83,13 @@ struct DeminoutPass : public Pass {
|
||||||
for (auto bit : sigmap(conn.second))
|
for (auto bit : sigmap(conn.second))
|
||||||
bits_used.insert(bit);
|
bits_used.insert(bit);
|
||||||
|
|
||||||
if (conn.first == ID(Y) && cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_TBUF_), ID($tribuf)))
|
if (conn.first == ID::Y && cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_TBUF_), ID($tribuf)))
|
||||||
{
|
{
|
||||||
bool tribuf = cell->type.in(ID($_TBUF_), ID($tribuf));
|
bool tribuf = cell->type.in(ID($_TBUF_), ID($tribuf));
|
||||||
|
|
||||||
if (!tribuf) {
|
if (!tribuf) {
|
||||||
for (auto &c : cell->connections()) {
|
for (auto &c : cell->connections()) {
|
||||||
if (!c.first.in(ID(A), ID(B)))
|
if (!c.first.in(ID::A, ID::B))
|
||||||
continue;
|
continue;
|
||||||
for (auto b : sigmap(c.second))
|
for (auto b : sigmap(c.second))
|
||||||
if (b == State::Sz)
|
if (b == State::Sz)
|
||||||
|
|
|
@ -53,7 +53,7 @@ struct Dff2dffeWorker
|
||||||
|
|
||||||
for (auto cell : module->cells()) {
|
for (auto cell : module->cells()) {
|
||||||
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
|
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
|
||||||
RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID(Y)));
|
RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y));
|
||||||
for (int i = 0; i < GetSize(sig_y); i++)
|
for (int i = 0; i < GetSize(sig_y); i++)
|
||||||
bit2mux[sig_y[i]] = cell_int_t(cell, i);
|
bit2mux[sig_y[i]] = cell_int_t(cell, i);
|
||||||
}
|
}
|
||||||
|
@ -86,8 +86,8 @@ struct Dff2dffeWorker
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cell_int_t mux_cell_int = bit2mux.at(d);
|
cell_int_t mux_cell_int = bit2mux.at(d);
|
||||||
RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort(ID(A)));
|
RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort(ID(B)));
|
RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort(ID::B));
|
||||||
RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort(ID(S)));
|
RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort(ID(S)));
|
||||||
int width = GetSize(sig_a), index = mux_cell_int.second;
|
int width = GetSize(sig_a), index = mux_cell_int.second;
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ struct Dff2dffeWorker
|
||||||
ret = find_muxtree_feedback_patterns(sig_b[i*width + index], q, path);
|
ret = find_muxtree_feedback_patterns(sig_b[i*width + index], q, path);
|
||||||
|
|
||||||
if (sig_b[i*width + index] == q) {
|
if (sig_b[i*width + index] == q) {
|
||||||
RTLIL::SigSpec s = mux_cell_int.first->getPort(ID(B));
|
RTLIL::SigSpec s = mux_cell_int.first->getPort(ID::B);
|
||||||
s[i*width + index] = RTLIL::Sx;
|
s[i*width + index] = RTLIL::Sx;
|
||||||
mux_cell_int.first->setPort(ID(B), s);
|
mux_cell_int.first->setPort(ID::B, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -120,9 +120,9 @@ struct Dff2dffeWorker
|
||||||
ret.insert(pat);
|
ret.insert(pat);
|
||||||
|
|
||||||
if (sig_b[i*width + index] == q) {
|
if (sig_b[i*width + index] == q) {
|
||||||
RTLIL::SigSpec s = mux_cell_int.first->getPort(ID(B));
|
RTLIL::SigSpec s = mux_cell_int.first->getPort(ID::B);
|
||||||
s[i*width + index] = RTLIL::Sx;
|
s[i*width + index] = RTLIL::Sx;
|
||||||
mux_cell_int.first->setPort(ID(B), s);
|
mux_cell_int.first->setPort(ID::B, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +130,9 @@ struct Dff2dffeWorker
|
||||||
ret.insert(pat);
|
ret.insert(pat);
|
||||||
|
|
||||||
if (sig_a[index] == q) {
|
if (sig_a[index] == q) {
|
||||||
RTLIL::SigSpec s = mux_cell_int.first->getPort(ID(A));
|
RTLIL::SigSpec s = mux_cell_int.first->getPort(ID::A);
|
||||||
s[index] = RTLIL::Sx;
|
s[index] = RTLIL::Sx;
|
||||||
mux_cell_int.first->setPort(ID(A), s);
|
mux_cell_int.first->setPort(ID::A, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -265,7 +265,7 @@ struct Dff2dffePass : public Pass {
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -unmap\n");
|
log(" -unmap\n");
|
||||||
log(" operate in the opposite direction: replace $dffe cells with combinations\n");
|
log(" operate in the opposite direction: replace $dffe cells with combinations\n");
|
||||||
log(" of $dff and $mux cells. the options below are ignore in unmap mode.\n");
|
log(" of $dff and $mux cells. the options below are ignored in unmap mode.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -unmap-mince N\n");
|
log(" -unmap-mince N\n");
|
||||||
log(" Same as -unmap but only unmap $dffe where the clock enable port\n");
|
log(" Same as -unmap but only unmap $dffe where the clock enable port\n");
|
||||||
|
|
|
@ -72,11 +72,11 @@ struct Dff2dffsPass : public Pass {
|
||||||
if (cell->type != ID($_MUX_))
|
if (cell->type != ID($_MUX_))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SigBit bit_a = sigmap(cell->getPort(ID(A)));
|
SigBit bit_a = sigmap(cell->getPort(ID::A));
|
||||||
SigBit bit_b = sigmap(cell->getPort(ID(B)));
|
SigBit bit_b = sigmap(cell->getPort(ID::B));
|
||||||
|
|
||||||
if (bit_a.wire == nullptr || bit_b.wire == nullptr)
|
if (bit_a.wire == nullptr || bit_b.wire == nullptr)
|
||||||
sr_muxes[sigmap(cell->getPort(ID(Y)))] = cell;
|
sr_muxes[sigmap(cell->getPort(ID::Y))] = cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto cell : ff_cells)
|
for (auto cell : ff_cells)
|
||||||
|
@ -92,8 +92,8 @@ struct Dff2dffsPass : public Pass {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Cell *mux_cell = sr_muxes.at(bit_d);
|
Cell *mux_cell = sr_muxes.at(bit_d);
|
||||||
SigBit bit_a = sigmap(mux_cell->getPort(ID(A)));
|
SigBit bit_a = sigmap(mux_cell->getPort(ID::A));
|
||||||
SigBit bit_b = sigmap(mux_cell->getPort(ID(B)));
|
SigBit bit_b = sigmap(mux_cell->getPort(ID::B));
|
||||||
SigBit bit_s = sigmap(mux_cell->getPort(ID(S)));
|
SigBit bit_s = sigmap(mux_cell->getPort(ID(S)));
|
||||||
|
|
||||||
log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
|
log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
|
||||||
|
|
|
@ -485,7 +485,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
|
||||||
if (design->selected(module, it.second) && cell_mappings.count(it.second->type) > 0)
|
if (design->selected(module, it.second) && cell_mappings.count(it.second->type) > 0)
|
||||||
cell_list.push_back(it.second);
|
cell_list.push_back(it.second);
|
||||||
if (it.second->type == ID($_NOT_))
|
if (it.second->type == ID($_NOT_))
|
||||||
notmap[sigmap(it.second->getPort(ID(A)))].insert(it.second);
|
notmap[sigmap(it.second->getPort(ID::A))].insert(it.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, int> stats;
|
std::map<std::string, int> stats;
|
||||||
|
@ -519,8 +519,8 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
|
||||||
sig = module->addWire(NEW_ID, GetSize(old_sig));
|
sig = module->addWire(NEW_ID, GetSize(old_sig));
|
||||||
if (has_q && has_qn) {
|
if (has_q && has_qn) {
|
||||||
for (auto &it : notmap[sigmap(old_sig)]) {
|
for (auto &it : notmap[sigmap(old_sig)]) {
|
||||||
module->connect(it->getPort(ID(Y)), sig);
|
module->connect(it->getPort(ID::Y), sig);
|
||||||
it->setPort(ID(Y), module->addWire(NEW_ID, GetSize(old_sig)));
|
it->setPort(ID::Y, module->addWire(NEW_ID, GetSize(old_sig)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
module->addNotGate(NEW_ID, sig, old_sig);
|
module->addNotGate(NEW_ID, sig, old_sig);
|
||||||
|
|
|
@ -138,7 +138,7 @@ int counter_tryextract(
|
||||||
|
|
||||||
//To be a counter, one input of the ALU must be a constant 1
|
//To be a counter, one input of the ALU must be a constant 1
|
||||||
//TODO: can A or B be swapped in synthesized RTL or is B always the 1?
|
//TODO: can A or B be swapped in synthesized RTL or is B always the 1?
|
||||||
const RTLIL::SigSpec b_port = sigmap(cell->getPort(ID(B)));
|
const RTLIL::SigSpec b_port = sigmap(cell->getPort(ID::B));
|
||||||
if(!b_port.is_fully_const() || (b_port.as_int() != 1) )
|
if(!b_port.is_fully_const() || (b_port.as_int() != 1) )
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ int counter_tryextract(
|
||||||
|
|
||||||
//Y must have exactly one connection, and it has to be a $mux cell.
|
//Y must have exactly one connection, and it has to be a $mux cell.
|
||||||
//We must have a direct bus connection from our Y to their A.
|
//We must have a direct bus connection from our Y to their A.
|
||||||
const RTLIL::SigSpec aluy = sigmap(cell->getPort(ID(Y)));
|
const RTLIL::SigSpec aluy = sigmap(cell->getPort(ID::Y));
|
||||||
pool<Cell*> y_loads = get_other_cells(aluy, index, cell);
|
pool<Cell*> y_loads = get_other_cells(aluy, index, cell);
|
||||||
if(y_loads.size() != 1)
|
if(y_loads.size() != 1)
|
||||||
return 9;
|
return 9;
|
||||||
|
@ -166,11 +166,11 @@ int counter_tryextract(
|
||||||
extract.count_mux = count_mux;
|
extract.count_mux = count_mux;
|
||||||
if(count_mux->type != ID($mux))
|
if(count_mux->type != ID($mux))
|
||||||
return 10;
|
return 10;
|
||||||
if(!is_full_bus(aluy, index, cell, ID(Y), count_mux, ID(A)))
|
if(!is_full_bus(aluy, index, cell, ID::Y, count_mux, ID::A))
|
||||||
return 11;
|
return 11;
|
||||||
|
|
||||||
//B connection of the mux is our underflow value
|
//B connection of the mux is our underflow value
|
||||||
const RTLIL::SigSpec underflow = sigmap(count_mux->getPort(ID(B)));
|
const RTLIL::SigSpec underflow = sigmap(count_mux->getPort(ID::B));
|
||||||
if(!underflow.is_fully_const())
|
if(!underflow.is_fully_const())
|
||||||
return 12;
|
return 12;
|
||||||
extract.count_value = underflow.as_int();
|
extract.count_value = underflow.as_int();
|
||||||
|
@ -184,7 +184,7 @@ int counter_tryextract(
|
||||||
{
|
{
|
||||||
if(c->type != ID($logic_not))
|
if(c->type != ID($logic_not))
|
||||||
continue;
|
continue;
|
||||||
if(!is_full_bus(muxsel, index, c, ID(Y), count_mux, ID(S), true))
|
if(!is_full_bus(muxsel, index, c, ID::Y, count_mux, ID(S), true))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
underflow_inv = c;
|
underflow_inv = c;
|
||||||
|
@ -196,7 +196,7 @@ int counter_tryextract(
|
||||||
|
|
||||||
//Y connection of the mux must have exactly one load, the counter's internal register, if there's no clock enable
|
//Y connection of the mux must have exactly one load, the counter's internal register, if there's no clock enable
|
||||||
//If we have a clock enable, Y drives the B input of a mux. A of that mux must come from our register
|
//If we have a clock enable, Y drives the B input of a mux. A of that mux must come from our register
|
||||||
const RTLIL::SigSpec muxy = sigmap(count_mux->getPort(ID(Y)));
|
const RTLIL::SigSpec muxy = sigmap(count_mux->getPort(ID::Y));
|
||||||
pool<Cell*> muxy_loads = get_other_cells(muxy, index, count_mux);
|
pool<Cell*> muxy_loads = get_other_cells(muxy, index, count_mux);
|
||||||
if(muxy_loads.size() != 1)
|
if(muxy_loads.size() != 1)
|
||||||
return 14;
|
return 14;
|
||||||
|
@ -209,7 +209,7 @@ int counter_tryextract(
|
||||||
//This mux is probably a clock enable mux.
|
//This mux is probably a clock enable mux.
|
||||||
//Find our count register (should be our only load)
|
//Find our count register (should be our only load)
|
||||||
cemux = muxload;
|
cemux = muxload;
|
||||||
cey = sigmap(cemux->getPort(ID(Y)));
|
cey = sigmap(cemux->getPort(ID::Y));
|
||||||
pool<Cell*> cey_loads = get_other_cells(cey, index, cemux);
|
pool<Cell*> cey_loads = get_other_cells(cey, index, cemux);
|
||||||
if(cey_loads.size() != 1)
|
if(cey_loads.size() != 1)
|
||||||
return 24;
|
return 24;
|
||||||
|
@ -217,11 +217,11 @@ int counter_tryextract(
|
||||||
|
|
||||||
//Mux should have A driven by count Q, and B by muxy
|
//Mux should have A driven by count Q, and B by muxy
|
||||||
//TODO: if A and B are swapped, CE polarity is inverted
|
//TODO: if A and B are swapped, CE polarity is inverted
|
||||||
if(sigmap(cemux->getPort(ID(B))) != muxy)
|
if(sigmap(cemux->getPort(ID::B)) != muxy)
|
||||||
return 24;
|
return 24;
|
||||||
if(sigmap(cemux->getPort(ID(A))) != sigmap(count_reg->getPort(ID(Q))))
|
if(sigmap(cemux->getPort(ID::A)) != sigmap(count_reg->getPort(ID(Q))))
|
||||||
return 24;
|
return 24;
|
||||||
if(sigmap(cemux->getPort(ID(Y))) != sigmap(count_reg->getPort(ID(D))))
|
if(sigmap(cemux->getPort(ID::Y)) != sigmap(count_reg->getPort(ID(D))))
|
||||||
return 24;
|
return 24;
|
||||||
|
|
||||||
//Select of the mux is our clock enable
|
//Select of the mux is our clock enable
|
||||||
|
@ -260,12 +260,12 @@ int counter_tryextract(
|
||||||
//Sanity check that we use the ALU output properly
|
//Sanity check that we use the ALU output properly
|
||||||
if(extract.has_ce)
|
if(extract.has_ce)
|
||||||
{
|
{
|
||||||
if(!is_full_bus(muxy, index, count_mux, ID(Y), cemux, ID(B)))
|
if(!is_full_bus(muxy, index, count_mux, ID::Y, cemux, ID::B))
|
||||||
return 16;
|
return 16;
|
||||||
if(!is_full_bus(cey, index, cemux, ID(Y), count_reg, ID(D)))
|
if(!is_full_bus(cey, index, cemux, ID::Y, count_reg, ID(D)))
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
else if(!is_full_bus(muxy, index, count_mux, ID(Y), count_reg, ID(D)))
|
else if(!is_full_bus(muxy, index, count_mux, ID::Y, count_reg, ID(D)))
|
||||||
return 16;
|
return 16;
|
||||||
|
|
||||||
//TODO: Verify count_reg CLK_POLARITY is 1
|
//TODO: Verify count_reg CLK_POLARITY is 1
|
||||||
|
@ -312,9 +312,9 @@ int counter_tryextract(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!is_full_bus(cnout, index, count_reg, ID(Q), underflow_inv, ID(A), true))
|
if(!is_full_bus(cnout, index, count_reg, ID(Q), underflow_inv, ID::A, true))
|
||||||
return 18;
|
return 18;
|
||||||
if(!is_full_bus(cnout, index, count_reg, ID(Q), cell, ID(A), true))
|
if(!is_full_bus(cnout, index, count_reg, ID(Q), cell, ID::A, true))
|
||||||
return 19;
|
return 19;
|
||||||
|
|
||||||
//Look up the clock from the register
|
//Look up the clock from the register
|
||||||
|
@ -348,7 +348,7 @@ void counter_worker(
|
||||||
|
|
||||||
//A input is the count value. Check if it has COUNT_EXTRACT set.
|
//A input is the count value. Check if it has COUNT_EXTRACT set.
|
||||||
//If it's not a wire, don't even try
|
//If it's not a wire, don't even try
|
||||||
auto port = sigmap(cell->getPort(ID(A)));
|
auto port = sigmap(cell->getPort(ID::A));
|
||||||
if(!port.is_wire())
|
if(!port.is_wire())
|
||||||
return;
|
return;
|
||||||
RTLIL::Wire* a_wire = port.as_wire();
|
RTLIL::Wire* a_wire = port.as_wire();
|
||||||
|
@ -434,13 +434,13 @@ void counter_worker(
|
||||||
string countname = string("$COUNTx$") + log_id(extract.rwire->name.str());
|
string countname = string("$COUNTx$") + log_id(extract.rwire->name.str());
|
||||||
|
|
||||||
//Wipe all of the old connections to the ALU
|
//Wipe all of the old connections to the ALU
|
||||||
cell->unsetPort(ID(A));
|
cell->unsetPort(ID::A);
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
cell->unsetPort(ID(BI));
|
cell->unsetPort(ID(BI));
|
||||||
cell->unsetPort(ID(CI));
|
cell->unsetPort(ID(CI));
|
||||||
cell->unsetPort(ID(CO));
|
cell->unsetPort(ID(CO));
|
||||||
cell->unsetPort(ID(X));
|
cell->unsetPort(ID(X));
|
||||||
cell->unsetPort(ID(Y));
|
cell->unsetPort(ID::Y);
|
||||||
cell->unsetParam(ID(A_SIGNED));
|
cell->unsetParam(ID(A_SIGNED));
|
||||||
cell->unsetParam(ID(A_WIDTH));
|
cell->unsetParam(ID(A_WIDTH));
|
||||||
cell->unsetParam(ID(B_SIGNED));
|
cell->unsetParam(ID(B_SIGNED));
|
||||||
|
|
|
@ -89,7 +89,7 @@ struct ExtractFaWorker
|
||||||
ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($_MUX_), ID($_NMUX_),
|
ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($_MUX_), ID($_NMUX_),
|
||||||
ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
|
ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
|
||||||
{
|
{
|
||||||
SigBit y = sigmap(SigBit(cell->getPort(ID(Y))));
|
SigBit y = sigmap(SigBit(cell->getPort(ID::Y)));
|
||||||
log_assert(driver.count(y) == 0);
|
log_assert(driver.count(y) == 0);
|
||||||
driver[y] = cell;
|
driver[y] = cell;
|
||||||
}
|
}
|
||||||
|
@ -262,8 +262,8 @@ struct ExtractFaWorker
|
||||||
pool<SigBit> new_leaves = leaves;
|
pool<SigBit> new_leaves = leaves;
|
||||||
|
|
||||||
new_leaves.erase(bit);
|
new_leaves.erase(bit);
|
||||||
if (cell->hasPort(ID(A))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(A)))));
|
if (cell->hasPort(ID::A)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::A))));
|
||||||
if (cell->hasPort(ID(B))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(B)))));
|
if (cell->hasPort(ID::B)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::B))));
|
||||||
if (cell->hasPort(ID(C))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(C)))));
|
if (cell->hasPort(ID(C))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(C)))));
|
||||||
if (cell->hasPort(ID(D))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(D)))));
|
if (cell->hasPort(ID(D))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(D)))));
|
||||||
|
|
||||||
|
@ -277,8 +277,8 @@ struct ExtractFaWorker
|
||||||
void assign_new_driver(SigBit bit, SigBit new_driver)
|
void assign_new_driver(SigBit bit, SigBit new_driver)
|
||||||
{
|
{
|
||||||
Cell *cell = driver.at(bit);
|
Cell *cell = driver.at(bit);
|
||||||
if (sigmap(cell->getPort(ID(Y))) == bit) {
|
if (sigmap(cell->getPort(ID::Y)) == bit) {
|
||||||
cell->setPort(ID(Y), module->addWire(NEW_ID));
|
cell->setPort(ID::Y, module->addWire(NEW_ID));
|
||||||
module->connect(bit, new_driver);
|
module->connect(bit, new_driver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,15 +395,15 @@ struct ExtractFaWorker
|
||||||
|
|
||||||
log(" Created $fa cell %s.\n", log_id(cell));
|
log(" Created $fa cell %s.\n", log_id(cell));
|
||||||
|
|
||||||
cell->setPort(ID(A), f3i.inv_a ? module->NotGate(NEW_ID, A) : A);
|
cell->setPort(ID::A, f3i.inv_a ? module->NotGate(NEW_ID, A) : A);
|
||||||
cell->setPort(ID(B), f3i.inv_b ? module->NotGate(NEW_ID, B) : B);
|
cell->setPort(ID::B, f3i.inv_b ? module->NotGate(NEW_ID, B) : B);
|
||||||
cell->setPort(ID(C), f3i.inv_c ? module->NotGate(NEW_ID, C) : C);
|
cell->setPort(ID(C), f3i.inv_c ? module->NotGate(NEW_ID, C) : C);
|
||||||
|
|
||||||
X = module->addWire(NEW_ID);
|
X = module->addWire(NEW_ID);
|
||||||
Y = module->addWire(NEW_ID);
|
Y = module->addWire(NEW_ID);
|
||||||
|
|
||||||
cell->setPort(ID(X), X);
|
cell->setPort(ID(X), X);
|
||||||
cell->setPort(ID(Y), Y);
|
cell->setPort(ID::Y, Y);
|
||||||
|
|
||||||
facache[fakey] = make_tuple(X, Y, cell);
|
facache[fakey] = make_tuple(X, Y, cell);
|
||||||
}
|
}
|
||||||
|
@ -501,15 +501,15 @@ struct ExtractFaWorker
|
||||||
|
|
||||||
log(" Created $fa cell %s.\n", log_id(cell));
|
log(" Created $fa cell %s.\n", log_id(cell));
|
||||||
|
|
||||||
cell->setPort(ID(A), f2i.inv_a ? module->NotGate(NEW_ID, A) : A);
|
cell->setPort(ID::A, f2i.inv_a ? module->NotGate(NEW_ID, A) : A);
|
||||||
cell->setPort(ID(B), f2i.inv_b ? module->NotGate(NEW_ID, B) : B);
|
cell->setPort(ID::B, f2i.inv_b ? module->NotGate(NEW_ID, B) : B);
|
||||||
cell->setPort(ID(C), State::S0);
|
cell->setPort(ID(C), State::S0);
|
||||||
|
|
||||||
X = module->addWire(NEW_ID);
|
X = module->addWire(NEW_ID);
|
||||||
Y = module->addWire(NEW_ID);
|
Y = module->addWire(NEW_ID);
|
||||||
|
|
||||||
cell->setPort(ID(X), X);
|
cell->setPort(ID(X), X);
|
||||||
cell->setPort(ID(Y), Y);
|
cell->setPort(ID::Y, Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func2.at(key).count(xor2_func)) {
|
if (func2.at(key).count(xor2_func)) {
|
||||||
|
|
|
@ -148,7 +148,7 @@ struct ExtractReducePass : public Pass
|
||||||
|
|
||||||
head_cell = x;
|
head_cell = x;
|
||||||
|
|
||||||
auto y = sigmap(x->getPort(ID(Y)));
|
auto y = sigmap(x->getPort(ID::Y));
|
||||||
log_assert(y.size() == 1);
|
log_assert(y.size() == 1);
|
||||||
|
|
||||||
// Should only continue if there is one fanout back into a cell (not to a port)
|
// Should only continue if there is one fanout back into a cell (not to a port)
|
||||||
|
@ -166,7 +166,7 @@ struct ExtractReducePass : public Pass
|
||||||
{
|
{
|
||||||
//BFS, following all chains until they hit a cell of a different type
|
//BFS, following all chains until they hit a cell of a different type
|
||||||
//Pick the longest one
|
//Pick the longest one
|
||||||
auto y = sigmap(cell->getPort(ID(Y)));
|
auto y = sigmap(cell->getPort(ID::Y));
|
||||||
pool<Cell*> current_loads = sig_to_sink[y];
|
pool<Cell*> current_loads = sig_to_sink[y];
|
||||||
pool<Cell*> next_loads;
|
pool<Cell*> next_loads;
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ struct ExtractReducePass : public Pass
|
||||||
|
|
||||||
cur_supercell.insert(x);
|
cur_supercell.insert(x);
|
||||||
|
|
||||||
auto a = sigmap(x->getPort(ID(A)));
|
auto a = sigmap(x->getPort(ID::A));
|
||||||
log_assert(a.size() == 1);
|
log_assert(a.size() == 1);
|
||||||
|
|
||||||
// Must have only one sink unless we're going off chain
|
// Must have only one sink unless we're going off chain
|
||||||
|
@ -249,7 +249,7 @@ struct ExtractReducePass : public Pass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto b = sigmap(x->getPort(ID(B)));
|
auto b = sigmap(x->getPort(ID::B));
|
||||||
log_assert(b.size() == 1);
|
log_assert(b.size() == 1);
|
||||||
|
|
||||||
// Must have only one sink
|
// Must have only one sink
|
||||||
|
@ -279,16 +279,16 @@ struct ExtractReducePass : public Pass
|
||||||
pool<SigBit> input_pool_intermed;
|
pool<SigBit> input_pool_intermed;
|
||||||
for (auto x : cur_supercell)
|
for (auto x : cur_supercell)
|
||||||
{
|
{
|
||||||
input_pool.insert(sigmap(x->getPort(ID(A)))[0]);
|
input_pool.insert(sigmap(x->getPort(ID::A))[0]);
|
||||||
input_pool.insert(sigmap(x->getPort(ID(B)))[0]);
|
input_pool.insert(sigmap(x->getPort(ID::B))[0]);
|
||||||
input_pool_intermed.insert(sigmap(x->getPort(ID(Y)))[0]);
|
input_pool_intermed.insert(sigmap(x->getPort(ID::Y))[0]);
|
||||||
}
|
}
|
||||||
SigSpec input;
|
SigSpec input;
|
||||||
for (auto b : input_pool)
|
for (auto b : input_pool)
|
||||||
if (input_pool_intermed.count(b) == 0)
|
if (input_pool_intermed.count(b) == 0)
|
||||||
input.append_bit(b);
|
input.append_bit(b);
|
||||||
|
|
||||||
SigBit output = sigmap(head_cell->getPort(ID(Y))[0]);
|
SigBit output = sigmap(head_cell->getPort(ID::Y)[0]);
|
||||||
|
|
||||||
auto new_reduce_cell = module->addCell(NEW_ID,
|
auto new_reduce_cell = module->addCell(NEW_ID,
|
||||||
gt == GateType::And ? ID($reduce_and) :
|
gt == GateType::And ? ID($reduce_and) :
|
||||||
|
@ -297,8 +297,8 @@ struct ExtractReducePass : public Pass
|
||||||
new_reduce_cell->setParam(ID(A_SIGNED), 0);
|
new_reduce_cell->setParam(ID(A_SIGNED), 0);
|
||||||
new_reduce_cell->setParam(ID(A_WIDTH), input.size());
|
new_reduce_cell->setParam(ID(A_WIDTH), input.size());
|
||||||
new_reduce_cell->setParam(ID(Y_WIDTH), 1);
|
new_reduce_cell->setParam(ID(Y_WIDTH), 1);
|
||||||
new_reduce_cell->setPort(ID(A), input);
|
new_reduce_cell->setPort(ID::A, input);
|
||||||
new_reduce_cell->setPort(ID(Y), output);
|
new_reduce_cell->setPort(ID::Y, output);
|
||||||
|
|
||||||
if(allow_off_chain)
|
if(allow_off_chain)
|
||||||
consumed_cells.insert(head_cell);
|
consumed_cells.insert(head_cell);
|
||||||
|
|
|
@ -198,7 +198,7 @@ struct IopadmapPass : public Pass {
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
if (cell->type == ID($_TBUF_)) {
|
if (cell->type == ID($_TBUF_)) {
|
||||||
SigBit bit = sigmap(cell->getPort(ID(Y)).as_bit());
|
SigBit bit = sigmap(cell->getPort(ID::Y).as_bit());
|
||||||
tbuf_bits[bit].first = cell->name;
|
tbuf_bits[bit].first = cell->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ struct IopadmapPass : public Pass {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SigBit en_sig = tbuf_cell->getPort(ID(E)).as_bit();
|
SigBit en_sig = tbuf_cell->getPort(ID(E)).as_bit();
|
||||||
SigBit data_sig = tbuf_cell->getPort(ID(A)).as_bit();
|
SigBit data_sig = tbuf_cell->getPort(ID::A).as_bit();
|
||||||
|
|
||||||
if (wire->port_input && !tinoutpad_celltype.empty())
|
if (wire->port_input && !tinoutpad_celltype.empty())
|
||||||
{
|
{
|
||||||
|
@ -244,7 +244,7 @@ struct IopadmapPass : public Pass {
|
||||||
cell->setPort(RTLIL::escape_id(tinoutpad_portname2), owire);
|
cell->setPort(RTLIL::escape_id(tinoutpad_portname2), owire);
|
||||||
cell->setPort(RTLIL::escape_id(tinoutpad_portname3), data_sig);
|
cell->setPort(RTLIL::escape_id(tinoutpad_portname3), data_sig);
|
||||||
cell->setPort(RTLIL::escape_id(tinoutpad_portname4), wire_bit);
|
cell->setPort(RTLIL::escape_id(tinoutpad_portname4), wire_bit);
|
||||||
cell->attributes[ID(keep)] = RTLIL::Const(1);
|
cell->attributes[ID::keep] = RTLIL::Const(1);
|
||||||
|
|
||||||
for (auto cn : tbuf_cache.second) {
|
for (auto cn : tbuf_cache.second) {
|
||||||
auto c = module->cell(cn);
|
auto c = module->cell(cn);
|
||||||
|
@ -281,7 +281,7 @@ struct IopadmapPass : public Pass {
|
||||||
cell->setPort(RTLIL::escape_id(toutpad_portname), en_sig);
|
cell->setPort(RTLIL::escape_id(toutpad_portname), en_sig);
|
||||||
cell->setPort(RTLIL::escape_id(toutpad_portname2), data_sig);
|
cell->setPort(RTLIL::escape_id(toutpad_portname2), data_sig);
|
||||||
cell->setPort(RTLIL::escape_id(toutpad_portname3), wire_bit);
|
cell->setPort(RTLIL::escape_id(toutpad_portname3), wire_bit);
|
||||||
cell->attributes[ID(keep)] = RTLIL::Const(1);
|
cell->attributes[ID::keep] = RTLIL::Const(1);
|
||||||
|
|
||||||
for (auto cn : tbuf_cache.second) {
|
for (auto cn : tbuf_cache.second) {
|
||||||
auto c = module->cell(cn);
|
auto c = module->cell(cn);
|
||||||
|
@ -408,7 +408,7 @@ struct IopadmapPass : public Pass {
|
||||||
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1);
|
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1);
|
||||||
if (!nameparam.empty())
|
if (!nameparam.empty())
|
||||||
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(stringf("%s[%d]", RTLIL::id2cstr(wire->name), i));
|
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(stringf("%s[%d]", RTLIL::id2cstr(wire->name), i));
|
||||||
cell->attributes[ID(keep)] = RTLIL::Const(1);
|
cell->attributes[ID::keep] = RTLIL::Const(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -421,7 +421,7 @@ struct IopadmapPass : public Pass {
|
||||||
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
|
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
|
||||||
if (!nameparam.empty())
|
if (!nameparam.empty())
|
||||||
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(RTLIL::id2cstr(wire->name));
|
cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(RTLIL::id2cstr(wire->name));
|
||||||
cell->attributes[ID(keep)] = RTLIL::Const(1);
|
cell->attributes[ID::keep] = RTLIL::Const(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
wire->port_id = 0;
|
wire->port_id = 0;
|
||||||
|
|
|
@ -25,8 +25,8 @@ PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
int lut2mux(Cell *cell)
|
int lut2mux(Cell *cell)
|
||||||
{
|
{
|
||||||
SigSpec sig_a = cell->getPort(ID(A));
|
SigSpec sig_a = cell->getPort(ID::A);
|
||||||
SigSpec sig_y = cell->getPort(ID(Y));
|
SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
Const lut = cell->getParam(ID(LUT));
|
Const lut = cell->getParam(ID(LUT));
|
||||||
int count = 1;
|
int count = 1;
|
||||||
|
|
||||||
|
|
|
@ -113,10 +113,10 @@ struct MaccmapWorker
|
||||||
|
|
||||||
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($fa));
|
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($fa));
|
||||||
cell->setParam(ID(WIDTH), width);
|
cell->setParam(ID(WIDTH), width);
|
||||||
cell->setPort(ID(A), in1);
|
cell->setPort(ID::A, in1);
|
||||||
cell->setPort(ID(B), in2);
|
cell->setPort(ID::B, in2);
|
||||||
cell->setPort(ID(C), in3);
|
cell->setPort(ID(C), in3);
|
||||||
cell->setPort(ID(Y), w1);
|
cell->setPort(ID::Y, w1);
|
||||||
cell->setPort(ID(X), w2);
|
cell->setPort(ID(X), w2);
|
||||||
|
|
||||||
out1 = {out_zeros_msb, w1, out_zeros_lsb};
|
out1 = {out_zeros_msb, w1, out_zeros_lsb};
|
||||||
|
@ -238,11 +238,11 @@ struct MaccmapWorker
|
||||||
|
|
||||||
|
|
||||||
RTLIL::Cell *c = module->addCell(NEW_ID, ID($alu));
|
RTLIL::Cell *c = module->addCell(NEW_ID, ID($alu));
|
||||||
c->setPort(ID(A), summands.front());
|
c->setPort(ID::A, summands.front());
|
||||||
c->setPort(ID(B), summands.back());
|
c->setPort(ID::B, summands.back());
|
||||||
c->setPort(ID(CI), State::S0);
|
c->setPort(ID(CI), State::S0);
|
||||||
c->setPort(ID(BI), State::S0);
|
c->setPort(ID(BI), State::S0);
|
||||||
c->setPort(ID(Y), module->addWire(NEW_ID, width));
|
c->setPort(ID::Y, module->addWire(NEW_ID, width));
|
||||||
c->setPort(ID(X), module->addWire(NEW_ID, width));
|
c->setPort(ID(X), module->addWire(NEW_ID, width));
|
||||||
c->setPort(ID(CO), module->addWire(NEW_ID, width));
|
c->setPort(ID(CO), module->addWire(NEW_ID, width));
|
||||||
c->fixup_parameters();
|
c->fixup_parameters();
|
||||||
|
@ -253,7 +253,7 @@ struct MaccmapWorker
|
||||||
}
|
}
|
||||||
log_assert(tree_sum_bits.empty());
|
log_assert(tree_sum_bits.empty());
|
||||||
|
|
||||||
return c->getPort(ID(Y));
|
return c->getPort(ID::Y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -264,17 +264,17 @@ extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false
|
||||||
|
|
||||||
void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
|
void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
|
||||||
{
|
{
|
||||||
int width = GetSize(cell->getPort(ID(Y)));
|
int width = GetSize(cell->getPort(ID::Y));
|
||||||
|
|
||||||
Macc macc;
|
Macc macc;
|
||||||
macc.from_cell(cell);
|
macc.from_cell(cell);
|
||||||
|
|
||||||
RTLIL::SigSpec all_input_bits;
|
RTLIL::SigSpec all_input_bits;
|
||||||
all_input_bits.append(cell->getPort(ID(A)));
|
all_input_bits.append(cell->getPort(ID::A));
|
||||||
all_input_bits.append(cell->getPort(ID(B)));
|
all_input_bits.append(cell->getPort(ID::B));
|
||||||
|
|
||||||
if (all_input_bits.to_sigbit_set().count(RTLIL::Sx)) {
|
if (all_input_bits.to_sigbit_set().count(RTLIL::Sx)) {
|
||||||
module->connect(cell->getPort(ID(Y)), RTLIL::SigSpec(RTLIL::Sx, width));
|
module->connect(cell->getPort(ID::Y), RTLIL::SigSpec(RTLIL::Sx, width));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,9 +339,9 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (summands.front().second)
|
if (summands.front().second)
|
||||||
module->addNeg(NEW_ID, summands.front().first, cell->getPort(ID(Y)));
|
module->addNeg(NEW_ID, summands.front().first, cell->getPort(ID::Y));
|
||||||
else
|
else
|
||||||
module->connect(cell->getPort(ID(Y)), summands.front().first);
|
module->connect(cell->getPort(ID::Y), summands.front().first);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -356,7 +356,7 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
|
||||||
for (auto &bit : macc.bit_ports)
|
for (auto &bit : macc.bit_ports)
|
||||||
worker.add(bit, 0);
|
worker.add(bit, 0);
|
||||||
|
|
||||||
module->connect(cell->getPort(ID(Y)), worker.synth());
|
module->connect(cell->getPort(ID::Y), worker.synth());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ struct MuxcoverWorker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cell->type == ID($_MUX_))
|
if (cell->type == ID($_MUX_))
|
||||||
sig_to_mux[sigmap(cell->getPort(ID(Y)))] = cell;
|
sig_to_mux[sigmap(cell->getPort(ID::Y))] = cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(" Treeifying %d MUXes:\n", GetSize(sig_to_mux));
|
log(" Treeifying %d MUXes:\n", GetSize(sig_to_mux));
|
||||||
|
@ -141,8 +141,8 @@ struct MuxcoverWorker
|
||||||
if (sig_to_mux.count(bit) && (bit == rootsig || !roots.count(bit))) {
|
if (sig_to_mux.count(bit) && (bit == rootsig || !roots.count(bit))) {
|
||||||
Cell *c = sig_to_mux.at(bit);
|
Cell *c = sig_to_mux.at(bit);
|
||||||
tree.muxes[bit] = c;
|
tree.muxes[bit] = c;
|
||||||
wavefront.insert(sigmap(c->getPort(ID(A))));
|
wavefront.insert(sigmap(c->getPort(ID::A)));
|
||||||
wavefront.insert(sigmap(c->getPort(ID(B))));
|
wavefront.insert(sigmap(c->getPort(ID::B)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,31 +517,31 @@ struct MuxcoverWorker
|
||||||
if (GetSize(mux.inputs) == 2) {
|
if (GetSize(mux.inputs) == 2) {
|
||||||
count_muxes_by_type[0]++;
|
count_muxes_by_type[0]++;
|
||||||
Cell *cell = module->addCell(NEW_ID, ID($_MUX_));
|
Cell *cell = module->addCell(NEW_ID, ID($_MUX_));
|
||||||
cell->setPort(ID(A), mux.inputs[0]);
|
cell->setPort(ID::A, mux.inputs[0]);
|
||||||
cell->setPort(ID(B), mux.inputs[1]);
|
cell->setPort(ID::B, mux.inputs[1]);
|
||||||
cell->setPort(ID(S), mux.selects[0]);
|
cell->setPort(ID(S), mux.selects[0]);
|
||||||
cell->setPort(ID(Y), bit);
|
cell->setPort(ID::Y, bit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSize(mux.inputs) == 4) {
|
if (GetSize(mux.inputs) == 4) {
|
||||||
count_muxes_by_type[1]++;
|
count_muxes_by_type[1]++;
|
||||||
Cell *cell = module->addCell(NEW_ID, ID($_MUX4_));
|
Cell *cell = module->addCell(NEW_ID, ID($_MUX4_));
|
||||||
cell->setPort(ID(A), mux.inputs[0]);
|
cell->setPort(ID::A, mux.inputs[0]);
|
||||||
cell->setPort(ID(B), mux.inputs[1]);
|
cell->setPort(ID::B, mux.inputs[1]);
|
||||||
cell->setPort(ID(C), mux.inputs[2]);
|
cell->setPort(ID(C), mux.inputs[2]);
|
||||||
cell->setPort(ID(D), mux.inputs[3]);
|
cell->setPort(ID(D), mux.inputs[3]);
|
||||||
cell->setPort(ID(S), mux.selects[0]);
|
cell->setPort(ID(S), mux.selects[0]);
|
||||||
cell->setPort(ID(T), mux.selects[1]);
|
cell->setPort(ID(T), mux.selects[1]);
|
||||||
cell->setPort(ID(Y), bit);
|
cell->setPort(ID::Y, bit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSize(mux.inputs) == 8) {
|
if (GetSize(mux.inputs) == 8) {
|
||||||
count_muxes_by_type[2]++;
|
count_muxes_by_type[2]++;
|
||||||
Cell *cell = module->addCell(NEW_ID, ID($_MUX8_));
|
Cell *cell = module->addCell(NEW_ID, ID($_MUX8_));
|
||||||
cell->setPort(ID(A), mux.inputs[0]);
|
cell->setPort(ID::A, mux.inputs[0]);
|
||||||
cell->setPort(ID(B), mux.inputs[1]);
|
cell->setPort(ID::B, mux.inputs[1]);
|
||||||
cell->setPort(ID(C), mux.inputs[2]);
|
cell->setPort(ID(C), mux.inputs[2]);
|
||||||
cell->setPort(ID(D), mux.inputs[3]);
|
cell->setPort(ID(D), mux.inputs[3]);
|
||||||
cell->setPort(ID(E), mux.inputs[4]);
|
cell->setPort(ID(E), mux.inputs[4]);
|
||||||
|
@ -551,15 +551,15 @@ struct MuxcoverWorker
|
||||||
cell->setPort(ID(S), mux.selects[0]);
|
cell->setPort(ID(S), mux.selects[0]);
|
||||||
cell->setPort(ID(T), mux.selects[1]);
|
cell->setPort(ID(T), mux.selects[1]);
|
||||||
cell->setPort(ID(U), mux.selects[2]);
|
cell->setPort(ID(U), mux.selects[2]);
|
||||||
cell->setPort(ID(Y), bit);
|
cell->setPort(ID::Y, bit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSize(mux.inputs) == 16) {
|
if (GetSize(mux.inputs) == 16) {
|
||||||
count_muxes_by_type[3]++;
|
count_muxes_by_type[3]++;
|
||||||
Cell *cell = module->addCell(NEW_ID, ID($_MUX16_));
|
Cell *cell = module->addCell(NEW_ID, ID($_MUX16_));
|
||||||
cell->setPort(ID(A), mux.inputs[0]);
|
cell->setPort(ID::A, mux.inputs[0]);
|
||||||
cell->setPort(ID(B), mux.inputs[1]);
|
cell->setPort(ID::B, mux.inputs[1]);
|
||||||
cell->setPort(ID(C), mux.inputs[2]);
|
cell->setPort(ID(C), mux.inputs[2]);
|
||||||
cell->setPort(ID(D), mux.inputs[3]);
|
cell->setPort(ID(D), mux.inputs[3]);
|
||||||
cell->setPort(ID(E), mux.inputs[4]);
|
cell->setPort(ID(E), mux.inputs[4]);
|
||||||
|
@ -578,7 +578,7 @@ struct MuxcoverWorker
|
||||||
cell->setPort(ID(T), mux.selects[1]);
|
cell->setPort(ID(T), mux.selects[1]);
|
||||||
cell->setPort(ID(U), mux.selects[2]);
|
cell->setPort(ID(U), mux.selects[2]);
|
||||||
cell->setPort(ID(V), mux.selects[3]);
|
cell->setPort(ID(V), mux.selects[3]);
|
||||||
cell->setPort(ID(Y), bit);
|
cell->setPort(ID::Y, bit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ struct NlutmapWorker
|
||||||
if (cell->type != ID($lut) || mapped_cells.count(cell))
|
if (cell->type != ID($lut) || mapped_cells.count(cell))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (GetSize(cell->getPort(ID(A))) == lut_size || lut_size == 2)
|
if (GetSize(cell->getPort(ID::A)) == lut_size || lut_size == 2)
|
||||||
candidate_ratings[cell] = 0;
|
candidate_ratings[cell] = 0;
|
||||||
|
|
||||||
for (auto &conn : cell->connections())
|
for (auto &conn : cell->connections())
|
||||||
|
|
|
@ -92,18 +92,18 @@ struct PmuxtreePass : public Pass {
|
||||||
if (cell->type != ID($pmux))
|
if (cell->type != ID($pmux))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SigSpec sig_data = cell->getPort(ID(B));
|
SigSpec sig_data = cell->getPort(ID::B);
|
||||||
SigSpec sig_sel = cell->getPort(ID(S));
|
SigSpec sig_sel = cell->getPort(ID(S));
|
||||||
|
|
||||||
if (!cell->getPort(ID(A)).is_fully_undef()) {
|
if (!cell->getPort(ID::A).is_fully_undef()) {
|
||||||
sig_data.append(cell->getPort(ID(A)));
|
sig_data.append(cell->getPort(ID::A));
|
||||||
SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel);
|
SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel);
|
||||||
sig_sel.append(module->Not(NEW_ID, sig_sel_or));
|
sig_sel.append(module->Not(NEW_ID, sig_sel_or));
|
||||||
}
|
}
|
||||||
|
|
||||||
SigSpec result, result_or;
|
SigSpec result, result_or;
|
||||||
result = recursive_mux_generator(module, sig_data, sig_sel, result_or);
|
result = recursive_mux_generator(module, sig_data, sig_sel, result_or);
|
||||||
module->connect(cell->getPort(ID(Y)), result);
|
module->connect(cell->getPort(ID::Y), result);
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,16 +107,16 @@ struct ShregmapTechXilinx7 : ShregmapTech
|
||||||
if (cell->type == ID($shiftx)) {
|
if (cell->type == ID($shiftx)) {
|
||||||
if (cell->getParam(ID(Y_WIDTH)) != 1) continue;
|
if (cell->getParam(ID(Y_WIDTH)) != 1) continue;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (auto bit : sigmap(cell->getPort(ID(A))))
|
for (auto bit : sigmap(cell->getPort(ID::A)))
|
||||||
sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0);
|
sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0);
|
||||||
log_assert(j == cell->getParam(ID(A_WIDTH)).as_int());
|
log_assert(j == cell->getParam(ID(A_WIDTH)).as_int());
|
||||||
}
|
}
|
||||||
else if (cell->type == ID($mux)) {
|
else if (cell->type == ID($mux)) {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (auto bit : sigmap(cell->getPort(ID(A))))
|
for (auto bit : sigmap(cell->getPort(ID::A)))
|
||||||
sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++);
|
sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++);
|
||||||
j = 0;
|
j = 0;
|
||||||
for (auto bit : sigmap(cell->getPort(ID(B))))
|
for (auto bit : sigmap(cell->getPort(ID::B)))
|
||||||
sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++);
|
sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,9 +128,9 @@ struct ShregmapTechXilinx7 : ShregmapTech
|
||||||
if (it == sigbit_to_shiftx_offset.end())
|
if (it == sigbit_to_shiftx_offset.end())
|
||||||
return;
|
return;
|
||||||
if (cell) {
|
if (cell) {
|
||||||
if (cell->type == ID($shiftx) && port == ID(A))
|
if (cell->type == ID($shiftx) && port == ID::A)
|
||||||
return;
|
return;
|
||||||
if (cell->type == ID($mux) && port.in(ID(A), ID(B)))
|
if (cell->type == ID($mux) && port.in(ID::A, ID::B))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sigbit_to_shiftx_offset.erase(it);
|
sigbit_to_shiftx_offset.erase(it);
|
||||||
|
@ -183,7 +183,7 @@ struct ShregmapTechXilinx7 : ShregmapTech
|
||||||
// Due to padding the most significant bits of A may be 1'bx,
|
// Due to padding the most significant bits of A may be 1'bx,
|
||||||
// and if so, discount them
|
// and if so, discount them
|
||||||
if (GetSize(taps) < shiftx->getParam(ID(A_WIDTH)).as_int()) {
|
if (GetSize(taps) < shiftx->getParam(ID(A_WIDTH)).as_int()) {
|
||||||
const SigSpec A = shiftx->getPort(ID(A));
|
const SigSpec A = shiftx->getPort(ID::A);
|
||||||
const int A_width = shiftx->getParam(ID(A_WIDTH)).as_int();
|
const int A_width = shiftx->getParam(ID(A_WIDTH)).as_int();
|
||||||
for (int i = GetSize(taps); i < A_width; ++i)
|
for (int i = GetSize(taps); i < A_width; ++i)
|
||||||
if (A[i] != RTLIL::Sx) return false;
|
if (A[i] != RTLIL::Sx) return false;
|
||||||
|
@ -223,14 +223,14 @@ struct ShregmapTechXilinx7 : ShregmapTech
|
||||||
Cell* shiftx = std::get<0>(it->second);
|
Cell* shiftx = std::get<0>(it->second);
|
||||||
RTLIL::SigSpec l_wire, q_wire;
|
RTLIL::SigSpec l_wire, q_wire;
|
||||||
if (shiftx->type == ID($shiftx)) {
|
if (shiftx->type == ID($shiftx)) {
|
||||||
l_wire = shiftx->getPort(ID(B));
|
l_wire = shiftx->getPort(ID::B);
|
||||||
q_wire = shiftx->getPort(ID(Y));
|
q_wire = shiftx->getPort(ID::Y);
|
||||||
shiftx->setPort(ID(Y), cell->module->addWire(NEW_ID));
|
shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID));
|
||||||
}
|
}
|
||||||
else if (shiftx->type == ID($mux)) {
|
else if (shiftx->type == ID($mux)) {
|
||||||
l_wire = shiftx->getPort(ID(S));
|
l_wire = shiftx->getPort(ID(S));
|
||||||
q_wire = shiftx->getPort(ID(Y));
|
q_wire = shiftx->getPort(ID::Y);
|
||||||
shiftx->setPort(ID(Y), cell->module->addWire(NEW_ID));
|
shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID));
|
||||||
}
|
}
|
||||||
else log_abort();
|
else log_abort();
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ struct ShregmapWorker
|
||||||
{
|
{
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
{
|
{
|
||||||
if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
|
if (wire->port_output || wire->get_bool_attribute(ID::keep)) {
|
||||||
for (auto bit : sigmap(wire)) {
|
for (auto bit : sigmap(wire)) {
|
||||||
sigbit_with_non_chain_users.insert(bit);
|
sigbit_with_non_chain_users.insert(bit);
|
||||||
if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {});
|
if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {});
|
||||||
|
@ -283,7 +283,7 @@ struct ShregmapWorker
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
{
|
{
|
||||||
if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute(ID(keep)))
|
if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute(ID::keep))
|
||||||
{
|
{
|
||||||
IdString d_port = opts.ffcells.at(cell->type).first;
|
IdString d_port = opts.ffcells.at(cell->type).first;
|
||||||
IdString q_port = opts.ffcells.at(cell->type).second;
|
IdString q_port = opts.ffcells.at(cell->type).second;
|
||||||
|
|
|
@ -28,23 +28,23 @@ YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
|
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a[i]);
|
gate->setPort(ID::A, sig_a[i]);
|
||||||
gate->setPort(ID(Y), sig_y[i]);
|
gate->setPort(ID::Y, sig_y[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
|
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
|
||||||
|
|
||||||
|
@ -53,9 +53,9 @@ void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
|
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
|
||||||
sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID(B_SIGNED)).as_bool());
|
sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID(B_SIGNED)).as_bool());
|
||||||
|
@ -67,8 +67,8 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_t[i]);
|
gate->setPort(ID::A, sig_t[i]);
|
||||||
gate->setPort(ID(Y), sig_y[i]);
|
gate->setPort(ID::Y, sig_y[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sig_y = sig_t;
|
sig_y = sig_t;
|
||||||
|
@ -84,16 +84,16 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
|
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a[i]);
|
gate->setPort(ID::A, sig_a[i]);
|
||||||
gate->setPort(ID(B), sig_b[i]);
|
gate->setPort(ID::B, sig_b[i]);
|
||||||
gate->setPort(ID(Y), sig_y[i]);
|
gate->setPort(ID::Y, sig_y[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
if (sig_y.size() == 0)
|
if (sig_y.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -135,9 +135,9 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
|
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
|
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a[i]);
|
gate->setPort(ID::A, sig_a[i]);
|
||||||
gate->setPort(ID(B), sig_a[i+1]);
|
gate->setPort(ID::B, sig_a[i+1]);
|
||||||
gate->setPort(ID(Y), sig_t[i/2]);
|
gate->setPort(ID::Y, sig_t[i/2]);
|
||||||
last_output_cell = gate;
|
last_output_cell = gate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
|
RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a);
|
gate->setPort(ID::A, sig_a);
|
||||||
gate->setPort(ID(Y), sig_t);
|
gate->setPort(ID::Y, sig_t);
|
||||||
last_output_cell = gate;
|
last_output_cell = gate;
|
||||||
sig_a = sig_t;
|
sig_a = sig_t;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
if (last_output_cell == NULL) {
|
if (last_output_cell == NULL) {
|
||||||
module->connect(RTLIL::SigSig(sig_y, sig_a));
|
module->connect(RTLIL::SigSig(sig_y, sig_a));
|
||||||
} else {
|
} else {
|
||||||
last_output_cell->setPort(ID(Y), sig_y);
|
last_output_cell->setPort(ID::Y, sig_y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,9 +176,9 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell
|
||||||
|
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig[i]);
|
gate->setPort(ID::A, sig[i]);
|
||||||
gate->setPort(ID(B), sig[i+1]);
|
gate->setPort(ID::B, sig[i+1]);
|
||||||
gate->setPort(ID(Y), sig_t[i/2]);
|
gate->setPort(ID::Y, sig_t[i/2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sig = sig_t;
|
sig = sig_t;
|
||||||
|
@ -190,10 +190,10 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell
|
||||||
|
|
||||||
void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
logic_reduce(module, sig_a, cell);
|
logic_reduce(module, sig_a, cell);
|
||||||
|
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
if (sig_y.size() == 0)
|
if (sig_y.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -205,19 +205,19 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
|
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a);
|
gate->setPort(ID::A, sig_a);
|
||||||
gate->setPort(ID(Y), sig_y);
|
gate->setPort(ID::Y, sig_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
logic_reduce(module, sig_a, cell);
|
logic_reduce(module, sig_a, cell);
|
||||||
|
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
logic_reduce(module, sig_b, cell);
|
logic_reduce(module, sig_b, cell);
|
||||||
|
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
if (sig_y.size() == 0)
|
if (sig_y.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -234,16 +234,16 @@ void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
|
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
|
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a);
|
gate->setPort(ID::A, sig_a);
|
||||||
gate->setPort(ID(B), sig_b);
|
gate->setPort(ID::B, sig_b);
|
||||||
gate->setPort(ID(Y), sig_y);
|
gate->setPort(ID::Y, sig_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
bool is_signed = cell->parameters.at(ID(A_SIGNED)).as_bool();
|
bool is_signed = cell->parameters.at(ID(A_SIGNED)).as_bool();
|
||||||
bool is_ne = cell->type.in(ID($ne), ID($nex));
|
bool is_ne = cell->type.in(ID($ne), ID($nex));
|
||||||
|
|
||||||
|
@ -269,38 +269,38 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
|
|
||||||
void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_b = cell->getPort(ID(B));
|
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a[i]);
|
gate->setPort(ID::A, sig_a[i]);
|
||||||
gate->setPort(ID(B), sig_b[i]);
|
gate->setPort(ID::B, sig_b[i]);
|
||||||
gate->setPort(ID(S), cell->getPort(ID(S)));
|
gate->setPort(ID(S), cell->getPort(ID(S)));
|
||||||
gate->setPort(ID(Y), sig_y[i]);
|
gate->setPort(ID::Y, sig_y[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_e = cell->getPort(ID(EN));
|
RTLIL::SigSpec sig_e = cell->getPort(ID(EN));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), sig_a[i]);
|
gate->setPort(ID::A, sig_a[i]);
|
||||||
gate->setPort(ID(E), sig_e);
|
gate->setPort(ID(E), sig_e);
|
||||||
gate->setPort(ID(Y), sig_y[i]);
|
gate->setPort(ID::Y, sig_y[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
SigSpec lut_ctrl = cell->getPort(ID(A));
|
SigSpec lut_ctrl = cell->getPort(ID::A);
|
||||||
SigSpec lut_data = cell->getParam(ID(LUT));
|
SigSpec lut_data = cell->getParam(ID(LUT));
|
||||||
lut_data.extend_u0(1 << cell->getParam(ID(WIDTH)).as_int());
|
lut_data.extend_u0(1 << cell->getParam(ID(WIDTH)).as_int());
|
||||||
|
|
||||||
|
@ -310,20 +310,20 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
for (int i = 0; i < GetSize(lut_data); i += 2) {
|
for (int i = 0; i < GetSize(lut_data); i += 2) {
|
||||||
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
|
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
|
||||||
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
|
||||||
gate->setPort(ID(A), lut_data[i]);
|
gate->setPort(ID::A, lut_data[i]);
|
||||||
gate->setPort(ID(B), lut_data[i+1]);
|
gate->setPort(ID::B, lut_data[i+1]);
|
||||||
gate->setPort(ID(S), lut_ctrl[idx]);
|
gate->setPort(ID(S), lut_ctrl[idx]);
|
||||||
gate->setPort(ID(Y), new_lut_data[i/2]);
|
gate->setPort(ID::Y, new_lut_data[i/2]);
|
||||||
}
|
}
|
||||||
lut_data = new_lut_data;
|
lut_data = new_lut_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
module->connect(cell->getPort(ID(Y)), lut_data);
|
module->connect(cell->getPort(ID::Y), lut_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
SigSpec ctrl = cell->getPort(ID(A));
|
SigSpec ctrl = cell->getPort(ID::A);
|
||||||
SigSpec table = cell->getParam(ID(TABLE));
|
SigSpec table = cell->getParam(ID(TABLE));
|
||||||
|
|
||||||
int width = cell->getParam(ID(WIDTH)).as_int();
|
int width = cell->getParam(ID(WIDTH)).as_int();
|
||||||
|
@ -348,22 +348,22 @@ void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
products.append(GetSize(in) > 0 ? module->Eq(NEW_ID, in, pat) : State::S1);
|
products.append(GetSize(in) > 0 ? module->Eq(NEW_ID, in, pat) : State::S1);
|
||||||
}
|
}
|
||||||
|
|
||||||
module->connect(cell->getPort(ID(Y)), module->ReduceOr(NEW_ID, products));
|
module->connect(cell->getPort(ID::Y), module->ReduceOr(NEW_ID, products));
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
int offset = cell->parameters.at(ID(OFFSET)).as_int();
|
int offset = cell->parameters.at(ID(OFFSET)).as_int();
|
||||||
RTLIL::SigSpec sig_a = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size())));
|
module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
|
void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_ab = cell->getPort(ID(A));
|
RTLIL::SigSpec sig_ab = cell->getPort(ID::A);
|
||||||
sig_ab.append(cell->getPort(ID(B)));
|
sig_ab.append(cell->getPort(ID::B));
|
||||||
RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
|
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
|
||||||
module->connect(RTLIL::SigSig(sig_y, sig_ab));
|
module->connect(RTLIL::SigSig(sig_y, sig_ab));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ struct TechmapWorker
|
||||||
record.wire = it.second;
|
record.wire = it.second;
|
||||||
record.value = it.second;
|
record.value = it.second;
|
||||||
result[p].push_back(record);
|
result[p].push_back(record);
|
||||||
it.second->attributes[ID(keep)] = RTLIL::Const(1);
|
it.second->attributes[ID::keep] = RTLIL::Const(1);
|
||||||
it.second->attributes[ID(_techmap_special_)] = RTLIL::Const(1);
|
it.second->attributes[ID(_techmap_special_)] = RTLIL::Const(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -520,7 +520,7 @@ struct TechmapWorker
|
||||||
int port_counter = 1;
|
int port_counter = 1;
|
||||||
for (auto &c : extmapper_cell->connections_) {
|
for (auto &c : extmapper_cell->connections_) {
|
||||||
RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second));
|
RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second));
|
||||||
if (w->name.in(ID(Y), ID(Q)))
|
if (w->name.in(ID::Y, ID(Q)))
|
||||||
w->port_output = true;
|
w->port_output = true;
|
||||||
else
|
else
|
||||||
w->port_input = true;
|
w->port_input = true;
|
||||||
|
@ -943,7 +943,8 @@ struct TechmapPass : public Pass {
|
||||||
log(" instead of inlining them.\n");
|
log(" instead of inlining them.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -max_iter <number>\n");
|
log(" -max_iter <number>\n");
|
||||||
log(" only run the specified number of iterations.\n");
|
log(" only run the specified number of iterations on each module.\n");
|
||||||
|
log(" default: unlimited\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -recursive\n");
|
log(" -recursive\n");
|
||||||
log(" instead of the iterative breadth-first algorithm use a recursive\n");
|
log(" instead of the iterative breadth-first algorithm use a recursive\n");
|
||||||
|
@ -1157,15 +1158,16 @@ struct TechmapPass : public Pass {
|
||||||
RTLIL::Module *module = *worker.module_queue.begin();
|
RTLIL::Module *module = *worker.module_queue.begin();
|
||||||
worker.module_queue.erase(module);
|
worker.module_queue.erase(module);
|
||||||
|
|
||||||
|
int module_max_iter = max_iter;
|
||||||
bool did_something = true;
|
bool did_something = true;
|
||||||
std::set<RTLIL::Cell*> handled_cells;
|
std::set<RTLIL::Cell*> handled_cells;
|
||||||
while (did_something) {
|
while (did_something) {
|
||||||
did_something = false;
|
did_something = false;
|
||||||
if (worker.techmap_module(design, module, map, handled_cells, celltypeMap, false))
|
if (worker.techmap_module(design, module, map, handled_cells, celltypeMap, false))
|
||||||
did_something = true;
|
did_something = true;
|
||||||
if (did_something)
|
if (did_something)
|
||||||
module->check();
|
module->check();
|
||||||
if (max_iter > 0 && --max_iter == 0)
|
if (module_max_iter > 0 && --module_max_iter == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,37 +64,37 @@ struct TribufWorker {
|
||||||
for (auto cell : module->selected_cells())
|
for (auto cell : module->selected_cells())
|
||||||
{
|
{
|
||||||
if (cell->type == ID($tribuf))
|
if (cell->type == ID($tribuf))
|
||||||
tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
|
tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
|
||||||
|
|
||||||
if (cell->type == ID($_TBUF_))
|
if (cell->type == ID($_TBUF_))
|
||||||
tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
|
tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
|
||||||
|
|
||||||
if (cell->type.in(ID($mux), ID($_MUX_)))
|
if (cell->type.in(ID($mux), ID($_MUX_)))
|
||||||
{
|
{
|
||||||
IdString en_port = cell->type == ID($mux) ? ID(EN) : ID(E);
|
IdString en_port = cell->type == ID($mux) ? ID(EN) : ID(E);
|
||||||
IdString tri_type = cell->type == ID($mux) ? ID($tribuf) : ID($_TBUF_);
|
IdString tri_type = cell->type == ID($mux) ? ID($tribuf) : ID($_TBUF_);
|
||||||
|
|
||||||
if (is_all_z(cell->getPort(ID(A))) && is_all_z(cell->getPort(ID(B)))) {
|
if (is_all_z(cell->getPort(ID::A)) && is_all_z(cell->getPort(ID::B))) {
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_all_z(cell->getPort(ID(A)))) {
|
if (is_all_z(cell->getPort(ID::A))) {
|
||||||
cell->setPort(ID(A), cell->getPort(ID(B)));
|
cell->setPort(ID::A, cell->getPort(ID::B));
|
||||||
cell->setPort(en_port, cell->getPort(ID(S)));
|
cell->setPort(en_port, cell->getPort(ID(S)));
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
cell->unsetPort(ID(S));
|
cell->unsetPort(ID(S));
|
||||||
cell->type = tri_type;
|
cell->type = tri_type;
|
||||||
tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
|
tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_all_z(cell->getPort(ID(B)))) {
|
if (is_all_z(cell->getPort(ID::B))) {
|
||||||
cell->setPort(en_port, module->Not(NEW_ID, cell->getPort(ID(S))));
|
cell->setPort(en_port, module->Not(NEW_ID, cell->getPort(ID(S))));
|
||||||
cell->unsetPort(ID(B));
|
cell->unsetPort(ID::B);
|
||||||
cell->unsetPort(ID(S));
|
cell->unsetPort(ID(S));
|
||||||
cell->type = tri_type;
|
cell->type = tri_type;
|
||||||
tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
|
tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ struct TribufWorker {
|
||||||
pmux_s.append(cell->getPort(ID(EN)));
|
pmux_s.append(cell->getPort(ID(EN)));
|
||||||
else
|
else
|
||||||
pmux_s.append(cell->getPort(ID(E)));
|
pmux_s.append(cell->getPort(ID(E)));
|
||||||
pmux_b.append(cell->getPort(ID(A)));
|
pmux_b.append(cell->getPort(ID::A));
|
||||||
module->remove(cell);
|
module->remove(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ struct SynthPass : public ScriptPass
|
||||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||||
|
|
||||||
if (abc == "abc9" && !lut)
|
if (abc == "abc9" && !lut)
|
||||||
log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)");
|
log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)\n");
|
||||||
|
|
||||||
log_header(design, "Executing SYNTH pass.\n");
|
log_header(design, "Executing SYNTH pass.\n");
|
||||||
log_push();
|
log_push();
|
||||||
|
|
|
@ -15,10 +15,13 @@ module L6MUX21 (input D0, D1, SD, output Z);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
(* abc_box_id=1, abc_carry="CIN,COUT", lib_whitebox *)
|
(* abc_box_id=1, lib_whitebox *)
|
||||||
module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
|
module CCU2C(
|
||||||
output S0, S1, COUT);
|
(* abc_carry *) input CIN,
|
||||||
|
input A0, B0, C0, D0, A1, B1, C1, D1,
|
||||||
|
output S0, S1,
|
||||||
|
(* 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;
|
||||||
parameter INJECT1_0 = "YES";
|
parameter INJECT1_0 = "YES";
|
||||||
|
@ -104,12 +107,13 @@ module PFUMX (input ALUT, BLUT, C0, output Z);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
//(* abc_box_id=2, abc_scc_break="DI,WAD,WRE" *)
|
//(* abc_box_id=2 *)
|
||||||
module TRELLIS_DPR16X4 (
|
module TRELLIS_DPR16X4 (
|
||||||
input [3:0] DI,
|
(* abc_scc_break *) input [3:0] DI,
|
||||||
input [3:0] WAD,
|
(* abc_scc_break *) input [3:0] WAD,
|
||||||
input WRE, WCK,
|
(* abc_scc_break *) input WRE,
|
||||||
input [3:0] RAD,
|
input WCK,
|
||||||
|
input [3:0] RAD,
|
||||||
output [3:0] DO
|
output [3:0] DO
|
||||||
);
|
);
|
||||||
parameter WCKMUX = "WCK";
|
parameter WCKMUX = "WCK";
|
||||||
|
|
|
@ -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
|
|
@ -4,7 +4,6 @@ OBJS += techlibs/ice40/ice40_braminit.o
|
||||||
OBJS += techlibs/ice40/ice40_ffssr.o
|
OBJS += techlibs/ice40/ice40_ffssr.o
|
||||||
OBJS += techlibs/ice40/ice40_ffinit.o
|
OBJS += techlibs/ice40/ice40_ffinit.o
|
||||||
OBJS += techlibs/ice40/ice40_opt.o
|
OBJS += techlibs/ice40/ice40_opt.o
|
||||||
OBJS += techlibs/ice40/ice40_unlut.o
|
|
||||||
|
|
||||||
GENFILES += techlibs/ice40/brams_init1.vh
|
GENFILES += techlibs/ice40/brams_init1.vh
|
||||||
GENFILES += techlibs/ice40/brams_init2.vh
|
GENFILES += techlibs/ice40/brams_init2.vh
|
||||||
|
|
|
@ -44,35 +44,21 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
||||||
`ifdef _ABC
|
\$__ICE40_CARRY_WRAPPER #(
|
||||||
\$__ICE40_FULL_ADDER carry (
|
// A[0]: 1010 1010 1010 1010
|
||||||
|
// A[1]: 1100 1100 1100 1100
|
||||||
|
// A[2]: 1111 0000 1111 0000
|
||||||
|
// A[3]: 1111 1111 0000 0000
|
||||||
|
.LUT(16'b 0110_1001_1001_0110)
|
||||||
|
) fadd (
|
||||||
.A(AA[i]),
|
.A(AA[i]),
|
||||||
.B(BB[i]),
|
.B(BB[i]),
|
||||||
.CI(C[i]),
|
.CI(C[i]),
|
||||||
|
.I0(1'b0),
|
||||||
|
.I3(C[i]),
|
||||||
.CO(CO[i]),
|
.CO(CO[i]),
|
||||||
.O(Y[i])
|
.O(Y[i])
|
||||||
);
|
);
|
||||||
`else
|
|
||||||
SB_CARRY carry (
|
|
||||||
.I0(AA[i]),
|
|
||||||
.I1(BB[i]),
|
|
||||||
.CI(C[i]),
|
|
||||||
.CO(CO[i])
|
|
||||||
);
|
|
||||||
SB_LUT4 #(
|
|
||||||
// I0: 1010 1010 1010 1010
|
|
||||||
// I1: 1100 1100 1100 1100
|
|
||||||
// I2: 1111 0000 1111 0000
|
|
||||||
// I3: 1111 1111 0000 0000
|
|
||||||
.LUT_INIT(16'b 0110_1001_1001_0110)
|
|
||||||
) adder (
|
|
||||||
.I0(1'b0),
|
|
||||||
.I1(AA[i]),
|
|
||||||
.I2(BB[i]),
|
|
||||||
.I3(C[i]),
|
|
||||||
.O(Y[i])
|
|
||||||
);
|
|
||||||
`endif
|
|
||||||
end endgenerate
|
end endgenerate
|
||||||
|
|
||||||
assign X = AA ^ BB;
|
assign X = AA ^ BB;
|
||||||
|
|
|
@ -62,26 +62,21 @@ module \$lut (A, Y);
|
||||||
endmodule
|
endmodule
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef _ABC
|
`ifndef NO_ADDER
|
||||||
module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
|
module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3);
|
||||||
|
parameter LUT = 0;
|
||||||
SB_CARRY carry (
|
SB_CARRY carry (
|
||||||
.I0(A),
|
.I0(A),
|
||||||
.I1(B),
|
.I1(B),
|
||||||
.CI(CI),
|
.CI(CI),
|
||||||
.CO(CO)
|
.CO(CO)
|
||||||
);
|
);
|
||||||
SB_LUT4 #(
|
\$lut #(
|
||||||
// I0: 1010 1010 1010 1010
|
.WIDTH(4),
|
||||||
// I1: 1100 1100 1100 1100
|
.LUT(LUT)
|
||||||
// I2: 1111 0000 1111 0000
|
) lut (
|
||||||
// I3: 1111 1111 0000 0000
|
.A({I0,A,B,I3}),
|
||||||
.LUT_INIT(16'b 0110_1001_1001_0110)
|
.Y(O)
|
||||||
) adder (
|
|
||||||
.I0(1'b0),
|
|
||||||
.I1(A),
|
|
||||||
.I2(B),
|
|
||||||
.I3(CI),
|
|
||||||
.O(O)
|
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
||||||
`endif
|
`endif
|
||||||
|
|
|
@ -141,8 +141,14 @@ module SB_CARRY (output CO, input I0, I1, CI);
|
||||||
assign CO = (I0 && I1) || ((I0 || I1) && CI);
|
assign CO = (I0 && I1) || ((I0 || I1) && CI);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *)
|
(* abc_box_id = 1, lib_whitebox *)
|
||||||
module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
|
module \$__ICE40_FULL_ADDER (
|
||||||
|
(* abc_carry *) output CO,
|
||||||
|
output O,
|
||||||
|
input A,
|
||||||
|
input B,
|
||||||
|
(* abc_carry *) input CI
|
||||||
|
);
|
||||||
SB_CARRY carry (
|
SB_CARRY carry (
|
||||||
.I0(A),
|
.I0(A),
|
||||||
.I1(B),
|
.I1(B),
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
* yosys -- Yosys Open SYnthesis Suite
|
|
||||||
*
|
|
||||||
* 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"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.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 run_ice40_unlut(Module *module)
|
|
||||||
{
|
|
||||||
SigMap sigmap(module);
|
|
||||||
|
|
||||||
for (auto cell : module->selected_cells())
|
|
||||||
{
|
|
||||||
if (cell->type == "\\SB_LUT4")
|
|
||||||
{
|
|
||||||
SigSpec inbits;
|
|
||||||
|
|
||||||
inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
|
|
||||||
inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
|
|
||||||
inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
|
|
||||||
inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
|
|
||||||
sigmap.apply(inbits);
|
|
||||||
|
|
||||||
log("Mapping SB_LUT4 cell %s.%s to $lut.\n", log_id(module), log_id(cell));
|
|
||||||
|
|
||||||
cell->type ="$lut";
|
|
||||||
cell->setParam("\\WIDTH", 4);
|
|
||||||
cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
|
|
||||||
cell->unsetParam("\\LUT_INIT");
|
|
||||||
|
|
||||||
cell->setPort("\\A", SigSpec({
|
|
||||||
get_bit_or_zero(cell->getPort("\\I0")),
|
|
||||||
get_bit_or_zero(cell->getPort("\\I1")),
|
|
||||||
get_bit_or_zero(cell->getPort("\\I2")),
|
|
||||||
get_bit_or_zero(cell->getPort("\\I3"))
|
|
||||||
}));
|
|
||||||
cell->setPort("\\Y", cell->getPort("\\O")[0]);
|
|
||||||
cell->unsetPort("\\I0");
|
|
||||||
cell->unsetPort("\\I1");
|
|
||||||
cell->unsetPort("\\I2");
|
|
||||||
cell->unsetPort("\\I3");
|
|
||||||
cell->unsetPort("\\O");
|
|
||||||
|
|
||||||
cell->check();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Ice40UnlutPass : public Pass {
|
|
||||||
Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: transform SB_LUT4 cells to $lut cells") { }
|
|
||||||
void help() YS_OVERRIDE
|
|
||||||
{
|
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
|
||||||
log("\n");
|
|
||||||
log(" ice40_unlut [options] [selection]\n");
|
|
||||||
log("\n");
|
|
||||||
log("This command transforms all SB_LUT4 cells to generic $lut cells.\n");
|
|
||||||
log("\n");
|
|
||||||
}
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
|
||||||
{
|
|
||||||
log_header(design, "Executing ICE40_UNLUT pass (convert SB_LUT4 to $lut).\n");
|
|
||||||
log_push();
|
|
||||||
|
|
||||||
size_t argidx;
|
|
||||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
|
||||||
// if (args[argidx] == "-???") {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
extra_args(args, argidx, design);
|
|
||||||
|
|
||||||
for (auto module : design->selected_modules())
|
|
||||||
run_ice40_unlut(module);
|
|
||||||
}
|
|
||||||
} Ice40UnlutPass;
|
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_END
|
|
|
@ -238,7 +238,7 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
{
|
{
|
||||||
if (check_label("begin"))
|
if (check_label("begin"))
|
||||||
{
|
{
|
||||||
run("read_verilog -icells -lib -D_ABC +/ice40/cells_sim.v");
|
run("read_verilog -icells -lib +/ice40/cells_sim.v");
|
||||||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||||
run("proc");
|
run("proc");
|
||||||
}
|
}
|
||||||
|
@ -293,8 +293,10 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
{
|
{
|
||||||
if (nocarry)
|
if (nocarry)
|
||||||
run("techmap");
|
run("techmap");
|
||||||
else
|
else {
|
||||||
run("techmap -map +/techmap.v -map +/ice40/arith_map.v" + std::string(abc == "abc9" ? " -D _ABC" : ""));
|
run("ice40_wrapcarry");
|
||||||
|
run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
|
||||||
|
}
|
||||||
if (retime || help_mode)
|
if (retime || help_mode)
|
||||||
run(abc + " -dff", "(only if -retime)");
|
run(abc + " -dff", "(only if -retime)");
|
||||||
run("ice40_opt");
|
run("ice40_opt");
|
||||||
|
@ -309,7 +311,7 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
run("opt_merge");
|
run("opt_merge");
|
||||||
run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
|
run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
|
||||||
}
|
}
|
||||||
run("techmap -D NO_LUT -map +/ice40/cells_map.v");
|
run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v");
|
||||||
run("opt_expr -mux_undef");
|
run("opt_expr -mux_undef");
|
||||||
run("simplemap");
|
run("simplemap");
|
||||||
run("ice40_ffinit");
|
run("ice40_ffinit");
|
||||||
|
@ -338,13 +340,12 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
else
|
else
|
||||||
wire_delay = 250;
|
wire_delay = 250;
|
||||||
run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
|
run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
|
||||||
run("techmap -D NO_LUT -D _ABC -map +/ice40/cells_map.v");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
run(abc + " -dress -lut 4", "(skip if -noabc)");
|
run(abc + " -dress -lut 4", "(skip if -noabc)");
|
||||||
}
|
}
|
||||||
|
run("techmap -D NO_LUT -map +/ice40/cells_map.v");
|
||||||
run("clean");
|
run("clean");
|
||||||
run("ice40_unlut");
|
|
||||||
run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
|
run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
read_verilog test_arith.v
|
read_verilog test_arith.v
|
||||||
synth_ice40
|
synth_ice40
|
||||||
techmap -map ../cells_sim.v
|
|
||||||
rename test gate
|
rename test gate
|
||||||
|
|
||||||
read_verilog test_arith.v
|
read_verilog test_arith.v
|
||||||
|
@ -8,3 +7,11 @@ rename test gold
|
||||||
|
|
||||||
miter -equiv -flatten -make_outputs gold gate miter
|
miter -equiv -flatten -make_outputs gold gate miter
|
||||||
sat -verify -prove trigger 0 -show-ports miter
|
sat -verify -prove trigger 0 -show-ports miter
|
||||||
|
|
||||||
|
synth_ice40 -top gate
|
||||||
|
|
||||||
|
read_verilog test_arith.v
|
||||||
|
rename test gold
|
||||||
|
|
||||||
|
miter -equiv -flatten -make_outputs gold gate miter
|
||||||
|
sat -verify -prove trigger 0 -show-ports miter
|
||||||
|
|
|
@ -5,20 +5,10 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/m9k_bb.v))
|
||||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/altpll_bb.v))
|
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/altpll_bb.v))
|
||||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.txt))
|
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.txt))
|
||||||
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v))
|
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v))
|
||||||
$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_sim.v))
|
|
||||||
$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/cells_sim.v))
|
# Add the cell models and mappings for the VQM backend
|
||||||
$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_sim.v))
|
families := max10 a10gx cyclonev cyclone10 cycloneiv cycloneive
|
||||||
$(eval $(call add_share_file,share/intel/cyclone10,techlibs/intel/cyclone10/cells_sim.v))
|
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))
|
||||||
$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/cells_sim.v))
|
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v)))
|
||||||
$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/cells_sim.v))
|
|
||||||
$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_map.v))
|
|
||||||
$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/cells_map.v))
|
|
||||||
$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_map.v))
|
|
||||||
$(eval $(call add_share_file,share/intel/cyclone10,techlibs/intel/cyclone10/cells_map.v))
|
|
||||||
$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/cells_map.v))
|
|
||||||
$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/cells_map.v))
|
|
||||||
#$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/arith_map.v))
|
|
||||||
#$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/arith_map.v))
|
|
||||||
#$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/arith_map.v))
|
|
||||||
#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
|
#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_bb.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams.txt))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams.txt))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_map.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_map.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_bb.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_bb.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams.txt))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams_map.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
|
||||||
|
|
|
@ -196,8 +196,14 @@ module XORCY(output O, input CI, LI);
|
||||||
assign O = CI ^ LI;
|
assign O = CI ^ LI;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* abc_box_id = 4, abc_carry="CI,CO", lib_whitebox *)
|
(* abc_box_id = 4, lib_whitebox *)
|
||||||
module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
|
module CARRY4(
|
||||||
|
(* abc_carry *) output [3:0] CO,
|
||||||
|
output [3:0] O,
|
||||||
|
(* abc_carry *) input CI,
|
||||||
|
input CYINIT,
|
||||||
|
input [3:0] DI, S
|
||||||
|
);
|
||||||
assign O = S ^ {CO[2:0], CI | CYINIT};
|
assign O = S ^ {CO[2:0], CI | CYINIT};
|
||||||
assign CO[0] = S[0] ? CI | CYINIT : DI[0];
|
assign CO[0] = S[0] ? CI | CYINIT : DI[0];
|
||||||
assign CO[1] = S[1] ? CO[0] : DI[1];
|
assign CO[1] = S[1] ? CO[0] : DI[1];
|
||||||
|
@ -304,12 +310,12 @@ module FDPE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
|
||||||
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
|
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* abc_box_id = 5, abc_scc_break="D,WE" *)
|
(* abc_box_id = 5 *)
|
||||||
module RAM32X1D (
|
module RAM32X1D (
|
||||||
output DPO, SPO,
|
output DPO, SPO,
|
||||||
(* clkbuf_sink *)
|
(* abc_scc_break *) input D,
|
||||||
input WCLK,
|
(* clkbuf_sink *) input WCLK,
|
||||||
input D, WE,
|
(* abc_scc_break *) input WE,
|
||||||
input A0, A1, A2, A3, A4,
|
input A0, A1, A2, A3, A4,
|
||||||
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
|
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
|
||||||
);
|
);
|
||||||
|
@ -324,12 +330,12 @@ module RAM32X1D (
|
||||||
always @(posedge clk) if (WE) mem[a] <= D;
|
always @(posedge clk) if (WE) mem[a] <= D;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* abc_box_id = 6, abc_scc_break="D,WE" *)
|
(* abc_box_id = 6 *)
|
||||||
module RAM64X1D (
|
module RAM64X1D (
|
||||||
output DPO, SPO,
|
output DPO, SPO,
|
||||||
(* clkbuf_sink *)
|
(* abc_scc_break *) input D,
|
||||||
input WCLK,
|
(* clkbuf_sink *) input WCLK,
|
||||||
input D, WE,
|
(* abc_scc_break *) input WE,
|
||||||
input A0, A1, A2, A3, A4, A5,
|
input A0, A1, A2, A3, A4, A5,
|
||||||
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
|
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
|
||||||
);
|
);
|
||||||
|
@ -344,12 +350,12 @@ module RAM64X1D (
|
||||||
always @(posedge clk) if (WE) mem[a] <= D;
|
always @(posedge clk) if (WE) mem[a] <= D;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
(* abc_box_id = 7, abc_scc_break="D,WE" *)
|
(* abc_box_id = 7 *)
|
||||||
module RAM128X1D (
|
module RAM128X1D (
|
||||||
output DPO, SPO,
|
output DPO, SPO,
|
||||||
input D, WE,
|
(* abc_scc_break *) input D,
|
||||||
(* clkbuf_sink *)
|
(* clkbuf_sink *) input WCLK,
|
||||||
input WCLK,
|
(* abc_scc_break *) input WE,
|
||||||
input [6:0] A, DPRA
|
input [6:0] A, DPRA
|
||||||
);
|
);
|
||||||
parameter INIT = 128'h0;
|
parameter INIT = 128'h0;
|
||||||
|
|
|
@ -67,13 +67,13 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
log(" generate an output netlist suitable for ISE (enables -iopad)\n");
|
log(" generate an output netlist suitable for ISE (enables -iopad)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nobram\n");
|
log(" -nobram\n");
|
||||||
log(" disable inference of block rams\n");
|
log(" do not use block RAM cells in output netlist\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nodram\n");
|
log(" -nolutram\n");
|
||||||
log(" disable inference of distributed rams\n");
|
log(" do not use distributed RAM cells in output netlist\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nosrl\n");
|
log(" -nosrl\n");
|
||||||
log(" disable inference of shift registers\n");
|
log(" do not use distributed SRL cells in output netlist\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nocarry\n");
|
log(" -nocarry\n");
|
||||||
log(" do not use XORCY/MUXCY/CARRY4 cells in output netlist\n");
|
log(" do not use XORCY/MUXCY/CARRY4 cells in output netlist\n");
|
||||||
|
@ -116,7 +116,7 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string top_opt, edif_file, blif_file, family;
|
std::string top_opt, edif_file, blif_file, family;
|
||||||
bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nodram, nosrl, nocarry, nowidelut, abc9;
|
bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, abc9;
|
||||||
int widemux;
|
int widemux;
|
||||||
|
|
||||||
void clear_flags() YS_OVERRIDE
|
void clear_flags() YS_OVERRIDE
|
||||||
|
@ -134,7 +134,7 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
noclkbuf = false;
|
noclkbuf = false;
|
||||||
nocarry = false;
|
nocarry = false;
|
||||||
nobram = false;
|
nobram = false;
|
||||||
nodram = false;
|
nolutram = false;
|
||||||
nosrl = false;
|
nosrl = false;
|
||||||
nocarry = false;
|
nocarry = false;
|
||||||
nowidelut = false;
|
nowidelut = false;
|
||||||
|
@ -218,8 +218,8 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
nobram = true;
|
nobram = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-nodram") {
|
if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
|
||||||
nodram = true;
|
nolutram = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-nosrl") {
|
if (args[argidx] == "-nosrl") {
|
||||||
|
@ -316,7 +316,7 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
run("opt_clean");
|
run("opt_clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("bram", "(skip if '-nobram')")) {
|
if (check_label("map_bram", "(skip if '-nobram')")) {
|
||||||
if (help_mode) {
|
if (help_mode) {
|
||||||
run("memory_bram -rules +/xilinx/{family}_brams.txt");
|
run("memory_bram -rules +/xilinx/{family}_brams.txt");
|
||||||
run("techmap -map +/xilinx/{family}_brams_map.v");
|
run("techmap -map +/xilinx/{family}_brams_map.v");
|
||||||
|
@ -333,20 +333,23 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("dram", "(skip if '-nodram')")) {
|
if (check_label("map_lutram", "(skip if '-nolutram')")) {
|
||||||
if (!nodram || help_mode) {
|
if (!nolutram || help_mode) {
|
||||||
run("memory_bram -rules +/xilinx/drams.txt");
|
run("memory_bram -rules +/xilinx/lutrams.txt");
|
||||||
run("techmap -map +/xilinx/drams_map.v");
|
run("techmap -map +/xilinx/lutrams_map.v");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("fine")) {
|
if (check_label("map_ffram")) {
|
||||||
if (widemux > 0)
|
if (widemux > 0)
|
||||||
run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover
|
run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover
|
||||||
// performs less efficiently
|
// performs less efficiently
|
||||||
else
|
else
|
||||||
run("opt -fast -full");
|
run("opt -fast -full");
|
||||||
run("memory_map");
|
run("memory_map");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("fine")) {
|
||||||
run("dffsr2dff");
|
run("dffsr2dff");
|
||||||
run("dff2dffe");
|
run("dff2dffe");
|
||||||
if (help_mode) {
|
if (help_mode) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
OPTIND=1
|
OPTIND=1
|
||||||
count=100
|
count=50
|
||||||
seed="" # default to no seed specified
|
seed="" # default to no seed specified
|
||||||
while getopts "c:S:" opt
|
while getopts "c:S:" opt
|
||||||
do
|
do
|
||||||
|
|
|
@ -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
|
|
@ -1,21 +0,0 @@
|
||||||
module top(
|
|
||||||
input clk,
|
|
||||||
input rst,
|
|
||||||
input [2:0] a,
|
|
||||||
output [1:0] b
|
|
||||||
);
|
|
||||||
reg [2:0] b_reg;
|
|
||||||
initial begin
|
|
||||||
b_reg <= 3'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
assign b = b_reg[1:0];
|
|
||||||
always @(posedge clk or posedge rst) begin
|
|
||||||
if(rst) begin
|
|
||||||
b_reg <= 3'b0;
|
|
||||||
end else begin
|
|
||||||
b_reg <= a;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue