Merge remote-tracking branch 'origin/master' into mwk/xilinx_bufgmap

This commit is contained in:
Eddie Hung 2019-08-23 10:00:50 -07:00
commit 6872805a3e
146 changed files with 4377 additions and 1490 deletions

View File

@ -6,3 +6,4 @@ brew "git"
brew "graphviz" brew "graphviz"
brew "pkg-config" brew "pkg-config"
brew "python3" brew "python3"
brew "tcl-tk"

View File

@ -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
-------------------------- --------------------------

View File

@ -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

View File

@ -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 ""

View File

@ -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
============================================================== ==============================================================

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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)) { }
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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));

View File

@ -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);

View File

@ -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
{ {

View File

@ -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

View File

@ -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));

View File

@ -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)]);

View File

@ -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;
} }

View File

@ -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");

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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;
} }

View File

@ -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);

View File

@ -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())

View File

@ -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 {

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;
} }

649
passes/opt/opt_share.cc Normal file
View File

@ -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

View File

@ -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)
{ {

View File

@ -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)

View File

@ -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));
} }
} }

View File

@ -1,2 +1 @@
/ice40_dsp_pm.h /*_pm.h
/peepopt_pm.h

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

330
passes/pmgen/test_pmgen.cc Normal file
View File

@ -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

106
passes/pmgen/test_pmgen.pmg Normal file
View File

@ -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

View File

@ -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();

View File

@ -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;
} }

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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)

View File

@ -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");

View File

@ -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),

View File

@ -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);

View File

@ -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));

View File

@ -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)) {

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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());
} }
} }

View File

@ -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;
} }

View File

@ -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())

View File

@ -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);
} }
} }

View File

@ -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;

View File

@ -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));
} }

View File

@ -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;
} }
} }

View File

@ -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);
} }

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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]})
); );
wire cout;
AL_MAP_ADDER #(
.ALUTYPE("ADD"))
adder_cout (
.a(1'b0),
.b(1'b0),
.c(COx[i]),
.o({cout, CO[i]})
);
end: slice end: slice
endgenerate endgenerate
/* End implementation */
AL_MAP_ADDER #( /* End implementation */
.ALUTYPE("ADD")) assign X = AA ^ BB;
adder_cout (
.c(C[Y_WIDTH+1]),
.o(COx[Y_WIDTH+1])
);
assign CO = COx[Y_WIDTH+1];
assign X = AA ^ BB;
endmodule endmodule

View File

@ -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");
} }

View File

@ -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();

View File

@ -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";

View File

@ -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))

View File

@ -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

32
techlibs/efinix/bram.txt Normal file
View File

@ -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

View File

@ -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

View File

@ -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

107
techlibs/efinix/cells_sim.v Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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");
} }

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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