mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +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 "rename -src" | ||||
|     - Added "equiv_opt" pass | ||||
|     - Added "read_aiger" frontend | ||||
|     - "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
 | ||||
| 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
 | ||||
| ENABLE_GCOV := 0 | ||||
|  | @ -54,6 +46,10 @@ OS := $(shell uname -s) | |||
| PREFIX ?= /usr/local | ||||
| INSTALL_SUDO := | ||||
| 
 | ||||
| ifneq ($(wildcard Makefile.conf),) | ||||
| include Makefile.conf | ||||
| endif | ||||
| 
 | ||||
| BINDIR := $(PREFIX)/bin | ||||
| LIBDIR := $(PREFIX)/lib | ||||
| DATDIR := $(PREFIX)/share/yosys | ||||
|  | @ -145,6 +141,21 @@ $(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$ | |||
| include Makefile.conf | ||||
| endif | ||||
| 
 | ||||
| ifeq ($(ENABLE_PYOSYS),1) | ||||
| PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)" | ||||
| PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi) | ||||
| PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"") | ||||
| PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.) | ||||
| PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix) | ||||
| PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages | ||||
| 
 | ||||
| # Reload Makefile.conf to override python specific variables if defined
 | ||||
| ifneq ($(wildcard Makefile.conf),) | ||||
| include Makefile.conf | ||||
| endif | ||||
| 
 | ||||
| endif | ||||
| 
 | ||||
| ifeq ($(CONFIG),clang) | ||||
| CXX = clang | ||||
| LD = clang++ | ||||
|  |  | |||
|  | @ -257,7 +257,7 @@ for them: | |||
| - Non-synthesizable language features as defined in | ||||
| 	IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002 | ||||
| 
 | ||||
| - The ``tri``, ``triand``, ``trior``, ``wand`` and ``wor`` net types | ||||
| - The ``tri``, ``triand`` and ``trior`` net types | ||||
| 
 | ||||
| - The ``config`` and ``disable`` keywords and library map files | ||||
| 
 | ||||
|  | @ -413,7 +413,7 @@ Verilog Attributes and non-standard features | |||
|       $ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v' | ||||
| 
 | ||||
| - 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`` | ||||
| 
 | ||||
| - The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in | ||||
|  |  | |||
|  | @ -81,11 +81,26 @@ end_of_header: | |||
| 	else | ||||
| 		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.)
 | ||||
| 	unsigned l1; | ||||
| 	std::string s; | ||||
| 	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); | ||||
| 			if (!(f >> l1 >> s)) | ||||
| 				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]; | ||||
| 			else if (c == 'l') wire = latches[l1]; | ||||
| 			else if (c == 'o') wire = outputs[l1]; | ||||
| 			else if (c == 'b') wire = bad_properties[l1]; | ||||
| 			else log_abort(); | ||||
| 
 | ||||
| 			module->rename(wire, stringf("\\%s", s.c_str())); | ||||
| 		} | ||||
|         else if (c == 'b' || c == 'j' || c == 'f') { | ||||
| 		else if (c == 'j' || c == 'f') { | ||||
| 			// TODO
 | ||||
| 		} | ||||
| 		else if (c == 'c') { | ||||
|  | @ -153,7 +169,7 @@ void AigerReader::parse_aiger_ascii() | |||
| 	unsigned l1, l2, l3; | ||||
| 
 | ||||
| 	// Parse inputs
 | ||||
|     for (unsigned i = 0; i < I; ++i, ++line_count) { | ||||
| 	for (unsigned i = 1; i <= I; ++i, ++line_count) { | ||||
| 		if (!(f >> l1)) | ||||
| 			log_error("Line %u cannot be interpreted as an input!\n", line_count); | ||||
| 		log_debug("%d is an input\n", l1); | ||||
|  | @ -187,8 +203,10 @@ void AigerReader::parse_aiger_ascii() | |||
| 			if (!(f >> l3)) | ||||
| 				log_error("Line %u cannot be interpreted as a latch!\n", line_count); | ||||
| 
 | ||||
|             if (l3 == 0 || l3 == 1) | ||||
|                 q_wire->attributes["\\init"] = RTLIL::Const(l3); | ||||
| 			if (l3 == 0) | ||||
| 				q_wire->attributes["\\init"] = RTLIL::S0; | ||||
| 			else if (l3 == 1) | ||||
| 				q_wire->attributes["\\init"] = RTLIL::S1; | ||||
| 			else if (l3 == l1) { | ||||
| 				//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
 | ||||
| 			} | ||||
|  | @ -197,7 +215,7 @@ void AigerReader::parse_aiger_ascii() | |||
| 		} | ||||
| 		else { | ||||
| 			// 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); | ||||
| 	} | ||||
|  | @ -212,11 +230,17 @@ void AigerReader::parse_aiger_ascii() | |||
| 		wire->port_output = true; | ||||
| 		outputs.push_back(wire); | ||||
| 	} | ||||
|     std::getline(f, line); // Ignore up to start of next line
 | ||||
| 
 | ||||
|     // TODO: Parse bad state properties
 | ||||
|     for (unsigned i = 0; i < B; ++i, ++line_count) | ||||
|         std::getline(f, line); // Ignore up to start of next line
 | ||||
| 	// Parse bad properties
 | ||||
| 	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); | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO: Parse invariant constraints
 | ||||
| 	for (unsigned i = 0; i < C; ++i, ++line_count) | ||||
|  | @ -290,8 +314,10 @@ void AigerReader::parse_aiger_binary() | |||
| 			if (!(f >> l3)) | ||||
| 				log_error("Line %u cannot be interpreted as a latch!\n", line_count); | ||||
| 
 | ||||
|             if (l3 == 0 || l3 == 1) | ||||
|                 q_wire->attributes["\\init"] = RTLIL::Const(l3); | ||||
| 			if (l3 == 0) | ||||
| 				q_wire->attributes["\\init"] = RTLIL::S0; | ||||
| 			else if (l3 == 1) | ||||
| 				q_wire->attributes["\\init"] = RTLIL::S1; | ||||
| 			else if (l3 == l1) { | ||||
| 				//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
 | ||||
| 			} | ||||
|  | @ -300,7 +326,7 @@ void AigerReader::parse_aiger_binary() | |||
| 		} | ||||
| 		else { | ||||
| 			// 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); | ||||
| 	} | ||||
|  | @ -317,8 +343,17 @@ void AigerReader::parse_aiger_binary() | |||
| 	} | ||||
| 	std::getline(f, line); // Ignore up to start of next line
 | ||||
| 
 | ||||
|     // TODO: Parse bad state properties
 | ||||
|     for (unsigned i = 0; i < B; ++i, ++line_count) | ||||
| 	// Parse bad properties
 | ||||
| 	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
 | ||||
| 
 | ||||
| 	// 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("\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 | ||||
| 				"top" // FIXME
 | ||||
| #else | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ struct AigerReader | |||
|     std::vector<RTLIL::Wire*> inputs; | ||||
|     std::vector<RTLIL::Wire*> latches; | ||||
|     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); | ||||
|     void parse_aiger(); | ||||
|  |  | |||
|  | @ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type) | |||
| 	X(AST_GENIF) | ||||
| 	X(AST_GENCASE) | ||||
| 	X(AST_GENBLOCK) | ||||
| 	X(AST_TECALL) | ||||
| 	X(AST_POSEDGE) | ||||
| 	X(AST_NEGEDGE) | ||||
| 	X(AST_EDGE) | ||||
|  | @ -194,6 +195,8 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch | |||
| 	is_logic = false; | ||||
| 	is_signed = false; | ||||
| 	is_string = false; | ||||
| 	is_wand = false; | ||||
| 	is_wor = false; | ||||
| 	is_unsized = false; | ||||
| 	was_checked = false; | ||||
| 	range_valid = false; | ||||
|  |  | |||
|  | @ -137,6 +137,7 @@ namespace AST | |||
| 		AST_GENIF, | ||||
| 		AST_GENCASE, | ||||
| 		AST_GENBLOCK, | ||||
| 		AST_TECALL, | ||||
| 		 | ||||
| 		AST_POSEDGE, | ||||
| 		AST_NEGEDGE, | ||||
|  | @ -173,7 +174,7 @@ namespace AST | |||
| 		// node content - most of it is unused in most node types
 | ||||
| 		std::string str; | ||||
| 		std::vector<RTLIL::State> bits; | ||||
| 		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked, 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; | ||||
| 		uint32_t integer; | ||||
| 		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()); | ||||
| 				wire->attributes[attr.first] = attr.second->asAttrConst(); | ||||
| 			} | ||||
| 
 | ||||
| 			if (is_wand) wire->set_bool_attribute("\\wand"); | ||||
| 			if (is_wor)  wire->set_bool_attribute("\\wor"); | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
|  | @ -1572,6 +1575,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | |||
| 			delete always; | ||||
| 		} 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: { | ||||
| 			if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") | ||||
| 			{ | ||||
|  |  | |||
|  | @ -48,6 +48,14 @@ USING_YOSYS_NAMESPACE | |||
| #include "VhdlUnits.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__ | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
|  | @ -2016,6 +2024,9 @@ struct VerificPass : public Pass { | |||
| 			// WARNING: instantiating unknown module 'XYZ' (VERI-1063)
 | ||||
| 			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 | ||||
| #  warning Verific was built without DB_PRESERVE_INITIAL_VALUE. | ||||
| #endif | ||||
|  |  | |||
|  | @ -218,6 +218,8 @@ YOSYS_NAMESPACE_END | |||
| "output"  { return TOK_OUTPUT; } | ||||
| "inout"   { return TOK_INOUT; } | ||||
| "wire"    { return TOK_WIRE; } | ||||
| "wor"     { return TOK_WOR; } | ||||
| "wand"    { return TOK_WAND; } | ||||
| "reg"     { return TOK_REG; } | ||||
| "integer" { return TOK_INTEGER; } | ||||
| "signed"  { return TOK_SIGNED; } | ||||
|  | @ -309,6 +311,11 @@ supply1 { return TOK_SUPPLY1; } | |||
| 	return TOK_ID; | ||||
| } | ||||
| 
 | ||||
| "$"(info|warning|error|fatal) { | ||||
| 	frontend_verilog_yylval.string = new std::string(yytext); | ||||
| 	return TOK_ELAB_TASK; | ||||
| } | ||||
| 
 | ||||
| "$signed"   { return TOK_TO_SIGNED; } | ||||
| "$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_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 ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END | ||||
| %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM | ||||
| %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP | ||||
| %token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR | ||||
| %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC | ||||
| %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC | ||||
| %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL | ||||
| %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT | ||||
| %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC | ||||
|  | @ -485,6 +485,12 @@ wire_type_token_io: | |||
| wire_type_token: | ||||
| 	TOK_WIRE { | ||||
| 	} | | ||||
| 	TOK_WOR { | ||||
| 		astbuf3->is_wor = true; | ||||
| 	} | | ||||
| 	TOK_WAND { | ||||
| 		astbuf3->is_wand = true; | ||||
| 	} | | ||||
| 	TOK_REG { | ||||
| 		astbuf3->is_reg = true; | ||||
| 	} | | ||||
|  | @ -1526,27 +1532,40 @@ cell_port_list_rules: | |||
| 	cell_port | cell_port_list_rules ',' cell_port; | ||||
| 
 | ||||
| cell_port: | ||||
| 	/* empty */ { | ||||
| 	attr { | ||||
| 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||
| 		astbuf2->children.push_back(node); | ||||
| 		free_attr($1); | ||||
| 	} | | ||||
| 	expr { | ||||
| 	attr expr { | ||||
| 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||
| 		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); | ||||
| 		node->str = *$2; | ||||
| 		node->str = *$3; | ||||
| 		astbuf2->children.push_back(node); | ||||
| 		node->children.push_back($4); | ||||
| 		delete $2; | ||||
| 		node->children.push_back($5); | ||||
| 		delete $3; | ||||
| 		free_attr($1); | ||||
| 	} | | ||||
| 	'.' TOK_ID '(' ')' { | ||||
| 	attr '.' TOK_ID '(' ')' { | ||||
| 		AstNode *node = new AstNode(AST_ARGUMENT); | ||||
| 		node->str = *$2; | ||||
| 		node->str = *$3; | ||||
| 		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: | ||||
|  | @ -2157,6 +2176,15 @@ gen_stmt: | |||
| 		if ($6 != NULL) | ||||
| 			delete $6; | ||||
| 		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: | ||||
|  |  | |||
|  | @ -282,6 +282,17 @@ void log_file_warning(const std::string &filename, int lineno, | |||
| 	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) | ||||
| static void logv_error_with_prefix(const char *prefix, | ||||
|                                    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.
 | ||||
| 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)); | ||||
| 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 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; | ||||
|  |  | |||
|  | @ -2026,7 +2026,6 @@ def gen_wrappers(filename, debug_level_ = 0): | |||
| #include <boost/python/wrapper.hpp> | ||||
| #include <boost/python/call.hpp> | ||||
| #include <boost/python.hpp> | ||||
| #include <boost/log/exceptions.hpp> | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| 
 | ||||
|  | @ -2060,7 +2059,6 @@ namespace YOSYS_PYTHON { | |||
| 				Yosys::log_streams.push_back(&std::cout); | ||||
| 				Yosys::log_error_stderr = true; | ||||
| 				Yosys::yosys_setup(); | ||||
| 				Yosys::yosys_banner(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -393,46 +393,114 @@ struct SetundefPass : public Pass { | |||
| 						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()) | ||||
| 						{ | ||||
| 							if (wire->name[0] == (wire_types ? '\\' : '$')) | ||||
| 								continue; | ||||
| 
 | ||||
| 							if (!wire->attributes.count("\\init")) | ||||
| 								continue; | ||||
| 
 | ||||
| 					for (auto bit : sigmap(wire)) | ||||
| 						ffbits.erase(bit); | ||||
| 							Const &initval = wire->attributes["\\init"]; | ||||
| 							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); | ||||
| 						} | ||||
| 
 | ||||
| 				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()) | ||||
| 						{ | ||||
| 							if (wire->name[0] == (wire_types ? '\\' : '$')) | ||||
| 					next_wire: | ||||
| 								continue; | ||||
| 
 | ||||
| 							for (auto bit : sigmap(wire)) | ||||
| 								if (!ffbits.count(bit)) | ||||
| 									goto next_wire; | ||||
| 
 | ||||
| 						for (auto bit : sigmap(wire)) | ||||
| 							ffbits.erase(bit); | ||||
| 							initwires.insert(wire); | ||||
| 
 | ||||
| 						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); | ||||
| 						} | ||||
| 
 | ||||
| 				for (auto wire : 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(); | ||||
| 						process_initwires(); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				log_assert(ffbits.empty()); | ||||
| 			} | ||||
| 
 | ||||
| 			module->rewrite_sigspecs(worker); | ||||
| 
 | ||||
| 			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 | ||||
| 	{ | ||||
| 		std::vector<FILE*> backup_log_files, files_to_close; | ||||
| 		std::vector<std::ostream*> backup_log_streams; | ||||
| 		int backup_log_verbose_level = log_verbose_level; | ||||
| 		backup_log_streams = log_streams; | ||||
| 		backup_log_files = log_files; | ||||
| 
 | ||||
| 		size_t argidx; | ||||
|  | @ -60,6 +62,7 @@ struct TeePass : public Pass { | |||
| 		{ | ||||
| 			if (args[argidx] == "-q" && files_to_close.empty()) { | ||||
| 				log_files.clear(); | ||||
| 				log_streams.clear(); | ||||
| 				continue; | ||||
| 			} | ||||
| 			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) | ||||
| 				fclose(cf); | ||||
| 			log_files = backup_log_files; | ||||
| 			log_streams = backup_log_streams; | ||||
| 			throw; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -97,6 +101,7 @@ struct TeePass : public Pass { | |||
| 
 | ||||
| 		log_verbose_level = backup_log_verbose_level; | ||||
| 		log_files = backup_log_files; | ||||
| 		log_streams = backup_log_streams; | ||||
| 	} | ||||
| } TeePass; | ||||
| 
 | ||||
|  |  | |||
|  | @ -562,7 +562,8 @@ struct HierarchyPass : public Pass { | |||
| 		log("In parametric designs, a module might exists in several variations with\n"); | ||||
| 		log("different parameter values. This pass looks at all modules in the current\n"); | ||||
| 		log("design an re-runs the language frontends for the parametric modules as\n"); | ||||
| 		log("needed.\n"); | ||||
| 		log("needed. It also resolves assignments to wired logic data types (wand/wor),\n"); | ||||
| 		log("resolves positional module parameters, unroll array instances, and more.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -check\n"); | ||||
| 		log("        also check the design hierarchy. this generates an error when\n"); | ||||
|  | @ -943,6 +944,121 @@ struct HierarchyPass : public Pass { | |||
| 		std::vector<Module*> design_modules = 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()) | ||||
| 			{ | ||||
| 				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)); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto module : blackbox_derivatives) | ||||
| 			design->remove(module); | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ void rmunused_module_cells(Module *module, bool verbose) | |||
| 				if (raw_bit.wire == nullptr) | ||||
| 					continue; | ||||
| 				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 " | ||||
| 							"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))); | ||||
|  |  | |||
|  | @ -299,8 +299,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) | |||
| 		sig_q = dff->getPort("\\Q"); | ||||
| 		sig_c = dff->getPort("\\C"); | ||||
| 		sig_e = dff->getPort("\\E"); | ||||
| 		val_cp = RTLIL::Const(dff->type[6] == 'P', 1); | ||||
| 		val_ep = RTLIL::Const(dff->type[7] == 'P', 1); | ||||
| 		val_cp = RTLIL::Const(dff->type[7] == 'P', 1); | ||||
| 		val_ep = RTLIL::Const(dff->type[8] == 'P', 1); | ||||
| 	} | ||||
| 	else if (dff->type == "$ff") { | ||||
| 		sig_d = dff->getPort("\\D"); | ||||
|  |  | |||
|  | @ -1,4 +1,7 @@ | |||
| pattern shiftmul | ||||
| // | ||||
| // Optimize mul+shift pairs that result from expressions such as foo[s*W+:W] | ||||
| // | ||||
| 
 | ||||
| state <SigSpec> shamt | ||||
| 
 | ||||
|  | @ -49,12 +52,16 @@ code | |||
| 	if (GetSize(port(shift, \Y)) > const_factor) | ||||
| 		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; | ||||
| 	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 << new_const_factor_log2; | ||||
| 
 | ||||
| 	int new_const_factor = 1 << factor_bits; | ||||
| 	SigSpec padding(State::Sx, new_const_factor-const_factor); | ||||
| 	SigSpec old_a = port(shift, \A), new_a; | ||||
| 	int trunc = 0; | ||||
|  | @ -73,7 +80,7 @@ code | |||
| 	if (trunc > 0) | ||||
| 		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()) | ||||
| 		new_b.append(State::S0); | ||||
| 
 | ||||
|  |  | |||
|  | @ -332,7 +332,7 @@ struct FmcombinePass : public Pass { | |||
| 
 | ||||
| 			gate_cell = module->cell(gate_name); | ||||
| 			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 | ||||
| 		{ | ||||
|  | @ -351,7 +351,7 @@ struct FmcombinePass : public Pass { | |||
| 		if (!gold_cell->parameters.empty()) | ||||
| 			log_cmd_error("Gold cell has unresolved instance parameters.\n"); | ||||
| 		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); | ||||
| 		worker.generate(); | ||||
|  |  | |||
|  | @ -88,6 +88,8 @@ struct SimInstance | |||
| 	SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : | ||||
| 			shared(shared), module(module), instance(instance), parent(parent), sigmap(module) | ||||
| 	{ | ||||
| 		log_assert(module); | ||||
| 
 | ||||
| 		if (parent) { | ||||
| 			log_assert(parent->children.count(instance) == 0); | ||||
| 			parent->children[instance] = this; | ||||
|  | @ -848,6 +850,9 @@ struct SimPass : public Pass { | |||
| 
 | ||||
| 		if (design->full_selection()) { | ||||
| 			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 { | ||||
| 			auto mods = design->selected_whole_modules(); | ||||
| 			if (GetSize(mods) != 1) | ||||
|  |  | |||
|  | @ -58,12 +58,21 @@ struct MuxcoverWorker | |||
| 	bool use_mux16; | ||||
| 	bool nodecode; | ||||
| 
 | ||||
| 	int cost_mux2; | ||||
| 	int cost_mux4; | ||||
| 	int cost_mux8; | ||||
| 	int cost_mux16; | ||||
| 
 | ||||
| 	MuxcoverWorker(Module *module) : module(module), sigmap(module) | ||||
| 	{ | ||||
| 		use_mux4 = false; | ||||
| 		use_mux8 = false; | ||||
| 		use_mux16 = false; | ||||
| 		nodecode = false; | ||||
| 		cost_mux2 = COST_MUX2; | ||||
| 		cost_mux4 = COST_MUX4; | ||||
| 		cost_mux8 = COST_MUX8; | ||||
| 		cost_mux16 = COST_MUX16; | ||||
| 		decode_mux_counter = 0; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -157,7 +166,7 @@ struct MuxcoverWorker | |||
| 		if (std::get<2>(entry)) | ||||
| 			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) | ||||
|  | @ -209,7 +218,7 @@ struct MuxcoverWorker | |||
| 			mux.inputs.push_back(B); | ||||
| 			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, B); | ||||
| 
 | ||||
|  | @ -247,7 +256,7 @@ struct MuxcoverWorker | |||
| 				mux.selects.push_back(S1); | ||||
| 				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, B); | ||||
| 				mux.cost += find_best_cover(tree, C); | ||||
|  | @ -310,7 +319,7 @@ struct MuxcoverWorker | |||
| 				mux.selects.push_back(T1); | ||||
| 				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, B); | ||||
| 				mux.cost += find_best_cover(tree, C); | ||||
|  | @ -414,7 +423,7 @@ struct MuxcoverWorker | |||
| 				mux.selects.push_back(U1); | ||||
| 				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, B); | ||||
| 				mux.cost += find_best_cover(tree, C); | ||||
|  | @ -569,9 +578,11 @@ struct MuxcoverPass : public Pass { | |||
| 		log("\n"); | ||||
| 		log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -mux4, -mux8, -mux16\n"); | ||||
| 		log("        Use the specified types of MUXes. If none of those options are used,\n"); | ||||
| 		log("        the effect is the same as if all of them where used.\n"); | ||||
| 		log("    -mux4[=cost], -mux8[=cost], -mux16[=cost]\n"); | ||||
| 		log("        Use the specified types of MUXes (with optional integer costs). If none\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("    -nodecode\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_mux16 = false; | ||||
| 		bool nodecode = false; | ||||
| 		int cost_mux4 = COST_MUX4; | ||||
| 		int cost_mux8 = COST_MUX8; | ||||
| 		int cost_mux16 = COST_MUX16; | ||||
| 
 | ||||
| 		size_t 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; | ||||
| 				if (arg.size() > 5) { | ||||
| 					if (arg[5] != '=') break; | ||||
| 					cost_mux4 = atoi(arg.substr(5).c_str()); | ||||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-mux8") { | ||||
| 			if (arg.size() >= 5 && arg.substr(0,5) == "-mux8") { | ||||
| 				use_mux8 = true; | ||||
| 				if (arg.size() > 5) { | ||||
| 					if (arg[5] != '=') break; | ||||
| 					cost_mux8 = atoi(arg.substr(5).c_str()); | ||||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-mux16") { | ||||
| 			if (arg.size() >= 6 && arg.substr(0,6) == "-mux16") { | ||||
| 				use_mux16 = true; | ||||
| 				if (arg.size() > 6) { | ||||
| 					if (arg[6] != '=') break; | ||||
| 					cost_mux16 = atoi(arg.substr(6).c_str()); | ||||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-nodecode") { | ||||
| 			if (arg == "-nodecode") { | ||||
| 				nodecode = true; | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -623,6 +650,9 @@ struct MuxcoverPass : public Pass { | |||
| 			worker.use_mux4 = use_mux4; | ||||
| 			worker.use_mux8 = use_mux8; | ||||
| 			worker.use_mux16 = use_mux16; | ||||
| 			worker.cost_mux4 = cost_mux4; | ||||
| 			worker.cost_mux8 = cost_mux8; | ||||
| 			worker.cost_mux16 = cost_mux16; | ||||
| 			worker.nodecode = nodecode; | ||||
| 			worker.run(); | ||||
| 		} | ||||
|  |  | |||
|  | @ -606,6 +606,9 @@ struct ShregmapPass : public Pass { | |||
| 		log("    -tech greenpak4\n"); | ||||
| 		log("        map to greenpak4 shift registers.\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 | ||||
| 	{ | ||||
|  |  | |||
|  | @ -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_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 | ||||
| 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"; | ||||
| 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 *) | ||||
| module SB_I2C( | ||||
| 	input  SBCLKI, | ||||
|  |  | |||
|  | @ -229,11 +229,6 @@ struct SynthXilinxPass : public ScriptPass | |||
| 			run("dff2dffe"); | ||||
| 			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) { | ||||
| 				// shregmap operates on bit-level flops, not word-level,
 | ||||
| 				//   so break those down here
 | ||||
|  | @ -242,7 +237,11 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				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"); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +0,0 @@ | |||
| aig 3 2 0 1 1 | ||||
| 6 | ||||
|  | ||||
|  | @ -3,3 +3,6 @@ aag 3 2 0 1 1 | |||
| 4 | ||||
| 6 | ||||
| 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 | ||||
| 2 | ||||
| 2 | ||||
| i0 pi0 | ||||
| o0 po0 | ||||
|  |  | |||
|  | @ -1,2 +1,4 @@ | |||
| aig 1 1 0 1 0 | ||||
| 2 | ||||
| i0 pi0 | ||||
| o0 po0 | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| aag 1 0 1 0 0 1 | ||||
| 2 3 | ||||
| 2 | ||||
| b0 po0 | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| aig 1 0 1 0 0 1 | ||||
| 3 | ||||
| 2 | ||||
| b0 po0 | ||||
|  |  | |||
|  | @ -6,3 +6,4 @@ aag 5 1 1 0 3 1 | |||
| 8 4 2 | ||||
| 10 9 7 | ||||
| b0 AIGER_NEVER | ||||
| i0 po0 | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| aig 5 1 1 0 3 1 | ||||
| 10 | ||||
| 4 | ||||
| b0 AIGER_NEVER | ||||
| i0 po0 | ||||
| b0 AIGER_NEVER | ||||
|  |  | |||
|  | @ -1,2 +1,3 @@ | |||
| aag 0 0 0 1 0 | ||||
| 0 | ||||
| o0 po0 | ||||
|  |  | |||
|  | @ -1,2 +1,3 @@ | |||
| aig 0 0 0 1 0 | ||||
| 0 | ||||
| o0 po0 | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| aag 1 1 0 1 0 | ||||
| 2 | ||||
| 3 | ||||
| i0 pi0 | ||||
| o0 po0 | ||||
|  |  | |||
|  | @ -1,2 +1,4 @@ | |||
| aig 1 1 0 1 0 | ||||
| 3 | ||||
| i0 pi0 | ||||
| o0 po0 | ||||
|  |  | |||
|  | @ -6,3 +6,4 @@ aag 5 1 1 0 3 1 | |||
| 8 4 2 | ||||
| 10 9 7 | ||||
| b0 AIGER_NEVER | ||||
| i0 pi0 | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| aig 5 1 1 0 3 1 | ||||
| 10 | ||||
| 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 | ||||
| 7 | ||||
| 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 | ||||
| 
 | ||||
| OPTIND=1 | ||||
| seed=""    # default to no seed specified | ||||
| while getopts "S:" opt | ||||
| do | ||||
|     case "$opt" in | ||||
| 	S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space | ||||
| 	   seed="SEED=$arg" ;; | ||||
|     esac | ||||
| set -e | ||||
| 
 | ||||
| # NB: *.aag and *.aig must contain a symbol table naming the primary | ||||
| #     inputs and outputs, otherwise ABC and Yosys will name them | ||||
| #     arbitrarily (and inconsistently with each other). | ||||
| 
 | ||||
| for aag in *.aag; do | ||||
|     # 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 | ||||
| shift "$((OPTIND-1))" | ||||
| 
 | ||||
| # check for Icarus Verilog | ||||
| if ! which iverilog > /dev/null ; then | ||||
|   echo "$0: Error: Icarus Verilog 'iverilog' not found." | ||||
|   exit 1 | ||||
| fi | ||||
| 
 | ||||
| echo "===== AAG ======" | ||||
| ${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" | ||||
| 
 | ||||
| echo "===== AIG ======" | ||||
| exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aig EXTRA_FLAGS="-f aiger" | ||||
| for aig in *.aig; do | ||||
|     ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" | ||||
|     ../../yosys -p " | ||||
| read_verilog ${aig%.*}_ref.v | ||||
| prep | ||||
| design -stash gold | ||||
| read_aiger -clk_name clock $aig | ||||
| 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 | ||||
|  |  | |||
|  | @ -2,3 +2,5 @@ aag 1 0 1 2 0 | |||
| 2 3 | ||||
| 2 | ||||
| 3 | ||||
| o0 po0 | ||||
| o1 po1 | ||||
|  |  | |||
|  | @ -2,3 +2,5 @@ aig 1 0 1 2 0 | |||
| 3 | ||||
| 2 | ||||
| 3 | ||||
| o0 po0 | ||||
| o1 po1 | ||||
|  |  | |||
|  | @ -1,2 +1,3 @@ | |||
| aag 0 0 0 1 0 | ||||
| 1 | ||||
| o0 po0 | ||||
|  |  | |||
|  | @ -1,2 +1,3 @@ | |||
| aig 0 0 0 1 0 | ||||
| 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]; | ||||
| 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); | ||||
| wire [3:0] t; | ||||
| assign t = i * 3; | ||||
|  |  | |||
|  | @ -17,4 +17,5 @@ if ! which iverilog > /dev/null ; then | |||
|   exit 1 | ||||
| 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() { | ||||
| 	exe="$1"; output="$2"; shift 2 | ||||
| 	ext=${1##*.} | ||||
| 	if [ "$ext" == "sv" ]; then | ||||
| 		language_gen="-g2012" | ||||
| 	else | ||||
| 		language_gen="-g2005" | ||||
| 	fi | ||||
| 
 | ||||
| 	if $use_modelsim; then | ||||
| 		altver=$( ls -v /opt/altera/ | grep '^[0-9]' | tail -n1; ) | ||||
| 		/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/xelab -R work.testbench | ||||
| 	else | ||||
| 		iverilog $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" | ||||
| 		iverilog $language_gen $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" | ||||
| 		vvp -n "$exe" | ||||
| 	fi | ||||
| } | ||||
|  | @ -110,7 +117,7 @@ for fn | |||
| do | ||||
| 	bn=${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 | ||||
| 		exit 1 | ||||
| 	fi | ||||
|  | @ -123,6 +130,10 @@ do | |||
| 		echo -n "Test: $bn " | ||||
| 	fi | ||||
| 
 | ||||
| 	if [ "$ext" == sv ]; then | ||||
| 		frontend="$frontend -sv" | ||||
| 	fi | ||||
| 
 | ||||
| 	rm -f ${bn}.{err,log,skip} | ||||
| 	mkdir -p ${bn}.out | ||||
| 	rm -rf ${bn}.out/* | ||||
|  | @ -135,9 +146,10 @@ do | |||
| 		rm -f ${bn}_ref.fir | ||||
| 		if [[ "$ext" == "v" ]]; then | ||||
| 			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 | ||||
| 			"$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn} | ||||
| 			frontend="verilog -noblackbox" | ||||
| 			cp ../${fn} ${bn}_ref.${ext} | ||||
| 		fi | ||||
| 
 | ||||
| 		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