mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/master' into xc7mux
This commit is contained in:
commit
ba9513b325
|
@ -4,6 +4,7 @@
|
|||
*.gch
|
||||
*.gcda
|
||||
*.gcno
|
||||
__pycache__
|
||||
/.cproject
|
||||
/.project
|
||||
/.settings
|
||||
|
@ -28,6 +29,8 @@
|
|||
/yosys-smtbmc-script.py
|
||||
/yosys-filterlib
|
||||
/yosys-filterlib.exe
|
||||
/kernel/*.pyh
|
||||
/kernel/python_wrappers.cc
|
||||
/kernel/version_*.cc
|
||||
/share
|
||||
/yosys-win32-mxebin-*
|
||||
|
|
71
Makefile
71
Makefile
|
@ -2,6 +2,7 @@
|
|||
CONFIG := clang
|
||||
# CONFIG := gcc
|
||||
# CONFIG := gcc-4.8
|
||||
# CONFIG := afl-gcc
|
||||
# CONFIG := emcc
|
||||
# CONFIG := mxe
|
||||
# CONFIG := msys2
|
||||
|
@ -21,12 +22,6 @@ ENABLE_PROTOBUF := 0
|
|||
|
||||
# python wrappers
|
||||
ENABLE_PYOSYS := 0
|
||||
PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)"
|
||||
PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi)
|
||||
PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"")
|
||||
PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.)
|
||||
PYTHON_PREFIX := `$(PYTHON_EXECUTABLE)-config --prefix`
|
||||
PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages
|
||||
|
||||
# other configuration flags
|
||||
ENABLE_GCOV := 0
|
||||
|
@ -90,6 +85,9 @@ PLUGIN_LDFLAGS += -undefined dynamic_lookup
|
|||
# homebrew search paths
|
||||
ifneq ($(shell which brew),)
|
||||
BREW_PREFIX := $(shell brew --prefix)/opt
|
||||
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
|
||||
CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost
|
||||
LDFLAGS += -L$(BREW_PREFIX)/boost/lib
|
||||
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
||||
LDFLAGS += -L$(BREW_PREFIX)/readline/lib
|
||||
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
|
||||
|
@ -139,6 +137,21 @@ $(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$
|
|||
include Makefile.conf
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_PYOSYS),1)
|
||||
PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)"
|
||||
PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi)
|
||||
PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"")
|
||||
PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.)
|
||||
PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix)
|
||||
PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages
|
||||
|
||||
# Reload Makefile.conf to override python specific variables if defined
|
||||
ifneq ($(wildcard Makefile.conf),)
|
||||
include Makefile.conf
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG),clang)
|
||||
CXX = clang
|
||||
LD = clang++
|
||||
|
@ -186,6 +199,12 @@ LD = gcc-4.8
|
|||
CXXFLAGS += -std=c++11 -Os
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
|
||||
|
||||
else ifeq ($(CONFIG),afl-gcc)
|
||||
CXX = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc
|
||||
LD = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc
|
||||
CXXFLAGS += -std=c++11 -Os
|
||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
|
||||
|
||||
else ifeq ($(CONFIG),cygwin)
|
||||
CXX = gcc
|
||||
LD = gcc
|
||||
|
@ -273,30 +292,51 @@ endif
|
|||
ifeq ($(ENABLE_PYOSYS),1)
|
||||
|
||||
#Detect name of boost_python library. Some distros usbe boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
|
||||
ifeq ($(OS), Darwin)
|
||||
BOOST_PYTHON_LIB ?= $(shell \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
|
||||
echo ""; fi; fi; fi; fi;)
|
||||
else
|
||||
BOOST_PYTHON_LIB ?= $(shell \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
|
||||
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
|
||||
echo ""; fi; fi; fi; fi;)
|
||||
endif
|
||||
|
||||
ifeq ($(BOOST_PYTHON_LIB),)
|
||||
$(error BOOST_PYTHON_LIB could not be detected. Please define manualy)
|
||||
endif
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
ifeq ($(PYTHON_MAJOR_VERSION),3)
|
||||
LDLIBS += `$(PYTHON_EXECUTABLE)-config --libs` $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
||||
CXXFLAGS += `$(PYTHON_EXECUTABLE)-config --includes` -D WITH_PYTHON
|
||||
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
||||
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
|
||||
else
|
||||
LDLIBS += `$(PYTHON_EXECUTABLE)-config --libs` $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
||||
CXXFLAGS += `$(PYTHON_EXECUTABLE)-config --includes` -D WITH_PYTHON
|
||||
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
||||
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
|
||||
endif
|
||||
else
|
||||
ifeq ($(PYTHON_MAJOR_VERSION),3)
|
||||
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
||||
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
|
||||
else
|
||||
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
||||
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_PYOSYS),1)
|
||||
PY_WRAPPER_FILE = kernel/python_wrappers
|
||||
OBJS += $(PY_WRAPPER_FILE).o
|
||||
PY_GEN_SCRIPT= py_wrap_generator
|
||||
PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_READLINE),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_READLINE
|
||||
|
@ -541,7 +581,11 @@ yosys$(EXE): $(OBJS)
|
|||
$(P) $(LD) -o yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS)
|
||||
|
||||
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
|
||||
ifeq ($(OS), Darwin)
|
||||
$(P) $(LD) -o libyosys.so -shared -Wl,-install_name,libyosys.so $(LDFLAGS) $^ $(LDLIBS)
|
||||
else
|
||||
$(P) $(LD) -o libyosys.so -shared -Wl,-soname,libyosys.so $(LDFLAGS) $^ $(LDLIBS)
|
||||
endif
|
||||
|
||||
%.o: %.cc
|
||||
$(Q) mkdir -p $(dir $@)
|
||||
|
@ -551,9 +595,11 @@ libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
|
|||
$(Q) mkdir -p $(dir $@)
|
||||
$(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) -x c++ -o $@ -E -P -
|
||||
|
||||
ifeq ($(ENABLE_PYOSYS),1)
|
||||
$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
|
||||
$(Q) mkdir -p $(dir $@)
|
||||
$(P) python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
|
||||
endif
|
||||
|
||||
%.o: %.cpp
|
||||
$(Q) mkdir -p $(dir $@)
|
||||
|
@ -788,6 +834,9 @@ config-gcc-static: clean
|
|||
config-gcc-4.8: clean
|
||||
echo 'CONFIG := gcc-4.8' > Makefile.conf
|
||||
|
||||
config-afl-gcc: clean
|
||||
echo 'CONFIG := afl-gcc' > Makefile.conf
|
||||
|
||||
config-emcc: clean
|
||||
echo 'CONFIG := emcc' > Makefile.conf
|
||||
echo 'ENABLE_TCL := 0' >> Makefile.conf
|
||||
|
@ -834,5 +883,5 @@ echo-git-rev:
|
|||
-include techlibs/*/*.d
|
||||
|
||||
.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator coverage vcxsrc mxebin
|
||||
.PHONY: config-clean config-clang config-gcc config-gcc-static config-gcc-4.8 config-gprof config-sudo
|
||||
.PHONY: config-clean config-clang config-gcc config-gcc-static config-gcc-4.8 config-afl-gcc config-gprof config-sudo
|
||||
|
||||
|
|
|
@ -257,7 +257,7 @@ for them:
|
|||
- Non-synthesizable language features as defined in
|
||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
||||
|
||||
- The ``tri``, ``triand``, ``trior``, ``wand`` and ``wor`` net types
|
||||
- The ``tri``, ``triand`` and ``trior`` net types
|
||||
|
||||
- The ``config`` and ``disable`` keywords and library map files
|
||||
|
||||
|
|
|
@ -194,6 +194,9 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
|
|||
is_logic = false;
|
||||
is_signed = false;
|
||||
is_string = false;
|
||||
is_wand = false;
|
||||
is_wor = false;
|
||||
is_unsized = false;
|
||||
was_checked = false;
|
||||
range_valid = false;
|
||||
range_swapped = false;
|
||||
|
@ -722,7 +725,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
|
|||
}
|
||||
|
||||
// create an AST node for a constant (using a bit vector as value)
|
||||
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
|
||||
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
|
||||
{
|
||||
AstNode *node = new AstNode(AST_CONSTANT);
|
||||
node->is_signed = is_signed;
|
||||
|
@ -736,9 +739,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
|
|||
node->range_valid = true;
|
||||
node->range_left = node->bits.size()-1;
|
||||
node->range_right = 0;
|
||||
node->is_unsized = is_unsized;
|
||||
return node;
|
||||
}
|
||||
|
||||
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
|
||||
{
|
||||
return mkconst_bits(v, is_signed, false);
|
||||
}
|
||||
|
||||
// create an AST node for a constant (using a string in bit vector form as value)
|
||||
AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
|
||||
{
|
||||
|
@ -775,6 +784,14 @@ bool AstNode::bits_only_01() const
|
|||
return true;
|
||||
}
|
||||
|
||||
RTLIL::Const AstNode::bitsAsUnsizedConst(int width)
|
||||
{
|
||||
RTLIL::State extbit = bits.back();
|
||||
while (width > int(bits.size()))
|
||||
bits.push_back(extbit);
|
||||
return RTLIL::Const(bits);
|
||||
}
|
||||
|
||||
RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed)
|
||||
{
|
||||
std::vector<RTLIL::State> bits = this->bits;
|
||||
|
|
|
@ -173,7 +173,7 @@ namespace AST
|
|||
// node content - most of it is unused in most node types
|
||||
std::string str;
|
||||
std::vector<RTLIL::State> bits;
|
||||
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked;
|
||||
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized;
|
||||
int port_id, range_left, range_right;
|
||||
uint32_t integer;
|
||||
double realvalue;
|
||||
|
@ -262,6 +262,7 @@ namespace AST
|
|||
|
||||
// helper functions for creating AST nodes for constants
|
||||
static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32);
|
||||
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
|
||||
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
|
||||
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
|
||||
static AstNode *mkconst_str(const std::string &str);
|
||||
|
@ -269,6 +270,7 @@ namespace AST
|
|||
// helper function for creating sign-extended const objects
|
||||
RTLIL::Const bitsAsConst(int width, bool is_signed);
|
||||
RTLIL::Const bitsAsConst(int width = -1);
|
||||
RTLIL::Const bitsAsUnsizedConst(int width);
|
||||
RTLIL::Const asAttrConst();
|
||||
RTLIL::Const asParaConst();
|
||||
uint64_t asInt(bool is_signed);
|
||||
|
|
|
@ -904,7 +904,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
if (!range_valid)
|
||||
log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str());
|
||||
|
||||
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
|
||||
if (!(range_left >= range_right || (range_left == -1 && range_right == 0)))
|
||||
log_file_error(filename, linenum, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
|
||||
|
||||
RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
|
||||
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
|
@ -919,6 +920,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
wire->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
if (is_wand) wire->set_bool_attribute("\\wand");
|
||||
if (is_wor) wire->set_bool_attribute("\\wor");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -963,8 +967,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
detectSignWidth(width_hint, sign_hint);
|
||||
is_signed = sign_hint;
|
||||
|
||||
if (type == AST_CONSTANT)
|
||||
return RTLIL::SigSpec(bitsAsConst());
|
||||
if (type == AST_CONSTANT) {
|
||||
if (is_unsized) {
|
||||
return RTLIL::SigSpec(bitsAsUnsizedConst(width_hint));
|
||||
} else {
|
||||
return RTLIL::SigSpec(bitsAsConst());
|
||||
}
|
||||
}
|
||||
|
||||
RTLIL::SigSpec sig = realAsConst(width_hint);
|
||||
log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
|
||||
|
|
|
@ -71,7 +71,7 @@ static int my_ilog2(int x)
|
|||
}
|
||||
|
||||
// parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
|
||||
static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type)
|
||||
static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized)
|
||||
{
|
||||
// all digits in string (MSB at index 0)
|
||||
std::vector<uint8_t> digits;
|
||||
|
@ -129,6 +129,9 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_unsized && (len > len_in_bits))
|
||||
log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len);
|
||||
|
||||
for (len = len - 1; len >= 0; len--)
|
||||
if (data[len] == RTLIL::S1)
|
||||
break;
|
||||
|
@ -186,7 +189,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
|
|||
// Simple base-10 integer
|
||||
if (*endptr == 0) {
|
||||
std::vector<RTLIL::State> data;
|
||||
my_strtobin(data, str, -1, 10, case_type);
|
||||
my_strtobin(data, str, -1, 10, case_type, false);
|
||||
if (data.back() == RTLIL::S1)
|
||||
data.push_back(RTLIL::S0);
|
||||
return AstNode::mkconst_bits(data, true);
|
||||
|
@ -201,6 +204,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
|
|||
{
|
||||
std::vector<RTLIL::State> data;
|
||||
bool is_signed = false;
|
||||
bool is_unsized = false;
|
||||
if (*(endptr+1) == 's') {
|
||||
is_signed = true;
|
||||
endptr++;
|
||||
|
@ -209,28 +213,34 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
|
|||
{
|
||||
case 'b':
|
||||
case 'B':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 2, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 2, case_type, false);
|
||||
break;
|
||||
case 'o':
|
||||
case 'O':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 8, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 8, case_type, false);
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 10, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 10, case_type, false);
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
my_strtobin(data, endptr+2, len_in_bits, 16, case_type);
|
||||
my_strtobin(data, endptr+2, len_in_bits, 16, case_type, false);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
char next_char = char(tolower(*(endptr+1)));
|
||||
if (next_char == '0' || next_char == '1' || next_char == 'x' || next_char == 'z') {
|
||||
my_strtobin(data, endptr+1, 1, 2, case_type, true);
|
||||
is_unsized = true;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (len_in_bits < 0) {
|
||||
if (is_signed && data.back() == RTLIL::S1)
|
||||
data.push_back(RTLIL::S0);
|
||||
}
|
||||
return AstNode::mkconst_bits(data, is_signed);
|
||||
return AstNode::mkconst_bits(data, is_signed, is_unsized);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -218,6 +218,8 @@ YOSYS_NAMESPACE_END
|
|||
"output" { return TOK_OUTPUT; }
|
||||
"inout" { return TOK_INOUT; }
|
||||
"wire" { return TOK_WIRE; }
|
||||
"wor" { return TOK_WOR; }
|
||||
"wand" { return TOK_WAND; }
|
||||
"reg" { return TOK_REG; }
|
||||
"integer" { return TOK_INTEGER; }
|
||||
"signed" { return TOK_SIGNED; }
|
||||
|
@ -232,7 +234,7 @@ YOSYS_NAMESPACE_END
|
|||
return TOK_CONSTVAL;
|
||||
}
|
||||
|
||||
[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
|
||||
[0-9]*[ \t]*\'s?[bodhBODH]*[ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
|
||||
frontend_verilog_yylval.string = new std::string(yytext);
|
||||
return TOK_CONSTVAL;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ struct specify_rise_fall {
|
|||
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
||||
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
|
||||
%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR
|
||||
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC
|
||||
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC
|
||||
%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
|
||||
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
|
||||
%token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC
|
||||
|
@ -485,6 +485,12 @@ wire_type_token_io:
|
|||
wire_type_token:
|
||||
TOK_WIRE {
|
||||
} |
|
||||
TOK_WOR {
|
||||
astbuf3->is_wor = true;
|
||||
} |
|
||||
TOK_WAND {
|
||||
astbuf3->is_wand = true;
|
||||
} |
|
||||
TOK_REG {
|
||||
astbuf3->is_reg = true;
|
||||
} |
|
||||
|
|
|
@ -230,6 +230,9 @@ static void logv_warning_with_prefix(const char *prefix,
|
|||
}
|
||||
else
|
||||
{
|
||||
int bak_log_make_debug = log_make_debug;
|
||||
log_make_debug = 0;
|
||||
|
||||
for (auto &re : log_werror_regexes)
|
||||
if (std::regex_search(message, re))
|
||||
log_error("%s", message.c_str());
|
||||
|
@ -254,6 +257,7 @@ static void logv_warning_with_prefix(const char *prefix,
|
|||
}
|
||||
|
||||
log_warnings_count++;
|
||||
log_make_debug = bak_log_make_debug;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,6 +289,9 @@ static void logv_error_with_prefix(const char *prefix,
|
|||
#ifdef EMSCRIPTEN
|
||||
auto backup_log_files = log_files;
|
||||
#endif
|
||||
int bak_log_make_debug = log_make_debug;
|
||||
log_make_debug = 0;
|
||||
log_suppressed();
|
||||
|
||||
if (log_errfile != NULL)
|
||||
log_files.push_back(log_errfile);
|
||||
|
@ -298,6 +305,8 @@ static void logv_error_with_prefix(const char *prefix,
|
|||
log("%s%s", prefix, log_last_error.c_str());
|
||||
log_flush();
|
||||
|
||||
log_make_debug = bak_log_make_debug;
|
||||
|
||||
if (log_error_atexit)
|
||||
log_error_atexit();
|
||||
|
||||
|
|
|
@ -607,6 +607,7 @@ struct RTLIL::SigChunk
|
|||
RTLIL::SigChunk &operator =(const RTLIL::SigChunk &other) = default;
|
||||
|
||||
RTLIL::SigChunk extract(int offset, int length) const;
|
||||
inline int size() const { return width; }
|
||||
|
||||
bool operator <(const RTLIL::SigChunk &other) const;
|
||||
bool operator ==(const RTLIL::SigChunk &other) const;
|
||||
|
|
|
@ -562,7 +562,8 @@ struct HierarchyPass : public Pass {
|
|||
log("In parametric designs, a module might exists in several variations with\n");
|
||||
log("different parameter values. This pass looks at all modules in the current\n");
|
||||
log("design an re-runs the language frontends for the parametric modules as\n");
|
||||
log("needed.\n");
|
||||
log("needed. It also resolves assignments to wired logic data types (wand/wor),\n");
|
||||
log("resolves positional module parameters, unroll array instances, and more.\n");
|
||||
log("\n");
|
||||
log(" -check\n");
|
||||
log(" also check the design hierarchy. this generates an error when\n");
|
||||
|
@ -943,62 +944,178 @@ struct HierarchyPass : public Pass {
|
|||
std::vector<Module*> design_modules = design->modules();
|
||||
|
||||
for (auto module : design_modules)
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
Module *m = design->module(cell->type);
|
||||
pool<Wire*> wand_wor_index;
|
||||
dict<Wire*, SigSpec> wand_map, wor_map;
|
||||
vector<SigSig> new_connections;
|
||||
|
||||
if (m == nullptr)
|
||||
continue;
|
||||
|
||||
if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
|
||||
IdString new_m_name = m->derive(design, cell->parameters, true);
|
||||
if (new_m_name.empty())
|
||||
continue;
|
||||
if (new_m_name != m->name) {
|
||||
m = design->module(new_m_name);
|
||||
blackbox_derivatives.insert(m);
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
if (wire->get_bool_attribute("\\wand")) {
|
||||
wand_map[wire] = SigSpec();
|
||||
wand_wor_index.insert(wire);
|
||||
}
|
||||
if (wire->get_bool_attribute("\\wor")) {
|
||||
wor_map[wire] = SigSpec();
|
||||
wand_wor_index.insert(wire);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
for (auto &conn : module->connections())
|
||||
{
|
||||
Wire *w = m->wire(conn.first);
|
||||
SigSig new_conn;
|
||||
int cursor = 0;
|
||||
|
||||
if (w == nullptr || w->port_id == 0)
|
||||
continue;
|
||||
|
||||
if (GetSize(conn.second) == 0)
|
||||
continue;
|
||||
|
||||
SigSpec sig = conn.second;
|
||||
|
||||
if (!keep_portwidths && GetSize(w) != GetSize(conn.second))
|
||||
for (auto c : conn.first.chunks())
|
||||
{
|
||||
if (GetSize(w) < GetSize(conn.second))
|
||||
{
|
||||
int n = GetSize(conn.second) - GetSize(w);
|
||||
if (!w->port_input && w->port_output)
|
||||
module->connect(sig.extract(GetSize(w), n), Const(0, n));
|
||||
sig.remove(GetSize(w), n);
|
||||
Wire *w = c.wire;
|
||||
SigSpec rhs = conn.second.extract(cursor, GetSize(c));
|
||||
|
||||
if (wand_wor_index.count(w) == 0) {
|
||||
new_conn.first.append(c);
|
||||
new_conn.second.append(rhs);
|
||||
} else {
|
||||
if (wand_map.count(w)) {
|
||||
SigSpec sig = SigSpec(State::S1, GetSize(w));
|
||||
sig.replace(c.offset, rhs);
|
||||
wand_map.at(w).append(sig);
|
||||
} else {
|
||||
SigSpec sig = SigSpec(State::S0, GetSize(w));
|
||||
sig.replace(c.offset, rhs);
|
||||
wor_map.at(w).append(sig);
|
||||
}
|
||||
}
|
||||
else
|
||||
cursor += GetSize(c);
|
||||
}
|
||||
new_connections.push_back(new_conn);
|
||||
}
|
||||
module->new_connections(new_connections);
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (!cell->known())
|
||||
continue;
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
{
|
||||
if (!cell->output(conn.first))
|
||||
continue;
|
||||
|
||||
SigSpec new_sig;
|
||||
bool update_port = false;
|
||||
|
||||
for (auto c : conn.second.chunks())
|
||||
{
|
||||
int n = GetSize(w) - GetSize(conn.second);
|
||||
if (w->port_input && !w->port_output)
|
||||
sig.append(Const(0, n));
|
||||
else
|
||||
sig.append(module->addWire(NEW_ID, n));
|
||||
Wire *w = c.wire;
|
||||
|
||||
if (wand_wor_index.count(w) == 0) {
|
||||
new_sig.append(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
Wire *t = module->addWire(NEW_ID, GetSize(c));
|
||||
new_sig.append(t);
|
||||
update_port = true;
|
||||
|
||||
if (wand_map.count(w)) {
|
||||
SigSpec sig = SigSpec(State::S1, GetSize(w));
|
||||
sig.replace(c.offset, t);
|
||||
wand_map.at(w).append(sig);
|
||||
} else {
|
||||
SigSpec sig = SigSpec(State::S0, GetSize(w));
|
||||
sig.replace(c.offset, t);
|
||||
wor_map.at(w).append(sig);
|
||||
}
|
||||
}
|
||||
|
||||
if (!conn.second.is_fully_const() || !w->port_input || w->port_output)
|
||||
log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", log_id(module), log_id(cell),
|
||||
log_id(conn.first), GetSize(conn.second), GetSize(sig));
|
||||
cell->setPort(conn.first, sig);
|
||||
if (update_port)
|
||||
cell->setPort(conn.first, new_sig);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto w : wand_wor_index)
|
||||
{
|
||||
bool wand = wand_map.count(w);
|
||||
SigSpec sigs = wand ? wand_map.at(w) : wor_map.at(w);
|
||||
|
||||
if (GetSize(sigs) == 0)
|
||||
continue;
|
||||
|
||||
if (GetSize(w) == 1) {
|
||||
if (wand)
|
||||
module->addReduceAnd(NEW_ID, sigs, w);
|
||||
else
|
||||
module->addReduceOr(NEW_ID, sigs, w);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (w->port_output && !w->port_input && sig.has_const())
|
||||
log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n",
|
||||
log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig));
|
||||
SigSpec s = sigs.extract(0, GetSize(w));
|
||||
for (int i = GetSize(w); i < GetSize(sigs); i += GetSize(w)) {
|
||||
if (wand)
|
||||
s = module->And(NEW_ID, s, sigs.extract(i, GetSize(w)));
|
||||
else
|
||||
s = module->Or(NEW_ID, s, sigs.extract(i, GetSize(w)));
|
||||
}
|
||||
module->connect(w, s);
|
||||
}
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
Module *m = design->module(cell->type);
|
||||
|
||||
if (m == nullptr)
|
||||
continue;
|
||||
|
||||
if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
|
||||
IdString new_m_name = m->derive(design, cell->parameters, true);
|
||||
if (new_m_name.empty())
|
||||
continue;
|
||||
if (new_m_name != m->name) {
|
||||
m = design->module(new_m_name);
|
||||
blackbox_derivatives.insert(m);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
{
|
||||
Wire *w = m->wire(conn.first);
|
||||
|
||||
if (w == nullptr || w->port_id == 0)
|
||||
continue;
|
||||
|
||||
if (GetSize(conn.second) == 0)
|
||||
continue;
|
||||
|
||||
SigSpec sig = conn.second;
|
||||
|
||||
if (!keep_portwidths && GetSize(w) != GetSize(conn.second))
|
||||
{
|
||||
if (GetSize(w) < GetSize(conn.second))
|
||||
{
|
||||
int n = GetSize(conn.second) - GetSize(w);
|
||||
if (!w->port_input && w->port_output)
|
||||
module->connect(sig.extract(GetSize(w), n), Const(0, n));
|
||||
sig.remove(GetSize(w), n);
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = GetSize(w) - GetSize(conn.second);
|
||||
if (w->port_input && !w->port_output)
|
||||
sig.append(Const(0, n));
|
||||
else
|
||||
sig.append(module->addWire(NEW_ID, n));
|
||||
}
|
||||
|
||||
if (!conn.second.is_fully_const() || !w->port_input || w->port_output)
|
||||
log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", log_id(module), log_id(cell),
|
||||
log_id(conn.first), GetSize(conn.second), GetSize(sig));
|
||||
cell->setPort(conn.first, sig);
|
||||
}
|
||||
|
||||
if (w->port_output && !w->port_input && sig.has_const())
|
||||
log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n",
|
||||
log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -319,8 +319,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
wire->attributes.erase("\\init");
|
||||
|
||||
if (GetSize(wire) == 0) {
|
||||
// delete zero-width wires
|
||||
goto delete_this_wire;
|
||||
// delete zero-width wires, unless they are module ports
|
||||
if (wire->port_id == 0)
|
||||
goto delete_this_wire;
|
||||
} else
|
||||
if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) {
|
||||
// do not delete anything with "keep" or module ports or initialized wires
|
||||
|
|
|
@ -338,16 +338,6 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
|
|||
val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
|
||||
}
|
||||
|
||||
if (sig_e.size()) {
|
||||
if (!sig_e.is_fully_const())
|
||||
return false;
|
||||
if (sig_e != val_ep) {
|
||||
if (has_init)
|
||||
mod->connect(sig_q, val_init);
|
||||
goto delete_dff;
|
||||
}
|
||||
}
|
||||
|
||||
if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) {
|
||||
std::set<RTLIL::Cell*> muxes;
|
||||
mux_drivers.find(sig_d, muxes);
|
||||
|
@ -365,39 +355,60 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
|
|||
}
|
||||
}
|
||||
|
||||
// If clock is driven by a constant and (i) no reset signal
|
||||
// (ii) Q has no initial value
|
||||
// (iii) initial value is same as reset value
|
||||
if (!sig_c.empty() && sig_c.is_fully_const() && (!sig_r.size() || !has_init || val_init == val_rv)) {
|
||||
if (val_rv.bits.size() == 0)
|
||||
val_rv = val_init;
|
||||
// Q is permanently reset value or initial value
|
||||
mod->connect(sig_q, val_rv);
|
||||
goto delete_dff;
|
||||
}
|
||||
|
||||
// If D is fully undefined and reset signal present and (i) Q has no initial value
|
||||
// (ii) initial value is same as reset value
|
||||
if (sig_d.is_fully_undef() && sig_r.size() && (!has_init || val_init == val_rv)) {
|
||||
// Q is permanently reset value
|
||||
mod->connect(sig_q, val_rv);
|
||||
goto delete_dff;
|
||||
}
|
||||
|
||||
// If D is fully undefined and no reset signal and Q has an initial value
|
||||
if (sig_d.is_fully_undef() && !sig_r.size() && has_init) {
|
||||
// Q is permanently initial value
|
||||
mod->connect(sig_q, val_init);
|
||||
goto delete_dff;
|
||||
}
|
||||
|
||||
// If D is fully constant and (i) no reset signal
|
||||
// (ii) reset value is same as constant D
|
||||
// and (a) has no initial value
|
||||
// (b) initial value same as constant D
|
||||
if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) {
|
||||
// Q is permanently D
|
||||
mod->connect(sig_q, sig_d);
|
||||
goto delete_dff;
|
||||
}
|
||||
|
||||
// If D input is same as Q output and (i) no reset signal
|
||||
// (ii) no initial signal
|
||||
// (iii) initial value is same as reset value
|
||||
if (sig_d == sig_q && (sig_r.empty() || !has_init || val_init == val_rv)) {
|
||||
// Q is permanently reset value or initial value
|
||||
if (sig_r.size())
|
||||
mod->connect(sig_q, val_rv);
|
||||
if (has_init)
|
||||
else if (has_init)
|
||||
mod->connect(sig_q, val_init);
|
||||
goto delete_dff;
|
||||
}
|
||||
|
||||
// If reset signal is present, and is fully constant
|
||||
if (!sig_r.empty() && sig_r.is_fully_const())
|
||||
{
|
||||
// If reset value is permanently active or if reset is undefined
|
||||
if (sig_r == val_rp || sig_r.is_fully_undef()) {
|
||||
// Q is permanently reset value
|
||||
mod->connect(sig_q, val_rv);
|
||||
goto delete_dff;
|
||||
}
|
||||
|
@ -417,6 +428,30 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
|
|||
dff->unsetPort("\\R");
|
||||
}
|
||||
|
||||
// If enable signal is present, and is fully constant
|
||||
if (!sig_e.empty() && sig_e.is_fully_const())
|
||||
{
|
||||
// If enable value is permanently inactive
|
||||
if (sig_e != val_ep) {
|
||||
// Q is permanently initial value
|
||||
mod->connect(sig_q, val_init);
|
||||
goto delete_dff;
|
||||
}
|
||||
|
||||
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") {
|
||||
dff->type = "$dff";
|
||||
dff->unsetPort("\\EN");
|
||||
dff->unsetParam("\\EN_POLARITY");
|
||||
return true;
|
||||
}
|
||||
|
||||
log_assert(dff->type.substr(0,7) == "$_DFFE_");
|
||||
dff->type = stringf("$_DFF_%c_", + dff->type[7]);
|
||||
dff->unsetPort("\\E");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
delete_dff:
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
module wandwor_test0 (A, B, C, D, X, Y, Z);
|
||||
input A, B, C, D;
|
||||
output wor X;
|
||||
output wand Y;
|
||||
output Z;
|
||||
|
||||
assign X = A, X = B, Y = C, Y = D;
|
||||
foo foo_0 (C, D, X);
|
||||
foo foo_1 (A, B, Y);
|
||||
foo foo_2 (X, Y, Z);
|
||||
endmodule
|
||||
|
||||
module wandwor_test1 (A, B, C, D, X, Y, Z);
|
||||
input [3:0] A, B, C, D;
|
||||
output wor [3:0] X;
|
||||
output wand [3:0] Y;
|
||||
output Z;
|
||||
|
||||
bar bar_inst (
|
||||
.I0({A, B}),
|
||||
.I1({B, A}),
|
||||
.O({X, Y})
|
||||
);
|
||||
|
||||
assign X = C, X = D;
|
||||
assign Y = C, Y = D;
|
||||
assign Z = ^{X,Y};
|
||||
endmodule
|
||||
|
||||
module foo(input I0, I1, output O);
|
||||
assign O = I0 ^ I1;
|
||||
endmodule
|
||||
|
||||
module bar(input [7:0] I0, I1, output [7:0] O);
|
||||
assign O = I0 + I1;
|
||||
endmodule
|
|
@ -1,30 +1,50 @@
|
|||
module opt_rmdff_test (input C, input D, input E, output reg [16:0] Q);
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove0 (.CLK(C), .D(D), .EN(1'b0), .Q(Q[0]));
|
||||
initial Q[1] = 1'b1;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove1 (.CLK(C), .D(D), .EN(1'b0), .Q(Q[1]));
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove2 (.CLK(C), .D(D), .EN(1'bx), .Q(Q[2]));
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) keep2 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[2]));
|
||||
initial Q[3] = 1'b0;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(0), .EN_POLARITY(1)) keep3 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[3]));
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove4 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[4]));
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove5 (.CLK(C), .D(D), .EN(1'bx), .Q(Q[5]));
|
||||
initial Q[6] = 1'b0;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(0), .EN_POLARITY(0)) keep6 (.CLK(C), .D(D), .EN(E), .Q(Q[6]));
|
||||
module opt_rmdff_test (input C, input D, input E, output [29:0] Q);
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove0 (.CLK(C), .D(D), .EN(1'b0), .Q(Q[0])); // EN is never active
|
||||
(* init = "1'b1" *) wire Q1; assign Q[1] = Q1;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove1 (.CLK(C), .D(D), .EN(1'b0), .Q(Q1)); // EN is never active
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove2 (.CLK(C), .D(D), .EN(1'bx), .Q(Q[2])); // EN is don't care
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) keep3 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[3])); // EN is always active
|
||||
(* init = "1'b0" *) wire Q4; assign Q[4] = Q4;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(0), .EN_POLARITY(1)) keep4 (.CLK(C), .D(D), .EN(1'b1), .Q(Q4)); // EN is always active
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove5 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[5])); // EN is never active
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove6 (.CLK(C), .D(D), .EN(1'bx), .Q(Q[6])); // EN is don't care
|
||||
(* init = "1'b0" *) wire Q7; assign Q[7] = Q7;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(0), .EN_POLARITY(0)) keep7 (.CLK(C), .D(D), .EN(E), .Q(Q7)); // EN is non constant
|
||||
|
||||
\$_DFFE_PP_ remove7 (.C(C), .D(D), .E(1'b0), .Q(Q[7]));
|
||||
initial Q[8] = 1'b1;
|
||||
\$_DFFE_PP_ remove8 (.C(C), .D(D), .E(1'b0), .Q(Q[8]));
|
||||
\$_DFFE_PP_ remove9 (.C(C), .D(D), .E(1'bx), .Q(Q[9]));
|
||||
\$_DFFE_PP_ keep10 (.C(C), .D(D), .E(1'b1), .Q(Q[10]));
|
||||
initial Q[11] = 1'b0;
|
||||
\$_DFFE_PP_ keep11 (.C(C), .D(D), .E(1'b1), .Q(Q[11]));
|
||||
\$_DFFE_PP_ remove8 (.C(C), .D(D), .E(1'b0), .Q(Q[8])); // EN is never active
|
||||
(* init = "1'b1" *) wire Q9; assign Q[9] = Q9;
|
||||
\$_DFFE_PP_ remove9 (.C(C), .D(D), .E(1'b0), .Q(Q9)); // EN is never active
|
||||
\$_DFFE_PP_ remove10 (.C(C), .D(D), .E(1'bx), .Q(Q[10])); // EN is don't care
|
||||
\$_DFFE_PP_ keep11 (.C(C), .D(D), .E(1'b1), .Q(Q[11])); // EN is always active
|
||||
(* init = "1'b0" *) wire Q12; assign Q[12] = Q12;
|
||||
\$_DFFE_PP_ keep12 (.C(C), .D(D), .E(1'b1), .Q(Q12)); // EN is always active
|
||||
|
||||
\$_DFFE_NN_ remove12 (.C(C), .D(D), .E(1'b1), .Q(Q[12]));
|
||||
initial Q[13] = 1'b1;
|
||||
\$_DFFE_NN_ remove13 (.C(C), .D(D), .E(1'b1), .Q(Q[13]));
|
||||
\$_DFFE_NN_ remove14 (.C(C), .D(D), .E(1'bx), .Q(Q[14]));
|
||||
\$_DFFE_NN_ keep15 (.C(C), .D(D), .E(1'b0), .Q(Q[15]));
|
||||
initial Q[16] = 1'b0;
|
||||
\$_DFFE_NN_ keep16 (.C(C), .D(D), .E(1'b0), .Q(Q[16]));
|
||||
\$_DFFE_NN_ remove13 (.C(C), .D(D), .E(1'b1), .Q(Q[13])); // EN is never active
|
||||
(* init = "1'b1" *) wire Q14; assign Q[14] = Q14;
|
||||
\$_DFFE_NN_ remove14 (.C(C), .D(D), .E(1'b1), .Q(Q14)); // EN is never active
|
||||
\$_DFFE_NN_ remove15 (.C(C), .D(D), .E(1'bx), .Q(Q[15])); // EN is don't care
|
||||
\$_DFFE_NN_ keep16 (.C(C), .D(D), .E(1'b0), .Q(Q[16])); // EN is always active
|
||||
(* init = "1'b0" *) wire Q17; assign Q[17] = Q17;
|
||||
\$_DFFE_NN_ keep17 (.C(C), .D(D), .E(1'b0), .Q(Q17)); // EN is always active
|
||||
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove18 (.CLK(1'b0), .D(D), .EN(E), .Q(Q[18])); // CLK is constant
|
||||
(* init = "1'b1" *) wire Q19; assign Q[19] = Q19;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove19 (.CLK(1'b1), .D(D), .EN(E), .Q(Q19)); // CLK is constant
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove20 (.CLK(C), .D(1'bx), .EN(E), .Q(Q[20])); // D is undriven, Q has no initial value
|
||||
(* init = "1'b0" *) wire Q21; assign Q[21] = Q21;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) keep21 (.CLK(C), .D(1'bx), .EN(E), .Q(Q21)); // D is undriven, Q has initial value
|
||||
//\$dffe #(.WIDTH(1), .CLK_POLARITY(0), .EN_POLARITY(1)) remove22 (.CLK(C), .D(1'b0), .EN(1'b1), .Q(Q[22])); // D is constant, no initial Q value, EN is always active
|
||||
// // (TODO, Q starts with 1'bx and becomes 1'b0)
|
||||
(* init = "1'b0" *) wire Q23; assign Q[23] = Q23;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) noenable23 (.CLK(C), .D(1'b0), .EN(1'b1), .Q(Q23)); // D is constant, initial Q value same as D, EN is always active
|
||||
(* init = "1'b1" *) wire Q24; assign Q[24] = Q24;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) keep24 (.CLK(C), .D(1'b0), .EN(1'b0), .Q(Q24)); // D is constant, initial Q value NOT same as D, EN is always active
|
||||
(* init = "1'b1" *) wire Q25; assign Q[25] = Q25;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove25 (.CLK(C), .D(1'b0), .EN(1'b1), .Q(Q25)); // D is constant, EN is never active
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove26 (.CLK(C), .D(Q[26]), .EN(1'b1), .Q(Q[26])); // D is Q, EN is always active
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove27 (.CLK(C), .D(Q[27]), .EN(1'b1), .Q(Q[27])); // D is Q, EN is never active, but no initial value
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove28 (.CLK(C), .D(Q[28]), .EN(E), .Q(Q[28])); // EN is nonconst, but no initial value
|
||||
(* init = "1'b1" *) wire Q29; assign Q[29] = Q29;
|
||||
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) keep29 (.CLK(C), .D(Q[29]), .EN(1'b1), .Q(Q29)); // EN is always active, but with initial value
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -2,12 +2,13 @@ read_verilog -icells opt_rmdff.v
|
|||
prep
|
||||
design -stash gold
|
||||
read_verilog -icells opt_rmdff.v
|
||||
proc
|
||||
opt_rmdff
|
||||
|
||||
select -assert-count 0 c:remove*
|
||||
select -assert-min 7 c:keep*
|
||||
select -assert-count 0 t:$dffe 7:$_DFFE_* %u c:noenable* %i
|
||||
|
||||
prep
|
||||
design -stash gate
|
||||
|
||||
design -import gold -as gold
|
||||
|
|
Loading…
Reference in New Issue