3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-19 04:13:39 +00:00

Merge branch 'master' into xc7dsp

This commit is contained in:
David Shah 2019-08-30 13:57:15 +01:00
commit 6919c0f9b0
190 changed files with 8815 additions and 4357 deletions

View file

@ -40,35 +40,6 @@ matrix:
env: env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8" - MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
# Latest gcc-6 on Travis Linux
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
- gperf
- build-essential
- bison
- flex
- libreadline-dev
- gawk
- tcl-dev
- libffi-dev
- git
- graphviz
- xdot
- pkg-config
- python
- python3
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
- zlib1g-dev
env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6"
# Latest gcc supported on Travis Linux # Latest gcc supported on Travis Linux
- os: linux - os: linux
addons: addons:
@ -76,7 +47,7 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- g++-7 - g++-9
- gperf - gperf
- build-essential - build-essential
- bison - bison
@ -96,7 +67,7 @@ matrix:
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev - zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7" - MATRIX_EVAL="CONFIG=gcc && CC=gcc-9 && CXX=g++-9"
# Clang which ships on Trusty Linux # Clang which ships on Trusty Linux
- os: linux - os: linux
@ -133,9 +104,9 @@ matrix:
addons: addons:
apt: apt:
sources: sources:
- llvm-toolchain-trusty-5.0 - llvm-toolchain-xenial-8
packages: packages:
- clang-5.0 - clang-8
- gperf - gperf
- build-essential - build-essential
- bison - bison
@ -155,7 +126,7 @@ matrix:
- libboost-filesystem-dev - libboost-filesystem-dev
- zlib1g-dev - zlib1g-dev
env: env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0" - MATRIX_EVAL="CONFIG=clang && CC=clang-8 && CXX=clang++-8"
# # Latest clang on Mac OS X # # Latest clang on Mac OS X
# - os: osx # - os: osx

View file

@ -51,7 +51,7 @@ fi
git clone git://github.com/steveicarus/iverilog.git git clone git://github.com/steveicarus/iverilog.git
cd iverilog cd iverilog
autoconf autoconf
./configure --prefix=$HOME/.local-bin CC=gcc CXX=g++ ./configure --prefix=$HOME/.local-bin
make make
make install make install
echo echo

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"

131
CHANGELOG
View file

@ -12,40 +12,149 @@ Yosys 0.9 .. Yosys 0.9-dev
- Added "synth_xilinx -abc9" (experimental) - Added "synth_xilinx -abc9" (experimental)
- Added "synth_ice40 -abc9" (experimental) - Added "synth_ice40 -abc9" (experimental)
- Added "synth -abc9" (experimental) - Added "synth -abc9" (experimental)
- Added "script -scriptwire - Added "script -scriptwire"
- Added "synth_xilinx -nocarry"
- Added "synth_xilinx -nowidelut"
- Added "synth_ecp5 -nowidelut"
- "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
- Improve attribute and parameter encoding in JSON to avoid ambiguities between - Improve attribute and parameter encoding in JSON to avoid ambiguities between
bit vectors and strings containing [01xz]* bit vectors and strings containing [01xz]*
- Added "clkbufmap" pass
- Added "synth_xilinx -family xc6s" for Spartan 6 support (experimental)
- Added "synth_xilinx -ise" (experimental)
- Added "synth_xilinx -iopad"
- "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"
- Improvements in pmgen: slices, choices, define, generate
Yosys 0.8 .. Yosys 0.8-dev Yosys 0.8 .. Yosys 0.9
-------------------------- ----------------------
* Various * Various
- Added $changed support to read_verilog - Many bugfixes and small improvements
- Added support for SystemVerilog interfaces and modports
- Added "write_edif -attrprop" - Added "write_edif -attrprop"
- Added "ice40_unlut" pass
- Added "opt_lut" pass - Added "opt_lut" pass
- Added "synth_ice40 -relut"
- Added "synth_ice40 -noabc"
- Added "gate2lut.v" techmap rule - Added "gate2lut.v" techmap rule
- Added "rename -src" - Added "rename -src"
- Added "equiv_opt" pass - Added "equiv_opt" pass
- Added "shregmap -tech xilinx" - Added "flowmap" LUT mapping pass
- Added "rename -wire" to rename cells based on the wires they drive
- Added "bugpoint" for creating minimised testcases
- Added "write_edif -gndvccy"
- "write_verilog" to escape Verilog keywords
- Fixed sign handling of real constants
- "write_verilog" to write initial statement for initial flop state
- Added pmgen pattern matcher generator
- Fixed opt_rmdff handling of $_DFFSR_???_ and $_DLATCHSR_???_
- Added "setundef -params" to replace undefined cell parameters
- Renamed "yosys -D" to "yosys -U", added "yosys -D" to set Verilog defines
- Fixed handling of defparam when default_nettype is none
- Fixed "wreduce" flipflop handling
- Fixed FIRRTL to Verilog process instance subfield assignment
- Added "write_verilog -siminit"
- Several fixes and improvements for mem2reg memories
- Fixed handling of task output ports in clocked always blocks
- Improved handling of and-with-1 and or-with-0 in "opt_expr"
- Added "read_aiger" frontend - Added "read_aiger" frontend
- Added "mutate" pass
- Added "hdlname" attribute
- Added "rename -output"
- Added "read_ilang -lib"
- Improved "proc" full_case detection and handling
- Added "whitebox" and "lib_whitebox" attributes
- Added "read_verilog -nowb", "flatten -wb" and "wbflip"
- Added Python bindings and support for Python plug-ins
- Added "pmux2shiftx"
- Added log_debug framework for reduced default verbosity
- Improved "opt_expr" and "opt_clean" handling of (partially) undriven and/or unused wires
- Added "peepopt" peephole optimisation pass using pmgen
- Added approximate support for SystemVerilog "var" keyword
- Added parsing of "specify" blocks into $specrule and $specify[23]
- Added support for attributes on parameters and localparams
- Added support for parsing attributes on port connections
- Added "wreduce -keepdc"
- Added support for optimising $dffe and $_DFFE_* cells in "opt_rmdff"
- Added Verilog wand/wor wire type support
- Added support for elaboration system tasks
- Added "muxcover -mux{4,8,16}=<cost>" - Added "muxcover -mux{4,8,16}=<cost>"
- Added "muxcover -dmux=<cost>" - Added "muxcover -dmux=<cost>"
- Added "muxcover -nopartial" - Added "muxcover -nopartial"
- Added "muxpack" pass - Added "muxpack" pass
- Added "pmux2shiftx -norange" - Added "pmux2shiftx -norange"
- Added support for "~" in filename parsing
- Added "read_verilog -pwires" feature to turn parameters into wires
- Fixed sign extension of unsized constants with 'bx and 'bz MSB
- Fixed genvar to be a signed type
- Added support for attributes on case rules
- Added "upto" and "offset" to JSON frontend and backend
- Several liberty file parser improvements
- Fixed handling of more complex BRAM patterns
- Add "write_aiger -I -O -B"
* Formal Verification
- Added $changed support to read_verilog
- Added "read_verilog -noassert -noassume -assert-assumes"
- Added btor ops for $mul, $div, $mod and $concat
- Added yosys-smtbmc support for btor witnesses
- Added "supercover" pass
- Fixed $global_clock handling vs autowire
- Added $dffsr support to "async2sync"
- Added "fmcombine" pass
- Added memory init support in "write_btor"
- Added "cutpoint" pass
- Changed "ne" to "neq" in btor2 output
- Added support for SVA "final" keyword
- Added "fmcombine -initeq -anyeq"
- Added timescale and generated-by header to yosys-smtbmc vcd output
- Improved BTOR2 handling of undriven wires
* Verific support
- Enabled Verific flags vhdl_support_variable_slice and veri_elaborate_top_level_modules_having_interface_ports
- Improved support for asymmetric memories
- Added "verific -chparam"
- Fixed "verific -extnets" for more complex situations
- Added "read -verific" and "read -noverific"
- Added "hierarchy -chparam"
* New back-ends
- Added initial Anlogic support
- Added initial SmartFusion2 and IGLOO2 support
* ECP5 support
- Added "synth_ecp5 -nowidelut"
- Added BRAM inference support to "synth_ecp5"
- Added support for transforming Diamond IO and flipflop primitives
* iCE40 support
- Added "ice40_unlut" pass
- Added "synth_ice40 -relut"
- Added "synth_ice40 -noabc"
- Added "synth_ice40 -dffe_min_ce_use"
- Added DSP inference support using pmgen
- Added support for initialising BRAM primitives from a file
- Added iCE40 Ultra RGB LED driver cells
* Xilinx support
- Use "write_edif -pvector bra" for Xilinx EDIF files
- Fixes for VPR place and route support with "synth_xilinx"
- Added more cell simulation models
- Added "synth_xilinx -family"
- Added "stat -tech xilinx" to estimate logic cell usage
- Added "synth_xilinx -nocarry" - Added "synth_xilinx -nocarry"
- Added "synth_xilinx -nowidelut" - Added "synth_xilinx -nowidelut"
- Added "synth_ecp5 -nowidelut"
- "synth_xilinx" to now infer hard shift registers (-nosrl to disable) - "synth_xilinx" to now infer hard shift registers (-nosrl to disable)
- Fixed sign extension of unsized constants with 'bx and 'bz MSB - Added support for mapping RAM32X1D
Yosys 0.7 .. Yosys 0.8 Yosys 0.7 .. Yosys 0.8
---------------------- ----------------------

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

@ -390,6 +390,7 @@ Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
Release: Release:
- set YOSYS_VER to x.y.z in Makefile - set YOSYS_VER to x.y.z in Makefile
- remove "bumpversion" target from Makefile
- update version string in CHANGELOG - update version string in CHANGELOG
git commit -am "Yosys x.y.z" git commit -am "Yosys x.y.z"

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)
@ -113,10 +115,13 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt LDLIBS += -lrt
endif endif
YOSYS_VER := 0.8+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 4d4665b.. 2> /dev/null | wc -l; }) YOSYS_VER := 0.9+36
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o OBJS = kernel/version_$(GIT_REV).o
bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 8a4c6e6.. | wc -l`/;" Makefile
# set 'ABCREV = default' to use abc/ as it is # set 'ABCREV = default' to use abc/ as it is
# #
# Note: If you do ABC development, make sure that 'abc' in this directory # Note: If you do ABC development, make sure that 'abc' in this directory
@ -487,6 +492,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 +692,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 +705,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:
@ -329,6 +332,21 @@ Verilog Attributes and non-standard features
that represent module parameters or localparams (when the HDL front-end that represent module parameters or localparams (when the HDL front-end
is run in -pwires mode). is run in -pwires mode).
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
module to mark it as a clock buffer output, and thus prevent ``clkbufmap``
from inserting another clock buffer on a net driven by such output.
- The ``clkbuf_sink`` attribute can be set on an input port of a module to
request clock buffer insertion by the ``clkbufmap`` pass.
- The ``clkbuf_inhibit`` is the default attribute to set on a wire to prevent
automatic clock buffer insertion by ``clkbufmap``. This behaviour can be
overridden by providing a custom selection to ``clkbufmap``.
- The ``iopad_external_pin`` attribute on a blackbox module's port marks
it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
from inserting another pad cell on it.
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports - In addition to the ``(* ... *)`` attribute syntax, Yosys supports
the non-standard ``{* ... *}`` attribute syntax to set default attributes the non-standard ``{* ... *}`` attribute syntax to set default attributes
for everything that comes after the ``{* ... *}`` statement. (Reset for everything that comes after the ``{* ... *}`` statement. (Reset
@ -405,6 +423,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

@ -1,4 +1,3 @@
read_verilog example.v read_verilog example.v
synth_xilinx -top example -family xc6s synth_xilinx -top example -family xc6s -ise
iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I
write_edif -pvector bra example.edif write_edif -pvector bra example.edif

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

@ -78,7 +78,7 @@ failed:
return std::pair<RTLIL::IdString, int>("\\" + name, 0); return std::pair<RTLIL::IdString, int>("\\" + name, 0);
} }
void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode, bool wideports) void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool run_clean, bool sop_mode, bool wideports)
{ {
RTLIL::Module *module = nullptr; RTLIL::Module *module = nullptr;
RTLIL::Const *lutptr = NULL; RTLIL::Const *lutptr = NULL;

View file

@ -24,7 +24,7 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
extern void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, extern void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name,
bool run_clean = false, bool sop_mode = false, bool wideports = false); bool run_clean = false, bool sop_mode = false, bool wideports = false);
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END

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

@ -268,9 +268,9 @@ Aig::Aig(Cell *cell)
cell->parameters.sort(); cell->parameters.sort();
for (auto p : cell->parameters) for (auto p : cell->parameters)
{ {
if (p.first == "\\A_WIDTH" && mkname_a_signed) { if (p.first == ID(A_WIDTH) && mkname_a_signed) {
name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U'); name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
} else if (p.first == "\\B_WIDTH" && mkname_b_signed) { } else if (p.first == ID(B_WIDTH) && mkname_b_signed) {
name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U'); name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
} else { } else {
mkname_last = name; mkname_last = name;
@ -280,183 +280,183 @@ Aig::Aig(Cell *cell)
mkname_a_signed = false; mkname_a_signed = false;
mkname_b_signed = false; mkname_b_signed = false;
mkname_is_signed = false; mkname_is_signed = false;
if (p.first == "\\A_SIGNED") { if (p.first == ID(A_SIGNED)) {
mkname_a_signed = true; mkname_a_signed = true;
mkname_is_signed = p.second.as_bool(); mkname_is_signed = p.second.as_bool();
} }
if (p.first == "\\B_SIGNED") { if (p.first == ID(B_SIGNED)) {
mkname_b_signed = true; mkname_b_signed = true;
mkname_is_signed = p.second.as_bool(); mkname_is_signed = p.second.as_bool();
} }
} }
if (cell->type.in("$not", "$_NOT_", "$pos", "$_BUF_")) if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($_BUF_)))
{ {
for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
int A = mk.inport("\\A", i); int A = mk.inport(ID::A, i);
int Y = cell->type.in("$not", "$_NOT_") ? mk.not_gate(A) : A; int Y = cell->type.in(ID($not), ID($_NOT_)) ? mk.not_gate(A) : A;
mk.outport(Y, "\\Y", i); mk.outport(Y, ID::Y, i);
} }
goto optimize; goto optimize;
} }
if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$xor", "$xnor", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_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("\\Y")); i++) { for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
int A = mk.inport("\\A", i); int A = mk.inport(ID::A, i);
int B = mk.inport("\\B", i); int B = mk.inport(ID::B, i);
int Y = cell->type.in("$and", "$_AND_") ? mk.and_gate(A, B) : int Y = cell->type.in(ID($and), ID($_AND_)) ? mk.and_gate(A, B) :
cell->type.in("$_NAND_") ? mk.nand_gate(A, B) : cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
cell->type.in("$or", "$_OR_") ? mk.or_gate(A, B) : cell->type.in(ID($or), ID($_OR_)) ? mk.or_gate(A, B) :
cell->type.in("$_NOR_") ? mk.nor_gate(A, B) : cell->type.in(ID($_NOR_)) ? mk.nor_gate(A, B) :
cell->type.in("$xor", "$_XOR_") ? mk.xor_gate(A, B) : cell->type.in(ID($xor), ID($_XOR_)) ? mk.xor_gate(A, B) :
cell->type.in("$xnor", "$_XNOR_") ? mk.xnor_gate(A, B) : cell->type.in(ID($xnor), ID($_XNOR_)) ? mk.xnor_gate(A, B) :
cell->type.in("$_ANDNOT_") ? mk.andnot_gate(A, B) : cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
cell->type.in("$_ORNOT_") ? mk.ornot_gate(A, B) : -1; cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
mk.outport(Y, "\\Y", i); mk.outport(Y, ID::Y, i);
} }
goto optimize; goto optimize;
} }
if (cell->type.in("$mux", "$_MUX_")) if (cell->type.in(ID($mux), ID($_MUX_)))
{ {
int S = mk.inport("\\S"); int S = mk.inport(ID(S));
for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
int A = mk.inport("\\A", i); int A = mk.inport(ID::A, i);
int B = mk.inport("\\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 == "$_NMUX_") if (cell->type == ID($_NMUX_))
Y = mk.not_gate(Y); Y = mk.not_gate(Y);
mk.outport(Y, "\\Y", i); mk.outport(Y, ID::Y, i);
} }
goto optimize; goto optimize;
} }
if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$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("\\A", 0); int Y = mk.inport(ID::A, 0);
for (int i = 1; i < GetSize(cell->getPort("\\A")); i++) { for (int i = 1; i < GetSize(cell->getPort(ID::A)); i++) {
int A = mk.inport("\\A", i); int A = mk.inport(ID::A, i);
if (cell->type == "$reduce_and") Y = mk.and_gate(A, Y); if (cell->type == ID($reduce_and)) Y = mk.and_gate(A, Y);
if (cell->type == "$reduce_or") Y = mk.or_gate(A, Y); if (cell->type == ID($reduce_or)) Y = mk.or_gate(A, Y);
if (cell->type == "$reduce_bool") Y = mk.or_gate(A, Y); if (cell->type == ID($reduce_bool)) Y = mk.or_gate(A, Y);
if (cell->type == "$reduce_xor") Y = mk.xor_gate(A, Y); if (cell->type == ID($reduce_xor)) Y = mk.xor_gate(A, Y);
if (cell->type == "$reduce_xnor") Y = mk.xor_gate(A, Y); if (cell->type == ID($reduce_xnor)) Y = mk.xor_gate(A, Y);
} }
if (cell->type == "$reduce_xnor") if (cell->type == ID($reduce_xnor))
Y = mk.not_gate(Y); Y = mk.not_gate(Y);
mk.outport(Y, "\\Y", 0); mk.outport(Y, ID::Y, 0);
for (int i = 1; i < GetSize(cell->getPort("\\Y")); i++) for (int i = 1; i < GetSize(cell->getPort(ID::Y)); i++)
mk.outport(mk.bool_node(false), "\\Y", i); mk.outport(mk.bool_node(false), ID::Y, i);
goto optimize; goto optimize;
} }
if (cell->type.in("$logic_not", "$logic_and", "$logic_or")) if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or)))
{ {
int A = mk.inport("\\A", 0), Y = -1; int A = mk.inport(ID::A, 0), Y = -1;
for (int i = 1; i < GetSize(cell->getPort("\\A")); i++) for (int i = 1; i < GetSize(cell->getPort(ID::A)); i++)
A = mk.or_gate(mk.inport("\\A", i), A); A = mk.or_gate(mk.inport(ID::A, i), A);
if (cell->type.in("$logic_and", "$logic_or")) { if (cell->type.in(ID($logic_and), ID($logic_or))) {
int B = mk.inport("\\B", 0); int B = mk.inport(ID::B, 0);
for (int i = 1; i < GetSize(cell->getPort("\\B")); i++) for (int i = 1; i < GetSize(cell->getPort(ID::B)); i++)
B = mk.or_gate(mk.inport("\\B", i), B); B = mk.or_gate(mk.inport(ID::B, i), B);
if (cell->type == "$logic_and") Y = mk.and_gate(A, B); if (cell->type == ID($logic_and)) Y = mk.and_gate(A, B);
if (cell->type == "$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 == "$logic_not") Y = mk.not_gate(A); if (cell->type == ID($logic_not)) Y = mk.not_gate(A);
} }
mk.outport_bool(Y, "\\Y"); mk.outport_bool(Y, ID::Y);
goto optimize; goto optimize;
} }
if (cell->type.in("$add", "$sub")) if (cell->type.in(ID($add), ID($sub)))
{ {
int width = GetSize(cell->getPort("\\Y")); int width = GetSize(cell->getPort(ID::Y));
vector<int> A = mk.inport_vec("\\A", width); vector<int> A = mk.inport_vec(ID::A, width);
vector<int> B = mk.inport_vec("\\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 == "$sub") { if (cell->type == ID($sub)) {
for (auto &n : B) for (auto &n : B)
n = mk.not_gate(n); n = mk.not_gate(n);
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, "\\Y"); mk.outport_vec(Y, ID::Y);
goto optimize; goto optimize;
} }
if (cell->type == "$alu") if (cell->type == ID($alu))
{ {
int width = GetSize(cell->getPort("\\Y")); int width = GetSize(cell->getPort(ID::Y));
vector<int> A = mk.inport_vec("\\A", width); vector<int> A = mk.inport_vec(ID::A, width);
vector<int> B = mk.inport_vec("\\B", width); vector<int> B = mk.inport_vec(ID::B, width);
int carry = mk.inport("\\CI"); int carry = mk.inport(ID(CI));
int binv = mk.inport("\\BI"); int binv = mk.inport(ID(BI));
for (auto &n : B) for (auto &n : B)
n = mk.xor_gate(n, binv); n = mk.xor_gate(n, binv);
vector<int> X(width), CO(width); vector<int> X(width), CO(width);
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, "\\Y"); mk.outport_vec(Y, ID::Y);
mk.outport_vec(X, "\\X"); mk.outport_vec(X, ID(X));
mk.outport_vec(CO, "\\CO"); mk.outport_vec(CO, ID(CO));
goto optimize; goto optimize;
} }
if (cell->type.in("$eq", "$ne")) if (cell->type.in(ID($eq), ID($ne)))
{ {
int width = max(GetSize(cell->getPort("\\A")), GetSize(cell->getPort("\\B"))); int width = max(GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::B)));
vector<int> A = mk.inport_vec("\\A", width); vector<int> A = mk.inport_vec(ID::A, width);
vector<int> B = mk.inport_vec("\\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 == "$eq") if (cell->type == ID($eq))
Y = mk.not_gate(Y); Y = mk.not_gate(Y);
mk.outport_bool(Y, "\\Y"); mk.outport_bool(Y, ID::Y);
goto optimize; goto optimize;
} }
if (cell->type == "$_AOI3_") if (cell->type == ID($_AOI3_))
{ {
int A = mk.inport("\\A"); int A = mk.inport(ID::A);
int B = mk.inport("\\B"); int B = mk.inport(ID::B);
int C = mk.inport("\\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, "\\Y"); mk.outport(Y, ID::Y);
goto optimize; goto optimize;
} }
if (cell->type == "$_OAI3_") if (cell->type == ID($_OAI3_))
{ {
int A = mk.inport("\\A"); int A = mk.inport(ID::A);
int B = mk.inport("\\B"); int B = mk.inport(ID::B);
int C = mk.inport("\\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, "\\Y"); mk.outport(Y, ID::Y);
goto optimize; goto optimize;
} }
if (cell->type == "$_AOI4_") if (cell->type == ID($_AOI4_))
{ {
int A = mk.inport("\\A"); int A = mk.inport(ID::A);
int B = mk.inport("\\B"); int B = mk.inport(ID::B);
int C = mk.inport("\\C"); int C = mk.inport(ID(C));
int D = mk.inport("\\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, "\\Y"); mk.outport(Y, ID::Y);
goto optimize; goto optimize;
} }
if (cell->type == "$_OAI4_") if (cell->type == ID($_OAI4_))
{ {
int A = mk.inport("\\A"); int A = mk.inport(ID::A);
int B = mk.inport("\\B"); int B = mk.inport(ID::B);
int C = mk.inport("\\C"); int C = mk.inport(ID(C));
int D = mk.inport("\\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, "\\Y"); mk.outport(Y, ID::Y);
goto optimize; goto optimize;
} }

View file

@ -24,9 +24,9 @@ PRIVATE_NAMESPACE_BEGIN
void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell) void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{ {
IdString A = "\\A", Y = "\\Y"; IdString A = ID::A, Y = ID::Y;
bool is_signed = cell->getParam("\\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));
int y_width = GetSize(cell->getPort(Y)); int y_width = GetSize(cell->getPort(Y));
@ -41,14 +41,14 @@ 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 = "\\A", B = "\\B", Y = "\\Y"; IdString A = ID::A, B = ID::B, Y = ID::Y;
bool is_signed = cell->getParam("\\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));
int b_width = GetSize(cell->getPort(B)); int b_width = GetSize(cell->getPort(B));
int y_width = GetSize(cell->getPort(Y)); int y_width = GetSize(cell->getPort(Y));
if (cell->type == "$and" && !is_signed) { if (cell->type == ID($and) && !is_signed) {
if (a_width > b_width) if (a_width > b_width)
a_width = b_width; a_width = b_width;
else else
@ -71,9 +71,9 @@ 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 = "\\A", Y = "\\Y"; IdString A = ID::A, Y = ID::Y;
bool is_signed = cell->getParam("\\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));
int y_width = GetSize(cell->getPort(Y)); int y_width = GetSize(cell->getPort(Y));
@ -87,14 +87,14 @@ 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 = "\\A", B = "\\B", Y = "\\Y"; IdString A = ID::A, B = ID::B, Y = ID::Y;
bool is_signed = cell->getParam("\\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));
int b_width = GetSize(cell->getPort(B)); int b_width = GetSize(cell->getPort(B));
int y_width = GetSize(cell->getPort(Y)); int y_width = GetSize(cell->getPort(Y));
if (!is_signed && cell->type != "$sub") { if (!is_signed && cell->type != ID($sub)) {
int ab_width = std::max(a_width, b_width); int ab_width = std::max(a_width, b_width);
y_width = std::min(y_width, ab_width+1); y_width = std::min(y_width, ab_width+1);
} }
@ -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 = "\\A", Y = "\\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 = "\\A", B = "\\B", Y = "\\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 = "\\A", B = "\\B", S = "\\S", Y = "\\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));
@ -160,43 +160,43 @@ PRIVATE_NAMESPACE_END
bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell) bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
{ {
if (cell->type.in("$not", "$pos")) { if (cell->type.in(ID($not), ID($pos))) {
bitwise_unary_op(this, cell); bitwise_unary_op(this, cell);
return true; return true;
} }
if (cell->type.in("$and", "$or", "$xor", "$xnor")) { if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) {
bitwise_binary_op(this, cell); bitwise_binary_op(this, cell);
return true; return true;
} }
if (cell->type == "$neg") { if (cell->type == ID($neg)) {
arith_neg_op(this, cell); arith_neg_op(this, cell);
return true; return true;
} }
if (cell->type.in("$add", "$sub")) { if (cell->type.in(ID($add), ID($sub))) {
arith_binary_op(this, cell); arith_binary_op(this, cell);
return true; return true;
} }
if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", "$logic_not")) { if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($logic_not))) {
reduce_op(this, cell); reduce_op(this, cell);
return true; return true;
} }
// FIXME: // FIXME:
// if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) { // if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
// shift_op(this, cell); // shift_op(this, cell);
// return true; // return true;
// } // }
if (cell->type.in("$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt")) { if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) {
compare_op(this, cell); compare_op(this, cell);
return true; return true;
} }
if (cell->type.in("$mux", "$pmux")) { if (cell->type.in(ID($mux), ID($pmux))) {
mux_op(this, cell); mux_op(this, cell);
return true; return true;
} }

View file

@ -84,46 +84,46 @@ struct CellTypes
{ {
setup_internals_eval(); setup_internals_eval();
IdString A = "\\A", B = "\\B", EN = "\\EN", Y = "\\Y"; IdString A = ID::A, B = ID::B, EN = ID(EN), Y = ID::Y;
IdString SRC = "\\SRC", DST = "\\DST", DAT = "\\DAT"; IdString SRC = ID(SRC), DST = ID(DST), DAT = ID(DAT);
IdString EN_SRC = "\\EN_SRC", EN_DST = "\\EN_DST"; IdString EN_SRC = ID(EN_SRC), EN_DST = ID(EN_DST);
setup_type("$tribuf", {A, EN}, {Y}, true); setup_type(ID($tribuf), {A, EN}, {Y}, true);
setup_type("$assert", {A, EN}, pool<RTLIL::IdString>(), true); setup_type(ID($assert), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$assume", {A, EN}, pool<RTLIL::IdString>(), true); setup_type(ID($assume), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$live", {A, EN}, pool<RTLIL::IdString>(), true); setup_type(ID($live), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$fair", {A, EN}, pool<RTLIL::IdString>(), true); setup_type(ID($fair), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$cover", {A, EN}, pool<RTLIL::IdString>(), true); setup_type(ID($cover), {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$initstate", pool<RTLIL::IdString>(), {Y}, true); setup_type(ID($initstate), pool<RTLIL::IdString>(), {Y}, true);
setup_type("$anyconst", pool<RTLIL::IdString>(), {Y}, true); setup_type(ID($anyconst), pool<RTLIL::IdString>(), {Y}, true);
setup_type("$anyseq", pool<RTLIL::IdString>(), {Y}, true); setup_type(ID($anyseq), pool<RTLIL::IdString>(), {Y}, true);
setup_type("$allconst", pool<RTLIL::IdString>(), {Y}, true); setup_type(ID($allconst), pool<RTLIL::IdString>(), {Y}, true);
setup_type("$allseq", pool<RTLIL::IdString>(), {Y}, true); setup_type(ID($allseq), pool<RTLIL::IdString>(), {Y}, true);
setup_type("$equiv", {A, B}, {Y}, true); setup_type(ID($equiv), {A, B}, {Y}, true);
setup_type("$specify2", {EN, SRC, DST}, pool<RTLIL::IdString>(), true); setup_type(ID($specify2), {EN, SRC, DST}, pool<RTLIL::IdString>(), true);
setup_type("$specify3", {EN, SRC, DST, DAT}, pool<RTLIL::IdString>(), true); setup_type(ID($specify3), {EN, SRC, DST, DAT}, pool<RTLIL::IdString>(), true);
setup_type("$specrule", {EN_SRC, EN_DST, SRC, DST}, pool<RTLIL::IdString>(), true); setup_type(ID($specrule), {EN_SRC, EN_DST, SRC, DST}, pool<RTLIL::IdString>(), true);
} }
void setup_internals_eval() void setup_internals_eval()
{ {
std::vector<RTLIL::IdString> unary_ops = { std::vector<RTLIL::IdString> unary_ops = {
"$not", "$pos", "$neg", ID($not), ID($pos), ID($neg),
"$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
"$logic_not", "$slice", "$lut", "$sop" ID($logic_not), ID($slice), ID($lut), ID($sop)
}; };
std::vector<RTLIL::IdString> binary_ops = { std::vector<RTLIL::IdString> binary_ops = {
"$and", "$or", "$xor", "$xnor", ID($and), ID($or), ID($xor), ID($xnor),
"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
"$add", "$sub", "$mul", "$div", "$mod", "$pow", ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow),
"$logic_and", "$logic_or", "$concat", "$macc" ID($logic_and), ID($logic_or), ID($concat), ID($macc)
}; };
IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y"; IdString A = ID::A, B = ID::B, S = ID(S), Y = ID::Y;
IdString P = "\\P", G = "\\G", C = "\\C", X = "\\X"; IdString P = ID(P), G = ID(G), C = ID(C), X = ID(X);
IdString BI = "\\BI", CI = "\\CI", CO = "\\CO", EN = "\\EN"; IdString BI = ID(BI), CI = ID(CI), CO = ID(CO), EN = ID(EN);
for (auto type : unary_ops) for (auto type : unary_ops)
setup_type(type, {A}, {Y}, true); setup_type(type, {A}, {Y}, true);
@ -131,27 +131,27 @@ struct CellTypes
for (auto type : binary_ops) for (auto type : binary_ops)
setup_type(type, {A, B}, {Y}, true); setup_type(type, {A, B}, {Y}, true);
for (auto type : std::vector<RTLIL::IdString>({"$mux", "$pmux"})) for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux)}))
setup_type(type, {A, B, S}, {Y}, true); setup_type(type, {A, B, S}, {Y}, true);
setup_type("$lcu", {P, G, CI}, {CO}, true); setup_type(ID($lcu), {P, G, CI}, {CO}, true);
setup_type("$alu", {A, B, CI, BI}, {X, Y, CO}, true); setup_type(ID($alu), {A, B, CI, BI}, {X, Y, CO}, true);
setup_type("$fa", {A, B, C}, {X, Y}, true); setup_type(ID($fa), {A, B, C}, {X, Y}, true);
} }
void setup_internals_ff() void setup_internals_ff()
{ {
IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN"; IdString SET = ID(SET), CLR = ID(CLR), CLK = ID(CLK), ARST = ID(ARST), EN = ID(EN);
IdString Q = "\\Q", D = "\\D"; IdString Q = ID(Q), D = ID(D);
setup_type("$sr", {SET, CLR}, {Q}); setup_type(ID($sr), {SET, CLR}, {Q});
setup_type("$ff", {D}, {Q}); setup_type(ID($ff), {D}, {Q});
setup_type("$dff", {CLK, D}, {Q}); setup_type(ID($dff), {CLK, D}, {Q});
setup_type("$dffe", {CLK, EN, D}, {Q}); setup_type(ID($dffe), {CLK, EN, D}, {Q});
setup_type("$dffsr", {CLK, SET, CLR, D}, {Q}); setup_type(ID($dffsr), {CLK, SET, CLR, D}, {Q});
setup_type("$adff", {CLK, ARST, D}, {Q}); setup_type(ID($adff), {CLK, ARST, D}, {Q});
setup_type("$dlatch", {EN, D}, {Q}); setup_type(ID($dlatch), {EN, D}, {Q});
setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q}); setup_type(ID($dlatchsr), {EN, SET, CLR, D}, {Q});
} }
@ -159,63 +159,63 @@ struct CellTypes
{ {
setup_internals_ff(); setup_internals_ff();
IdString CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN"; IdString CLK = ID(CLK), ARST = ID(ARST), EN = ID(EN);
IdString ADDR = "\\ADDR", DATA = "\\DATA", RD_EN = "\\RD_EN"; IdString ADDR = ID(ADDR), DATA = ID(DATA), RD_EN = ID(RD_EN);
IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN"; IdString RD_CLK = ID(RD_CLK), RD_ADDR = ID(RD_ADDR), WR_CLK = ID(WR_CLK), WR_EN = ID(WR_EN);
IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA"; IdString WR_ADDR = ID(WR_ADDR), WR_DATA = ID(WR_DATA), RD_DATA = ID(RD_DATA);
IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT"; IdString CTRL_IN = ID(CTRL_IN), CTRL_OUT = ID(CTRL_OUT);
setup_type("$memrd", {CLK, EN, ADDR}, {DATA}); setup_type(ID($memrd), {CLK, EN, ADDR}, {DATA});
setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>()); setup_type(ID($memwr), {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
setup_type("$meminit", {ADDR, DATA}, pool<RTLIL::IdString>()); setup_type(ID($meminit), {ADDR, DATA}, pool<RTLIL::IdString>());
setup_type("$mem", {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA}); setup_type(ID($mem), {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
setup_type("$fsm", {CLK, ARST, CTRL_IN}, {CTRL_OUT}); setup_type(ID($fsm), {CLK, ARST, CTRL_IN}, {CTRL_OUT});
} }
void setup_stdcells() void setup_stdcells()
{ {
setup_stdcells_eval(); setup_stdcells_eval();
IdString A = "\\A", E = "\\E", Y = "\\Y"; IdString A = ID::A, E = ID(E), Y = ID::Y;
setup_type("$_TBUF_", {A, E}, {Y}, true); setup_type(ID($_TBUF_), {A, E}, {Y}, true);
} }
void setup_stdcells_eval() void setup_stdcells_eval()
{ {
IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D"; IdString A = ID::A, B = ID::B, C = ID(C), D = ID(D);
IdString E = "\\E", F = "\\F", G = "\\G", H = "\\H"; IdString E = ID(E), F = ID(F), G = ID(G), H = ID(H);
IdString I = "\\I", J = "\\J", K = "\\K", L = "\\L"; IdString I = ID(I), J = ID(J), K = ID(K), L = ID(L);
IdString M = "\\M", N = "\\N", O = "\\O", P = "\\P"; IdString M = ID(M), N = ID(N), O = ID(O), P = ID(P);
IdString S = "\\S", T = "\\T", U = "\\U", V = "\\V"; IdString S = ID(S), T = ID(T), U = ID(U), V = ID(V);
IdString Y = "\\Y"; IdString Y = ID::Y;
setup_type("$_BUF_", {A}, {Y}, true); setup_type(ID($_BUF_), {A}, {Y}, true);
setup_type("$_NOT_", {A}, {Y}, true); setup_type(ID($_NOT_), {A}, {Y}, true);
setup_type("$_AND_", {A, B}, {Y}, true); setup_type(ID($_AND_), {A, B}, {Y}, true);
setup_type("$_NAND_", {A, B}, {Y}, true); setup_type(ID($_NAND_), {A, B}, {Y}, true);
setup_type("$_OR_", {A, B}, {Y}, true); setup_type(ID($_OR_), {A, B}, {Y}, true);
setup_type("$_NOR_", {A, B}, {Y}, true); setup_type(ID($_NOR_), {A, B}, {Y}, true);
setup_type("$_XOR_", {A, B}, {Y}, true); setup_type(ID($_XOR_), {A, B}, {Y}, true);
setup_type("$_XNOR_", {A, B}, {Y}, true); setup_type(ID($_XNOR_), {A, B}, {Y}, true);
setup_type("$_ANDNOT_", {A, B}, {Y}, true); setup_type(ID($_ANDNOT_), {A, B}, {Y}, true);
setup_type("$_ORNOT_", {A, B}, {Y}, true); setup_type(ID($_ORNOT_), {A, B}, {Y}, true);
setup_type("$_MUX_", {A, B, S}, {Y}, true); setup_type(ID($_MUX_), {A, B, S}, {Y}, true);
setup_type("$_NMUX_", {A, B, S}, {Y}, true); setup_type(ID($_NMUX_), {A, B, S}, {Y}, true);
setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true); setup_type(ID($_MUX4_), {A, B, C, D, S, T}, {Y}, true);
setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true); setup_type(ID($_MUX8_), {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true); setup_type(ID($_MUX16_), {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
setup_type("$_AOI3_", {A, B, C}, {Y}, true); setup_type(ID($_AOI3_), {A, B, C}, {Y}, true);
setup_type("$_OAI3_", {A, B, C}, {Y}, true); setup_type(ID($_OAI3_), {A, B, C}, {Y}, true);
setup_type("$_AOI4_", {A, B, C, D}, {Y}, true); setup_type(ID($_AOI4_), {A, B, C, D}, {Y}, true);
setup_type("$_OAI4_", {A, B, C, D}, {Y}, true); setup_type(ID($_OAI4_), {A, B, C, D}, {Y}, true);
} }
void setup_stdcells_mem() void setup_stdcells_mem()
{ {
IdString S = "\\S", R = "\\R", C = "\\C"; IdString S = ID(S), R = ID(R), C = ID(C);
IdString D = "\\D", Q = "\\Q", E = "\\E"; IdString D = ID(D), Q = ID(Q), E = ID(E);
std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'}; std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'};
@ -223,7 +223,7 @@ struct CellTypes
for (auto c2 : list_np) for (auto c2 : list_np)
setup_type(stringf("$_SR_%c%c_", c1, c2), {S, R}, {Q}); setup_type(stringf("$_SR_%c%c_", c1, c2), {S, R}, {Q});
setup_type("$_FF_", {D}, {Q}); setup_type(ID($_FF_), {D}, {Q});
for (auto c1 : list_np) for (auto c1 : list_np)
setup_type(stringf("$_DFF_%c_", c1), {C, D}, {Q}); setup_type(stringf("$_DFF_%c_", c1), {C, D}, {Q});
@ -289,13 +289,13 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr) static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr)
{ {
if (type == "$sshr" && !signed1) if (type == ID($sshr) && !signed1)
type = "$shr"; type = ID($shr);
if (type == "$sshl" && !signed1) if (type == ID($sshl) && !signed1)
type = "$shl"; type = ID($shl);
if (type != "$sshr" && type != "$sshl" && type != "$shr" && type != "$shl" && type != "$shift" && type != "$shiftx" && if (type != ID($sshr) && type != ID($sshl) && type != ID($shr) && type != ID($shl) && type != ID($shift) && type != ID($shiftx) &&
type != "$pos" && type != "$neg" && type != "$not") { type != ID($pos) && type != ID($neg) && type != ID($not)) {
if (!signed1 || !signed2) if (!signed1 || !signed2)
signed1 = false, signed2 = false; signed1 = false, signed2 = false;
} }
@ -338,25 +338,25 @@ struct CellTypes
HANDLE_CELL_TYPE(neg) HANDLE_CELL_TYPE(neg)
#undef HANDLE_CELL_TYPE #undef HANDLE_CELL_TYPE
if (type == "$_BUF_") if (type == ID($_BUF_))
return arg1; return arg1;
if (type == "$_NOT_") if (type == ID($_NOT_))
return eval_not(arg1); return eval_not(arg1);
if (type == "$_AND_") if (type == ID($_AND_))
return const_and(arg1, arg2, false, false, 1); return const_and(arg1, arg2, false, false, 1);
if (type == "$_NAND_") if (type == ID($_NAND_))
return eval_not(const_and(arg1, arg2, false, false, 1)); return eval_not(const_and(arg1, arg2, false, false, 1));
if (type == "$_OR_") if (type == ID($_OR_))
return const_or(arg1, arg2, false, false, 1); return const_or(arg1, arg2, false, false, 1);
if (type == "$_NOR_") if (type == ID($_NOR_))
return eval_not(const_or(arg1, arg2, false, false, 1)); return eval_not(const_or(arg1, arg2, false, false, 1));
if (type == "$_XOR_") if (type == ID($_XOR_))
return const_xor(arg1, arg2, false, false, 1); return const_xor(arg1, arg2, false, false, 1);
if (type == "$_XNOR_") if (type == ID($_XNOR_))
return const_xnor(arg1, arg2, false, false, 1); return const_xnor(arg1, arg2, false, false, 1);
if (type == "$_ANDNOT_") if (type == ID($_ANDNOT_))
return const_and(arg1, eval_not(arg2), false, false, 1); return const_and(arg1, eval_not(arg2), false, false, 1);
if (type == "$_ORNOT_") if (type == ID($_ORNOT_))
return const_or(arg1, eval_not(arg2), false, false, 1); return const_or(arg1, eval_not(arg2), false, false, 1);
if (errp != nullptr) { if (errp != nullptr) {
@ -369,25 +369,25 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr) static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr)
{ {
if (cell->type == "$slice") { if (cell->type == ID($slice)) {
RTLIL::Const ret; RTLIL::Const ret;
int width = cell->parameters.at("\\Y_WIDTH").as_int(); int width = cell->parameters.at(ID(Y_WIDTH)).as_int();
int offset = cell->parameters.at("\\OFFSET").as_int(); int offset = cell->parameters.at(ID(OFFSET)).as_int();
ret.bits.insert(ret.bits.end(), arg1.bits.begin()+offset, arg1.bits.begin()+offset+width); ret.bits.insert(ret.bits.end(), arg1.bits.begin()+offset, arg1.bits.begin()+offset+width);
return ret; return ret;
} }
if (cell->type == "$concat") { if (cell->type == ID($concat)) {
RTLIL::Const ret = arg1; RTLIL::Const ret = arg1;
ret.bits.insert(ret.bits.end(), arg2.bits.begin(), arg2.bits.end()); ret.bits.insert(ret.bits.end(), arg2.bits.begin(), arg2.bits.end());
return ret; return ret;
} }
if (cell->type == "$lut") if (cell->type == ID($lut))
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
std::vector<RTLIL::State> t = cell->parameters.at("\\LUT").bits; std::vector<RTLIL::State> t = cell->parameters.at(ID(LUT)).bits;
while (GetSize(t) < (1 << width)) while (GetSize(t) < (1 << width))
t.push_back(State::S0); t.push_back(State::S0);
t.resize(1 << width); t.resize(1 << width);
@ -409,11 +409,11 @@ struct CellTypes
return t; return t;
} }
if (cell->type == "$sop") if (cell->type == ID($sop))
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
int depth = cell->parameters.at("\\DEPTH").as_int(); int depth = cell->parameters.at(ID(DEPTH)).as_int();
std::vector<RTLIL::State> t = cell->parameters.at("\\TABLE").bits; std::vector<RTLIL::State> t = cell->parameters.at(ID(TABLE)).bits;
while (GetSize(t) < width*depth*2) while (GetSize(t) < width*depth*2)
t.push_back(State::S0); t.push_back(State::S0);
@ -447,15 +447,15 @@ struct CellTypes
return default_ret; return default_ret;
} }
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool(); bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool();
bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool(); bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool();
int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1; int result_len = cell->parameters.count(ID(Y_WIDTH)) > 0 ? cell->parameters[ID(Y_WIDTH)].as_int() : -1;
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp); return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp);
} }
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr) static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
{ {
if (cell->type.in("$mux", "$pmux", "$_MUX_")) { if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
RTLIL::Const ret = arg1; RTLIL::Const ret = arg1;
for (size_t i = 0; i < arg3.bits.size(); i++) for (size_t i = 0; i < arg3.bits.size(); i++)
if (arg3.bits[i] == RTLIL::State::S1) { if (arg3.bits[i] == RTLIL::State::S1) {
@ -465,9 +465,9 @@ struct CellTypes
return ret; return ret;
} }
if (cell->type == "$_AOI3_") if (cell->type == ID($_AOI3_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1)); return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
if (cell->type == "$_OAI3_") if (cell->type == ID($_OAI3_))
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1)); return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
log_assert(arg3.bits.size() == 0); log_assert(arg3.bits.size() == 0);
@ -476,9 +476,9 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4, bool *errp = nullptr) static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4, bool *errp = nullptr)
{ {
if (cell->type == "$_AOI4_") if (cell->type == ID($_AOI4_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
if (cell->type == "$_OAI4_") if (cell->type == ID($_OAI4_))
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1)); return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1));
log_assert(arg4.bits.size() == 0); log_assert(arg4.bits.size() == 0);

View file

@ -89,12 +89,12 @@ struct ConstEval
bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef) bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef)
{ {
if (cell->type == "$lcu") if (cell->type == ID($lcu))
{ {
RTLIL::SigSpec sig_p = cell->getPort("\\P"); RTLIL::SigSpec sig_p = cell->getPort(ID(P));
RTLIL::SigSpec sig_g = cell->getPort("\\G"); RTLIL::SigSpec sig_g = cell->getPort(ID(G));
RTLIL::SigSpec sig_ci = cell->getPort("\\CI"); RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort("\\CO"))); RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort(ID(CO))));
if (sig_co.is_fully_const()) if (sig_co.is_fully_const())
return true; return true;
@ -128,24 +128,24 @@ 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("\\Y")); log_assert(cell->hasPort(ID::Y));
sig_y = values_map(assign_map(cell->getPort("\\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;
if (cell->hasPort("\\S")) { if (cell->hasPort(ID(S))) {
sig_s = cell->getPort("\\S"); sig_s = cell->getPort(ID(S));
if (!eval(sig_s, undef, cell)) if (!eval(sig_s, undef, cell))
return false; return false;
} }
if (cell->hasPort("\\A")) if (cell->hasPort(ID::A))
sig_a = cell->getPort("\\A"); sig_a = cell->getPort(ID::A);
if (cell->hasPort("\\B")) if (cell->hasPort(ID::B))
sig_b = cell->getPort("\\B"); sig_b = cell->getPort(ID::B);
if (cell->type.in("$mux", "$pmux", "$_MUX_", "$_NMUX_")) if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_NMUX_)))
{ {
std::vector<RTLIL::SigSpec> y_candidates; std::vector<RTLIL::SigSpec> y_candidates;
int count_maybe_set_s_bits = 0; int count_maybe_set_s_bits = 0;
@ -175,7 +175,7 @@ struct ConstEval
for (auto &yc : y_candidates) { for (auto &yc : y_candidates) {
if (!eval(yc, undef, cell)) if (!eval(yc, undef, cell))
return false; return false;
if (cell->type == "$_NMUX_") if (cell->type == ID($_NMUX_))
y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc))); y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc)));
else else
y_values.push_back(yc.as_const()); y_values.push_back(yc.as_const());
@ -198,10 +198,10 @@ struct ConstEval
else else
set(sig_y, y_values.front()); set(sig_y, y_values.front());
} }
else if (cell->type == "$fa") else if (cell->type == ID($fa))
{ {
RTLIL::SigSpec sig_c = cell->getPort("\\C"); RTLIL::SigSpec sig_c = cell->getPort(ID(C));
RTLIL::SigSpec sig_x = cell->getPort("\\X"); RTLIL::SigSpec sig_x = cell->getPort(ID(X));
int width = GetSize(sig_c); int width = GetSize(sig_c);
if (!eval(sig_a, undef, cell)) if (!eval(sig_a, undef, cell))
@ -227,13 +227,13 @@ struct ConstEval
set(sig_y, val_y); set(sig_y, val_y);
set(sig_x, val_x); set(sig_x, val_x);
} }
else if (cell->type == "$alu") else if (cell->type == ID($alu))
{ {
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool(); bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool();
bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool(); bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool();
RTLIL::SigSpec sig_ci = cell->getPort("\\CI"); RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
RTLIL::SigSpec sig_bi = cell->getPort("\\BI"); RTLIL::SigSpec sig_bi = cell->getPort(ID(BI));
if (!eval(sig_a, undef, cell)) if (!eval(sig_a, undef, cell))
return false; return false;
@ -247,8 +247,8 @@ struct ConstEval
if (!eval(sig_bi, undef, cell)) if (!eval(sig_bi, undef, cell))
return false; return false;
RTLIL::SigSpec sig_x = cell->getPort("\\X"); RTLIL::SigSpec sig_x = cell->getPort(ID(X));
RTLIL::SigSpec sig_co = cell->getPort("\\CO"); RTLIL::SigSpec sig_co = cell->getPort(ID(CO));
bool any_input_undef = !(sig_a.is_fully_def() && sig_b.is_fully_def() && sig_ci.is_fully_def() && sig_bi.is_fully_def()); bool any_input_undef = !(sig_a.is_fully_def() && sig_b.is_fully_def() && sig_ci.is_fully_def() && sig_bi.is_fully_def());
sig_a.extend_u0(GetSize(sig_y), signed_a); sig_a.extend_u0(GetSize(sig_y), signed_a);
@ -283,7 +283,7 @@ struct ConstEval
} }
} }
} }
else if (cell->type == "$macc") else if (cell->type == ID($macc))
{ {
Macc macc; Macc macc;
macc.from_cell(cell); macc.from_cell(cell);
@ -298,21 +298,21 @@ struct ConstEval
return false; return false;
} }
RTLIL::Const result(0, GetSize(cell->getPort("\\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("\\Y"), result); set(cell->getPort(ID::Y), result);
} }
else else
{ {
RTLIL::SigSpec sig_c, sig_d; RTLIL::SigSpec sig_c, sig_d;
if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) { if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) {
if (cell->hasPort("\\C")) if (cell->hasPort(ID(C)))
sig_c = cell->getPort("\\C"); sig_c = cell->getPort(ID(C));
if (cell->hasPort("\\D")) if (cell->hasPort(ID(D)))
sig_d = cell->getPort("\\D"); sig_d = cell->getPort(ID(D));
} }
if (sig_a.size() > 0 && !eval(sig_a, undef, cell)) if (sig_a.size() > 0 && !eval(sig_a, undef, cell))

View file

@ -28,44 +28,44 @@ struct CellCosts
{ {
static const dict<RTLIL::IdString, int>& default_gate_cost() { static const dict<RTLIL::IdString, int>& default_gate_cost() {
static const dict<RTLIL::IdString, int> db = { static const dict<RTLIL::IdString, int> db = {
{ "$_BUF_", 1 }, { ID($_BUF_), 1 },
{ "$_NOT_", 2 }, { ID($_NOT_), 2 },
{ "$_AND_", 4 }, { ID($_AND_), 4 },
{ "$_NAND_", 4 }, { ID($_NAND_), 4 },
{ "$_OR_", 4 }, { ID($_OR_), 4 },
{ "$_NOR_", 4 }, { ID($_NOR_), 4 },
{ "$_ANDNOT_", 4 }, { ID($_ANDNOT_), 4 },
{ "$_ORNOT_", 4 }, { ID($_ORNOT_), 4 },
{ "$_XOR_", 5 }, { ID($_XOR_), 5 },
{ "$_XNOR_", 5 }, { ID($_XNOR_), 5 },
{ "$_AOI3_", 6 }, { ID($_AOI3_), 6 },
{ "$_OAI3_", 6 }, { ID($_OAI3_), 6 },
{ "$_AOI4_", 7 }, { ID($_AOI4_), 7 },
{ "$_OAI4_", 7 }, { ID($_OAI4_), 7 },
{ "$_MUX_", 4 }, { ID($_MUX_), 4 },
{ "$_NMUX_", 4 } { ID($_NMUX_), 4 }
}; };
return db; return db;
} }
static const dict<RTLIL::IdString, int>& cmos_gate_cost() { static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
static const dict<RTLIL::IdString, int> db = { static const dict<RTLIL::IdString, int> db = {
{ "$_BUF_", 1 }, { ID($_BUF_), 1 },
{ "$_NOT_", 2 }, { ID($_NOT_), 2 },
{ "$_AND_", 6 }, { ID($_AND_), 6 },
{ "$_NAND_", 4 }, { ID($_NAND_), 4 },
{ "$_OR_", 6 }, { ID($_OR_), 6 },
{ "$_NOR_", 4 }, { ID($_NOR_), 4 },
{ "$_ANDNOT_", 6 }, { ID($_ANDNOT_), 6 },
{ "$_ORNOT_", 6 }, { ID($_ORNOT_), 6 },
{ "$_XOR_", 12 }, { ID($_XOR_), 12 },
{ "$_XNOR_", 12 }, { ID($_XNOR_), 12 },
{ "$_AOI3_", 6 }, { ID($_AOI3_), 6 },
{ "$_OAI3_", 6 }, { ID($_OAI3_), 6 },
{ "$_AOI4_", 8 }, { ID($_AOI4_), 8 },
{ "$_OAI4_", 8 }, { ID($_OAI4_), 8 },
{ "$_MUX_", 12 }, { ID($_MUX_), 12 },
{ "$_NMUX_", 10 } { ID($_NMUX_), 10 }
}; };
return db; return db;
} }
@ -92,8 +92,8 @@ struct CellCosts
{ {
RTLIL::Module *mod = design->module(cell->type); RTLIL::Module *mod = design->module(cell->type);
if (mod->attributes.count("\\cost")) if (mod->attributes.count(ID(cost)))
return mod->attributes.at("\\cost").as_int(); return mod->attributes.at(ID(cost)).as_int();
if (mod_cost_cache.count(mod->name)) if (mod_cost_cache.count(mod->name))
return mod_cost_cache.at(mod->name); return mod_cost_cache.at(mod->name);

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,16 +99,16 @@ struct Macc
void from_cell(RTLIL::Cell *cell) void from_cell(RTLIL::Cell *cell)
{ {
RTLIL::SigSpec port_a = cell->getPort("\\A"); RTLIL::SigSpec port_a = cell->getPort(ID::A);
ports.clear(); ports.clear();
bit_ports = cell->getPort("\\B"); bit_ports = cell->getPort(ID::B);
std::vector<RTLIL::State> config_bits = cell->getParam("\\CONFIG").bits; std::vector<RTLIL::State> config_bits = cell->getParam(ID(CONFIG)).bits;
int config_cursor = 0; int config_cursor = 0;
#ifndef NDEBUG #ifndef NDEBUG
int config_width = cell->getParam("\\CONFIG_WIDTH").as_int(); int config_width = cell->getParam(ID(CONFIG_WIDTH)).as_int();
log_assert(GetSize(config_bits) >= config_width); log_assert(GetSize(config_bits) >= config_width);
#endif #endif
@ -191,12 +191,12 @@ struct Macc
port_a.append(port.in_b); port_a.append(port.in_b);
} }
cell->setPort("\\A", port_a); cell->setPort(ID::A, port_a);
cell->setPort("\\B", bit_ports); cell->setPort(ID::B, bit_ports);
cell->setParam("\\CONFIG", config_bits); cell->setParam(ID(CONFIG), config_bits);
cell->setParam("\\CONFIG_WIDTH", GetSize(config_bits)); cell->setParam(ID(CONFIG_WIDTH), GetSize(config_bits));
cell->setParam("\\A_WIDTH", GetSize(port_a)); cell->setParam(ID(A_WIDTH), GetSize(port_a));
cell->setParam("\\B_WIDTH", GetSize(bit_ports)); cell->setParam(ID(B_WIDTH), GetSize(bit_ports));
} }
bool eval(RTLIL::Const &result) const bool eval(RTLIL::Const &result) const

File diff suppressed because it is too large Load diff

View file

@ -78,6 +78,8 @@ namespace RTLIL
{ {
#undef YOSYS_XTRACE_GET_PUT #undef YOSYS_XTRACE_GET_PUT
#undef YOSYS_SORT_ID_FREE_LIST #undef YOSYS_SORT_ID_FREE_LIST
#undef YOSYS_USE_STICKY_IDS
#undef YOSYS_NO_IDS_REFCNT
// the global id string cache // the global id string cache
@ -87,13 +89,17 @@ namespace RTLIL
~destruct_guard_t() { ok = false; } ~destruct_guard_t() { ok = false; }
} destruct_guard; } destruct_guard;
static std::vector<int> global_refcount_storage_;
static std::vector<char*> global_id_storage_; static std::vector<char*> global_id_storage_;
static dict<char*, int, hash_cstr_ops> global_id_index_; static dict<char*, int, hash_cstr_ops> global_id_index_;
#ifndef YOSYS_NO_IDS_REFCNT
static std::vector<int> global_refcount_storage_;
static std::vector<int> global_free_idx_list_; static std::vector<int> global_free_idx_list_;
#endif
#ifdef YOSYS_USE_STICKY_IDS
static int last_created_idx_ptr_; static int last_created_idx_ptr_;
static int last_created_idx_[8]; static int last_created_idx_[8];
#endif
static inline void xtrace_db_dump() static inline void xtrace_db_dump()
{ {
@ -110,12 +116,14 @@ namespace RTLIL
static inline void checkpoint() static inline void checkpoint()
{ {
#ifdef YOSYS_USE_STICKY_IDS
last_created_idx_ptr_ = 0; last_created_idx_ptr_ = 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (last_created_idx_[i]) if (last_created_idx_[i])
put_reference(last_created_idx_[i]); put_reference(last_created_idx_[i]);
last_created_idx_[i] = 0; last_created_idx_[i] = 0;
} }
#endif
#ifdef YOSYS_SORT_ID_FREE_LIST #ifdef YOSYS_SORT_ID_FREE_LIST
std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>()); std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
#endif #endif
@ -123,36 +131,47 @@ namespace RTLIL
static inline int get_reference(int idx) static inline int get_reference(int idx)
{ {
global_refcount_storage_.at(idx)++; if (idx) {
#ifdef YOSYS_XTRACE_GET_PUT #ifndef YOSYS_NO_IDS_REFCNT
if (yosys_xtrace) { global_refcount_storage_[idx]++;
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
}
#endif #endif
#ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace)
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
#endif
}
return idx; return idx;
} }
static inline int get_reference(const char *p) static int get_reference(const char *p)
{ {
log_assert(destruct_guard.ok); log_assert(destruct_guard.ok);
if (p[0]) { if (!p[0])
log_assert(p[1] != 0); return 0;
log_assert(p[0] == '$' || p[0] == '\\'); log_assert(p[0] == '$' || p[0] == '\\');
} log_assert(p[1] != 0);
auto it = global_id_index_.find((char*)p); auto it = global_id_index_.find((char*)p);
if (it != global_id_index_.end()) { if (it != global_id_index_.end()) {
#ifndef YOSYS_NO_IDS_REFCNT
global_refcount_storage_.at(it->second)++; global_refcount_storage_.at(it->second)++;
#endif
#ifdef YOSYS_XTRACE_GET_PUT #ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace) { if (yosys_xtrace)
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second)); log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
}
#endif #endif
return it->second; return it->second;
} }
#ifndef YOSYS_NO_IDS_REFCNT
if (global_free_idx_list_.empty()) { if (global_free_idx_list_.empty()) {
if (global_id_storage_.empty()) {
global_refcount_storage_.push_back(0);
global_id_storage_.push_back((char*)"");
global_id_index_[global_id_storage_.back()] = 0;
}
log_assert(global_id_storage_.size() < 0x40000000); log_assert(global_id_storage_.size() < 0x40000000);
global_free_idx_list_.push_back(global_id_storage_.size()); global_free_idx_list_.push_back(global_id_storage_.size());
global_id_storage_.push_back(nullptr); global_id_storage_.push_back(nullptr);
@ -164,13 +183,15 @@ namespace RTLIL
global_id_storage_.at(idx) = strdup(p); global_id_storage_.at(idx) = strdup(p);
global_id_index_[global_id_storage_.at(idx)] = idx; global_id_index_[global_id_storage_.at(idx)] = idx;
global_refcount_storage_.at(idx)++; global_refcount_storage_.at(idx)++;
#else
// Avoid Create->Delete->Create pattern if (global_id_storage_.empty()) {
if (last_created_idx_[last_created_idx_ptr_]) global_id_storage_.push_back((char*)"");
put_reference(last_created_idx_[last_created_idx_ptr_]); global_id_index_[global_id_storage_.back()] = 0;
last_created_idx_[last_created_idx_ptr_] = idx; }
get_reference(last_created_idx_[last_created_idx_ptr_]); int idx = global_id_storage_.size();
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7; global_id_storage_.push_back(strdup(p));
global_id_index_[global_id_storage_.back()] = idx;
#endif
if (yosys_xtrace) { if (yosys_xtrace) {
log("#X# New IdString '%s' with index %d.\n", p, idx); log("#X# New IdString '%s' with index %d.\n", p, idx);
@ -178,18 +199,28 @@ namespace RTLIL
} }
#ifdef YOSYS_XTRACE_GET_PUT #ifdef YOSYS_XTRACE_GET_PUT
if (yosys_xtrace) { if (yosys_xtrace)
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx)); log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
}
#endif #endif
#ifdef YOSYS_USE_STICKY_IDS
// Avoid Create->Delete->Create pattern
if (last_created_idx_[last_created_idx_ptr_])
put_reference(last_created_idx_[last_created_idx_ptr_]);
last_created_idx_[last_created_idx_ptr_] = idx;
get_reference(last_created_idx_[last_created_idx_ptr_]);
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
#endif
return idx; return idx;
} }
#ifndef YOSYS_NO_IDS_REFCNT
static inline void put_reference(int idx) static inline void put_reference(int idx)
{ {
// put_reference() may be called from destructors after the destructor of // put_reference() may be called from destructors after the destructor of
// global_refcount_storage_ has been run. in this case we simply do nothing. // global_refcount_storage_ has been run. in this case we simply do nothing.
if (!destruct_guard.ok) if (!destruct_guard.ok || !idx)
return; return;
#ifdef YOSYS_XTRACE_GET_PUT #ifdef YOSYS_XTRACE_GET_PUT
@ -198,11 +229,13 @@ namespace RTLIL
} }
#endif #endif
log_assert(global_refcount_storage_.at(idx) > 0); int &refcount = global_refcount_storage_[idx];
if (--global_refcount_storage_.at(idx) != 0) if (--refcount > 0)
return; return;
log_assert(refcount == 0);
if (yosys_xtrace) { if (yosys_xtrace) {
log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx); log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
log_backtrace("-X- ", yosys_xtrace-1); log_backtrace("-X- ", yosys_xtrace-1);
@ -213,46 +246,50 @@ namespace RTLIL
global_id_storage_.at(idx) = nullptr; global_id_storage_.at(idx) = nullptr;
global_free_idx_list_.push_back(idx); global_free_idx_list_.push_back(idx);
} }
#else
static inline void put_reference(int) { }
#endif
// the actual IdString object is just is a single int // the actual IdString object is just is a single int
int index_; int index_;
IdString() : index_(get_reference("")) { } inline IdString() : index_(0) { }
IdString(const char *str) : index_(get_reference(str)) { } inline IdString(const char *str) : index_(get_reference(str)) { }
IdString(const IdString &str) : index_(get_reference(str.index_)) { } inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
IdString(const std::string &str) : index_(get_reference(str.c_str())) { } inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
~IdString() { put_reference(index_); } inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
inline ~IdString() { put_reference(index_); }
void operator=(const IdString &rhs) { inline void operator=(const IdString &rhs) {
put_reference(index_); put_reference(index_);
index_ = get_reference(rhs.index_); index_ = get_reference(rhs.index_);
} }
void operator=(const char *rhs) { inline void operator=(const char *rhs) {
IdString id(rhs); IdString id(rhs);
*this = id; *this = id;
} }
void operator=(const std::string &rhs) { inline void operator=(const std::string &rhs) {
IdString id(rhs); IdString id(rhs);
*this = id; *this = id;
} }
const char *c_str() const { inline const char *c_str() const {
return global_id_storage_.at(index_); return global_id_storage_.at(index_);
} }
std::string str() const { inline std::string str() const {
return std::string(global_id_storage_.at(index_)); return std::string(global_id_storage_.at(index_));
} }
bool operator<(const IdString &rhs) const { inline bool operator<(const IdString &rhs) const {
return index_ < rhs.index_; return index_ < rhs.index_;
} }
bool operator==(const IdString &rhs) const { return index_ == rhs.index_; } inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; } inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
// The methods below are just convenience functions for better compatibility with std::string. // The methods below are just convenience functions for better compatibility with std::string.
@ -332,6 +369,14 @@ namespace RTLIL
bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; } bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
}; };
namespace ID {
// defined in rtlil.cc, initialized in yosys.cc
extern IdString A, B, Y;
extern IdString keep;
extern IdString whitebox;
extern IdString blackbox;
};
static inline std::string escape_id(std::string str) { static inline std::string escape_id(std::string str) {
if (str.size() > 0 && str[0] != '\\' && str[0] != '$') if (str.size() > 0 && str[0] != '\\' && str[0] != '$')
return "\\" + str; return "\\" + str;
@ -604,7 +649,7 @@ struct RTLIL::AttrObject
bool get_bool_attribute(RTLIL::IdString id) const; bool get_bool_attribute(RTLIL::IdString id) const;
bool get_blackbox_attribute(bool ignore_wb=false) const { bool get_blackbox_attribute(bool ignore_wb=false) const {
return get_bool_attribute("\\blackbox") || (!ignore_wb && get_bool_attribute("\\whitebox")); return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox));
} }
void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data); void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
@ -1339,8 +1384,8 @@ public:
void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false); void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false);
bool has_keep_attr() const { bool has_keep_attr() const {
return get_bool_attribute("\\keep") || (module && module->design && module->design->module(type) && return get_bool_attribute(ID::keep) || (module && module->design && module->design->module(type) &&
module->design->module(type)->get_bool_attribute("\\keep")); module->design->module(type)->get_bool_attribute(ID::keep));
} }
template<typename T> void rewrite_sigspecs(T &functor); template<typename T> void rewrite_sigspecs(T &functor);

File diff suppressed because it is too large Load diff

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");
@ -510,10 +510,13 @@ void yosys_setup()
if(already_setup) if(already_setup)
return; return;
already_setup = true; already_setup = true;
// if there are already IdString objects then we have a global initialization order bug
IdString empty_id; RTLIL::ID::A = "\\A";
log_assert(empty_id.index_ == 0); RTLIL::ID::B = "\\B";
IdString::get_reference(empty_id.index_); RTLIL::ID::Y = "\\Y";
RTLIL::ID::keep = "\\keep";
RTLIL::ID::whitebox = "\\whitebox";
RTLIL::ID::blackbox = "\\blackbox";
#ifdef WITH_PYTHON #ifdef WITH_PYTHON
PyImport_AppendInittab((char*)"libyosys", INIT_MODULE); PyImport_AppendInittab((char*)"libyosys", INIT_MODULE);
@ -575,9 +578,6 @@ void yosys_shutdown()
#ifdef WITH_PYTHON #ifdef WITH_PYTHON
Py_Finalize(); Py_Finalize();
#endif #endif
IdString empty_id;
IdString::put_reference(empty_id.index_);
} }
RTLIL::IdString new_id(std::string file, int line, std::string func) RTLIL::IdString new_id(std::string file, int line, std::string func)

View file

@ -305,8 +305,17 @@ RTLIL::IdString new_id(std::string file, int line, std::string func);
#define NEW_ID \ #define NEW_ID \
YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__) YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__)
#define ID(_str) \ // Create a statically allocated IdString object, using for example ID(A) or ID($add).
([]() { static YOSYS_NAMESPACE_PREFIX RTLIL::IdString _id(_str); return _id; })() //
// Recipe for Converting old code that is using conversion of strings like "\\A" and
// "$add" for creating IdStrings: Run below SED command on the .cc file and then use for
// example "meld foo.cc foo.cc.orig" to manually compile errors, if necessary.
//
// sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' <filename>
//
#define ID(_id) ([]() { const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
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

@ -508,23 +508,17 @@ class TupleTranslator(PythonDictTranslator):
#Generate c++ code to translate to a boost::python::tuple #Generate c++ code to translate to a boost::python::tuple
@classmethod @classmethod
def translate_cpp(c, varname, types, prefix, ref): def translate_cpp(c, varname, types, prefix, ref):
text = prefix + TupleTranslator.typename + " " + varname + "___tmp = boost::python::make_tuple(" + varname + ".first, " + varname + ".second);" # if the tuple is a pair of SigSpecs (aka SigSig), then we need
return text # to call get_py_obj() on each item in the tuple
tmp_name = "tmp_" + str(Translator.tmp_cntr) if types[0].name in classnames:
Translator.tmp_cntr = Translator.tmp_cntr + 1 first_var = types[0].name + "::get_py_obj(" + varname + ".first)"
if ref:
text += prefix + "for(auto " + tmp_name + " : *" + varname + ")"
else: else:
text += prefix + "for(auto " + tmp_name + " : " + varname + ")" first_var = varname + ".first"
text += prefix + "{" if types[1].name in classnames:
if types[0].name.split(" ")[-1] in primitive_types or types[0].name in enum_names: second_var = types[1].name + "::get_py_obj(" + varname + ".second)"
text += prefix + "\t" + varname + "___tmp.append(" + tmp_name + ");" else:
elif types[0].name in known_containers: second_var = varname + ".second"
text += known_containers[types[0].name].translate_cpp(tmp_name, types[0].cont.args, prefix + "\t", types[1].attr_type == attr_types.star) text = prefix + TupleTranslator.typename + " " + varname + "___tmp = boost::python::make_tuple(" + first_var + ", " + second_var + ");"
text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "___tmp);"
elif types[0].name in classnames:
text += prefix + "\t" + varname + "___tmp.append(" + types[0].name + "::get_py_obj(" + tmp_name + "));"
text += prefix + "}"
return text return text
#Associate the Translators with their c++ type #Associate the Translators with their c++ type

View file

@ -107,7 +107,7 @@ struct DeletePass : public Pass {
for (auto &it : module->cells_) { for (auto &it : module->cells_) {
if (design->selected(module, it.second)) if (design->selected(module, it.second))
delete_cells.insert(it.second); delete_cells.insert(it.second);
if ((it.second->type == "$memrd" || it.second->type == "$memwr") && if (it.second->type.in("$memrd", "$memwr") &&
delete_mems.count(it.second->parameters.at("\\MEMID").decode_string()) != 0) delete_mems.count(it.second->parameters.at("\\MEMID").decode_string()) != 0)
delete_cells.insert(it.second); delete_cells.insert(it.second);
} }

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

@ -37,22 +37,22 @@ struct ExclusiveDatabase
SigBit y_port; SigBit y_port;
pool<Cell*> reduce_or; pool<Cell*> reduce_or;
for (auto cell : module->cells()) { for (auto cell : module->cells()) {
if (cell->type == "$eq") { if (cell->type == ID($eq)) {
nonconst_sig = sigmap(cell->getPort("\\A")); nonconst_sig = sigmap(cell->getPort(ID::A));
const_sig = sigmap(cell->getPort("\\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("\\Y")); y_port = sigmap(cell->getPort(ID::Y));
} }
else if (cell->type == "$logic_not") { else if (cell->type == ID($logic_not)) {
nonconst_sig = sigmap(cell->getPort("\\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("\\Y")); y_port = sigmap(cell->getPort(ID::Y));
} }
else if (cell->type == "$reduce_or") { else if (cell->type == ID($reduce_or)) {
reduce_or.insert(cell); reduce_or.insert(cell);
continue; continue;
} }
@ -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("\\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("\\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("\\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("$mux", "$pmux") && !cell->get_bool_attribute("\\keep")) if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID::keep))
{ {
SigSpec a_sig = sigmap(cell->getPort("\\A")); SigSpec a_sig = sigmap(cell->getPort(ID::A));
SigSpec b_sig; SigSpec b_sig;
if (cell->type == "$mux") if (cell->type == ID($mux))
b_sig = sigmap(cell->getPort("\\B")); b_sig = sigmap(cell->getPort(ID::B));
SigSpec y_sig = sigmap(cell->getPort("\\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,16 +186,16 @@ 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("\\A")); SigSpec a_sig = sigmap(cell->getPort(ID::A));
if (cell->type == "$mux") { if (cell->type == ID($mux)) {
SigSpec b_sig = sigmap(cell->getPort("\\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;
if (!sig_chain_prev.count(a_sig)) if (!sig_chain_prev.count(a_sig))
a_sig = b_sig; a_sig = b_sig;
} }
else if (cell->type == "$pmux") { else if (cell->type == ID($pmux)) {
if (!sig_chain_prev.count(a_sig)) if (!sig_chain_prev.count(a_sig))
goto start_cell; goto start_cell;
} }
@ -208,8 +208,8 @@ struct MuxpackWorker
{ {
Cell *prev_cell = sig_chain_prev.at(a_sig); Cell *prev_cell = sig_chain_prev.at(a_sig);
log_assert(prev_cell); log_assert(prev_cell);
SigSpec s_sig = sigmap(cell->getPort("\\S")); SigSpec s_sig = sigmap(cell->getPort(ID(S)));
s_sig.append(sigmap(prev_cell->getPort("\\S"))); s_sig.append(sigmap(prev_cell->getPort(ID(S))));
if (!excl_db.query(s_sig)) if (!excl_db.query(s_sig))
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("\\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;
@ -269,29 +269,29 @@ struct MuxpackWorker
mux_count += cases; mux_count += cases;
pmux_count += 1; pmux_count += 1;
first_cell->type = "$pmux"; first_cell->type = ID($pmux);
SigSpec b_sig = first_cell->getPort("\\B"); SigSpec b_sig = first_cell->getPort(ID::B);
SigSpec s_sig = first_cell->getPort("\\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("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) { if (sigmap(prev_cell->getPort(ID::Y)) == sigmap(cursor_cell->getPort(ID::A))) {
b_sig.append(cursor_cell->getPort("\\B")); b_sig.append(cursor_cell->getPort(ID::B));
s_sig.append(cursor_cell->getPort("\\S")); s_sig.append(cursor_cell->getPort(ID(S)));
} }
else { else {
log_assert(cursor_cell->type == "$mux"); log_assert(cursor_cell->type == ID($mux));
b_sig.append(cursor_cell->getPort("\\A")); b_sig.append(cursor_cell->getPort(ID::A));
s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\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("\\B", b_sig); first_cell->setPort(ID::B, b_sig);
first_cell->setPort("\\S", s_sig); first_cell->setPort(ID(S), s_sig);
first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); first_cell->setParam(ID(S_WIDTH), GetSize(s_sig));
first_cell->setPort("\\Y", last_cell->getPort("\\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("\\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;
@ -64,7 +64,7 @@ struct keep_cache_t
bool query(Cell *cell) bool query(Cell *cell)
{ {
if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule")) if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover), ID($specify2), ID($specify3), ID($specrule)))
return true; return true;
if (cell->has_keep_attr()) if (cell->has_keep_attr())
@ -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("\\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);
@ -177,8 +177,8 @@ void rmunused_module_cells(Module *module, bool verbose)
int count_nontrivial_wire_attrs(RTLIL::Wire *w) int count_nontrivial_wire_attrs(RTLIL::Wire *w)
{ {
int count = w->attributes.size(); int count = w->attributes.size();
count -= w->attributes.count("\\src"); count -= w->attributes.count(ID(src));
count -= w->attributes.count("\\unused_bits"); count -= w->attributes.count(ID(unused_bits));
return count; return count;
} }
@ -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("\\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);
@ -311,19 +311,19 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
log_assert(GetSize(s1) == GetSize(s2)); log_assert(GetSize(s1) == GetSize(s2));
Const initval; Const initval;
if (wire->attributes.count("\\init")) if (wire->attributes.count(ID(init)))
initval = wire->attributes.at("\\init"); initval = wire->attributes.at(ID(init));
if (GetSize(initval) != GetSize(wire)) if (GetSize(initval) != GetSize(wire))
initval.bits.resize(GetSize(wire), State::Sx); initval.bits.resize(GetSize(wire), State::Sx);
if (initval.is_fully_undef()) if (initval.is_fully_undef())
wire->attributes.erase("\\init"); wire->attributes.erase(ID(init));
if (GetSize(wire) == 0) { if (GetSize(wire) == 0) {
// delete zero-width wires, unless they are module ports // delete zero-width wires, unless they are module ports
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("\\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)) {
@ -357,9 +357,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
} }
if (new_conn.first.size() > 0) { if (new_conn.first.size() > 0) {
if (initval.is_fully_undef()) if (initval.is_fully_undef())
wire->attributes.erase("\\init"); wire->attributes.erase(ID(init));
else else
wire->attributes.at("\\init") = initval; wire->attributes.at(ID(init)) = initval;
used_signals.add(new_conn.first); used_signals.add(new_conn.first);
used_signals.add(new_conn.second); used_signals.add(new_conn.second);
module->connect(new_conn); module->connect(new_conn);
@ -377,11 +377,11 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
} }
} }
if (unused_bits.empty() || wire->port_id != 0) if (unused_bits.empty() || wire->port_id != 0)
wire->attributes.erase("\\unused_bits"); wire->attributes.erase(ID(unused_bits));
else else
wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits); wire->attributes[ID(unused_bits)] = RTLIL::Const(unused_bits);
} else { } else {
wire->attributes.erase("\\unused_bits"); wire->attributes.erase(ID(unused_bits));
} }
} }
} }
@ -413,18 +413,18 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
dict<SigBit, State> qbits; dict<SigBit, State> qbits;
for (auto cell : module->cells()) for (auto cell : module->cells())
if (fftypes.cell_known(cell->type) && cell->hasPort("\\Q")) if (fftypes.cell_known(cell->type) && cell->hasPort(ID(Q)))
{ {
SigSpec sig = cell->getPort("\\Q"); SigSpec sig = cell->getPort(ID(Q));
for (int i = 0; i < GetSize(sig); i++) for (int i = 0; i < GetSize(sig); i++)
{ {
SigBit bit = sig[i]; SigBit bit = sig[i];
if (bit.wire == nullptr || bit.wire->attributes.count("\\init") == 0) if (bit.wire == nullptr || bit.wire->attributes.count(ID(init)) == 0)
continue; continue;
Const init = bit.wire->attributes.at("\\init"); Const init = bit.wire->attributes.at(ID(init));
if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz) if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz)
continue; continue;
@ -439,10 +439,10 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
if (!purge_mode && wire->name[0] == '\\') if (!purge_mode && wire->name[0] == '\\')
continue; continue;
if (wire->attributes.count("\\init") == 0) if (wire->attributes.count(ID(init)) == 0)
continue; continue;
Const init = wire->attributes.at("\\init"); Const init = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++) for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++)
{ {
@ -465,7 +465,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
if (verbose) if (verbose)
log_debug(" removing redundant init attribute on %s.\n", log_id(wire)); log_debug(" removing redundant init attribute on %s.\n", log_id(wire));
wire->attributes.erase("\\init"); wire->attributes.erase(ID(init));
did_something = true; did_something = true;
next_wire:; next_wire:;
} }
@ -480,10 +480,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
std::vector<RTLIL::Cell*> delcells; std::vector<RTLIL::Cell*> delcells;
for (auto cell : module->cells()) for (auto cell : module->cells())
if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) { if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) {
bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool(); bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool();
RTLIL::SigSpec a = cell->getPort("\\A"); RTLIL::SigSpec a = cell->getPort(ID::A);
RTLIL::SigSpec y = cell->getPort("\\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("\\Y")), log_signal(cell->getPort("\\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

@ -35,10 +35,10 @@ void demorgan_worker(
//TODO: Add support for reduce_xor //TODO: Add support for reduce_xor
//DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number) //DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number)
if( (cell->type != "$reduce_and") && (cell->type != "$reduce_or") ) if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) )
return; return;
auto insig = sigmap(cell->getPort("\\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 == "\\Y" && x.cell->type == "$_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 == "\\Y" && x.cell->type == "$_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("\\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,20 +151,20 @@ 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("\\A", insig); cell->setPort(ID::A, insig);
//Change the cell type //Change the cell type
if(cell->type == "$reduce_and") if(cell->type == ID($reduce_and))
cell->type = "$reduce_or"; cell->type = ID($reduce_or);
else if(cell->type == "$reduce_or") else if(cell->type == ID($reduce_or))
cell->type = "$reduce_and"; cell->type = ID($reduce_and);
//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("\\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("\\Y", uninverted_output); cell->setPort(ID::Y, uninverted_output);
} }
struct OptDemorganPass : public Pass { struct OptDemorganPass : public Pass {

File diff suppressed because it is too large Load diff

View file

@ -40,9 +40,9 @@ 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("\\A")); SigSpec lut_input = sigmap(lut->getPort(ID::A));
int lut_width = lut->getParam("\\WIDTH").as_int(); int lut_width = lut->getParam(ID(WIDTH)).as_int();
Const lut_table = lut->getParam("\\LUT"); Const lut_table = lut->getParam(ID(LUT));
int lut_index = 0; int lut_index = 0;
for (int i = 0; i < lut_width; i++) for (int i = 0; i < lut_width; i++)
@ -99,16 +99,16 @@ struct OptLutWorker
log("Discovering LUTs.\n"); log("Discovering LUTs.\n");
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type == "$lut") if (cell->type == ID($lut))
{ {
if (cell->has_keep_attr()) if (cell->has_keep_attr())
continue; continue;
SigBit lut_output = cell->getPort("\\Y"); SigBit lut_output = cell->getPort(ID::Y);
if (lut_output.wire->get_bool_attribute("\\keep")) if (lut_output.wire->get_bool_attribute(ID::keep))
continue; continue;
int lut_width = cell->getParam("\\WIDTH").as_int(); int lut_width = cell->getParam(ID(WIDTH)).as_int();
SigSpec lut_input = cell->getPort("\\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("\\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("\\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("\\A")); SigSpec lutA_input = sigmap(lutA->getPort(ID::A));
SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); SigSpec lutA_output = sigmap(lutA->getPort(ID::Y)[0]);
int lutA_width = lutA->getParam("\\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("\\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("\\A")); SigSpec lutB_input = sigmap(lutB->getPort(ID::A));
SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); SigSpec lutB_output = sigmap(lutB->getPort(ID::Y)[0]);
int lutB_width = lutB->getParam("\\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("\\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;
@ -372,7 +372,7 @@ struct OptLutWorker
log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n");
else if (lutB_dlogic_inputs.size() > 0) else if (lutB_dlogic_inputs.size() > 0)
log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
else if (lutB->get_bool_attribute("\\lut_keep")) else if (lutB->get_bool_attribute(ID(lut_keep)))
log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
else else
combine_mask |= COMBINE_A; combine_mask |= COMBINE_A;
@ -380,7 +380,7 @@ struct OptLutWorker
log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n");
else if (lutA_dlogic_inputs.size() > 0) else if (lutA_dlogic_inputs.size() > 0)
log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
else if (lutA->get_bool_attribute("\\lut_keep")) else if (lutA->get_bool_attribute(ID(lut_keep)))
log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
else else
combine_mask |= COMBINE_B; combine_mask |= COMBINE_B;
@ -440,8 +440,8 @@ struct OptLutWorker
lutR_unique.insert(bit); lutR_unique.insert(bit);
} }
int lutM_width = lutM->getParam("\\WIDTH").as_int(); int lutM_width = lutM->getParam(ID(WIDTH)).as_int();
SigSpec lutM_input = sigmap(lutM->getPort("\\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++)
{ {
@ -482,13 +482,13 @@ struct OptLutWorker
lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs);
} }
log_debug(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str()); log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID(LUT)).as_string().c_str());
log_debug(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str()); log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID(LUT)).as_string().c_str());
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("\\LUT", lutM_new_table); lutM->setParam(ID(LUT), lutM_new_table);
lutM->setPort("\\A", lutM_new_inputs); lutM->setPort(ID::A, lutM_new_inputs);
lutM->setPort("\\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

@ -47,8 +47,8 @@ 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("\\S"); SigSpec sig_s = conn.at(ID(S));
SigSpec sig_b = conn.at("\\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;
@ -59,12 +59,12 @@ struct OptMergeWorker
std::sort(sb_pairs.begin(), sb_pairs.end()); std::sort(sb_pairs.begin(), sb_pairs.end());
conn["\\S"] = SigSpec(); conn[ID(S)] = SigSpec();
conn["\\B"] = SigSpec(); conn[ID::B] = SigSpec();
for (auto &it : sb_pairs) { for (auto &it : sb_pairs) {
conn["\\S"].append(it.first); conn[ID(S)].append(it.first);
conn["\\B"].append(it.second); conn[ID::B].append(it.second);
} }
} }
@ -94,32 +94,32 @@ struct OptMergeWorker
const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections(); const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections();
dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn; dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn;
if (cell->type.in("$and", "$or", "$xor", "$xnor", "$add", "$mul", if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
"$logic_and", "$logic_or", "$_AND_", "$_OR_", "$_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("\\A")) < assign_map(alt_conn.at("\\B"))) { if (assign_map(alt_conn.at(ID::A)) < assign_map(alt_conn.at(ID::B))) {
alt_conn["\\A"] = conn->at("\\B"); alt_conn[ID::A] = conn->at(ID::B);
alt_conn["\\B"] = conn->at("\\A"); alt_conn[ID::B] = conn->at(ID::A);
} }
conn = &alt_conn; conn = &alt_conn;
} else } else
if (cell->type.in("$reduce_xor", "$reduce_xnor")) { if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
alt_conn = *conn; alt_conn = *conn;
assign_map.apply(alt_conn.at("\\A")); assign_map.apply(alt_conn.at(ID::A));
alt_conn.at("\\A").sort(); alt_conn.at(ID::A).sort();
conn = &alt_conn; conn = &alt_conn;
} else } else
if (cell->type.in("$reduce_and", "$reduce_or", "$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("\\A")); assign_map.apply(alt_conn.at(ID::A));
alt_conn.at("\\A").sort_and_unify(); alt_conn.at(ID::A).sort_and_unify();
conn = &alt_conn; conn = &alt_conn;
} else } else
if (cell->type == "$pmux") { if (cell->type == ID($pmux)) {
alt_conn = *conn; alt_conn = *conn;
assign_map.apply(alt_conn.at("\\A")); assign_map.apply(alt_conn.at(ID::A));
assign_map.apply(alt_conn.at("\\B")); assign_map.apply(alt_conn.at(ID::B));
assign_map.apply(alt_conn.at("\\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;
} }
@ -189,28 +189,28 @@ struct OptMergeWorker
assign_map.apply(it.second); assign_map.apply(it.second);
} }
if (cell1->type == "$and" || cell1->type == "$or" || cell1->type == "$xor" || cell1->type == "$xnor" || cell1->type == "$add" || cell1->type == "$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 == "$logic_and" || cell1->type == "$logic_or" || cell1->type == "$_AND_" || cell1->type == "$_OR_" || cell1->type == "$_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("\\A") < conn1.at("\\B")) { if (conn1.at(ID::A) < conn1.at(ID::B)) {
RTLIL::SigSpec tmp = conn1["\\A"]; RTLIL::SigSpec tmp = conn1[ID::A];
conn1["\\A"] = conn1["\\B"]; conn1[ID::A] = conn1[ID::B];
conn1["\\B"] = tmp; conn1[ID::B] = tmp;
} }
if (conn2.at("\\A") < conn2.at("\\B")) { if (conn2.at(ID::A) < conn2.at(ID::B)) {
RTLIL::SigSpec tmp = conn2["\\A"]; RTLIL::SigSpec tmp = conn2[ID::A];
conn2["\\A"] = conn2["\\B"]; conn2[ID::A] = conn2[ID::B];
conn2["\\B"] = tmp; conn2[ID::B] = tmp;
} }
} else } else
if (cell1->type == "$reduce_xor" || cell1->type == "$reduce_xnor") { if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) {
conn1["\\A"].sort(); conn1[ID::A].sort();
conn2["\\A"].sort(); conn2[ID::A].sort();
} else } else
if (cell1->type == "$reduce_and" || cell1->type == "$reduce_or" || cell1->type == "$reduce_bool") { if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) {
conn1["\\A"].sort_and_unify(); conn1[ID::A].sort_and_unify();
conn2["\\A"].sort_and_unify(); conn2[ID::A].sort_and_unify();
} else } else
if (cell1->type == "$pmux") { if (cell1->type == ID($pmux)) {
sort_pmux_conn(conn1); sort_pmux_conn(conn1);
sort_pmux_conn(conn2); sort_pmux_conn(conn2);
} }
@ -222,9 +222,9 @@ struct OptMergeWorker
return true; return true;
} }
if (cell1->type.begins_with("$") && conn1.count("\\Q") != 0) { if (cell1->type.begins_with("$") && conn1.count(ID(Q)) != 0) {
std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort("\\Q")).to_sigbit_vector(); std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector();
std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort("\\Q")).to_sigbit_vector(); std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector();
for (size_t i = 0; i < q1.size(); i++) for (size_t i = 0; i < q1.size(); i++)
if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) { if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) {
lt = q1.at(i) < q2.at(i); lt = q1.at(i) < q2.at(i);
@ -271,24 +271,24 @@ struct OptMergeWorker
ct.setup_stdcells_mem(); ct.setup_stdcells_mem();
if (mode_nomux) { if (mode_nomux) {
ct.cell_types.erase("$mux"); ct.cell_types.erase(ID($mux));
ct.cell_types.erase("$pmux"); ct.cell_types.erase(ID($pmux));
} }
ct.cell_types.erase("$tribuf"); ct.cell_types.erase(ID($tribuf));
ct.cell_types.erase("$_TBUF_"); ct.cell_types.erase(ID($_TBUF_));
ct.cell_types.erase("$anyseq"); ct.cell_types.erase(ID($anyseq));
ct.cell_types.erase("$anyconst"); ct.cell_types.erase(ID($anyconst));
ct.cell_types.erase("$allseq"); ct.cell_types.erase(ID($allseq));
ct.cell_types.erase("$allconst"); ct.cell_types.erase(ID($allconst));
log("Finding identical cells in module `%s'.\n", module->name.c_str()); log("Finding identical cells in module `%s'.\n", module->name.c_str());
assign_map.set(module); assign_map.set(module);
dff_init_map.set(module); dff_init_map.set(module);
for (auto &it : module->wires_) for (auto &it : module->wires_)
if (it.second->attributes.count("\\init") != 0) { if (it.second->attributes.count(ID(init)) != 0) {
Const initval = it.second->attributes.at("\\init"); Const initval = it.second->attributes.at(ID(init));
for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++) for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++)
if (initval[i] == State::S0 || initval[i] == State::S1) if (initval[i] == State::S0 || initval[i] == State::S1)
dff_init_map.add(SigBit(it.second, i), initval[i]); dff_init_map.add(SigBit(it.second, i), initval[i]);

View file

@ -84,12 +84,12 @@ struct OptMuxtreeWorker
// .const_deactivated // .const_deactivated
for (auto cell : module->cells()) for (auto cell : module->cells())
{ {
if (cell->type.in("$mux", "$pmux")) if (cell->type.in(ID($mux), ID($pmux)))
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_s = cell->getPort("\\S"); RTLIL::SigSpec sig_s = cell->getPort(ID(S));
RTLIL::SigSpec sig_y = cell->getPort("\\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("\\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("\\A"); RTLIL::SigSpec sig_a = mi.cell->getPort(ID::A);
RTLIL::SigSpec sig_b = mi.cell->getPort("\\B"); RTLIL::SigSpec sig_b = mi.cell->getPort(ID::B);
RTLIL::SigSpec sig_s = mi.cell->getPort("\\S"); RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S));
RTLIL::SigSpec sig_y = mi.cell->getPort("\\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,14 +255,14 @@ struct OptMuxtreeWorker
} }
} }
mi.cell->setPort("\\A", new_sig_a); mi.cell->setPort(ID::A, new_sig_a);
mi.cell->setPort("\\B", new_sig_b); mi.cell->setPort(ID::B, new_sig_b);
mi.cell->setPort("\\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 = "$mux"; mi.cell->type = ID($mux);
mi.cell->parameters.erase("\\S_WIDTH"); mi.cell->parameters.erase(ID(S_WIDTH));
} else { } else {
mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(GetSize(new_sig_s)); mi.cell->parameters[ID(S_WIDTH)] = RTLIL::Const(GetSize(new_sig_s));
} }
} }
} }
@ -364,9 +364,9 @@ struct OptMuxtreeWorker
int width = 0; int width = 0;
idict<int> ctrl_bits; idict<int> ctrl_bits;
if (portname == "\\B") if (portname == ID::B)
width = GetSize(muxinfo.cell->getPort("\\A")); width = GetSize(muxinfo.cell->getPort(ID::A));
for (int bit : sig2bits(muxinfo.cell->getPort("\\S"), false)) for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false))
ctrl_bits(bit); ctrl_bits(bit);
int port_idx = 0, port_off = 0; int port_idx = 0, port_off = 0;
@ -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, "\\A"); replace_known(knowledge, muxinfo, ID::A);
replace_known(knowledge, muxinfo, "\\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,13 +43,13 @@ struct OptReduceWorker
return; return;
cells.erase(cell); cells.erase(cell);
RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\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())
{ {
if (bit == RTLIL::State::S0) { if (bit == RTLIL::State::S0) {
if (cell->type == "$reduce_and") { if (cell->type == ID($reduce_and)) {
new_sig_a_bits.clear(); new_sig_a_bits.clear();
new_sig_a_bits.insert(RTLIL::State::S0); new_sig_a_bits.insert(RTLIL::State::S0);
break; break;
@ -57,7 +57,7 @@ struct OptReduceWorker
continue; continue;
} }
if (bit == RTLIL::State::S1) { if (bit == RTLIL::State::S1) {
if (cell->type == "$reduce_or") { if (cell->type == ID($reduce_or)) {
new_sig_a_bits.clear(); new_sig_a_bits.clear();
new_sig_a_bits.insert(RTLIL::State::S1); new_sig_a_bits.insert(RTLIL::State::S1);
break; break;
@ -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("\\Y")[0] == bit) { if (child_cell->getPort(ID::Y)[0] == bit) {
pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort("\\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,22 +87,22 @@ 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("\\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("\\A", new_sig_a); cell->setPort(ID::A, new_sig_a);
cell->parameters["\\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("\\A")); RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
RTLIL::SigSpec sig_s = assign_map(cell->getPort("\\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;
pool<RTLIL::SigSpec> handled_sig; pool<RTLIL::SigSpec> handled_sig;
@ -123,15 +123,15 @@ struct OptReduceWorker
if (this_s.size() > 1) if (this_s.size() > 1)
{ {
RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, "$reduce_or"); RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or));
reduce_or_cell->setPort("\\A", this_s); reduce_or_cell->setPort(ID::A, this_s);
reduce_or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0);
reduce_or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(this_s.size()); reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size());
reduce_or_cell->parameters["\\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("\\Y", this_s); reduce_or_cell->setPort(ID::Y, this_s);
} }
new_sig_b.append(this_b); new_sig_b.append(this_b);
@ -147,28 +147,28 @@ struct OptReduceWorker
if (new_sig_s.size() == 0) if (new_sig_s.size() == 0)
{ {
module->connect(RTLIL::SigSig(cell->getPort("\\Y"), cell->getPort("\\A"))); module->connect(RTLIL::SigSig(cell->getPort(ID::Y), cell->getPort(ID::A)));
assign_map.add(cell->getPort("\\Y"), cell->getPort("\\A")); assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A));
module->remove(cell); module->remove(cell);
} }
else else
{ {
cell->setPort("\\B", new_sig_b); cell->setPort(ID::B, new_sig_b);
cell->setPort("\\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["\\S_WIDTH"] = RTLIL::Const(new_sig_s.size()); cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size());
} else { } else {
cell->type = "$mux"; cell->type = ID($mux);
cell->parameters.erase("\\S_WIDTH"); cell->parameters.erase(ID(S_WIDTH));
} }
} }
} }
void opt_mux_bits(RTLIL::Cell *cell) void opt_mux_bits(RTLIL::Cell *cell)
{ {
std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort("\\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("\\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("\\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("\\A")), log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y"))); log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
cell->setPort("\\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("\\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("\\A", new_a); cell->setPort(ID::A, new_a);
} }
cell->setPort("\\B", RTLIL::SigSpec()); cell->setPort(ID::B, RTLIL::SigSpec());
for (int i = 1; i <= cell->getPort("\\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("\\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("\\B", new_b); cell->setPort(ID::B, new_b);
} }
cell->parameters["\\WIDTH"] = RTLIL::Const(new_sig_y.size()); cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size());
cell->setPort("\\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("\\A")), log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\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);
@ -253,15 +253,15 @@ struct OptReduceWorker
SigPool mem_wren_sigs; SigPool mem_wren_sigs;
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 == "$mem") if (cell->type == ID($mem))
mem_wren_sigs.add(assign_map(cell->getPort("\\WR_EN"))); mem_wren_sigs.add(assign_map(cell->getPort(ID(WR_EN))));
if (cell->type == "$memwr") if (cell->type == ID($memwr))
mem_wren_sigs.add(assign_map(cell->getPort("\\EN"))); mem_wren_sigs.add(assign_map(cell->getPort(ID(EN))));
} }
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 == "$dff" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Q")))) if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Q)))))
mem_wren_sigs.add(assign_map(cell->getPort("\\D"))); mem_wren_sigs.add(assign_map(cell->getPort(ID(D))));
} }
bool keep_expanding_mem_wren_sigs = true; bool keep_expanding_mem_wren_sigs = true;
@ -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 == "$mux" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\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("\\A"))) || if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID::A))) ||
!mem_wren_sigs.check_all(assign_map(cell->getPort("\\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("\\A"))); mem_wren_sigs.add(assign_map(cell->getPort(ID::A)));
mem_wren_sigs.add(assign_map(cell->getPort("\\B"))); mem_wren_sigs.add(assign_map(cell->getPort(ID::B)));
} }
} }
} }
@ -286,7 +286,7 @@ struct OptReduceWorker
// merge trees of reduce_* cells to one single cell and unify input vectors // merge trees of reduce_* cells to one single cell and unify input vectors
// (only handle reduce_and and reduce_or for various reasons) // (only handle reduce_and and reduce_or for various reasons)
const char *type_list[] = { "$reduce_or", "$reduce_and" }; const IdString type_list[] = { ID($reduce_or), ID($reduce_and) };
for (auto type : type_list) for (auto type : type_list)
{ {
SigSet<RTLIL::Cell*> drivers; SigSet<RTLIL::Cell*> drivers;
@ -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("\\Y")), cell); drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
cells.insert(cell); cells.insert(cell);
} }
@ -311,14 +311,14 @@ struct OptReduceWorker
std::vector<RTLIL::Cell*> cells; std::vector<RTLIL::Cell*> cells;
for (auto &it : module->cells_) for (auto &it : module->cells_)
if ((it.second->type == "$mux" || it.second->type == "$pmux") && design->selected(module, it.second)) if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second))
cells.push_back(it.second); cells.push_back(it.second);
for (auto cell : cells) for (auto cell : cells)
{ {
// 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("\\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

@ -41,7 +41,7 @@ void remove_init_attr(SigSpec sig)
for (auto bit : assign_map(sig)) for (auto bit : assign_map(sig))
if (init_attributes.count(bit)) if (init_attributes.count(bit))
for (auto wbit : init_attributes.at(bit)) for (auto wbit : init_attributes.at(bit))
wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx; wbit.wire->attributes.at(ID(init))[wbit.offset] = State::Sx;
} }
bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
@ -49,17 +49,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
SigSpec sig_set, sig_clr; SigSpec sig_set, sig_clr;
State pol_set, pol_clr; State pol_set, pol_clr;
if (cell->hasPort("\\S")) if (cell->hasPort(ID(S)))
sig_set = cell->getPort("\\S"); sig_set = cell->getPort(ID(S));
if (cell->hasPort("\\R")) if (cell->hasPort(ID(R)))
sig_clr = cell->getPort("\\R"); sig_clr = cell->getPort(ID(R));
if (cell->hasPort("\\SET")) if (cell->hasPort(ID(SET)))
sig_set = cell->getPort("\\SET"); sig_set = cell->getPort(ID(SET));
if (cell->hasPort("\\CLR")) if (cell->hasPort(ID(CLR)))
sig_clr = cell->getPort("\\CLR"); sig_clr = cell->getPort(ID(CLR));
log_assert(GetSize(sig_set) == GetSize(sig_clr)); log_assert(GetSize(sig_set) == GetSize(sig_clr));
@ -71,17 +71,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
pol_set = cell->type[12] == 'P' ? State::S1 : State::S0; pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0; pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
} else } else
if (cell->type.in("$dffsr", "$dlatchsr")) { if (cell->type.in(ID($dffsr), ID($dlatchsr))) {
pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0; pol_set = cell->parameters[ID(SET_POLARITY)].as_bool() ? State::S1 : State::S0;
pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0; pol_clr = cell->parameters[ID(CLR_POLARITY)].as_bool() ? State::S1 : State::S0;
} else } else
log_abort(); log_abort();
State npol_set = pol_set == State::S0 ? State::S1 : State::S0; State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0; State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;
SigSpec sig_d = cell->getPort("\\D"); SigSpec sig_d = cell->getPort(ID(D));
SigSpec sig_q = cell->getPort("\\Q"); SigSpec sig_q = cell->getPort(ID(Q));
bool did_something = false; bool did_something = false;
bool proper_sr = false; bool proper_sr = false;
@ -137,20 +137,20 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
return true; return true;
} }
if (cell->type.in("$dffsr", "$dlatchsr")) if (cell->type.in(ID($dffsr), ID($dlatchsr)))
{ {
cell->setParam("\\WIDTH", GetSize(sig_d)); cell->setParam(ID(WIDTH), GetSize(sig_d));
cell->setPort("\\SET", sig_set); cell->setPort(ID(SET), sig_set);
cell->setPort("\\CLR", sig_clr); cell->setPort(ID(CLR), sig_clr);
cell->setPort("\\D", sig_d); cell->setPort(ID(D), sig_d);
cell->setPort("\\Q", sig_q); cell->setPort(ID(Q), sig_q);
} }
else else
{ {
cell->setPort("\\S", sig_set); cell->setPort(ID(S), sig_set);
cell->setPort("\\R", sig_clr); cell->setPort(ID(R), sig_clr);
cell->setPort("\\D", sig_d); cell->setPort(ID(D), sig_d);
cell->setPort("\\Q", sig_q); cell->setPort(ID(Q), sig_q);
} }
if (proper_sr) if (proper_sr)
@ -159,36 +159,36 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
if (used_pol_set && used_pol_clr && pol_set != pol_clr) if (used_pol_set && used_pol_clr && pol_set != pol_clr)
return did_something; return did_something;
if (cell->type == "$dlatchsr") if (cell->type == ID($dlatchsr))
return did_something; return did_something;
State unified_pol = used_pol_set ? pol_set : pol_clr; State unified_pol = used_pol_set ? pol_set : pol_clr;
if (cell->type == "$dffsr") if (cell->type == ID($dffsr))
{ {
if (hasreset) if (hasreset)
{ {
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod)); log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));
cell->type = "$adff"; cell->type = ID($adff);
cell->setParam("\\ARST_POLARITY", unified_pol); cell->setParam(ID(ARST_POLARITY), unified_pol);
cell->setParam("\\ARST_VALUE", reset_val); cell->setParam(ID(ARST_VALUE), reset_val);
cell->setPort("\\ARST", sig_reset); cell->setPort(ID(ARST), sig_reset);
cell->unsetParam("\\SET_POLARITY"); cell->unsetParam(ID(SET_POLARITY));
cell->unsetParam("\\CLR_POLARITY"); cell->unsetParam(ID(CLR_POLARITY));
cell->unsetPort("\\SET"); cell->unsetPort(ID(SET));
cell->unsetPort("\\CLR"); cell->unsetPort(ID(CLR));
} }
else else
{ {
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod)); log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod));
cell->type = "$dff"; cell->type = ID($dff);
cell->unsetParam("\\SET_POLARITY"); cell->unsetParam(ID(SET_POLARITY));
cell->unsetParam("\\CLR_POLARITY"); cell->unsetParam(ID(CLR_POLARITY));
cell->unsetPort("\\SET"); cell->unsetPort(ID(SET));
cell->unsetPort("\\CLR"); cell->unsetPort(ID(CLR));
} }
return true; return true;
@ -208,8 +208,8 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod)); log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod));
cell->type = new_type; cell->type = new_type;
cell->unsetPort("\\S"); cell->unsetPort(ID(S));
cell->unsetPort("\\R"); cell->unsetPort(ID(R));
return true; return true;
} }
@ -222,18 +222,18 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
SigSpec sig_e; SigSpec sig_e;
State on_state, off_state; State on_state, off_state;
if (dlatch->type == "$dlatch") { if (dlatch->type == ID($dlatch)) {
sig_e = assign_map(dlatch->getPort("\\EN")); sig_e = assign_map(dlatch->getPort(ID(EN)));
on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0; on_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S1 : State::S0;
off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1; off_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S0 : State::S1;
} else } else
if (dlatch->type == "$_DLATCH_P_") { if (dlatch->type == ID($_DLATCH_P_)) {
sig_e = assign_map(dlatch->getPort("\\E")); sig_e = assign_map(dlatch->getPort(ID(E)));
on_state = State::S1; on_state = State::S1;
off_state = State::S0; off_state = State::S0;
} else } else
if (dlatch->type == "$_DLATCH_N_") { if (dlatch->type == ID($_DLATCH_N_)) {
sig_e = assign_map(dlatch->getPort("\\E")); sig_e = assign_map(dlatch->getPort(ID(E)));
on_state = State::S0; on_state = State::S0;
off_state = State::S1; off_state = State::S1;
} else } else
@ -242,15 +242,15 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
if (sig_e == off_state) if (sig_e == off_state)
{ {
RTLIL::Const val_init; RTLIL::Const val_init;
for (auto bit : dff_init_map(dlatch->getPort("\\Q"))) for (auto bit : dff_init_map(dlatch->getPort(ID(Q))))
val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx); val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx);
mod->connect(dlatch->getPort("\\Q"), val_init); mod->connect(dlatch->getPort(ID(Q)), val_init);
goto delete_dlatch; goto delete_dlatch;
} }
if (sig_e == on_state) if (sig_e == on_state)
{ {
mod->connect(dlatch->getPort("\\Q"), dlatch->getPort("\\D")); mod->connect(dlatch->getPort(ID(Q)), dlatch->getPort(ID(D)));
goto delete_dlatch; goto delete_dlatch;
} }
@ -258,7 +258,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
delete_dlatch: delete_dlatch:
log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod)); log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod));
remove_init_attr(dlatch->getPort("\\Q")); remove_init_attr(dlatch->getPort(ID(Q)));
mod->remove(dlatch); mod->remove(dlatch);
return true; return true;
} }
@ -268,24 +268,24 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
RTLIL::Const val_cp, val_rp, val_rv, val_ep; RTLIL::Const val_cp, val_rp, val_rv, val_ep;
if (dff->type == "$_FF_") { if (dff->type == ID($_FF_)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
} }
else if (dff->type == "$_DFF_N_" || dff->type == "$_DFF_P_") { else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\C"); sig_c = dff->getPort(ID(C));
val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1); val_cp = RTLIL::Const(dff->type == ID($_DFF_P_), 1);
} }
else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 && else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 &&
(dff->type[6] == 'N' || dff->type[6] == 'P') && (dff->type[6] == 'N' || dff->type[6] == 'P') &&
(dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == '0' || dff->type[8] == '1')) { (dff->type[8] == '0' || dff->type[8] == '1')) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\C"); sig_c = dff->getPort(ID(C));
sig_r = dff->getPort("\\R"); sig_r = dff->getPort(ID(R));
val_cp = RTLIL::Const(dff->type[6] == 'P', 1); val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
val_rv = RTLIL::Const(dff->type[8] == '1', 1); val_rv = RTLIL::Const(dff->type[8] == '1', 1);
@ -293,39 +293,39 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 && else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 &&
(dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == 'N' || dff->type[8] == 'P')) { (dff->type[8] == 'N' || dff->type[8] == 'P')) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\C"); sig_c = dff->getPort(ID(C));
sig_e = dff->getPort("\\E"); sig_e = dff->getPort(ID(E));
val_cp = RTLIL::Const(dff->type[7] == 'P', 1); val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
val_ep = RTLIL::Const(dff->type[8] == 'P', 1); val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
} }
else if (dff->type == "$ff") { else if (dff->type == ID($ff)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
} }
else if (dff->type == "$dff") { else if (dff->type == ID($dff)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\CLK"); sig_c = dff->getPort(ID(CLK));
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
} }
else if (dff->type == "$dffe") { else if (dff->type == ID($dffe)) {
sig_e = dff->getPort("\\EN"); sig_e = dff->getPort(ID(EN));
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\CLK"); sig_c = dff->getPort(ID(CLK));
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1); val_ep = RTLIL::Const(dff->parameters[ID(EN_POLARITY)].as_bool(), 1);
} }
else if (dff->type == "$adff") { else if (dff->type == ID($adff)) {
sig_d = dff->getPort("\\D"); sig_d = dff->getPort(ID(D));
sig_q = dff->getPort("\\Q"); sig_q = dff->getPort(ID(Q));
sig_c = dff->getPort("\\CLK"); sig_c = dff->getPort(ID(CLK));
sig_r = dff->getPort("\\ARST"); sig_r = dff->getPort(ID(ARST));
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
val_rp = RTLIL::Const(dff->parameters["\\ARST_POLARITY"].as_bool(), 1); val_rp = RTLIL::Const(dff->parameters[ID(ARST_POLARITY)].as_bool(), 1);
val_rv = dff->parameters["\\ARST_VALUE"]; val_rv = dff->parameters[ID(ARST_VALUE)];
} }
else else
log_abort(); log_abort();
@ -343,12 +343,12 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
} }
if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) { if (dff->type.in(ID($ff), ID($dff)) && mux_drivers.has(sig_d)) {
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("\\A")); RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(mux->getPort("\\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;
@ -420,17 +420,17 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
log("Removing unused reset from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); log("Removing unused reset from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
if (dff->type == "$adff") { if (dff->type == ID($adff)) {
dff->type = "$dff"; dff->type = ID($dff);
dff->unsetPort("\\ARST"); dff->unsetPort(ID(ARST));
dff->unsetParam("\\ARST_POLARITY"); dff->unsetParam(ID(ARST_POLARITY));
dff->unsetParam("\\ARST_VALUE"); dff->unsetParam(ID(ARST_VALUE));
return true; return true;
} }
log_assert(dff->type.begins_with("$_DFF_")); log_assert(dff->type.begins_with("$_DFF_"));
dff->type = stringf("$_DFF_%c_", + dff->type[6]); dff->type = stringf("$_DFF_%c_", + dff->type[6]);
dff->unsetPort("\\R"); dff->unsetPort(ID(R));
} }
// If enable signal is present, and is fully constant // If enable signal is present, and is fully constant
@ -445,16 +445,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
if (dff->type == "$dffe") { if (dff->type == ID($dffe)) {
dff->type = "$dff"; dff->type = ID($dff);
dff->unsetPort("\\EN"); dff->unsetPort(ID(EN));
dff->unsetParam("\\EN_POLARITY"); dff->unsetParam(ID(EN_POLARITY));
return true; return true;
} }
log_assert(dff->type.begins_with("$_DFFE_")); log_assert(dff->type.begins_with("$_DFFE_"));
dff->type = stringf("$_DFF_%c_", + dff->type[7]); dff->type = stringf("$_DFF_%c_", + dff->type[7]);
dff->unsetPort("\\E"); dff->unsetPort(ID(E));
} }
if (sat && has_init && (!sig_r.size() || val_init == val_rv)) if (sat && has_init && (!sig_r.size() || val_init == val_rv))
@ -509,9 +509,9 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0, log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0,
position, log_id(dff), log_id(dff->type), log_id(mod)); position, log_id(dff), log_id(dff->type), log_id(mod));
SigSpec tmp = dff->getPort("\\D"); SigSpec tmp = dff->getPort(ID(D));
tmp[position] = sigbit_init_val; tmp[position] = sigbit_init_val;
dff->setPort("\\D", tmp); dff->setPort(ID(D), tmp);
removed_sigbits = true; removed_sigbits = true;
} }
@ -528,7 +528,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
delete_dff: delete_dff:
log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
remove_init_attr(dff->getPort("\\Q")); remove_init_attr(dff->getPort(ID(Q)));
mod->remove(dff); mod->remove(dff);
for (auto &entry : bit2driver) for (auto &entry : bit2driver)
@ -588,8 +588,8 @@ struct OptRmdffPass : public Pass {
for (auto wire : module->wires()) for (auto wire : module->wires())
{ {
if (wire->attributes.count("\\init") != 0) { if (wire->attributes.count(ID(init)) != 0) {
Const initval = wire->attributes.at("\\init"); Const initval = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++)
if (initval[i] == State::S0 || initval[i] == State::S1) if (initval[i] == State::S0 || initval[i] == State::S1)
dff_init_map.add(SigBit(wire, i), initval[i]); dff_init_map.add(SigBit(wire, i), initval[i]);
@ -624,29 +624,29 @@ struct OptRmdffPass : public Pass {
} }
} }
if (cell->type.in("$mux", "$pmux")) { if (cell->type.in(ID($mux), ID($pmux))) {
if (cell->getPort("\\A").size() == cell->getPort("\\B").size()) if (cell->getPort(ID::A).size() == cell->getPort(ID::B).size())
mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell); mux_drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
continue; continue;
} }
if (!design->selected(module, cell)) if (!design->selected(module, cell))
continue; continue;
if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_", if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr", ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), ID($dffsr),
"$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_", ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
"$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr")) ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($dlatchsr)))
dffsr_list.push_back(cell->name); dffsr_list.push_back(cell->name);
if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_", if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_),
"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
"$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_", ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
"$ff", "$dff", "$dffe", "$adff")) ID($ff), ID($dff), ID($dffe), ID($adff)))
dff_list.push_back(cell->name); dff_list.push_back(cell->name);
if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_")) if (cell->type.in(ID($dlatch), ID($_DLATCH_P_), ID($_DLATCH_N_)))
dlatch_list.push_back(cell->name); dlatch_list.push_back(cell->name);
} }

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

@ -46,7 +46,7 @@ struct OnehotDatabase
for (auto wire : module->wires()) for (auto wire : module->wires())
{ {
auto it = wire->attributes.find("\\init"); auto it = wire->attributes.find(ID(init));
if (it == wire->attributes.end()) if (it == wire->attributes.end())
continue; continue;
@ -63,19 +63,19 @@ struct OnehotDatabase
vector<SigSpec> inputs; vector<SigSpec> inputs;
SigSpec output; SigSpec output;
if (cell->type.in("$adff", "$dff", "$dffe", "$dlatch", "$ff")) if (cell->type.in(ID($adff), ID($dff), ID($dffe), ID($dlatch), ID($ff)))
{ {
output = cell->getPort("\\Q"); output = cell->getPort(ID(Q));
if (cell->type == "$adff") if (cell->type == ID($adff))
inputs.push_back(cell->getParam("\\ARST_VALUE")); inputs.push_back(cell->getParam(ID(ARST_VALUE)));
inputs.push_back(cell->getPort("\\D")); inputs.push_back(cell->getPort(ID(D)));
} }
if (cell->type.in("$mux", "$pmux")) if (cell->type.in(ID($mux), ID($pmux)))
{ {
output = cell->getPort("\\Y"); output = cell->getPort(ID::Y);
inputs.push_back(cell->getPort("\\A")); inputs.push_back(cell->getPort(ID::A));
SigSpec B = cell->getPort("\\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)));
} }
@ -292,23 +292,23 @@ struct Pmux2ShiftxPass : public Pass {
for (auto cell : module->cells()) for (auto cell : module->cells())
{ {
if (cell->type == "$eq") if (cell->type == ID($eq))
{ {
dict<SigBit, State> bits; dict<SigBit, State> bits;
SigSpec A = sigmap(cell->getPort("\\A")); SigSpec A = sigmap(cell->getPort(ID::A));
SigSpec B = sigmap(cell->getPort("\\B")); SigSpec B = sigmap(cell->getPort(ID::B));
int a_width = cell->getParam("\\A_WIDTH").as_int(); int a_width = cell->getParam(ID(A_WIDTH)).as_int();
int b_width = cell->getParam("\\B_WIDTH").as_int(); int b_width = cell->getParam(ID(B_WIDTH)).as_int();
if (a_width < b_width) { if (a_width < b_width) {
bool a_signed = cell->getParam("\\A_SIGNED").as_int(); bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
A.extend_u0(b_width, a_signed); A.extend_u0(b_width, a_signed);
} }
if (b_width < a_width) { if (b_width < a_width) {
bool b_signed = cell->getParam("\\B_SIGNED").as_int(); bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
B.extend_u0(a_width, b_signed); B.extend_u0(a_width, b_signed);
} }
@ -335,15 +335,15 @@ struct Pmux2ShiftxPass : public Pass {
entry.second.bits.push_back(it.second); entry.second.bits.push_back(it.second);
} }
eqdb[sigmap(cell->getPort("\\Y")[0])] = entry; eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry;
goto next_cell; goto next_cell;
} }
if (cell->type == "$logic_not") if (cell->type == ID($logic_not))
{ {
dict<SigBit, State> bits; dict<SigBit, State> bits;
SigSpec A = sigmap(cell->getPort("\\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("\\Y")[0])] = entry; eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry;
goto next_cell; goto next_cell;
} }
next_cell:; next_cell:;
@ -364,11 +364,11 @@ struct Pmux2ShiftxPass : public Pass {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type != "$pmux") if (cell->type != ID($pmux))
continue; continue;
string src = cell->get_src_attribute(); string src = cell->get_src_attribute();
int width = cell->getParam("\\WIDTH").as_int(); int width = cell->getParam(ID(WIDTH)).as_int();
int width_bits = ceil_log2(width); int width_bits = ceil_log2(width);
int extwidth = width; int extwidth = width;
@ -377,9 +377,9 @@ struct Pmux2ShiftxPass : public Pass {
dict<SigSpec, pool<int>> seldb; dict<SigSpec, pool<int>> seldb;
SigSpec A = cell->getPort("\\A"); SigSpec A = cell->getPort(ID::A);
SigSpec B = cell->getPort("\\B"); SigSpec B = cell->getPort(ID::B);
SigSpec S = sigmap(cell->getPort("\\S")); SigSpec S = sigmap(cell->getPort(ID(S)));
for (int i = 0; i < GetSize(S); i++) for (int i = 0; i < GetSize(S); i++)
{ {
if (!eqdb.count(S[i])) if (!eqdb.count(S[i]))
@ -400,8 +400,8 @@ struct Pmux2ShiftxPass : public Pass {
log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits);
} }
SigSpec updated_S = cell->getPort("\\S"); SigSpec updated_S = cell->getPort(ID(S));
SigSpec updated_B = cell->getPort("\\B"); SigSpec updated_B = cell->getPort(ID::B);
while (!seldb.empty()) while (!seldb.empty())
{ {
@ -727,9 +727,9 @@ struct Pmux2ShiftxPass : public Pass {
} }
// update $pmux cell // update $pmux cell
cell->setPort("\\S", updated_S); cell->setPort(ID(S), updated_S);
cell->setPort("\\B", updated_B); cell->setPort(ID::B, updated_B);
cell->setParam("\\S_WIDTH", GetSize(updated_S)); cell->setParam(ID(S_WIDTH), GetSize(updated_S));
} }
} }
} }
@ -779,22 +779,22 @@ struct OnehotPass : public Pass {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type != "$eq") if (cell->type != ID($eq))
continue; continue;
SigSpec A = sigmap(cell->getPort("\\A")); SigSpec A = sigmap(cell->getPort(ID::A));
SigSpec B = sigmap(cell->getPort("\\B")); SigSpec B = sigmap(cell->getPort(ID::B));
int a_width = cell->getParam("\\A_WIDTH").as_int(); int a_width = cell->getParam(ID(A_WIDTH)).as_int();
int b_width = cell->getParam("\\B_WIDTH").as_int(); int b_width = cell->getParam(ID(B_WIDTH)).as_int();
if (a_width < b_width) { if (a_width < b_width) {
bool a_signed = cell->getParam("\\A_SIGNED").as_int(); bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
A.extend_u0(b_width, a_signed); A.extend_u0(b_width, a_signed);
} }
if (b_width < a_width) { if (b_width < a_width) {
bool b_signed = cell->getParam("\\B_SIGNED").as_int(); bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
B.extend_u0(a_width, b_signed); B.extend_u0(a_width, b_signed);
} }
@ -830,7 +830,7 @@ struct OnehotPass : public Pass {
continue; continue;
} }
SigSpec Y = cell->getPort("\\Y"); SigSpec Y = cell->getPort(ID::Y);
if (not_onehot) if (not_onehot)
{ {

View file

@ -89,8 +89,8 @@ struct ShareWorker
queue_bits.clear(); queue_bits.clear();
for (auto &pbit : portbits) { for (auto &pbit : portbits) {
if (pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") { if (pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) {
pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort("\\S")).to_sigbit_pool(); pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort(ID(S))).to_sigbit_pool();
terminal_bits.insert(bits.begin(), bits.end()); terminal_bits.insert(bits.begin(), bits.end());
queue_bits.insert(bits.begin(), bits.end()); queue_bits.insert(bits.begin(), bits.end());
visited_cells.insert(pbit.cell); visited_cells.insert(pbit.cell);
@ -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("\\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("\\Y")), w2 = GetSize(c2->getPort("\\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("\\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("\\Y"))); supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID::Y)));
supercell->setParam("\\Y_WIDTH", width); supercell->setParam(ID(Y_WIDTH), width);
supercell->setPort("\\Y", sig_y); supercell->setPort(ID::Y, sig_y);
supermacc.optimize(width); supermacc.optimize(width);
supermacc.to_cell(supercell); supermacc.to_cell(supercell);
@ -368,22 +368,22 @@ struct ShareWorker
continue; continue;
} }
if (cell->type == "$memrd") { if (cell->type == ID($memrd)) {
if (cell->parameters.at("\\CLK_ENABLE").as_bool()) if (cell->parameters.at(ID(CLK_ENABLE)).as_bool())
continue; continue;
if (config.opt_aggressive || !modwalker.sigmap(cell->getPort("\\ADDR")).is_fully_const()) if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID(ADDR))).is_fully_const())
shareable_cells.insert(cell); shareable_cells.insert(cell);
continue; continue;
} }
if (cell->type.in("$mul", "$div", "$mod")) { if (cell->type.in(ID($mul), ID($div), ID($mod))) {
if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 4) if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 4)
shareable_cells.insert(cell); shareable_cells.insert(cell);
continue; continue;
} }
if (cell->type.in("$shl", "$shr", "$sshl", "$sshr")) { if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 8) if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 8)
shareable_cells.insert(cell); shareable_cells.insert(cell);
continue; continue;
} }
@ -401,9 +401,9 @@ struct ShareWorker
if (c1->type != c2->type) if (c1->type != c2->type)
return false; return false;
if (c1->type == "$memrd") if (c1->type == ID($memrd))
{ {
if (c1->parameters.at("\\MEMID").decode_string() != c2->parameters.at("\\MEMID").decode_string()) if (c1->parameters.at(ID(MEMID)).decode_string() != c2->parameters.at(ID(MEMID)).decode_string())
return false; return false;
return true; return true;
@ -413,11 +413,11 @@ struct ShareWorker
{ {
if (!config.opt_aggressive) if (!config.opt_aggressive)
{ {
int a1_width = c1->parameters.at("\\A_WIDTH").as_int(); int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
int y1_width = c1->parameters.at("\\Y_WIDTH").as_int(); int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
int a2_width = c2->parameters.at("\\A_WIDTH").as_int(); int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
int y2_width = c2->parameters.at("\\Y_WIDTH").as_int(); int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false; if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
if (max(y1_width, y2_width) > 2 * min(y1_width, y2_width)) return false; if (max(y1_width, y2_width) > 2 * min(y1_width, y2_width)) return false;
@ -426,17 +426,17 @@ struct ShareWorker
return true; return true;
} }
if (config.generic_bin_ops.count(c1->type) || c1->type == "$alu") if (config.generic_bin_ops.count(c1->type) || c1->type == ID($alu))
{ {
if (!config.opt_aggressive) if (!config.opt_aggressive)
{ {
int a1_width = c1->parameters.at("\\A_WIDTH").as_int(); int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
int b1_width = c1->parameters.at("\\B_WIDTH").as_int(); int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
int y1_width = c1->parameters.at("\\Y_WIDTH").as_int(); int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
int a2_width = c2->parameters.at("\\A_WIDTH").as_int(); int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
int b2_width = c2->parameters.at("\\B_WIDTH").as_int(); int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
int y2_width = c2->parameters.at("\\Y_WIDTH").as_int(); int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false; if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
if (max(b1_width, b2_width) > 2 * min(b1_width, b2_width)) return false; if (max(b1_width, b2_width) > 2 * min(b1_width, b2_width)) return false;
@ -450,13 +450,13 @@ struct ShareWorker
{ {
if (!config.opt_aggressive) if (!config.opt_aggressive)
{ {
int a1_width = c1->parameters.at("\\A_WIDTH").as_int(); int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
int b1_width = c1->parameters.at("\\B_WIDTH").as_int(); int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
int y1_width = c1->parameters.at("\\Y_WIDTH").as_int(); int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
int a2_width = c2->parameters.at("\\A_WIDTH").as_int(); int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
int b2_width = c2->parameters.at("\\B_WIDTH").as_int(); int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
int y2_width = c2->parameters.at("\\Y_WIDTH").as_int(); int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
int min1_width = min(a1_width, b1_width); int min1_width = min(a1_width, b1_width);
int max1_width = max(a1_width, b1_width); int max1_width = max(a1_width, b1_width);
@ -472,7 +472,7 @@ struct ShareWorker
return true; return true;
} }
if (c1->type == "$macc") if (c1->type == ID($macc))
{ {
if (!config.opt_aggressive) if (!config.opt_aggressive)
if (share_macc(c1, c2) > 2 * min(bits_macc(c1), bits_macc(c2))) return false; if (share_macc(c1, c2) > 2 * min(bits_macc(c1), bits_macc(c2))) return false;
@ -510,27 +510,27 @@ struct ShareWorker
if (config.generic_uni_ops.count(c1->type)) if (config.generic_uni_ops.count(c1->type))
{ {
if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\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("\\A_SIGNED").as_bool() ? c2 : c1; RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
if (unsigned_cell->getPort("\\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("\\A_WIDTH") = unsigned_cell->parameters.at("\\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("\\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("\\A", new_a); unsigned_cell->setPort(ID::A, new_a);
} }
unsigned_cell->parameters.at("\\A_SIGNED") = true; unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
unsigned_cell->check(); unsigned_cell->check();
} }
bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool(); bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool()); log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
RTLIL::SigSpec a1 = c1->getPort("\\A"); RTLIL::SigSpec a1 = c1->getPort(ID::A);
RTLIL::SigSpec y1 = c1->getPort("\\Y"); RTLIL::SigSpec y1 = c1->getPort(ID::Y);
RTLIL::SigSpec a2 = c2->getPort("\\A"); RTLIL::SigSpec a2 = c2->getPort(ID::A);
RTLIL::SigSpec y2 = c2->getPort("\\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());
@ -544,11 +544,11 @@ struct ShareWorker
RTLIL::Wire *y = module->addWire(NEW_ID, y_width); RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
supercell->parameters["\\A_SIGNED"] = a_signed; supercell->parameters[ID(A_SIGNED)] = a_signed;
supercell->parameters["\\A_WIDTH"] = a_width; supercell->parameters[ID(A_WIDTH)] = a_width;
supercell->parameters["\\Y_WIDTH"] = y_width; supercell->parameters[ID(Y_WIDTH)] = y_width;
supercell->setPort("\\A", a); supercell->setPort(ID::A, a);
supercell->setPort("\\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));
@ -557,54 +557,54 @@ struct ShareWorker
return supercell; return supercell;
} }
if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == "$alu") if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == ID($alu))
{ {
bool modified_src_cells = false; bool modified_src_cells = false;
if (config.generic_cbin_ops.count(c1->type)) if (config.generic_cbin_ops.count(c1->type))
{ {
int score_unflipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int()) + int score_unflipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()) +
max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int()); max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int());
int score_flipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int()) + int score_flipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()) +
max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int()); max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int());
if (score_flipped < score_unflipped) if (score_flipped < score_unflipped)
{ {
RTLIL::SigSpec tmp = c2->getPort("\\A"); RTLIL::SigSpec tmp = c2->getPort(ID::A);
c2->setPort("\\A", c2->getPort("\\B")); c2->setPort(ID::A, c2->getPort(ID::B));
c2->setPort("\\B", tmp); c2->setPort(ID::B, tmp);
std::swap(c2->parameters.at("\\A_WIDTH"), c2->parameters.at("\\B_WIDTH")); std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH)));
std::swap(c2->parameters.at("\\A_SIGNED"), c2->parameters.at("\\B_SIGNED")); std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED)));
modified_src_cells = true; modified_src_cells = true;
} }
} }
if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\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("\\A_SIGNED").as_bool() ? c2 : c1; RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
if (unsigned_cell->getPort("\\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("\\A_WIDTH") = unsigned_cell->parameters.at("\\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("\\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("\\A", new_a); unsigned_cell->setPort(ID::A, new_a);
} }
unsigned_cell->parameters.at("\\A_SIGNED") = true; unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
modified_src_cells = true; modified_src_cells = true;
} }
if (c1->parameters.at("\\B_SIGNED").as_bool() != c2->parameters.at("\\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("\\B_SIGNED").as_bool() ? c2 : c1; RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1;
if (unsigned_cell->getPort("\\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("\\B_WIDTH") = unsigned_cell->parameters.at("\\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("\\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("\\B", new_b); unsigned_cell->setPort(ID::B, new_b);
} }
unsigned_cell->parameters.at("\\B_SIGNED") = true; unsigned_cell->parameters.at(ID(B_SIGNED)) = true;
modified_src_cells = true; modified_src_cells = true;
} }
@ -613,28 +613,28 @@ struct ShareWorker
c2->check(); c2->check();
} }
bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool(); bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
bool b_signed = c1->parameters.at("\\B_SIGNED").as_bool(); bool b_signed = c1->parameters.at(ID(B_SIGNED)).as_bool();
log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool()); log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
log_assert(b_signed == c2->parameters.at("\\B_SIGNED").as_bool()); log_assert(b_signed == c2->parameters.at(ID(B_SIGNED)).as_bool());
if (c1->type == "$shl" || c1->type == "$shr" || c1->type == "$sshl" || c1->type == "$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("\\A"); RTLIL::SigSpec a1 = c1->getPort(ID::A);
RTLIL::SigSpec b1 = c1->getPort("\\B"); RTLIL::SigSpec b1 = c1->getPort(ID::B);
RTLIL::SigSpec y1 = c1->getPort("\\Y"); RTLIL::SigSpec y1 = c1->getPort(ID::Y);
RTLIL::SigSpec a2 = c2->getPort("\\A"); RTLIL::SigSpec a2 = c2->getPort(ID::A);
RTLIL::SigSpec b2 = c2->getPort("\\B"); RTLIL::SigSpec b2 = c2->getPort(ID::B);
RTLIL::SigSpec y2 = c2->getPort("\\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());
int y_width = max(y1.size(), y2.size()); int y_width = max(y1.size(), y2.size());
if (c1->type == "$shr" && a_signed) if (c1->type == ID($shr) && a_signed)
{ {
a_width = max(y_width, a_width); a_width = max(y_width, a_width);
@ -660,43 +660,43 @@ struct ShareWorker
supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b)); supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b));
RTLIL::Wire *y = module->addWire(NEW_ID, y_width); RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
RTLIL::Wire *x = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr; RTLIL::Wire *x = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
RTLIL::Wire *co = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr; RTLIL::Wire *co = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
supercell->parameters["\\A_SIGNED"] = a_signed; supercell->parameters[ID(A_SIGNED)] = a_signed;
supercell->parameters["\\B_SIGNED"] = b_signed; supercell->parameters[ID(B_SIGNED)] = b_signed;
supercell->parameters["\\A_WIDTH"] = a_width; supercell->parameters[ID(A_WIDTH)] = a_width;
supercell->parameters["\\B_WIDTH"] = b_width; supercell->parameters[ID(B_WIDTH)] = b_width;
supercell->parameters["\\Y_WIDTH"] = y_width; supercell->parameters[ID(Y_WIDTH)] = y_width;
supercell->setPort("\\A", a); supercell->setPort(ID::A, a);
supercell->setPort("\\B", b); supercell->setPort(ID::B, b);
supercell->setPort("\\Y", y); supercell->setPort(ID::Y, y);
if (c1->type == "$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("\\CI"), c1->getPort("\\CI"), act, ci)); 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("\\BI"), c1->getPort("\\BI"), act, bi)); supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(BI)), c1->getPort(ID(BI)), act, bi));
supercell->setPort("\\CI", ci); supercell->setPort(ID(CI), ci);
supercell->setPort("\\BI", bi); supercell->setPort(ID(BI), bi);
supercell->setPort("\\CO", co); supercell->setPort(ID(CO), co);
supercell->setPort("\\X", x); supercell->setPort(ID(X), x);
} }
supercell->check(); supercell->check();
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));
if (c1->type == "$alu") { if (c1->type == ID($alu)) {
supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort("\\CO"))); supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort(ID(CO))));
supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort("\\CO"))); supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort(ID(CO))));
supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort("\\X"))); supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort(ID(X))));
supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort("\\X"))); supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort(ID(X))));
} }
supercell_aux.insert(supercell); supercell_aux.insert(supercell);
return supercell; return supercell;
} }
if (c1->type == "$macc") if (c1->type == ID($macc))
{ {
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
supercell_aux.insert(supercell); supercell_aux.insert(supercell);
@ -705,18 +705,18 @@ struct ShareWorker
return supercell; return supercell;
} }
if (c1->type == "$memrd") if (c1->type == ID($memrd))
{ {
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1); RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
RTLIL::SigSpec addr1 = c1->getPort("\\ADDR"); RTLIL::SigSpec addr1 = c1->getPort(ID(ADDR));
RTLIL::SigSpec addr2 = c2->getPort("\\ADDR"); RTLIL::SigSpec addr2 = c2->getPort(ID(ADDR));
if (GetSize(addr1) < GetSize(addr2)) if (GetSize(addr1) < GetSize(addr2))
addr1.extend_u0(GetSize(addr2)); addr1.extend_u0(GetSize(addr2));
else else
addr2.extend_u0(GetSize(addr1)); addr2.extend_u0(GetSize(addr1));
supercell->setPort("\\ADDR", addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1); supercell->setPort(ID(ADDR), addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
supercell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr1)); supercell->parameters[ID(ABITS)] = RTLIL::Const(GetSize(addr1));
supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA"))); supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort(ID(DATA)), c2->getPort(ID(DATA))));
supercell_aux.insert(supercell); supercell_aux.insert(supercell);
return supercell; return supercell;
} }
@ -747,8 +747,8 @@ struct ShareWorker
modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]); modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]);
for (auto &bit : pbits) { for (auto &bit : pbits) {
if ((bit.cell->type == "$mux" || bit.cell->type == "$pmux") && bit.port == "\\S") if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == ID(S))
forbidden_controls_cache[cell].insert(bit.cell->getPort("\\S").extract(bit.offset, 1)); forbidden_controls_cache[cell].insert(bit.cell->getPort(ID(S)).extract(bit.offset, 1));
consumer_cells.insert(bit.cell); consumer_cells.insert(bit.cell);
} }
@ -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 == "$mux" || pbit.cell->type == "$pmux") && (pbit.port == "\\A" || pbit.port == "\\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);
@ -890,10 +890,10 @@ struct ShareWorker
bool used_in_a = false; bool used_in_a = false;
std::set<int> used_in_b_parts; std::set<int> used_in_b_parts;
int width = c->parameters.at("\\WIDTH").as_int(); int width = c->parameters.at(ID(WIDTH)).as_int();
std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort("\\A")); std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort(ID::A));
std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort("\\B")); std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort(ID::B));
std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort("\\S")); std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort(ID(S)));
for (auto &bit : sig_a) for (auto &bit : sig_a)
if (cell_out_bits.count(bit)) if (cell_out_bits.count(bit))
@ -1132,14 +1132,14 @@ struct ShareWorker
fwd_ct.setup_internals(); fwd_ct.setup_internals();
cone_ct.setup_internals(); cone_ct.setup_internals();
cone_ct.cell_types.erase("$mul"); cone_ct.cell_types.erase(ID($mul));
cone_ct.cell_types.erase("$mod"); cone_ct.cell_types.erase(ID($mod));
cone_ct.cell_types.erase("$div"); cone_ct.cell_types.erase(ID($div));
cone_ct.cell_types.erase("$pow"); cone_ct.cell_types.erase(ID($pow));
cone_ct.cell_types.erase("$shl"); cone_ct.cell_types.erase(ID($shl));
cone_ct.cell_types.erase("$shr"); cone_ct.cell_types.erase(ID($shr));
cone_ct.cell_types.erase("$sshl"); cone_ct.cell_types.erase(ID($sshl));
cone_ct.cell_types.erase("$sshr"); cone_ct.cell_types.erase(ID($sshr));
modwalker.setup(design, module); modwalker.setup(design, module);
@ -1153,9 +1153,9 @@ struct ShareWorker
GetSize(shareable_cells), log_id(module)); GetSize(shareable_cells), log_id(module));
for (auto cell : module->cells()) for (auto cell : module->cells())
if (cell->type == "$pmux") if (cell->type == ID($pmux))
for (auto bit : cell->getPort("\\S")) for (auto bit : cell->getPort(ID(S)))
for (auto other_bit : cell->getPort("\\S")) for (auto other_bit : cell->getPort(ID(S)))
if (bit < other_bit) if (bit < other_bit)
exclusive_ctrls.push_back(std::pair<RTLIL::SigBit, RTLIL::SigBit>(bit, other_bit)); exclusive_ctrls.push_back(std::pair<RTLIL::SigBit, RTLIL::SigBit>(bit, other_bit));
@ -1466,43 +1466,43 @@ struct SharePass : public Pass {
config.opt_aggressive = false; config.opt_aggressive = false;
config.opt_fast = false; config.opt_fast = false;
config.generic_uni_ops.insert("$not"); config.generic_uni_ops.insert(ID($not));
// config.generic_uni_ops.insert("$pos"); // config.generic_uni_ops.insert(ID($pos));
config.generic_uni_ops.insert("$neg"); config.generic_uni_ops.insert(ID($neg));
config.generic_cbin_ops.insert("$and"); config.generic_cbin_ops.insert(ID($and));
config.generic_cbin_ops.insert("$or"); config.generic_cbin_ops.insert(ID($or));
config.generic_cbin_ops.insert("$xor"); config.generic_cbin_ops.insert(ID($xor));
config.generic_cbin_ops.insert("$xnor"); config.generic_cbin_ops.insert(ID($xnor));
config.generic_bin_ops.insert("$shl"); config.generic_bin_ops.insert(ID($shl));
config.generic_bin_ops.insert("$shr"); config.generic_bin_ops.insert(ID($shr));
config.generic_bin_ops.insert("$sshl"); config.generic_bin_ops.insert(ID($sshl));
config.generic_bin_ops.insert("$sshr"); config.generic_bin_ops.insert(ID($sshr));
config.generic_bin_ops.insert("$lt"); config.generic_bin_ops.insert(ID($lt));
config.generic_bin_ops.insert("$le"); config.generic_bin_ops.insert(ID($le));
config.generic_bin_ops.insert("$eq"); config.generic_bin_ops.insert(ID($eq));
config.generic_bin_ops.insert("$ne"); config.generic_bin_ops.insert(ID($ne));
config.generic_bin_ops.insert("$eqx"); config.generic_bin_ops.insert(ID($eqx));
config.generic_bin_ops.insert("$nex"); config.generic_bin_ops.insert(ID($nex));
config.generic_bin_ops.insert("$ge"); config.generic_bin_ops.insert(ID($ge));
config.generic_bin_ops.insert("$gt"); config.generic_bin_ops.insert(ID($gt));
config.generic_cbin_ops.insert("$add"); config.generic_cbin_ops.insert(ID($add));
config.generic_cbin_ops.insert("$mul"); config.generic_cbin_ops.insert(ID($mul));
config.generic_bin_ops.insert("$sub"); config.generic_bin_ops.insert(ID($sub));
config.generic_bin_ops.insert("$div"); config.generic_bin_ops.insert(ID($div));
config.generic_bin_ops.insert("$mod"); config.generic_bin_ops.insert(ID($mod));
// config.generic_bin_ops.insert("$pow"); // config.generic_bin_ops.insert(ID($pow));
config.generic_uni_ops.insert("$logic_not"); config.generic_uni_ops.insert(ID($logic_not));
config.generic_cbin_ops.insert("$logic_and"); config.generic_cbin_ops.insert(ID($logic_and));
config.generic_cbin_ops.insert("$logic_or"); config.generic_cbin_ops.insert(ID($logic_or));
config.generic_other_ops.insert("$alu"); config.generic_other_ops.insert(ID($alu));
config.generic_other_ops.insert("$macc"); config.generic_other_ops.insert(ID($macc));
log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n"); log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n");

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
@ -34,13 +33,13 @@ struct WreduceConfig
WreduceConfig() WreduceConfig()
{ {
supported_cell_types = pool<IdString>({ supported_cell_types = pool<IdString>({
"$not", "$pos", "$neg", ID($not), ID($pos), ID($neg),
"$and", "$or", "$xor", "$xnor", ID($and), ID($or), ID($xor), ID($xnor),
"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
"$add", "$sub", "$mul", // "$div", "$mod", "$pow", ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($pow),
"$mux", "$pmux", ID($mux), ID($pmux),
"$dff", "$adff" ID($dff), ID($adff)
}); });
} }
}; };
@ -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("\\A")); SigSpec sig_a = mi.sigmap(cell->getPort(ID::A));
SigSpec sig_b = mi.sigmap(cell->getPort("\\B")); SigSpec sig_b = mi.sigmap(cell->getPort(ID::B));
SigSpec sig_s = mi.sigmap(cell->getPort("\\S")); SigSpec sig_s = mi.sigmap(cell->getPort(ID(S)));
SigSpec sig_y = mi.sigmap(cell->getPort("\\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("\\A", new_sig_a); cell->setPort(ID::A, new_sig_a);
cell->setPort("\\B", new_sig_b); cell->setPort(ID::B, new_sig_b);
cell->setPort("\\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);
@ -142,8 +141,8 @@ struct WreduceWorker
{ {
// Reduce size of FF if inputs are just sign/zero extended or output bit is not used // Reduce size of FF if inputs are just sign/zero extended or output bit is not used
SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); SigSpec sig_d = mi.sigmap(cell->getPort(ID(D)));
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q)));
Const initval; Const initval;
int width_before = GetSize(sig_q); int width_before = GetSize(sig_q);
@ -214,14 +213,14 @@ struct WreduceWorker
work_queue_bits.insert(bit); work_queue_bits.insert(bit);
// Narrow ARST_VALUE parameter to new size. // Narrow ARST_VALUE parameter to new size.
if (cell->parameters.count("\\ARST_VALUE")) { if (cell->parameters.count(ID(ARST_VALUE))) {
Const arst_value = cell->getParam("\\ARST_VALUE"); Const arst_value = cell->getParam(ID(ARST_VALUE));
arst_value.bits.resize(GetSize(sig_q)); arst_value.bits.resize(GetSize(sig_q));
cell->setParam("\\ARST_VALUE", arst_value); cell->setParam(ID(ARST_VALUE), arst_value);
} }
cell->setPort("\\D", sig_d); cell->setPort(ID(D), sig_d);
cell->setPort("\\Q", sig_q); cell->setPort(ID(Q), sig_q);
cell->fixup_parameters(); cell->fixup_parameters();
} }
@ -230,7 +229,7 @@ struct WreduceWorker
port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool(); port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool();
SigSpec sig = mi.sigmap(cell->getPort(stringf("\\%c", port))); SigSpec sig = mi.sigmap(cell->getPort(stringf("\\%c", port)));
if (port == 'B' && cell->type.in("$shl", "$shr", "$sshl", "$sshr")) if (port == 'B' && cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr)))
port_signed = false; port_signed = false;
int bits_removed = 0; int bits_removed = 0;
@ -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++;
} }
@ -264,13 +263,13 @@ struct WreduceWorker
if (!cell->type.in(config->supported_cell_types)) if (!cell->type.in(config->supported_cell_types))
return; return;
if (cell->type.in("$mux", "$pmux")) if (cell->type.in(ID($mux), ID($pmux)))
return run_cell_mux(cell); return run_cell_mux(cell);
if (cell->type.in("$dff", "$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("\\Y")); SigSpec sig = mi.sigmap(cell->getPort(ID::Y));
if (sig.has_const()) if (sig.has_const())
return; return;
@ -278,10 +277,10 @@ 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("\\A") ? GetSize(cell->getPort("\\A")) : -1; int max_port_a_size = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : -1;
int max_port_b_size = cell->hasPort("\\B") ? GetSize(cell->getPort("\\B")) : -1; int max_port_b_size = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : -1;
if (cell->type.in("$not", "$pos", "$neg", "$and", "$or", "$xor", "$add", "$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));
max_port_b_size = min(max_port_b_size, GetSize(sig)); max_port_b_size = min(max_port_b_size, GetSize(sig));
} }
@ -289,32 +288,32 @@ struct WreduceWorker
bool port_a_signed = false; bool port_a_signed = false;
bool port_b_signed = false; bool port_b_signed = false;
if (max_port_a_size >= 0 && cell->type != "$shiftx") if (max_port_a_size >= 0 && cell->type != ID($shiftx))
run_reduce_inport(cell, 'A', max_port_a_size, port_a_signed, did_something); run_reduce_inport(cell, 'A', max_port_a_size, port_a_signed, did_something);
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("\\A") && cell->hasPort("\\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("\\A")), sig_b = mi.sigmap(cell->getPort("\\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",
log_id(module), log_id(cell), log_id(cell->type)); log_id(module), log_id(cell), log_id(cell->type));
cell->setParam("\\A_SIGNED", 0); cell->setParam(ID(A_SIGNED), 0);
cell->setParam("\\B_SIGNED", 0); cell->setParam(ID(B_SIGNED), 0);
port_a_signed = false; port_a_signed = false;
port_b_signed = false; port_b_signed = false;
did_something = true; did_something = true;
} }
} }
if (cell->hasPort("\\A") && !cell->hasPort("\\B") && port_a_signed) { if (cell->hasPort(ID::A) && !cell->hasPort(ID::B) && port_a_signed) {
SigSpec sig_a = mi.sigmap(cell->getPort("\\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));
cell->setParam("\\A_SIGNED", 0); cell->setParam(ID(A_SIGNED), 0);
port_a_signed = false; port_a_signed = false;
did_something = true; did_something = true;
} }
@ -324,7 +323,7 @@ struct WreduceWorker
// Reduce size of port Y based on sizes for A and B and unused bits in Y // Reduce size of port Y based on sizes for A and B and unused bits in Y
int bits_removed = 0; int bits_removed = 0;
if (port_a_signed && cell->type == "$shr") { if (port_a_signed && cell->type == ID($shr)) {
// do not reduce size of output on $shr cells with signed A inputs // do not reduce size of output on $shr cells with signed A inputs
} else { } else {
while (GetSize(sig) > 0) while (GetSize(sig) > 0)
@ -342,24 +341,24 @@ struct WreduceWorker
} }
} }
if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub")) if (cell->type.in(ID($pos), ID($add), ID($mul), ID($and), ID($or), ID($xor), ID($sub)))
{ {
bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$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("\\A")) a_size = GetSize(cell->getPort("\\A")); if (cell->hasPort(ID::A)) a_size = GetSize(cell->getPort(ID::A));
if (cell->hasPort("\\B")) b_size = GetSize(cell->getPort("\\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);
if (cell->type.in("$add", "$sub")) if (cell->type.in(ID($add), ID($sub)))
max_y_size++; max_y_size++;
if (cell->type == "$mul") if (cell->type == ID($mul))
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("\\Y", sig); cell->setPort(ID::Y, sig);
did_something = true; did_something = true;
} }
@ -387,8 +386,8 @@ struct WreduceWorker
static int count_nontrivial_wire_attrs(RTLIL::Wire *w) static int count_nontrivial_wire_attrs(RTLIL::Wire *w)
{ {
int count = w->attributes.size(); int count = w->attributes.size();
count -= w->attributes.count("\\src"); count -= w->attributes.count(ID(src));
count -= w->attributes.count("\\unused_bits"); count -= w->attributes.count(ID(unused_bits));
return count; return count;
} }
@ -398,11 +397,11 @@ 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("\\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("\\init")) { if (w->attributes.count(ID(init))) {
Const initval = w->attributes.at("\\init"); Const initval = w->attributes.at(ID(init));
SigSpec initsig = init_attr_sigmap(w); SigSpec initsig = init_attr_sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig)); int width = std::min(GetSize(initval), GetSize(initsig));
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
@ -459,8 +458,8 @@ struct WreduceWorker
if (!remove_init_bits.empty()) { if (!remove_init_bits.empty()) {
for (auto w : module->wires()) { for (auto w : module->wires()) {
if (w->attributes.count("\\init")) { if (w->attributes.count(ID(init))) {
Const initval = w->attributes.at("\\init"); Const initval = w->attributes.at(ID(init));
Const new_initval(State::Sx, GetSize(w)); Const new_initval(State::Sx, GetSize(w));
SigSpec initsig = init_attr_sigmap(w); SigSpec initsig = init_attr_sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig)); int width = std::min(GetSize(initval), GetSize(initsig));
@ -468,7 +467,7 @@ struct WreduceWorker
if (!remove_init_bits.count(initsig[i])) if (!remove_init_bits.count(initsig[i]))
new_initval[i] = initval[i]; new_initval[i] = initval[i];
} }
w->attributes.at("\\init") = new_initval; w->attributes.at(ID(init)) = new_initval;
} }
} }
} }
@ -528,23 +527,23 @@ struct WreducePass : public Pass {
for (auto c : module->selected_cells()) for (auto c : module->selected_cells())
{ {
if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
"$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) { ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID::Y)) > 1) {
SigSpec sig = c->getPort("\\Y"); SigSpec sig = c->getPort(ID::Y);
if (!sig.has_const()) { if (!sig.has_const()) {
c->setPort("\\Y", sig[0]); c->setPort(ID::Y, sig[0]);
c->setParam("\\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)));
} }
} }
if (c->type.in("$div", "$mod", "$pow")) if (c->type.in(ID($div), ID($mod), ID($pow)))
{ {
SigSpec A = c->getPort("\\A"); SigSpec A = c->getPort(ID::A);
int original_a_width = GetSize(A); int original_a_width = GetSize(A);
if (c->getParam("\\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)
A.remove(GetSize(A)-1, 1); A.remove(GetSize(A)-1, 1);
} else { } else {
@ -554,13 +553,13 @@ 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("\\A", A); c->setPort(ID::A, A);
c->setParam("\\A_WIDTH", GetSize(A)); c->setParam(ID(A_WIDTH), GetSize(A));
} }
SigSpec B = c->getPort("\\B"); SigSpec B = c->getPort(ID::B);
int original_b_width = GetSize(B); int original_b_width = GetSize(B);
if (c->getParam("\\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)
B.remove(GetSize(B)-1, 1); B.remove(GetSize(B)-1, 1);
} else { } else {
@ -570,24 +569,24 @@ 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("\\B", B); c->setPort(ID::B, B);
c->setParam("\\B_WIDTH", GetSize(B)); c->setParam(ID(B_WIDTH), GetSize(B));
} }
} }
if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) { if (!opt_memx && c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
IdString memid = c->getParam("\\MEMID").decode_string(); IdString memid = c->getParam(ID(MEMID)).decode_string();
RTLIL::Memory *mem = module->memories.at(memid); RTLIL::Memory *mem = module->memories.at(memid);
if (mem->start_offset >= 0) { if (mem->start_offset >= 0) {
int cur_addrbits = c->getParam("\\ABITS").as_int(); int cur_addrbits = c->getParam(ID(ABITS)).as_int();
int max_addrbits = ceil_log2(mem->start_offset + mem->size); int max_addrbits = ceil_log2(mem->start_offset + mem->size);
if (cur_addrbits > max_addrbits) { if (cur_addrbits > max_addrbits) {
log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n", log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n",
cur_addrbits-max_addrbits, cur_addrbits, cur_addrbits-max_addrbits, cur_addrbits,
c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init", c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init",
log_id(module), log_id(c), log_id(memid)); log_id(module), log_id(c), log_id(memid));
c->setParam("\\ABITS", max_addrbits); c->setParam(ID(ABITS), max_addrbits);
c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits)); c->setPort(ID(ADDR), c->getPort(ID(ADDR)).extract(0, max_addrbits));
} }
} }
} }

View file

@ -1,25 +1,35 @@
%_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/xilinx_dsp.o
OBJS += passes/pmgen/peepopt.o
# --------------------------------------
passes/pmgen/%.o: passes/pmgen/%_pm.h
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h $(eval $(call add_extra_objs,passes/pmgen/ice40_dsp_pm.h))
EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
EXTRA_OBJS += passes/pmgen/xilinx_dsp_pm.h
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
.SECONDARY: passes/pmgen/xilinx_dsp_pm.h
passes/pmgen/%_pm.h: passes/pmgen/pmgen.py passes/pmgen/%.pmg
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p $* $(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/xilinx_dsp.o
passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_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,48 @@ 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`.
Slices and choices
------------------
Cell matches can contain "slices" and "choices". Slices can be used to
create matches for different sections of a cell. For example:
state <int> pmux_slice
match pmux
select pmux->type == $pmux
slice idx GetSize(port(pmux, \S))
index <SigBit> port(pmux, \S)[idx] === port(eq, \Y)
set pmux_slice idx
endmatch
The first argument to `slice` is the local variable name used to identify the
slice. The second argument is the number of slices that should be created for
this cell. The `set` statement can be used to copy that index into a state
variable so that later matches and/or code blocks can refer to it.
A similar mechanism is "choices", where a list of options is given as
second argument, and the matcher will iterate over those options:
state <SigSpec> foo bar
state <IdString> eq_ab eq_ba
match eq
select eq->type == $eq
choice <IdString> AB {\A, \B}
define <IdString> BA (AB == \A ? \B : \A)
index <SigSpec> port(eq, AB) === foo
index <SigSpec> port(eq, BA) === bar
set eq_ab AB
set eq_ba BA
generate
Notice how `define` can be used to define additional local variables similar
to the loop variables defined by `slice` and `choice`.
Additional code Additional code
--------------- ---------------
@ -232,5 +274,111 @@ 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 0
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 first argument to `generate` is the chance of this generate block being
executed when the match block did not match anything, in percent.
The second argument to `generate` is the chance of this generate block being
executed when the match block did match something, in percent.
The special statement `finish` can be used within generate blocks to terminate
the current pattern matcher run.

View file

@ -265,4 +265,5 @@ code clock clock_pol sigO sigCD
sigCD.extend_u0(32, addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool()); sigCD.extend_u0(32, addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool());
} }
} }
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,21 +194,28 @@ 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*";
block["if"] = list() block["if"] = list()
block["select"] = list() block["setup"] = list()
block["index"] = list() block["index"] = list()
block["filter"] = list() block["filter"] = list()
block["sets"] = 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()
@ -183,7 +229,22 @@ def process_pmgfile(f):
if a[0] == "select": if a[0] == "select":
b = l.lstrip()[6:] b = l.lstrip()[6:]
block["select"].append(rewrite_cpp(b.strip())) block["setup"].append(("select", rewrite_cpp(b.strip())))
continue
if a[0] == "slice":
m = re.match(r"^\s*slice\s+(\S+)\s+(.*?)\s*$", l)
block["setup"].append(("slice", m.group(1), rewrite_cpp(m.group(2))))
continue
if a[0] == "choice":
m = re.match(r"^\s*choice\s+<(.*?)>\s+(\S+)\s+(.*?)\s*$", l)
block["setup"].append(("choice", m.group(1), m.group(2), rewrite_cpp(m.group(3))))
continue
if a[0] == "define":
m = re.match(r"^\s*define\s+<(.*?)>\s+(\S+)\s+(.*?)\s*$", l)
block["setup"].append(("define", m.group(1), m.group(2), rewrite_cpp(m.group(3))))
continue continue
if a[0] == "index": if a[0] == "index":
@ -197,35 +258,71 @@ def process_pmgfile(f):
block["filter"].append(rewrite_cpp(b.strip())) block["filter"].append(rewrite_cpp(b.strip()))
continue continue
if a[0] == "set":
m = re.match(r"^\s*set\s+(\S+)\s+(.*?)\s*$", l)
block["sets"].append((m.group(1), rewrite_cpp(m.group(2))))
continue
if a[0] == "optional": if a[0] == "optional":
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:]])
if len(block["genargs"]) == 0: block["genargs"].append(100)
if len(block["genargs"]) == 1: block["genargs"].append(0)
assert len(block["genargs"]) == 2
block["gencode"] = list()
while True:
linenr += 1
l = f.readline()
assert l != ""
a = l.split()
if len(a) == 1 and 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 +331,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 +360,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)):
@ -271,12 +380,21 @@ with open(outfile, "w") as f:
index_types = list() index_types = list()
for entry in block["index"]: for entry in block["index"]:
index_types.append(entry[0]) index_types.append(entry[0])
value_types = ["Cell*"]
for entry in block["setup"]:
if entry[0] == "slice":
value_types.append("int")
if entry[0] == "choice":
value_types.append(entry[1])
if entry[0] == "define":
value_types.append(entry[1])
print(" typedef std::tuple<{}> index_{}_key_type;".format(", ".join(index_types), index), file=f) print(" typedef std::tuple<{}> index_{}_key_type;".format(", ".join(index_types), index), file=f)
print(" dict<index_{}_key_type, vector<Cell*>> index_{};".format(index, index), file=f) print(" typedef std::tuple<{}> index_{}_value_type;".format(", ".join(value_types), index), file=f)
print(" dict<index_{}_key_type, vector<index_{}_value_type>> index_{};".format(index, index, index), file=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)
@ -304,47 +422,30 @@ with open(outfile, "w") as f:
print(" void add_siguser(const SigSpec &sig, Cell *cell) {", file=f) print(" void add_siguser(const SigSpec &sig, Cell *cell) {", file=f)
print(" for (auto bit : sigmap(sig)) {", file=f) print(" for (auto bit : sigmap(sig)) {", file=f)
print(" if (bit.wire == nullptr) continue;", file=f) print(" if (bit.wire == nullptr) continue;", file=f)
print(" if (sigusers.count(bit) == 0 && bit.wire->port_id)", file=f)
print(" sigusers[bit].insert(nullptr);", file=f)
print(" sigusers[bit].insert(cell);", file=f) print(" sigusers[bit].insert(cell);", file=f)
print(" }", file=f) print(" }", file=f)
print(" }", file=f) print(" }", file=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 +468,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("*"):
@ -375,10 +476,11 @@ with open(outfile, "w") as f:
else: else:
print(" ud_{}.{} = {}();".format(current_pattern, s, t), file=f) print(" ud_{}.{} = {}();".format(current_pattern, s, t), file=f)
current_pattern = None current_pattern = None
print(" for (auto cell : module->cells()) {", file=f) print(" for (auto port : module->ports)", file=f)
print(" add_siguser(module->wire(port), nullptr);", file=f)
print(" for (auto cell : module->cells())", file=f)
print(" for (auto &conn : cell->connections())", file=f) print(" for (auto &conn : cell->connections())", file=f)
print(" add_siguser(conn.second, cell);", file=f) print(" add_siguser(conn.second, cell);", file=f)
print(" }", file=f)
print(" for (auto cell : cells) {", file=f) print(" for (auto cell : cells) {", file=f)
for index in range(len(blocks)): for index in range(len(blocks)):
@ -386,12 +488,34 @@ with open(outfile, "w") as f:
if block["type"] == "match": if block["type"] == "match":
print(" do {", file=f) print(" do {", file=f)
print(" Cell *{} = cell;".format(block["cell"]), file=f) print(" Cell *{} = cell;".format(block["cell"]), file=f)
for expr in block["select"]: print(" index_{}_value_type value;".format(index), file=f)
print(" if (!({})) break;".format(expr), file=f) print(" std::get<0>(value) = cell;", file=f)
loopcnt = 0
valueidx = 1
for item in block["setup"]:
if item[0] == "select":
print(" if (!({})) continue;".format(item[1]), file=f)
if item[0] == "slice":
print(" int &{} = std::get<{}>(value);".format(item[1], valueidx), file=f)
print(" for ({} = 0; {} < {}; {}++) {{".format(item[1], item[1], item[2], item[1]), file=f)
valueidx += 1
loopcnt += 1
if item[0] == "choice":
print(" vector<{}> _pmg_choices_{} = {};".format(item[1], item[2], item[3]), file=f)
print(" for (const {} &{} : _pmg_choices_{}) {{".format(item[1], item[2], item[2]), file=f)
print(" std::get<{}>(value) = {};".format(valueidx, item[2]), file=f)
valueidx += 1
loopcnt += 1
if item[0] == "define":
print(" {} &{} = std::get<{}>(value);".format(item[1], item[2], valueidx), file=f)
print(" {} = {};".format(item[2], item[3]), file=f)
valueidx += 1
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[1]), file=f) print(" std::get<{}>(key) = {};".format(field, entry[1]), file=f)
print(" index_{}[key].push_back(cell);".format(index), file=f) print(" index_{}[key].push_back(value);".format(index), file=f)
for i in range(loopcnt):
print(" }", file=f)
print(" } while (0);", file=f) print(" } while (0);", file=f)
print(" }", file=f) print(" }", file=f)
@ -405,41 +529,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,12 +579,17 @@ 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)
elif blocks[i]["type"] == "match": elif blocks[i]["type"] == "match":
const_st.add(blocks[i]["cell"]) const_st.add(blocks[i]["cell"])
for item in blocks[i]["sets"]:
const_st.add(item[0])
else: else:
assert False assert False
@ -468,6 +603,10 @@ with open(outfile, "w") as f:
s = block["cell"] s = block["cell"]
assert s not in const_st assert s not in const_st
nonconst_st.add(s) nonconst_st.add(s)
for item in block["sets"]:
if item[0] in const_st:
const_st.remove(item[0])
nonconst_st.add(item[0])
else: else:
assert False assert False
@ -482,37 +621,55 @@ 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):
t = state_types[current_pattern][s] t = state_types[current_pattern][s]
print(" {} backup_{} = {};".format(t, s, s), file=f) print(" {} _pmg_backup_{} = {};".format(t, s, s), file=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):
t = state_types[current_pattern][s] t = state_types[current_pattern][s]
print(" {} = backup_{};".format(s, s), file=f) print(" {} = _pmg_backup_{};".format(s, s), file=f)
for s in sorted(nonconst_st): for s in sorted(nonconst_st):
if s not in restore_st: if s not in restore_st:
t = state_types[current_pattern][s] t = state_types[current_pattern][s]
@ -524,12 +681,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* _pmg_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(" {} = _pmg_backup_{};".format(block["cell"], block["cell"]), file=f)
print(" return;", file=f) print(" return;", file=f)
print(" }", file=f) print(" }", file=f)
@ -537,30 +697,69 @@ 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<index_{}_value_type> &cells = cells_ptr->second;".format(index), file=f)
print(" for (int _pmg_idx = 0; _pmg_idx < GetSize(cells); _pmg_idx++) {", file=f)
print(" {} = std::get<0>(cells[_pmg_idx]);".format(block["cell"]), file=f)
valueidx = 1
for item in block["setup"]:
if item[0] == "slice":
print(" const int &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], valueidx), file=f)
valueidx += 1
if item[0] == "choice":
print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
valueidx += 1
if item[0] == "define":
print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
valueidx += 1
print(" if (blacklist_cells.count({})) continue;".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(" found_any_match = true;", file=f)
for item in block["sets"]:
print(" auto _pmg_backup_{} = {};".format(item[0], item[0]), file=f)
print(" {} = {};".format(item[0], item[1]), file=f)
print(" auto rollback_ptr = rollback_cache.insert(make_pair(std::get<0>(cells[_pmg_idx]), recursion));", file=f)
print(" block_{}(recursion+1);".format(index+1), file=f)
for item in block["sets"]:
print(" {} = _pmg_backup_{};".format(item[0], item[0]), 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) {", file=f)
print(" if (rollback != {}) {{".format(index+1), file=f) print(" if (rollback != recursion) {{".format(index+1), file=f)
print(" {} = nullptr;".format(block["cell"]), file=f) print(" {} = _pmg_backup_{};".format(block["cell"], block["cell"]), file=f)
print(" return;", file=f) print(" return;", file=f)
print(" }", file=f) print(" }", file=f)
print(" rollback = 0;", file=f) print(" rollback = 0;", file=f)
print(" }", file=f) print(" }", file=f)
print(" }", file=f) print(" }", file=f)
print(" }", file=f)
print("", file=f) print("", file=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(" {} = _pmg_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 && rng(100) < (found_any_match ? {} : {})) {{".format(block["genargs"][1], 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

379
passes/pmgen/test_pmgen.cc Normal file
View file

@ -0,0 +1,379 @@
/*
* 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));
}
void opt_eqpmux(test_pmgen_pm &pm)
{
auto &st = pm.st_eqpmux;
SigSpec Y = st.pmux->getPort(ID::Y);
int width = GetSize(Y);
SigSpec EQ = st.pmux->getPort(ID::B).extract(st.pmux_slice_eq*width, width);
SigSpec NE = st.pmux->getPort(ID::B).extract(st.pmux_slice_ne*width, width);
log("Found eqpmux circuit driving %s (eq=%s, ne=%s, pmux=%s).\n",
log_signal(Y), log_id(st.eq), log_id(st.ne), log_id(st.pmux));
pm.autoremove(st.pmux);
Cell *c = pm.module->addMux(NEW_ID, NE, EQ, st.eq->getPort(ID::Y), Y);
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 maxmodcnt = 100;
int maxsubcnt = 4;
int timeout = 0;
vector<Module*> mods;
while (modcnt < maxmodcnt)
{
int submodcnt = 0, itercnt = 0, cellcnt = 0;
Module *mod = design->addModule(NEW_ID);
while (modcnt < maxmodcnt && 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 -eqpmux [options] [selection]\n");
log("\n");
log("Demo for recursive pmgen patterns. Optimize EQ/NE/PMUX circuits.\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_eqpmux(std::vector<std::string> args, RTLIL::Design *design)
{
log_header(design, "Executing TEST_PMGEN pass (-eqpmux).\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_eqpmux(opt_eqpmux);
}
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 == "eqpmux")
return GENERATE_PATTERN(test_pmgen_pm, eqpmux);
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] == "-eqpmux")
return execute_eqpmux(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

189
passes/pmgen/test_pmgen.pmg Normal file
View file

@ -0,0 +1,189 @@
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 next->type.in($_AND_, $_OR_, $_XOR_)
select nusers(port(next, \Y)) == 2
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 next->type.in($_AND_, $_OR_, $_XOR_)
select nusers(port(next, \Y)) == 2
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
// ==================================================================
pattern eqpmux
state <bool> eq_ne_signed
state <SigSpec> eq_inA eq_inB
state <int> pmux_slice_eq pmux_slice_ne
match eq
select eq->type == $eq
choice <IdString> AB {\A, \B}
define <IdString> BA AB == \A ? \B : \A
set eq_inA port(eq, \A)
set eq_inB port(eq, \B)
set eq_ne_signed param(eq, \A_SIGNED).as_bool()
generate 100 10
SigSpec A = module->addWire(NEW_ID, rng(7)+1);
SigSpec B = module->addWire(NEW_ID, rng(7)+1);
SigSpec Y = module->addWire(NEW_ID);
module->addEq(NEW_ID, A, B, Y, rng(2));
endmatch
match pmux
select pmux->type == $pmux
slice idx GetSize(port(pmux, \S))
index <SigBit> port(pmux, \S)[idx] === port(eq, \Y)
set pmux_slice_eq idx
generate 100 10
int width = rng(7) + 1;
int numsel = rng(4) + 1;
int idx = rng(numsel);
SigSpec A = module->addWire(NEW_ID, width);
SigSpec Y = module->addWire(NEW_ID, width);
SigSpec B, S;
for (int i = 0; i < numsel; i++) {
B.append(module->addWire(NEW_ID, width));
S.append(i == idx ? port(eq, \Y) : module->addWire(NEW_ID));
}
module->addPmux(NEW_ID, A, B, S, Y);
endmatch
match ne
select ne->type == $ne
choice <IdString> AB {\A, \B}
define <IdString> BA (AB == \A ? \B : \A)
index <SigSpec> port(ne, AB) === eq_inA
index <SigSpec> port(ne, BA) === eq_inB
index <int> param(ne, \A_SIGNED).as_bool() === eq_ne_signed
generate 100 10
SigSpec A = eq_inA, B = eq_inB, Y;
if (rng(2)) {
std::swap(A, B);
}
if (rng(2)) {
for (auto bit : port(pmux, \S)) {
if (nusers(bit) < 2)
Y.append(bit);
}
if (GetSize(Y))
Y = Y[rng(GetSize(Y))];
else
Y = module->addWire(NEW_ID);
} else {
Y = module->addWire(NEW_ID);
}
module->addNe(NEW_ID, A, B, Y, rng(2));
endmatch
match pmux2
select pmux2->type == $pmux
slice idx GetSize(port(pmux2, \S))
index <Cell*> pmux2 === pmux
index <SigBit> port(pmux2, \S)[idx] === port(ne, \Y)
set pmux_slice_ne idx
endmatch
code
accept;
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

@ -39,7 +39,7 @@ struct Async2syncPass : public Pass {
log("reset value in the next cycle regardless of the data-in value at the time of\n"); log("reset value in the next cycle regardless of the data-in value at the time of\n");
log("the clock edge.\n"); log("the clock edge.\n");
log("\n"); log("\n");
log("Currently only $adff and $dffsr cells are supported by this pass.\n"); log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\n");
log("\n"); log("\n");
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@ -169,6 +169,41 @@ struct Async2syncPass : public Pass {
cell->type = "$dff"; cell->type = "$dff";
continue; continue;
} }
if (cell->type.in("$dlatch"))
{
bool en_pol = cell->parameters["\\EN_POLARITY"].as_bool();
SigSpec sig_en = cell->getPort("\\EN");
SigSpec sig_d = cell->getPort("\\D");
SigSpec sig_q = cell->getPort("\\Q");
log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
log_signal(sig_en), log_signal(sig_d), log_signal(sig_q));
Const init_val;
for (int i = 0; i < GetSize(sig_q); i++) {
SigBit bit = sigmap(sig_q[i]);
init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
del_initbits.insert(bit);
}
Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
new_q->attributes["\\init"] = init_val;
if (en_pol) {
module->addMux(NEW_ID, new_q, sig_d, sig_en, sig_q);
} else {
module->addMux(NEW_ID, sig_d, new_q, sig_en, sig_q);
}
cell->setPort("\\Q", new_q);
cell->unsetPort("\\EN");
cell->unsetParam("\\EN_POLARITY");
cell->type = "$ff";
continue;
}
} }
for (auto wire : module->wires()) for (auto wire : module->wires())

View file

@ -143,7 +143,7 @@ void create_dff_dq_map(std::map<RTLIL::IdString, dff_map_info_t> &map, RTLIL::De
continue; continue;
} }
if (info.cell->type == "$_DFF_N_" || info.cell->type == "$_DFF_P_") { if (info.cell->type.in("$_DFF_N_", "$_DFF_P_")) {
info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit(); info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit();
info.clk_polarity = info.cell->type == "$_DFF_P_"; info.clk_polarity = info.cell->type == "$_DFF_P_";
info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit(); info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit();

View file

@ -268,7 +268,7 @@ struct SatHelper
RTLIL::SigSpec removed_bits; RTLIL::SigSpec removed_bits;
for (int i = 0; i < lhs.size(); i++) { for (int i = 0; i < lhs.size(); i++) {
RTLIL::SigSpec bit = lhs.extract(i, 1); RTLIL::SigSpec bit = lhs.extract(i, 1);
if (!satgen.initial_state.check_all(bit)) { if (rhs[i] == State::Sx || !satgen.initial_state.check_all(bit)) {
removed_bits.append(bit); removed_bits.append(bit);
lhs.remove(i, 1); lhs.remove(i, 1);
rhs.remove(i, 1); rhs.remove(i, 1);

View file

@ -16,6 +16,7 @@ endif
ifneq ($(SMALL),1) ifneq ($(SMALL),1)
OBJS += passes/techmap/iopadmap.o OBJS += passes/techmap/iopadmap.o
OBJS += passes/techmap/clkbufmap.o
OBJS += passes/techmap/hilomap.o OBJS += passes/techmap/hilomap.o
OBJS += passes/techmap/extract.o OBJS += passes/techmap/extract.o
OBJS += passes/techmap/extract_fa.o OBJS += passes/techmap/extract_fa.o

View file

@ -166,39 +166,39 @@ void mark_port(RTLIL::SigSpec sig)
void extract_cell(RTLIL::Cell *cell, bool keepff) void extract_cell(RTLIL::Cell *cell, bool keepff)
{ {
if (cell->type.in("$_DFF_N_", "$_DFF_P_")) if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
{ {
if (clk_polarity != (cell->type == "$_DFF_P_")) if (clk_polarity != (cell->type == ID($_DFF_P_)))
return; return;
if (clk_sig != assign_map(cell->getPort("\\C"))) if (clk_sig != assign_map(cell->getPort(ID(C))))
return; return;
if (GetSize(en_sig) != 0) if (GetSize(en_sig) != 0)
return; return;
goto matching_dff; goto matching_dff;
} }
if (cell->type.in("$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_")) if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
{ {
if (clk_polarity != cell->type.in("$_DFFE_PN_", "$_DFFE_PP_")) if (clk_polarity != cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)))
return; return;
if (en_polarity != cell->type.in("$_DFFE_NP_", "$_DFFE_PP_")) if (en_polarity != cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)))
return; return;
if (clk_sig != assign_map(cell->getPort("\\C"))) if (clk_sig != assign_map(cell->getPort(ID(C))))
return; return;
if (en_sig != assign_map(cell->getPort("\\E"))) if (en_sig != assign_map(cell->getPort(ID(E))))
return; return;
goto matching_dff; goto matching_dff;
} }
if (0) { if (0) {
matching_dff: matching_dff:
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
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["\\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);
@ -209,25 +209,25 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
return; return;
} }
if (cell->type.in("$_BUF_", "$_NOT_")) if (cell->type.in(ID($_BUF_), ID($_NOT_)))
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_y = cell->getPort("\\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);
map_signal(sig_y, cell->type == "$_BUF_" ? G(BUF) : G(NOT), map_signal(sig_a)); map_signal(sig_y, cell->type == ID($_BUF_) ? G(BUF) : G(NOT), map_signal(sig_a));
module->remove(cell); module->remove(cell);
return; return;
} }
if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_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("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_y = cell->getPort("\\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);
@ -236,21 +236,21 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_a = map_signal(sig_a); int mapped_a = map_signal(sig_a);
int mapped_b = map_signal(sig_b); int mapped_b = map_signal(sig_b);
if (cell->type == "$_AND_") if (cell->type == ID($_AND_))
map_signal(sig_y, G(AND), mapped_a, mapped_b); map_signal(sig_y, G(AND), mapped_a, mapped_b);
else if (cell->type == "$_NAND_") else if (cell->type == ID($_NAND_))
map_signal(sig_y, G(NAND), mapped_a, mapped_b); map_signal(sig_y, G(NAND), mapped_a, mapped_b);
else if (cell->type == "$_OR_") else if (cell->type == ID($_OR_))
map_signal(sig_y, G(OR), mapped_a, mapped_b); map_signal(sig_y, G(OR), mapped_a, mapped_b);
else if (cell->type == "$_NOR_") else if (cell->type == ID($_NOR_))
map_signal(sig_y, G(NOR), mapped_a, mapped_b); map_signal(sig_y, G(NOR), mapped_a, mapped_b);
else if (cell->type == "$_XOR_") else if (cell->type == ID($_XOR_))
map_signal(sig_y, G(XOR), mapped_a, mapped_b); map_signal(sig_y, G(XOR), mapped_a, mapped_b);
else if (cell->type == "$_XNOR_") else if (cell->type == ID($_XNOR_))
map_signal(sig_y, G(XNOR), mapped_a, mapped_b); map_signal(sig_y, G(XNOR), mapped_a, mapped_b);
else if (cell->type == "$_ANDNOT_") else if (cell->type == ID($_ANDNOT_))
map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b); map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b);
else if (cell->type == "$_ORNOT_") else if (cell->type == ID($_ORNOT_))
map_signal(sig_y, G(ORNOT), mapped_a, mapped_b); map_signal(sig_y, G(ORNOT), mapped_a, mapped_b);
else else
log_abort(); log_abort();
@ -259,12 +259,12 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
return; return;
} }
if (cell->type.in("$_MUX_", "$_NMUX_")) if (cell->type.in(ID($_MUX_), ID($_NMUX_)))
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_s = cell->getPort("\\S"); RTLIL::SigSpec sig_s = cell->getPort(ID(S));
RTLIL::SigSpec sig_y = cell->getPort("\\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);
@ -275,18 +275,18 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_b = map_signal(sig_b); int mapped_b = map_signal(sig_b);
int mapped_s = map_signal(sig_s); int mapped_s = map_signal(sig_s);
map_signal(sig_y, cell->type == "$_MUX_" ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s); map_signal(sig_y, cell->type == ID($_MUX_) ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s);
module->remove(cell); module->remove(cell);
return; return;
} }
if (cell->type.in("$_AOI3_", "$_OAI3_")) if (cell->type.in(ID($_AOI3_), ID($_OAI3_)))
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_c = cell->getPort("\\C"); RTLIL::SigSpec sig_c = cell->getPort(ID(C));
RTLIL::SigSpec sig_y = cell->getPort("\\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);
@ -297,19 +297,19 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_b = map_signal(sig_b); int mapped_b = map_signal(sig_b);
int mapped_c = map_signal(sig_c); int mapped_c = map_signal(sig_c);
map_signal(sig_y, cell->type == "$_AOI3_" ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c); map_signal(sig_y, cell->type == ID($_AOI3_) ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c);
module->remove(cell); module->remove(cell);
return; return;
} }
if (cell->type.in("$_AOI4_", "$_OAI4_")) if (cell->type.in(ID($_AOI4_), ID($_OAI4_)))
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_c = cell->getPort("\\C"); RTLIL::SigSpec sig_c = cell->getPort(ID(C));
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_y = cell->getPort("\\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);
@ -322,7 +322,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_c = map_signal(sig_c); int mapped_c = map_signal(sig_c);
int mapped_d = map_signal(sig_d); int mapped_d = map_signal(sig_d);
map_signal(sig_y, cell->type == "$_AOI4_" ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d); map_signal(sig_y, cell->type == ID($_AOI4_) ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
module->remove(cell); module->remove(cell);
return; return;
@ -352,23 +352,20 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp
auto sig = signal_list.at(sid); auto sig = signal_list.at(sid);
if (sig.bit.wire != nullptr) if (sig.bit.wire != nullptr)
{ {
std::stringstream sstr; std::string s = stringf("$abc$%d$%s", map_autoidx, sig.bit.wire->name.c_str()+1);
sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1);
if (sig.bit.wire->width != 1) if (sig.bit.wire->width != 1)
sstr << "[" << sig.bit.offset << "]"; s += stringf("[%d]", sig.bit.offset);
if (isnew) if (isnew)
sstr << "_new"; s += "_new";
sstr << postfix; s += postfix;
if (orig_wire != nullptr) if (orig_wire != nullptr)
*orig_wire = sig.bit.wire; *orig_wire = sig.bit.wire;
return sstr.str(); return s;
} }
} }
} }
} }
std::stringstream sstr; return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1);
return sstr.str();
} }
void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts) void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts)
@ -790,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("\\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));
} }
@ -939,42 +936,42 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); fprintf(f, "GATE ZERO 1 Y=CONST0;\n");
fprintf(f, "GATE ONE 1 Y=CONST1;\n"); fprintf(f, "GATE ONE 1 Y=CONST1;\n");
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_BUF_")); fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_BUF_)));
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOT_")); fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOT_)));
if (enabled_gates.count("AND")) if (enabled_gates.count("AND"))
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_AND_")); fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_AND_)));
if (enabled_gates.count("NAND")) if (enabled_gates.count("NAND"))
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NAND_")); fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NAND_)));
if (enabled_gates.count("OR")) if (enabled_gates.count("OR"))
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_OR_")); fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_OR_)));
if (enabled_gates.count("NOR")) if (enabled_gates.count("NOR"))
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOR_")); fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOR_)));
if (enabled_gates.count("XOR")) if (enabled_gates.count("XOR"))
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_")); fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XOR_)));
if (enabled_gates.count("XNOR")) if (enabled_gates.count("XNOR"))
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_")); fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XNOR_)));
if (enabled_gates.count("ANDNOT")) if (enabled_gates.count("ANDNOT"))
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_")); fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ANDNOT_)));
if (enabled_gates.count("ORNOT")) if (enabled_gates.count("ORNOT"))
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_")); fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ORNOT_)));
if (enabled_gates.count("AOI3")) if (enabled_gates.count("AOI3"))
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI3_")); fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI3_)));
if (enabled_gates.count("OAI3")) if (enabled_gates.count("OAI3"))
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI3_")); fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI3_)));
if (enabled_gates.count("AOI4")) if (enabled_gates.count("AOI4"))
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI4_")); fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI4_)));
if (enabled_gates.count("OAI4")) if (enabled_gates.count("OAI4"))
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI4_")); fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI4_)));
if (enabled_gates.count("MUX")) if (enabled_gates.count("MUX"))
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_")); fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_MUX_)));
if (enabled_gates.count("NMUX")) if (enabled_gates.count("NMUX"))
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_")); fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_NMUX_)));
if (map_mux4) if (map_mux4)
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_")); fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at(ID($_MUX_)));
if (map_mux8) if (map_mux8)
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at("$_MUX_")); fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at(ID($_MUX_)));
if (map_mux16) if (map_mux16)
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at("$_MUX_")); fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at(ID($_MUX_)));
fclose(f); fclose(f);
if (!lut_costs.empty()) { if (!lut_costs.empty()) {
@ -1019,21 +1016,21 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
bool builtin_lib = liberty_file.empty(); bool builtin_lib = liberty_file.empty();
RTLIL::Design *mapped_design = new RTLIL::Design; RTLIL::Design *mapped_design = new RTLIL::Design;
parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode); parse_blif(mapped_design, ifs, builtin_lib ? ID(DFF) : ID(_dff_), false, sop_mode);
ifs.close(); ifs.close();
log_header(design, "Re-integrating ABC results.\n"); log_header(design, "Re-integrating ABC results.\n");
RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"]; RTLIL::Module *mapped_mod = mapped_design->modules_[ID(netlist)];
if (mapped_mod == NULL) if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `netlist'.\n"); log_error("ABC output file does not contain a module `netlist'.\n");
for (auto &it : mapped_mod->wires_) { for (auto &it : mapped_mod->wires_) {
RTLIL::Wire *w = it.second; RTLIL::Wire *w = it.second;
RTLIL::Wire *orig_wire = nullptr; RTLIL::Wire *orig_wire = nullptr;
RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire)); RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire));
if (orig_wire != nullptr && orig_wire->attributes.count("\\src")) if (orig_wire != nullptr && orig_wire->attributes.count(ID(src)))
wire->attributes["\\src"] = orig_wire->attributes["\\src"]; wire->attributes[ID(src)] = orig_wire->attributes[ID(src)];
if (markgroups) wire->attributes["\\abcgroup"] = map_autoidx; if (markgroups) wire->attributes[ID(abcgroup)] = map_autoidx;
design->select(module, wire); design->select(module, wire);
} }
@ -1043,141 +1040,140 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (builtin_lib) if (builtin_lib)
{ {
cell_stats[RTLIL::unescape_id(c->type)]++; cell_stats[RTLIL::unescape_id(c->type)]++;
if (c->type == "\\ZERO" || c->type == "\\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("\\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 == "\\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 == "\\BUF") { if (c->type == ID(BUF)) {
RTLIL::SigSig conn; RTLIL::SigSig conn;
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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("\\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 == "\\NOT") { if (c->type == ID(NOT)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_));
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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 == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) {
c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\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), "$_" + c->type.substr(1) + "_"); if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort(ID::Y, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::Y).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
design->select(module, cell); design->select(module, cell);
continue; continue;
} }
if (c->type == "\\MUX" || c->type == "\\NMUX") { if (c->type.in(ID(MUX), ID(NMUX))) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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 == "\\MUX4") { if (c->type == ID(MUX4)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX4_));
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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 == "\\MUX8") { if (c->type == ID(MUX8)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX8_));
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)])); cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)])); cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)]));
cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)])); cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)]));
cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)])); cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)])); cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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 == "\\MUX16") { if (c->type == ID(MUX16)) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX16_));
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)])); cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)])); cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)]));
cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)])); cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)]));
cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)])); cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)]));
cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)])); cell->setPort(ID(I), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(I)).as_wire()->name)]));
cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)])); cell->setPort(ID(J), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(J)).as_wire()->name)]));
cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)])); cell->setPort(ID(K), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(K)).as_wire()->name)]));
cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)])); cell->setPort(ID(L), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(L)).as_wire()->name)]));
cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)])); cell->setPort(ID(M), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(M)).as_wire()->name)]));
cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)])); cell->setPort(ID(N), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(N)).as_wire()->name)]));
cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)])); cell->setPort(ID(O), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(O)).as_wire()->name)]));
cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)])); cell->setPort(ID(P), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(P)).as_wire()->name)]));
cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)])); cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)])); cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)])); cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").as_wire()->name)])); cell->setPort(ID(V), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(V)).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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 == "\\AOI3" || c->type == "\\OAI3") { if (c->type.in(ID(AOI3), ID(OAI3))) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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 == "\\AOI4" || c->type == "\\OAI4") { if (c->type.in(ID(AOI4), ID(OAI4))) {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort(ID::A, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::A).as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort(ID::B, RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID::B).as_wire()->name)]));
cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)])); cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\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 == "\\DFF") { if (c->type == ID(DFF)) {
log_assert(clk_sig.size() == 1); log_assert(clk_sig.size() == 1);
RTLIL::Cell *cell; RTLIL::Cell *cell;
if (en_sig.size() == 0) { if (en_sig.size() == 0) {
cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
} else { } else {
log_assert(en_sig.size() == 1); log_assert(en_sig.size() == 1);
cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
cell->setPort("\\E", en_sig); cell->setPort(ID(E), en_sig);
} }
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)]));
cell->setPort("\\C", clk_sig); cell->setPort(ID(C), clk_sig);
design->select(module, cell); design->select(module, cell);
continue; continue;
} }
@ -1185,41 +1181,41 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
else else
cell_stats[RTLIL::unescape_id(c->type)]++; cell_stats[RTLIL::unescape_id(c->type)]++;
if (c->type == "\\_const0_" || c->type == "\\_const1_") { if (c->type.in(ID(_const0_), ID(_const1_))) {
RTLIL::SigSig conn; RTLIL::SigSig conn;
conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]); conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]);
conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1); conn.second = RTLIL::SigSpec(c->type == ID(_const0_) ? 0 : 1, 1);
module->connect(conn); module->connect(conn);
continue; continue;
} }
if (c->type == "\\_dff_") { if (c->type == ID(_dff_)) {
log_assert(clk_sig.size() == 1); log_assert(clk_sig.size() == 1);
RTLIL::Cell *cell; RTLIL::Cell *cell;
if (en_sig.size() == 0) { if (en_sig.size() == 0) {
cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
} else { } else {
log_assert(en_sig.size() == 1); log_assert(en_sig.size() == 1);
cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
cell->setPort("\\E", en_sig); cell->setPort(ID(E), en_sig);
} }
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)]));
cell->setPort("\\C", clk_sig); cell->setPort(ID(C), clk_sig);
design->select(module, cell); design->select(module, cell);
continue; continue;
} }
if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\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("\\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("\\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;
} }
RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type);
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
cell->parameters = c->parameters; cell->parameters = c->parameters;
for (auto &conn : c->connections()) { for (auto &conn : c->connections()) {
RTLIL::SigSpec newsig; RTLIL::SigSpec newsig;
@ -1244,10 +1240,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (recover_init) if (recover_init)
for (auto wire : mapped_mod->wires()) { for (auto wire : mapped_mod->wires()) {
if (wire->attributes.count("\\init")) { if (wire->attributes.count(ID(init))) {
Wire *w = module->wires_[remap_name(wire->name)]; Wire *w = module->wires_[remap_name(wire->name)];
log_assert(w->attributes.count("\\init") == 0); log_assert(w->attributes.count(ID(init)) == 0);
w->attributes["\\init"] = wire->attributes.at("\\init"); w->attributes[ID(init)] = wire->attributes.at(ID(init));
} }
} }
@ -1634,6 +1630,7 @@ struct AbcPass : public Pass {
if (g == "ANDNOT") goto ok_gate; if (g == "ANDNOT") goto ok_gate;
if (g == "ORNOT") goto ok_gate; if (g == "ORNOT") goto ok_gate;
if (g == "MUX") goto ok_gate; if (g == "MUX") goto ok_gate;
if (g == "NMUX") goto ok_gate;
if (g == "AOI3") goto ok_gate; if (g == "AOI3") goto ok_gate;
if (g == "OAI3") goto ok_gate; if (g == "OAI3") goto ok_gate;
if (g == "AOI4") goto ok_gate; if (g == "AOI4") goto ok_gate;
@ -1802,9 +1799,9 @@ struct AbcPass : public Pass {
signal_init.clear(); signal_init.clear();
for (Wire *wire : mod->wires()) for (Wire *wire : mod->wires())
if (wire->attributes.count("\\init")) { if (wire->attributes.count(ID(init))) {
SigSpec initsig = assign_map(wire); SigSpec initsig = assign_map(wire);
Const initval = wire->attributes.at("\\init"); Const initval = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
switch (initval[i]) { switch (initval[i]) {
case State::S0: case State::S0:
@ -1861,16 +1858,16 @@ struct AbcPass : public Pass {
} }
} }
if (cell->type.in("$_DFF_N_", "$_DFF_P_")) if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
{ {
key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec()); key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
} }
else else
if (cell->type.in("$_DFFE_NN_", "$_DFFE_NP_" "$_DFFE_PN_", "$_DFFE_PP_")) if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
{ {
bool this_clk_pol = cell->type.in("$_DFFE_PN_", "$_DFFE_PP_"); bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
bool this_en_pol = cell->type.in("$_DFFE_NP_", "$_DFFE_PP_"); bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E"))); key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E))));
} }
else else
continue; continue;

View file

@ -71,25 +71,22 @@ RTLIL::Module *module;
bool clk_polarity, en_polarity; bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig; RTLIL::SigSpec clk_sig, en_sig;
std::string remap_name(RTLIL::IdString abc_name) inline std::string remap_name(RTLIL::IdString abc_name)
{ {
std::stringstream sstr; return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1);
return sstr.str();
} }
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
pool<RTLIL::Const> ids_seen; pool<RTLIL::Const> ids_seen;
for (auto cell : module->cells()) { for (auto cell : module->cells()) {
auto it = cell->attributes.find("\\abc_scc_id"); auto it = cell->attributes.find(ID(abc_scc_id));
if (it != cell->attributes.end()) { if (it != cell->attributes.end()) {
auto r = ids_seen.insert(it->second); auto r = ids_seen.insert(it->second);
if (r.second) { if (r.second) {
@ -109,7 +106,7 @@ void handle_loops(RTLIL::Design *design)
log_assert(w->port_input); log_assert(w->port_input);
log_assert(b.offset < GetSize(w)); log_assert(b.offset < GetSize(w));
} }
w->set_bool_attribute("\\abc_scc_break"); w->set_bool_attribute(ID(abc_scc_break));
module->swap_names(b.wire, w); module->swap_names(b.wire, w);
c.second = RTLIL::SigBit(w, b.offset); c.second = RTLIL::SigBit(w, b.offset);
} }
@ -118,23 +115,8 @@ 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;
RTLIL::Module* box_module = design->module(cell->type);
if (box_module) {
auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string();
for (const auto &port_name : split_tokens(ports_csv, ",")) {
auto port_id = RTLIL::escape_id(port_name);
auto kt = cell->connections_.find(port_id);
if (kt == cell->connections_.end())
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));
ports.push_back(port_id);
}
}
jt = abc_scc_break.insert(std::make_pair(cell->type, std::move(ports))).first;
}
for (auto port_name : jt->second) { for (auto port_name : jt->second) {
RTLIL::SigSpec sig; RTLIL::SigSpec sig;
auto &rhs = cell->connections_.at(port_name); auto &rhs = cell->connections_.at(port_name);
@ -142,7 +124,7 @@ void handle_loops(RTLIL::Design *design)
Wire *w = b.wire; Wire *w = b.wire;
if (!w) continue; if (!w) continue;
w->port_output = true; w->port_output = true;
w->set_bool_attribute("\\abc_scc_break"); w->set_bool_attribute(ID(abc_scc_break));
w = module->wire(stringf("%s.abci", w->name.c_str())); w = module->wire(stringf("%s.abci", w->name.c_str()));
if (!w) { if (!w) {
w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
@ -290,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++;
@ -429,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");
@ -446,14 +430,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (ifs.fail()) if (ifs.fail())
log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
log_assert(!design->module("$__abc9__")); log_assert(!design->module(ID($__abc9__)));
{ {
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
reader.parse_xaiger(); reader.parse_xaiger();
} }
ifs.close(); ifs.close();
Pass::call(design, stringf("write_verilog -noexpr -norename")); Pass::call(design, stringf("write_verilog -noexpr -norename"));
design->remove(design->module("$__abc9__")); design->remove(design->module(ID($__abc9__)));
#endif #endif
design->selection_stack.pop_back(); design->selection_stack.pop_back();
@ -462,7 +446,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
// the expose operation -- remove them from PO/PI // the expose operation -- remove them from PO/PI
// and re-connecting them back together // and re-connecting them back together
for (auto wire : module->wires()) { for (auto wire : module->wires()) {
auto it = wire->attributes.find("\\abc_scc_break"); auto it = wire->attributes.find(ID(abc_scc_break));
if (it != wire->attributes.end()) { if (it != wire->attributes.end()) {
wire->attributes.erase(it); wire->attributes.erase(it);
log_assert(wire->port_output); log_assert(wire->port_output);
@ -518,9 +502,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
log_assert(!design->module("$__abc9__")); log_assert(!design->module(ID($__abc9__)));
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
reader.parse_xaiger(box_lookup); reader.parse_xaiger(box_lookup);
ifs.close(); ifs.close();
@ -529,7 +513,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
#endif #endif
log_header(design, "Re-integrating ABC9 results.\n"); log_header(design, "Re-integrating ABC9 results.\n");
RTLIL::Module *mapped_mod = design->module("$__abc9__"); RTLIL::Module *mapped_mod = design->module(ID($__abc9__));
if (mapped_mod == NULL) if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `$__abc9__'.\n"); log_error("ABC output file does not contain a module `$__abc9__'.\n");
@ -537,7 +521,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
for (auto &it : mapped_mod->wires_) { for (auto &it : mapped_mod->wires_) {
RTLIL::Wire *w = it.second; RTLIL::Wire *w = it.second;
RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w)); RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx; if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
if (w->port_output) { if (w->port_output) {
RTLIL::Wire *wire = module->wire(w->name); RTLIL::Wire *wire = module->wire(w->name);
log_assert(wire); log_assert(wire);
@ -559,14 +543,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
vector<RTLIL::Cell*> boxes; vector<RTLIL::Cell*> boxes;
for (const auto &it : module->cells_) { for (const auto &it : module->cells_) {
auto cell = it.second; auto cell = it.second;
if (cell->type.in("$_AND_", "$_NOT_")) { if (cell->type.in(ID($_AND_), ID($_NOT_))) {
module->remove(cell); module->remove(cell);
continue; continue;
} }
auto jt = abc_box.find(cell->type); auto jt = abc_box.find(cell->type);
if (jt == abc_box.end()) { if (jt == abc_box.end()) {
RTLIL::Module* box_module = design->module(cell->type); RTLIL::Module* box_module = design->module(cell->type);
jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count("\\abc_box_id"))).first; jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc_box_id)))).first;
} }
if (jt->second) if (jt->second)
boxes.emplace_back(cell); boxes.emplace_back(cell);
@ -577,20 +561,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
dict<RTLIL::Cell*,RTLIL::Cell*> not2drivers; dict<RTLIL::Cell*,RTLIL::Cell*> not2drivers;
dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks; dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
std::map<std::string, int> cell_stats; std::map<IdString, int> cell_stats;
for (auto c : mapped_mod->cells()) for (auto c : mapped_mod->cells())
{ {
toposort.node(c->name); toposort.node(c->name);
RTLIL::Cell *cell = nullptr; RTLIL::Cell *cell = nullptr;
if (c->type == "$_NOT_") { if (c->type == ID($_NOT_)) {
RTLIL::SigBit a_bit = c->getPort("\\A"); RTLIL::SigBit a_bit = c->getPort(ID::A);
RTLIL::SigBit y_bit = c->getPort("\\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("\\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);
@ -618,8 +602,8 @@ 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("\\A")].push_back(cell); bit2sinks[cell->getPort(ID::A)].push_back(cell);
cell_stats["$lut"]++; cell_stats[ID($lut)]++;
} }
else else
not2drivers[c] = driver_lut; not2drivers[c] = driver_lut;
@ -627,18 +611,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
} }
else else
log_abort(); log_abort();
if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
continue; continue;
} }
cell_stats[RTLIL::unescape_id(c->type)]++; cell_stats[c->type]++;
RTLIL::Cell *existing_cell = nullptr; RTLIL::Cell *existing_cell = nullptr;
if (c->type == "$lut") { if (c->type == ID($lut)) {
if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\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("\\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("\\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["\\abcgroup"] = map_autoidx; if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx;
log_abort(); log_abort();
continue; continue;
} }
@ -651,7 +635,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
module->swap_names(cell, existing_cell); module->swap_names(cell, existing_cell);
} }
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
if (existing_cell) { if (existing_cell) {
cell->parameters = existing_cell->parameters; cell->parameters = existing_cell->parameters;
cell->attributes = existing_cell->attributes; cell->attributes = existing_cell->attributes;
@ -741,20 +725,20 @@ 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++) {
RTLIL::Cell *not_cell = mapped_mod->cell(*ii); RTLIL::Cell *not_cell = mapped_mod->cell(*ii);
log_assert(not_cell); log_assert(not_cell);
if (not_cell->type != "$_NOT_") if (not_cell->type != ID($_NOT_))
continue; continue;
auto it = not2drivers.find(not_cell); auto it = not2drivers.find(not_cell);
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("\\A"); RTLIL::SigBit a_bit = not_cell->getPort(ID::A);
RTLIL::SigBit y_bit = not_cell->getPort("\\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));
@ -765,13 +749,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
goto clone_lut; goto clone_lut;
for (auto sink_cell : jt->second) for (auto sink_cell : jt->second)
if (sink_cell->type != "$lut") if (sink_cell->type != ID($lut))
goto clone_lut; goto clone_lut;
// 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("\\A"); SigSpec A = sink_cell->getPort(ID::A);
RTLIL::Const mask = sink_cell->getParam("\\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++)
if (A[index] == a_bit) if (A[index] == a_bit)
@ -784,8 +768,8 @@ 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("\\A", A); sink_cell->setPort(ID::A, A);
sink_cell->setParam("\\LUT", mask); sink_cell->setParam(ID(LUT), mask);
} }
// Since we have rewritten all sinks (which we know // Since we have rewritten all sinks (which we know
@ -794,16 +778,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
// that the original driving LUT will become dangling // that the original driving LUT will become dangling
// and get cleaned away // and get cleaned away
clone_lut: clone_lut:
driver_mask = driver_lut->getParam("\\LUT"); driver_mask = driver_lut->getParam(ID(LUT));
for (auto &b : driver_mask.bits) { for (auto &b : driver_mask.bits) {
if (b == RTLIL::State::S0) b = RTLIL::State::S1; if (b == RTLIL::State::S0) b = RTLIL::State::S1;
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("\\A"), driver_lut->getPort(ID::A),
y_bit, y_bit,
driver_mask); driver_mask);
for (auto &bit : cell->connections_.at("\\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);
} }
@ -1083,8 +1067,9 @@ 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("\\abc_box_id"); auto it = m->attributes.find(ID(abc_box_id));
if (it == m->attributes.end()) if (it == m->attributes.end())
continue; continue;
if (m->name.begins_with("$paramod")) if (m->name.begins_with("$paramod"))
@ -1095,11 +1080,61 @@ 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())
{ {
if (mod->attributes.count("\\abc_box_id")) if (mod->attributes.count(ID(abc_box_id)))
continue; continue;
if (mod->processes.size() > 0) { if (mod->processes.size() > 0) {
@ -1112,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;
} }
@ -1153,16 +1188,16 @@ struct Abc9Pass : public Pass {
} }
} }
if (cell->type.in("$_DFF_N_", "$_DFF_P_")) if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
{ {
key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec()); key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
} }
else else
if (cell->type.in("$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_")) if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
{ {
bool this_clk_pol = cell->type.in("$_DFFE_PN_", "$_DFFE_PP_"); bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
bool this_en_pol = cell->type.in("$_DFFE_NP_", "$_DFFE_PP_"); bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E"))); key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E))));
} }
else else
continue; continue;
@ -1258,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

@ -66,10 +66,10 @@ struct AigmapPass : public Pass {
{ {
Aig aig(cell); Aig aig(cell);
if (cell->type.in("$_AND_", "$_NOT_")) if (cell->type.in(ID($_AND_), ID($_NOT_)))
aig.name.clear(); aig.name.clear();
if (nand_mode && cell->type == "$_NAND_") if (nand_mode && cell->type == ID($_NAND_))
aig.name.clear(); aig.name.clear();
if (aig.name.empty()) { if (aig.name.empty()) {

View file

@ -61,7 +61,7 @@ struct AlumaccWorker
RTLIL::SigSpec get_eq() { RTLIL::SigSpec get_eq() {
if (GetSize(cached_eq) == 0) if (GetSize(cached_eq) == 0)
cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort("\\X"), false, alu_cell->get_src_attribute()); cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort(ID(X)), false, alu_cell->get_src_attribute());
return cached_eq; return cached_eq;
} }
@ -73,7 +73,7 @@ struct AlumaccWorker
RTLIL::SigSpec get_cf() { RTLIL::SigSpec get_cf() {
if (GetSize(cached_cf) == 0) { if (GetSize(cached_cf) == 0) {
cached_cf = alu_cell->getPort("\\CO"); cached_cf = alu_cell->getPort(ID(CO));
log_assert(GetSize(cached_cf) >= 1); log_assert(GetSize(cached_cf) >= 1);
cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1], false, alu_cell->get_src_attribute()); cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1], false, alu_cell->get_src_attribute());
} }
@ -82,7 +82,7 @@ struct AlumaccWorker
RTLIL::SigSpec get_of() { RTLIL::SigSpec get_of() {
if (GetSize(cached_of) == 0) { if (GetSize(cached_of) == 0) {
cached_of = {alu_cell->getPort("\\CO"), alu_cell->getPort("\\CI")}; cached_of = {alu_cell->getPort(ID(CO)), alu_cell->getPort(ID(CI))};
log_assert(GetSize(cached_of) >= 2); log_assert(GetSize(cached_of) >= 2);
cached_of = alu_cell->module->Xor(NEW_ID, cached_of[GetSize(cached_of)-1], cached_of[GetSize(cached_of)-2]); cached_of = alu_cell->module->Xor(NEW_ID, cached_of[GetSize(cached_of)-1], cached_of[GetSize(cached_of)-2]);
} }
@ -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("\\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;
@ -125,7 +125,7 @@ struct AlumaccWorker
{ {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (!cell->type.in("$pos", "$neg", "$add", "$sub", "$mul")) if (!cell->type.in(ID($pos), ID($neg), ID($add), ID($sub), ID($mul)))
continue; continue;
log(" creating $macc model for %s (%s).\n", log_id(cell), log_id(cell->type)); log(" creating $macc model for %s (%s).\n", log_id(cell), log_id(cell->type));
@ -134,38 +134,38 @@ struct AlumaccWorker
Macc::port_t new_port; Macc::port_t new_port;
n->cell = cell; n->cell = cell;
n->y = sigmap(cell->getPort("\\Y")); n->y = sigmap(cell->getPort(ID::Y));
n->users = 0; n->users = 0;
for (auto bit : n->y) for (auto bit : n->y)
n->users = max(n->users, bit_users.at(bit) - 1); n->users = max(n->users, bit_users.at(bit) - 1);
if (cell->type.in("$pos", "$neg")) if (cell->type.in(ID($pos), ID($neg)))
{ {
new_port.in_a = sigmap(cell->getPort("\\A")); new_port.in_a = sigmap(cell->getPort(ID::A));
new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool(); new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
new_port.do_subtract = cell->type == "$neg"; new_port.do_subtract = cell->type == ID($neg);
n->macc.ports.push_back(new_port); n->macc.ports.push_back(new_port);
} }
if (cell->type.in("$add", "$sub")) if (cell->type.in(ID($add), ID($sub)))
{ {
new_port.in_a = sigmap(cell->getPort("\\A")); new_port.in_a = sigmap(cell->getPort(ID::A));
new_port.is_signed = cell->getParam("\\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("\\B")); new_port.in_a = sigmap(cell->getPort(ID::B));
new_port.is_signed = cell->getParam("\\B_SIGNED").as_bool(); new_port.is_signed = cell->getParam(ID(B_SIGNED)).as_bool();
new_port.do_subtract = cell->type == "$sub"; new_port.do_subtract = cell->type == ID($sub);
n->macc.ports.push_back(new_port); n->macc.ports.push_back(new_port);
} }
if (cell->type.in("$mul")) if (cell->type.in(ID($mul)))
{ {
new_port.in_a = sigmap(cell->getPort("\\A")); new_port.in_a = sigmap(cell->getPort(ID::A));
new_port.in_b = sigmap(cell->getPort("\\B")); new_port.in_b = sigmap(cell->getPort(ID::B));
new_port.is_signed = cell->getParam("\\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);
} }
@ -351,7 +351,7 @@ struct AlumaccWorker
for (auto &it : sig_macc) for (auto &it : sig_macc)
{ {
auto n = it.second; auto n = it.second;
auto cell = module->addCell(NEW_ID, "$macc"); auto cell = module->addCell(NEW_ID, ID($macc));
macc_counter++; macc_counter++;
@ -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("\\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;
@ -376,9 +376,9 @@ struct AlumaccWorker
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type.in("$lt", "$le", "$ge", "$gt")) if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt)))
lge_cells.push_back(cell); lge_cells.push_back(cell);
if (cell->type.in("$eq", "$eqx", "$ne", "$nex")) if (cell->type.in(ID($eq), ID($eqx), ID($ne), ID($nex)))
eq_cells.push_back(cell); eq_cells.push_back(cell);
} }
@ -386,13 +386,13 @@ struct AlumaccWorker
{ {
log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type)); log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type));
bool cmp_less = cell->type.in("$lt", "$le"); bool cmp_less = cell->type.in(ID($lt), ID($le));
bool cmp_equal = cell->type.in("$le", "$ge"); bool cmp_equal = cell->type.in(ID($le), ID($ge));
bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
RTLIL::SigSpec A = sigmap(cell->getPort("\\A")); RTLIL::SigSpec A = sigmap(cell->getPort(ID::A));
RTLIL::SigSpec B = sigmap(cell->getPort("\\B")); RTLIL::SigSpec B = sigmap(cell->getPort(ID::B));
RTLIL::SigSpec Y = sigmap(cell->getPort("\\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;
@ -427,12 +427,12 @@ struct AlumaccWorker
for (auto cell : eq_cells) for (auto cell : eq_cells)
{ {
bool cmp_equal = cell->type.in("$eq", "$eqx"); bool cmp_equal = cell->type.in(ID($eq), ID($eqx));
bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
RTLIL::SigSpec A = sigmap(cell->getPort("\\A")); RTLIL::SigSpec A = sigmap(cell->getPort(ID::A));
RTLIL::SigSpec B = sigmap(cell->getPort("\\B")); RTLIL::SigSpec B = sigmap(cell->getPort(ID::B));
RTLIL::SigSpec Y = sigmap(cell->getPort("\\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);
@ -471,7 +471,7 @@ struct AlumaccWorker
goto delete_node; goto delete_node;
} }
n->alu_cell = module->addCell(NEW_ID, "$alu"); n->alu_cell = module->addCell(NEW_ID, ID($alu));
alu_counter++; alu_counter++;
log(" creating $alu cell for "); log(" creating $alu cell for ");
@ -482,13 +482,13 @@ 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("\\A", n->a); n->alu_cell->setPort(ID::A, n->a);
n->alu_cell->setPort("\\B", n->b); n->alu_cell->setPort(ID::B, n->b);
n->alu_cell->setPort("\\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("\\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("\\Y", n->y); n->alu_cell->setPort(ID::Y, n->y);
n->alu_cell->setPort("\\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("\\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);
for (auto &it : n->cmp) for (auto &it : n->cmp)

View file

@ -143,17 +143,8 @@ void attrmap_apply(string objname, vector<std::unique_ptr<AttrmapAction>> &actio
attributes.swap(new_attributes); attributes.swap(new_attributes);
} }
struct AttrmapPass : public Pass { void log_attrmap_paramap_options()
AttrmapPass() : Pass("attrmap", "renaming attributes") { }
void help() YS_OVERRIDE
{ {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" attrmap [options] [selection]\n");
log("\n");
log("This command renames attributes and/or mapps key/value pairs to\n");
log("other key/value pairs.\n");
log("\n");
log(" -tocase <name>\n"); log(" -tocase <name>\n");
log(" Match attribute names case-insensitively and set it to the specified\n"); log(" Match attribute names case-insensitively and set it to the specified\n");
log(" name.\n"); log(" name.\n");
@ -170,39 +161,23 @@ struct AttrmapPass : public Pass {
log("\n"); log("\n");
log(" -remove <name>=<value>\n"); log(" -remove <name>=<value>\n");
log(" Remove attributes matching this pattern.\n"); log(" Remove attributes matching this pattern.\n");
log("\n");
log(" -modattr\n");
log(" Operate on module attributes instead of attributes on wires and cells.\n");
log("\n");
log("For example, mapping Xilinx-style \"keep\" attributes to Yosys-style:\n");
log("\n");
log(" attrmap -tocase keep -imap keep=\"true\" keep=1 \\\n");
log(" -imap keep=\"false\" keep=0 -remove keep=0\n");
log("\n");
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n");
bool modattr_mode = false; bool parse_attrmap_paramap_options(size_t &argidx, std::vector<std::string> &args, vector<std::unique_ptr<AttrmapAction>> &actions)
vector<std::unique_ptr<AttrmapAction>> actions;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{ {
std::string arg = args[argidx]; std::string arg = args[argidx];
if (arg == "-tocase" && argidx+1 < args.size()) { if (arg == "-tocase" && argidx+1 < args.size()) {
auto action = new AttrmapTocase; auto action = new AttrmapTocase;
action->name = args[++argidx]; action->name = args[++argidx];
actions.push_back(std::unique_ptr<AttrmapAction>(action)); actions.push_back(std::unique_ptr<AttrmapAction>(action));
continue; return true;
} }
if (arg == "-rename" && argidx+2 < args.size()) { if (arg == "-rename" && argidx+2 < args.size()) {
auto action = new AttrmapRename; auto action = new AttrmapRename;
action->old_name = args[++argidx]; action->old_name = args[++argidx];
action->new_name = args[++argidx]; action->new_name = args[++argidx];
actions.push_back(std::unique_ptr<AttrmapAction>(action)); actions.push_back(std::unique_ptr<AttrmapAction>(action));
continue; return true;
} }
if ((arg == "-map" || arg == "-imap") && argidx+2 < args.size()) { if ((arg == "-map" || arg == "-imap") && argidx+2 < args.size()) {
string arg1 = args[++argidx]; string arg1 = args[++argidx];
@ -225,7 +200,7 @@ struct AttrmapPass : public Pass {
action->old_value = val1; action->old_value = val1;
action->new_value = val2; action->new_value = val2;
actions.push_back(std::unique_ptr<AttrmapAction>(action)); actions.push_back(std::unique_ptr<AttrmapAction>(action));
continue; return true;
} }
if (arg == "-remove" && argidx+1 < args.size()) { if (arg == "-remove" && argidx+1 < args.size()) {
string arg1 = args[++argidx], val1; string arg1 = args[++argidx], val1;
@ -239,9 +214,46 @@ struct AttrmapPass : public Pass {
action->has_value = (p != string::npos); action->has_value = (p != string::npos);
action->value = val1; action->value = val1;
actions.push_back(std::unique_ptr<AttrmapAction>(action)); actions.push_back(std::unique_ptr<AttrmapAction>(action));
continue; return true;
} }
if (arg == "-modattr") { return false;
}
struct AttrmapPass : public Pass {
AttrmapPass() : Pass("attrmap", "renaming attributes") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" attrmap [options] [selection]\n");
log("\n");
log("This command renames attributes and/or maps key/value pairs to\n");
log("other key/value pairs.\n");
log("\n");
log_attrmap_paramap_options();
log("\n");
log(" -modattr\n");
log(" Operate on module attributes instead of attributes on wires and cells.\n");
log("\n");
log("For example, mapping Xilinx-style \"keep\" attributes to Yosys-style:\n");
log("\n");
log(" attrmap -tocase keep -imap keep=\"true\" keep=1 \\\n");
log(" -imap keep=\"false\" keep=0 -remove keep=0\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n");
bool modattr_mode = false;
vector<std::unique_ptr<AttrmapAction>> actions;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (parse_attrmap_paramap_options(argidx, args, actions))
continue;
if (args[argidx] == "-modattr") {
modattr_mode = true; modattr_mode = true;
continue; continue;
} }
@ -287,4 +299,43 @@ struct AttrmapPass : public Pass {
} }
} AttrmapPass; } AttrmapPass;
struct ParamapPass : public Pass {
ParamapPass() : Pass("paramap", "renaming cell parameters") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" paramap [options] [selection]\n");
log("\n");
log("This command renames cell parameters and/or maps key/value pairs to\n");
log("other key/value pairs.\n");
log("\n");
log_attrmap_paramap_options();
log("\n");
log("For example, mapping Diamond-style ECP5 \"init\" attributes to Yosys-style:\n");
log("\n");
log(" paramap -tocase INIT t:LUT4\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing PARAMAP pass (move or copy cell parameters).\n");
vector<std::unique_ptr<AttrmapAction>> actions;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (parse_attrmap_paramap_options(argidx, args, actions))
continue;
break;
}
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
for (auto cell : module->selected_cells())
attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->parameters);
}
} ParamapPass;
PRIVATE_NAMESPACE_END PRIVATE_NAMESPACE_END

298
passes/techmap/clkbufmap.cc Normal file
View file

@ -0,0 +1,298 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* Copyright (C) 2019 Marcin Kościelnicki <mwk@0x04.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
void split_portname_pair(std::string &port1, std::string &port2)
{
size_t pos = port1.find_first_of(':');
if (pos != std::string::npos) {
port2 = port1.substr(pos+1);
port1 = port1.substr(0, pos);
}
}
struct ClkbufmapPass : public Pass {
ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" clkbufmap [options] [selection]\n");
log("\n");
log("Inserts global buffers between nets connected to clock inputs and their drivers.\n");
log("\n");
log("In the absence of any selection, all wires without the 'clkbuf_inhibit'\n");
log("attribute will be considered for global buffer insertion.\n");
log("Alternatively, to consider all wires without the 'buffer_type' attribute set to\n");
log("'none' or 'bufr' one would specify:\n");
log(" 'w:* a:buffer_type=none a:buffer_type=bufr %%u %%d'\n");
log("as the selection.\n");
log("\n");
log(" -buf <celltype> <portname_out>:<portname_in>\n");
log(" Specifies the cell type to use for the global buffers\n");
log(" and its port names. The first port will be connected to\n");
log(" the clock network sinks, and the second will be connected\n");
log(" to the actual clock source. This option is required.\n");
log("\n");
log(" -inpad <celltype> <portname_out>:<portname_in>\n");
log(" If specified, a PAD cell of the given type is inserted on\n");
log(" clock nets that are also top module's inputs (in addition\n");
log(" to the global buffer).\n");
log("\n");
}
void module_queue(Design *design, Module *module, std::vector<Module *> &modules_sorted, pool<Module *> &modules_processed) {
if (modules_processed.count(module))
return;
for (auto cell : module->cells()) {
Module *submodule = design->module(cell->type);
if (!submodule)
continue;
module_queue(design, submodule, modules_sorted, modules_processed);
}
modules_sorted.push_back(module);
modules_processed.insert(module);
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing CLKBUFMAP pass (inserting global clock buffers).\n");
std::string buf_celltype, buf_portname, buf_portname2;
std::string inpad_celltype, inpad_portname, inpad_portname2;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
if (arg == "-buf" && argidx+2 < args.size()) {
buf_celltype = args[++argidx];
buf_portname = args[++argidx];
split_portname_pair(buf_portname, buf_portname2);
continue;
}
if (arg == "-inpad" && argidx+2 < args.size()) {
inpad_celltype = args[++argidx];
inpad_portname = args[++argidx];
split_portname_pair(inpad_portname, inpad_portname2);
continue;
}
break;
}
bool select = false;
if (argidx < args.size()) {
if (args[argidx].compare(0, 1, "-") != 0)
select = true;
extra_args(args, argidx, design);
}
if (buf_celltype.empty())
log_error("The -buf option is required.\n");
// Cell type, port name, bit index.
pool<pair<IdString, pair<IdString, int>>> sink_ports;
pool<pair<IdString, pair<IdString, int>>> buf_ports;
// Process submodules before module using them.
std::vector<Module *> modules_sorted;
pool<Module *> modules_processed;
for (auto module : design->selected_modules())
module_queue(design, module, modules_sorted, modules_processed);
for (auto module : modules_sorted)
{
if (module->get_blackbox_attribute()) {
for (auto port : module->ports) {
auto wire = module->wire(port);
if (wire->get_bool_attribute("\\clkbuf_driver"))
for (int i = 0; i < GetSize(wire); i++)
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
if (wire->get_bool_attribute("\\clkbuf_sink"))
for (int i = 0; i < GetSize(wire); i++)
sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
}
continue;
}
pool<SigBit> sink_wire_bits;
pool<SigBit> buf_wire_bits;
pool<SigBit> driven_wire_bits;
SigMap sigmap(module);
// bit -> (buffer, buffer's input)
dict<SigBit, pair<Cell *, Wire *>> buffered_bits;
// First, collect nets that could use a clock buffer.
for (auto cell : module->cells())
for (auto port : cell->connections())
for (int i = 0; i < port.second.size(); i++)
if (sink_ports.count(make_pair(cell->type, make_pair(port.first, i))))
sink_wire_bits.insert(sigmap(port.second[i]));
// Second, collect ones that already have a clock buffer.
for (auto cell : module->cells())
for (auto port : cell->connections())
for (int i = 0; i < port.second.size(); i++)
if (buf_ports.count(make_pair(cell->type, make_pair(port.first, i))))
buf_wire_bits.insert(sigmap(port.second[i]));
// Collect all driven bits.
for (auto cell : module->cells())
for (auto port : cell->connections())
if (cell->output(port.first))
for (int i = 0; i < port.second.size(); i++)
driven_wire_bits.insert(port.second[i]);
// Insert buffers.
std::vector<pair<Wire *, Wire *>> input_queue;
// Copy current wire list, as we will be adding new ones during iteration.
std::vector<Wire *> wires(module->wires());
for (auto wire : wires)
{
// Should not happen.
if (wire->port_input && wire->port_output)
continue;
bool process_wire = module->selected(wire);
if (!select && wire->get_bool_attribute("\\clkbuf_inhibit"))
process_wire = false;
if (!process_wire) {
// This wire is supposed to be bypassed, so make sure we don't buffer it in
// some buffer higher up in the hierarchy.
if (wire->port_output)
for (int i = 0; i < GetSize(wire); i++)
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
continue;
}
pool<int> input_bits;
for (int i = 0; i < GetSize(wire); i++)
{
SigBit wire_bit(wire, i);
SigBit mapped_wire_bit = sigmap(wire_bit);
if (buf_wire_bits.count(mapped_wire_bit)) {
// Already buffered downstream. If this is an output, mark it.
if (wire->port_output)
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
} else if (!sink_wire_bits.count(mapped_wire_bit)) {
// Nothing to do.
} else if (driven_wire_bits.count(wire_bit) || (wire->port_input && module->get_bool_attribute("\\top"))) {
// Clock network not yet buffered, driven by one of
// our cells or a top-level input -- buffer it.
log("Inserting %s on %s.%s[%d].\n", buf_celltype.c_str(), log_id(module), log_id(wire), i);
RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
Wire *iwire = module->addWire(NEW_ID);
cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
if (wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute("\\top")) {
log("Inserting %s on %s.%s[%d].\n", inpad_celltype.c_str(), log_id(module), log_id(wire), i);
RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype));
cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);
iwire = module->addWire(NEW_ID);
cell2->setPort(RTLIL::escape_id(inpad_portname2), iwire);
}
buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
if (wire->port_input) {
input_bits.insert(i);
}
} else if (wire->port_input) {
// A clock input in a submodule -- mark it, let higher level
// worry about it.
if (wire->port_input)
sink_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
}
}
if (!input_bits.empty()) {
// This is an input port and some buffers were inserted -- we need
// to create a new input wire and transfer attributes.
Wire *new_wire = module->addWire(NEW_ID, wire);
for (int i = 0; i < wire->width; i++) {
SigBit wire_bit(wire, i);
SigBit mapped_wire_bit = sigmap(wire_bit);
auto it = buffered_bits.find(mapped_wire_bit);
if (it != buffered_bits.end()) {
module->connect(it->second.second, SigSpec(new_wire, i));
} else {
module->connect(SigSpec(wire, i), SigSpec(new_wire, i));
}
}
input_queue.push_back(make_pair(wire, new_wire));
}
}
// Mark any newly-buffered output ports as such.
for (auto wire : module->selected_wires()) {
if (wire->port_input || !wire->port_output)
continue;
for (int i = 0; i < GetSize(wire); i++)
{
SigBit wire_bit(wire, i);
SigBit mapped_wire_bit = sigmap(wire_bit);
if (buffered_bits.count(mapped_wire_bit))
buf_ports.insert(make_pair(module->name, make_pair(wire->name, i)));
}
}
// Reconnect the drivers to buffer inputs.
for (auto cell : module->cells())
for (auto port : cell->connections()) {
if (!cell->output(port.first))
continue;
SigSpec sig = port.second;
bool newsig = false;
for (auto &bit : sig) {
const auto it = buffered_bits.find(sigmap(bit));
if (it == buffered_bits.end())
continue;
// Avoid substituting buffer's own output pin.
if (cell == it->second.first)
continue;
bit = it->second.second;
newsig = true;
}
if (newsig)
cell->setPort(port.first, sig);
}
// This has to be done last, to avoid upsetting sigmap before the port reconnections.
for (auto &it : input_queue) {
Wire *wire = it.first;
Wire *new_wire = it.second;
module->swap_names(new_wire, wire);
wire->attributes.clear();
wire->port_id = 0;
wire->port_input = false;
wire->port_output = false;
}
module->fixup_ports();
}
}
} ClkbufmapPass;
PRIVATE_NAMESPACE_END

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 == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_", "$tribuf")) if (conn.first == ID::Y && cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_TBUF_), ID($tribuf)))
{ {
bool tribuf = cell->type.in("$_TBUF_", "$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("\\A", "\\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

@ -52,13 +52,13 @@ struct Dff2dffeWorker
} }
for (auto cell : module->cells()) { for (auto cell : module->cells()) {
if (cell->type.in("$mux", "$pmux", "$_MUX_")) { if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\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);
} }
if (direct_dict.empty()) { if (direct_dict.empty()) {
if (cell->type.in("$dff", "$_DFF_N_", "$_DFF_P_")) if (cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_)))
dff_cells.push_back(cell); dff_cells.push_back(cell);
} else { } else {
if (direct_dict.count(cell->type)) if (direct_dict.count(cell->type))
@ -86,9 +86,9 @@ 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("\\A")); RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort(ID::A));
RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort("\\B")); RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort(ID::B));
RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort("\\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;
for (int i = 0; i < GetSize(sig_s); i++) for (int i = 0; i < GetSize(sig_s); i++)
@ -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("\\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("\\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("\\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("\\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("\\A"); RTLIL::SigSpec s = mux_cell_int.first->getPort(ID::A);
s[index] = RTLIL::Sx; s[index] = RTLIL::Sx;
mux_cell_int.first->setPort("\\A", s); mux_cell_int.first->setPort(ID::A, s);
} }
return ret; return ret;
@ -185,8 +185,8 @@ struct Dff2dffeWorker
void handle_dff_cell(RTLIL::Cell *dff_cell) void handle_dff_cell(RTLIL::Cell *dff_cell)
{ {
RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort("\\D")); RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort(ID(D)));
RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort("\\Q")); RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort(ID(Q)));
std::map<patterns_t, std::set<int>> grouped_patterns; std::map<patterns_t, std::set<int>> grouped_patterns;
std::set<int> remaining_indices; std::set<int> remaining_indices;
@ -208,16 +208,16 @@ struct Dff2dffeWorker
} }
if (!direct_dict.empty()) { if (!direct_dict.empty()) {
log(" converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_dict.at(dff_cell->type)), log_signal(new_sig_d), log_signal(new_sig_q)); log(" converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_dict.at(dff_cell->type)), log_signal(new_sig_d), log_signal(new_sig_q));
dff_cell->setPort("\\E", make_patterns_logic(it.first, true)); dff_cell->setPort(ID(E), make_patterns_logic(it.first, true));
dff_cell->type = direct_dict.at(dff_cell->type); dff_cell->type = direct_dict.at(dff_cell->type);
} else } else
if (dff_cell->type == "$dff") { if (dff_cell->type == ID($dff)) {
RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first, false), RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort(ID(CLK)), make_patterns_logic(it.first, false),
new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true); new_sig_d, new_sig_q, dff_cell->getParam(ID(CLK_POLARITY)).as_bool(), true);
log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
} else { } else {
RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort("\\C"), make_patterns_logic(it.first, true), RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort(ID(C)), make_patterns_logic(it.first, true),
new_sig_d, new_sig_q, dff_cell->type == "$_DFF_P_", true); new_sig_d, new_sig_q, dff_cell->type == ID($_DFF_P_), true);
log(" created %s cell %s for %s -> %s.\n", log_id(new_cell->type), log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q)); log(" created %s cell %s for %s -> %s.\n", log_id(new_cell->type), log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
} }
} }
@ -235,9 +235,9 @@ struct Dff2dffeWorker
new_sig_d.append(sig_d[i]); new_sig_d.append(sig_d[i]);
new_sig_q.append(sig_q[i]); new_sig_q.append(sig_q[i]);
} }
dff_cell->setPort("\\D", new_sig_d); dff_cell->setPort(ID(D), new_sig_d);
dff_cell->setPort("\\Q", new_sig_q); dff_cell->setPort(ID(Q), new_sig_q);
dff_cell->setParam("\\WIDTH", GetSize(remaining_indices)); dff_cell->setParam(ID(WIDTH), GetSize(remaining_indices));
} }
} }
@ -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");
@ -316,25 +316,25 @@ struct Dff2dffePass : public Pass {
if (args[argidx] == "-direct-match" && argidx + 1 < args.size()) { if (args[argidx] == "-direct-match" && argidx + 1 < args.size()) {
bool found_match = false; bool found_match = false;
const char *pattern = args[++argidx].c_str(); const char *pattern = args[++argidx].c_str();
if (patmatch(pattern, "$_DFF_P_" )) found_match = true, direct_dict["$_DFF_P_" ] = "$_DFFE_PP_"; if (patmatch(pattern, "$_DFF_P_" )) found_match = true, direct_dict[ID($_DFF_P_) ] = ID($_DFFE_PP_);
if (patmatch(pattern, "$_DFF_N_" )) found_match = true, direct_dict["$_DFF_N_" ] = "$_DFFE_NP_"; if (patmatch(pattern, "$_DFF_N_" )) found_match = true, direct_dict[ID($_DFF_N_) ] = ID($_DFFE_NP_);
if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict["$_DFF_NN0_"] = "$__DFFE_NN0"; if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict[ID($_DFF_NN0_)] = ID($__DFFE_NN0);
if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict["$_DFF_NN1_"] = "$__DFFE_NN1"; if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict[ID($_DFF_NN1_)] = ID($__DFFE_NN1);
if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict["$_DFF_NP0_"] = "$__DFFE_NP0"; if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict[ID($_DFF_NP0_)] = ID($__DFFE_NP0);
if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict["$_DFF_NP1_"] = "$__DFFE_NP1"; if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict[ID($_DFF_NP1_)] = ID($__DFFE_NP1);
if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict["$_DFF_PN0_"] = "$__DFFE_PN0"; if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict[ID($_DFF_PN0_)] = ID($__DFFE_PN0);
if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict["$_DFF_PN1_"] = "$__DFFE_PN1"; if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict[ID($_DFF_PN1_)] = ID($__DFFE_PN1);
if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict["$_DFF_PP0_"] = "$__DFFE_PP0"; if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict[ID($_DFF_PP0_)] = ID($__DFFE_PP0);
if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict["$_DFF_PP1_"] = "$__DFFE_PP1"; if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict[ID($_DFF_PP1_)] = ID($__DFFE_PP1);
if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict["$__DFFS_NN0_"] = "$__DFFSE_NN0"; if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict[ID($__DFFS_NN0_)] = ID($__DFFSE_NN0);
if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict["$__DFFS_NN1_"] = "$__DFFSE_NN1"; if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict[ID($__DFFS_NN1_)] = ID($__DFFSE_NN1);
if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict["$__DFFS_NP0_"] = "$__DFFSE_NP0"; if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict[ID($__DFFS_NP0_)] = ID($__DFFSE_NP0);
if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict["$__DFFS_NP1_"] = "$__DFFSE_NP1"; if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict[ID($__DFFS_NP1_)] = ID($__DFFSE_NP1);
if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict["$__DFFS_PN0_"] = "$__DFFSE_PN0"; if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict[ID($__DFFS_PN0_)] = ID($__DFFSE_PN0);
if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict["$__DFFS_PN1_"] = "$__DFFSE_PN1"; if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict[ID($__DFFS_PN1_)] = ID($__DFFSE_PN1);
if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict["$__DFFS_PP0_"] = "$__DFFSE_PP0"; if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict[ID($__DFFS_PP0_)] = ID($__DFFSE_PP0);
if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict["$__DFFS_PP1_"] = "$__DFFSE_PP1"; if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict[ID($__DFFS_PP1_)] = ID($__DFFSE_PP1);
if (!found_match) if (!found_match)
log_cmd_error("No cell types matched pattern '%s'.\n", pattern); log_cmd_error("No cell types matched pattern '%s'.\n", pattern);
continue; continue;
@ -355,25 +355,25 @@ struct Dff2dffePass : public Pass {
if (unmap_mode) { if (unmap_mode) {
SigMap sigmap(mod); SigMap sigmap(mod);
for (auto cell : mod->selected_cells()) { for (auto cell : mod->selected_cells()) {
if (cell->type == "$dffe") { if (cell->type == ID($dffe)) {
if (min_ce_use >= 0) { if (min_ce_use >= 0) {
int ce_use = 0; int ce_use = 0;
for (auto cell_other : mod->selected_cells()) { for (auto cell_other : mod->selected_cells()) {
if (cell_other->type != cell->type) if (cell_other->type != cell->type)
continue; continue;
if (sigmap(cell->getPort("\\EN")) == sigmap(cell_other->getPort("\\EN"))) if (sigmap(cell->getPort(ID(EN))) == sigmap(cell_other->getPort(ID(EN))))
ce_use++; ce_use++;
} }
if (ce_use >= min_ce_use) if (ce_use >= min_ce_use)
continue; continue;
} }
RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort("\\D"))); RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort(ID(D))));
mod->addDff(NEW_ID, cell->getPort("\\CLK"), tmp, cell->getPort("\\Q"), cell->getParam("\\CLK_POLARITY").as_bool()); mod->addDff(NEW_ID, cell->getPort(ID(CLK)), tmp, cell->getPort(ID(Q)), cell->getParam(ID(CLK_POLARITY)).as_bool());
if (cell->getParam("\\EN_POLARITY").as_bool()) if (cell->getParam(ID(EN_POLARITY)).as_bool())
mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\EN"), tmp); mod->addMux(NEW_ID, cell->getPort(ID(Q)), cell->getPort(ID(D)), cell->getPort(ID(EN)), tmp);
else else
mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\EN"), tmp); mod->addMux(NEW_ID, cell->getPort(ID(D)), cell->getPort(ID(Q)), cell->getPort(ID(EN)), tmp);
mod->remove(cell); mod->remove(cell);
continue; continue;
} }
@ -383,7 +383,7 @@ struct Dff2dffePass : public Pass {
for (auto cell_other : mod->selected_cells()) { for (auto cell_other : mod->selected_cells()) {
if (cell_other->type != cell->type) if (cell_other->type != cell->type)
continue; continue;
if (sigmap(cell->getPort("\\E")) == sigmap(cell_other->getPort("\\E"))) if (sigmap(cell->getPort(ID(E))) == sigmap(cell_other->getPort(ID(E))))
ce_use++; ce_use++;
} }
if (ce_use >= min_ce_use) if (ce_use >= min_ce_use)
@ -393,11 +393,11 @@ struct Dff2dffePass : public Pass {
bool clk_pol = cell->type.compare(7, 1, "P") == 0; bool clk_pol = cell->type.compare(7, 1, "P") == 0;
bool en_pol = cell->type.compare(8, 1, "P") == 0; bool en_pol = cell->type.compare(8, 1, "P") == 0;
RTLIL::SigSpec tmp = mod->addWire(NEW_ID); RTLIL::SigSpec tmp = mod->addWire(NEW_ID);
mod->addDff(NEW_ID, cell->getPort("\\C"), tmp, cell->getPort("\\Q"), clk_pol); mod->addDff(NEW_ID, cell->getPort(ID(C)), tmp, cell->getPort(ID(Q)), clk_pol);
if (en_pol) if (en_pol)
mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\E"), tmp); mod->addMux(NEW_ID, cell->getPort(ID(Q)), cell->getPort(ID(D)), cell->getPort(ID(E)), tmp);
else else
mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\E"), tmp); mod->addMux(NEW_ID, cell->getPort(ID(D)), cell->getPort(ID(Q)), cell->getPort(ID(E)), tmp);
mod->remove(cell); mod->remove(cell);
continue; continue;
} }

View file

@ -51,8 +51,8 @@ struct Dff2dffsPass : public Pass {
extra_args(args, argidx, design); extra_args(args, argidx, design);
pool<IdString> dff_types; pool<IdString> dff_types;
dff_types.insert("$_DFF_N_"); dff_types.insert(ID($_DFF_N_));
dff_types.insert("$_DFF_P_"); dff_types.insert(ID($_DFF_P_));
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
@ -69,19 +69,19 @@ struct Dff2dffsPass : public Pass {
continue; continue;
} }
if (cell->type != "$_MUX_") if (cell->type != ID($_MUX_))
continue; continue;
SigBit bit_a = sigmap(cell->getPort("\\A")); SigBit bit_a = sigmap(cell->getPort(ID::A));
SigBit bit_b = sigmap(cell->getPort("\\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("\\Y"))] = cell; sr_muxes[sigmap(cell->getPort(ID::Y))] = cell;
} }
for (auto cell : ff_cells) for (auto cell : ff_cells)
{ {
SigSpec sig_d = cell->getPort("\\D"); SigSpec sig_d = cell->getPort(ID(D));
if (GetSize(sig_d) < 1) if (GetSize(sig_d) < 1)
continue; continue;
@ -92,9 +92,9 @@ 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("\\A")); SigBit bit_a = sigmap(mux_cell->getPort(ID::A));
SigBit bit_b = sigmap(mux_cell->getPort("\\B")); SigBit bit_b = sigmap(mux_cell->getPort(ID::B));
SigBit bit_s = sigmap(mux_cell->getPort("\\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),
log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type)); log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
@ -114,26 +114,26 @@ struct Dff2dffsPass : public Pass {
} }
if (sr_val == State::S1) { if (sr_val == State::S1) {
if (cell->type == "$_DFF_N_") { if (cell->type == ID($_DFF_N_)) {
if (invert_sr) cell->type = "$__DFFS_NN1_"; if (invert_sr) cell->type = ID($__DFFS_NN1_);
else cell->type = "$__DFFS_NP1_"; else cell->type = ID($__DFFS_NP1_);
} else { } else {
log_assert(cell->type == "$_DFF_P_"); log_assert(cell->type == ID($_DFF_P_));
if (invert_sr) cell->type = "$__DFFS_PN1_"; if (invert_sr) cell->type = ID($__DFFS_PN1_);
else cell->type = "$__DFFS_PP1_"; else cell->type = ID($__DFFS_PP1_);
} }
} else { } else {
if (cell->type == "$_DFF_N_") { if (cell->type == ID($_DFF_N_)) {
if (invert_sr) cell->type = "$__DFFS_NN0_"; if (invert_sr) cell->type = ID($__DFFS_NN0_);
else cell->type = "$__DFFS_NP0_"; else cell->type = ID($__DFFS_NP0_);
} else { } else {
log_assert(cell->type == "$_DFF_P_"); log_assert(cell->type == ID($_DFF_P_));
if (invert_sr) cell->type = "$__DFFS_PN0_"; if (invert_sr) cell->type = ID($__DFFS_PN0_);
else cell->type = "$__DFFS_PP0_"; else cell->type = ID($__DFFS_PP0_);
} }
} }
cell->setPort("\\R", sr_sig); cell->setPort(ID(R), sr_sig);
cell->setPort("\\D", bit_d); cell->setPort(ID(D), bit_d);
} }
} }
} }

View file

@ -99,8 +99,8 @@ struct DffinitPass : public Pass {
pool<SigBit> used_bits; pool<SigBit> used_bits;
for (auto wire : module->selected_wires()) { for (auto wire : module->selected_wires()) {
if (wire->attributes.count("\\init")) { if (wire->attributes.count(ID(init))) {
Const value = wire->attributes.at("\\init"); Const value = wire->attributes.at(ID(init));
for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++)
if (value[i] != State::Sx) if (value[i] != State::Sx)
init_bits[sigmap(SigBit(wire, i))] = value[i]; init_bits[sigmap(SigBit(wire, i))] = value[i];
@ -161,8 +161,8 @@ struct DffinitPass : public Pass {
} }
for (auto wire : module->selected_wires()) for (auto wire : module->selected_wires())
if (wire->attributes.count("\\init")) { if (wire->attributes.count(ID(init))) {
Const &value = wire->attributes.at("\\init"); Const &value = wire->attributes.at(ID(init));
bool do_cleanup = true; bool do_cleanup = true;
for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) { for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) {
SigBit bit = sigmap(SigBit(wire, i)); SigBit bit = sigmap(SigBit(wire, i));
@ -173,7 +173,7 @@ struct DffinitPass : public Pass {
} }
if (do_cleanup) { if (do_cleanup) {
log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire)); log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire));
wire->attributes.erase("\\init"); wire->attributes.erase(ID(init));
} }
} }
} }

View file

@ -27,12 +27,12 @@ USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
struct cell_mapping { struct cell_mapping {
std::string cell_name; IdString cell_name;
std::map<std::string, char> ports; std::map<std::string, char> ports;
}; };
static std::map<RTLIL::IdString, cell_mapping> cell_mappings; static std::map<RTLIL::IdString, cell_mapping> cell_mappings;
static void logmap(std::string dff) static void logmap(IdString dff)
{ {
if (cell_mappings.count(dff) == 0) { if (cell_mappings.count(dff) == 0) {
log(" unmapped dff cell: %s\n", dff.c_str()); log(" unmapped dff cell: %s\n", dff.c_str());
@ -54,26 +54,26 @@ static void logmap(std::string dff)
static void logmap_all() static void logmap_all()
{ {
logmap("$_DFF_N_"); logmap(ID($_DFF_N_));
logmap("$_DFF_P_"); logmap(ID($_DFF_P_));
logmap("$_DFF_NN0_"); logmap(ID($_DFF_NN0_));
logmap("$_DFF_NN1_"); logmap(ID($_DFF_NN1_));
logmap("$_DFF_NP0_"); logmap(ID($_DFF_NP0_));
logmap("$_DFF_NP1_"); logmap(ID($_DFF_NP1_));
logmap("$_DFF_PN0_"); logmap(ID($_DFF_PN0_));
logmap("$_DFF_PN1_"); logmap(ID($_DFF_PN1_));
logmap("$_DFF_PP0_"); logmap(ID($_DFF_PP0_));
logmap("$_DFF_PP1_"); logmap(ID($_DFF_PP1_));
logmap("$_DFFSR_NNN_"); logmap(ID($_DFFSR_NNN_));
logmap("$_DFFSR_NNP_"); logmap(ID($_DFFSR_NNP_));
logmap("$_DFFSR_NPN_"); logmap(ID($_DFFSR_NPN_));
logmap("$_DFFSR_NPP_"); logmap(ID($_DFFSR_NPP_));
logmap("$_DFFSR_PNN_"); logmap(ID($_DFFSR_PNN_));
logmap("$_DFFSR_PNP_"); logmap(ID($_DFFSR_PNP_));
logmap("$_DFFSR_PPN_"); logmap(ID($_DFFSR_PPN_));
logmap("$_DFFSR_PPP_"); logmap(ID($_DFFSR_PPP_));
} }
static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol) static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol)
@ -115,7 +115,7 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
return false; return false;
} }
static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode) static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode)
{ {
LibertyAst *best_cell = NULL; LibertyAst *best_cell = NULL;
std::map<std::string, char> best_cell_ports; std::map<std::string, char> best_cell_ports;
@ -230,13 +230,13 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
cell_mappings[cell_type].ports["D"] = 'D'; cell_mappings[cell_type].ports["D"] = 'D';
cell_mappings[cell_type].ports["Q"] = 'Q'; cell_mappings[cell_type].ports["Q"] = 'Q';
} else { } else {
cell_mappings[cell_type].cell_name = best_cell->args[0]; cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
cell_mappings[cell_type].ports = best_cell_ports; cell_mappings[cell_type].ports = best_cell_ports;
} }
} }
} }
static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode) static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode)
{ {
LibertyAst *best_cell = NULL; LibertyAst *best_cell = NULL;
std::map<std::string, char> best_cell_ports; std::map<std::string, char> best_cell_ports;
@ -347,7 +347,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
cell_mappings[cell_type].ports["D"] = 'D'; cell_mappings[cell_type].ports["D"] = 'D';
cell_mappings[cell_type].ports["Q"] = 'Q'; cell_mappings[cell_type].ports["Q"] = 'Q';
} else { } else {
cell_mappings[cell_type].cell_name = best_cell->args[0]; cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
cell_mappings[cell_type].ports = best_cell_ports; cell_mappings[cell_type].ports = best_cell_ports;
} }
} }
@ -404,7 +404,7 @@ static bool expand_cellmap(std::string pattern, std::string inv)
return return_status; return return_status;
} }
static void map_sr_to_arst(const char *from, const char *to) static void map_sr_to_arst(IdString from, IdString to)
{ {
if (!cell_mappings.count(from) || cell_mappings.count(to) > 0) if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
return; return;
@ -419,7 +419,7 @@ static void map_sr_to_arst(const char *from, const char *to)
log_assert(from_clk_pol == to_clk_pol); log_assert(from_clk_pol == to_clk_pol);
log_assert(to_rst_pol == from_set_pol && to_rst_pol == from_clr_pol); log_assert(to_rst_pol == from_set_pol && to_rst_pol == from_clr_pol);
log(" create mapping for %s from mapping for %s.\n", to, from); log(" create mapping for %s from mapping for %s.\n", to.c_str(), from.c_str());
cell_mappings[to].cell_name = cell_mappings[from].cell_name; cell_mappings[to].cell_name = cell_mappings[from].cell_name;
cell_mappings[to].ports = cell_mappings[from].ports; cell_mappings[to].ports = cell_mappings[from].ports;
@ -450,7 +450,7 @@ static void map_sr_to_arst(const char *from, const char *to)
} }
} }
static void map_adff_to_dff(const char *from, const char *to) static void map_adff_to_dff(IdString from, IdString to)
{ {
if (!cell_mappings.count(from) || cell_mappings.count(to) > 0) if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
return; return;
@ -461,7 +461,7 @@ static void map_adff_to_dff(const char *from, const char *to)
log_assert(from_clk_pol == to_clk_pol); log_assert(from_clk_pol == to_clk_pol);
log(" create mapping for %s from mapping for %s.\n", to, from); log(" create mapping for %s from mapping for %s.\n", to.c_str(), from.c_str());
cell_mappings[to].cell_name = cell_mappings[from].cell_name; cell_mappings[to].cell_name = cell_mappings[from].cell_name;
cell_mappings[to].ports = cell_mappings[from].ports; cell_mappings[to].ports = cell_mappings[from].ports;
@ -484,8 +484,8 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
for (auto &it : module->cells_) { for (auto &it : module->cells_) {
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 == "$_NOT_") if (it.second->type == ID($_NOT_))
notmap[sigmap(it.second->getPort("\\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;
@ -499,7 +499,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
module->remove(cell); module->remove(cell);
cell_mapping &cm = cell_mappings[cell_type]; cell_mapping &cm = cell_mappings[cell_type];
RTLIL::Cell *new_cell = module->addCell(cell_name, prepare_mode ? cm.cell_name : "\\" + cm.cell_name); RTLIL::Cell *new_cell = module->addCell(cell_name, prepare_mode ? cm.cell_name : cm.cell_name);
new_cell->set_src_attribute(src); new_cell->set_src_attribute(src);
@ -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("\\Y"), sig); module->connect(it->getPort(ID::Y), sig);
it->setPort("\\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);
@ -599,26 +599,26 @@ struct DfflibmapPass : public Pass {
LibertyParser libparser(f); LibertyParser libparser(f);
f.close(); f.close();
find_cell(libparser.ast, "$_DFF_N_", false, false, false, false, prepare_mode); find_cell(libparser.ast, ID($_DFF_N_), false, false, false, false, prepare_mode);
find_cell(libparser.ast, "$_DFF_P_", true, false, false, false, prepare_mode); find_cell(libparser.ast, ID($_DFF_P_), true, false, false, false, prepare_mode);
find_cell(libparser.ast, "$_DFF_NN0_", false, true, false, false, prepare_mode); find_cell(libparser.ast, ID($_DFF_NN0_), false, true, false, false, prepare_mode);
find_cell(libparser.ast, "$_DFF_NN1_", false, true, false, true, prepare_mode); find_cell(libparser.ast, ID($_DFF_NN1_), false, true, false, true, prepare_mode);
find_cell(libparser.ast, "$_DFF_NP0_", false, true, true, false, prepare_mode); find_cell(libparser.ast, ID($_DFF_NP0_), false, true, true, false, prepare_mode);
find_cell(libparser.ast, "$_DFF_NP1_", false, true, true, true, prepare_mode); find_cell(libparser.ast, ID($_DFF_NP1_), false, true, true, true, prepare_mode);
find_cell(libparser.ast, "$_DFF_PN0_", true, true, false, false, prepare_mode); find_cell(libparser.ast, ID($_DFF_PN0_), true, true, false, false, prepare_mode);
find_cell(libparser.ast, "$_DFF_PN1_", true, true, false, true, prepare_mode); find_cell(libparser.ast, ID($_DFF_PN1_), true, true, false, true, prepare_mode);
find_cell(libparser.ast, "$_DFF_PP0_", true, true, true, false, prepare_mode); find_cell(libparser.ast, ID($_DFF_PP0_), true, true, true, false, prepare_mode);
find_cell(libparser.ast, "$_DFF_PP1_", true, true, true, true, prepare_mode); find_cell(libparser.ast, ID($_DFF_PP1_), true, true, true, true, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_NNN_", false, false, false, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_NNN_), false, false, false, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_NNP_", false, false, true, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_NNP_), false, false, true, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_NPN_", false, true, false, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_NPN_), false, true, false, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_NPP_", false, true, true, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_NPP_), false, true, true, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_PNN_", true, false, false, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_PNN_), true, false, false, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_PNP_", true, false, true, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_PNP_), true, false, true, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_PPN_", true, true, false, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_PPN_), true, true, false, prepare_mode);
find_cell_sr(libparser.ast, "$_DFFSR_PPP_", true, true, true, prepare_mode); find_cell_sr(libparser.ast, ID($_DFFSR_PPP_), true, true, true, prepare_mode);
// try to implement as many cells as possible just by inverting // try to implement as many cells as possible just by inverting
// the SET and RESET pins. If necessary, implement cell types // the SET and RESET pins. If necessary, implement cell types
@ -642,23 +642,23 @@ struct DfflibmapPass : public Pass {
break; break;
} }
map_sr_to_arst("$_DFFSR_NNN_", "$_DFF_NN0_"); map_sr_to_arst(ID($_DFFSR_NNN_), ID($_DFF_NN0_));
map_sr_to_arst("$_DFFSR_NNN_", "$_DFF_NN1_"); map_sr_to_arst(ID($_DFFSR_NNN_), ID($_DFF_NN1_));
map_sr_to_arst("$_DFFSR_NPP_", "$_DFF_NP0_"); map_sr_to_arst(ID($_DFFSR_NPP_), ID($_DFF_NP0_));
map_sr_to_arst("$_DFFSR_NPP_", "$_DFF_NP1_"); map_sr_to_arst(ID($_DFFSR_NPP_), ID($_DFF_NP1_));
map_sr_to_arst("$_DFFSR_PNN_", "$_DFF_PN0_"); map_sr_to_arst(ID($_DFFSR_PNN_), ID($_DFF_PN0_));
map_sr_to_arst("$_DFFSR_PNN_", "$_DFF_PN1_"); map_sr_to_arst(ID($_DFFSR_PNN_), ID($_DFF_PN1_));
map_sr_to_arst("$_DFFSR_PPP_", "$_DFF_PP0_"); map_sr_to_arst(ID($_DFFSR_PPP_), ID($_DFF_PP0_));
map_sr_to_arst("$_DFFSR_PPP_", "$_DFF_PP1_"); map_sr_to_arst(ID($_DFFSR_PPP_), ID($_DFF_PP1_));
map_adff_to_dff("$_DFF_NN0_", "$_DFF_N_"); map_adff_to_dff(ID($_DFF_NN0_), ID($_DFF_N_));
map_adff_to_dff("$_DFF_NN1_", "$_DFF_N_"); map_adff_to_dff(ID($_DFF_NN1_), ID($_DFF_N_));
map_adff_to_dff("$_DFF_NP0_", "$_DFF_N_"); map_adff_to_dff(ID($_DFF_NP0_), ID($_DFF_N_));
map_adff_to_dff("$_DFF_NP1_", "$_DFF_N_"); map_adff_to_dff(ID($_DFF_NP1_), ID($_DFF_N_));
map_adff_to_dff("$_DFF_PN0_", "$_DFF_P_"); map_adff_to_dff(ID($_DFF_PN0_), ID($_DFF_P_));
map_adff_to_dff("$_DFF_PN1_", "$_DFF_P_"); map_adff_to_dff(ID($_DFF_PN1_), ID($_DFF_P_));
map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_"); map_adff_to_dff(ID($_DFF_PP0_), ID($_DFF_P_));
map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_"); map_adff_to_dff(ID($_DFF_PP1_), ID($_DFF_P_));
log(" final dff cell mappings:\n"); log(" final dff cell mappings:\n");
logmap_all(); logmap_all();

View file

@ -25,17 +25,17 @@ PRIVATE_NAMESPACE_BEGIN
void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell) void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
{ {
if (cell->type == "$dffsr") if (cell->type == ID($dffsr))
{ {
int width = cell->getParam("\\WIDTH").as_int(); int width = cell->getParam(ID(WIDTH)).as_int();
bool setpol = cell->getParam("\\SET_POLARITY").as_bool(); bool setpol = cell->getParam(ID(SET_POLARITY)).as_bool();
bool clrpol = cell->getParam("\\CLR_POLARITY").as_bool(); bool clrpol = cell->getParam(ID(CLR_POLARITY)).as_bool();
SigBit setunused = setpol ? State::S0 : State::S1; SigBit setunused = setpol ? State::S0 : State::S1;
SigBit clrunused = clrpol ? State::S0 : State::S1; SigBit clrunused = clrpol ? State::S0 : State::S1;
SigSpec setsig = sigmap(cell->getPort("\\SET")); SigSpec setsig = sigmap(cell->getPort(ID(SET)));
SigSpec clrsig = sigmap(cell->getPort("\\CLR")); SigSpec clrsig = sigmap(cell->getPort(ID(CLR)));
Const reset_val; Const reset_val;
SigSpec setctrl, clrctrl; SigSpec setctrl, clrctrl;
@ -78,32 +78,32 @@ void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
log("Converting %s cell %s.%s to $adff.\n", log_id(cell->type), log_id(module), log_id(cell)); log("Converting %s cell %s.%s to $adff.\n", log_id(cell->type), log_id(module), log_id(cell));
if (GetSize(setctrl) == 1) { if (GetSize(setctrl) == 1) {
cell->setPort("\\ARST", setctrl); cell->setPort(ID(ARST), setctrl);
cell->setParam("\\ARST_POLARITY", setpol); cell->setParam(ID(ARST_POLARITY), setpol);
} else { } else {
cell->setPort("\\ARST", clrctrl); cell->setPort(ID(ARST), clrctrl);
cell->setParam("\\ARST_POLARITY", clrpol); cell->setParam(ID(ARST_POLARITY), clrpol);
} }
cell->type = "$adff"; cell->type = ID($adff);
cell->unsetPort("\\SET"); cell->unsetPort(ID(SET));
cell->unsetPort("\\CLR"); cell->unsetPort(ID(CLR));
cell->setParam("\\ARST_VALUE", reset_val); cell->setParam(ID(ARST_VALUE), reset_val);
cell->unsetParam("\\SET_POLARITY"); cell->unsetParam(ID(SET_POLARITY));
cell->unsetParam("\\CLR_POLARITY"); cell->unsetParam(ID(CLR_POLARITY));
return; return;
} }
if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_", if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_")) ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
{ {
char clkpol = cell->type.c_str()[8]; char clkpol = cell->type.c_str()[8];
char setpol = cell->type.c_str()[9]; char setpol = cell->type.c_str()[9];
char clrpol = cell->type.c_str()[10]; char clrpol = cell->type.c_str()[10];
SigBit setbit = sigmap(cell->getPort("\\S")); SigBit setbit = sigmap(cell->getPort(ID(S)));
SigBit clrbit = sigmap(cell->getPort("\\R")); SigBit clrbit = sigmap(cell->getPort(ID(R)));
SigBit setunused = setpol == 'P' ? State::S0 : State::S1; SigBit setunused = setpol == 'P' ? State::S0 : State::S1;
SigBit clrunused = clrpol == 'P' ? State::S0 : State::S1; SigBit clrunused = clrpol == 'P' ? State::S0 : State::S1;
@ -112,14 +112,14 @@ void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
if (setbit == setunused) { if (setbit == setunused) {
cell->type = stringf("$_DFF_%c%c0_", clkpol, clrpol); cell->type = stringf("$_DFF_%c%c0_", clkpol, clrpol);
cell->unsetPort("\\S"); cell->unsetPort(ID(S));
goto converted_gate; goto converted_gate;
} }
if (clrbit == clrunused) { if (clrbit == clrunused) {
cell->type = stringf("$_DFF_%c%c1_", clkpol, setpol); cell->type = stringf("$_DFF_%c%c1_", clkpol, setpol);
cell->setPort("\\R", cell->getPort("\\S")); cell->setPort(ID(R), cell->getPort(ID(S)));
cell->unsetPort("\\S"); cell->unsetPort(ID(S));
goto converted_gate; goto converted_gate;
} }
@ -133,32 +133,32 @@ void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
void adff_worker(SigMap &sigmap, Module *module, Cell *cell) void adff_worker(SigMap &sigmap, Module *module, Cell *cell)
{ {
if (cell->type == "$adff") if (cell->type == ID($adff))
{ {
bool rstpol = cell->getParam("\\ARST_POLARITY").as_bool(); bool rstpol = cell->getParam(ID(ARST_POLARITY)).as_bool();
SigBit rstunused = rstpol ? State::S0 : State::S1; SigBit rstunused = rstpol ? State::S0 : State::S1;
SigSpec rstsig = sigmap(cell->getPort("\\ARST")); SigSpec rstsig = sigmap(cell->getPort(ID(ARST)));
if (rstsig != rstunused) if (rstsig != rstunused)
return; return;
log("Converting %s cell %s.%s to $dff.\n", log_id(cell->type), log_id(module), log_id(cell)); log("Converting %s cell %s.%s to $dff.\n", log_id(cell->type), log_id(module), log_id(cell));
cell->type = "$dff"; cell->type = ID($dff);
cell->unsetPort("\\ARST"); cell->unsetPort(ID(ARST));
cell->unsetParam("\\ARST_VALUE"); cell->unsetParam(ID(ARST_VALUE));
cell->unsetParam("\\ARST_POLARITY"); cell->unsetParam(ID(ARST_POLARITY));
return; return;
} }
if (cell->type.in("$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_")) ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
{ {
char clkpol = cell->type.c_str()[6]; char clkpol = cell->type.c_str()[6];
char rstpol = cell->type.c_str()[7]; char rstpol = cell->type.c_str()[7];
SigBit rstbit = sigmap(cell->getPort("\\R")); SigBit rstbit = sigmap(cell->getPort(ID(R)));
SigBit rstunused = rstpol == 'P' ? State::S0 : State::S1; SigBit rstunused = rstpol == 'P' ? State::S0 : State::S1;
if (rstbit != rstunused) if (rstbit != rstunused)
@ -168,7 +168,7 @@ void adff_worker(SigMap &sigmap, Module *module, Cell *cell)
log("Converting %s cell %s.%s to %s.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(newtype)); log("Converting %s cell %s.%s to %s.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(newtype));
cell->type = newtype; cell->type = newtype;
cell->unsetPort("\\R"); cell->unsetPort(ID(R));
return; return;
} }

View file

@ -58,36 +58,36 @@ public:
return value; return value;
#define param_bool(_n) if (param == _n) return value.as_bool(); #define param_bool(_n) if (param == _n) return value.as_bool();
param_bool("\\ARST_POLARITY"); param_bool(ID(ARST_POLARITY));
param_bool("\\A_SIGNED"); param_bool(ID(A_SIGNED));
param_bool("\\B_SIGNED"); param_bool(ID(B_SIGNED));
param_bool("\\CLK_ENABLE"); param_bool(ID(CLK_ENABLE));
param_bool("\\CLK_POLARITY"); param_bool(ID(CLK_POLARITY));
param_bool("\\CLR_POLARITY"); param_bool(ID(CLR_POLARITY));
param_bool("\\EN_POLARITY"); param_bool(ID(EN_POLARITY));
param_bool("\\SET_POLARITY"); param_bool(ID(SET_POLARITY));
param_bool("\\TRANSPARENT"); param_bool(ID(TRANSPARENT));
#undef param_bool #undef param_bool
#define param_int(_n) if (param == _n) return value.as_int(); #define param_int(_n) if (param == _n) return value.as_int();
param_int("\\ABITS") param_int(ID(ABITS))
param_int("\\A_WIDTH") param_int(ID(A_WIDTH))
param_int("\\B_WIDTH") param_int(ID(B_WIDTH))
param_int("\\CTRL_IN_WIDTH") param_int(ID(CTRL_IN_WIDTH))
param_int("\\CTRL_OUT_WIDTH") param_int(ID(CTRL_OUT_WIDTH))
param_int("\\OFFSET") param_int(ID(OFFSET))
param_int("\\PRIORITY") param_int(ID(PRIORITY))
param_int("\\RD_PORTS") param_int(ID(RD_PORTS))
param_int("\\SIZE") param_int(ID(SIZE))
param_int("\\STATE_BITS") param_int(ID(STATE_BITS))
param_int("\\STATE_NUM") param_int(ID(STATE_NUM))
param_int("\\STATE_NUM_LOG2") param_int(ID(STATE_NUM_LOG2))
param_int("\\STATE_RST") param_int(ID(STATE_RST))
param_int("\\S_WIDTH") param_int(ID(S_WIDTH))
param_int("\\TRANS_NUM") param_int(ID(TRANS_NUM))
param_int("\\WIDTH") param_int(ID(WIDTH))
param_int("\\WR_PORTS") param_int(ID(WR_PORTS))
param_int("\\Y_WIDTH") param_int(ID(Y_WIDTH))
#undef param_int #undef param_int
return value; return value;
@ -341,10 +341,10 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit:
bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right) bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right)
{ {
int left_idx = 0, right_idx = 0; int left_idx = 0, right_idx = 0;
if (left->attributes.count("\\extract_order") > 0) if (left->attributes.count(ID(extract_order)) > 0)
left_idx = left->attributes.at("\\extract_order").as_int(); left_idx = left->attributes.at(ID(extract_order)).as_int();
if (right->attributes.count("\\extract_order") > 0) if (right->attributes.count(ID(extract_order)) > 0)
right_idx = right->attributes.at("\\extract_order").as_int(); right_idx = right->attributes.at(ID(extract_order)).as_int();
if (left_idx != right_idx) if (left_idx != right_idx)
return left_idx < right_idx; return left_idx < right_idx;
return left->name < right->name; return left->name < right->name;

View file

@ -120,71 +120,71 @@ int counter_tryextract(
//A counter with less than 2 bits makes no sense //A counter with less than 2 bits makes no sense
//TODO: configurable min threshold //TODO: configurable min threshold
int a_width = cell->getParam("\\A_WIDTH").as_int(); int a_width = cell->getParam(ID(A_WIDTH)).as_int();
extract.width = a_width; extract.width = a_width;
if( (a_width < 2) || (a_width > maxwidth) ) if( (a_width < 2) || (a_width > maxwidth) )
return 1; return 1;
//Second input must be a single bit //Second input must be a single bit
int b_width = cell->getParam("\\B_WIDTH").as_int(); int b_width = cell->getParam(ID(B_WIDTH)).as_int();
if(b_width != 1) if(b_width != 1)
return 2; return 2;
//Both inputs must be unsigned, so don't extract anything with a signed input //Both inputs must be unsigned, so don't extract anything with a signed input
bool a_sign = cell->getParam("\\A_SIGNED").as_bool(); bool a_sign = cell->getParam(ID(A_SIGNED)).as_bool();
bool b_sign = cell->getParam("\\B_SIGNED").as_bool(); bool b_sign = cell->getParam(ID(B_SIGNED)).as_bool();
if(a_sign || b_sign) if(a_sign || b_sign)
return 3; return 3;
//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("\\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;
//BI and CI must be constant 1 as well //BI and CI must be constant 1 as well
const RTLIL::SigSpec bi_port = sigmap(cell->getPort("\\BI")); const RTLIL::SigSpec bi_port = sigmap(cell->getPort(ID(BI)));
if(!bi_port.is_fully_const() || (bi_port.as_int() != 1) ) if(!bi_port.is_fully_const() || (bi_port.as_int() != 1) )
return 5; return 5;
const RTLIL::SigSpec ci_port = sigmap(cell->getPort("\\CI")); const RTLIL::SigSpec ci_port = sigmap(cell->getPort(ID(CI)));
if(!ci_port.is_fully_const() || (ci_port.as_int() != 1) ) if(!ci_port.is_fully_const() || (ci_port.as_int() != 1) )
return 6; return 6;
//CO and X must be unconnected (exactly one connection to each port) //CO and X must be unconnected (exactly one connection to each port)
if(!is_unconnected(sigmap(cell->getPort("\\CO")), index)) if(!is_unconnected(sigmap(cell->getPort(ID(CO))), index))
return 7; return 7;
if(!is_unconnected(sigmap(cell->getPort("\\X")), index)) if(!is_unconnected(sigmap(cell->getPort(ID(X))), index))
return 8; return 8;
//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("\\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;
Cell* count_mux = *y_loads.begin(); Cell* count_mux = *y_loads.begin();
extract.count_mux = count_mux; extract.count_mux = count_mux;
if(count_mux->type != "$mux") if(count_mux->type != ID($mux))
return 10; return 10;
if(!is_full_bus(aluy, index, cell, "\\Y", count_mux, "\\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("\\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();
//S connection of the mux must come from an inverter (need not be the only load) //S connection of the mux must come from an inverter (need not be the only load)
const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort("\\S")); const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort(ID(S)));
extract.outsig = muxsel; extract.outsig = muxsel;
pool<Cell*> muxsel_conns = get_other_cells(muxsel, index, count_mux); pool<Cell*> muxsel_conns = get_other_cells(muxsel, index, count_mux);
Cell* underflow_inv = NULL; Cell* underflow_inv = NULL;
for(auto c : muxsel_conns) for(auto c : muxsel_conns)
{ {
if(c->type != "$logic_not") if(c->type != ID($logic_not))
continue; continue;
if(!is_full_bus(muxsel, index, c, "\\Y", count_mux, "\\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("\\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;
@ -204,12 +204,12 @@ int counter_tryextract(
Cell* count_reg = muxload; Cell* count_reg = muxload;
Cell* cemux = NULL; Cell* cemux = NULL;
RTLIL::SigSpec cey; RTLIL::SigSpec cey;
if(muxload->type == "$mux") if(muxload->type == ID($mux))
{ {
//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("\\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,32 +217,32 @@ 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("\\B")) != muxy) if(sigmap(cemux->getPort(ID::B)) != muxy)
return 24; return 24;
if(sigmap(cemux->getPort("\\A")) != sigmap(count_reg->getPort("\\Q"))) if(sigmap(cemux->getPort(ID::A)) != sigmap(count_reg->getPort(ID(Q))))
return 24; return 24;
if(sigmap(cemux->getPort("\\Y")) != sigmap(count_reg->getPort("\\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
extract.has_ce = true; extract.has_ce = true;
extract.ce = sigmap(cemux->getPort("\\S")); extract.ce = sigmap(cemux->getPort(ID(S)));
} }
else else
extract.has_ce = false; extract.has_ce = false;
extract.count_reg = count_reg; extract.count_reg = count_reg;
if(count_reg->type == "$dff") if(count_reg->type == ID($dff))
extract.has_reset = false; extract.has_reset = false;
else if(count_reg->type == "$adff") else if(count_reg->type == ID($adff))
{ {
extract.has_reset = true; extract.has_reset = true;
//Check polarity of reset - we may have to add an inverter later on! //Check polarity of reset - we may have to add an inverter later on!
extract.rst_inverted = (count_reg->getParam("\\ARST_POLARITY").as_int() != 1); extract.rst_inverted = (count_reg->getParam(ID(ARST_POLARITY)).as_int() != 1);
//Verify ARST_VALUE is zero or full scale //Verify ARST_VALUE is zero or full scale
int rst_value = count_reg->getParam("\\ARST_VALUE").as_int(); int rst_value = count_reg->getParam(ID(ARST_VALUE)).as_int();
if(rst_value == 0) if(rst_value == 0)
extract.rst_to_max = false; extract.rst_to_max = false;
else if(rst_value == extract.count_value) else if(rst_value == extract.count_value)
@ -251,7 +251,7 @@ int counter_tryextract(
return 23; return 23;
//Save the reset //Save the reset
extract.rst = sigmap(count_reg->getPort("\\ARST")); extract.rst = sigmap(count_reg->getPort(ID(ARST)));
} }
//TODO: support synchronous reset //TODO: support synchronous reset
else else
@ -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, "\\Y", cemux, "\\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, "\\Y", count_reg, "\\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, "\\Y", count_reg, "\\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
@ -273,7 +273,7 @@ int counter_tryextract(
//Register output must have exactly two loads, the inverter and ALU //Register output must have exactly two loads, the inverter and ALU
//(unless we have a parallel output!) //(unless we have a parallel output!)
//If we have a clock enable, 3 is OK //If we have a clock enable, 3 is OK
const RTLIL::SigSpec qport = count_reg->getPort("\\Q"); const RTLIL::SigSpec qport = count_reg->getPort(ID(Q));
const RTLIL::SigSpec cnout = sigmap(qport); const RTLIL::SigSpec cnout = sigmap(qport);
pool<Cell*> cnout_loads = get_other_cells(cnout, index, count_reg); pool<Cell*> cnout_loads = get_other_cells(cnout, index, count_reg);
unsigned int max_loads = 2; unsigned int max_loads = 2;
@ -312,19 +312,19 @@ int counter_tryextract(
} }
} }
} }
if(!is_full_bus(cnout, index, count_reg, "\\Q", underflow_inv, "\\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, "\\Q", cell, "\\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
extract.clk = sigmap(count_reg->getPort("\\CLK")); extract.clk = sigmap(count_reg->getPort(ID(CLK)));
//Register output net must have an INIT attribute equal to the count value //Register output net must have an INIT attribute equal to the count value
extract.rwire = cnout.as_wire(); extract.rwire = cnout.as_wire();
if(extract.rwire->attributes.find("\\init") == extract.rwire->attributes.end()) if(extract.rwire->attributes.find(ID(init)) == extract.rwire->attributes.end())
return 20; return 20;
int rinit = extract.rwire->attributes["\\init"].as_int(); int rinit = extract.rwire->attributes[ID(init)].as_int();
if(rinit != extract.count_value) if(rinit != extract.count_value)
return 21; return 21;
@ -343,21 +343,21 @@ void counter_worker(
SigMap& sigmap = index.sigmap; SigMap& sigmap = index.sigmap;
//Core of the counter must be an ALU //Core of the counter must be an ALU
if (cell->type != "$alu") if (cell->type != ID($alu))
return; return;
//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("\\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();
bool force_extract = false; bool force_extract = false;
bool never_extract = false; bool never_extract = false;
string count_reg_src = a_wire->attributes["\\src"].decode_string().c_str(); string count_reg_src = a_wire->attributes[ID(src)].decode_string().c_str();
if(a_wire->attributes.find("\\COUNT_EXTRACT") != a_wire->attributes.end()) if(a_wire->attributes.find(ID(COUNT_EXTRACT)) != a_wire->attributes.end())
{ {
pool<string> sa = a_wire->get_strpool_attribute("\\COUNT_EXTRACT"); pool<string> sa = a_wire->get_strpool_attribute(ID(COUNT_EXTRACT));
string extract_value; string extract_value;
if(sa.size() >= 1) if(sa.size() >= 1)
{ {
@ -434,66 +434,66 @@ 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("\\A"); cell->unsetPort(ID::A);
cell->unsetPort("\\B"); cell->unsetPort(ID::B);
cell->unsetPort("\\BI"); cell->unsetPort(ID(BI));
cell->unsetPort("\\CI"); cell->unsetPort(ID(CI));
cell->unsetPort("\\CO"); cell->unsetPort(ID(CO));
cell->unsetPort("\\X"); cell->unsetPort(ID(X));
cell->unsetPort("\\Y"); cell->unsetPort(ID::Y);
cell->unsetParam("\\A_SIGNED"); cell->unsetParam(ID(A_SIGNED));
cell->unsetParam("\\A_WIDTH"); cell->unsetParam(ID(A_WIDTH));
cell->unsetParam("\\B_SIGNED"); cell->unsetParam(ID(B_SIGNED));
cell->unsetParam("\\B_WIDTH"); cell->unsetParam(ID(B_WIDTH));
cell->unsetParam("\\Y_WIDTH"); cell->unsetParam(ID(Y_WIDTH));
//Change the cell type //Change the cell type
cell->type = "$__COUNT_"; cell->type = ID($__COUNT_);
//Hook up resets //Hook up resets
if(extract.has_reset) if(extract.has_reset)
{ {
//TODO: support other kinds of reset //TODO: support other kinds of reset
cell->setParam("\\RESET_MODE", RTLIL::Const("LEVEL")); cell->setParam(ID(RESET_MODE), RTLIL::Const("LEVEL"));
//If the reset is active low, infer an inverter ($__COUNT_ cells always have active high reset) //If the reset is active low, infer an inverter ($__COUNT_ cells always have active high reset)
if(extract.rst_inverted) if(extract.rst_inverted)
{ {
auto realreset = cell->module->addWire(NEW_ID); auto realreset = cell->module->addWire(NEW_ID);
cell->module->addNot(NEW_ID, extract.rst, RTLIL::SigSpec(realreset)); cell->module->addNot(NEW_ID, extract.rst, RTLIL::SigSpec(realreset));
cell->setPort("\\RST", realreset); cell->setPort(ID(RST), realreset);
} }
else else
cell->setPort("\\RST", extract.rst); cell->setPort(ID(RST), extract.rst);
} }
else else
{ {
cell->setParam("\\RESET_MODE", RTLIL::Const("RISING")); cell->setParam(ID(RESET_MODE), RTLIL::Const("RISING"));
cell->setPort("\\RST", RTLIL::SigSpec(false)); cell->setPort(ID(RST), RTLIL::SigSpec(false));
} }
//Hook up other stuff //Hook up other stuff
//cell->setParam("\\CLKIN_DIVIDE", RTLIL::Const(1)); //cell->setParam(ID(CLKIN_DIVIDE), RTLIL::Const(1));
cell->setParam("\\COUNT_TO", RTLIL::Const(extract.count_value)); cell->setParam(ID(COUNT_TO), RTLIL::Const(extract.count_value));
cell->setParam("\\WIDTH", RTLIL::Const(extract.width)); cell->setParam(ID(WIDTH), RTLIL::Const(extract.width));
cell->setPort("\\CLK", extract.clk); cell->setPort(ID(CLK), extract.clk);
cell->setPort("\\OUT", extract.outsig); cell->setPort(ID(OUT), extract.outsig);
//Hook up clock enable //Hook up clock enable
if(extract.has_ce) if(extract.has_ce)
{ {
cell->setParam("\\HAS_CE", RTLIL::Const(1)); cell->setParam(ID(HAS_CE), RTLIL::Const(1));
cell->setPort("\\CE", extract.ce); cell->setPort(ID(CE), extract.ce);
} }
else else
cell->setParam("\\HAS_CE", RTLIL::Const(0)); cell->setParam(ID(HAS_CE), RTLIL::Const(0));
//Hook up hard-wired ports (for now up/down are not supported), default to no parallel output //Hook up hard-wired ports (for now up/down are not supported), default to no parallel output
cell->setParam("\\HAS_POUT", RTLIL::Const(0)); cell->setParam(ID(HAS_POUT), RTLIL::Const(0));
cell->setParam("\\RESET_TO_MAX", RTLIL::Const(0)); cell->setParam(ID(RESET_TO_MAX), RTLIL::Const(0));
cell->setParam("\\DIRECTION", RTLIL::Const("DOWN")); cell->setParam(ID(DIRECTION), RTLIL::Const("DOWN"));
cell->setPort("\\CE", RTLIL::Const(1)); cell->setPort(ID(CE), RTLIL::Const(1));
cell->setPort("\\UP", RTLIL::Const(0)); cell->setPort(ID(UP), RTLIL::Const(0));
//Hook up any parallel outputs //Hook up any parallel outputs
for(auto load : extract.pouts) for(auto load : extract.pouts)
@ -505,8 +505,8 @@ void counter_worker(
//Connect it to our parallel output //Connect it to our parallel output
//(this is OK to do more than once b/c they all go to the same place) //(this is OK to do more than once b/c they all go to the same place)
cell->setPort("\\POUT", sig); cell->setPort(ID(POUT), sig);
cell->setParam("\\HAS_POUT", RTLIL::Const(1)); cell->setParam(ID(HAS_POUT), RTLIL::Const(1));
} }
//Delete the cells we've replaced (let opt_clean handle deleting the now-redundant wires) //Delete the cells we've replaced (let opt_clean handle deleting the now-redundant wires)
@ -546,7 +546,7 @@ void counter_worker(
int newbits = ceil(log2(extract.count_value)); int newbits = ceil(log2(extract.count_value));
if(extract.width != newbits) if(extract.width != newbits)
{ {
cell->setParam("\\WIDTH", RTLIL::Const(newbits)); cell->setParam(ID(WIDTH), RTLIL::Const(newbits));
log(" Optimizing out %d unused high-order bits (new width is %d)\n", log(" Optimizing out %d unused high-order bits (new width is %d)\n",
extract.width - newbits, extract.width - newbits,
newbits); newbits);

View file

@ -85,11 +85,11 @@ struct ExtractFaWorker
{ {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", if (cell->type.in( ID($_BUF_), ID($_NOT_), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_),
"$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", "$_NMUX_", ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($_MUX_), ID($_NMUX_),
"$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
{ {
SigBit y = sigmap(SigBit(cell->getPort("\\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,10 +262,10 @@ struct ExtractFaWorker
pool<SigBit> new_leaves = leaves; pool<SigBit> new_leaves = leaves;
new_leaves.erase(bit); new_leaves.erase(bit);
if (cell->hasPort("\\A")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\A")))); if (cell->hasPort(ID::A)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::A))));
if (cell->hasPort("\\B")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\B")))); if (cell->hasPort(ID::B)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::B))));
if (cell->hasPort("\\C")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\C")))); if (cell->hasPort(ID(C))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(C)))));
if (cell->hasPort("\\D")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\D")))); if (cell->hasPort(ID(D))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(D)))));
if (GetSize(new_leaves) > maxbreadth) if (GetSize(new_leaves) > maxbreadth)
continue; continue;
@ -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("\\Y")) == bit) { if (sigmap(cell->getPort(ID::Y)) == bit) {
cell->setPort("\\Y", module->addWire(NEW_ID)); cell->setPort(ID::Y, module->addWire(NEW_ID));
module->connect(bit, new_driver); module->connect(bit, new_driver);
} }
} }
@ -289,7 +289,7 @@ struct ExtractFaWorker
for (auto it : driver) for (auto it : driver)
{ {
if (it.second->type.in("$_BUF_", "$_NOT_")) if (it.second->type.in(ID($_BUF_), ID($_NOT_)))
continue; continue;
SigBit root = it.first; SigBit root = it.first;
@ -390,20 +390,20 @@ struct ExtractFaWorker
} }
else else
{ {
Cell *cell = module->addCell(NEW_ID, "$fa"); Cell *cell = module->addCell(NEW_ID, ID($fa));
cell->setParam("\\WIDTH", 1); cell->setParam(ID(WIDTH), 1);
log(" Created $fa cell %s.\n", log_id(cell)); log(" Created $fa cell %s.\n", log_id(cell));
cell->setPort("\\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("\\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("\\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("\\X", X); cell->setPort(ID(X), X);
cell->setPort("\\Y", Y); cell->setPort(ID::Y, Y);
facache[fakey] = make_tuple(X, Y, cell); facache[fakey] = make_tuple(X, Y, cell);
} }
@ -496,30 +496,30 @@ struct ExtractFaWorker
} }
else else
{ {
Cell *cell = module->addCell(NEW_ID, "$fa"); Cell *cell = module->addCell(NEW_ID, ID($fa));
cell->setParam("\\WIDTH", 1); cell->setParam(ID(WIDTH), 1);
log(" Created $fa cell %s.\n", log_id(cell)); log(" Created $fa cell %s.\n", log_id(cell));
cell->setPort("\\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("\\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("\\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("\\X", X); cell->setPort(ID(X), X);
cell->setPort("\\Y", Y); cell->setPort(ID::Y, Y);
} }
if (func2.at(key).count(xor2_func)) { if (func2.at(key).count(xor2_func)) {
SigBit YY = invert_xy ? module->NotGate(NEW_ID, Y) : Y; SigBit YY = invert_xy || (f2i.inv_a && !f2i.inv_b) || (!f2i.inv_a && f2i.inv_b) ? module->NotGate(NEW_ID, Y) : Y;
for (auto bit : func2.at(key).at(xor2_func)) for (auto bit : func2.at(key).at(xor2_func))
assign_new_driver(bit, YY); assign_new_driver(bit, YY);
} }
if (func2.at(key).count(xnor2_func)) { if (func2.at(key).count(xnor2_func)) {
SigBit YY = invert_xy ? Y : module->NotGate(NEW_ID, Y); SigBit YY = invert_xy || (f2i.inv_a && !f2i.inv_b) || (!f2i.inv_a && f2i.inv_b) ? Y : module->NotGate(NEW_ID, Y);
for (auto bit : func2.at(key).at(xnor2_func)) for (auto bit : func2.at(key).at(xnor2_func))
assign_new_driver(bit, YY); assign_new_driver(bit, YY);
} }

View file

@ -58,9 +58,9 @@ struct ExtractReducePass : public Pass
inline bool IsRightType(Cell* cell, GateType gt) inline bool IsRightType(Cell* cell, GateType gt)
{ {
return (cell->type == "$_AND_" && gt == GateType::And) || return (cell->type == ID($_AND_) && gt == GateType::And) ||
(cell->type == "$_OR_" && gt == GateType::Or) || (cell->type == ID($_OR_) && gt == GateType::Or) ||
(cell->type == "$_XOR_" && gt == GateType::Xor); (cell->type == ID($_XOR_) && gt == GateType::Xor);
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@ -124,11 +124,11 @@ struct ExtractReducePass : public Pass
GateType gt; GateType gt;
if (cell->type == "$_AND_") if (cell->type == ID($_AND_))
gt = GateType::And; gt = GateType::And;
else if (cell->type == "$_OR_") else if (cell->type == ID($_OR_))
gt = GateType::Or; gt = GateType::Or;
else if (cell->type == "$_XOR_") else if (cell->type == ID($_XOR_))
gt = GateType::Xor; gt = GateType::Xor;
else else
continue; continue;
@ -148,7 +148,7 @@ struct ExtractReducePass : public Pass
head_cell = x; head_cell = x;
auto y = sigmap(x->getPort("\\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("\\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("\\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("\\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,26 +279,26 @@ 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("\\A"))[0]); input_pool.insert(sigmap(x->getPort(ID::A))[0]);
input_pool.insert(sigmap(x->getPort("\\B"))[0]); input_pool.insert(sigmap(x->getPort(ID::B))[0]);
input_pool_intermed.insert(sigmap(x->getPort("\\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("\\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 ? "$reduce_and" : gt == GateType::And ? ID($reduce_and) :
gt == GateType::Or ? "$reduce_or" : gt == GateType::Or ? ID($reduce_or) :
gt == GateType::Xor ? "$reduce_xor" : ""); gt == GateType::Xor ? ID($reduce_xor) : "");
new_reduce_cell->setParam("\\A_SIGNED", 0); new_reduce_cell->setParam(ID(A_SIGNED), 0);
new_reduce_cell->setParam("\\A_WIDTH", input.size()); new_reduce_cell->setParam(ID(A_WIDTH), input.size());
new_reduce_cell->setParam("\\Y_WIDTH", 1); new_reduce_cell->setParam(ID(Y_WIDTH), 1);
new_reduce_cell->setPort("\\A", input); new_reduce_cell->setPort(ID::A, input);
new_reduce_cell->setPort("\\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

@ -671,8 +671,8 @@ struct FlowmapWorker
labels[node] = -1; labels[node] = -1;
for (auto input : inputs) for (auto input : inputs)
{ {
if (input.wire->attributes.count("\\$flowmap_level")) if (input.wire->attributes.count(ID($flowmap_level)))
labels[input] = input.wire->attributes["\\$flowmap_level"].as_int(); labels[input] = input.wire->attributes[ID($flowmap_level)].as_int();
else else
labels[input] = 0; labels[input] = 0;
} }
@ -1412,7 +1412,7 @@ struct FlowmapWorker
for (auto gate_node : lut_gates[node]) for (auto gate_node : lut_gates[node])
{ {
auto gate_origin = node_origins[gate_node]; auto gate_origin = node_origins[gate_node];
lut->add_strpool_attribute("\\src", gate_origin.cell->get_strpool_attribute("\\src")); lut->add_strpool_attribute(ID(src), gate_origin.cell->get_strpool_attribute(ID(src)));
packed_count++; packed_count++;
} }
lut_count++; lut_count++;
@ -1586,7 +1586,7 @@ struct FlowmapPass : public Pass {
} }
else else
{ {
cell_types = {"$_NOT_", "$_AND_", "$_OR_", "$_XOR_", "$_MUX_"}; cell_types = {ID($_NOT_), ID($_AND_), ID($_OR_), ID($_XOR_), ID($_MUX_)};
} }
const char *algo_r = relax ? "-r" : ""; const char *algo_r = relax ? "-r" : "";

View file

@ -64,6 +64,11 @@ struct IopadmapPass : public Pass {
log(" of the tristate driver and the 2nd portname is the internal output\n"); log(" of the tristate driver and the 2nd portname is the internal output\n");
log(" buffering the external signal.\n"); log(" buffering the external signal.\n");
log("\n"); log("\n");
log(" -ignore <celltype> <portname>[:<portname>]*\n");
log(" Skips mapping inputs/outputs that are already connected to given\n");
log(" ports of the given cell. Can be used multiple times. This is in\n");
log(" addition to the cells specified as mapping targets.\n");
log("\n");
log(" -widthparam <param_name>\n"); log(" -widthparam <param_name>\n");
log(" Use the specified parameter name to set the port width.\n"); log(" Use the specified parameter name to set the port width.\n");
log("\n"); log("\n");
@ -88,6 +93,7 @@ struct IopadmapPass : public Pass {
std::string toutpad_celltype, toutpad_portname, toutpad_portname2, toutpad_portname3; std::string toutpad_celltype, toutpad_portname, toutpad_portname2, toutpad_portname3;
std::string tinoutpad_celltype, tinoutpad_portname, tinoutpad_portname2, tinoutpad_portname3, tinoutpad_portname4; std::string tinoutpad_celltype, tinoutpad_portname, tinoutpad_portname2, tinoutpad_portname3, tinoutpad_portname4;
std::string widthparam, nameparam; std::string widthparam, nameparam;
pool<pair<IdString, IdString>> ignore;
bool flag_bits = false; bool flag_bits = false;
size_t argidx; size_t argidx;
@ -127,6 +133,18 @@ struct IopadmapPass : public Pass {
split_portname_pair(tinoutpad_portname3, tinoutpad_portname4); split_portname_pair(tinoutpad_portname3, tinoutpad_portname4);
continue; continue;
} }
if (arg == "-ignore" && argidx+2 < args.size()) {
std::string ignore_celltype = args[++argidx];
std::string ignore_portname = args[++argidx];
std::string ignore_portname2;
while (!ignore_portname.empty()) {
split_portname_pair(ignore_portname, ignore_portname2);
ignore.insert(make_pair(RTLIL::escape_id(ignore_celltype), RTLIL::escape_id(ignore_portname)));
ignore_portname = ignore_portname2;
}
continue;
}
if (arg == "-widthparam" && argidx+1 < args.size()) { if (arg == "-widthparam" && argidx+1 < args.size()) {
widthparam = args[++argidx]; widthparam = args[++argidx];
continue; continue;
@ -143,6 +161,23 @@ struct IopadmapPass : public Pass {
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
if (!inpad_portname2.empty())
ignore.insert(make_pair(RTLIL::escape_id(inpad_celltype), RTLIL::escape_id(inpad_portname2)));
if (!outpad_portname2.empty())
ignore.insert(make_pair(RTLIL::escape_id(outpad_celltype), RTLIL::escape_id(outpad_portname2)));
if (!inoutpad_portname2.empty())
ignore.insert(make_pair(RTLIL::escape_id(inoutpad_celltype), RTLIL::escape_id(inoutpad_portname2)));
if (!toutpad_portname3.empty())
ignore.insert(make_pair(RTLIL::escape_id(toutpad_celltype), RTLIL::escape_id(toutpad_portname3)));
if (!tinoutpad_portname4.empty())
ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname4)));
for (auto module : design->modules())
if (module->get_blackbox_attribute())
for (auto wire : module->wires())
if (wire->get_bool_attribute("\\iopad_external_pin"))
ignore.insert(make_pair(module->name, wire->name));
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
dict<IdString, pool<int>> skip_wires; dict<IdString, pool<int>> skip_wires;
@ -150,28 +185,11 @@ struct IopadmapPass : public Pass {
SigMap sigmap(module); SigMap sigmap(module);
for (auto cell : module->cells()) for (auto cell : module->cells())
{ for (auto port : cell->connections())
if (cell->type == RTLIL::escape_id(inpad_celltype) && cell->hasPort(RTLIL::escape_id(inpad_portname2))) if (ignore.count(make_pair(cell->type, port.first)))
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inpad_portname2)))) for (auto bit : sigmap(port.second))
skip_wire_bits.insert(bit); skip_wire_bits.insert(bit);
if (cell->type == RTLIL::escape_id(outpad_celltype) && cell->hasPort(RTLIL::escape_id(outpad_portname2)))
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(outpad_portname2))))
skip_wire_bits.insert(bit);
if (cell->type == RTLIL::escape_id(inoutpad_celltype) && cell->hasPort(RTLIL::escape_id(inoutpad_portname2)))
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inoutpad_portname2))))
skip_wire_bits.insert(bit);
if (cell->type == RTLIL::escape_id(toutpad_celltype) && cell->hasPort(RTLIL::escape_id(toutpad_portname3)))
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(toutpad_portname3))))
skip_wire_bits.insert(bit);
if (cell->type == RTLIL::escape_id(tinoutpad_celltype) && cell->hasPort(RTLIL::escape_id(tinoutpad_portname4)))
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(tinoutpad_portname4))))
skip_wire_bits.insert(bit);
}
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty()) if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
{ {
dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits; dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
@ -179,8 +197,8 @@ struct IopadmapPass : public Pass {
SigMap rewrites; SigMap rewrites;
for (auto cell : module->cells()) for (auto cell : module->cells())
if (cell->type == "$_TBUF_") { if (cell->type == ID($_TBUF_)) {
SigBit bit = sigmap(cell->getPort("\\Y").as_bit()); SigBit bit = sigmap(cell->getPort(ID::Y).as_bit());
tbuf_bits[bit].first = cell->name; tbuf_bits[bit].first = cell->name;
} }
@ -212,8 +230,8 @@ struct IopadmapPass : public Pass {
if (tbuf_cell == nullptr) if (tbuf_cell == nullptr)
continue; continue;
SigBit en_sig = tbuf_cell->getPort("\\E").as_bit(); SigBit en_sig = tbuf_cell->getPort(ID(E)).as_bit();
SigBit data_sig = tbuf_cell->getPort("\\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())
{ {
@ -226,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["\\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);
@ -263,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["\\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);
@ -390,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["\\keep"] = RTLIL::Const(1); cell->attributes[ID::keep] = RTLIL::Const(1);
} }
} }
else else
@ -403,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["\\keep"] = RTLIL::Const(1); cell->attributes[ID::keep] = RTLIL::Const(1);
} }
wire->port_id = 0; wire->port_id = 0;

View file

@ -25,9 +25,9 @@ PRIVATE_NAMESPACE_BEGIN
int lut2mux(Cell *cell) int lut2mux(Cell *cell)
{ {
SigSpec sig_a = cell->getPort("\\A"); SigSpec sig_a = cell->getPort(ID::A);
SigSpec sig_y = cell->getPort("\\Y"); SigSpec sig_y = cell->getPort(ID::Y);
Const lut = cell->getParam("\\LUT"); Const lut = cell->getParam(ID(LUT));
int count = 1; int count = 1;
if (GetSize(sig_a) == 1) if (GetSize(sig_a) == 1)
@ -81,7 +81,7 @@ struct Lut2muxPass : public Pass {
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
for (auto cell : module->selected_cells()) { for (auto cell : module->selected_cells()) {
if (cell->type == "$lut") { if (cell->type == ID($lut)) {
IdString cell_name = cell->name; IdString cell_name = cell->name;
int count = lut2mux(cell); int count = lut2mux(cell);
log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count); log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count);

View file

@ -111,13 +111,13 @@ struct MaccmapWorker
RTLIL::Wire *w1 = module->addWire(NEW_ID, width); RTLIL::Wire *w1 = module->addWire(NEW_ID, width);
RTLIL::Wire *w2 = module->addWire(NEW_ID, width); RTLIL::Wire *w2 = module->addWire(NEW_ID, width);
RTLIL::Cell *cell = module->addCell(NEW_ID, "$fa"); RTLIL::Cell *cell = module->addCell(NEW_ID, ID($fa));
cell->setParam("\\WIDTH", width); cell->setParam(ID(WIDTH), width);
cell->setPort("\\A", in1); cell->setPort(ID::A, in1);
cell->setPort("\\B", in2); cell->setPort(ID::B, in2);
cell->setPort("\\C", in3); cell->setPort(ID(C), in3);
cell->setPort("\\Y", w1); cell->setPort(ID::Y, w1);
cell->setPort("\\X", w2); cell->setPort(ID(X), w2);
out1 = {out_zeros_msb, w1, out_zeros_lsb}; out1 = {out_zeros_msb, w1, out_zeros_lsb};
out2 = {out_zeros_msb, w2, out_zeros_lsb}; out2 = {out_zeros_msb, w2, out_zeros_lsb};
@ -237,23 +237,23 @@ struct MaccmapWorker
} }
RTLIL::Cell *c = module->addCell(NEW_ID, "$alu"); RTLIL::Cell *c = module->addCell(NEW_ID, ID($alu));
c->setPort("\\A", summands.front()); c->setPort(ID::A, summands.front());
c->setPort("\\B", summands.back()); c->setPort(ID::B, summands.back());
c->setPort("\\CI", State::S0); c->setPort(ID(CI), State::S0);
c->setPort("\\BI", State::S0); c->setPort(ID(BI), State::S0);
c->setPort("\\Y", module->addWire(NEW_ID, width)); c->setPort(ID::Y, module->addWire(NEW_ID, width));
c->setPort("\\X", module->addWire(NEW_ID, width)); c->setPort(ID(X), module->addWire(NEW_ID, width));
c->setPort("\\CO", module->addWire(NEW_ID, width)); c->setPort(ID(CO), module->addWire(NEW_ID, width));
c->fixup_parameters(); c->fixup_parameters();
if (!tree_sum_bits.empty()) { if (!tree_sum_bits.empty()) {
c->setPort("\\CI", tree_sum_bits.back()); c->setPort(ID(CI), tree_sum_bits.back());
tree_sum_bits.pop_back(); tree_sum_bits.pop_back();
} }
log_assert(tree_sum_bits.empty()); log_assert(tree_sum_bits.empty());
return c->getPort("\\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("\\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("\\A")); all_input_bits.append(cell->getPort(ID::A));
all_input_bits.append(cell->getPort("\\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("\\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("\\Y")); module->addNeg(NEW_ID, summands.front().first, cell->getPort(ID::Y));
else else
module->connect(cell->getPort("\\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("\\Y"), worker.synth()); module->connect(cell->getPort(ID::Y), worker.synth());
} }
} }
@ -393,7 +393,7 @@ struct MaccmapPass : public Pass {
for (auto mod : design->selected_modules()) for (auto mod : design->selected_modules())
for (auto cell : mod->selected_cells()) for (auto cell : mod->selected_cells())
if (cell->type == "$macc") { if (cell->type == ID($macc)) {
log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type)); log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type));
maccmap(mod, cell, unmap_mode); maccmap(mod, cell, unmap_mode);
mod->remove(cell); mod->remove(cell);

View file

@ -116,13 +116,13 @@ struct MuxcoverWorker
if (!cell->input(conn.first)) if (!cell->input(conn.first))
continue; continue;
for (auto bit : sigmap(conn.second)) { for (auto bit : sigmap(conn.second)) {
if (used_once.count(bit) || cell->type != "$_MUX_" || conn.first == "\\S") if (used_once.count(bit) || cell->type != ID($_MUX_) || conn.first == ID(S))
roots.insert(bit); roots.insert(bit);
used_once.insert(bit); used_once.insert(bit);
} }
} }
if (cell->type == "$_MUX_") if (cell->type == ID($_MUX_))
sig_to_mux[sigmap(cell->getPort("\\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("\\A"))); wavefront.insert(sigmap(c->getPort(ID::A)));
wavefront.insert(sigmap(c->getPort("\\B"))); wavefront.insert(sigmap(c->getPort(ID::B)));
} }
} }
@ -516,69 +516,69 @@ 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, "$_MUX_"); Cell *cell = module->addCell(NEW_ID, ID($_MUX_));
cell->setPort("\\A", mux.inputs[0]); cell->setPort(ID::A, mux.inputs[0]);
cell->setPort("\\B", mux.inputs[1]); cell->setPort(ID::B, mux.inputs[1]);
cell->setPort("\\S", mux.selects[0]); cell->setPort(ID(S), mux.selects[0]);
cell->setPort("\\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, "$_MUX4_"); Cell *cell = module->addCell(NEW_ID, ID($_MUX4_));
cell->setPort("\\A", mux.inputs[0]); cell->setPort(ID::A, mux.inputs[0]);
cell->setPort("\\B", mux.inputs[1]); cell->setPort(ID::B, mux.inputs[1]);
cell->setPort("\\C", mux.inputs[2]); cell->setPort(ID(C), mux.inputs[2]);
cell->setPort("\\D", mux.inputs[3]); cell->setPort(ID(D), mux.inputs[3]);
cell->setPort("\\S", mux.selects[0]); cell->setPort(ID(S), mux.selects[0]);
cell->setPort("\\T", mux.selects[1]); cell->setPort(ID(T), mux.selects[1]);
cell->setPort("\\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, "$_MUX8_"); Cell *cell = module->addCell(NEW_ID, ID($_MUX8_));
cell->setPort("\\A", mux.inputs[0]); cell->setPort(ID::A, mux.inputs[0]);
cell->setPort("\\B", mux.inputs[1]); cell->setPort(ID::B, mux.inputs[1]);
cell->setPort("\\C", mux.inputs[2]); cell->setPort(ID(C), mux.inputs[2]);
cell->setPort("\\D", mux.inputs[3]); cell->setPort(ID(D), mux.inputs[3]);
cell->setPort("\\E", mux.inputs[4]); cell->setPort(ID(E), mux.inputs[4]);
cell->setPort("\\F", mux.inputs[5]); cell->setPort(ID(F), mux.inputs[5]);
cell->setPort("\\G", mux.inputs[6]); cell->setPort(ID(G), mux.inputs[6]);
cell->setPort("\\H", mux.inputs[7]); cell->setPort(ID(H), mux.inputs[7]);
cell->setPort("\\S", mux.selects[0]); cell->setPort(ID(S), mux.selects[0]);
cell->setPort("\\T", mux.selects[1]); cell->setPort(ID(T), mux.selects[1]);
cell->setPort("\\U", mux.selects[2]); cell->setPort(ID(U), mux.selects[2]);
cell->setPort("\\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, "$_MUX16_"); Cell *cell = module->addCell(NEW_ID, ID($_MUX16_));
cell->setPort("\\A", mux.inputs[0]); cell->setPort(ID::A, mux.inputs[0]);
cell->setPort("\\B", mux.inputs[1]); cell->setPort(ID::B, mux.inputs[1]);
cell->setPort("\\C", mux.inputs[2]); cell->setPort(ID(C), mux.inputs[2]);
cell->setPort("\\D", mux.inputs[3]); cell->setPort(ID(D), mux.inputs[3]);
cell->setPort("\\E", mux.inputs[4]); cell->setPort(ID(E), mux.inputs[4]);
cell->setPort("\\F", mux.inputs[5]); cell->setPort(ID(F), mux.inputs[5]);
cell->setPort("\\G", mux.inputs[6]); cell->setPort(ID(G), mux.inputs[6]);
cell->setPort("\\H", mux.inputs[7]); cell->setPort(ID(H), mux.inputs[7]);
cell->setPort("\\I", mux.inputs[8]); cell->setPort(ID(I), mux.inputs[8]);
cell->setPort("\\J", mux.inputs[9]); cell->setPort(ID(J), mux.inputs[9]);
cell->setPort("\\K", mux.inputs[10]); cell->setPort(ID(K), mux.inputs[10]);
cell->setPort("\\L", mux.inputs[11]); cell->setPort(ID(L), mux.inputs[11]);
cell->setPort("\\M", mux.inputs[12]); cell->setPort(ID(M), mux.inputs[12]);
cell->setPort("\\N", mux.inputs[13]); cell->setPort(ID(N), mux.inputs[13]);
cell->setPort("\\O", mux.inputs[14]); cell->setPort(ID(O), mux.inputs[14]);
cell->setPort("\\P", mux.inputs[15]); cell->setPort(ID(P), mux.inputs[15]);
cell->setPort("\\S", mux.selects[0]); cell->setPort(ID(S), mux.selects[0]);
cell->setPort("\\T", mux.selects[1]); cell->setPort(ID(T), mux.selects[1]);
cell->setPort("\\U", mux.selects[2]); cell->setPort(ID(U), mux.selects[2]);
cell->setPort("\\V", mux.selects[3]); cell->setPort(ID(V), mux.selects[3]);
cell->setPort("\\Y", bit); cell->setPort(ID::Y, bit);
return; return;
} }

View file

@ -82,10 +82,10 @@ struct NlutmapWorker
for (auto cell : module->cells()) for (auto cell : module->cells())
{ {
if (cell->type != "$lut" || mapped_cells.count(cell)) if (cell->type != ID($lut) || mapped_cells.count(cell))
continue; continue;
if (GetSize(cell->getPort("\\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())
@ -119,7 +119,7 @@ struct NlutmapWorker
if (config.assert_mode) { if (config.assert_mode) {
for (auto cell : module->cells()) for (auto cell : module->cells())
if (cell->type == "$lut" && !mapped_cells.count(cell)) if (cell->type == ID($lut) && !mapped_cells.count(cell))
log_error("Insufficient number of LUTs to map all logic cells!\n"); log_error("Insufficient number of LUTs to map all logic cells!\n");
} }

View file

@ -89,21 +89,21 @@ struct PmuxtreePass : public Pass {
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type != "$pmux") if (cell->type != ID($pmux))
continue; continue;
SigSpec sig_data = cell->getPort("\\B"); SigSpec sig_data = cell->getPort(ID::B);
SigSpec sig_sel = cell->getPort("\\S"); SigSpec sig_sel = cell->getPort(ID(S));
if (!cell->getPort("\\A").is_fully_undef()) { if (!cell->getPort(ID::A).is_fully_undef()) {
sig_data.append(cell->getPort("\\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("\\Y"), result); module->connect(cell->getPort(ID::Y), result);
module->remove(cell); module->remove(cell);
} }
} }

View file

@ -73,22 +73,22 @@ struct ShregmapTechGreenpak4 : ShregmapTech
bool fixup(Cell *cell, dict<int, SigBit> &taps) bool fixup(Cell *cell, dict<int, SigBit> &taps)
{ {
auto D = cell->getPort("\\D"); auto D = cell->getPort(ID(D));
auto C = cell->getPort("\\C"); auto C = cell->getPort(ID(C));
auto newcell = cell->module->addCell(NEW_ID, "\\GP_SHREG"); auto newcell = cell->module->addCell(NEW_ID, ID(GP_SHREG));
newcell->setPort("\\nRST", State::S1); newcell->setPort(ID(nRST), State::S1);
newcell->setPort("\\CLK", C); newcell->setPort(ID(CLK), C);
newcell->setPort("\\IN", D); newcell->setPort(ID(IN), D);
int i = 0; int i = 0;
for (auto tap : taps) { for (auto tap : taps) {
newcell->setPort(i ? "\\OUTB" : "\\OUTA", tap.second); newcell->setPort(i ? ID(OUTB) : ID(OUTA), tap.second);
newcell->setParam(i ? "\\OUTB_TAP" : "\\OUTA_TAP", tap.first + 1); newcell->setParam(i ? ID(OUTB_TAP) : ID(OUTA_TAP), tap.first + 1);
i++; i++;
} }
cell->setParam("\\OUTA_INVERT", 0); cell->setParam(ID(OUTA_INVERT), 0);
return false; return false;
} }
}; };
@ -104,19 +104,19 @@ struct ShregmapTechXilinx7 : ShregmapTech
{ {
for (const auto &i : module->cells_) { for (const auto &i : module->cells_) {
auto cell = i.second; auto cell = i.second;
if (cell->type == "$shiftx") { if (cell->type == ID($shiftx)) {
if (cell->getParam("\\Y_WIDTH") != 1) continue; if (cell->getParam(ID(Y_WIDTH)) != 1) continue;
int j = 0; int j = 0;
for (auto bit : sigmap(cell->getPort("\\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("\\A_WIDTH").as_int()); log_assert(j == cell->getParam(ID(A_WIDTH)).as_int());
} }
else if (cell->type == "$mux") { else if (cell->type == ID($mux)) {
int j = 0; int j = 0;
for (auto bit : sigmap(cell->getPort("\\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("\\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 == "$shiftx" && port == "\\A") if (cell->type == ID($shiftx) && port == ID::A)
return; return;
if (cell->type == "$mux" && (port == "\\A" || port == "\\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);
@ -177,21 +177,21 @@ struct ShregmapTechXilinx7 : ShregmapTech
log_assert(shiftx); log_assert(shiftx);
// Only map if $shiftx exclusively covers the shift register // Only map if $shiftx exclusively covers the shift register
if (shiftx->type == "$shiftx") { if (shiftx->type == ID($shiftx)) {
if (GetSize(taps) > shiftx->getParam("\\A_WIDTH").as_int()) if (GetSize(taps) > shiftx->getParam(ID(A_WIDTH)).as_int())
return false; return false;
// 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("\\A_WIDTH").as_int()) { if (GetSize(taps) < shiftx->getParam(ID(A_WIDTH)).as_int()) {
const SigSpec A = shiftx->getPort("\\A"); const SigSpec A = shiftx->getPort(ID::A);
const int A_width = shiftx->getParam("\\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;
} }
else if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) else if (GetSize(taps) != shiftx->getParam(ID(A_WIDTH)).as_int())
return false; return false;
} }
else if (shiftx->type == "$mux") { else if (shiftx->type == ID($mux)) {
if (GetSize(taps) != 2) if (GetSize(taps) != 2)
return false; return false;
} }
@ -208,34 +208,34 @@ struct ShregmapTechXilinx7 : ShregmapTech
auto it = sigbit_to_shiftx_offset.find(bit); auto it = sigbit_to_shiftx_offset.find(bit);
log_assert(it != sigbit_to_shiftx_offset.end()); log_assert(it != sigbit_to_shiftx_offset.end());
auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); auto newcell = cell->module->addCell(NEW_ID, ID($__XILINX_SHREG_));
newcell->set_src_attribute(cell->get_src_attribute()); newcell->set_src_attribute(cell->get_src_attribute());
newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); newcell->setParam(ID(DEPTH), cell->getParam(ID(DEPTH)));
newcell->setParam("\\INIT", cell->getParam("\\INIT")); newcell->setParam(ID(INIT), cell->getParam(ID(INIT)));
newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL")); newcell->setParam(ID(CLKPOL), cell->getParam(ID(CLKPOL)));
newcell->setParam("\\ENPOL", cell->getParam("\\ENPOL")); newcell->setParam(ID(ENPOL), cell->getParam(ID(ENPOL)));
newcell->setPort("\\C", cell->getPort("\\C")); newcell->setPort(ID(C), cell->getPort(ID(C)));
newcell->setPort("\\D", cell->getPort("\\D")); newcell->setPort(ID(D), cell->getPort(ID(D)));
if (cell->hasPort("\\E")) if (cell->hasPort(ID(E)))
newcell->setPort("\\E", cell->getPort("\\E")); newcell->setPort(ID(E), cell->getPort(ID(E)));
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 == "$shiftx") { if (shiftx->type == ID($shiftx)) {
l_wire = shiftx->getPort("\\B"); l_wire = shiftx->getPort(ID::B);
q_wire = shiftx->getPort("\\Y"); q_wire = shiftx->getPort(ID::Y);
shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID));
} }
else if (shiftx->type == "$mux") { else if (shiftx->type == ID($mux)) {
l_wire = shiftx->getPort("\\S"); l_wire = shiftx->getPort(ID(S));
q_wire = shiftx->getPort("\\Y"); q_wire = shiftx->getPort(ID::Y);
shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID));
} }
else log_abort(); else log_abort();
newcell->setPort("\\Q", q_wire); newcell->setPort(ID(Q), q_wire);
newcell->setPort("\\L", l_wire); newcell->setPort(ID(L), l_wire);
return false; return false;
} }
@ -263,16 +263,16 @@ struct ShregmapWorker
{ {
for (auto wire : module->wires()) for (auto wire : module->wires())
{ {
if (wire->port_output || wire->get_bool_attribute("\\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, {});
} }
} }
if (wire->attributes.count("\\init")) { if (wire->attributes.count(ID(init))) {
SigSpec initsig = sigmap(wire); SigSpec initsig = sigmap(wire);
Const initval = wire->attributes.at("\\init"); Const initval = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
if (initval[i] == State::S0 && !opts.zinit) if (initval[i] == State::S0 && !opts.zinit)
sigbit_init[initsig[i]] = false; sigbit_init[initsig[i]] = false;
@ -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("\\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;
@ -346,7 +346,7 @@ struct ShregmapWorker
IdString q_port = opts.ffcells.at(c1->type).second; IdString q_port = opts.ffcells.at(c1->type).second;
auto c1_conn = c1->connections(); auto c1_conn = c1->connections();
auto c2_conn = c1->connections(); auto c2_conn = c2->connections();
c1_conn.erase(d_port); c1_conn.erase(d_port);
c1_conn.erase(q_port); c1_conn.erase(q_port);
@ -474,7 +474,7 @@ struct ShregmapWorker
initval.push_back(State::S0); initval.push_back(State::S0);
remove_init.insert(bit); remove_init.insert(bit);
} }
first_cell->setParam("\\INIT", initval); first_cell->setParam(ID(INIT), initval);
} }
if (opts.zinit) if (opts.zinit)
@ -488,22 +488,22 @@ struct ShregmapWorker
int param_clkpol = -1; int param_clkpol = -1;
int param_enpol = 2; int param_enpol = 2;
if (first_cell->type == "$_DFF_N_") param_clkpol = 0; if (first_cell->type == ID($_DFF_N_)) param_clkpol = 0;
if (first_cell->type == "$_DFF_P_") param_clkpol = 1; if (first_cell->type == ID($_DFF_P_)) param_clkpol = 1;
if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; if (first_cell->type == ID($_DFFE_NN_)) param_clkpol = 0, param_enpol = 0;
if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; if (first_cell->type == ID($_DFFE_NP_)) param_clkpol = 0, param_enpol = 1;
if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; if (first_cell->type == ID($_DFFE_PN_)) param_clkpol = 1, param_enpol = 0;
if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; if (first_cell->type == ID($_DFFE_PP_)) param_clkpol = 1, param_enpol = 1;
log_assert(param_clkpol >= 0); log_assert(param_clkpol >= 0);
first_cell->setParam("\\CLKPOL", param_clkpol); first_cell->setParam(ID(CLKPOL), param_clkpol);
if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); if (opts.ffe) first_cell->setParam(ID(ENPOL), param_enpol);
} }
first_cell->type = shreg_cell_type_str; first_cell->type = shreg_cell_type_str;
first_cell->setPort(q_port, last_cell->getPort(q_port)); first_cell->setPort(q_port, last_cell->getPort(q_port));
first_cell->setParam("\\DEPTH", depth); first_cell->setParam(ID(DEPTH), depth);
if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict))
remove_cells.insert(first_cell); remove_cells.insert(first_cell);
@ -521,18 +521,18 @@ struct ShregmapWorker
for (auto wire : module->wires()) for (auto wire : module->wires())
{ {
if (wire->attributes.count("\\init") == 0) if (wire->attributes.count(ID(init)) == 0)
continue; continue;
SigSpec initsig = sigmap(wire); SigSpec initsig = sigmap(wire);
Const &initval = wire->attributes.at("\\init"); Const &initval = wire->attributes.at(ID(init));
for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
if (remove_init.count(initsig[i])) if (remove_init.count(initsig[i]))
initval[i] = State::Sx; initval[i] = State::Sx;
if (SigSpec(initval).is_fully_undef()) if (SigSpec(initval).is_fully_undef())
wire->attributes.erase("\\init"); wire->attributes.erase(ID(init));
} }
remove_cells.clear(); remove_cells.clear();
@ -717,19 +717,19 @@ struct ShregmapPass : public Pass {
bool en_neg = enpol == "neg" || enpol == "any" || enpol == "any_or_none"; bool en_neg = enpol == "neg" || enpol == "any" || enpol == "any_or_none";
if (clk_pos && en_none) if (clk_pos && en_none)
opts.ffcells["$_DFF_P_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells[ID($_DFF_P_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
if (clk_neg && en_none) if (clk_neg && en_none)
opts.ffcells["$_DFF_N_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells[ID($_DFF_N_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
if (clk_pos && en_pos) if (clk_pos && en_pos)
opts.ffcells["$_DFFE_PP_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells[ID($_DFFE_PP_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
if (clk_pos && en_neg) if (clk_pos && en_neg)
opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells[ID($_DFFE_PN_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
if (clk_neg && en_pos) if (clk_neg && en_pos)
opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells[ID($_DFFE_NP_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
if (clk_neg && en_neg) if (clk_neg && en_neg)
opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q")); opts.ffcells[ID($_DFFE_NN_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
if (en_pos || en_neg) if (en_pos || en_neg)
opts.ffe = true; opts.ffe = true;

View file

@ -28,82 +28,82 @@ 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("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_y = cell->getPort("\\Y"); RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\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, "$_NOT_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a[i]); gate->setPort(ID::A, sig_a[i]);
gate->setPort("\\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("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_y = cell->getPort("\\Y"); RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool()); sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
module->connect(RTLIL::SigSig(sig_y, sig_a)); module->connect(RTLIL::SigSig(sig_y, sig_a));
} }
void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_y = cell->getPort("\\Y"); RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\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("\\B_SIGNED").as_bool()); sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID(B_SIGNED)).as_bool());
if (cell->type == "$xnor") if (cell->type == ID($xnor))
{ {
RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_y)); RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_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, "$_NOT_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_t[i]); gate->setPort(ID::A, sig_t[i]);
gate->setPort("\\Y", sig_y[i]); gate->setPort(ID::Y, sig_y[i]);
} }
sig_y = sig_t; sig_y = sig_t;
} }
std::string gate_type; IdString gate_type;
if (cell->type == "$and") gate_type = "$_AND_"; if (cell->type == ID($and)) gate_type = ID($_AND_);
if (cell->type == "$or") gate_type = "$_OR_"; if (cell->type == ID($or)) gate_type = ID($_OR_);
if (cell->type == "$xor") gate_type = "$_XOR_"; if (cell->type == ID($xor)) gate_type = ID($_XOR_);
if (cell->type == "$xnor") gate_type = "$_XOR_"; if (cell->type == ID($xnor)) gate_type = ID($_XOR_);
log_assert(!gate_type.empty()); log_assert(!gate_type.empty());
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("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a[i]); gate->setPort(ID::A, sig_a[i]);
gate->setPort("\\B", sig_b[i]); gate->setPort(ID::B, sig_b[i]);
gate->setPort("\\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("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_y = cell->getPort("\\Y"); RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
if (sig_y.size() == 0) if (sig_y.size() == 0)
return; return;
if (sig_a.size() == 0) { if (sig_a.size() == 0) {
if (cell->type == "$reduce_and") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size()))); if (cell->type == ID($reduce_and)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
if (cell->type == "$reduce_or") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size()))); if (cell->type == ID($reduce_or)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
if (cell->type == "$reduce_xor") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size()))); if (cell->type == ID($reduce_xor)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
if (cell->type == "$reduce_xnor") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size()))); if (cell->type == ID($reduce_xnor)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
if (cell->type == "$reduce_bool") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size()))); if (cell->type == ID($reduce_bool)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
return; return;
} }
@ -112,12 +112,12 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
sig_y = sig_y.extract(0, 1); sig_y = sig_y.extract(0, 1);
} }
std::string gate_type; IdString gate_type;
if (cell->type == "$reduce_and") gate_type = "$_AND_"; if (cell->type == ID($reduce_and)) gate_type = ID($_AND_);
if (cell->type == "$reduce_or") gate_type = "$_OR_"; if (cell->type == ID($reduce_or)) gate_type = ID($_OR_);
if (cell->type == "$reduce_xor") gate_type = "$_XOR_"; if (cell->type == ID($reduce_xor)) gate_type = ID($_XOR_);
if (cell->type == "$reduce_xnor") gate_type = "$_XOR_"; if (cell->type == ID($reduce_xnor)) gate_type = ID($_XOR_);
if (cell->type == "$reduce_bool") gate_type = "$_OR_"; if (cell->type == ID($reduce_bool)) gate_type = ID($_OR_);
log_assert(!gate_type.empty()); log_assert(!gate_type.empty());
RTLIL::Cell *last_output_cell = NULL; RTLIL::Cell *last_output_cell = NULL;
@ -134,22 +134,22 @@ 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("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a[i]); gate->setPort(ID::A, sig_a[i]);
gate->setPort("\\B", sig_a[i+1]); gate->setPort(ID::B, sig_a[i+1]);
gate->setPort("\\Y", sig_t[i/2]); gate->setPort(ID::Y, sig_t[i/2]);
last_output_cell = gate; last_output_cell = gate;
} }
sig_a = sig_t; sig_a = sig_t;
} }
if (cell->type == "$reduce_xnor") { if (cell->type == ID($reduce_xnor)) {
RTLIL::SigSpec sig_t = module->addWire(NEW_ID); RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a); gate->setPort(ID::A, sig_a);
gate->setPort("\\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("\\Y", sig_y); last_output_cell->setPort(ID::Y, sig_y);
} }
} }
@ -174,11 +174,11 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell
continue; continue;
} }
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_OR_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig[i]); gate->setPort(ID::A, sig[i]);
gate->setPort("\\B", sig[i+1]); gate->setPort(ID::B, sig[i+1]);
gate->setPort("\\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("\\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("\\Y"); RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
if (sig_y.size() == 0) if (sig_y.size() == 0)
return; return;
@ -203,21 +203,21 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
sig_y = sig_y.extract(0, 1); sig_y = sig_y.extract(0, 1);
} }
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a); gate->setPort(ID::A, sig_a);
gate->setPort("\\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("\\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("\\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("\\Y"); RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
if (sig_y.size() == 0) if (sig_y.size() == 0)
return; return;
@ -227,41 +227,41 @@ void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
sig_y = sig_y.extract(0, 1); sig_y = sig_y.extract(0, 1);
} }
std::string gate_type; IdString gate_type;
if (cell->type == "$logic_and") gate_type = "$_AND_"; if (cell->type == ID($logic_and)) gate_type = ID($_AND_);
if (cell->type == "$logic_or") gate_type = "$_OR_"; if (cell->type == ID($logic_or)) gate_type = ID($_OR_);
log_assert(!gate_type.empty()); log_assert(!gate_type.empty());
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a); gate->setPort(ID::A, sig_a);
gate->setPort("\\B", sig_b); gate->setPort(ID::B, sig_b);
gate->setPort("\\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("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_y = cell->getPort("\\Y"); RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); bool is_signed = cell->parameters.at(ID(A_SIGNED)).as_bool();
bool is_ne = cell->type.in("$ne", "$nex"); bool is_ne = cell->type.in(ID($ne), ID($nex));
RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b))); RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b)));
RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed); RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed);
xor_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); xor_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
simplemap_bitop(module, xor_cell); simplemap_bitop(module, xor_cell);
module->remove(xor_cell); module->remove(xor_cell);
RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID);
RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out);
reduce_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); reduce_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
simplemap_reduce(module, reduce_cell); simplemap_reduce(module, reduce_cell);
module->remove(reduce_cell); module->remove(reduce_cell);
if (!is_ne) { if (!is_ne) {
RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y); RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y);
not_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); not_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
simplemap_lognot(module, not_cell); simplemap_lognot(module, not_cell);
module->remove(not_cell); module->remove(not_cell);
} }
@ -269,65 +269,65 @@ 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("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_y = cell->getPort("\\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, "$_MUX_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a[i]); gate->setPort(ID::A, sig_a[i]);
gate->setPort("\\B", sig_b[i]); gate->setPort(ID::B, sig_b[i]);
gate->setPort("\\S", cell->getPort("\\S")); gate->setPort(ID(S), cell->getPort(ID(S)));
gate->setPort("\\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("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_e = cell->getPort("\\EN"); RTLIL::SigSpec sig_e = cell->getPort(ID(EN));
RTLIL::SigSpec sig_y = cell->getPort("\\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, "$_TBUF_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", sig_a[i]); gate->setPort(ID::A, sig_a[i]);
gate->setPort("\\E", sig_e); gate->setPort(ID(E), sig_e);
gate->setPort("\\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("\\A"); SigSpec lut_ctrl = cell->getPort(ID::A);
SigSpec lut_data = cell->getParam("\\LUT"); SigSpec lut_data = cell->getParam(ID(LUT));
lut_data.extend_u0(1 << cell->getParam("\\WIDTH").as_int()); lut_data.extend_u0(1 << cell->getParam(ID(WIDTH)).as_int());
for (int idx = 0; GetSize(lut_data) > 1; idx++) { for (int idx = 0; GetSize(lut_data) > 1; idx++) {
SigSpec sig_s = lut_ctrl[idx]; SigSpec sig_s = lut_ctrl[idx];
SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2); SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2);
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, "$_MUX_"); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\A", lut_data[i]); gate->setPort(ID::A, lut_data[i]);
gate->setPort("\\B", lut_data[i+1]); gate->setPort(ID::B, lut_data[i+1]);
gate->setPort("\\S", lut_ctrl[idx]); gate->setPort(ID(S), lut_ctrl[idx]);
gate->setPort("\\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("\\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("\\A"); SigSpec ctrl = cell->getPort(ID::A);
SigSpec table = cell->getParam("\\TABLE"); SigSpec table = cell->getParam(ID(TABLE));
int width = cell->getParam("\\WIDTH").as_int(); int width = cell->getParam(ID(WIDTH)).as_int();
int depth = cell->getParam("\\DEPTH").as_int(); int depth = cell->getParam(ID(DEPTH)).as_int();
table.extend_u0(2 * width * depth); table.extend_u0(2 * width * depth);
SigSpec products; SigSpec products;
@ -348,213 +348,213 @@ 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("\\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("\\OFFSET").as_int(); int offset = cell->parameters.at(ID(OFFSET)).as_int();
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort(ID::A);
RTLIL::SigSpec sig_y = cell->getPort("\\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("\\A"); RTLIL::SigSpec sig_ab = cell->getPort(ID::A);
sig_ab.append(cell->getPort("\\B")); sig_ab.append(cell->getPort(ID::B));
RTLIL::SigSpec sig_y = cell->getPort("\\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));
} }
void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N'; char set_pol = cell->parameters.at(ID(SET_POLARITY)).as_bool() ? 'P' : 'N';
char clr_pol = cell->parameters.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N'; char clr_pol = cell->parameters.at(ID(CLR_POLARITY)).as_bool() ? 'P' : 'N';
RTLIL::SigSpec sig_s = cell->getPort("\\SET"); RTLIL::SigSpec sig_s = cell->getPort(ID(SET));
RTLIL::SigSpec sig_r = cell->getPort("\\CLR"); RTLIL::SigSpec sig_r = cell->getPort(ID(CLR));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol); std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\S", sig_s[i]); gate->setPort(ID(S), sig_s[i]);
gate->setPort("\\R", sig_r[i]); gate->setPort(ID(R), sig_r[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort(ID(Q), sig_q[i]);
} }
} }
void simplemap_ff(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_ff(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
std::string gate_type = "$_FF_"; IdString gate_type = ID($_FF_);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\D", sig_d[i]); gate->setPort(ID(D), sig_d[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort(ID(Q), sig_q[i]);
} }
} }
void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
RTLIL::SigSpec sig_clk = cell->getPort("\\CLK"); RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
std::string gate_type = stringf("$_DFF_%c_", clk_pol); IdString gate_type = stringf("$_DFF_%c_", clk_pol);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\C", sig_clk); gate->setPort(ID(C), sig_clk);
gate->setPort("\\D", sig_d[i]); gate->setPort(ID(D), sig_d[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort(ID(Q), sig_q[i]);
} }
} }
void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N'; char en_pol = cell->parameters.at(ID(EN_POLARITY)).as_bool() ? 'P' : 'N';
RTLIL::SigSpec sig_clk = cell->getPort("\\CLK"); RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
RTLIL::SigSpec sig_en = cell->getPort("\\EN"); RTLIL::SigSpec sig_en = cell->getPort(ID(EN));
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
std::string gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol); IdString gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\C", sig_clk); gate->setPort(ID(C), sig_clk);
gate->setPort("\\E", sig_en); gate->setPort(ID(E), sig_en);
gate->setPort("\\D", sig_d[i]); gate->setPort(ID(D), sig_d[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort(ID(Q), sig_q[i]);
} }
} }
void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N'; char set_pol = cell->parameters.at(ID(SET_POLARITY)).as_bool() ? 'P' : 'N';
char clr_pol = cell->parameters.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N'; char clr_pol = cell->parameters.at(ID(CLR_POLARITY)).as_bool() ? 'P' : 'N';
RTLIL::SigSpec sig_clk = cell->getPort("\\CLK"); RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
RTLIL::SigSpec sig_s = cell->getPort("\\SET"); RTLIL::SigSpec sig_s = cell->getPort(ID(SET));
RTLIL::SigSpec sig_r = cell->getPort("\\CLR"); RTLIL::SigSpec sig_r = cell->getPort(ID(CLR));
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
std::string gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol); IdString gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\C", sig_clk); gate->setPort(ID(C), sig_clk);
gate->setPort("\\S", sig_s[i]); gate->setPort(ID(S), sig_s[i]);
gate->setPort("\\R", sig_r[i]); gate->setPort(ID(R), sig_r[i]);
gate->setPort("\\D", sig_d[i]); gate->setPort(ID(D), sig_d[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort(ID(Q), sig_q[i]);
} }
} }
void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N'; char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
char rst_pol = cell->parameters.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N'; char rst_pol = cell->parameters.at(ID(ARST_POLARITY)).as_bool() ? 'P' : 'N';
std::vector<RTLIL::State> rst_val = cell->parameters.at("\\ARST_VALUE").bits; std::vector<RTLIL::State> rst_val = cell->parameters.at(ID(ARST_VALUE)).bits;
while (int(rst_val.size()) < width) while (int(rst_val.size()) < width)
rst_val.push_back(RTLIL::State::S0); rst_val.push_back(RTLIL::State::S0);
RTLIL::SigSpec sig_clk = cell->getPort("\\CLK"); RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
RTLIL::SigSpec sig_rst = cell->getPort("\\ARST"); RTLIL::SigSpec sig_rst = cell->getPort(ID(ARST));
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
std::string gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol); IdString gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol);
std::string gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol); IdString gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0); RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\C", sig_clk); gate->setPort(ID(C), sig_clk);
gate->setPort("\\R", sig_rst); gate->setPort(ID(R), sig_rst);
gate->setPort("\\D", sig_d[i]); gate->setPort(ID(D), sig_d[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort(ID(Q), sig_q[i]);
} }
} }
void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
{ {
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at(ID(WIDTH)).as_int();
char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N'; char en_pol = cell->parameters.at(ID(EN_POLARITY)).as_bool() ? 'P' : 'N';
RTLIL::SigSpec sig_en = cell->getPort("\\EN"); RTLIL::SigSpec sig_en = cell->getPort(ID(EN));
RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_d = cell->getPort(ID(D));
RTLIL::SigSpec sig_q = cell->getPort("\\Q"); RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
std::string gate_type = stringf("$_DLATCH_%c_", en_pol); IdString gate_type = stringf("$_DLATCH_%c_", en_pol);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src")); gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
gate->setPort("\\E", sig_en); gate->setPort(ID(E), sig_en);
gate->setPort("\\D", sig_d[i]); gate->setPort(ID(D), sig_d[i]);
gate->setPort("\\Q", sig_q[i]); gate->setPort(ID(Q), sig_q[i]);
} }
} }
void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers) void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
{ {
mappers["$not"] = simplemap_not; mappers[ID($not)] = simplemap_not;
mappers["$pos"] = simplemap_pos; mappers[ID($pos)] = simplemap_pos;
mappers["$and"] = simplemap_bitop; mappers[ID($and)] = simplemap_bitop;
mappers["$or"] = simplemap_bitop; mappers[ID($or)] = simplemap_bitop;
mappers["$xor"] = simplemap_bitop; mappers[ID($xor)] = simplemap_bitop;
mappers["$xnor"] = simplemap_bitop; mappers[ID($xnor)] = simplemap_bitop;
mappers["$reduce_and"] = simplemap_reduce; mappers[ID($reduce_and)] = simplemap_reduce;
mappers["$reduce_or"] = simplemap_reduce; mappers[ID($reduce_or)] = simplemap_reduce;
mappers["$reduce_xor"] = simplemap_reduce; mappers[ID($reduce_xor)] = simplemap_reduce;
mappers["$reduce_xnor"] = simplemap_reduce; mappers[ID($reduce_xnor)] = simplemap_reduce;
mappers["$reduce_bool"] = simplemap_reduce; mappers[ID($reduce_bool)] = simplemap_reduce;
mappers["$logic_not"] = simplemap_lognot; mappers[ID($logic_not)] = simplemap_lognot;
mappers["$logic_and"] = simplemap_logbin; mappers[ID($logic_and)] = simplemap_logbin;
mappers["$logic_or"] = simplemap_logbin; mappers[ID($logic_or)] = simplemap_logbin;
mappers["$eq"] = simplemap_eqne; mappers[ID($eq)] = simplemap_eqne;
mappers["$eqx"] = simplemap_eqne; mappers[ID($eqx)] = simplemap_eqne;
mappers["$ne"] = simplemap_eqne; mappers[ID($ne)] = simplemap_eqne;
mappers["$nex"] = simplemap_eqne; mappers[ID($nex)] = simplemap_eqne;
mappers["$mux"] = simplemap_mux; mappers[ID($mux)] = simplemap_mux;
mappers["$tribuf"] = simplemap_tribuf; mappers[ID($tribuf)] = simplemap_tribuf;
mappers["$lut"] = simplemap_lut; mappers[ID($lut)] = simplemap_lut;
mappers["$sop"] = simplemap_sop; mappers[ID($sop)] = simplemap_sop;
mappers["$slice"] = simplemap_slice; mappers[ID($slice)] = simplemap_slice;
mappers["$concat"] = simplemap_concat; mappers[ID($concat)] = simplemap_concat;
mappers["$sr"] = simplemap_sr; mappers[ID($sr)] = simplemap_sr;
mappers["$ff"] = simplemap_ff; mappers[ID($ff)] = simplemap_ff;
mappers["$dff"] = simplemap_dff; mappers[ID($dff)] = simplemap_dff;
mappers["$dffe"] = simplemap_dffe; mappers[ID($dffe)] = simplemap_dffe;
mappers["$dffsr"] = simplemap_dffsr; mappers[ID($dffsr)] = simplemap_dffsr;
mappers["$adff"] = simplemap_adff; mappers[ID($adff)] = simplemap_adff;
mappers["$dlatch"] = simplemap_dlatch; mappers[ID($dlatch)] = simplemap_dlatch;
} }
void simplemap(RTLIL::Module *module, RTLIL::Cell *cell) void simplemap(RTLIL::Module *module, RTLIL::Cell *cell)

View file

@ -39,20 +39,20 @@ YOSYS_NAMESPACE_END
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
void apply_prefix(std::string prefix, std::string &id) void apply_prefix(IdString prefix, IdString &id)
{ {
if (id[0] == '\\') if (id[0] == '\\')
id = prefix + "." + id.substr(1); id = stringf("%s.%s", prefix.c_str(), id.c_str()+1);
else else
id = "$techmap" + prefix + "." + id; id = stringf("$techmap%s.%s", prefix.c_str(), id.c_str());
} }
void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module *module) void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
{ {
vector<SigChunk> chunks = sig; vector<SigChunk> chunks = sig;
for (auto &chunk : chunks) for (auto &chunk : chunks)
if (chunk.wire != NULL) { if (chunk.wire != NULL) {
std::string wire_name = chunk.wire->name.str(); IdString wire_name = chunk.wire->name;
apply_prefix(prefix, wire_name); apply_prefix(prefix, wire_name);
log_assert(module->wires_.count(wire_name) > 0); log_assert(module->wires_.count(wire_name) > 0);
chunk.wire = module->wires_[wire_name]; chunk.wire = module->wires_[wire_name];
@ -145,8 +145,8 @@ 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["\\keep"] = RTLIL::Const(1); it.second->attributes[ID::keep] = RTLIL::Const(1);
it.second->attributes["\\_techmap_special_"] = RTLIL::Const(1); it.second->attributes[ID(_techmap_special_)] = RTLIL::Const(1);
} }
} }
@ -175,11 +175,11 @@ struct TechmapWorker
} }
std::string orig_cell_name; std::string orig_cell_name;
pool<string> extra_src_attrs = cell->get_strpool_attribute("\\src"); pool<string> extra_src_attrs = cell->get_strpool_attribute(ID(src));
if (!flatten_mode) { if (!flatten_mode) {
for (auto &it : tpl->cells_) for (auto &it : tpl->cells_)
if (it.first == "\\_TECHMAP_REPLACE_") { if (it.first == ID(_TECHMAP_REPLACE_)) {
orig_cell_name = cell->name.str(); orig_cell_name = cell->name.str();
module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str()); module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str());
break; break;
@ -189,16 +189,16 @@ struct TechmapWorker
dict<IdString, IdString> memory_renames; dict<IdString, IdString> memory_renames;
for (auto &it : tpl->memories) { for (auto &it : tpl->memories) {
std::string m_name = it.first.str(); IdString m_name = it.first;
apply_prefix(cell->name.str(), m_name); apply_prefix(cell->name, m_name);
RTLIL::Memory *m = new RTLIL::Memory; RTLIL::Memory *m = new RTLIL::Memory;
m->name = m_name; m->name = m_name;
m->width = it.second->width; m->width = it.second->width;
m->start_offset = it.second->start_offset; m->start_offset = it.second->start_offset;
m->size = it.second->size; m->size = it.second->size;
m->attributes = it.second->attributes; m->attributes = it.second->attributes;
if (m->attributes.count("\\src")) if (m->attributes.count(ID(src)))
m->add_strpool_attribute("\\src", extra_src_attrs); m->add_strpool_attribute(ID(src), extra_src_attrs);
module->memories[m->name] = m; module->memories[m->name] = m;
memory_renames[it.first] = m->name; memory_renames[it.first] = m->name;
design->select(module, m); design->select(module, m);
@ -209,16 +209,16 @@ struct TechmapWorker
for (auto &it : tpl->wires_) { for (auto &it : tpl->wires_) {
if (it.second->port_id > 0) if (it.second->port_id > 0)
positional_ports[stringf("$%d", it.second->port_id)] = it.first; positional_ports[stringf("$%d", it.second->port_id)] = it.first;
std::string w_name = it.second->name.str(); IdString w_name = it.second->name;
apply_prefix(cell->name.str(), w_name); apply_prefix(cell->name, w_name);
RTLIL::Wire *w = module->addWire(w_name, it.second); RTLIL::Wire *w = module->addWire(w_name, it.second);
w->port_input = false; w->port_input = false;
w->port_output = false; w->port_output = false;
w->port_id = 0; w->port_id = 0;
if (it.second->get_bool_attribute("\\_techmap_special_")) if (it.second->get_bool_attribute(ID(_techmap_special_)))
w->attributes.clear(); w->attributes.clear();
if (w->attributes.count("\\src")) if (w->attributes.count(ID(src)))
w->add_strpool_attribute("\\src", extra_src_attrs); w->add_strpool_attribute(ID(src), extra_src_attrs);
design->select(module, w); design->select(module, w);
} }
@ -257,18 +257,18 @@ struct TechmapWorker
if (w->port_output && !w->port_input) { if (w->port_output && !w->port_input) {
c.first = it.second; c.first = it.second;
c.second = RTLIL::SigSpec(w); c.second = RTLIL::SigSpec(w);
apply_prefix(cell->name.str(), c.second, module); apply_prefix(cell->name, c.second, module);
extra_connect.first = c.second; extra_connect.first = c.second;
extra_connect.second = c.first; extra_connect.second = c.first;
} else if (!w->port_output && w->port_input) { } else if (!w->port_output && w->port_input) {
c.first = RTLIL::SigSpec(w); c.first = RTLIL::SigSpec(w);
c.second = it.second; c.second = it.second;
apply_prefix(cell->name.str(), c.first, module); apply_prefix(cell->name, c.first, module);
extra_connect.first = c.first; extra_connect.first = c.first;
extra_connect.second = c.second; extra_connect.second = c.second;
} else { } else {
SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second; SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second;
apply_prefix(cell->name.str(), sig_tpl_pf, module); apply_prefix(cell->name, sig_tpl_pf, module);
for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) { for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
if (tpl_written_bits.count(tpl_sigmap(sig_tpl[i]))) { if (tpl_written_bits.count(tpl_sigmap(sig_tpl[i]))) {
c.first.append(sig_mod[i]); c.first.append(sig_mod[i]);
@ -320,7 +320,7 @@ struct TechmapWorker
} }
for (auto &attr : w->attributes) { for (auto &attr : w->attributes) {
if (attr.first == "\\src") if (attr.first == ID(src))
continue; continue;
module->connect(extra_connect); module->connect(extra_connect);
break; break;
@ -330,13 +330,13 @@ struct TechmapWorker
for (auto &it : tpl->cells_) for (auto &it : tpl->cells_)
{ {
std::string c_name = it.second->name.str(); IdString c_name = it.second->name.str();
bool techmap_replace_cell = (!flatten_mode) && (c_name == "\\_TECHMAP_REPLACE_"); bool techmap_replace_cell = (!flatten_mode) && (c_name == ID(_TECHMAP_REPLACE_));
if (techmap_replace_cell) if (techmap_replace_cell)
c_name = orig_cell_name; c_name = orig_cell_name;
else else
apply_prefix(cell->name.str(), c_name); apply_prefix(cell->name, c_name);
RTLIL::Cell *c = module->addCell(c_name, it.second); RTLIL::Cell *c = module->addCell(c_name, it.second);
design->select(module, c); design->select(module, c);
@ -345,24 +345,24 @@ struct TechmapWorker
c->type = c->type.substr(1); c->type = c->type.substr(1);
for (auto &it2 : c->connections_) { for (auto &it2 : c->connections_) {
apply_prefix(cell->name.str(), it2.second, module); apply_prefix(cell->name, it2.second, module);
port_signal_map.apply(it2.second); port_signal_map.apply(it2.second);
} }
if (c->type == "$memrd" || c->type == "$memwr" || c->type == "$meminit") { if (c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
IdString memid = c->getParam("\\MEMID").decode_string(); IdString memid = c->getParam(ID(MEMID)).decode_string();
log_assert(memory_renames.count(memid) != 0); log_assert(memory_renames.count(memid) != 0);
c->setParam("\\MEMID", Const(memory_renames[memid].str())); c->setParam(ID(MEMID), Const(memory_renames[memid].str()));
} }
if (c->type == "$mem") { if (c->type == ID($mem)) {
string memid = c->getParam("\\MEMID").decode_string(); IdString memid = c->getParam(ID(MEMID)).decode_string();
apply_prefix(cell->name.str(), memid); apply_prefix(cell->name, memid);
c->setParam("\\MEMID", Const(memid)); c->setParam(ID(MEMID), Const(memid.c_str()));
} }
if (c->attributes.count("\\src")) if (c->attributes.count(ID(src)))
c->add_strpool_attribute("\\src", extra_src_attrs); c->add_strpool_attribute(ID(src), extra_src_attrs);
if (techmap_replace_cell) if (techmap_replace_cell)
for (auto attr : cell->attributes) for (auto attr : cell->attributes)
@ -416,9 +416,9 @@ struct TechmapWorker
} }
if (flatten_mode) { if (flatten_mode) {
bool keepit = cell->get_bool_attribute("\\keep_hierarchy"); bool keepit = cell->get_bool_attribute(ID(keep_hierarchy));
for (auto &tpl_name : celltypeMap.at(cell_type)) for (auto &tpl_name : celltypeMap.at(cell_type))
if (map->modules_[tpl_name]->get_bool_attribute("\\keep_hierarchy")) if (map->modules_[tpl_name]->get_bool_attribute(ID(keep_hierarchy)))
keepit = true; keepit = true;
if (keepit) { if (keepit) {
if (!flatten_keep_list[cell]) { if (!flatten_keep_list[cell]) {
@ -484,13 +484,13 @@ struct TechmapWorker
{ {
std::string extmapper_name; std::string extmapper_name;
if (tpl->get_bool_attribute("\\techmap_simplemap")) if (tpl->get_bool_attribute(ID(techmap_simplemap)))
extmapper_name = "simplemap"; extmapper_name = "simplemap";
if (tpl->get_bool_attribute("\\techmap_maccmap")) if (tpl->get_bool_attribute(ID(techmap_maccmap)))
extmapper_name = "maccmap"; extmapper_name = "maccmap";
if (tpl->attributes.count("\\techmap_wrap")) if (tpl->attributes.count(ID(techmap_wrap)))
extmapper_name = "wrap"; extmapper_name = "wrap";
if (!extmapper_name.empty()) if (!extmapper_name.empty())
@ -505,7 +505,7 @@ struct TechmapWorker
m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second)); m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second));
if (extmapper_name == "wrap") if (extmapper_name == "wrap")
m_name += ":" + sha1(tpl->attributes.at("\\techmap_wrap").decode_string()); m_name += ":" + sha1(tpl->attributes.at(ID(techmap_wrap)).decode_string());
RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design; RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design;
RTLIL::Module *extmapper_module = extmapper_design->module(m_name); RTLIL::Module *extmapper_module = extmapper_design->module(m_name);
@ -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 == "\\Y" || w->name == "\\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;
@ -541,14 +541,14 @@ struct TechmapWorker
if (extmapper_name == "maccmap") { if (extmapper_name == "maccmap") {
log("Creating %s with maccmap.\n", log_id(extmapper_module)); log("Creating %s with maccmap.\n", log_id(extmapper_module));
if (extmapper_cell->type != "$macc") if (extmapper_cell->type != ID($macc))
log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(extmapper_cell->type)); log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(extmapper_cell->type));
maccmap(extmapper_module, extmapper_cell); maccmap(extmapper_module, extmapper_cell);
extmapper_module->remove(extmapper_cell); extmapper_module->remove(extmapper_cell);
} }
if (extmapper_name == "wrap") { if (extmapper_name == "wrap") {
std::string cmd_string = tpl->attributes.at("\\techmap_wrap").decode_string(); std::string cmd_string = tpl->attributes.at(ID(techmap_wrap)).decode_string();
log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module)); log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module));
mkdebug.on(); mkdebug.on();
Pass::call_on_module(extmapper_design, extmapper_module, cmd_string); Pass::call_on_module(extmapper_design, extmapper_module, cmd_string);
@ -587,7 +587,7 @@ struct TechmapWorker
} }
if (extmapper_name == "maccmap") { if (extmapper_name == "maccmap") {
if (cell->type != "$macc") if (cell->type != ID($macc))
log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(cell->type)); log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(cell->type));
maccmap(module, cell); maccmap(module, cell);
} }
@ -616,8 +616,8 @@ struct TechmapWorker
continue; continue;
} }
if (tpl->avail_parameters.count("\\_TECHMAP_CELLTYPE_") != 0) if (tpl->avail_parameters.count(ID(_TECHMAP_CELLTYPE_)) != 0)
parameters["\\_TECHMAP_CELLTYPE_"] = RTLIL::unescape_id(cell->type); parameters[ID(_TECHMAP_CELLTYPE_)] = RTLIL::unescape_id(cell->type);
for (auto conn : cell->connections()) { for (auto conn : cell->connections()) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))) != 0) { if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))) != 0) {
@ -656,8 +656,8 @@ struct TechmapWorker
bits = i; bits = i;
// Increment index by one to get number of bits // Increment index by one to get number of bits
bits++; bits++;
if (tpl->avail_parameters.count("\\_TECHMAP_BITS_CONNMAP_")) if (tpl->avail_parameters.count(ID(_TECHMAP_BITS_CONNMAP_)))
parameters["\\_TECHMAP_BITS_CONNMAP_"] = bits; parameters[ID(_TECHMAP_BITS_CONNMAP_)] = bits;
for (auto conn : cell->connections()) for (auto conn : cell->connections())
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) { if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) {
@ -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");
@ -1136,8 +1137,8 @@ struct TechmapPass : public Pass {
std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap; std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
for (auto &it : map->modules_) { for (auto &it : map->modules_) {
if (it.second->attributes.count("\\techmap_celltype") && !it.second->attributes.at("\\techmap_celltype").bits.empty()) { if (it.second->attributes.count(ID(techmap_celltype)) && !it.second->attributes.at(ID(techmap_celltype)).bits.empty()) {
char *p = strdup(it.second->attributes.at("\\techmap_celltype").decode_string().c_str()); char *p = strdup(it.second->attributes.at(ID(techmap_celltype)).decode_string().c_str());
for (char *q = strtok(p, " \t\r\n"); q; q = strtok(NULL, " \t\r\n")) for (char *q = strtok(p, " \t\r\n"); q; q = strtok(NULL, " \t\r\n"))
celltypeMap[RTLIL::escape_id(q)].insert(it.first); celltypeMap[RTLIL::escape_id(q)].insert(it.first);
free(p); free(p);
@ -1157,6 +1158,7 @@ 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) {
@ -1165,7 +1167,7 @@ struct TechmapPass : public Pass {
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;
} }
} }
@ -1222,7 +1224,7 @@ struct FlattenPass : public Pass {
RTLIL::Module *top_mod = NULL; RTLIL::Module *top_mod = NULL;
if (design->full_selection()) if (design->full_selection())
for (auto mod : design->modules()) for (auto mod : design->modules())
if (mod->get_bool_attribute("\\top")) if (mod->get_bool_attribute(ID(top)))
top_mod = mod; top_mod = mod;
std::set<RTLIL::Cell*> handled_cells; std::set<RTLIL::Cell*> handled_cells;

View file

@ -63,38 +63,38 @@ struct TribufWorker {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type == "$tribuf") if (cell->type == ID($tribuf))
tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell); tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
if (cell->type == "$_TBUF_") if (cell->type == ID($_TBUF_))
tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell); tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
if (cell->type.in("$mux", "$_MUX_")) if (cell->type.in(ID($mux), ID($_MUX_)))
{ {
IdString en_port = cell->type == "$mux" ? "\\EN" : "\\E"; IdString en_port = cell->type == ID($mux) ? ID(EN) : ID(E);
IdString tri_type = cell->type == "$mux" ? "$tribuf" : "$_TBUF_"; IdString tri_type = cell->type == ID($mux) ? ID($tribuf) : ID($_TBUF_);
if (is_all_z(cell->getPort("\\A")) && is_all_z(cell->getPort("\\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("\\A"))) { if (is_all_z(cell->getPort(ID::A))) {
cell->setPort("\\A", cell->getPort("\\B")); cell->setPort(ID::A, cell->getPort(ID::B));
cell->setPort(en_port, cell->getPort("\\S")); cell->setPort(en_port, cell->getPort(ID(S)));
cell->unsetPort("\\B"); cell->unsetPort(ID::B);
cell->unsetPort("\\S"); cell->unsetPort(ID(S));
cell->type = tri_type; cell->type = tri_type;
tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell); tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
continue; continue;
} }
if (is_all_z(cell->getPort("\\B"))) { if (is_all_z(cell->getPort(ID::B))) {
cell->setPort(en_port, module->Not(NEW_ID, cell->getPort("\\S"))); cell->setPort(en_port, module->Not(NEW_ID, cell->getPort(ID(S))));
cell->unsetPort("\\B"); cell->unsetPort(ID::B);
cell->unsetPort("\\S"); cell->unsetPort(ID(S));
cell->type = tri_type; cell->type = tri_type;
tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell); tribuf_cells[sigmap(cell->getPort(ID::Y))].push_back(cell);
continue; continue;
} }
} }
@ -118,11 +118,11 @@ struct TribufWorker {
SigSpec pmux_b, pmux_s; SigSpec pmux_b, pmux_s;
for (auto cell : it.second) { for (auto cell : it.second) {
if (cell->type == "$tribuf") if (cell->type == ID($tribuf))
pmux_s.append(cell->getPort("\\EN")); pmux_s.append(cell->getPort(ID(EN)));
else else
pmux_s.append(cell->getPort("\\E")); pmux_s.append(cell->getPort(ID(E)));
pmux_b.append(cell->getPort("\\A")); pmux_b.append(cell->getPort(ID::A));
module->remove(cell); module->remove(cell);
} }

View file

@ -62,12 +62,12 @@ struct ZinitPass : public Pass {
for (auto wire : module->selected_wires()) for (auto wire : module->selected_wires())
{ {
if (wire->attributes.count("\\init") == 0) if (wire->attributes.count(ID(init)) == 0)
continue; continue;
SigSpec wirebits = sigmap(wire); SigSpec wirebits = sigmap(wire);
Const initval = wire->attributes.at("\\init"); Const initval = wire->attributes.at(ID(init));
wire->attributes.erase("\\init"); wire->attributes.erase(ID(init));
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
{ {
@ -90,12 +90,12 @@ struct ZinitPass : public Pass {
} }
pool<IdString> dff_types = { pool<IdString> dff_types = {
"$ff", "$dff", "$dffe", "$dffsr", "$adff", ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($adff),
"$_FF_", "$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_", ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
"$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_", ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
"$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
"$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_" ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)
}; };
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
@ -103,8 +103,8 @@ struct ZinitPass : public Pass {
if (!dff_types.count(cell->type)) if (!dff_types.count(cell->type))
continue; continue;
SigSpec sig_d = sigmap(cell->getPort("\\D")); SigSpec sig_d = sigmap(cell->getPort(ID(D)));
SigSpec sig_q = sigmap(cell->getPort("\\Q")); SigSpec sig_q = sigmap(cell->getPort(ID(Q)));
if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1) if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
continue; continue;
@ -120,14 +120,14 @@ struct ZinitPass : public Pass {
} }
Wire *initwire = module->addWire(NEW_ID, GetSize(initval)); Wire *initwire = module->addWire(NEW_ID, GetSize(initval));
initwire->attributes["\\init"] = initval; initwire->attributes[ID(init)] = initval;
for (int i = 0; i < GetSize(initwire); i++) for (int i = 0; i < GetSize(initwire); i++)
if (initval.bits.at(i) == State::S1) if (initval.bits.at(i) == State::S1)
{ {
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]); sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]); module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
initwire->attributes["\\init"].bits.at(i) = State::S0; initwire->attributes[ID(init)].bits.at(i) = State::S0;
} }
else else
{ {
@ -137,8 +137,8 @@ struct ZinitPass : public Pass {
log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type), log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
log_signal(sig_q), log_signal(initval)); log_signal(sig_q), log_signal(initval));
cell->setPort("\\D", sig_d); cell->setPort(ID(D), sig_d);
cell->setPort("\\Q", initwire); cell->setPort(ID(Q), initwire);
} }
for (auto &it : initbits) for (auto &it : initbits)

View file

@ -43,7 +43,7 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
RTLIL::Cell *cell = module->addCell("\\UUT", cell_type); RTLIL::Cell *cell = module->addCell("\\UUT", cell_type);
RTLIL::Wire *wire; RTLIL::Wire *wire;
if (cell_type == "$mux" || cell_type == "$pmux") if (cell_type.in("$mux", "$pmux"))
{ {
int width = 1 + xorshift32(8); int width = 1 + xorshift32(8);
int swidth = cell_type == "$mux" ? 1 : 1 + xorshift32(8); int swidth = cell_type == "$mux" ? 1 : 1 + xorshift32(8);
@ -264,7 +264,7 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
cell->setPort("\\Y", wire); cell->setPort("\\Y", wire);
} }
if (muxdiv && (cell_type == "$div" || cell_type == "$mod")) { if (muxdiv && cell_type.in("$div", "$mod")) {
auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort("\\B")); auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort("\\B"));
auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort("\\Y"))); auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort("\\Y")));
module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(div_out)), div_out, b_not_zero, cell->getPort("\\Y")); module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(div_out)), div_out, b_not_zero, cell->getPort("\\Y"));

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

@ -1,5 +1,6 @@
OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \
techlibs/ecp5/ecp5_gsr.o
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))

View file

@ -33,7 +33,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.CLKBMUX(CLKBMUX), .CLKBMUX(CLKBMUX),
.WRITEMODE_A(WRITEMODE_A), .WRITEMODE_A(WRITEMODE_A),
.WRITEMODE_B("READBEFOREWRITE"), .WRITEMODE_B("READBEFOREWRITE"),
.GSR("DISABLED") .GSR("AUTO")
) _TECHMAP_REPLACE_ ( ) _TECHMAP_REPLACE_ (
`include "bram_conn_1.vh" `include "bram_conn_1.vh"
.CLKA(CLK2), .CLKB(CLK3), .CLKA(CLK2), .CLKB(CLK3),
@ -50,7 +50,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.CLKBMUX(CLKBMUX), .CLKBMUX(CLKBMUX),
.WRITEMODE_A(WRITEMODE_A), .WRITEMODE_A(WRITEMODE_A),
.WRITEMODE_B("READBEFOREWRITE"), .WRITEMODE_B("READBEFOREWRITE"),
.GSR("DISABLED") .GSR("AUTO")
) _TECHMAP_REPLACE_ ( ) _TECHMAP_REPLACE_ (
`include "bram_conn_2.vh" `include "bram_conn_2.vh"
.CLKA(CLK2), .CLKB(CLK3), .CLKA(CLK2), .CLKB(CLK3),
@ -67,7 +67,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.CLKBMUX(CLKBMUX), .CLKBMUX(CLKBMUX),
.WRITEMODE_A(WRITEMODE_A), .WRITEMODE_A(WRITEMODE_A),
.WRITEMODE_B("READBEFOREWRITE"), .WRITEMODE_B("READBEFOREWRITE"),
.GSR("DISABLED") .GSR("AUTO")
) _TECHMAP_REPLACE_ ( ) _TECHMAP_REPLACE_ (
`include "bram_conn_4.vh" `include "bram_conn_4.vh"
.CLKA(CLK2), .CLKB(CLK3), .CLKA(CLK2), .CLKB(CLK3),
@ -84,7 +84,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.CLKBMUX(CLKBMUX), .CLKBMUX(CLKBMUX),
.WRITEMODE_A(WRITEMODE_A), .WRITEMODE_A(WRITEMODE_A),
.WRITEMODE_B("READBEFOREWRITE"), .WRITEMODE_B("READBEFOREWRITE"),
.GSR("DISABLED") .GSR("AUTO")
) _TECHMAP_REPLACE_ ( ) _TECHMAP_REPLACE_ (
`include "bram_conn_9.vh" `include "bram_conn_9.vh"
.CLKA(CLK2), .CLKB(CLK3), .CLKA(CLK2), .CLKB(CLK3),
@ -101,7 +101,7 @@ module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.CLKBMUX(CLKBMUX), .CLKBMUX(CLKBMUX),
.WRITEMODE_A(WRITEMODE_A), .WRITEMODE_A(WRITEMODE_A),
.WRITEMODE_B("READBEFOREWRITE"), .WRITEMODE_B("READBEFOREWRITE"),
.GSR("DISABLED") .GSR("AUTO")
) _TECHMAP_REPLACE_ ( ) _TECHMAP_REPLACE_ (
`include "bram_conn_18.vh" `include "bram_conn_18.vh"
.CLKA(CLK2), .CLKB(CLK3), .CLKA(CLK2), .CLKB(CLK3),

View file

@ -664,3 +664,23 @@ module PCSCLKDIV (
); );
parameter GSR = "DISABLED"; parameter GSR = "DISABLED";
endmodule endmodule
// Note: this module is not marked keep as we want it swept away in synth (sim use only)
(* blackbox *)
module PUR (
input PUR
);
parameter RST_PULSE = 1;
endmodule
(* blackbox, keep *)
module GSR (
input GSR
);
endmodule
(* blackbox, keep *)
module SGSR (
input GSR, CLK
);
endmodule

View file

@ -1,51 +1,51 @@
module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
// TODO: Diamond flip-flops // TODO: Diamond flip-flops
// module FD1P3AX(); endmodule // module FD1P3AX(); endmodule

Some files were not shown because too many files have changed in this diff Show more