mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master'
This commit is contained in:
		
						commit
						fe651922cb
					
				
					 73 changed files with 1321 additions and 444 deletions
				
			
		
							
								
								
									
										13
									
								
								.dockerignore
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.dockerignore
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | .editorconfig | ||||||
|  | .gitignore | ||||||
|  | .gitmodules | ||||||
|  | .github | ||||||
|  | .git | ||||||
|  | Dockerfile | ||||||
|  | README.md | ||||||
|  | manual | ||||||
|  | CodingReadme | ||||||
|  | CodeOfConduct | ||||||
|  | .travis | ||||||
|  | .travis.yml | ||||||
|  | 
 | ||||||
|  | @ -16,6 +16,7 @@ Yosys 0.8 .. Yosys 0.8-dev | ||||||
|     - 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 "read_aiger" frontend | ||||||
|     - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" |     - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								Dockerfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Dockerfile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | FROM ubuntu:18.04 as builder | ||||||
|  | LABEL author="Abdelrahman Hosny <abdelrahman.hosny@hotmail.com>" | ||||||
|  | ENV DEBIAN_FRONTEND=noninteractive | ||||||
|  | RUN apt-get update && apt-get install -y build-essential \ | ||||||
|  |     clang \ | ||||||
|  |     bison \ | ||||||
|  |     flex \ | ||||||
|  |     libreadline-dev \ | ||||||
|  |     gawk \ | ||||||
|  |     tcl-dev \ | ||||||
|  |     libffi-dev \ | ||||||
|  |     git \ | ||||||
|  |     pkg-config \ | ||||||
|  |     python3 && \ | ||||||
|  |     rm -rf /var/lib/apt/lists | ||||||
|  | COPY . / | ||||||
|  | RUN make && \ | ||||||
|  |     make install | ||||||
|  | 
 | ||||||
|  | FROM ubuntu:18.04 | ||||||
|  | ENV DEBIAN_FRONTEND=noninteractive | ||||||
|  | RUN apt-get update && apt-get install -y libreadline-dev tcl-dev | ||||||
|  | 
 | ||||||
|  | COPY --from=builder /yosys /build/yosys | ||||||
|  | COPY --from=builder /yosys-abc /build/yosys-abc | ||||||
|  | COPY --from=builder /yosys-config /build/yosys-config | ||||||
|  | COPY --from=builder /yosys-filterlib /build/yosys-filterlib | ||||||
|  | COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc | ||||||
|  | 
 | ||||||
|  | ENV PATH /build:$PATH | ||||||
|  | RUN useradd -m yosys | ||||||
|  | USER yosys | ||||||
|  | ENTRYPOINT ["yosys"] | ||||||
							
								
								
									
										27
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -22,14 +22,6 @@ ENABLE_PROTOBUF := 0 | ||||||
| 
 | 
 | ||||||
| # python wrappers
 | # python wrappers
 | ||||||
| ENABLE_PYOSYS := 0 | ENABLE_PYOSYS := 0 | ||||||
| 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 |  | ||||||
| endif |  | ||||||
| 
 | 
 | ||||||
| # other configuration flags
 | # other configuration flags
 | ||||||
| ENABLE_GCOV := 0 | ENABLE_GCOV := 0 | ||||||
|  | @ -54,6 +46,10 @@ OS := $(shell uname -s) | ||||||
| PREFIX ?= /usr/local | PREFIX ?= /usr/local | ||||||
| INSTALL_SUDO := | INSTALL_SUDO := | ||||||
| 
 | 
 | ||||||
|  | ifneq ($(wildcard Makefile.conf),) | ||||||
|  | include Makefile.conf | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| BINDIR := $(PREFIX)/bin | BINDIR := $(PREFIX)/bin | ||||||
| LIBDIR := $(PREFIX)/lib | LIBDIR := $(PREFIX)/lib | ||||||
| DATDIR := $(PREFIX)/share/yosys | DATDIR := $(PREFIX)/share/yosys | ||||||
|  | @ -145,6 +141,21 @@ $(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$ | ||||||
| include Makefile.conf | include Makefile.conf | ||||||
| endif | 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) | ifeq ($(CONFIG),clang) | ||||||
| CXX = clang | CXX = clang | ||||||
| LD = clang++ | LD = clang++ | ||||||
|  |  | ||||||
|  | @ -257,7 +257,7 @@ for them: | ||||||
| - Non-synthesizable language features as defined in | - Non-synthesizable language features as defined in | ||||||
| 	IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002 | 	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 | - The ``config`` and ``disable`` keywords and library map files | ||||||
| 
 | 
 | ||||||
|  | @ -413,7 +413,7 @@ Verilog Attributes and non-standard features | ||||||
|       $ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v' |       $ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v' | ||||||
| 
 | 
 | ||||||
| - Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant | - Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant | ||||||
|   expressions as <size>. If the expression is not a simple identifier, it |   expressions as ``<size>``. If the expression is not a simple identifier, it | ||||||
|   must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010`` |   must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010`` | ||||||
| 
 | 
 | ||||||
| - The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in | - The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in | ||||||
|  |  | ||||||
|  | @ -81,11 +81,26 @@ end_of_header: | ||||||
| 	else | 	else | ||||||
| 		log_abort(); | 		log_abort(); | ||||||
| 
 | 
 | ||||||
|  | 	RTLIL::Wire* n0 = module->wire("\\n0"); | ||||||
|  | 	if (n0) | ||||||
|  | 		module->connect(n0, RTLIL::S0); | ||||||
|  | 
 | ||||||
|  | 	for (unsigned i = 0; i < outputs.size(); ++i) { | ||||||
|  | 		RTLIL::Wire *wire = outputs[i]; | ||||||
|  | 		if (wire->port_input) { | ||||||
|  | 			RTLIL::Wire *o_wire = module->addWire(wire->name.str() + "_o"); | ||||||
|  | 			o_wire->port_output = true; | ||||||
|  | 			wire->port_output = false; | ||||||
|  | 			module->connect(o_wire, wire); | ||||||
|  | 			outputs[i] = o_wire; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// Parse footer (symbol table, comments, etc.)
 | 	// Parse footer (symbol table, comments, etc.)
 | ||||||
| 	unsigned l1; | 	unsigned l1; | ||||||
| 	std::string s; | 	std::string s; | ||||||
| 	for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { | 	for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { | ||||||
|         if (c == 'i' || c == 'l' || c == 'o') { | 		if (c == 'i' || c == 'l' || c == 'o' || c == 'b') { | ||||||
| 			f.ignore(1); | 			f.ignore(1); | ||||||
| 			if (!(f >> l1 >> s)) | 			if (!(f >> l1 >> s)) | ||||||
| 				log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); | 				log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); | ||||||
|  | @ -97,11 +112,12 @@ end_of_header: | ||||||
| 			if (c == 'i') wire = inputs[l1]; | 			if (c == 'i') wire = inputs[l1]; | ||||||
| 			else if (c == 'l') wire = latches[l1]; | 			else if (c == 'l') wire = latches[l1]; | ||||||
| 			else if (c == 'o') wire = outputs[l1]; | 			else if (c == 'o') wire = outputs[l1]; | ||||||
|  | 			else if (c == 'b') wire = bad_properties[l1]; | ||||||
| 			else log_abort(); | 			else log_abort(); | ||||||
| 
 | 
 | ||||||
| 			module->rename(wire, stringf("\\%s", s.c_str())); | 			module->rename(wire, stringf("\\%s", s.c_str())); | ||||||
| 		} | 		} | ||||||
|         else if (c == 'b' || c == 'j' || c == 'f') { | 		else if (c == 'j' || c == 'f') { | ||||||
| 			// TODO
 | 			// TODO
 | ||||||
| 		} | 		} | ||||||
| 		else if (c == 'c') { | 		else if (c == 'c') { | ||||||
|  | @ -153,7 +169,7 @@ void AigerReader::parse_aiger_ascii() | ||||||
| 	unsigned l1, l2, l3; | 	unsigned l1, l2, l3; | ||||||
| 
 | 
 | ||||||
| 	// Parse inputs
 | 	// Parse inputs
 | ||||||
|     for (unsigned i = 0; i < I; ++i, ++line_count) { | 	for (unsigned i = 1; i <= I; ++i, ++line_count) { | ||||||
| 		if (!(f >> l1)) | 		if (!(f >> l1)) | ||||||
| 			log_error("Line %u cannot be interpreted as an input!\n", line_count); | 			log_error("Line %u cannot be interpreted as an input!\n", line_count); | ||||||
| 		log_debug("%d is an input\n", l1); | 		log_debug("%d is an input\n", l1); | ||||||
|  | @ -187,8 +203,10 @@ void AigerReader::parse_aiger_ascii() | ||||||
| 			if (!(f >> l3)) | 			if (!(f >> l3)) | ||||||
| 				log_error("Line %u cannot be interpreted as a latch!\n", line_count); | 				log_error("Line %u cannot be interpreted as a latch!\n", line_count); | ||||||
| 
 | 
 | ||||||
|             if (l3 == 0 || l3 == 1) | 			if (l3 == 0) | ||||||
|                 q_wire->attributes["\\init"] = RTLIL::Const(l3); | 				q_wire->attributes["\\init"] = RTLIL::S0; | ||||||
|  | 			else if (l3 == 1) | ||||||
|  | 				q_wire->attributes["\\init"] = RTLIL::S1; | ||||||
| 			else if (l3 == l1) { | 			else if (l3 == l1) { | ||||||
| 				//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
 | 				//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
 | ||||||
| 			} | 			} | ||||||
|  | @ -197,7 +215,7 @@ void AigerReader::parse_aiger_ascii() | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			// AIGER latches are assumed to be initialized to zero
 | 			// AIGER latches are assumed to be initialized to zero
 | ||||||
|             q_wire->attributes["\\init"] = RTLIL::Const(0); | 			q_wire->attributes["\\init"] = RTLIL::S0; | ||||||
| 		} | 		} | ||||||
| 		latches.push_back(q_wire); | 		latches.push_back(q_wire); | ||||||
| 	} | 	} | ||||||
|  | @ -212,11 +230,17 @@ void AigerReader::parse_aiger_ascii() | ||||||
| 		wire->port_output = true; | 		wire->port_output = true; | ||||||
| 		outputs.push_back(wire); | 		outputs.push_back(wire); | ||||||
| 	} | 	} | ||||||
|     std::getline(f, line); // Ignore up to start of next line
 |  | ||||||
| 
 | 
 | ||||||
|     // TODO: Parse bad state properties
 | 	// Parse bad properties
 | ||||||
|     for (unsigned i = 0; i < B; ++i, ++line_count) | 	for (unsigned i = 0; i < B; ++i, ++line_count) { | ||||||
|         std::getline(f, line); // Ignore up to start of next line
 | 		if (!(f >> l1)) | ||||||
|  | 			log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); | ||||||
|  | 
 | ||||||
|  | 		log_debug("%d is a bad state property\n", l1); | ||||||
|  | 		RTLIL::Wire *wire = createWireIfNotExists(module, l1); | ||||||
|  | 		wire->port_output = true; | ||||||
|  | 		bad_properties.push_back(wire); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	// TODO: Parse invariant constraints
 | 	// TODO: Parse invariant constraints
 | ||||||
| 	for (unsigned i = 0; i < C; ++i, ++line_count) | 	for (unsigned i = 0; i < C; ++i, ++line_count) | ||||||
|  | @ -290,8 +314,10 @@ void AigerReader::parse_aiger_binary() | ||||||
| 			if (!(f >> l3)) | 			if (!(f >> l3)) | ||||||
| 				log_error("Line %u cannot be interpreted as a latch!\n", line_count); | 				log_error("Line %u cannot be interpreted as a latch!\n", line_count); | ||||||
| 
 | 
 | ||||||
|             if (l3 == 0 || l3 == 1) | 			if (l3 == 0) | ||||||
|                 q_wire->attributes["\\init"] = RTLIL::Const(l3); | 				q_wire->attributes["\\init"] = RTLIL::S0; | ||||||
|  | 			else if (l3 == 1) | ||||||
|  | 				q_wire->attributes["\\init"] = RTLIL::S1; | ||||||
| 			else if (l3 == l1) { | 			else if (l3 == l1) { | ||||||
| 				//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
 | 				//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
 | ||||||
| 			} | 			} | ||||||
|  | @ -300,7 +326,7 @@ void AigerReader::parse_aiger_binary() | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			// AIGER latches are assumed to be initialized to zero
 | 			// AIGER latches are assumed to be initialized to zero
 | ||||||
|             q_wire->attributes["\\init"] = RTLIL::Const(0); | 			q_wire->attributes["\\init"] = RTLIL::S0; | ||||||
| 		} | 		} | ||||||
| 		latches.push_back(q_wire); | 		latches.push_back(q_wire); | ||||||
| 	} | 	} | ||||||
|  | @ -317,8 +343,17 @@ void AigerReader::parse_aiger_binary() | ||||||
| 	} | 	} | ||||||
| 	std::getline(f, line); // Ignore up to start of next line
 | 	std::getline(f, line); // Ignore up to start of next line
 | ||||||
| 
 | 
 | ||||||
|     // TODO: Parse bad state properties
 | 	// Parse bad properties
 | ||||||
|     for (unsigned i = 0; i < B; ++i, ++line_count) | 	for (unsigned i = 0; i < B; ++i, ++line_count) { | ||||||
|  | 		if (!(f >> l1)) | ||||||
|  | 			log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); | ||||||
|  | 
 | ||||||
|  | 		log_debug("%d is a bad state property\n", l1); | ||||||
|  | 		RTLIL::Wire *wire = createWireIfNotExists(module, l1); | ||||||
|  | 		wire->port_output = true; | ||||||
|  | 		bad_properties.push_back(wire); | ||||||
|  | 	} | ||||||
|  | 	if (B > 0) | ||||||
| 		std::getline(f, line); // Ignore up to start of next line
 | 		std::getline(f, line); // Ignore up to start of next line
 | ||||||
| 
 | 
 | ||||||
| 	// TODO: Parse invariant constraints
 | 	// TODO: Parse invariant constraints
 | ||||||
|  | @ -363,7 +398,7 @@ struct AigerFrontend : public Frontend { | ||||||
| 		log("Load module from an AIGER file into the current design.\n"); | 		log("Load module from an AIGER file into the current design.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -module_name <module_name>\n"); | 		log("    -module_name <module_name>\n"); | ||||||
|         log("        Name of module to be created (default: <filename>)" | 		log("        Name of module to be created (default: " | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| 				"top" // FIXME
 | 				"top" // FIXME
 | ||||||
| #else | #else | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ struct AigerReader | ||||||
|     std::vector<RTLIL::Wire*> inputs; |     std::vector<RTLIL::Wire*> inputs; | ||||||
|     std::vector<RTLIL::Wire*> latches; |     std::vector<RTLIL::Wire*> latches; | ||||||
|     std::vector<RTLIL::Wire*> outputs; |     std::vector<RTLIL::Wire*> outputs; | ||||||
|  |     std::vector<RTLIL::Wire*> bad_properties; | ||||||
| 
 | 
 | ||||||
|     AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); |     AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); | ||||||
|     void parse_aiger(); |     void parse_aiger(); | ||||||
|  |  | ||||||
|  | @ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type) | ||||||
| 	X(AST_GENIF) | 	X(AST_GENIF) | ||||||
| 	X(AST_GENCASE) | 	X(AST_GENCASE) | ||||||
| 	X(AST_GENBLOCK) | 	X(AST_GENBLOCK) | ||||||
|  | 	X(AST_TECALL) | ||||||
| 	X(AST_POSEDGE) | 	X(AST_POSEDGE) | ||||||
| 	X(AST_NEGEDGE) | 	X(AST_NEGEDGE) | ||||||
| 	X(AST_EDGE) | 	X(AST_EDGE) | ||||||
|  | @ -194,6 +195,8 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch | ||||||
| 	is_logic = false; | 	is_logic = false; | ||||||
| 	is_signed = false; | 	is_signed = false; | ||||||
| 	is_string = false; | 	is_string = false; | ||||||
|  | 	is_wand = false; | ||||||
|  | 	is_wor = false; | ||||||
| 	is_unsized = false; | 	is_unsized = false; | ||||||
| 	was_checked = false; | 	was_checked = false; | ||||||
| 	range_valid = false; | 	range_valid = false; | ||||||
|  |  | ||||||
|  | @ -137,6 +137,7 @@ namespace AST | ||||||
| 		AST_GENIF, | 		AST_GENIF, | ||||||
| 		AST_GENCASE, | 		AST_GENCASE, | ||||||
| 		AST_GENBLOCK, | 		AST_GENBLOCK, | ||||||
|  | 		AST_TECALL, | ||||||
| 		 | 		 | ||||||
| 		AST_POSEDGE, | 		AST_POSEDGE, | ||||||
| 		AST_NEGEDGE, | 		AST_NEGEDGE, | ||||||
|  | @ -173,7 +174,7 @@ namespace AST | ||||||
| 		// node content - most of it is unused in most node types
 | 		// node content - most of it is unused in most node types
 | ||||||
| 		std::string str; | 		std::string str; | ||||||
| 		std::vector<RTLIL::State> bits; | 		std::vector<RTLIL::State> bits; | ||||||
| 		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked, is_unsized; | 		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; | 		int port_id, range_left, range_right; | ||||||
| 		uint32_t integer; | 		uint32_t integer; | ||||||
| 		double realvalue; | 		double realvalue; | ||||||
|  |  | ||||||
|  | @ -920,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()); | 					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); | ||||||
| 				wire->attributes[attr.first] = attr.second->asAttrConst(); | 				wire->attributes[attr.first] = attr.second->asAttrConst(); | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
|  | 			if (is_wand) wire->set_bool_attribute("\\wand"); | ||||||
|  | 			if (is_wor)  wire->set_bool_attribute("\\wor"); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
|  | @ -1572,6 +1575,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | ||||||
| 			delete always; | 			delete always; | ||||||
| 		} break; | 		} break; | ||||||
| 
 | 
 | ||||||
|  | 	case AST_TECALL: { | ||||||
|  | 			int sz = children.size(); | ||||||
|  | 			if (str == "$info") { | ||||||
|  | 				if (sz > 0) | ||||||
|  | 					log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); | ||||||
|  | 				else | ||||||
|  | 					log_file_info(filename, linenum, "\n"); | ||||||
|  | 			} else if (str == "$warning") { | ||||||
|  | 				if (sz > 0) | ||||||
|  | 					log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); | ||||||
|  | 				else | ||||||
|  | 					log_file_warning(filename, linenum, "\n"); | ||||||
|  | 			} else if (str == "$error") { | ||||||
|  | 				if (sz > 0) | ||||||
|  | 					log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); | ||||||
|  | 				else | ||||||
|  | 					log_file_error(filename, linenum, "\n"); | ||||||
|  | 			} else if (str == "$fatal") { | ||||||
|  | 				// TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish()
 | ||||||
|  | 				// if no parameter is given, default value is 1
 | ||||||
|  | 				// dollar_finish(sz ? children[0] : 1);
 | ||||||
|  | 				// perhaps create & use log_file_fatal()
 | ||||||
|  | 				if (sz > 0) | ||||||
|  | 					log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); | ||||||
|  | 				else | ||||||
|  | 					log_file_error(filename, linenum, "FATAL.\n"); | ||||||
|  | 			} else { | ||||||
|  | 				log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); | ||||||
|  | 			} | ||||||
|  | 		} break; | ||||||
|  | 
 | ||||||
| 	case AST_FCALL: { | 	case AST_FCALL: { | ||||||
| 			if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") | 			if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") | ||||||
| 			{ | 			{ | ||||||
|  |  | ||||||
|  | @ -48,6 +48,14 @@ USING_YOSYS_NAMESPACE | ||||||
| #include "VhdlUnits.h" | #include "VhdlUnits.h" | ||||||
| #include "VeriLibrary.h" | #include "VeriLibrary.h" | ||||||
| 
 | 
 | ||||||
|  | #ifndef SYMBIOTIC_VERIFIC_API_VERSION | ||||||
|  | #  error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific." | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if SYMBIOTIC_VERIFIC_API_VERSION < 1 | ||||||
|  | #  error "Please update your version of Symbiotic EDA flavored Verific." | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef __clang__ | #ifdef __clang__ | ||||||
| #pragma clang diagnostic pop | #pragma clang diagnostic pop | ||||||
| #endif | #endif | ||||||
|  | @ -2016,6 +2024,9 @@ struct VerificPass : public Pass { | ||||||
| 			// WARNING: instantiating unknown module 'XYZ' (VERI-1063)
 | 			// WARNING: instantiating unknown module 'XYZ' (VERI-1063)
 | ||||||
| 			Message::SetMessageType("VERI-1063", VERIFIC_ERROR); | 			Message::SetMessageType("VERI-1063", VERIFIC_ERROR); | ||||||
| 
 | 
 | ||||||
|  | 			// https://github.com/YosysHQ/yosys/issues/1055
 | ||||||
|  | 			RuntimeFlags::SetVar("veri_elaborate_top_level_modules_having_interface_ports", 1) ; | ||||||
|  | 
 | ||||||
| #ifndef DB_PRESERVE_INITIAL_VALUE | #ifndef DB_PRESERVE_INITIAL_VALUE | ||||||
| #  warning Verific was built without DB_PRESERVE_INITIAL_VALUE. | #  warning Verific was built without DB_PRESERVE_INITIAL_VALUE. | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -218,6 +218,8 @@ YOSYS_NAMESPACE_END | ||||||
| "output"  { return TOK_OUTPUT; } | "output"  { return TOK_OUTPUT; } | ||||||
| "inout"   { return TOK_INOUT; } | "inout"   { return TOK_INOUT; } | ||||||
| "wire"    { return TOK_WIRE; } | "wire"    { return TOK_WIRE; } | ||||||
|  | "wor"     { return TOK_WOR; } | ||||||
|  | "wand"    { return TOK_WAND; } | ||||||
| "reg"     { return TOK_REG; } | "reg"     { return TOK_REG; } | ||||||
| "integer" { return TOK_INTEGER; } | "integer" { return TOK_INTEGER; } | ||||||
| "signed"  { return TOK_SIGNED; } | "signed"  { return TOK_SIGNED; } | ||||||
|  | @ -309,6 +311,11 @@ supply1 { return TOK_SUPPLY1; } | ||||||
| 	return TOK_ID; | 	return TOK_ID; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | "$"(info|warning|error|fatal) { | ||||||
|  | 	frontend_verilog_yylval.string = new std::string(yytext); | ||||||
|  | 	return TOK_ELAB_TASK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| "$signed"   { return TOK_TO_SIGNED; } | "$signed"   { return TOK_TO_SIGNED; } | ||||||
| "$unsigned" { return TOK_TO_UNSIGNED; } | "$unsigned" { return TOK_TO_UNSIGNED; } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -133,13 +133,13 @@ struct specify_rise_fall { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE | %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE | ||||||
| %token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER | %token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_ELAB_TASK | ||||||
| %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL | %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL | ||||||
| %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END | %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END | ||||||
| %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM | %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM | ||||||
| %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP | %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP | ||||||
| %token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR | %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_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_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 | %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC | ||||||
|  | @ -485,6 +485,12 @@ wire_type_token_io: | ||||||
| wire_type_token: | wire_type_token: | ||||||
| 	TOK_WIRE { | 	TOK_WIRE { | ||||||
| 	} | | 	} | | ||||||
|  | 	TOK_WOR { | ||||||
|  | 		astbuf3->is_wor = true; | ||||||
|  | 	} | | ||||||
|  | 	TOK_WAND { | ||||||
|  | 		astbuf3->is_wand = true; | ||||||
|  | 	} | | ||||||
| 	TOK_REG { | 	TOK_REG { | ||||||
| 		astbuf3->is_reg = true; | 		astbuf3->is_reg = true; | ||||||
| 	} | | 	} | | ||||||
|  | @ -1526,27 +1532,40 @@ cell_port_list_rules: | ||||||
| 	cell_port | cell_port_list_rules ',' cell_port; | 	cell_port | cell_port_list_rules ',' cell_port; | ||||||
| 
 | 
 | ||||||
| cell_port: | cell_port: | ||||||
| 	/* empty */ { | 	attr { | ||||||
| 		AstNode *node = new AstNode(AST_ARGUMENT); | 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||||
| 		astbuf2->children.push_back(node); | 		astbuf2->children.push_back(node); | ||||||
|  | 		free_attr($1); | ||||||
| 	} | | 	} | | ||||||
| 	expr { | 	attr expr { | ||||||
| 		AstNode *node = new AstNode(AST_ARGUMENT); | 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||||
| 		astbuf2->children.push_back(node); | 		astbuf2->children.push_back(node); | ||||||
| 		node->children.push_back($1); | 		node->children.push_back($2); | ||||||
|  | 		free_attr($1); | ||||||
| 	} | | 	} | | ||||||
| 	'.' TOK_ID '(' expr ')' { | 	attr '.' TOK_ID '(' expr ')' { | ||||||
| 		AstNode *node = new AstNode(AST_ARGUMENT); | 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||||
| 		node->str = *$2; | 		node->str = *$3; | ||||||
| 		astbuf2->children.push_back(node); | 		astbuf2->children.push_back(node); | ||||||
| 		node->children.push_back($4); | 		node->children.push_back($5); | ||||||
| 		delete $2; | 		delete $3; | ||||||
|  | 		free_attr($1); | ||||||
| 	} | | 	} | | ||||||
| 	'.' TOK_ID '(' ')' { | 	attr '.' TOK_ID '(' ')' { | ||||||
| 		AstNode *node = new AstNode(AST_ARGUMENT); | 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||||
| 		node->str = *$2; | 		node->str = *$3; | ||||||
| 		astbuf2->children.push_back(node); | 		astbuf2->children.push_back(node); | ||||||
| 		delete $2; | 		delete $3; | ||||||
|  | 		free_attr($1); | ||||||
|  | 	} | | ||||||
|  | 	attr '.' TOK_ID { | ||||||
|  | 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||||
|  | 		node->str = *$3; | ||||||
|  | 		astbuf2->children.push_back(node); | ||||||
|  | 		node->children.push_back(new AstNode(AST_IDENTIFIER)); | ||||||
|  | 		node->children.back()->str = *$3; | ||||||
|  | 		delete $3; | ||||||
|  | 		free_attr($1); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| always_stmt: | always_stmt: | ||||||
|  | @ -2157,6 +2176,15 @@ gen_stmt: | ||||||
| 		if ($6 != NULL) | 		if ($6 != NULL) | ||||||
| 			delete $6; | 			delete $6; | ||||||
| 		ast_stack.pop_back(); | 		ast_stack.pop_back(); | ||||||
|  | 	} | | ||||||
|  | 	TOK_ELAB_TASK { | ||||||
|  | 		AstNode *node = new AstNode(AST_TECALL); | ||||||
|  | 		node->str = *$1; | ||||||
|  | 		delete $1; | ||||||
|  | 		ast_stack.back()->children.push_back(node); | ||||||
|  | 		ast_stack.push_back(node); | ||||||
|  | 	} opt_arg_list ';'{ | ||||||
|  | 		ast_stack.pop_back();		 | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| gen_stmt_block: | gen_stmt_block: | ||||||
|  |  | ||||||
|  | @ -282,6 +282,17 @@ void log_file_warning(const std::string &filename, int lineno, | ||||||
| 	va_end(ap); | 	va_end(ap); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void log_file_info(const std::string &filename, int lineno, | ||||||
|  |                       const char *format, ...) | ||||||
|  | { | ||||||
|  | 	va_list ap; | ||||||
|  | 	va_start(ap, format); | ||||||
|  | 	std::string fmt = stringf("%s:%d: Info: %s", | ||||||
|  | 			filename.c_str(), lineno, format); | ||||||
|  | 	logv(fmt.c_str(), ap); | ||||||
|  | 	va_end(ap); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| YS_ATTRIBUTE(noreturn) | YS_ATTRIBUTE(noreturn) | ||||||
| static void logv_error_with_prefix(const char *prefix, | static void logv_error_with_prefix(const char *prefix, | ||||||
|                                    const char *format, va_list ap) |                                    const char *format, va_list ap) | ||||||
|  |  | ||||||
|  | @ -80,6 +80,7 @@ void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); | ||||||
| 
 | 
 | ||||||
| // Log with filename to report a problem in a source file.
 | // Log with filename to report a problem in a source file.
 | ||||||
| void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); | void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); | ||||||
|  | void log_file_info(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); | ||||||
| 
 | 
 | ||||||
| void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); | void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); | ||||||
| YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); | YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); | ||||||
|  |  | ||||||
|  | @ -601,6 +601,7 @@ struct RTLIL::SigChunk | ||||||
| 	RTLIL::SigChunk &operator =(const RTLIL::SigChunk &other) = default; | 	RTLIL::SigChunk &operator =(const RTLIL::SigChunk &other) = default; | ||||||
| 
 | 
 | ||||||
| 	RTLIL::SigChunk extract(int offset, int length) const; | 	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; | ||||||
| 	bool operator ==(const RTLIL::SigChunk &other) const; | 	bool operator ==(const RTLIL::SigChunk &other) const; | ||||||
|  |  | ||||||
|  | @ -2026,7 +2026,6 @@ def gen_wrappers(filename, debug_level_ = 0): | ||||||
| #include <boost/python/wrapper.hpp> | #include <boost/python/wrapper.hpp> | ||||||
| #include <boost/python/call.hpp> | #include <boost/python/call.hpp> | ||||||
| #include <boost/python.hpp> | #include <boost/python.hpp> | ||||||
| #include <boost/log/exceptions.hpp> |  | ||||||
| 
 | 
 | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| 
 | 
 | ||||||
|  | @ -2060,7 +2059,6 @@ namespace YOSYS_PYTHON { | ||||||
| 				Yosys::log_streams.push_back(&std::cout); | 				Yosys::log_streams.push_back(&std::cout); | ||||||
| 				Yosys::log_error_stderr = true; | 				Yosys::log_error_stderr = true; | ||||||
| 				Yosys::yosys_setup(); | 				Yosys::yosys_setup(); | ||||||
| 				Yosys::yosys_banner(); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -393,46 +393,114 @@ struct SetundefPass : public Pass { | ||||||
| 						ffbits.insert(bit); | 						ffbits.insert(bit); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | 				auto process_initwires = [&]() | ||||||
|  | 				{ | ||||||
|  | 					dict<Wire*, int> wire_weights; | ||||||
|  | 
 | ||||||
|  | 					for (auto wire : initwires) | ||||||
|  | 					{ | ||||||
|  | 						int weight = 0; | ||||||
|  | 
 | ||||||
|  | 						for (auto bit : sigmap(wire)) | ||||||
|  | 							weight += ffbits.count(bit) ? +1 : -1; | ||||||
|  | 
 | ||||||
|  | 						wire_weights[wire] = weight; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					initwires.sort([&](Wire *a, Wire *b) { return wire_weights.at(a) > wire_weights.at(b); }); | ||||||
|  | 
 | ||||||
|  | 					for (auto wire : initwires) | ||||||
|  | 					{ | ||||||
|  | 						Const &initval = wire->attributes["\\init"]; | ||||||
|  | 						initval.bits.resize(GetSize(wire), State::Sx); | ||||||
|  | 
 | ||||||
|  | 						for (int i = 0; i < GetSize(wire); i++) { | ||||||
|  | 							SigBit bit = sigmap(SigBit(wire, i)); | ||||||
|  | 							if (initval[i] == State::Sx && ffbits.count(bit)) { | ||||||
|  | 								initval[i] = worker.next_bit(); | ||||||
|  | 								ffbits.erase(bit); | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						if (initval.is_fully_undef()) | ||||||
|  | 							wire->attributes.erase("\\init"); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					initwires.clear(); | ||||||
|  | 				}; | ||||||
|  | 
 | ||||||
|  | 				for (int wire_types = 0; wire_types < 2; wire_types++) | ||||||
|  | 				{ | ||||||
|  | 					// prioritize wires that already have an init attribute
 | ||||||
|  | 					if (!ffbits.empty()) | ||||||
|  | 					{ | ||||||
| 						for (auto wire : module->wires()) | 						for (auto wire : module->wires()) | ||||||
| 						{ | 						{ | ||||||
|  | 							if (wire->name[0] == (wire_types ? '\\' : '$')) | ||||||
|  | 								continue; | ||||||
|  | 
 | ||||||
| 							if (!wire->attributes.count("\\init")) | 							if (!wire->attributes.count("\\init")) | ||||||
| 								continue; | 								continue; | ||||||
| 
 | 
 | ||||||
| 					for (auto bit : sigmap(wire)) | 							Const &initval = wire->attributes["\\init"]; | ||||||
| 						ffbits.erase(bit); | 							initval.bits.resize(GetSize(wire), State::Sx); | ||||||
|  | 
 | ||||||
|  | 							if (initval.is_fully_undef()) { | ||||||
|  | 								wire->attributes.erase("\\init"); | ||||||
|  | 								continue; | ||||||
|  | 							} | ||||||
|  | 
 | ||||||
|  | 							for (int i = 0; i < GetSize(wire); i++) | ||||||
|  | 								if (initval[i] != State::Sx) | ||||||
|  | 									ffbits.erase(sigmap(SigBit(wire, i))); | ||||||
| 
 | 
 | ||||||
| 							initwires.insert(wire); | 							initwires.insert(wire); | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 				for (int wire_types = 0; wire_types < 2; wire_types++) | 						process_initwires(); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// next consider wires that completely contain bits to be initialized
 | ||||||
|  | 					if (!ffbits.empty()) | ||||||
|  | 					{ | ||||||
| 						for (auto wire : module->wires()) | 						for (auto wire : module->wires()) | ||||||
| 						{ | 						{ | ||||||
| 							if (wire->name[0] == (wire_types ? '\\' : '$')) | 							if (wire->name[0] == (wire_types ? '\\' : '$')) | ||||||
| 					next_wire: |  | ||||||
| 								continue; | 								continue; | ||||||
| 
 | 
 | ||||||
| 							for (auto bit : sigmap(wire)) | 							for (auto bit : sigmap(wire)) | ||||||
| 								if (!ffbits.count(bit)) | 								if (!ffbits.count(bit)) | ||||||
| 									goto next_wire; | 									goto next_wire; | ||||||
| 
 | 
 | ||||||
| 						for (auto bit : sigmap(wire)) | 							initwires.insert(wire); | ||||||
| 							ffbits.erase(bit); |  | ||||||
| 
 | 
 | ||||||
|  | 						next_wire: | ||||||
|  | 							continue; | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						process_initwires(); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// finally use whatever wire we can find.
 | ||||||
|  | 					if (!ffbits.empty()) | ||||||
|  | 					{ | ||||||
|  | 						for (auto wire : module->wires()) | ||||||
|  | 						{ | ||||||
|  | 							if (wire->name[0] == (wire_types ? '\\' : '$')) | ||||||
|  | 								continue; | ||||||
|  | 
 | ||||||
|  | 							for (auto bit : sigmap(wire)) | ||||||
|  | 								if (ffbits.count(bit)) | ||||||
| 									initwires.insert(wire); | 									initwires.insert(wire); | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 				for (auto wire : initwires) | 						process_initwires(); | ||||||
| 				{ |  | ||||||
| 					Const &initval = wire->attributes["\\init"]; |  | ||||||
| 
 |  | ||||||
| 					for (int i = 0; i < GetSize(wire); i++) |  | ||||||
| 						if (GetSize(initval) <= i) |  | ||||||
| 							initval.bits.push_back(worker.next_bit()); |  | ||||||
| 						else if (initval.bits[i] == State::Sx) |  | ||||||
| 							initval.bits[i] = worker.next_bit(); |  | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | 				log_assert(ffbits.empty()); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			module->rewrite_sigspecs(worker); | 			module->rewrite_sigspecs(worker); | ||||||
| 
 | 
 | ||||||
| 			if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST) | 			if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST) | ||||||
|  |  | ||||||
|  | @ -52,7 +52,9 @@ struct TeePass : public Pass { | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		std::vector<FILE*> backup_log_files, files_to_close; | 		std::vector<FILE*> backup_log_files, files_to_close; | ||||||
|  | 		std::vector<std::ostream*> backup_log_streams; | ||||||
| 		int backup_log_verbose_level = log_verbose_level; | 		int backup_log_verbose_level = log_verbose_level; | ||||||
|  | 		backup_log_streams = log_streams; | ||||||
| 		backup_log_files = log_files; | 		backup_log_files = log_files; | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
|  | @ -60,6 +62,7 @@ struct TeePass : public Pass { | ||||||
| 		{ | 		{ | ||||||
| 			if (args[argidx] == "-q" && files_to_close.empty()) { | 			if (args[argidx] == "-q" && files_to_close.empty()) { | ||||||
| 				log_files.clear(); | 				log_files.clear(); | ||||||
|  | 				log_streams.clear(); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) { | 			if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) { | ||||||
|  | @ -89,6 +92,7 @@ struct TeePass : public Pass { | ||||||
| 			for (auto cf : files_to_close) | 			for (auto cf : files_to_close) | ||||||
| 				fclose(cf); | 				fclose(cf); | ||||||
| 			log_files = backup_log_files; | 			log_files = backup_log_files; | ||||||
|  | 			log_streams = backup_log_streams; | ||||||
| 			throw; | 			throw; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -97,6 +101,7 @@ struct TeePass : public Pass { | ||||||
| 
 | 
 | ||||||
| 		log_verbose_level = backup_log_verbose_level; | 		log_verbose_level = backup_log_verbose_level; | ||||||
| 		log_files = backup_log_files; | 		log_files = backup_log_files; | ||||||
|  | 		log_streams = backup_log_streams; | ||||||
| 	} | 	} | ||||||
| } TeePass; | } TeePass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -562,7 +562,8 @@ struct HierarchyPass : public Pass { | ||||||
| 		log("In parametric designs, a module might exists in several variations with\n"); | 		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("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("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("\n"); | ||||||
| 		log("    -check\n"); | 		log("    -check\n"); | ||||||
| 		log("        also check the design hierarchy. this generates an error when\n"); | 		log("        also check the design hierarchy. this generates an error when\n"); | ||||||
|  | @ -943,6 +944,121 @@ struct HierarchyPass : public Pass { | ||||||
| 		std::vector<Module*> design_modules = design->modules(); | 		std::vector<Module*> design_modules = design->modules(); | ||||||
| 
 | 
 | ||||||
| 		for (auto module : design_modules) | 		for (auto module : design_modules) | ||||||
|  | 		{ | ||||||
|  | 			pool<Wire*> wand_wor_index; | ||||||
|  | 			dict<Wire*, SigSpec> wand_map, wor_map; | ||||||
|  | 			vector<SigSig> new_connections; | ||||||
|  | 
 | ||||||
|  | 			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 : module->connections()) | ||||||
|  | 			{ | ||||||
|  | 				SigSig new_conn; | ||||||
|  | 				int cursor = 0; | ||||||
|  | 
 | ||||||
|  | 				for (auto c : conn.first.chunks()) | ||||||
|  | 				{ | ||||||
|  | 					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); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					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()) | ||||||
|  | 					{ | ||||||
|  | 						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 (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; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				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()) | 			for (auto cell : module->cells()) | ||||||
| 			{ | 			{ | ||||||
| 				Module *m = design->module(cell->type); | 				Module *m = design->module(cell->type); | ||||||
|  | @ -1001,6 +1117,7 @@ struct HierarchyPass : public Pass { | ||||||
| 								log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig)); | 								log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig)); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto module : blackbox_derivatives) | 		for (auto module : blackbox_derivatives) | ||||||
| 			design->remove(module); | 			design->remove(module); | ||||||
|  |  | ||||||
|  | @ -106,7 +106,7 @@ void rmunused_module_cells(Module *module, bool verbose) | ||||||
| 				if (raw_bit.wire == nullptr) | 				if (raw_bit.wire == nullptr) | ||||||
| 					continue; | 					continue; | ||||||
| 				auto bit = sigmap(raw_bit); | 				auto bit = sigmap(raw_bit); | ||||||
| 				if (bit.wire == nullptr) | 				if (bit.wire == nullptr && ct_all.cell_known(cell->type)) | ||||||
| 					driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict " | 					driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict " | ||||||
| 							"for %s between cell %s.%s and constant %s in %s: Resolved using constant.", | 							"for %s between cell %s.%s and constant %s in %s: Resolved using constant.", | ||||||
| 							log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); | 							log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); | ||||||
|  |  | ||||||
|  | @ -299,8 +299,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) | ||||||
| 		sig_q = dff->getPort("\\Q"); | 		sig_q = dff->getPort("\\Q"); | ||||||
| 		sig_c = dff->getPort("\\C"); | 		sig_c = dff->getPort("\\C"); | ||||||
| 		sig_e = dff->getPort("\\E"); | 		sig_e = dff->getPort("\\E"); | ||||||
| 		val_cp = RTLIL::Const(dff->type[6] == 'P', 1); | 		val_cp = RTLIL::Const(dff->type[7] == 'P', 1); | ||||||
| 		val_ep = RTLIL::Const(dff->type[7] == 'P', 1); | 		val_ep = RTLIL::Const(dff->type[8] == 'P', 1); | ||||||
| 	} | 	} | ||||||
| 	else if (dff->type == "$ff") { | 	else if (dff->type == "$ff") { | ||||||
| 		sig_d = dff->getPort("\\D"); | 		sig_d = dff->getPort("\\D"); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,7 @@ | ||||||
| pattern shiftmul | pattern shiftmul | ||||||
|  | // | ||||||
|  | // Optimize mul+shift pairs that result from expressions such as foo[s*W+:W] | ||||||
|  | // | ||||||
| 
 | 
 | ||||||
| state <SigSpec> shamt | state <SigSpec> shamt | ||||||
| 
 | 
 | ||||||
|  | @ -49,12 +52,16 @@ code | ||||||
| 	if (GetSize(port(shift, \Y)) > const_factor) | 	if (GetSize(port(shift, \Y)) > const_factor) | ||||||
| 		reject; | 		reject; | ||||||
| 
 | 
 | ||||||
|  | 	int factor_bits = ceil_log2(const_factor); | ||||||
|  | 	SigSpec mul_din = port(mul, const_factor_port == \A ? \B : \A); | ||||||
|  | 
 | ||||||
|  | 	if (GetSize(shamt) < factor_bits+GetSize(mul_din)) | ||||||
|  | 		reject; | ||||||
|  | 
 | ||||||
| 	did_something = true; | 	did_something = true; | ||||||
| 	log("shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul)); | 	log("shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul)); | ||||||
| 
 | 
 | ||||||
| 	int new_const_factor_log2 = ceil_log2(const_factor); | 	int new_const_factor = 1 << factor_bits; | ||||||
| 	int new_const_factor = 1 << new_const_factor_log2; |  | ||||||
| 
 |  | ||||||
| 	SigSpec padding(State::Sx, new_const_factor-const_factor); | 	SigSpec padding(State::Sx, new_const_factor-const_factor); | ||||||
| 	SigSpec old_a = port(shift, \A), new_a; | 	SigSpec old_a = port(shift, \A), new_a; | ||||||
| 	int trunc = 0; | 	int trunc = 0; | ||||||
|  | @ -73,7 +80,7 @@ code | ||||||
| 	if (trunc > 0) | 	if (trunc > 0) | ||||||
| 		new_a.remove(GetSize(new_a)-trunc, trunc); | 		new_a.remove(GetSize(new_a)-trunc, trunc); | ||||||
| 
 | 
 | ||||||
| 	SigSpec new_b = {port(mul, const_factor_port == \A ? \B : \A), SigSpec(State::S0, new_const_factor_log2)}; | 	SigSpec new_b = {mul_din, SigSpec(State::S0, factor_bits)}; | ||||||
| 	if (param(shift, \B_SIGNED).as_bool()) | 	if (param(shift, \B_SIGNED).as_bool()) | ||||||
| 		new_b.append(State::S0); | 		new_b.append(State::S0); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -332,7 +332,7 @@ struct FmcombinePass : public Pass { | ||||||
| 
 | 
 | ||||||
| 			gate_cell = module->cell(gate_name); | 			gate_cell = module->cell(gate_name); | ||||||
| 			if (gate_cell == nullptr) | 			if (gate_cell == nullptr) | ||||||
| 				log_cmd_error("Gold cell %s not found in module %s.\n", log_id(gate_name), log_id(module)); | 				log_cmd_error("Gate cell %s not found in module %s.\n", log_id(gate_name), log_id(module)); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
|  | @ -351,7 +351,7 @@ struct FmcombinePass : public Pass { | ||||||
| 		if (!gold_cell->parameters.empty()) | 		if (!gold_cell->parameters.empty()) | ||||||
| 			log_cmd_error("Gold cell has unresolved instance parameters.\n"); | 			log_cmd_error("Gold cell has unresolved instance parameters.\n"); | ||||||
| 		if (!gate_cell->parameters.empty()) | 		if (!gate_cell->parameters.empty()) | ||||||
| 			log_cmd_error("Gold cell has unresolved instance parameters.\n"); | 			log_cmd_error("Gate cell has unresolved instance parameters.\n"); | ||||||
| 
 | 
 | ||||||
| 		FmcombineWorker worker(design, gold_cell->type, opts); | 		FmcombineWorker worker(design, gold_cell->type, opts); | ||||||
| 		worker.generate(); | 		worker.generate(); | ||||||
|  |  | ||||||
|  | @ -88,6 +88,8 @@ struct SimInstance | ||||||
| 	SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : | 	SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : | ||||||
| 			shared(shared), module(module), instance(instance), parent(parent), sigmap(module) | 			shared(shared), module(module), instance(instance), parent(parent), sigmap(module) | ||||||
| 	{ | 	{ | ||||||
|  | 		log_assert(module); | ||||||
|  | 
 | ||||||
| 		if (parent) { | 		if (parent) { | ||||||
| 			log_assert(parent->children.count(instance) == 0); | 			log_assert(parent->children.count(instance) == 0); | ||||||
| 			parent->children[instance] = this; | 			parent->children[instance] = this; | ||||||
|  | @ -848,6 +850,9 @@ struct SimPass : public Pass { | ||||||
| 
 | 
 | ||||||
| 		if (design->full_selection()) { | 		if (design->full_selection()) { | ||||||
| 			top_mod = design->top_module(); | 			top_mod = design->top_module(); | ||||||
|  | 
 | ||||||
|  | 			if (!top_mod) | ||||||
|  | 				log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n"); | ||||||
| 		} else { | 		} else { | ||||||
| 			auto mods = design->selected_whole_modules(); | 			auto mods = design->selected_whole_modules(); | ||||||
| 			if (GetSize(mods) != 1) | 			if (GetSize(mods) != 1) | ||||||
|  |  | ||||||
|  | @ -58,12 +58,21 @@ struct MuxcoverWorker | ||||||
| 	bool use_mux16; | 	bool use_mux16; | ||||||
| 	bool nodecode; | 	bool nodecode; | ||||||
| 
 | 
 | ||||||
|  | 	int cost_mux2; | ||||||
|  | 	int cost_mux4; | ||||||
|  | 	int cost_mux8; | ||||||
|  | 	int cost_mux16; | ||||||
|  | 
 | ||||||
| 	MuxcoverWorker(Module *module) : module(module), sigmap(module) | 	MuxcoverWorker(Module *module) : module(module), sigmap(module) | ||||||
| 	{ | 	{ | ||||||
| 		use_mux4 = false; | 		use_mux4 = false; | ||||||
| 		use_mux8 = false; | 		use_mux8 = false; | ||||||
| 		use_mux16 = false; | 		use_mux16 = false; | ||||||
| 		nodecode = false; | 		nodecode = false; | ||||||
|  | 		cost_mux2 = COST_MUX2; | ||||||
|  | 		cost_mux4 = COST_MUX4; | ||||||
|  | 		cost_mux8 = COST_MUX8; | ||||||
|  | 		cost_mux16 = COST_MUX16; | ||||||
| 		decode_mux_counter = 0; | 		decode_mux_counter = 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -157,7 +166,7 @@ struct MuxcoverWorker | ||||||
| 		if (std::get<2>(entry)) | 		if (std::get<2>(entry)) | ||||||
| 			return 0; | 			return 0; | ||||||
| 
 | 
 | ||||||
| 		return COST_MUX2 / GetSize(std::get<1>(entry)); | 		return cost_mux2 / GetSize(std::get<1>(entry)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void implement_decode_mux(SigBit ctrl_bit) | 	void implement_decode_mux(SigBit ctrl_bit) | ||||||
|  | @ -209,7 +218,7 @@ struct MuxcoverWorker | ||||||
| 			mux.inputs.push_back(B); | 			mux.inputs.push_back(B); | ||||||
| 			mux.selects.push_back(S1); | 			mux.selects.push_back(S1); | ||||||
| 
 | 
 | ||||||
| 			mux.cost += COST_MUX2; | 			mux.cost += cost_mux2; | ||||||
| 			mux.cost += find_best_cover(tree, A); | 			mux.cost += find_best_cover(tree, A); | ||||||
| 			mux.cost += find_best_cover(tree, B); | 			mux.cost += find_best_cover(tree, B); | ||||||
| 
 | 
 | ||||||
|  | @ -247,7 +256,7 @@ struct MuxcoverWorker | ||||||
| 				mux.selects.push_back(S1); | 				mux.selects.push_back(S1); | ||||||
| 				mux.selects.push_back(T1); | 				mux.selects.push_back(T1); | ||||||
| 
 | 
 | ||||||
| 				mux.cost += COST_MUX4; | 				mux.cost += cost_mux4; | ||||||
| 				mux.cost += find_best_cover(tree, A); | 				mux.cost += find_best_cover(tree, A); | ||||||
| 				mux.cost += find_best_cover(tree, B); | 				mux.cost += find_best_cover(tree, B); | ||||||
| 				mux.cost += find_best_cover(tree, C); | 				mux.cost += find_best_cover(tree, C); | ||||||
|  | @ -310,7 +319,7 @@ struct MuxcoverWorker | ||||||
| 				mux.selects.push_back(T1); | 				mux.selects.push_back(T1); | ||||||
| 				mux.selects.push_back(U1); | 				mux.selects.push_back(U1); | ||||||
| 
 | 
 | ||||||
| 				mux.cost += COST_MUX8; | 				mux.cost += cost_mux8; | ||||||
| 				mux.cost += find_best_cover(tree, A); | 				mux.cost += find_best_cover(tree, A); | ||||||
| 				mux.cost += find_best_cover(tree, B); | 				mux.cost += find_best_cover(tree, B); | ||||||
| 				mux.cost += find_best_cover(tree, C); | 				mux.cost += find_best_cover(tree, C); | ||||||
|  | @ -414,7 +423,7 @@ struct MuxcoverWorker | ||||||
| 				mux.selects.push_back(U1); | 				mux.selects.push_back(U1); | ||||||
| 				mux.selects.push_back(V1); | 				mux.selects.push_back(V1); | ||||||
| 
 | 
 | ||||||
| 				mux.cost += COST_MUX16; | 				mux.cost += cost_mux16; | ||||||
| 				mux.cost += find_best_cover(tree, A); | 				mux.cost += find_best_cover(tree, A); | ||||||
| 				mux.cost += find_best_cover(tree, B); | 				mux.cost += find_best_cover(tree, B); | ||||||
| 				mux.cost += find_best_cover(tree, C); | 				mux.cost += find_best_cover(tree, C); | ||||||
|  | @ -569,9 +578,11 @@ struct MuxcoverPass : public Pass { | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); | 		log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -mux4, -mux8, -mux16\n"); | 		log("    -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); | ||||||
| 		log("        Use the specified types of MUXes. If none of those options are used,\n"); | 		log("        Use the specified types of MUXes (with optional integer costs). If none\n"); | ||||||
| 		log("        the effect is the same as if all of them where used.\n"); | 		log("        of these options are given, the effect is the same as if all of them are.\n"); | ||||||
|  | 		log("        Default costs: $_MUX_ = %d, $_MUX4_ = %d,\n", COST_MUX2, COST_MUX4); | ||||||
|  | 		log("                       $_MUX8_ = %d, $_MUX16_ = %d\n", COST_MUX8, COST_MUX16); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -nodecode\n"); | 		log("    -nodecode\n"); | ||||||
| 		log("        Do not insert decoder logic. This reduces the number of possible\n"); | 		log("        Do not insert decoder logic. This reduces the number of possible\n"); | ||||||
|  | @ -587,23 +598,39 @@ struct MuxcoverPass : public Pass { | ||||||
| 		bool use_mux8 = false; | 		bool use_mux8 = false; | ||||||
| 		bool use_mux16 = false; | 		bool use_mux16 = false; | ||||||
| 		bool nodecode = false; | 		bool nodecode = false; | ||||||
|  | 		int cost_mux4 = COST_MUX4; | ||||||
|  | 		int cost_mux8 = COST_MUX8; | ||||||
|  | 		int cost_mux16 = COST_MUX16; | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
| 		{ | 		{ | ||||||
| 			if (args[argidx] == "-mux4") { | 			const auto &arg = args[argidx]; | ||||||
|  | 			if (arg.size() >= 5 && arg.substr(0,5) == "-mux4") { | ||||||
| 				use_mux4 = true; | 				use_mux4 = true; | ||||||
|  | 				if (arg.size() > 5) { | ||||||
|  | 					if (arg[5] != '=') break; | ||||||
|  | 					cost_mux4 = atoi(arg.substr(5).c_str()); | ||||||
|  | 				} | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-mux8") { | 			if (arg.size() >= 5 && arg.substr(0,5) == "-mux8") { | ||||||
| 				use_mux8 = true; | 				use_mux8 = true; | ||||||
|  | 				if (arg.size() > 5) { | ||||||
|  | 					if (arg[5] != '=') break; | ||||||
|  | 					cost_mux8 = atoi(arg.substr(5).c_str()); | ||||||
|  | 				} | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-mux16") { | 			if (arg.size() >= 6 && arg.substr(0,6) == "-mux16") { | ||||||
| 				use_mux16 = true; | 				use_mux16 = true; | ||||||
|  | 				if (arg.size() > 6) { | ||||||
|  | 					if (arg[6] != '=') break; | ||||||
|  | 					cost_mux16 = atoi(arg.substr(6).c_str()); | ||||||
|  | 				} | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-nodecode") { | 			if (arg == "-nodecode") { | ||||||
| 				nodecode = true; | 				nodecode = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | @ -623,6 +650,9 @@ struct MuxcoverPass : public Pass { | ||||||
| 			worker.use_mux4 = use_mux4; | 			worker.use_mux4 = use_mux4; | ||||||
| 			worker.use_mux8 = use_mux8; | 			worker.use_mux8 = use_mux8; | ||||||
| 			worker.use_mux16 = use_mux16; | 			worker.use_mux16 = use_mux16; | ||||||
|  | 			worker.cost_mux4 = cost_mux4; | ||||||
|  | 			worker.cost_mux8 = cost_mux8; | ||||||
|  | 			worker.cost_mux16 = cost_mux16; | ||||||
| 			worker.nodecode = nodecode; | 			worker.nodecode = nodecode; | ||||||
| 			worker.run(); | 			worker.run(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -606,6 +606,9 @@ struct ShregmapPass : public Pass { | ||||||
| 		log("    -tech greenpak4\n"); | 		log("    -tech greenpak4\n"); | ||||||
| 		log("        map to greenpak4 shift registers.\n"); | 		log("        map to greenpak4 shift registers.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -tech xilinx\n"); | ||||||
|  | 		log("        map to xilinx dynamic-length shift registers.\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 | ||||||
| 	{ | 	{ | ||||||
|  |  | ||||||
|  | @ -47,6 +47,21 @@ module  \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED" | ||||||
| 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("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_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("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 | ||||||
| 
 | 
 | ||||||
|  | // Diamond I/O buffers | ||||||
|  | module IB   (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule | ||||||
|  | module IBPU (input I, output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("INPUT"))   _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule | ||||||
|  | module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule | ||||||
|  | module OB   (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule | ||||||
|  | module OBZ  (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule | ||||||
|  | module OBZPU(input I, T, output O); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("OUTPUT"))   _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule | ||||||
|  | module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule | ||||||
|  | module OBCO (input I, output OT, OC); OLVDS _TECHMAP_REPLACE_ (.A(I), .Z(OT), .ZN(OC)); endmodule | ||||||
|  | module BB   (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule | ||||||
|  | module BBPU (input I, T, output O, inout B); (* PULLMODE="UP"   *) TRELLIS_IO #(.DIR("BIDIR"))   _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule | ||||||
|  | module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule | ||||||
|  | module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT"))  _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule | ||||||
|  | module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule | ||||||
|  | 
 | ||||||
| // For Diamond compatibility, FIXME: add all Diamond flipflop mappings | // For Diamond compatibility, FIXME: add all Diamond flipflop mappings | ||||||
| module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule | module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -973,6 +973,30 @@ parameter RGB1_CURRENT = "0b000000"; | ||||||
| parameter RGB2_CURRENT = "0b000000"; | parameter RGB2_CURRENT = "0b000000"; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module SB_LED_DRV_CUR( | ||||||
|  | 	input EN, | ||||||
|  | 	output LEDPU | ||||||
|  | ); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module SB_RGB_DRV( | ||||||
|  | 	input RGBLEDEN, | ||||||
|  | 	input RGB0PWM, | ||||||
|  | 	input RGB1PWM, | ||||||
|  | 	input RGB2PWM, | ||||||
|  | 	input RGBPU, | ||||||
|  | 	output RGB0, | ||||||
|  | 	output RGB1, | ||||||
|  | 	output RGB2 | ||||||
|  | ); | ||||||
|  | parameter CURRENT_MODE = "0b0"; | ||||||
|  | parameter RGB0_CURRENT = "0b000000"; | ||||||
|  | parameter RGB1_CURRENT = "0b000000"; | ||||||
|  | parameter RGB2_CURRENT = "0b000000"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| (* blackbox *) | (* blackbox *) | ||||||
| module SB_I2C( | module SB_I2C( | ||||||
| 	input  SBCLKI, | 	input  SBCLKI, | ||||||
|  |  | ||||||
|  | @ -229,11 +229,6 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 			run("dff2dffe"); | 			run("dff2dffe"); | ||||||
| 			run("opt -full"); | 			run("opt -full"); | ||||||
| 
 | 
 | ||||||
| 			if (!vpr || help_mode) |  | ||||||
| 				run("techmap -map +/xilinx/arith_map.v"); |  | ||||||
| 			else |  | ||||||
| 				run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); |  | ||||||
| 
 |  | ||||||
| 			if (!nosrl || help_mode) { | 			if (!nosrl || help_mode) { | ||||||
| 				// shregmap operates on bit-level flops, not word-level,
 | 				// shregmap operates on bit-level flops, not word-level,
 | ||||||
| 				//   so break those down here
 | 				//   so break those down here
 | ||||||
|  | @ -242,7 +237,11 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); | 				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			run("techmap"); | 			if (!vpr || help_mode) | ||||||
|  | 				run("techmap -map +/techmap.v -map +/xilinx/arith_map.v"); | ||||||
|  | 			else | ||||||
|  | 				run("techmap -map +/techmap.v +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); | ||||||
|  | 
 | ||||||
| 			run("opt -fast"); | 			run("opt -fast"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +0,0 @@ | ||||||
| aig 3 2 0 1 1 |  | ||||||
| 6 |  | ||||||
|  |  | ||||||
|  | @ -3,3 +3,6 @@ aag 3 2 0 1 1 | ||||||
| 4 | 4 | ||||||
| 6 | 6 | ||||||
| 6 2 4 | 6 2 4 | ||||||
|  | i0 pi0 | ||||||
|  | i1 pi1 | ||||||
|  | o0 po0 | ||||||
							
								
								
									
										5
									
								
								tests/aiger/and_.aig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/aiger/and_.aig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | aig 3 2 0 1 1 | ||||||
|  | 6 | ||||||
|  | i0 pi0 | ||||||
|  | i1 pi1 | ||||||
|  | o0 po0 | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
| aag 1 1 0 1 0 | aag 1 1 0 1 0 | ||||||
| 2 | 2 | ||||||
| 2 | 2 | ||||||
|  | i0 pi0 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
|  | @ -1,2 +1,4 @@ | ||||||
| aig 1 1 0 1 0 | aig 1 1 0 1 0 | ||||||
| 2 | 2 | ||||||
|  | i0 pi0 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
| aag 1 0 1 0 0 1 | aag 1 0 1 0 0 1 | ||||||
| 2 3 | 2 3 | ||||||
| 2 | 2 | ||||||
|  | b0 po0 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
| aig 1 0 1 0 0 1 | aig 1 0 1 0 0 1 | ||||||
| 3 | 3 | ||||||
| 2 | 2 | ||||||
|  | b0 po0 | ||||||
|  |  | ||||||
|  | @ -6,3 +6,4 @@ aag 5 1 1 0 3 1 | ||||||
| 8 4 2 | 8 4 2 | ||||||
| 10 9 7 | 10 9 7 | ||||||
| b0 AIGER_NEVER | b0 AIGER_NEVER | ||||||
|  | i0 po0 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| aig 5 1 1 0 3 1 | aig 5 1 1 0 3 1 | ||||||
| 10 | 10 | ||||||
| 4 | 4 | ||||||
| b0 AIGER_NEVER | i0 po0 | ||||||
|  | b0 AIGER_NEVER | ||||||
|  |  | ||||||
|  | @ -1,2 +1,3 @@ | ||||||
| aag 0 0 0 1 0 | aag 0 0 0 1 0 | ||||||
| 0 | 0 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
|  | @ -1,2 +1,3 @@ | ||||||
| aig 0 0 0 1 0 | aig 0 0 0 1 0 | ||||||
| 0 | 0 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
| aag 1 1 0 1 0 | aag 1 1 0 1 0 | ||||||
| 2 | 2 | ||||||
| 3 | 3 | ||||||
|  | i0 pi0 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
|  | @ -1,2 +1,4 @@ | ||||||
| aig 1 1 0 1 0 | aig 1 1 0 1 0 | ||||||
| 3 | 3 | ||||||
|  | i0 pi0 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
|  | @ -6,3 +6,4 @@ aag 5 1 1 0 3 1 | ||||||
| 8 4 2 | 8 4 2 | ||||||
| 10 9 7 | 10 9 7 | ||||||
| b0 AIGER_NEVER | b0 AIGER_NEVER | ||||||
|  | i0 pi0 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| aig 5 1 1 0 3 1 | aig 5 1 1 0 3 1 | ||||||
| 10 | 10 | ||||||
| 5 | 5 | ||||||
| b0 AIGER_NEVER | i0 pi0 | ||||||
|  | b0 AIGER_NEVER | ||||||
|  |  | ||||||
|  | @ -1,3 +0,0 @@ | ||||||
| aig 3 2 0 1 1 |  | ||||||
| 7 |  | ||||||
|  |  | ||||||
|  | @ -3,3 +3,6 @@ aag 3 2 0 1 1 | ||||||
| 4 | 4 | ||||||
| 7 | 7 | ||||||
| 6 3 5 | 6 3 5 | ||||||
|  | i0 pi0 | ||||||
|  | i1 pi1 | ||||||
|  | o0 po0 | ||||||
							
								
								
									
										5
									
								
								tests/aiger/or_.aig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/aiger/or_.aig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | aig 3 2 0 1 1 | ||||||
|  | 7 | ||||||
|  | i0 pi0 | ||||||
|  | i1 pi1 | ||||||
|  | o0 po0 | ||||||
|  | @ -1,24 +1,42 @@ | ||||||
| #!/bin/bash | #!/bin/bash | ||||||
| 
 | 
 | ||||||
| OPTIND=1 | set -e | ||||||
| seed=""    # default to no seed specified | 
 | ||||||
| while getopts "S:" opt | # NB: *.aag and *.aig must contain a symbol table naming the primary | ||||||
| do | #     inputs and outputs, otherwise ABC and Yosys will name them | ||||||
|     case "$opt" in | #     arbitrarily (and inconsistently with each other). | ||||||
| 	S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space | 
 | ||||||
| 	   seed="SEED=$arg" ;; | for aag in *.aag; do | ||||||
|     esac |     # Since ABC cannot read *.aag, read the *.aig instead | ||||||
|  |     # (which would have been created by the reference aig2aig utility, | ||||||
|  |     #  available from http://fmv.jku.at/aiger/) | ||||||
|  |     ../../yosys-abc -c "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" | ||||||
|  |     ../../yosys -p " | ||||||
|  | read_verilog ${aag%.*}_ref.v | ||||||
|  | prep | ||||||
|  | design -stash gold | ||||||
|  | read_aiger -clk_name clock $aag | ||||||
|  | prep | ||||||
|  | design -stash gate | ||||||
|  | design -import gold -as gold | ||||||
|  | design -import gate -as gate | ||||||
|  | miter -equiv -flatten -make_assert -make_outputs gold gate miter | ||||||
|  | sat -verify -prove-asserts -show-ports -seq 16 miter | ||||||
|  | " | ||||||
| done | done | ||||||
| shift "$((OPTIND-1))" |  | ||||||
| 
 | 
 | ||||||
| # check for Icarus Verilog | for aig in *.aig; do | ||||||
| if ! which iverilog > /dev/null ; then |     ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" | ||||||
|   echo "$0: Error: Icarus Verilog 'iverilog' not found." |     ../../yosys -p " | ||||||
|   exit 1 | read_verilog ${aig%.*}_ref.v | ||||||
| fi | prep | ||||||
| 
 | design -stash gold | ||||||
| echo "===== AAG ======" | read_aiger -clk_name clock $aig | ||||||
| ${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" | prep | ||||||
| 
 | design -stash gate | ||||||
| echo "===== AIG ======" | design -import gold -as gold | ||||||
| exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aig EXTRA_FLAGS="-f aiger" | design -import gate -as gate | ||||||
|  | miter -equiv -flatten -make_assert -make_outputs gold gate miter | ||||||
|  | sat -verify -prove-asserts -show-ports -seq 16 miter | ||||||
|  | " | ||||||
|  | done | ||||||
|  |  | ||||||
|  | @ -2,3 +2,5 @@ aag 1 0 1 2 0 | ||||||
| 2 3 | 2 3 | ||||||
| 2 | 2 | ||||||
| 3 | 3 | ||||||
|  | o0 po0 | ||||||
|  | o1 po1 | ||||||
|  |  | ||||||
|  | @ -2,3 +2,5 @@ aig 1 0 1 2 0 | ||||||
| 3 | 3 | ||||||
| 2 | 2 | ||||||
| 3 | 3 | ||||||
|  | o0 po0 | ||||||
|  | o1 po1 | ||||||
|  |  | ||||||
|  | @ -1,2 +1,3 @@ | ||||||
| aag 0 0 0 1 0 | aag 0 0 0 1 0 | ||||||
| 1 | 1 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
|  | @ -1,2 +1,3 @@ | ||||||
| aig 0 0 0 1 0 | aig 0 0 0 1 0 | ||||||
| 1 | 1 | ||||||
|  | o0 po0 | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								tests/simple/attrib01_module.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/simple/attrib01_module.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output reg  out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 1'd0; | ||||||
|  |     else     out <= ~inp; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output wire out; | ||||||
|  | 
 | ||||||
|  |   bar bar_instance (clk, rst, inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										25
									
								
								tests/simple/attrib02_port_decl.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tests/simple/attrib02_port_decl.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  |   (* this_is_clock = 1 *) | ||||||
|  |   input  wire clk; | ||||||
|  |   (* this_is_reset = 1 *) | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   (* an_output_register = 1*) | ||||||
|  |   output reg  out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 1'd0; | ||||||
|  |     else     out <= ~inp; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   (* this_is_the_master_clock *) | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output wire out; | ||||||
|  | 
 | ||||||
|  |   bar bar_instance (clk, rst, inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										28
									
								
								tests/simple/attrib03_parameter.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tests/simple/attrib03_parameter.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  | 
 | ||||||
|  |   (* bus_width *) | ||||||
|  |   parameter WIDTH = 2; | ||||||
|  | 
 | ||||||
|  |   (* an_attribute_on_localparam = 55 *) | ||||||
|  |   localparam INCREMENT = 5; | ||||||
|  | 
 | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [WIDTH-1:0] inp; | ||||||
|  |   output reg  [WIDTH-1:0] out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 0; | ||||||
|  |     else     out <= inp + INCREMENT; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [7:0] inp; | ||||||
|  |   output wire [7:0] out; | ||||||
|  | 
 | ||||||
|  |   bar # (.WIDTH(8)) bar_instance (clk, rst, inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										32
									
								
								tests/simple/attrib04_net_var.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								tests/simple/attrib04_net_var.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output reg  out; | ||||||
|  | 
 | ||||||
|  |   (* this_is_a_prescaler *) | ||||||
|  |   reg [7:0] counter; | ||||||
|  | 
 | ||||||
|  |   (* temp_wire *) | ||||||
|  |   wire out_val; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     counter <= counter + 1; | ||||||
|  | 
 | ||||||
|  |   assign out_val = inp ^ counter[4]; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 1'd0; | ||||||
|  |     else     out <= out_val; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output wire out; | ||||||
|  | 
 | ||||||
|  |   bar bar_instance (clk, rst, inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										21
									
								
								tests/simple/attrib05_port_conn.v.DISABLED
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/simple/attrib05_port_conn.v.DISABLED
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output reg  out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 1'd0; | ||||||
|  |     else     out <= ~inp; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output wire out; | ||||||
|  | 
 | ||||||
|  |   bar bar_instance ( (* clock_connected *) clk, rst, (* this_is_the_input *) inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										23
									
								
								tests/simple/attrib06_operator_suffix.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/simple/attrib06_operator_suffix.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | module bar(clk, rst, inp_a, inp_b, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [7:0] inp_a; | ||||||
|  |   input  wire [7:0] inp_b; | ||||||
|  |   output reg  [7:0] out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 0; | ||||||
|  |     else     out <= inp_a + (* ripple_adder *) inp_b; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp_a, inp_b, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [7:0] inp_a; | ||||||
|  |   input  wire [7:0] inp_b; | ||||||
|  |   output wire [7:0] out; | ||||||
|  | 
 | ||||||
|  |   bar bar_instance (clk, rst, inp_a, inp_b, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										21
									
								
								tests/simple/attrib07_func_call.v.DISABLED
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/simple/attrib07_func_call.v.DISABLED
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | function [7:0] do_add; | ||||||
|  |   input [7:0] inp_a; | ||||||
|  |   input [7:0] inp_b; | ||||||
|  | 
 | ||||||
|  |   do_add = inp_a + inp_b; | ||||||
|  | 
 | ||||||
|  | endfunction | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp_a, inp_b, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [7:0] inp_a; | ||||||
|  |   input  wire [7:0] inp_b; | ||||||
|  |   output wire [7:0] out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 0; | ||||||
|  |     else     out <= do_add (* combinational_adder *) (inp_a, inp_b); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										22
									
								
								tests/simple/attrib08_mod_inst.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/simple/attrib08_mod_inst.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output reg  out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 1'd0; | ||||||
|  |     else     out <= ~inp; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output wire out; | ||||||
|  | 
 | ||||||
|  |   (* my_module_instance = 99 *) | ||||||
|  |   bar bar_instance (clk, rst, inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										26
									
								
								tests/simple/attrib09_case.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tests/simple/attrib09_case.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [1:0] inp; | ||||||
|  |   output reg  [1:0] out; | ||||||
|  | 
 | ||||||
|  |   always @(inp) | ||||||
|  |     (* full_case, parallel_case *) | ||||||
|  |     case(inp) | ||||||
|  |       2'd0: out <= 2'd3; | ||||||
|  |       2'd1: out <= 2'd2; | ||||||
|  |       2'd2: out <= 2'd1; | ||||||
|  |       2'd3: out <= 2'd0; | ||||||
|  |     endcase | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [1:0] inp; | ||||||
|  |   output wire [1:0] out; | ||||||
|  | 
 | ||||||
|  |   bar bar_instance (clk, rst, inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										16
									
								
								tests/simple/implicit_ports.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								tests/simple/implicit_ports.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | // Test implicit port connections | ||||||
|  | module alu (input [2:0] a, input [2:0] b, input cin, output cout, output [2:0] result); | ||||||
|  | 	assign cout = cin; | ||||||
|  | 	assign result = a + b; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module named_ports(input [2:0] a, b, output [2:0] alu_result, output cout); | ||||||
|  | 	wire cin = 1; | ||||||
|  | 	alu alu ( | ||||||
|  | 		.a(a), | ||||||
|  | 		.b, // Implicit connection is equivalent to .b(b) | ||||||
|  | 		.cin(), // Explicitely unconnected | ||||||
|  | 		.cout(cout), | ||||||
|  | 		.result(alu_result) | ||||||
|  | 	); | ||||||
|  | endmodule | ||||||
|  | @ -2,6 +2,10 @@ module peepopt_shiftmul_0 #(parameter N=3, parameter W=3) (input [N*W-1:0] i, in | ||||||
| assign o = i[s*W+:W]; | assign o = i[s*W+:W]; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | module peepopt_shiftmul_1 (output y, input [2:0] w); | ||||||
|  | assign y = 1'b1 >> (w * (3'b110)); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| module peepopt_muldiv_0(input [1:0] i, output [1:0] o); | module peepopt_muldiv_0(input [1:0] i, output [1:0] o); | ||||||
| wire [3:0] t; | wire [3:0] t; | ||||||
| assign t = i * 3; | assign t = i * 3; | ||||||
|  |  | ||||||
|  | @ -17,4 +17,5 @@ if ! which iverilog > /dev/null ; then | ||||||
|   exit 1 |   exit 1 | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v | shopt -s nullglob | ||||||
|  | exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.{sv,v} | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								tests/simple/wandwor.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								tests/simple/wandwor.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||||
|  | @ -89,6 +89,13 @@ done | ||||||
| 
 | 
 | ||||||
| compile_and_run() { | compile_and_run() { | ||||||
| 	exe="$1"; output="$2"; shift 2 | 	exe="$1"; output="$2"; shift 2 | ||||||
|  | 	ext=${1##*.} | ||||||
|  | 	if [ "$ext" == "sv" ]; then | ||||||
|  | 		language_gen="-g2012" | ||||||
|  | 	else | ||||||
|  | 		language_gen="-g2005" | ||||||
|  | 	fi | ||||||
|  | 
 | ||||||
| 	if $use_modelsim; then | 	if $use_modelsim; then | ||||||
| 		altver=$( ls -v /opt/altera/ | grep '^[0-9]' | tail -n1; ) | 		altver=$( ls -v /opt/altera/ | grep '^[0-9]' | tail -n1; ) | ||||||
| 		/opt/altera/$altver/modelsim_ase/bin/vlib work | 		/opt/altera/$altver/modelsim_ase/bin/vlib work | ||||||
|  | @ -99,7 +106,7 @@ compile_and_run() { | ||||||
| 		/opt/Xilinx/Vivado/$xilver/bin/xvlog $xinclude_opts -d outfile=\"$output\" "$@" | 		/opt/Xilinx/Vivado/$xilver/bin/xvlog $xinclude_opts -d outfile=\"$output\" "$@" | ||||||
| 		/opt/Xilinx/Vivado/$xilver/bin/xelab -R work.testbench | 		/opt/Xilinx/Vivado/$xilver/bin/xelab -R work.testbench | ||||||
| 	else | 	else | ||||||
| 		iverilog $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" | 		iverilog $language_gen $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" | ||||||
| 		vvp -n "$exe" | 		vvp -n "$exe" | ||||||
| 	fi | 	fi | ||||||
| } | } | ||||||
|  | @ -110,7 +117,7 @@ for fn | ||||||
| do | do | ||||||
| 	bn=${fn%.*} | 	bn=${fn%.*} | ||||||
| 	ext=${fn##*.} | 	ext=${fn##*.} | ||||||
| 	if [[ "$ext" != "v" ]] && [[ "$ext" != "aag" ]] && [[ "$ext" != "aig" ]]; then | 	if [[ "$ext" != "v" ]] && [[ "$ext" != "sv" ]] && [[ "$ext" != "aag" ]] && [[ "$ext" != "aig" ]]; then | ||||||
| 		echo "Invalid argument: $fn" >&2 | 		echo "Invalid argument: $fn" >&2 | ||||||
| 		exit 1 | 		exit 1 | ||||||
| 	fi | 	fi | ||||||
|  | @ -123,6 +130,10 @@ do | ||||||
| 		echo -n "Test: $bn " | 		echo -n "Test: $bn " | ||||||
| 	fi | 	fi | ||||||
| 
 | 
 | ||||||
|  | 	if [ "$ext" == sv ]; then | ||||||
|  | 		frontend="$frontend -sv" | ||||||
|  | 	fi | ||||||
|  | 
 | ||||||
| 	rm -f ${bn}.{err,log,skip} | 	rm -f ${bn}.{err,log,skip} | ||||||
| 	mkdir -p ${bn}.out | 	mkdir -p ${bn}.out | ||||||
| 	rm -rf ${bn}.out/* | 	rm -rf ${bn}.out/* | ||||||
|  | @ -135,9 +146,10 @@ do | ||||||
| 		rm -f ${bn}_ref.fir | 		rm -f ${bn}_ref.fir | ||||||
| 		if [[ "$ext" == "v" ]]; then | 		if [[ "$ext" == "v" ]]; then | ||||||
| 			egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} | 			egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} | ||||||
|  | 		elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then | ||||||
|  | 			"$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.v" | ||||||
| 		else | 		else | ||||||
| 			"$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn} | 			cp ../${fn} ${bn}_ref.${ext} | ||||||
| 			frontend="verilog -noblackbox" |  | ||||||
| 		fi | 		fi | ||||||
| 
 | 
 | ||||||
| 		if [ ! -f ../${bn}_tb.v ]; then | 		if [ ! -f ../${bn}_tb.v ]; then | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								tests/various/attrib05_port_conn.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/various/attrib05_port_conn.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | module bar(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output reg  out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 1'd0; | ||||||
|  |     else     out <= ~inp; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire inp; | ||||||
|  |   output wire out; | ||||||
|  | 
 | ||||||
|  |   bar bar_instance ( (* clock_connected *) clk, rst, (* this_is_the_input *) inp, out); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										2
									
								
								tests/various/attrib05_port_conn.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/various/attrib05_port_conn.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | # Read and parse Verilog file | ||||||
|  | read_verilog attrib05_port_conn.v | ||||||
							
								
								
									
										21
									
								
								tests/various/attrib07_func_call.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/various/attrib07_func_call.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | function [7:0] do_add; | ||||||
|  |   input [7:0] inp_a; | ||||||
|  |   input [7:0] inp_b; | ||||||
|  | 
 | ||||||
|  |   do_add = inp_a + inp_b; | ||||||
|  | 
 | ||||||
|  | endfunction | ||||||
|  | 
 | ||||||
|  | module foo(clk, rst, inp_a, inp_b, out); | ||||||
|  |   input  wire clk; | ||||||
|  |   input  wire rst; | ||||||
|  |   input  wire [7:0] inp_a; | ||||||
|  |   input  wire [7:0] inp_b; | ||||||
|  |   output wire [7:0] out; | ||||||
|  | 
 | ||||||
|  |   always @(posedge clk) | ||||||
|  |     if (rst) out <= 0; | ||||||
|  |     else     out <= do_add (* combinational_adder *) (inp_a, inp_b); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
							
								
								
									
										2
									
								
								tests/various/attrib07_func_call.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/various/attrib07_func_call.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | # Read and parse Verilog file | ||||||
|  | read_verilog attrib07_func_call.v | ||||||
							
								
								
									
										30
									
								
								tests/various/elab_sys_tasks.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/various/elab_sys_tasks.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | module test; | ||||||
|  | localparam X=1; | ||||||
|  | genvar i; | ||||||
|  | generate | ||||||
|  | if (X == 1) | ||||||
|  |   $info("X is 1"); | ||||||
|  | if (X == 1) | ||||||
|  |   $warning("X is 1"); | ||||||
|  | else | ||||||
|  |   $error("X is not 1"); | ||||||
|  | case (X) | ||||||
|  |   1: $info("X is 1 in a case statement"); | ||||||
|  | endcase | ||||||
|  | //case (X-1)
 | ||||||
|  | //  1: $warn("X is 2");
 | ||||||
|  | //  default: $warn("X might be anything in a case statement");
 | ||||||
|  | //endcase
 | ||||||
|  | for (i = 0; i < 3; i = i + 1) | ||||||
|  | begin | ||||||
|  |   case(i) | ||||||
|  |     0: $info; | ||||||
|  |     1: $warning; | ||||||
|  |     default: $info("default case statemnent"); | ||||||
|  |   endcase | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | $info("This is a standalone $info(). Next $info has no parameters"); | ||||||
|  | $info; | ||||||
|  | endgenerate | ||||||
|  | endmodule | ||||||
							
								
								
									
										1
									
								
								tests/various/elab_sys_tasks.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/various/elab_sys_tasks.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | read_verilog -sv elab_sys_tasks.sv | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue