diff options
| author | Andrew Zonenberg <azonenberg@drawersteak.com> | 2017-02-11 11:25:16 -0800 | 
|---|---|---|
| committer | Andrew Zonenberg <azonenberg@drawersteak.com> | 2017-02-11 11:25:16 -0800 | 
| commit | 203b521a781ccc4c8dba05d2cc73e4625bcf2a8e (patch) | |
| tree | 12efc580521210c43957c010a7fe5367606cb2f2 | |
| parent | 0d7e71f7abd49d1c95f0657993b55bb5f66317a1 (diff) | |
| parent | cdb6ceb8c63f2c38bdba3f66be7c444def43897e (diff) | |
| download | yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.tar.gz yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.tar.bz2 yosys-203b521a781ccc4c8dba05d2cc73e4625bcf2a8e.zip  | |
Merge https://github.com/cliffordwolf/yosys
| -rw-r--r-- | Makefile | 51 | ||||
| -rw-r--r-- | README.md | 28 | ||||
| -rw-r--r-- | frontends/verific/verific.cc | 145 | ||||
| -rw-r--r-- | frontends/verilog/verilog_lexer.l | 20 | ||||
| -rw-r--r-- | frontends/verilog/verilog_parser.y | 15 | ||||
| -rw-r--r-- | kernel/log.cc | 7 | ||||
| -rw-r--r-- | kernel/log.h | 1 | ||||
| -rw-r--r-- | passes/opt/opt_expr.cc | 52 | ||||
| -rw-r--r-- | passes/opt/opt_merge.cc | 8 | ||||
| -rw-r--r-- | passes/opt/opt_rmdff.cc | 4 | 
10 files changed, 273 insertions, 58 deletions
@@ -53,27 +53,35 @@ all: top-all  YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))  VPATH := $(YOSYS_SRC) -CXXFLAGS += -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include -LDFLAGS += -L$(LIBDIR) -LDLIBS = -lstdc++ -lm +CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include +LDFLAGS := $(LDFLAGS) -L$(LIBDIR) +LDLIBS := $(LDLIBS) -lstdc++ -lm -PKG_CONFIG = pkg-config -SED = sed -BISON = bison +PKG_CONFIG ?= pkg-config +SED ?= sed +BISON ?= bison  ifeq (Darwin,$(findstring Darwin,$(shell uname))) -	# add macports/homebrew include and library path to search directories, don't use '-rdynamic' and '-lrt': -	CXXFLAGS += -I/opt/local/include -I/usr/local/opt/readline/include -	LDFLAGS += -L/opt/local/lib -L/usr/local/opt/readline/lib -	# add homebrew's libffi include and library path -	CXXFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --cflags libffi) -	LDFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --libs libffi) -	# use bison installed by homebrew if available -	BISON = $(shell (brew list bison | grep -m1 "bin/bison") || echo bison) -	SED = sed +# homebrew search paths +ifneq ($(shell which brew),) +BREW_PREFIX := $(shell brew --prefix)/opt +CXXFLAGS += -I$(BREW_PREFIX)/readline/include +LDFLAGS += -L$(BREW_PREFIX)/readline/lib +PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH) +PKG_CONFIG_PATH := $(BREW_PREFIX)/tcl-tk/lib/pkgconfig:$(PKG_CONFIG_PATH) +export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH) + +# macports search paths +else ifneq ($(shell which port),) +PORT_PREFIX := $(patsubst %/bin/port,%,$(shell which port)) +CXXFLAGS += -I$(PORT_PREFIX)/include +LDFLAGS += -L$(PORT_PREFIX)/lib +PKG_CONFIG_PATH := $(PORT_PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH) +export PATH := $(PORT_PREFIX)/bin:$(PATH) +endif  else -	LDFLAGS += -rdynamic -	LDLIBS += -lrt +LDFLAGS += -rdynamic +LDLIBS += -lrt  endif  YOSYS_VER := 0.7+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 61f6811.. | wc -l; }) @@ -210,15 +218,16 @@ endif  endif  ifeq ($(ENABLE_PLUGINS),1) -CXXFLAGS += -DYOSYS_ENABLE_PLUGINS $(shell $(PKG_CONFIG) --silence-errors --cflags libffi) -LDLIBS += $(shell $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) -ldl +CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS +LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) -ldl  endif  ifeq ($(ENABLE_TCL),1)  TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")  TCL_INCLUDE ?= /usr/include/$(TCL_VERSION) -CXXFLAGS += -I$(TCL_INCLUDE) -DYOSYS_ENABLE_TCL -LDLIBS += -l$(TCL_VERSION) + +CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL +LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION))  endif  ifeq ($(ENABLE_GPROF),1) @@ -40,14 +40,14 @@ Web Site  More information and documentation can be found on the Yosys web site:  http://www.clifford.at/yosys/ - -Getting Started -=============== +Setup +======  You need a C++ compiler with C++11 support (up-to-date CLANG or GCC is  recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make.  TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).  Xdot (graphviz) is used by the ``show`` command in yosys to display schematics. +  For example on Ubuntu Linux 16.04 LTS the following commands will install all  prerequisites for building yosys: @@ -55,6 +55,13 @@ prerequisites for building yosys:  		libreadline-dev gawk tcl-dev libffi-dev git mercurial \  		graphviz xdot pkg-config python3 +Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies: + +	$ brew install bison flex gawk libffi \ +		git mercurial graphviz pkg-config python3 +	$ sudo port install bison flex readline gawk libffi \ +		git mercurial graphviz pkgconfig python36 +  There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well  as a source distribution for Visual Studio. Visit the Yosys download page for  more information: http://www.clifford.at/yosys/download.html @@ -80,6 +87,9 @@ To build Yosys simply type 'make' in this directory.  Note that this also downloads, builds and installs ABC (using yosys-abc  as executable name). +Getting Started +=============== +  Yosys can be used with the interactive command shell, with  synthesis scripts or with command line arguments. Let's perform  a simple synthesis job using the interactive command shell: @@ -379,10 +389,13 @@ Non-standard or SystemVerilog features for formal verification    to 0 otherwise.  - The system task ``$anyconst`` evaluates to any constant value. This is -  equivalent to declaring a reg as ``const rand``. +  equivalent to declaring a reg as ``rand const``, but also works outside +  of checkers. (Yosys also supports ``rand const`` outside checkers.)  - The system task ``$anyseq`` evaluates to any value, possibly a different -  value in each cycle. This is equivalent to declaring a reg as ``rand``. +  value in each cycle. This is equivalent to declaring a reg as ``rand``, +  but also works outside of checkers. (Yosys also supports ``rand`` +  variables outside checkers.)  - The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are    supported in any clocked block. @@ -407,7 +420,10 @@ from SystemVerilog:  - The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``    and ``bit`` are supported. -- Declaring free variables with ``rand`` and ``const rand`` is supported. +- Declaring free variables with ``rand`` and ``rand const`` is supported. + +- Checkers without a port list that do not need to be instantiated (but instead +  behave like a named block) are supported.  - SystemVerilog packages are supported. Once a SystemVerilog file is read    into a design with ``read_verilog``, all its packages are available to diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index f3b997dc5..bc0bd60fc 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -57,7 +57,7 @@ PRIVATE_NAMESPACE_BEGIN  void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args)  { -	log("VERIFIC-%s [%s] ", +	string message = stringf("VERIFIC-%s [%s] ",  			msg_type == VERIFIC_NONE ? "NONE" :  			msg_type == VERIFIC_ERROR ? "ERROR" :  			msg_type == VERIFIC_WARNING ? "WARNING" : @@ -65,10 +65,16 @@ void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefil  			msg_type == VERIFIC_INFO ? "INFO" :  			msg_type == VERIFIC_COMMENT ? "COMMENT" :  			msg_type == VERIFIC_PROGRAM_ERROR ? "PROGRAM_ERROR" : "UNKNOWN", message_id); +  	if (linefile) -		log("%s:%d: ", LineFile::GetFileName(linefile), LineFile::GetLineNo(linefile)); -	logv(msg, args); -	log("\n"); +		message += stringf("%s:%d: ", LineFile::GetFileName(linefile), LineFile::GetLineNo(linefile)); + +	message += vstringf(msg, args); + +	if (msg_type == VERIFIC_ERROR || msg_type == VERIFIC_WARNING || msg_type == VERIFIC_PROGRAM_ERROR) +		log_warning("%s\n", message.c_str()); +	else +		log("%s\n", message.c_str());  }  struct VerificImporter @@ -617,6 +623,10 @@ struct VerificImporter  		module->fixup_ports(); +		dict<Net*, char, hash_ptr_ops> init_nets; +		pool<Net*, hash_ptr_ops> anyconst_nets; +		pool<Net*, hash_ptr_ops> anyseq_nets; +  		FOREACH_NET_OF_NETLIST(nl, mi, net)  		{  			if (net->IsRamNet()) @@ -643,9 +653,59 @@ struct VerificImporter  				memory->width = bits_in_word;  				memory->size = number_of_bits / bits_in_word; + +				const char *ascii_initdata = net->GetWideInitialValue(); +				if (ascii_initdata) { +					while (*ascii_initdata != 0 && *ascii_initdata != '\'') +						ascii_initdata++; +					if (*ascii_initdata == '\'') +						ascii_initdata++; +					if (*ascii_initdata != 0) { +						log_assert(*ascii_initdata == 'b'); +						ascii_initdata++; +					} +					for (int word_idx = 0; word_idx < memory->size; word_idx++) { +						Const initval = Const(State::Sx, memory->width); +						bool initval_valid = false; +						for (int bit_idx = memory->width-1; bit_idx >= 0; bit_idx--) { +							if (*ascii_initdata == 0) +								break; +							if (*ascii_initdata == '0' || *ascii_initdata == '1') { +								initval[bit_idx] = (*ascii_initdata == '0') ? State::S0 : State::S1; +								initval_valid = true; +							} +							ascii_initdata++; +						} +						if (initval_valid) { +							RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit"); +							cell->parameters["\\WORDS"] = 1; +							if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound()) +								cell->setPort("\\ADDR", word_idx); +							else +								cell->setPort("\\ADDR", memory->size - word_idx - 1); +							cell->setPort("\\DATA", initval); +							cell->parameters["\\MEMID"] = RTLIL::Const(memory->name.str()); +							cell->parameters["\\ABITS"] = 32; +							cell->parameters["\\WIDTH"] = memory->width; +							cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1); +						} +					} +				}  				continue;  			} +			if (net->GetInitialValue()) +				init_nets[net] = net->GetInitialValue(); + +			const char *rand_const_attr = net->GetAttValue(" rand_const"); +			const char *rand_attr = net->GetAttValue(" rand"); + +			if (rand_const_attr != nullptr && !strcmp(rand_const_attr, "1")) +				anyconst_nets.insert(net); + +			else if (rand_attr != nullptr && !strcmp(rand_attr, "1")) +				anyseq_nets.insert(net); +  			if (net_map.count(net)) {  				// log("  skipping net %s.\n", net->Name());  				continue; @@ -683,25 +743,94 @@ struct VerificImporter  				wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex());  				import_attributes(wire->attributes, netbus); -				for (int i = netbus->LeftIndex();; i += netbus->IsUp() ? +1 : -1) { -					if (netbus->ElementAtIndex(i)) { +				RTLIL::Const initval = Const(State::Sx, GetSize(wire)); +				bool initval_valid = false; + +				for (int i = netbus->LeftIndex();; i += netbus->IsUp() ? +1 : -1) +				{ +					if (netbus->ElementAtIndex(i)) +					{ +						int bitidx = i - wire->start_offset;  						net = netbus->ElementAtIndex(i); -						RTLIL::SigBit bit(wire, i - wire->start_offset); +						RTLIL::SigBit bit(wire, bitidx); + +						if (init_nets.count(net)) { +							if (init_nets.at(net) == '0') +								initval.bits.at(bitidx) = State::S0; +							if (init_nets.at(net) == '1') +								initval.bits.at(bitidx) = State::S1; +							initval_valid = true; +							init_nets.erase(net); +						} +  						if (net_map.count(net) == 0)  							net_map[net] = bit;  						else  							module->connect(bit, net_map.at(net));  					} +  					if (i == netbus->RightIndex())  						break;  				} + +				if (initval_valid) +					wire->attributes["\\init"] = initval;  			}  			else  			{  				// log("  skipping netbus %s.\n", netbus->Name());  			} + +			SigSpec anyconst_sig; +			SigSpec anyseq_sig; + +			for (int i = netbus->RightIndex();; i += netbus->IsUp() ? -1 : +1) { +				net = netbus->ElementAtIndex(i); +				if (net != nullptr && anyconst_nets.count(net)) { +					anyconst_sig.append(net_map.at(net)); +					anyconst_nets.erase(net); +				} +				if (net != nullptr && anyseq_nets.count(net)) { +					anyseq_sig.append(net_map.at(net)); +					anyseq_nets.erase(net); +				} +				if (i == netbus->LeftIndex()) +					break; +			} + +			if (GetSize(anyconst_sig)) +				module->connect(anyconst_sig, module->Anyconst(NEW_ID, GetSize(anyconst_sig))); + +			if (GetSize(anyseq_sig)) +				module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig)));  		} +		for (auto it : init_nets) +		{ +			Const initval; +			SigBit bit = net_map.at(it.first); +			log_assert(bit.wire); + +			if (bit.wire->attributes.count("\\init")) +				initval = bit.wire->attributes.at("\\init"); + +			while (GetSize(initval) < GetSize(bit.wire)) +				initval.bits.push_back(State::Sx); + +			if (it.second == '0') +				initval.bits.at(bit.offset) = State::S0; +			if (it.second == '1') +				initval.bits.at(bit.offset) = State::S1; + +			bit.wire->attributes["\\init"] = initval; +		} + +		for (auto net : anyconst_nets) +			module->connect(net_map.at(net), module->Anyconst(NEW_ID)); + +		for (auto net : anyseq_nets) +			module->connect(net_map.at(net), module->Anyseq(NEW_ID)); +  		FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)  		{  			if (inst->Type() == PRIM_SVA_POSEDGE) { @@ -733,7 +862,7 @@ struct VerificImporter  				SigBit outsig = net_map.at(out);  				log_assert(outsig.wire && GetSize(outsig.wire) == 1); -				outsig.wire->attributes["\\init"] == Const(0, 1); +				outsig.wire->attributes["\\init"] = Const(1, 1);  				module->addDff(NEW_ID, net_map.at(clk), net_map.at(in2), net_map.at(out));  				continue; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 97af0ae2d..ff2fa5753 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -175,15 +175,17 @@ YOSYS_NAMESPACE_END  "always_ff"    { SV_KEYWORD(TOK_ALWAYS); }  "always_latch" { SV_KEYWORD(TOK_ALWAYS); } -"assert"   { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } -"assume"   { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } -"cover"    { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } -"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } -"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } -"rand"     { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } -"const"    { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } -"logic"    { SV_KEYWORD(TOK_REG); } -"bit"      { SV_KEYWORD(TOK_REG); } +"assert"     { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } +"assume"     { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } +"cover"      { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } +"restrict"   { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } +"property"   { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } +"rand"       { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } +"const"      { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } +"checker"    { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); } +"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); } +"logic"      { SV_KEYWORD(TOK_REG); } +"bit"        { SV_KEYWORD(TOK_REG); }  "input"   { return TOK_INPUT; }  "output"  { return TOK_OUTPUT; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 3eb03dfd8..1879ff441 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -116,7 +116,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)  %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED  %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME  %token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF -%token TOK_RAND TOK_CONST +%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER  %type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int  %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list @@ -465,7 +465,18 @@ module_body:  module_body_stmt:  	task_func_decl | param_decl | localparam_decl | defparam_decl | wire_decl | assign_stmt | cell_stmt | -	always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property; +	always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl; + +checker_decl: +	TOK_CHECKER TOK_ID ';' { +		AstNode *node = new AstNode(AST_GENBLOCK); +		node->str = *$2; +		ast_stack.back()->children.push_back(node); +		ast_stack.push_back(node); +	} module_body TOK_ENDCHECKER { +		delete $2; +		ast_stack.pop_back(); +	};  task_func_decl:  	attr TOK_DPI_FUNCTION TOK_ID TOK_ID { diff --git a/kernel/log.cc b/kernel/log.cc index cd16bb344..956d93fd1 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -488,6 +488,13 @@ void log_cell(RTLIL::Cell *cell, std::string indent)  	log("%s", buf.str().c_str());  } +void log_wire(RTLIL::Wire *wire, std::string indent) +{ +	std::stringstream buf; +	ILANG_BACKEND::dump_wire(buf, indent, wire); +	log("%s", buf.str().c_str()); +} +  // ---------------------------------------------------  // This is the magic behind the code coverage counters  // --------------------------------------------------- diff --git a/kernel/log.h b/kernel/log.h index 5b1729eb1..34b8ac3a5 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -90,6 +90,7 @@ template<typename T> static inline const char *log_id(T *obj) {  void log_module(RTLIL::Module *module, std::string indent = "");  void log_cell(RTLIL::Cell *cell, std::string indent = ""); +void log_wire(RTLIL::Wire *wire, std::string indent = "");  #ifndef NDEBUG  static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) { diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index b3f2e87ed..236908060 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -383,7 +383,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  		if (detect_const_and || detect_const_or)  		{  			pool<SigBit> input_bits = assign_map(cell->getPort("\\A")).to_sigbit_pool(); -			bool found_zero = false, found_one = false, found_inv = false; +			bool found_zero = false, found_one = false, found_undef = false, found_inv = false, many_conconst = false; +			SigBit non_const_input = State::Sm;  			if (cell->hasPort("\\B")) {  				vector<SigBit> more_bits = assign_map(cell->getPort("\\B")).to_sigbit_vector(); @@ -391,12 +392,20 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  			}  			for (auto bit : input_bits) { -				if (bit == State::S0) -					found_zero = true; -				if (bit == State::S1) -					found_one = true; -				if (invert_map.count(bit) && input_bits.count(invert_map.at(bit))) -					found_inv = true; +				if (bit.wire) { +					if (invert_map.count(bit) && input_bits.count(invert_map.at(bit))) +						found_inv = true; +					if (non_const_input != State::Sm) +						many_conconst = true; +					non_const_input = many_conconst ? State::Sm : bit; +				} else { +					if (bit == State::S0) +						found_zero = true; +					else if (bit == State::S1) +						found_one = true; +					else +						found_undef = true; +				}  			}  			if (detect_const_and && (found_zero || found_inv)) { @@ -410,6 +419,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  				replace_cell(assign_map, module, cell, "const_or", "\\Y", RTLIL::State::S1);  				goto next_cell;  			} + +			if (non_const_input != State::Sm && !found_undef) { +				cover("opt.opt_expr.and_or_buffer"); +				replace_cell(assign_map, module, cell, "and_or_buffer", "\\Y", non_const_input); +				goto next_cell; +			}  		}  		if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor", "$neg") && @@ -1208,6 +1223,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  			//width of the variable port  			int width; +			int const_width;  			bool var_signed; @@ -1216,6 +1232,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  				sigVar = cell->getPort("\\A");  				sigConst = cell->getPort("\\B");  				width = cell->parameters["\\A_WIDTH"].as_int(); +				const_width = cell->parameters["\\B_WIDTH"].as_int();  				var_signed = cell->parameters["\\A_SIGNED"].as_bool();  			} else  			if (cell->type == "$gt" || cell->type == "$le") { @@ -1223,8 +1240,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  				sigVar = cell->getPort("\\B");  				sigConst = cell->getPort("\\A");  				width = cell->parameters["\\B_WIDTH"].as_int(); +				const_width = cell->parameters["\\A_WIDTH"].as_int();  				var_signed = cell->parameters["\\B_SIGNED"].as_bool(); -			} +			} else +				log_abort();  			// replace a(signed) < 0 with the high bit of a  			if (sigConst.is_fully_const() && sigConst.is_fully_zero() && var_signed == true) @@ -1265,7 +1284,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  				}  				int const_bit_set = get_onehot_bit_index(sigConst); -				if (const_bit_set >= 0) { +				if (const_bit_set >= 0 && const_bit_set < width) {  					int bit_set = const_bit_set;  					RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set);  					for (int i = bit_set; i < width; i++) { @@ -1284,6 +1303,21 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons  					did_something = true;  					goto next_cell;  				} +				else if(const_bit_set >= width && const_bit_set >= 0){ +					RTLIL::SigSpec a_prime(RTLIL::State::S0, 1); +					if(is_lt){ +						a_prime[0] = RTLIL::State::S1; +						log("Replacing %s cell `%s' (implementing unsigned X[%d:0] < %s[%d:0]) with constant 0.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1);  +					} +					else{ +						log("Replacing %s cell `%s' (implementing unsigned X[%d:0]>= %s[%d:0]) with constant 1.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1);  +					} +					module->connect(cell->getPort("\\Y"), a_prime); +					module->remove(cell); +					did_something = true; +					goto next_cell; + +				}  			}  		} diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 97989d271..07e4dd39f 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -280,8 +280,12 @@ struct OptMergeWorker  		dff_init_map.set(module);  		for (auto &it : module->wires_) -			if (it.second->attributes.count("\\init") != 0) -				dff_init_map.add(it.second, it.second->attributes.at("\\init")); +			if (it.second->attributes.count("\\init") != 0) { +				Const initval = it.second->attributes.at("\\init"); +				for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++) +					if (initval[i] == State::S0 || initval[i] == State::S1) +						dff_init_map.add(SigBit(it.second, i), initval[i]); +			}  		bool did_something = true;  		while (did_something) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 00094738c..0eefd6a86 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -244,7 +244,9 @@ struct OptRmdffPass : public Pass {  			{  				if (wire->attributes.count("\\init") != 0) {  					Const initval = wire->attributes.at("\\init"); -					dff_init_map.add(wire, initval); +					for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) +						if (initval[i] == State::S0 || initval[i] == State::S1) +							dff_init_map.add(SigBit(wire, i), initval[i]);  					for (int i = 0; i < GetSize(wire); i++) {  						SigBit wire_bit(wire, i), mapped_bit = assign_map(wire_bit);  						if (mapped_bit.wire) {  | 
