mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into xc7srl
This commit is contained in:
		
						commit
						f1a8e8a480
					
				
					 82 changed files with 2492 additions and 593 deletions
				
			
		
							
								
								
									
										10
									
								
								.travis.yml
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								.travis.yml
									
										
									
									
									
								
							|  | @ -132,11 +132,11 @@ matrix: | ||||||
|       env: |       env: | ||||||
|         - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0" |         - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0" | ||||||
| 
 | 
 | ||||||
|     # Latest clang on Mac OS X | #   # Latest clang on Mac OS X | ||||||
|     - os: osx | #   - os: osx | ||||||
|       osx_image: xcode9.4 | #     osx_image: xcode9.4 | ||||||
|       env: | #     env: | ||||||
|         - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++" | #       - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++" | ||||||
| 
 | 
 | ||||||
| before_install: | before_install: | ||||||
|   - ./.travis/setup.sh |   - ./.travis/setup.sh | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -10,6 +10,7 @@ CONFIG := clang | ||||||
| # features (the more the better)
 | # features (the more the better)
 | ||||||
| ENABLE_TCL := 1 | ENABLE_TCL := 1 | ||||||
| ENABLE_ABC := 1 | ENABLE_ABC := 1 | ||||||
|  | ENABLE_GLOB := 1 | ||||||
| ENABLE_PLUGINS := 1 | ENABLE_PLUGINS := 1 | ||||||
| ENABLE_READLINE := 1 | ENABLE_READLINE := 1 | ||||||
| ENABLE_EDITLINE := 0 | ENABLE_EDITLINE := 0 | ||||||
|  | @ -298,6 +299,10 @@ LDLIBS += -ldl | ||||||
| endif | endif | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | ifeq ($(ENABLE_GLOB),1) | ||||||
|  | CXXFLAGS += -DYOSYS_ENABLE_GLOB | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| ifeq ($(ENABLE_TCL),1) | ifeq ($(ENABLE_TCL),1) | ||||||
| TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')") | TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')") | ||||||
| ifeq ($(OS), FreeBSD) | ifeq ($(OS), FreeBSD) | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								README.md
									
										
									
									
									
								
							|  | @ -34,11 +34,24 @@ compatible license that is similar in terms to the MIT license | ||||||
| or the 2-clause BSD license). | or the 2-clause BSD license). | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Web Site | Web Site and Other Resources | ||||||
| ======== | ============================ | ||||||
| 
 | 
 | ||||||
| More information and documentation can be found on the Yosys web site: | More information and documentation can be found on the Yosys web site: | ||||||
| http://www.clifford.at/yosys/ | - http://www.clifford.at/yosys/ | ||||||
|  | 
 | ||||||
|  | The "Documentation" page on the web site contains links to more resources, | ||||||
|  | including a manual that even describes some of the Yosys internals: | ||||||
|  | - http://www.clifford.at/yosys/documentation.html | ||||||
|  | 
 | ||||||
|  | The file `CodingReadme` in this directory contains additional information | ||||||
|  | for people interested in using the Yosys C++ APIs. | ||||||
|  | 
 | ||||||
|  | Users interested in formal verification might want to use the formal verification | ||||||
|  | front-end for Yosys, SymbiYosys: | ||||||
|  | - https://symbiyosys.readthedocs.io/en/latest/ | ||||||
|  | - https://github.com/YosysHQ/SymbiYosys | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| Setup | Setup | ||||||
| ====== | ====== | ||||||
|  | @ -296,6 +309,9 @@ Verilog Attributes and non-standard features | ||||||
|   passes to identify input and output ports of cells. The Verilog backend |   passes to identify input and output ports of cells. The Verilog backend | ||||||
|   also does not output blackbox modules on default. |   also does not output blackbox modules on default. | ||||||
| 
 | 
 | ||||||
|  | - The ``dynports'' attribute is used by the Verilog front-end to mark modules | ||||||
|  |   that have ports with a width that depends on a parameter. | ||||||
|  | 
 | ||||||
| - The ``keep`` attribute on cells and wires is used to mark objects that should | - The ``keep`` attribute on cells and wires is used to mark objects that should | ||||||
|   never be removed by the optimizer. This is used for example for cells that |   never be removed by the optimizer. This is used for example for cells that | ||||||
|   have hidden connections that are not part of the netlist, such as IO pads. |   have hidden connections that are not part of the netlist, such as IO pads. | ||||||
|  |  | ||||||
|  | @ -130,7 +130,7 @@ struct EdifBackend : public Backend { | ||||||
| 		bool port_rename = false; | 		bool port_rename = false; | ||||||
| 		bool attr_properties = false; | 		bool attr_properties = false; | ||||||
| 		std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports; | 		std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports; | ||||||
| 		bool nogndvcc = false, gndvccy = true; | 		bool nogndvcc = false, gndvccy = false; | ||||||
| 		CellTypes ct(design); | 		CellTypes ct(design); | ||||||
| 		EdifNames edif_names; | 		EdifNames edif_names; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -165,11 +165,9 @@ struct FirrtlWorker | ||||||
| 
 | 
 | ||||||
| 	std::string fid(RTLIL::IdString internal_id) | 	std::string fid(RTLIL::IdString internal_id) | ||||||
| 	{ | 	{ | ||||||
| 		const char *str = internal_id.c_str(); | 		return make_id(internal_id); | ||||||
| 		return *str == '\\' ? str + 1 : str; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	std::string cellname(RTLIL::Cell *cell) | 	std::string cellname(RTLIL::Cell *cell) | ||||||
| 	{ | 	{ | ||||||
| 		return fid(cell->name).c_str(); | 		return fid(cell->name).c_str(); | ||||||
|  | @ -219,29 +217,42 @@ struct FirrtlWorker | ||||||
| 			if (it->second.size() > 0) { | 			if (it->second.size() > 0) { | ||||||
| 				const SigSpec &secondSig = it->second; | 				const SigSpec &secondSig = it->second; | ||||||
| 				const std::string firstName = cell_name + "." + make_id(it->first); | 				const std::string firstName = cell_name + "." + make_id(it->first); | ||||||
| 				const std::string secondName = make_expr(secondSig); | 				const std::string secondExpr = make_expr(secondSig); | ||||||
| 				// Find the direction for this port.
 | 				// Find the direction for this port.
 | ||||||
| 				FDirection dir = getPortFDirection(it->first, instModule); | 				FDirection dir = getPortFDirection(it->first, instModule); | ||||||
| 				std::string source, sink; | 				std::string sourceExpr, sinkExpr; | ||||||
|  | 				const SigSpec *sinkSig = nullptr; | ||||||
| 				switch (dir) { | 				switch (dir) { | ||||||
| 					case FD_INOUT: | 					case FD_INOUT: | ||||||
| 						log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); | 						log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); | ||||||
| 					case FD_OUT: | 					case FD_OUT: | ||||||
| 						source = firstName; | 						sourceExpr = firstName; | ||||||
| 						sink = secondName; | 						sinkExpr = secondExpr; | ||||||
|  | 						sinkSig = &secondSig; | ||||||
| 						break; | 						break; | ||||||
| 					case FD_NODIRECTION: | 					case FD_NODIRECTION: | ||||||
| 						log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); | 						log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); | ||||||
| 						/* FALL_THROUGH */ | 						/* FALL_THROUGH */ | ||||||
| 					case FD_IN: | 					case FD_IN: | ||||||
| 						source = secondName; | 						sourceExpr = secondExpr; | ||||||
| 						sink = firstName; | 						sinkExpr = firstName; | ||||||
| 						break; | 						break; | ||||||
| 					default: | 					default: | ||||||
| 						log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); | 						log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); | ||||||
| 						break; | 						break; | ||||||
| 				} | 				} | ||||||
| 				wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str())); | 				// Check for subfield assignment.
 | ||||||
|  | 				std::string bitsString = "bits("; | ||||||
|  | 				if (sinkExpr.substr(0, bitsString.length()) == bitsString ) { | ||||||
|  | 					if (sinkSig == nullptr) | ||||||
|  | 						log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str()); | ||||||
|  | 					// Don't generate the assignment here.
 | ||||||
|  | 					// Add the source and sink to the "reverse_wire_map" and we'll output the assignment
 | ||||||
|  | 					//  as part of the coalesced subfield assignments for this wire.
 | ||||||
|  | 					register_reverse_wire_map(sourceExpr, *sinkSig); | ||||||
|  | 				} else { | ||||||
|  | 					wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str())); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		wire_exprs.push_back(stringf("\n")); | 		wire_exprs.push_back(stringf("\n")); | ||||||
|  |  | ||||||
|  | @ -416,6 +416,7 @@ struct Smt2Worker | ||||||
| 		for (char ch : expr) { | 		for (char ch : expr) { | ||||||
| 			if (ch == 'A') processed_expr += get_bv(sig_a); | 			if (ch == 'A') processed_expr += get_bv(sig_a); | ||||||
| 			else if (ch == 'B') processed_expr += get_bv(sig_b); | 			else if (ch == 'B') processed_expr += get_bv(sig_b); | ||||||
|  | 			else if (ch == 'P') processed_expr += get_bv(cell->getPort("\\B")); | ||||||
| 			else if (ch == 'L') processed_expr += is_signed ? "a" : "l"; | 			else if (ch == 'L') processed_expr += is_signed ? "a" : "l"; | ||||||
| 			else if (ch == 'U') processed_expr += is_signed ? "s" : "u"; | 			else if (ch == 'U') processed_expr += is_signed ? "s" : "u"; | ||||||
| 			else processed_expr += ch; | 			else processed_expr += ch; | ||||||
|  | @ -554,7 +555,7 @@ struct Smt2Worker | ||||||
| 
 | 
 | ||||||
| 			if (cell->type.in("$shift", "$shiftx")) { | 			if (cell->type.in("$shift", "$shiftx")) { | ||||||
| 				if (cell->getParam("\\B_SIGNED").as_bool()) { | 				if (cell->getParam("\\B_SIGNED").as_bool()) { | ||||||
| 					return export_bvop(cell, stringf("(ite (bvsge B #b%0*d) " | 					return export_bvop(cell, stringf("(ite (bvsge P #b%0*d) " | ||||||
| 							"(bvlshr A B) (bvlshr A (bvneg B)))", | 							"(bvlshr A B) (bvlshr A (bvneg B)))", | ||||||
| 							GetSize(cell->getPort("\\B")), 0), 's'); | 							GetSize(cell->getPort("\\B")), 0), 's'); | ||||||
| 				} else { | 				} else { | ||||||
|  | @ -887,8 +888,8 @@ struct Smt2Worker | ||||||
| 
 | 
 | ||||||
| 				string name_a = get_bool(cell->getPort("\\A")); | 				string name_a = get_bool(cell->getPort("\\A")); | ||||||
| 				string name_en = get_bool(cell->getPort("\\EN")); | 				string name_en = get_bool(cell->getPort("\\EN")); | ||||||
| 				decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, | 				string infostr = (cell->name[0] == '$' && cell->attributes.count("\\src")) ? cell->attributes.at("\\src").decode_string() : get_id(cell); | ||||||
| 						cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell))); | 				decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, infostr.c_str())); | ||||||
| 
 | 
 | ||||||
| 				if (cell->type == "$cover") | 				if (cell->type == "$cover") | ||||||
| 					decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n", | 					decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n", | ||||||
|  | @ -1103,20 +1104,27 @@ struct Smt2Worker | ||||||
| 							break; | 							break; | ||||||
| 
 | 
 | ||||||
| 						Const initword = init_data.extract(i*width, width, State::Sx); | 						Const initword = init_data.extract(i*width, width, State::Sx); | ||||||
|  | 						Const initmask = initword; | ||||||
| 						bool gen_init_constr = false; | 						bool gen_init_constr = false; | ||||||
| 
 | 
 | ||||||
| 						for (auto bit : initword.bits) | 						for (int k = 0; k < GetSize(initword); k++) { | ||||||
| 							if (bit == State::S0 || bit == State::S1) | 							if (initword[k] == State::S0 || initword[k] == State::S1) { | ||||||
| 								gen_init_constr = true; | 								gen_init_constr = true; | ||||||
|  | 								initmask[k] = State::S1; | ||||||
|  | 							} else { | ||||||
|  | 								initmask[k] = State::S0; | ||||||
|  | 								initword[k] = State::S0; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
| 
 | 
 | ||||||
| 						if (gen_init_constr) | 						if (gen_init_constr) | ||||||
| 						{ | 						{ | ||||||
| 							if (statebv) | 							if (statebv) | ||||||
| 								/* FIXME */; | 								/* FIXME */; | ||||||
| 							else | 							else | ||||||
| 								init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]", | 								init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]", | ||||||
| 										get_id(module), arrayid, Const(i, abits).as_string().c_str(), | 										get_id(module), arrayid, Const(i, abits).as_string().c_str(), | ||||||
| 										initword.as_string().c_str(), get_id(cell), i)); | 										initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i)); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal; | bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit; | ||||||
| int auto_name_counter, auto_name_offset, auto_name_digits; | int auto_name_counter, auto_name_offset, auto_name_digits; | ||||||
| std::map<RTLIL::IdString, int> auto_name_map; | std::map<RTLIL::IdString, int> auto_name_map; | ||||||
| std::set<RTLIL::IdString> reg_wires, reg_ct; | std::set<RTLIL::IdString> reg_wires, reg_ct; | ||||||
|  | @ -1310,7 +1310,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) { | 	if (siminit && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { | ||||||
| 		std::stringstream ss; | 		std::stringstream ss; | ||||||
| 		dump_reg_init(ss, cell->getPort("\\Q")); | 		dump_reg_init(ss, cell->getPort("\\Q")); | ||||||
| 		if (!ss.str().empty()) { | 		if (!ss.str().empty()) { | ||||||
|  | @ -1607,6 +1607,10 @@ struct VerilogBackend : public Backend { | ||||||
| 		log("        without this option all internal cells are converted to Verilog\n"); | 		log("        without this option all internal cells are converted to Verilog\n"); | ||||||
| 		log("        expressions.\n"); | 		log("        expressions.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -siminit\n"); | ||||||
|  | 		log("        add initial statements with hierarchical refs to initialize FFs when\n"); | ||||||
|  | 		log("        in -noexpr mode.\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -nodec\n"); | 		log("    -nodec\n"); | ||||||
| 		log("        32-bit constant values are by default dumped as decimal numbers,\n"); | 		log("        32-bit constant values are by default dumped as decimal numbers,\n"); | ||||||
| 		log("        not bit pattern. This option deactivates this feature and instead\n"); | 		log("        not bit pattern. This option deactivates this feature and instead\n"); | ||||||
|  | @ -1663,11 +1667,14 @@ struct VerilogBackend : public Backend { | ||||||
| 		nostr = false; | 		nostr = false; | ||||||
| 		defparam = false; | 		defparam = false; | ||||||
| 		decimal = false; | 		decimal = false; | ||||||
|  | 		siminit = false; | ||||||
| 		auto_prefix = ""; | 		auto_prefix = ""; | ||||||
| 
 | 
 | ||||||
| 		bool blackboxes = false; | 		bool blackboxes = false; | ||||||
| 		bool selected = false; | 		bool selected = false; | ||||||
| 
 | 
 | ||||||
|  | 		auto_name_map.clear(); | ||||||
|  | 		reg_wires.clear(); | ||||||
| 		reg_ct.clear(); | 		reg_ct.clear(); | ||||||
| 
 | 
 | ||||||
| 		reg_ct.insert("$dff"); | 		reg_ct.insert("$dff"); | ||||||
|  | @ -1739,6 +1746,10 @@ struct VerilogBackend : public Backend { | ||||||
| 				decimal = true; | 				decimal = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (arg == "-siminit") { | ||||||
|  | 				siminit = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (arg == "-blackboxes") { | 			if (arg == "-blackboxes") { | ||||||
| 				blackboxes = true; | 				blackboxes = true; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -1770,6 +1781,8 @@ struct VerilogBackend : public Backend { | ||||||
| 			dump_module(*f, "", it->second); | 			dump_module(*f, "", it->second); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		auto_name_map.clear(); | ||||||
|  | 		reg_wires.clear(); | ||||||
| 		reg_ct.clear(); | 		reg_ct.clear(); | ||||||
| 	} | 	} | ||||||
| } VerilogBackend; | } VerilogBackend; | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								examples/anlogic/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								examples/anlogic/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | demo.bit | ||||||
|  | demo_phy.area | ||||||
|  | full.v | ||||||
|  | *.log | ||||||
|  | *.h | ||||||
|  | *.tde | ||||||
|  | *.svf | ||||||
							
								
								
									
										12
									
								
								examples/anlogic/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								examples/anlogic/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | LED Blink project for Anlogic Lichee Tang board. | ||||||
|  | 
 | ||||||
|  | Follow the install instructions for the Tang Dynasty IDE from given link below. | ||||||
|  | 
 | ||||||
|  | https://tang.sipeed.com/en/getting-started/installing-td-ide/linux/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | set TD_HOME env variable to the full path to the TD <TD Install Directory> as follow. | ||||||
|  | 
 | ||||||
|  | export TD_HOME=<TD Install Directory> | ||||||
|  | 
 | ||||||
|  | then run "bash build.sh" in this directory. | ||||||
							
								
								
									
										4
									
								
								examples/anlogic/build.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								examples/anlogic/build.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | #!/bin/bash | ||||||
|  | set -ex | ||||||
|  | yosys demo.ys | ||||||
|  | $TD_HOME/bin/td build.tcl | ||||||
							
								
								
									
										11
									
								
								examples/anlogic/build.tcl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/anlogic/build.tcl
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | import_device eagle_s20.db -package BG256 | ||||||
|  | read_verilog full.v -top demo | ||||||
|  | read_adc demo.adc | ||||||
|  | optimize_rtl | ||||||
|  | map_macro | ||||||
|  | map | ||||||
|  | pack | ||||||
|  | place | ||||||
|  | route | ||||||
|  | report_area -io_info -file demo_phy.area | ||||||
|  | bitgen -bit demo.bit -version 0X0000 -svf demo.svf -svf_comment_on -g ucode:00000000000000000000000000000000 | ||||||
							
								
								
									
										2
									
								
								examples/anlogic/demo.adc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								examples/anlogic/demo.adc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | set_pin_assignment {CLK_IN} { LOCATION = K14;  } ##24MHZ | ||||||
|  | set_pin_assignment {R_LED} { LOCATION = R3;  } ##R_LED | ||||||
							
								
								
									
										18
									
								
								examples/anlogic/demo.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								examples/anlogic/demo.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | module demo ( | ||||||
|  |     input wire CLK_IN, | ||||||
|  |     output wire R_LED | ||||||
|  | ); | ||||||
|  |     parameter time1 = 30'd12_000_000; | ||||||
|  |     reg led_state; | ||||||
|  |     reg [29:0] count; | ||||||
|  | 
 | ||||||
|  |     always @(posedge CLK_IN)begin | ||||||
|  |         if(count == time1)begin | ||||||
|  |             count<= 30'd0; | ||||||
|  |             led_state <= ~led_state; | ||||||
|  |         end | ||||||
|  |         else | ||||||
|  |             count <= count + 1'b1; | ||||||
|  |     end | ||||||
|  |     assign R_LED = led_state; | ||||||
|  | endmodule | ||||||
							
								
								
									
										3
									
								
								examples/anlogic/demo.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								examples/anlogic/demo.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | read_verilog demo.v | ||||||
|  | synth_anlogic -top demo | ||||||
|  | write_verilog full.v | ||||||
							
								
								
									
										1
									
								
								examples/igloo2/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								examples/igloo2/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,4 @@ | ||||||
| /netlist.edn | /netlist.edn | ||||||
| /netlist.vm | /netlist.vm | ||||||
|  | /example.stp | ||||||
| /proj | /proj | ||||||
|  |  | ||||||
|  | @ -1 +1,20 @@ | ||||||
| # Add placement constraints here | # Add placement constraints here | ||||||
|  | 
 | ||||||
|  | set_io clk  -pinname H16 -fixed yes -DIRECTION INPUT | ||||||
|  | 
 | ||||||
|  | set_io SW1  -pinname H12 -fixed yes -DIRECTION INPUT | ||||||
|  | set_io SW2  -pinname H13 -fixed yes -DIRECTION INPUT | ||||||
|  | 
 | ||||||
|  | set_io LED1 -pinname J16 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io LED2 -pinname M16 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io LED3 -pinname K16 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io LED4 -pinname N16 -fixed yes -DIRECTION OUTPUT | ||||||
|  | 
 | ||||||
|  | set_io AA   -pinname L12 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io AB   -pinname L13 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io AC   -pinname M13 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io AD   -pinname N15 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io AE   -pinname L11 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io AF   -pinname L14 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io AG   -pinname N14 -fixed yes -DIRECTION OUTPUT | ||||||
|  | set_io CA   -pinname M15 -fixed yes -DIRECTION OUTPUT | ||||||
|  |  | ||||||
|  | @ -1 +1,2 @@ | ||||||
| # Add timing constraints here | # Add timing constraints here | ||||||
|  | create_clock -period 10.000 -waveform {0.000 5.000} [get_ports {clk}] | ||||||
|  |  | ||||||
|  | @ -1,23 +1,64 @@ | ||||||
| module example ( | module example ( | ||||||
| 	input  clk, | 	input  clk, | ||||||
| 	input  EN, | 	input  SW1, | ||||||
|  | 	input  SW2, | ||||||
| 	output LED1, | 	output LED1, | ||||||
| 	output LED2, | 	output LED2, | ||||||
| 	output LED3, | 	output LED3, | ||||||
| 	output LED4, | 	output LED4, | ||||||
| 	output LED5 | 
 | ||||||
|  | 	output AA, AB, AC, AD, | ||||||
|  | 	output AE, AF, AG, CA | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| 	localparam BITS = 5; | 	localparam BITS = 8; | ||||||
| 	localparam LOG2DELAY = 22; | 	localparam LOG2DELAY = 22; | ||||||
| 
 | 
 | ||||||
| 	reg [BITS+LOG2DELAY-1:0] counter = 0; | 	reg [BITS+LOG2DELAY-1:0] counter = 0; | ||||||
| 	reg [BITS-1:0] outcnt; | 	reg [BITS-1:0] outcnt; | ||||||
| 
 | 
 | ||||||
| 	always @(posedge clk) begin | 	always @(posedge clk) begin | ||||||
| 		counter <= counter + EN; | 		counter <= counter + SW1 + SW2 + 1; | ||||||
| 		outcnt <= counter >> LOG2DELAY; | 		outcnt <= counter >> LOG2DELAY; | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| 	assign {LED1, LED2, LED3, LED4, LED5} = outcnt ^ (outcnt >> 1); | 	assign {LED1, LED2, LED3, LED4} = outcnt ^ (outcnt >> 1); | ||||||
|  | 
 | ||||||
|  | 	// assign CA = counter[10]; | ||||||
|  | 	// seg7enc seg7encinst ( | ||||||
|  | 	// 	.seg({AA, AB, AC, AD, AE, AF, AG}), | ||||||
|  | 	// 	.dat(CA ? outcnt[3:0] : outcnt[7:4]) | ||||||
|  | 	// ); | ||||||
|  | 
 | ||||||
|  | 	assign {AA, AB, AC, AD, AE, AF, AG} = ~(7'b 100_0000 >> outcnt[6:4]); | ||||||
|  | 	assign CA = outcnt[7]; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module seg7enc ( | ||||||
|  | 	input [3:0] dat, | ||||||
|  | 	output [6:0] seg | ||||||
|  | ); | ||||||
|  | 	reg [6:0] seg_inv; | ||||||
|  | 	always @* begin | ||||||
|  | 		seg_inv = 0; | ||||||
|  | 		case (dat) | ||||||
|  | 			4'h0: seg_inv = 7'b 0111111; | ||||||
|  | 			4'h1: seg_inv = 7'b 0000110; | ||||||
|  | 			4'h2: seg_inv = 7'b 1011011; | ||||||
|  | 			4'h3: seg_inv = 7'b 1001111; | ||||||
|  | 			4'h4: seg_inv = 7'b 1100110; | ||||||
|  | 			4'h5: seg_inv = 7'b 1101101; | ||||||
|  | 			4'h6: seg_inv = 7'b 1111101; | ||||||
|  | 			4'h7: seg_inv = 7'b 0000111; | ||||||
|  | 			4'h8: seg_inv = 7'b 1111111; | ||||||
|  | 			4'h9: seg_inv = 7'b 1101111; | ||||||
|  | 			4'hA: seg_inv = 7'b 1110111; | ||||||
|  | 			4'hB: seg_inv = 7'b 1111100; | ||||||
|  | 			4'hC: seg_inv = 7'b 0111001; | ||||||
|  | 			4'hD: seg_inv = 7'b 1011110; | ||||||
|  | 			4'hE: seg_inv = 7'b 1111001; | ||||||
|  | 			4'hF: seg_inv = 7'b 1110001; | ||||||
|  | 		endcase | ||||||
|  | 	end | ||||||
|  | 	assign seg = ~seg_inv; | ||||||
| endmodule | endmodule | ||||||
|  |  | ||||||
|  | @ -8,13 +8,14 @@ new_project \ | ||||||
|     -block_mode 0 \ |     -block_mode 0 \ | ||||||
|     -hdl "VERILOG" \ |     -hdl "VERILOG" \ | ||||||
|     -family IGLOO2 \ |     -family IGLOO2 \ | ||||||
|     -die PA4MGL500 \ |     -die PA4MGL2500 \ | ||||||
|     -package tq144 \ |     -package vf256 \ | ||||||
|     -speed -1 |     -speed -1 | ||||||
| 
 | 
 | ||||||
| import_files -hdl_source {netlist.vm} | import_files -hdl_source {netlist.vm} | ||||||
| import_files -sdc {example.sdc} | import_files -sdc {example.sdc} | ||||||
| import_files -io_pdc {example.pdc} | import_files -io_pdc {example.pdc} | ||||||
|  | build_design_hierarchy | ||||||
| set_option -synth 0 | set_option -synth 0 | ||||||
| 
 | 
 | ||||||
| organize_tool_files -tool PLACEROUTE \ | organize_tool_files -tool PLACEROUTE \ | ||||||
|  | @ -32,22 +33,25 @@ configure_tool -name PLACEROUTE \ | ||||||
|     -params EFFORT_LEVEL:false \ |     -params EFFORT_LEVEL:false \ | ||||||
|     -params REPAIR_MIN_DELAY:false |     -params REPAIR_MIN_DELAY:false | ||||||
| 
 | 
 | ||||||
|  | puts "" | ||||||
| puts "**> COMPILE" | puts "**> COMPILE" | ||||||
| run_tool -name {COMPILE} | run_tool -name {COMPILE} | ||||||
| puts "<** COMPILE" | puts "<** COMPILE" | ||||||
| 
 | 
 | ||||||
|  | puts "" | ||||||
| puts "**> PLACEROUTE" | puts "**> PLACEROUTE" | ||||||
| run_tool -name {PLACEROUTE} | run_tool -name {PLACEROUTE} | ||||||
| puts "<** PLACEROUTE" | puts "<** PLACEROUTE" | ||||||
| 
 | 
 | ||||||
|  | puts "" | ||||||
| puts "**> VERIFYTIMING" | puts "**> VERIFYTIMING" | ||||||
| run_tool -name {VERIFYTIMING} | run_tool -name {VERIFYTIMING} | ||||||
| puts "<** VERIFYTIMING" | puts "<** VERIFYTIMING" | ||||||
| 
 | 
 | ||||||
| save_project | puts "" | ||||||
| 
 | puts "**> BITSTREAM" | ||||||
| # puts "**> export_bitstream" | export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC} | ||||||
| # export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC} | puts "<** BITSTREAM" | ||||||
| # puts "<** export_bitstream" |  | ||||||
| 
 | 
 | ||||||
|  | puts "" | ||||||
| exit 0 | exit 0 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| #!/bin/bash | #!/bin/bash | ||||||
| set -ex | set -ex | ||||||
| yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v | yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v | ||||||
| LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero SCRIPT:libero.tcl | export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost} | ||||||
|  | /opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl | ||||||
|  | cp proj/designer/example/export/example.stp . | ||||||
|  |  | ||||||
|  | @ -214,6 +214,8 @@ namespace AST | ||||||
| 			MEM2REG_FL_SET_ASYNC = 0x00000800, | 			MEM2REG_FL_SET_ASYNC = 0x00000800, | ||||||
| 			MEM2REG_FL_EQ2       = 0x00001000, | 			MEM2REG_FL_EQ2       = 0x00001000, | ||||||
| 			MEM2REG_FL_CMPLX_LHS = 0x00002000, | 			MEM2REG_FL_CMPLX_LHS = 0x00002000, | ||||||
|  | 			MEM2REG_FL_CONST_LHS = 0x00004000, | ||||||
|  | 			MEM2REG_FL_VAR_LHS   = 0x00008000, | ||||||
| 
 | 
 | ||||||
| 			/* proc flags */ | 			/* proc flags */ | ||||||
| 			MEM2REG_FL_EQ1       = 0x01000000, | 			MEM2REG_FL_EQ1       = 0x01000000, | ||||||
|  | @ -237,6 +239,7 @@ namespace AST | ||||||
| 		bool has_const_only_constructs(bool &recommend_const_eval); | 		bool has_const_only_constructs(bool &recommend_const_eval); | ||||||
| 		void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall); | 		void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall); | ||||||
| 		AstNode *eval_const_function(AstNode *fcall); | 		AstNode *eval_const_function(AstNode *fcall); | ||||||
|  | 		bool is_simple_const_expr(); | ||||||
| 
 | 
 | ||||||
| 		// create a human-readable text representation of the AST (for debugging)
 | 		// create a human-readable text representation of the AST (for debugging)
 | ||||||
| 		void dumpAst(FILE *f, std::string indent) const; | 		void dumpAst(FILE *f, std::string indent) const; | ||||||
|  |  | ||||||
|  | @ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		case AST_WIRE: | 		case AST_WIRE: | ||||||
| 			log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n"); | 			log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n"); | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case AST_ASSIGN: | ||||||
|  | 			log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n"); | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		case AST_PARAMETER: | 		case AST_PARAMETER: | ||||||
|  | @ -1409,10 +1413,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | ||||||
| 			if (GetSize(en) != 1) | 			if (GetSize(en) != 1) | ||||||
| 				en = current_module->ReduceBool(NEW_ID, en); | 				en = current_module->ReduceBool(NEW_ID, en); | ||||||
| 
 | 
 | ||||||
| 			std::stringstream sstr; | 			IdString cellname; | ||||||
| 			sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++); | 			if (str.empty()) { | ||||||
|  | 				std::stringstream sstr; | ||||||
|  | 				sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++); | ||||||
|  | 				cellname = sstr.str(); | ||||||
|  | 			} else { | ||||||
|  | 				cellname = str; | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Cell *cell = current_module->addCell(sstr.str(), celltype); | 			RTLIL::Cell *cell = current_module->addCell(cellname, celltype); | ||||||
| 			cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); | 			cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); | ||||||
| 
 | 
 | ||||||
| 			for (auto &attr : attributes) { | 			for (auto &attr : attributes) { | ||||||
|  |  | ||||||
|  | @ -50,7 +50,6 @@ using namespace AST_INTERNAL; | ||||||
| bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param) | bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param) | ||||||
| { | { | ||||||
| 	static int recursion_counter = 0; | 	static int recursion_counter = 0; | ||||||
| 	static pair<string, int> last_blocking_assignment_warn; |  | ||||||
| 	static bool deep_recursion_warning = false; | 	static bool deep_recursion_warning = false; | ||||||
| 
 | 
 | ||||||
| 	if (recursion_counter++ == 1000 && deep_recursion_warning) { | 	if (recursion_counter++ == 1000 && deep_recursion_warning) { | ||||||
|  | @ -72,7 +71,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | ||||||
| 	if (stage == 0) | 	if (stage == 0) | ||||||
| 	{ | 	{ | ||||||
| 		log_assert(type == AST_MODULE || type == AST_INTERFACE); | 		log_assert(type == AST_MODULE || type == AST_INTERFACE); | ||||||
| 		last_blocking_assignment_warn = pair<string, int>(); |  | ||||||
| 
 | 
 | ||||||
| 		deep_recursion_warning = true; | 		deep_recursion_warning = true; | ||||||
| 		while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { } | 		while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { } | ||||||
|  | @ -113,6 +111,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | ||||||
| 				if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS) | 				if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS) | ||||||
| 					goto verbose_activate; | 					goto verbose_activate; | ||||||
| 
 | 
 | ||||||
|  | 				if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS)) | ||||||
|  | 					goto verbose_activate; | ||||||
|  | 
 | ||||||
| 				// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
 | 				// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
 | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
|  | @ -325,6 +326,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | ||||||
| 		for (size_t i = 0; i < children.size(); i++) { | 		for (size_t i = 0; i < children.size(); i++) { | ||||||
| 			AstNode *node = children[i]; | 			AstNode *node = children[i]; | ||||||
| 			if (node->type == AST_WIRE) { | 			if (node->type == AST_WIRE) { | ||||||
|  | 				if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { | ||||||
|  | 					for (auto c : node->children[0]->children) { | ||||||
|  | 						if (!c->is_simple_const_expr()) { | ||||||
|  | 							if (attributes.count("\\dynports")) | ||||||
|  | 								delete attributes.at("\\dynports"); | ||||||
|  | 							attributes["\\dynports"] = AstNode::mkconst_int(1, true); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
| 				if (this_wire_scope.count(node->str) > 0) { | 				if (this_wire_scope.count(node->str) > 0) { | ||||||
| 					AstNode *first_node = this_wire_scope[node->str]; | 					AstNode *first_node = this_wire_scope[node->str]; | ||||||
| 					if (first_node->is_input && node->is_reg) | 					if (first_node->is_input && node->is_reg) | ||||||
|  | @ -938,7 +948,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (current_scope.count(str) == 0) { | 		if (current_scope.count(str) == 0) { | ||||||
| 			if (flag_autowire) { | 			if (flag_autowire || str == "\\$global_clock") { | ||||||
| 				AstNode *auto_wire = new AstNode(AST_AUTOWIRE); | 				AstNode *auto_wire = new AstNode(AST_AUTOWIRE); | ||||||
| 				auto_wire->str = str; | 				auto_wire->str = str; | ||||||
| 				current_ast_mod->children.push_back(auto_wire); | 				current_ast_mod->children.push_back(auto_wire); | ||||||
|  | @ -1499,6 +1509,7 @@ skip_dynamic_range_lvalue_expansion:; | ||||||
| 		newNode->children.push_back(assign_en); | 		newNode->children.push_back(assign_en); | ||||||
| 
 | 
 | ||||||
| 		AstNode *assertnode = new AstNode(type); | 		AstNode *assertnode = new AstNode(type); | ||||||
|  | 		assertnode->str = str; | ||||||
| 		assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); | 		assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); | ||||||
| 		assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); | 		assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); | ||||||
| 		assertnode->children[0]->str = id_check; | 		assertnode->children[0]->str = id_check; | ||||||
|  | @ -1579,14 +1590,6 @@ skip_dynamic_range_lvalue_expansion:; | ||||||
| 		sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); | 		sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); | ||||||
| 		std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; | 		std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; | ||||||
| 
 | 
 | ||||||
| 		if (type == AST_ASSIGN_EQ) { |  | ||||||
| 			pair<string, int> this_blocking_assignment_warn(filename, linenum); |  | ||||||
| 			if (this_blocking_assignment_warn != last_blocking_assignment_warn) |  | ||||||
| 				log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", |  | ||||||
| 						filename.c_str(), linenum); |  | ||||||
| 			last_blocking_assignment_warn = this_blocking_assignment_warn; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		int mem_width, mem_size, addr_bits; | 		int mem_width, mem_size, addr_bits; | ||||||
| 		bool mem_signed = children[0]->id2ast->is_signed; | 		bool mem_signed = children[0]->id2ast->is_signed; | ||||||
| 		children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); | 		children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); | ||||||
|  | @ -2169,6 +2172,8 @@ skip_dynamic_range_lvalue_expansion:; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init); | 				newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init); | ||||||
|  | 				delete node_filename; | ||||||
|  | 				delete node_memory; | ||||||
| 				goto apply_newNode; | 				goto apply_newNode; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -2210,6 +2215,8 @@ skip_dynamic_range_lvalue_expansion:; | ||||||
| 		std::map<std::string, std::string> replace_rules; | 		std::map<std::string, std::string> replace_rules; | ||||||
| 		vector<AstNode*> added_mod_children; | 		vector<AstNode*> added_mod_children; | ||||||
| 		dict<std::string, AstNode*> wire_cache; | 		dict<std::string, AstNode*> wire_cache; | ||||||
|  | 		vector<AstNode*> new_stmts; | ||||||
|  | 		vector<AstNode*> output_assignments; | ||||||
| 
 | 
 | ||||||
| 		if (current_block == NULL) | 		if (current_block == NULL) | ||||||
| 		{ | 		{ | ||||||
|  | @ -2334,8 +2341,8 @@ skip_dynamic_range_lvalue_expansion:; | ||||||
| 					wire->port_id = 0; | 					wire->port_id = 0; | ||||||
| 					wire->is_input = false; | 					wire->is_input = false; | ||||||
| 					wire->is_output = false; | 					wire->is_output = false; | ||||||
| 					if (!child->is_output) | 					wire->is_reg = true; | ||||||
| 						wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); | 					wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); | ||||||
| 					wire_cache[child->str] = wire; | 					wire_cache[child->str] = wire; | ||||||
| 
 | 
 | ||||||
| 					current_ast_mod->children.push_back(wire); | 					current_ast_mod->children.push_back(wire); | ||||||
|  | @ -2357,13 +2364,10 @@ skip_dynamic_range_lvalue_expansion:; | ||||||
| 							new AstNode(AST_ASSIGN_EQ, wire_id, arg) : | 							new AstNode(AST_ASSIGN_EQ, wire_id, arg) : | ||||||
| 							new AstNode(AST_ASSIGN_EQ, arg, wire_id); | 							new AstNode(AST_ASSIGN_EQ, arg, wire_id); | ||||||
| 					assign->children[0]->was_checked = true; | 					assign->children[0]->was_checked = true; | ||||||
| 
 | 					if (child->is_input) | ||||||
| 					for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { | 						new_stmts.push_back(assign); | ||||||
| 						if (*it != current_block_child) | 					else | ||||||
| 							continue; | 						output_assignments.push_back(assign); | ||||||
| 						current_block->children.insert(it, assign); |  | ||||||
| 						break; |  | ||||||
| 					} |  | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -2377,15 +2381,19 @@ skip_dynamic_range_lvalue_expansion:; | ||||||
| 			{ | 			{ | ||||||
| 				AstNode *stmt = child->clone(); | 				AstNode *stmt = child->clone(); | ||||||
| 				stmt->replace_ids(prefix, replace_rules); | 				stmt->replace_ids(prefix, replace_rules); | ||||||
| 
 | 				new_stmts.push_back(stmt); | ||||||
| 				for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { |  | ||||||
| 					if (*it != current_block_child) |  | ||||||
| 						continue; |  | ||||||
| 					current_block->children.insert(it, stmt); |  | ||||||
| 					break; |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 		new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end()); | ||||||
|  | 
 | ||||||
|  | 		for (auto it = current_block->children.begin(); ; it++) { | ||||||
|  | 			log_assert(it != current_block->children.end()); | ||||||
|  | 			if (*it == current_block_child) { | ||||||
|  | 				current_block->children.insert(it, new_stmts.begin(), new_stmts.end()); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 	replace_fcall_with_id: | 	replace_fcall_with_id: | ||||||
| 		if (type == AST_FCALL) { | 		if (type == AST_FCALL) { | ||||||
| 			delete_children(); | 			delete_children(); | ||||||
|  | @ -2910,7 +2918,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg | ||||||
| 		dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags) | 		dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags) | ||||||
| { | { | ||||||
| 	uint32_t children_flags = 0; | 	uint32_t children_flags = 0; | ||||||
| 	int ignore_children_counter = 0; | 	int lhs_children_counter = 0; | ||||||
| 
 | 
 | ||||||
| 	if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) | 	if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) | ||||||
| 	{ | 	{ | ||||||
|  | @ -2936,6 +2944,16 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg | ||||||
| 				proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; | 				proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			// for proper (non-init) writes: remember if this is a constant index or not
 | ||||||
|  | 			if ((flags & MEM2REG_FL_INIT) == 0) { | ||||||
|  | 				if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { | ||||||
|  | 					if (children[0]->children[0]->children[0]->type == AST_CONSTANT) | ||||||
|  | 						mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; | ||||||
|  | 					else | ||||||
|  | 						mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			// remember where this is
 | 			// remember where this is
 | ||||||
| 			if (flags & MEM2REG_FL_INIT) { | 			if (flags & MEM2REG_FL_INIT) { | ||||||
| 				if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT)) | 				if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT)) | ||||||
|  | @ -2948,7 +2966,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ignore_children_counter = 1; | 		lhs_children_counter = 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY) | 	if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY) | ||||||
|  | @ -2991,12 +3009,23 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg | ||||||
| 	log_assert((flags & ~0x000000ff) == 0); | 	log_assert((flags & ~0x000000ff) == 0); | ||||||
| 
 | 
 | ||||||
| 	for (auto child : children) | 	for (auto child : children) | ||||||
| 		if (ignore_children_counter > 0) | 	{ | ||||||
| 			ignore_children_counter--; | 		if (lhs_children_counter > 0) { | ||||||
| 		else if (proc_flags_p) | 			lhs_children_counter--; | ||||||
|  | 			if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) { | ||||||
|  | 				for (auto c : child->children[0]->children) { | ||||||
|  | 					if (proc_flags_p) | ||||||
|  | 						c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); | ||||||
|  | 					else | ||||||
|  | 						c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} else | ||||||
|  | 		if (proc_flags_p) | ||||||
| 			child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); | 			child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); | ||||||
| 		else | 		else | ||||||
| 			child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags); | 			child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	flags &= ~children_flags | backup_flags; | 	flags &= ~children_flags | backup_flags; | ||||||
| 
 | 
 | ||||||
|  | @ -3048,6 +3077,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, | ||||||
| 	if (type == AST_FUNCTION || type == AST_TASK) | 	if (type == AST_FUNCTION || type == AST_TASK) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
|  | 	if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) | ||||||
|  | 	{ | ||||||
|  | 		log_assert(children[0]->type == AST_CONSTANT); | ||||||
|  | 		log_assert(children[1]->type == AST_CONSTANT); | ||||||
|  | 		log_assert(children[2]->type == AST_CONSTANT); | ||||||
|  | 
 | ||||||
|  | 		int cursor = children[0]->asInt(false); | ||||||
|  | 		Const data = children[1]->bitsAsConst(); | ||||||
|  | 		int length = children[2]->asInt(false); | ||||||
|  | 
 | ||||||
|  | 		if (length != 0) | ||||||
|  | 		{ | ||||||
|  | 			AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK)); | ||||||
|  | 			mod->children.push_back(block); | ||||||
|  | 			block = block->children[0]; | ||||||
|  | 
 | ||||||
|  | 			int wordsz = GetSize(data) / length; | ||||||
|  | 
 | ||||||
|  | 			for (int i = 0; i < length; i++) { | ||||||
|  | 				block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false))); | ||||||
|  | 				block->children.back()->children[0]->str = str; | ||||||
|  | 				block->children.back()->children[0]->id2ast = id2ast; | ||||||
|  | 				block->children.back()->children[0]->was_checked = true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		AstNode *newNode = new AstNode(AST_NONE); | ||||||
|  | 		newNode->cloneInto(this); | ||||||
|  | 		delete newNode; | ||||||
|  | 
 | ||||||
|  | 		did_something = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set)) | 	if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set)) | ||||||
| 	{ | 	{ | ||||||
| 		if (async_block == NULL) { | 		if (async_block == NULL) { | ||||||
|  | @ -3277,6 +3339,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval) | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool AstNode::is_simple_const_expr() | ||||||
|  | { | ||||||
|  | 	if (type == AST_IDENTIFIER) | ||||||
|  | 		return false; | ||||||
|  | 	for (auto child : children) | ||||||
|  | 		if (!child->is_simple_const_expr()) | ||||||
|  | 			return false; | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // helper function for AstNode::eval_const_function()
 | // helper function for AstNode::eval_const_function()
 | ||||||
| void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall) | void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ Then run in the following command in this directory: | ||||||
| 
 | 
 | ||||||
| 	sby -f example.sby | 	sby -f example.sby | ||||||
| 
 | 
 | ||||||
| This will generate approximately one page of text outpout. The last lines | This will generate approximately one page of text output. The last lines | ||||||
| should be something like this: | should be something like this: | ||||||
| 
 | 
 | ||||||
| 	SBY [example] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0) | 	SBY [example] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0) | ||||||
|  |  | ||||||
|  | @ -1855,6 +1855,13 @@ struct VerificPass : public Pass { | ||||||
| 		log("  -autocover\n"); | 		log("  -autocover\n"); | ||||||
| 		log("    Generate automatic cover statements for all asserts\n"); | 		log("    Generate automatic cover statements for all asserts\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("  -chparam name value \n"); | ||||||
|  | 		log("    Elaborate the specified top modules (all modules when -all given) using\n"); | ||||||
|  | 		log("    this parameter value. Modules on which this parameter does not exist will\n"); | ||||||
|  | 		log("    cause Verific to produce a VERI-1928 or VHDL-1676 message. This option\n"); | ||||||
|  | 		log("    can be specified multiple times to override multiple parameters.\n"); | ||||||
|  | 		log("    String values must be passed in double quotes (\").\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("  -v, -vv\n"); | 		log("  -v, -vv\n"); | ||||||
| 		log("    Verbose log messages. (-vv is even more verbose than -v.)\n"); | 		log("    Verbose log messages. (-vv is even more verbose than -v.)\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -2109,6 +2116,7 @@ struct VerificPass : public Pass { | ||||||
| 			bool mode_autocover = false; | 			bool mode_autocover = false; | ||||||
| 			bool flatten = false, extnets = false; | 			bool flatten = false, extnets = false; | ||||||
| 			string dumpfile; | 			string dumpfile; | ||||||
|  | 			Map parameters(STRING_HASH); | ||||||
| 
 | 
 | ||||||
| 			for (argidx++; argidx < GetSize(args); argidx++) { | 			for (argidx++; argidx < GetSize(args); argidx++) { | ||||||
| 				if (args[argidx] == "-all") { | 				if (args[argidx] == "-all") { | ||||||
|  | @ -2147,6 +2155,15 @@ struct VerificPass : public Pass { | ||||||
| 					mode_autocover = true; | 					mode_autocover = true; | ||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
|  | 				if (args[argidx] == "-chparam"  && argidx+2 < GetSize(args)) { | ||||||
|  |                                         const std::string &key = args[++argidx]; | ||||||
|  |                                         const std::string &value = args[++argidx]; | ||||||
|  | 					unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(), | ||||||
|  | 									           1 /* force_overwrite */); | ||||||
|  | 					if (!new_insertion) | ||||||
|  | 						log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str()); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
| 				if (args[argidx] == "-V") { | 				if (args[argidx] == "-V") { | ||||||
| 					mode_verific = true; | 					mode_verific = true; | ||||||
| 					continue; | 					continue; | ||||||
|  | @ -2180,7 +2197,7 @@ struct VerificPass : public Pass { | ||||||
| 				if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib); | 				if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib); | ||||||
| 				if (veri_lib) veri_libs.InsertLast(veri_lib); | 				if (veri_lib) veri_libs.InsertLast(veri_lib); | ||||||
| 
 | 
 | ||||||
| 				Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs); | 				Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, ¶meters); | ||||||
| 				Netlist *nl; | 				Netlist *nl; | ||||||
| 				int i; | 				int i; | ||||||
| 
 | 
 | ||||||
|  | @ -2217,7 +2234,7 @@ struct VerificPass : public Pass { | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				log("Running hier_tree::Elaborate().\n"); | 				log("Running hier_tree::Elaborate().\n"); | ||||||
| 				Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units); | 				Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, ¶meters); | ||||||
| 				Netlist *nl; | 				Netlist *nl; | ||||||
| 				int i; | 				int i; | ||||||
| 
 | 
 | ||||||
|  | @ -2316,7 +2333,7 @@ struct ReadPass : 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 | ||||||
| 	{ | 	{ | ||||||
| 		if (args.size() < 2) | 		if (args.size() < 2 || args[1][0] != '-') | ||||||
| 			log_cmd_error("Missing mode parameter.\n"); | 			log_cmd_error("Missing mode parameter.\n"); | ||||||
| 
 | 
 | ||||||
| 		if (args.size() < 3) | 		if (args.size() < 3) | ||||||
|  |  | ||||||
|  | @ -1666,7 +1666,20 @@ struct VerificSvaImporter | ||||||
| 				log("  importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(), | 				log("  importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(), | ||||||
| 						LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile())); | 						LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile())); | ||||||
| 
 | 
 | ||||||
| 			RTLIL::IdString root_name = module->uniquify(importer->mode_names || root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID); | 			bool is_user_declared = root->IsUserDeclared(); | ||||||
|  | 
 | ||||||
|  | 			// FIXME
 | ||||||
|  | 			if (!is_user_declared) { | ||||||
|  | 				const char *name = root->Name(); | ||||||
|  | 				for (int i = 0; name[i]; i++) { | ||||||
|  | 					if (i ? (name[i] < '0' || name[i] > '9') : (name[i] != 'i')) { | ||||||
|  | 						is_user_declared = true; | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			RTLIL::IdString root_name = module->uniquify(importer->mode_names || is_user_declared ? RTLIL::escape_id(root->Name()) : NEW_ID); | ||||||
| 
 | 
 | ||||||
| 			// parse SVA sequence into trigger signal
 | 			// parse SVA sequence into trigger signal
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -189,6 +189,14 @@ YOSYS_NAMESPACE_END | ||||||
| "always_ff"    { SV_KEYWORD(TOK_ALWAYS); } | "always_ff"    { SV_KEYWORD(TOK_ALWAYS); } | ||||||
| "always_latch" { SV_KEYWORD(TOK_ALWAYS); } | "always_latch" { SV_KEYWORD(TOK_ALWAYS); } | ||||||
| 
 | 
 | ||||||
|  |  /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex | ||||||
|  |     to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some | ||||||
|  |     global state.. its a mess) */ | ||||||
|  | [a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { | ||||||
|  | 	frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); | ||||||
|  | 	return TOK_SVA_LABEL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| "assert"     { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } | "assert"     { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } | ||||||
| "assume"     { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } | "assume"     { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } | ||||||
| "cover"      { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } | "cover"      { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } | ||||||
|  | @ -303,7 +311,7 @@ supply1 { return TOK_SUPPLY1; } | ||||||
| 
 | 
 | ||||||
| [a-zA-Z_$][a-zA-Z0-9_$\.]* { | [a-zA-Z_$][a-zA-Z0-9_$\.]* { | ||||||
| 	frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); | 	frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); | ||||||
|     return TOK_ID; | 	return TOK_ID; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { | "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { | ||||||
|  |  | ||||||
|  | @ -105,7 +105,8 @@ static void free_attr(std::map<std::string, AstNode*> *al) | ||||||
| 	bool boolean; | 	bool boolean; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE | %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL | ||||||
|  | %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER | ||||||
| %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 | ||||||
|  | @ -119,14 +120,13 @@ static void free_attr(std::map<std::string, AstNode*> *al) | ||||||
| %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL | %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL | ||||||
| %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE | %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE | ||||||
| %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED | %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED | ||||||
| %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME | %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF | ||||||
| %token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF |  | ||||||
| %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY | %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY | ||||||
| %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY | %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY | ||||||
| 
 | 
 | ||||||
| %type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int | %type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int | ||||||
| %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list | %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list | ||||||
| %type <string> opt_label tok_prim_wrapper hierarchical_id | %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id | ||||||
| %type <boolean> opt_signed opt_property unique_case_attr | %type <boolean> opt_signed opt_property unique_case_attr | ||||||
| %type <al> attr case_attr | %type <al> attr case_attr | ||||||
| 
 | 
 | ||||||
|  | @ -1329,6 +1329,14 @@ opt_label: | ||||||
| 		$$ = NULL; | 		$$ = NULL; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | opt_sva_label: | ||||||
|  | 	TOK_SVA_LABEL ':' { | ||||||
|  | 		$$ = $1; | ||||||
|  | 	} | | ||||||
|  | 	/* empty */ { | ||||||
|  | 		$$ = NULL; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| opt_property: | opt_property: | ||||||
| 	TOK_PROPERTY { | 	TOK_PROPERTY { | ||||||
| 		$$ = true; | 		$$ = true; | ||||||
|  | @ -1337,9 +1345,6 @@ opt_property: | ||||||
| 		$$ = false; | 		$$ = false; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| opt_stmt_label: |  | ||||||
| 	TOK_ID ':' | /* empty */; |  | ||||||
| 
 |  | ||||||
| modport_stmt: | modport_stmt: | ||||||
|     TOK_MODPORT TOK_ID { |     TOK_MODPORT TOK_ID { | ||||||
|         AstNode *modport = new AstNode(AST_MODPORT); |         AstNode *modport = new AstNode(AST_MODPORT); | ||||||
|  | @ -1376,83 +1381,164 @@ modport_type_token: | ||||||
|     TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} |     TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} | ||||||
| 
 | 
 | ||||||
| assert: | assert: | ||||||
| 	opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { | 	opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' { | ||||||
| 		if (noassert_mode) | 		if (noassert_mode) { | ||||||
| 			delete $5; | 			delete $5; | ||||||
| 		else | 		} else { | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); | 			AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); | ||||||
|  | 			if ($1 != nullptr) | ||||||
|  | 				node->str = *$1; | ||||||
|  | 			ast_stack.back()->children.push_back(node); | ||||||
|  | 		} | ||||||
|  | 		if ($1 != nullptr) | ||||||
|  | 			delete $1; | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { | 	opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' { | ||||||
| 		if (noassume_mode) | 		if (noassume_mode) { | ||||||
| 			delete $5; | 			delete $5; | ||||||
| 		else | 		} else { | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5)); | 			AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); | ||||||
|  | 			if ($1 != nullptr) | ||||||
|  | 				node->str = *$1; | ||||||
|  | 			ast_stack.back()->children.push_back(node); | ||||||
|  | 		} | ||||||
|  | 		if ($1 != nullptr) | ||||||
|  | 			delete $1; | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { | 	opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { | ||||||
| 		if (noassert_mode) | 		if (noassert_mode) { | ||||||
| 			delete $6; | 			delete $6; | ||||||
| 		else | 		} else { | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); | 			AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); | ||||||
|  | 			if ($1 != nullptr) | ||||||
|  | 				node->str = *$1; | ||||||
|  | 			ast_stack.back()->children.push_back(node); | ||||||
|  | 		} | ||||||
|  | 		if ($1 != nullptr) | ||||||
|  | 			delete $1; | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { | 	opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { | ||||||
| 		if (noassume_mode) | 		if (noassume_mode) { | ||||||
| 			delete $6; | 			delete $6; | ||||||
| 		else | 		} else { | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6)); | 			AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); | ||||||
|  | 			if ($1 != nullptr) | ||||||
|  | 				node->str = *$1; | ||||||
|  | 			ast_stack.back()->children.push_back(node); | ||||||
|  | 		} | ||||||
|  | 		if ($1 != nullptr) | ||||||
|  | 			delete $1; | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { | 	opt_sva_label TOK_COVER opt_property '(' expr ')' ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); | 		AstNode *node = new AstNode(AST_COVER, $5); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			node->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
|  | 		ast_stack.back()->children.push_back(node); | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_COVER opt_property '(' ')' ';' { | 	opt_sva_label TOK_COVER opt_property '(' ')' ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); | 		AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			node->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
|  | 		ast_stack.back()->children.push_back(node); | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_COVER ';' { | 	opt_sva_label TOK_COVER ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); | 		AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			node->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
|  | 		ast_stack.back()->children.push_back(node); | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' { | 	opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' { | ||||||
| 		if (norestrict_mode) | 		if (norestrict_mode) { | ||||||
| 			delete $5; | 			delete $5; | ||||||
| 		else | 		} else { | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); | 			AstNode *node = new AstNode(AST_ASSUME, $5); | ||||||
|  | 			if ($1 != nullptr) | ||||||
|  | 				node->str = *$1; | ||||||
|  | 			ast_stack.back()->children.push_back(node); | ||||||
|  | 		} | ||||||
| 		if (!$3) | 		if (!$3) | ||||||
| 			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); | 			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); | ||||||
|  | 		if ($1 != nullptr) | ||||||
|  | 			delete $1; | ||||||
| 	} | | 	} | | ||||||
| 	opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { | 	opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { | ||||||
| 		if (norestrict_mode) | 		if (norestrict_mode) { | ||||||
| 			delete $6; | 			delete $6; | ||||||
| 		else | 		} else { | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); | 			AstNode *node = new AstNode(AST_FAIR, $6); | ||||||
|  | 			if ($1 != nullptr) | ||||||
|  | 				node->str = *$1; | ||||||
|  | 			ast_stack.back()->children.push_back(node); | ||||||
|  | 		} | ||||||
| 		if (!$3) | 		if (!$3) | ||||||
| 			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); | 			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); | ||||||
|  | 		if ($1 != nullptr) | ||||||
|  | 			delete $1; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| assert_property: | assert_property: | ||||||
| 	TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { | 	opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4)); | 		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
| 	} | | 	} | | ||||||
| 	TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { | 	opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); | 		ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
| 	} | | 	} | | ||||||
| 	TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { | 	opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5)); | 		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
| 	} | | 	} | | ||||||
| 	TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { | 	opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); | 		ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
| 	} | | 	} | | ||||||
| 	TOK_COVER TOK_PROPERTY '(' expr ')' ';' { | 	opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4)); | 		ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); | ||||||
|  | 		if ($1 != nullptr) { | ||||||
|  | 			ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 			delete $1; | ||||||
|  | 		} | ||||||
| 	} | | 	} | | ||||||
| 	TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { | 	opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { | ||||||
| 		if (norestrict_mode) | 		if (norestrict_mode) { | ||||||
| 			delete $4; |  | ||||||
| 		else |  | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); |  | ||||||
| 	} | |  | ||||||
| 	TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { |  | ||||||
| 		if (norestrict_mode) |  | ||||||
| 			delete $5; | 			delete $5; | ||||||
| 		else | 		} else { | ||||||
| 			ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); | 			ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); | ||||||
|  | 			if ($1 != nullptr) { | ||||||
|  | 				ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 				delete $1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | | ||||||
|  | 	opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { | ||||||
|  | 		if (norestrict_mode) { | ||||||
|  | 			delete $6; | ||||||
|  | 		} else { | ||||||
|  | 			ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); | ||||||
|  | 			if ($1 != nullptr) { | ||||||
|  | 				ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 				delete $1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| simple_behavioral_stmt: | simple_behavioral_stmt: | ||||||
|  | @ -1670,6 +1756,11 @@ case_expr_list: | ||||||
| 	TOK_DEFAULT { | 	TOK_DEFAULT { | ||||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT)); | 		ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT)); | ||||||
| 	} | | 	} | | ||||||
|  | 	TOK_SVA_LABEL { | ||||||
|  | 		ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER)); | ||||||
|  | 		ast_stack.back()->children.back()->str = *$1; | ||||||
|  | 		delete $1; | ||||||
|  | 	} | | ||||||
| 	expr { | 	expr { | ||||||
| 		ast_stack.back()->children.push_back($1); | 		ast_stack.back()->children.push_back($1); | ||||||
| 	} | | 	} | | ||||||
|  |  | ||||||
|  | @ -196,7 +196,11 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap) | ||||||
| 	if (log_hdump.count(header_id) && design != nullptr) | 	if (log_hdump.count(header_id) && design != nullptr) | ||||||
| 		for (auto &filename : log_hdump.at(header_id)) { | 		for (auto &filename : log_hdump.at(header_id)) { | ||||||
| 			log("Dumping current design to '%s'.\n", filename.c_str()); | 			log("Dumping current design to '%s'.\n", filename.c_str()); | ||||||
|  | 			if (yosys_xtrace) | ||||||
|  | 				IdString::xtrace_db_dump(); | ||||||
| 			Pass::call(design, {"dump", "-o", filename}); | 			Pass::call(design, {"dump", "-o", filename}); | ||||||
|  | 			if (yosys_xtrace) | ||||||
|  | 				log("#X# -- end of dump --\n"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	if (pop_errfile) | 	if (pop_errfile) | ||||||
|  |  | ||||||
|  | @ -86,6 +86,8 @@ Pass::pre_post_exec_state_t Pass::pre_execute() | ||||||
| 
 | 
 | ||||||
| void Pass::post_execute(Pass::pre_post_exec_state_t state) | void Pass::post_execute(Pass::pre_post_exec_state_t state) | ||||||
| { | { | ||||||
|  | 	IdString::checkpoint(); | ||||||
|  | 
 | ||||||
| 	int64_t time_ns = PerformanceTimer::query() - state.begin_ns; | 	int64_t time_ns = PerformanceTimer::query() - state.begin_ns; | ||||||
| 	runtime_ns += time_ns; | 	runtime_ns += time_ns; | ||||||
| 	current_pass = state.parent_pass; | 	current_pass = state.parent_pass; | ||||||
|  |  | ||||||
|  | @ -33,6 +33,8 @@ std::vector<int> RTLIL::IdString::global_refcount_storage_; | ||||||
| std::vector<char*> RTLIL::IdString::global_id_storage_; | std::vector<char*> RTLIL::IdString::global_id_storage_; | ||||||
| dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_; | dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_; | ||||||
| std::vector<int> RTLIL::IdString::global_free_idx_list_; | std::vector<int> RTLIL::IdString::global_free_idx_list_; | ||||||
|  | int RTLIL::IdString::last_created_idx_[8]; | ||||||
|  | int RTLIL::IdString::last_created_idx_ptr_; | ||||||
| 
 | 
 | ||||||
| RTLIL::Const::Const() | RTLIL::Const::Const() | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -76,6 +76,9 @@ namespace RTLIL | ||||||
| 
 | 
 | ||||||
| 	struct IdString | 	struct IdString | ||||||
| 	{ | 	{ | ||||||
|  | 		#undef YOSYS_XTRACE_GET_PUT | ||||||
|  | 		#undef YOSYS_SORT_ID_FREE_LIST | ||||||
|  | 
 | ||||||
| 		// the global id string cache
 | 		// the global id string cache
 | ||||||
| 
 | 
 | ||||||
| 		static struct destruct_guard_t { | 		static struct destruct_guard_t { | ||||||
|  | @ -89,9 +92,43 @@ namespace RTLIL | ||||||
| 		static dict<char*, int, hash_cstr_ops> global_id_index_; | 		static dict<char*, int, hash_cstr_ops> global_id_index_; | ||||||
| 		static std::vector<int> global_free_idx_list_; | 		static std::vector<int> global_free_idx_list_; | ||||||
| 
 | 
 | ||||||
|  | 		static int last_created_idx_ptr_; | ||||||
|  | 		static int last_created_idx_[8]; | ||||||
|  | 
 | ||||||
|  | 		static inline void xtrace_db_dump() | ||||||
|  | 		{ | ||||||
|  | 		#ifdef YOSYS_XTRACE_GET_PUT | ||||||
|  | 			for (int idx = 0; idx < GetSize(global_id_storage_); idx++) | ||||||
|  | 			{ | ||||||
|  | 				if (global_id_storage_.at(idx) == nullptr) | ||||||
|  | 					log("#X# DB-DUMP index %d: FREE\n", idx); | ||||||
|  | 				else | ||||||
|  | 					log("#X# DB-DUMP index %d: '%s' (ref %d)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx)); | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		static inline void checkpoint() | ||||||
|  | 		{ | ||||||
|  | 			last_created_idx_ptr_ = 0; | ||||||
|  | 			for (int i = 0; i < 8; i++) { | ||||||
|  | 				if (last_created_idx_[i]) | ||||||
|  | 					put_reference(last_created_idx_[i]); | ||||||
|  | 				last_created_idx_[i] = 0; | ||||||
|  | 			} | ||||||
|  | 		#ifdef YOSYS_SORT_ID_FREE_LIST | ||||||
|  | 			std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>()); | ||||||
|  | 		#endif | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		static inline int get_reference(int idx) | 		static inline int get_reference(int idx) | ||||||
| 		{ | 		{ | ||||||
| 			global_refcount_storage_.at(idx)++; | 			global_refcount_storage_.at(idx)++; | ||||||
|  | 		#ifdef YOSYS_XTRACE_GET_PUT | ||||||
|  | 			if (yosys_xtrace) { | ||||||
|  | 				log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx)); | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
| 			return idx; | 			return idx; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -107,6 +144,11 @@ namespace RTLIL | ||||||
| 			auto it = global_id_index_.find((char*)p); | 			auto it = global_id_index_.find((char*)p); | ||||||
| 			if (it != global_id_index_.end()) { | 			if (it != global_id_index_.end()) { | ||||||
| 				global_refcount_storage_.at(it->second)++; | 				global_refcount_storage_.at(it->second)++; | ||||||
|  | 		#ifdef YOSYS_XTRACE_GET_PUT | ||||||
|  | 				if (yosys_xtrace) { | ||||||
|  | 					log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second)); | ||||||
|  | 				} | ||||||
|  | 		#endif | ||||||
| 				return it->second; | 				return it->second; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -124,16 +166,22 @@ namespace RTLIL | ||||||
| 			global_refcount_storage_.at(idx)++; | 			global_refcount_storage_.at(idx)++; | ||||||
| 
 | 
 | ||||||
| 			// Avoid Create->Delete->Create pattern
 | 			// Avoid Create->Delete->Create pattern
 | ||||||
| 			static IdString last_created_id; | 			if (last_created_idx_[last_created_idx_ptr_]) | ||||||
| 			put_reference(last_created_id.index_); | 				put_reference(last_created_idx_[last_created_idx_ptr_]); | ||||||
| 			last_created_id.index_ = idx; | 			last_created_idx_[last_created_idx_ptr_] = idx; | ||||||
| 			get_reference(last_created_id.index_); | 			get_reference(last_created_idx_[last_created_idx_ptr_]); | ||||||
|  | 			last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7; | ||||||
| 
 | 
 | ||||||
| 			if (yosys_xtrace) { | 			if (yosys_xtrace) { | ||||||
| 				log("#X# New IdString '%s' with index %d.\n", p, idx); | 				log("#X# New IdString '%s' with index %d.\n", p, idx); | ||||||
| 				log_backtrace("-X- ", yosys_xtrace-1); | 				log_backtrace("-X- ", yosys_xtrace-1); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 		#ifdef YOSYS_XTRACE_GET_PUT | ||||||
|  | 			if (yosys_xtrace) { | ||||||
|  | 				log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx)); | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
| 			return idx; | 			return idx; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -144,6 +192,12 @@ namespace RTLIL | ||||||
| 			if (!destruct_guard.ok) | 			if (!destruct_guard.ok) | ||||||
| 				return; | 				return; | ||||||
| 
 | 
 | ||||||
|  | 		#ifdef YOSYS_XTRACE_GET_PUT | ||||||
|  | 			if (yosys_xtrace) { | ||||||
|  | 				log("#X# PUT '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx)); | ||||||
|  | 			} | ||||||
|  | 		#endif | ||||||
|  | 
 | ||||||
| 			log_assert(global_refcount_storage_.at(idx) > 0); | 			log_assert(global_refcount_storage_.at(idx) > 0); | ||||||
| 
 | 
 | ||||||
| 			if (--global_refcount_storage_.at(idx) != 0) | 			if (--global_refcount_storage_.at(idx) != 0) | ||||||
|  | @ -1282,7 +1336,7 @@ inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const { | ||||||
| 		return wire ? (offset < other.offset) : (data < other.data); | 		return wire ? (offset < other.offset) : (data < other.data); | ||||||
| 	if (wire != nullptr && other.wire != nullptr) | 	if (wire != nullptr && other.wire != nullptr) | ||||||
| 		return wire->name < other.wire->name; | 		return wire->name < other.wire->name; | ||||||
| 	return wire < other.wire; | 	return (wire != nullptr) < (other.wire != nullptr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const { | inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const { | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
| #  include <dlfcn.h> | #  include <dlfcn.h> | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef _WIN32 | #if defined(_WIN32) | ||||||
| #  include <windows.h> | #  include <windows.h> | ||||||
| #  include <io.h> | #  include <io.h> | ||||||
| #elif defined(__APPLE__) | #elif defined(__APPLE__) | ||||||
|  | @ -41,13 +41,15 @@ | ||||||
| #  include <unistd.h> | #  include <unistd.h> | ||||||
| #  include <dirent.h> | #  include <dirent.h> | ||||||
| #  include <sys/stat.h> | #  include <sys/stat.h> | ||||||
| #  include <glob.h> |  | ||||||
| #else | #else | ||||||
| #  include <unistd.h> | #  include <unistd.h> | ||||||
| #  include <dirent.h> | #  include <dirent.h> | ||||||
| #  include <sys/types.h> | #  include <sys/types.h> | ||||||
| #  include <sys/wait.h> | #  include <sys/wait.h> | ||||||
| #  include <sys/stat.h> | #  include <sys/stat.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB) | ||||||
| #  include <glob.h> | #  include <glob.h> | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -216,12 +218,18 @@ std::string next_token(std::string &text, const char *sep, bool long_strings) | ||||||
| 
 | 
 | ||||||
| 	if (long_strings && pos_begin != text.size() && text[pos_begin] == '"') { | 	if (long_strings && pos_begin != text.size() && text[pos_begin] == '"') { | ||||||
| 		string sep_string = sep; | 		string sep_string = sep; | ||||||
| 		for (size_t i = pos_begin+1; i < text.size(); i++) | 		for (size_t i = pos_begin+1; i < text.size(); i++) { | ||||||
| 			if (text[i] == '"' && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) { | 			if (text[i] == '"' && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) { | ||||||
| 				std::string token = text.substr(pos_begin, i-pos_begin+1); | 				std::string token = text.substr(pos_begin, i-pos_begin+1); | ||||||
| 				text = text.substr(i+1); | 				text = text.substr(i+1); | ||||||
| 				return token; | 				return token; | ||||||
| 			} | 			} | ||||||
|  | 			if (i+1 < text.size() && text[i] == '"' && text[i+1] == ';' && (i+2 == text.size() || sep_string.find(text[i+2]) != std::string::npos)) { | ||||||
|  | 				std::string token = text.substr(pos_begin, i-pos_begin+1); | ||||||
|  | 				text = text.substr(i+2); | ||||||
|  | 				return token + ";"; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	size_t pos_end = text.find_first_of(sep, pos_begin); | 	size_t pos_end = text.find_first_of(sep, pos_begin); | ||||||
|  | @ -564,7 +572,7 @@ std::vector<std::string> glob_filename(const std::string &filename_pattern) | ||||||
| { | { | ||||||
| 	std::vector<std::string> results; | 	std::vector<std::string> results; | ||||||
| 
 | 
 | ||||||
| #ifdef _WIN32 | #if defined(_WIN32) || !defined(YOSYS_ENABLE_GLOB) | ||||||
| 	results.push_back(filename_pattern); | 	results.push_back(filename_pattern); | ||||||
| #else | #else | ||||||
| 	glob_t globbuf; | 	glob_t globbuf; | ||||||
|  |  | ||||||
|  | @ -910,7 +910,7 @@ struct HierarchyPass : public Pass { | ||||||
| 			if (m == nullptr) | 			if (m == nullptr) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty()) { | 			if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) { | ||||||
| 				IdString new_m_name = m->derive(design, cell->parameters, true); | 				IdString new_m_name = m->derive(design, cell->parameters, true); | ||||||
| 				if (new_m_name.empty()) | 				if (new_m_name.empty()) | ||||||
| 					continue; | 					continue; | ||||||
|  |  | ||||||
|  | @ -53,6 +53,7 @@ struct WreduceWorker | ||||||
| 	std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells; | 	std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells; | ||||||
| 	std::set<SigBit> work_queue_bits; | 	std::set<SigBit> work_queue_bits; | ||||||
| 	pool<SigBit> keep_bits; | 	pool<SigBit> keep_bits; | ||||||
|  | 	dict<SigBit, State> init_bits; | ||||||
| 
 | 
 | ||||||
| 	WreduceWorker(WreduceConfig *config, Module *module) : | 	WreduceWorker(WreduceConfig *config, Module *module) : | ||||||
| 			config(config), module(module), mi(module) { } | 			config(config), module(module), mi(module) { } | ||||||
|  | @ -141,6 +142,7 @@ struct WreduceWorker | ||||||
| 
 | 
 | ||||||
| 		SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); | 		SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); | ||||||
| 		SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); | 		SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); | ||||||
|  | 		Const initval; | ||||||
| 
 | 
 | ||||||
| 		int width_before = GetSize(sig_q); | 		int width_before = GetSize(sig_q); | ||||||
| 
 | 
 | ||||||
|  | @ -150,16 +152,24 @@ struct WreduceWorker | ||||||
| 		bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; | 		bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; | ||||||
| 		bool sign_ext = !zero_ext; | 		bool sign_ext = !zero_ext; | ||||||
| 
 | 
 | ||||||
|  | 		for (int i = 0; i < GetSize(sig_q); i++) { | ||||||
|  | 			SigBit bit = sig_q[i]; | ||||||
|  | 			if (init_bits.count(bit)) | ||||||
|  | 				initval.bits.push_back(init_bits.at(bit)); | ||||||
|  | 			else | ||||||
|  | 				initval.bits.push_back(State::Sx); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		for (int i = GetSize(sig_q)-1; i >= 0; i--) | 		for (int i = GetSize(sig_q)-1; i >= 0; i--) | ||||||
| 		{ | 		{ | ||||||
| 			if (zero_ext && sig_d[i] == State::S0) { | 			if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) { | ||||||
| 				module->connect(sig_q[i], State::S0); | 				module->connect(sig_q[i], State::S0); | ||||||
| 				sig_d.remove(i); | 				sig_d.remove(i); | ||||||
| 				sig_q.remove(i); | 				sig_q.remove(i); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) { | 			if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) { | ||||||
| 				module->connect(sig_q[i], sig_q[i-1]); | 				module->connect(sig_q[i], sig_q[i-1]); | ||||||
| 				sig_d.remove(i); | 				sig_d.remove(i); | ||||||
| 				sig_q.remove(i); | 				sig_q.remove(i); | ||||||
|  | @ -167,7 +177,7 @@ struct WreduceWorker | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			auto info = mi.query(sig_q[i]); | 			auto info = mi.query(sig_q[i]); | ||||||
| 			if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { | 			if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { | ||||||
| 				sig_d.remove(i); | 				sig_d.remove(i); | ||||||
| 				sig_q.remove(i); | 				sig_q.remove(i); | ||||||
| 				zero_ext = false; | 				zero_ext = false; | ||||||
|  | @ -183,10 +193,11 @@ struct WreduceWorker | ||||||
| 
 | 
 | ||||||
| 		if (GetSize(sig_q) == 0) { | 		if (GetSize(sig_q) == 0) { | ||||||
| 			log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); | 			log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); | ||||||
|  | 			module->remove(cell); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, | 		log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, | ||||||
| 				log_id(module), log_id(cell), log_id(cell->type)); | 				log_id(module), log_id(cell), log_id(cell->type)); | ||||||
| 
 | 
 | ||||||
| 		for (auto bit : sig_d) | 		for (auto bit : sig_d) | ||||||
|  | @ -376,10 +387,18 @@ struct WreduceWorker | ||||||
| 
 | 
 | ||||||
| 	void run() | 	void run() | ||||||
| 	{ | 	{ | ||||||
| 		for (auto w : module->wires()) | 		for (auto w : module->wires()) { | ||||||
| 			if (w->get_bool_attribute("\\keep")) | 			if (w->get_bool_attribute("\\keep")) | ||||||
| 				for (auto bit : mi.sigmap(w)) | 				for (auto bit : mi.sigmap(w)) | ||||||
| 					keep_bits.insert(bit); | 					keep_bits.insert(bit); | ||||||
|  | 			if (w->attributes.count("\\init")) { | ||||||
|  | 				Const initval = w->attributes.at("\\init"); | ||||||
|  | 				SigSpec initsig = mi.sigmap(w); | ||||||
|  | 				int width = std::min(GetSize(initval), GetSize(initsig)); | ||||||
|  | 				for (int i = 0; i < width; i++) | ||||||
|  | 					init_bits[initsig[i]] = initval[i]; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto c : module->selected_cells()) | 		for (auto c : module->selected_cells()) | ||||||
| 			work_queue_cells.insert(c); | 			work_queue_cells.insert(c); | ||||||
|  |  | ||||||
|  | @ -4,5 +4,5 @@ passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h | ||||||
| EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h | EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h | ||||||
| .SECONDARY: passes/pmgen/ice40_dsp_pm.h | .SECONDARY: passes/pmgen/ice40_dsp_pm.h | ||||||
| 
 | 
 | ||||||
| passes/pmgen/ice40_dsp_pm.h: passes/pmgen/ice40_dsp.pmg passes/pmgen/pmgen.py | passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg | ||||||
| 	$(P) cd passes/pmgen && python3 pmgen.py ice40_dsp | 	$(P) mkdir -p passes/pmgen && python3 $^ $@ | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ API of Generated Matcher | ||||||
| ======================== | ======================== | ||||||
| 
 | 
 | ||||||
| When `pmgen.py` reads a `foobar.pmg` file, it writes `foobar_pm.h` containing | When `pmgen.py` reads a `foobar.pmg` file, it writes `foobar_pm.h` containing | ||||||
| a class `foobar_pm`. That class is instanciated with an RTLIL module and a | a class `foobar_pm`. That class is instantiated with an RTLIL module and a | ||||||
| list of cells from that module: | list of cells from that module: | ||||||
| 
 | 
 | ||||||
|     foobar_pm pm(module, module->selected_cells()); |     foobar_pm pm(module, module->selected_cells()); | ||||||
|  | @ -142,7 +142,7 @@ The `select` lines are evaluated once for each cell when the matcher is | ||||||
| initialized. A `match` block will only consider cells for which all `select` | initialized. A `match` block will only consider cells for which all `select` | ||||||
| expressions evaluated to `true`. Note that the state variable corresponding to | expressions evaluated to `true`. Note that the state variable corresponding to | ||||||
| the match (in the example `mul`) is the only state variable that may be used | the match (in the example `mul`) is the only state variable that may be used | ||||||
| `select` lines. | in `select` lines. | ||||||
| 
 | 
 | ||||||
| Index lines are using the `index <type> expr1 === expr2` syntax.  `expr1` is | Index lines are using the `index <type> expr1 === expr2` syntax.  `expr1` is | ||||||
| evaluated during matcher initialization and the same restrictions apply as for | evaluated during matcher initialization and the same restrictions apply as for | ||||||
|  |  | ||||||
|  | @ -6,7 +6,11 @@ import pprint | ||||||
| 
 | 
 | ||||||
| pp = pprint.PrettyPrinter(indent=4) | pp = pprint.PrettyPrinter(indent=4) | ||||||
| 
 | 
 | ||||||
| prefix = sys.argv[1] | pmgfile = sys.argv[1] | ||||||
|  | assert pmgfile.endswith(".pmg") | ||||||
|  | prefix = pmgfile[0:-4] | ||||||
|  | prefix = prefix.split('/')[-1] | ||||||
|  | outfile = sys.argv[2] | ||||||
| 
 | 
 | ||||||
| state_types = dict() | state_types = dict() | ||||||
| udata_types = dict() | udata_types = dict() | ||||||
|  | @ -73,7 +77,7 @@ def rewrite_cpp(s): | ||||||
| 
 | 
 | ||||||
|     return "".join(t) |     return "".join(t) | ||||||
| 
 | 
 | ||||||
| with open("%s.pmg" % prefix, "r") as f: | with open(pmgfile, "r") as f: | ||||||
|     while True: |     while True: | ||||||
|         line = f.readline() |         line = f.readline() | ||||||
|         if line == "": break |         if line == "": break | ||||||
|  | @ -176,7 +180,7 @@ with open("%s.pmg" % prefix, "r") as f: | ||||||
| 
 | 
 | ||||||
|             blocks.append(block) |             blocks.append(block) | ||||||
| 
 | 
 | ||||||
| with open("%s_pm.h" % prefix, "w") as f: | with open(outfile, "w") as f: | ||||||
|     print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f) |     print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f) | ||||||
|     print("", file=f) |     print("", file=f) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,4 +8,5 @@ OBJS += passes/sat/expose.o | ||||||
| OBJS += passes/sat/assertpmux.o | OBJS += passes/sat/assertpmux.o | ||||||
| OBJS += passes/sat/clk2fflogic.o | OBJS += passes/sat/clk2fflogic.o | ||||||
| OBJS += passes/sat/async2sync.o | OBJS += passes/sat/async2sync.o | ||||||
|  | OBJS += passes/sat/supercover.o | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ struct Async2syncPass : public Pass { | ||||||
| 		log("reset value in the next cycle regardless of the data-in value at the time of\n"); | 		log("reset value in the next cycle regardless of the data-in value at the time of\n"); | ||||||
| 		log("the clock edge.\n"); | 		log("the clock edge.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Currently only $adff cells are supported by this pass.\n"); | 		log("Currently only $adff and $dffsr cells are supported by this pass.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | @ -84,7 +84,7 @@ struct Async2syncPass : public Pass { | ||||||
| 					bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool(); | 					bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool(); | ||||||
| 					Const arst_val = cell->parameters["\\ARST_VALUE"]; | 					Const arst_val = cell->parameters["\\ARST_VALUE"]; | ||||||
| 
 | 
 | ||||||
| 					SigSpec sig_clk = cell->getPort("\\CLK"); | 					// SigSpec sig_clk = cell->getPort("\\CLK");
 | ||||||
| 					SigSpec sig_arst = cell->getPort("\\ARST"); | 					SigSpec sig_arst = cell->getPort("\\ARST"); | ||||||
| 					SigSpec sig_d = cell->getPort("\\D"); | 					SigSpec sig_d = cell->getPort("\\D"); | ||||||
| 					SigSpec sig_q = cell->getPort("\\Q"); | 					SigSpec sig_q = cell->getPort("\\Q"); | ||||||
|  | @ -120,6 +120,55 @@ struct Async2syncPass : public Pass { | ||||||
| 					cell->type = "$dff"; | 					cell->type = "$dff"; | ||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
|  | 				if (cell->type.in("$dffsr")) | ||||||
|  | 				{ | ||||||
|  | 					// bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool();
 | ||||||
|  | 					bool set_pol = cell->parameters["\\SET_POLARITY"].as_bool(); | ||||||
|  | 					bool clr_pol = cell->parameters["\\CLR_POLARITY"].as_bool(); | ||||||
|  | 
 | ||||||
|  | 					// SigSpec sig_clk = cell->getPort("\\CLK");
 | ||||||
|  | 					SigSpec sig_set = cell->getPort("\\SET"); | ||||||
|  | 					SigSpec sig_clr = cell->getPort("\\CLR"); | ||||||
|  | 					SigSpec sig_d = cell->getPort("\\D"); | ||||||
|  | 					SigSpec sig_q = cell->getPort("\\Q"); | ||||||
|  | 
 | ||||||
|  | 					log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n", | ||||||
|  | 							log_id(module), log_id(cell), log_id(cell->type), | ||||||
|  | 							log_signal(sig_set), log_signal(sig_clr), log_signal(sig_d), log_signal(sig_q)); | ||||||
|  | 
 | ||||||
|  | 					Const init_val; | ||||||
|  | 					for (int i = 0; i < GetSize(sig_q); i++) { | ||||||
|  | 						SigBit bit = sigmap(sig_q[i]); | ||||||
|  | 						init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx); | ||||||
|  | 						del_initbits.insert(bit); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d)); | ||||||
|  | 					Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); | ||||||
|  | 					new_q->attributes["\\init"] = init_val; | ||||||
|  | 
 | ||||||
|  | 					if (!set_pol) | ||||||
|  | 						sig_set = module->Not(NEW_ID, sig_set); | ||||||
|  | 
 | ||||||
|  | 					if (clr_pol) | ||||||
|  | 						sig_clr = module->Not(NEW_ID, sig_clr); | ||||||
|  | 
 | ||||||
|  | 					SigSpec tmp = module->Or(NEW_ID, sig_d, sig_set); | ||||||
|  | 					module->addAnd(NEW_ID, tmp, sig_clr, new_d); | ||||||
|  | 
 | ||||||
|  | 					tmp = module->Or(NEW_ID, new_q, sig_set); | ||||||
|  | 					module->addAnd(NEW_ID, tmp, sig_clr, sig_q); | ||||||
|  | 
 | ||||||
|  | 					cell->setPort("\\D", new_d); | ||||||
|  | 					cell->setPort("\\Q", new_q); | ||||||
|  | 					cell->unsetPort("\\SET"); | ||||||
|  | 					cell->unsetPort("\\CLR"); | ||||||
|  | 					cell->unsetParam("\\SET_POLARITY"); | ||||||
|  | 					cell->unsetParam("\\CLR_POLARITY"); | ||||||
|  | 					cell->type = "$dff"; | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			for (auto wire : module->wires()) | 			for (auto wire : module->wires()) | ||||||
|  |  | ||||||
							
								
								
									
										92
									
								
								passes/sat/supercover.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								passes/sat/supercover.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | ||||||
|  | /*
 | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "kernel/yosys.h" | ||||||
|  | #include "kernel/sigtools.h" | ||||||
|  | 
 | ||||||
|  | USING_YOSYS_NAMESPACE | ||||||
|  | PRIVATE_NAMESPACE_BEGIN | ||||||
|  | 
 | ||||||
|  | struct SupercoverPass : public Pass { | ||||||
|  | 	SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { } | ||||||
|  | 	void help() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    supercover [options] [selection]\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("This command adds two cover cells for each bit of each selected wire, one\n"); | ||||||
|  | 		log("checking for a hi signal level and one checking for lo level.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 	} | ||||||
|  | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		// bool flag_noinit = false;
 | ||||||
|  | 
 | ||||||
|  | 		log_header(design, "Executing SUPERCOVER pass.\n"); | ||||||
|  | 
 | ||||||
|  | 		size_t argidx; | ||||||
|  | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
|  | 		{ | ||||||
|  | 			// if (args[argidx] == "-noinit") {
 | ||||||
|  | 			// 	flag_noinit = true;
 | ||||||
|  | 			// 	continue;
 | ||||||
|  | 			// }
 | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		extra_args(args, argidx, design); | ||||||
|  | 
 | ||||||
|  | 		for (auto module : design->selected_modules()) | ||||||
|  | 		{ | ||||||
|  | 			SigMap sigmap(module); | ||||||
|  | 			pool<SigBit> handled_bits; | ||||||
|  | 
 | ||||||
|  | 			int cnt_wire = 0, cnt_bits = 0; | ||||||
|  | 			log("Adding cover cells to module %s.\n", log_id(module)); | ||||||
|  | 			for (auto wire : module->selected_wires()) | ||||||
|  | 			{ | ||||||
|  | 				bool counted_wire = false; | ||||||
|  | 				std::string src = wire->get_src_attribute(); | ||||||
|  | 
 | ||||||
|  | 				for (auto bit : sigmap(SigSpec(wire))) | ||||||
|  | 				{ | ||||||
|  | 					if (bit.wire == nullptr) | ||||||
|  | 						continue; | ||||||
|  | 
 | ||||||
|  | 					if (handled_bits.count(bit)) | ||||||
|  | 						continue; | ||||||
|  | 
 | ||||||
|  | 					SigSpec inv = module->Not(NEW_ID, bit); | ||||||
|  | 					module->addCover(NEW_ID, bit, State::S1, src); | ||||||
|  | 					module->addCover(NEW_ID, inv, State::S1, src); | ||||||
|  | 
 | ||||||
|  | 					handled_bits.insert(bit); | ||||||
|  | 					if (!counted_wire) { | ||||||
|  | 						counted_wire = false; | ||||||
|  | 						cnt_wire++; | ||||||
|  | 					} | ||||||
|  | 					cnt_bits++; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			log("  added cover cells to %d wires, %d bits.\n", cnt_wire, cnt_bits); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } SupercoverPass; | ||||||
|  | 
 | ||||||
|  | PRIVATE_NAMESPACE_END | ||||||
|  | @ -660,8 +660,8 @@ struct DfflibmapPass : public Pass { | ||||||
| 		map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_"); | 		map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_"); | ||||||
| 		map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_"); | 		map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_"); | ||||||
| 
 | 
 | ||||||
|  		log("  final dff cell mappings:\n"); | 		log("  final dff cell mappings:\n"); | ||||||
|  		logmap_all(); | 		logmap_all(); | ||||||
| 
 | 
 | ||||||
| 		for (auto &it : design->modules_) | 		for (auto &it : design->modules_) | ||||||
| 			if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox")) | 			if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox")) | ||||||
|  |  | ||||||
|  | @ -132,9 +132,9 @@ static void dump_dot_graph(string filename, | ||||||
|                            pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges, |                            pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges, | ||||||
|                            pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs, |                            pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs, | ||||||
|                            std::function<GraphStyle(RTLIL::SigBit)> node_style = |                            std::function<GraphStyle(RTLIL::SigBit)> node_style = | ||||||
|                            		[](RTLIL::SigBit) { return GraphStyle{}; }, |                                    [](RTLIL::SigBit) { return GraphStyle{}; }, | ||||||
|                            std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style = |                            std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style = | ||||||
|                            		[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, |                                    [](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, | ||||||
|                            string name = "") |                            string name = "") | ||||||
| { | { | ||||||
| 	FILE *f = fopen(filename.c_str(), "w"); | 	FILE *f = fopen(filename.c_str(), "w"); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| 
 | 
 | ||||||
| OBJS += techlibs/ecp5/synth_ecp5.o | OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o | ||||||
| 
 | 
 | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) | $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) | $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO); | ||||||
| 	input CI, BI; | 	input CI, BI; | ||||||
| 	output [Y_WIDTH-1:0] CO; | 	output [Y_WIDTH-1:0] CO; | ||||||
| 
 | 
 | ||||||
| 	wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; | 	wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; | ||||||
| 
 | 
 | ||||||
| 	wire [Y_WIDTH-1:0] A_buf, B_buf; | 	wire [Y_WIDTH-1:0] A_buf, B_buf; | ||||||
| 	\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); | 	\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); | ||||||
|  |  | ||||||
|  | @ -156,6 +156,41 @@ module OSCG( | ||||||
| parameter DIV = 128; | parameter DIV = 128; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* blackbox *) (* keep *) | ||||||
|  | module USRMCLK( | ||||||
|  | 	input USRMCLKI, USRMCLKTS, | ||||||
|  | 	output USRMCLKO | ||||||
|  | ); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) (* keep *) | ||||||
|  | module JTAGG( | ||||||
|  | 	input TCK, TMS, TDI, JTDO2, JTDO1, | ||||||
|  | 	output TDO, JTDI, JTCK, JRTI2, JRTI1, | ||||||
|  | 	output JSHIFT, JUPDATE, JRSTN, JCE2, JCE1 | ||||||
|  | ); | ||||||
|  | parameter ER1 = "ENABLED"; | ||||||
|  | parameter ER2 = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module DELAYF( | ||||||
|  | 	input A, LOADN, MOVE, DIRECTION, | ||||||
|  | 	output Z, CFLAG | ||||||
|  | ); | ||||||
|  | 	parameter DEL_MODE = "USER_DEFINED"; | ||||||
|  | 	parameter DEL_VALUE = 0; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module DELAYG( | ||||||
|  | 	input A, | ||||||
|  | 	output Z | ||||||
|  | ); | ||||||
|  | 	parameter DEL_MODE = "USER_DEFINED"; | ||||||
|  | 	parameter DEL_VALUE = 0; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| (* blackbox *) | (* blackbox *) | ||||||
| module IDDRX1F( | module IDDRX1F( | ||||||
| 	input D, SCLK, RST, | 	input D, SCLK, RST, | ||||||
|  | @ -164,6 +199,31 @@ module IDDRX1F( | ||||||
| 	parameter GSR = "ENABLED"; | 	parameter GSR = "ENABLED"; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module IDDRX2F( | ||||||
|  | 	input D, SCLK, ECLK, RST, | ||||||
|  | 	output Q0, Q1, Q2, Q3 | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module IDDR71B( | ||||||
|  | 	input D, SCLK, ECLK, RST, ALIGNWD, | ||||||
|  | 	output Q0, Q1, Q2, Q3, Q4, Q5, Q6 | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module IDDRX2DQA( | ||||||
|  | 	input D, DQSR90, ECLK, SCLK, RST, | ||||||
|  | 	input RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0, | ||||||
|  | 	output Q0, Q1, Q2, Q3, QWL | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| (* blackbox *) | (* blackbox *) | ||||||
| module ODDRX1F( | module ODDRX1F( | ||||||
| 	input SCLK, RST, D0, D1, | 	input SCLK, RST, D0, D1, | ||||||
|  | @ -172,6 +232,91 @@ module ODDRX1F( | ||||||
| 	parameter GSR = "ENABLED"; | 	parameter GSR = "ENABLED"; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module ODDRX2F( | ||||||
|  | 	input SCLK, ECLK, RST, D0, D1, D2, D3, | ||||||
|  | 	output Q | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module ODDR71B( | ||||||
|  | 	input SCLK, ECLK, RST, D0, D1, D2, D3, D4, D5, D6, | ||||||
|  | 	output Q | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module OSHX2A( | ||||||
|  | 	input D0, D1, RST, ECLK, SCLK, | ||||||
|  | 	output Q | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module ODDRX2DQA( | ||||||
|  | 	input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW270, | ||||||
|  | 	output Q | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module ODDRX2DQSB( | ||||||
|  | 	input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW, | ||||||
|  | 	output Q | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module TSHX2DQA( | ||||||
|  | 	input T0, T1, SCLK, ECLK, DQSW270, RST, | ||||||
|  | 	output Q | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | 	parameter REGSET = "SET"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module TSHX2DQSA( | ||||||
|  | 	input T0, T1, SCLK, ECLK, DQSW, RST, | ||||||
|  | 	output Q | ||||||
|  | ); | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | 	parameter REGSET = "SET"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module DQSBUFM( | ||||||
|  | 	input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL, | ||||||
|  | 	input ECLK, SCLK, | ||||||
|  | 	input DYNDELAY7, DYNDELAY6, DYNDELAY5, DYNDELAY4, | ||||||
|  | 	input DYNDELAY3, DYNDELAY2, DYNDELAY1, DYNDELAY0,  | ||||||
|  | 	input RST, RDLOADN, RDMOVE, RDDIRECTION, WRLOADN, WRMOVE, WRDIRECTION, PAUSE, | ||||||
|  | 	output DQSR90, DQSW, DQSW270, | ||||||
|  | 	output RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0, | ||||||
|  | 	output DATAVALID, BURSTDET, RDCFLAG, WRCFLAG | ||||||
|  | ); | ||||||
|  | 	parameter DQS_LI_DEL_ADJ = "FACTORYONLY"; | ||||||
|  | 	parameter DQS_LI_DEL_VAL = 0; | ||||||
|  | 	parameter DQS_LO_DEL_ADJ = "FACTORYONLY"; | ||||||
|  | 	parameter DQS_LO_DEL_VAL = 0; | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module DDRDLLA( | ||||||
|  | 	input CLK, RST, UDDCNTLN, FREEZE, | ||||||
|  | 	output LOCK, DDRDEL, DCNTL7, DCNTL6, DCNTL5, DCNTL4, DCNTL3, DCNTL2, DCNTL1, DCNTL0 | ||||||
|  | ); | ||||||
|  | 	parameter FORCE_MAX_DELAY = "NO"; | ||||||
|  | 	parameter GSR = "ENABLED"; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| (* blackbox *) | (* blackbox *) | ||||||
| module CLKDIVF( | module CLKDIVF( | ||||||
| 	input CLKI, RST, ALIGNWD, | 	input CLKI, RST, ALIGNWD, | ||||||
|  | @ -181,6 +326,13 @@ module CLKDIVF( | ||||||
| 	parameter DIV = "2.0"; | 	parameter DIV = "2.0"; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module ECLKSYNCB( | ||||||
|  | 	input ECLKI, STOP, | ||||||
|  | 	output ECLKO | ||||||
|  | ); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| (* blackbox *) | (* blackbox *) | ||||||
| module DCCA( | module DCCA( | ||||||
| 	input CLKI, CE, | 	input CLKI, CE, | ||||||
|  |  | ||||||
|  | @ -47,6 +47,9 @@ 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 | ||||||
| 
 | 
 | ||||||
|  | // 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 | ||||||
|  | 
 | ||||||
| `ifndef NO_LUT | `ifndef NO_LUT | ||||||
| module \$lut (A, Y); | module \$lut (A, Y); | ||||||
|     parameter WIDTH = 0; |     parameter WIDTH = 0; | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ module TRELLIS_RAM16X2 ( | ||||||
| 	input RAD0, RAD1, RAD2, RAD3, | 	input RAD0, RAD1, RAD2, RAD3, | ||||||
| 	output DO0, DO1 | 	output DO0, DO1 | ||||||
| ); | ); | ||||||
|   	parameter WCKMUX = "WCK"; | 	parameter WCKMUX = "WCK"; | ||||||
| 	parameter WREMUX = "WRE"; | 	parameter WREMUX = "WRE"; | ||||||
| 	parameter INITVAL_0 = 16'h0000; | 	parameter INITVAL_0 = 16'h0000; | ||||||
| 	parameter INITVAL_1 = 16'h0000; | 	parameter INITVAL_1 = 16'h0000; | ||||||
|  | @ -104,7 +104,7 @@ module TRELLIS_DPR16X4 ( | ||||||
| 	input [3:0] RAD, | 	input [3:0] RAD, | ||||||
| 	output [3:0] DO | 	output [3:0] DO | ||||||
| ); | ); | ||||||
|   	parameter WCKMUX = "WCK"; | 	parameter WCKMUX = "WCK"; | ||||||
| 	parameter WREMUX = "WRE"; | 	parameter WREMUX = "WRE"; | ||||||
| 	parameter [63:0] INITVAL = 64'h0000000000000000; | 	parameter [63:0] INITVAL = 64'h0000000000000000; | ||||||
| 
 | 
 | ||||||
|  | @ -203,13 +203,14 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------- | // --------------------------------------- | ||||||
| 
 | 
 | ||||||
| module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q); | module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); | ||||||
| 	parameter GSR = "ENABLED"; | 	parameter GSR = "ENABLED"; | ||||||
| 	parameter [127:0] CEMUX = "1"; | 	parameter [127:0] CEMUX = "1"; | ||||||
| 	parameter CLKMUX = "CLK"; | 	parameter CLKMUX = "CLK"; | ||||||
| 	parameter LSRMUX = "LSR"; | 	parameter LSRMUX = "LSR"; | ||||||
| 	parameter SRMODE = "LSR_OVER_CE"; | 	parameter SRMODE = "LSR_OVER_CE"; | ||||||
| 	parameter REGSET = "RESET"; | 	parameter REGSET = "RESET"; | ||||||
|  | 	parameter [127:0] LSRMODE = "LSR"; | ||||||
| 
 | 
 | ||||||
| 	reg muxce; | 	reg muxce; | ||||||
| 	always @(*) | 	always @(*) | ||||||
|  | @ -222,8 +223,13 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q); | ||||||
| 
 | 
 | ||||||
| 	wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR; | 	wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR; | ||||||
| 	wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK; | 	wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK; | ||||||
| 
 | 	wire srval; | ||||||
| 	localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0; | 	generate | ||||||
|  | 		if (LSRMODE == "PRLD") | ||||||
|  | 			assign srval = M; | ||||||
|  | 		else | ||||||
|  | 			assign srval = (REGSET == "SET") ? 1'b1 : 1'b0; | ||||||
|  | 	endgenerate | ||||||
| 
 | 
 | ||||||
| 	initial Q = srval; | 	initial Q = srval; | ||||||
| 
 | 
 | ||||||
|  | @ -339,6 +345,8 @@ module TRELLIS_SLICE( | ||||||
| 	parameter REG1_SD = "0"; | 	parameter REG1_SD = "0"; | ||||||
| 	parameter REG0_REGSET = "RESET"; | 	parameter REG0_REGSET = "RESET"; | ||||||
| 	parameter REG1_REGSET = "RESET"; | 	parameter REG1_REGSET = "RESET"; | ||||||
|  | 	parameter REG0_LSRMODE = "LSR"; | ||||||
|  | 	parameter REG1_LSRMODE = "LSR"; | ||||||
| 	parameter [127:0] CCU2_INJECT1_0 = "NO"; | 	parameter [127:0] CCU2_INJECT1_0 = "NO"; | ||||||
| 	parameter [127:0] CCU2_INJECT1_1 = "NO"; | 	parameter [127:0] CCU2_INJECT1_1 = "NO"; | ||||||
| 	parameter WREMUX = "WRE"; | 	parameter WREMUX = "WRE"; | ||||||
|  | @ -428,10 +436,11 @@ module TRELLIS_SLICE( | ||||||
| 		.CLKMUX(CLKMUX), | 		.CLKMUX(CLKMUX), | ||||||
| 		.LSRMUX(LSRMUX), | 		.LSRMUX(LSRMUX), | ||||||
| 		.SRMODE(SRMODE), | 		.SRMODE(SRMODE), | ||||||
| 		.REGSET(REG0_REGSET) | 		.REGSET(REG0_REGSET), | ||||||
|  | 		.LSRMODE(REG0_LSRMODE) | ||||||
| 	) ff_0 ( | 	) ff_0 ( | ||||||
| 		.CLK(CLK), .LSR(LSR), .CE(CE), | 		.CLK(CLK), .LSR(LSR), .CE(CE), | ||||||
| 		.DI(muxdi0), | 		.DI(muxdi0), .M(M0), | ||||||
| 		.Q(Q0) | 		.Q(Q0) | ||||||
| 	); | 	); | ||||||
| 	TRELLIS_FF #( | 	TRELLIS_FF #( | ||||||
|  | @ -440,10 +449,11 @@ module TRELLIS_SLICE( | ||||||
| 		.CLKMUX(CLKMUX), | 		.CLKMUX(CLKMUX), | ||||||
| 		.LSRMUX(LSRMUX), | 		.LSRMUX(LSRMUX), | ||||||
| 		.SRMODE(SRMODE), | 		.SRMODE(SRMODE), | ||||||
| 		.REGSET(REG1_REGSET) | 		.REGSET(REG1_REGSET), | ||||||
|  | 		.LSRMODE(REG1_LSRMODE) | ||||||
| 	) ff_1 ( | 	) ff_1 ( | ||||||
| 		.CLK(CLK), .LSR(LSR), .CE(CE), | 		.CLK(CLK), .LSR(LSR), .CE(CE), | ||||||
| 		.DI(muxdi1), | 		.DI(muxdi1), .M(M1), | ||||||
| 		.Q(Q1) | 		.Q(Q1) | ||||||
| 	); | 	); | ||||||
| endmodule | endmodule | ||||||
|  | @ -547,3 +557,20 @@ module DP16KD( | ||||||
|   parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; |   parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; | ||||||
|   parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; |   parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; | ||||||
| endmodule | 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") | ||||||
|  | 	) tff_i ( | ||||||
|  | 		.CLK(CK), | ||||||
|  | 		.LSR(PD), | ||||||
|  | 		.DI(D), | ||||||
|  | 		.Q(Q) | ||||||
|  | 	); | ||||||
|  | endmodule | ||||||
|  |  | ||||||
							
								
								
									
										203
									
								
								techlibs/ecp5/ecp5_ffinit.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								techlibs/ecp5/ecp5_ffinit.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,203 @@ | ||||||
|  | /*
 | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  *  Copyright (C) 2018-19  David Shah <david@symbioticeda.com> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "kernel/yosys.h" | ||||||
|  | #include "kernel/sigtools.h" | ||||||
|  | 
 | ||||||
|  | USING_YOSYS_NAMESPACE | ||||||
|  | PRIVATE_NAMESPACE_BEGIN | ||||||
|  | 
 | ||||||
|  | struct Ecp5FfinitPass : public Pass { | ||||||
|  | 	Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { } | ||||||
|  | 	void help() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    ecp5_ffinit [options] [selection]\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("Remove init values for FF output signals when equal to reset value.\n"); | ||||||
|  | 		log("If reset is not used, set the reset value to the init value, otherwise\n"); | ||||||
|  | 		log("unmap out the reset (if not an async reset).\n"); | ||||||
|  | 	} | ||||||
|  | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\n"); | ||||||
|  | 
 | ||||||
|  | 		size_t argidx; | ||||||
|  | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
|  | 		{ | ||||||
|  | 			// if (args[argidx] == "-singleton") {
 | ||||||
|  | 			// 	singleton_mode = true;
 | ||||||
|  | 			// 	continue;
 | ||||||
|  | 			// }
 | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		extra_args(args, argidx, design); | ||||||
|  | 
 | ||||||
|  | 		for (auto module : design->selected_modules()) | ||||||
|  | 		{ | ||||||
|  | 			log("Handling FF init values in %s.\n", log_id(module)); | ||||||
|  | 
 | ||||||
|  | 			SigMap sigmap(module); | ||||||
|  | 			pool<Wire*> init_wires; | ||||||
|  | 			dict<SigBit, State> initbits; | ||||||
|  | 			dict<SigBit, SigBit> initbit_to_wire; | ||||||
|  | 			pool<SigBit> handled_initbits; | ||||||
|  | 
 | ||||||
|  | 			for (auto wire : module->selected_wires()) | ||||||
|  | 			{ | ||||||
|  | 				if (wire->attributes.count("\\init") == 0) | ||||||
|  | 					continue; | ||||||
|  | 
 | ||||||
|  | 				SigSpec wirebits = sigmap(wire); | ||||||
|  | 				Const initval = wire->attributes.at("\\init"); | ||||||
|  | 				init_wires.insert(wire); | ||||||
|  | 
 | ||||||
|  | 				for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) | ||||||
|  | 				{ | ||||||
|  | 					SigBit bit = wirebits[i]; | ||||||
|  | 					State val = initval[i]; | ||||||
|  | 
 | ||||||
|  | 					if (val != State::S0 && val != State::S1) | ||||||
|  | 						continue; | ||||||
|  | 
 | ||||||
|  | 					if (initbits.count(bit)) { | ||||||
|  | 						if (initbits.at(bit) != val) { | ||||||
|  | 							log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n", | ||||||
|  | 									log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val), | ||||||
|  | 									log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit))); | ||||||
|  | 							initbits.at(bit) = State::Sx; | ||||||
|  | 						} | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					initbits[bit] = val; | ||||||
|  | 					initbit_to_wire[bit] = SigBit(wire, i); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			for (auto cell : module->selected_cells()) | ||||||
|  | 			{ | ||||||
|  | 				if (cell->type != "\\TRELLIS_FF") | ||||||
|  | 					continue; | ||||||
|  | 				SigSpec sig_d = cell->getPort("\\DI"); | ||||||
|  | 				SigSpec sig_q = cell->getPort("\\Q"); | ||||||
|  | 				SigSpec sig_lsr = cell->getPort("\\LSR"); | ||||||
|  | 
 | ||||||
|  | 				if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1) | ||||||
|  | 					continue; | ||||||
|  | 
 | ||||||
|  | 				SigBit bit_d = sigmap(sig_d[0]); | ||||||
|  | 				SigBit bit_q = sigmap(sig_q[0]); | ||||||
|  | 
 | ||||||
|  | 				std::string regset = "RESET"; | ||||||
|  | 				if (cell->hasParam("\\REGSET")) | ||||||
|  | 					regset = cell->getParam("\\REGSET").decode_string(); | ||||||
|  | 				State resetState; | ||||||
|  | 				if (regset == "SET") | ||||||
|  | 					resetState = State::S1; | ||||||
|  | 				else if (regset == "RESET") | ||||||
|  | 					resetState = State::S0; | ||||||
|  | 				else | ||||||
|  | 					log_error("FF cell %s has illegal REGSET value %s.\n", | ||||||
|  | 						log_id(cell), regset.c_str()); | ||||||
|  | 
 | ||||||
|  | 				if (!initbits.count(bit_q)) | ||||||
|  | 					continue; | ||||||
|  | 
 | ||||||
|  | 				State val = initbits.at(bit_q); | ||||||
|  | 
 | ||||||
|  | 				if (val == State::Sx) | ||||||
|  | 					continue; | ||||||
|  | 
 | ||||||
|  | 				log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type), | ||||||
|  | 						log_signal(bit_q), val != State::S0 ? '1' : '0'); | ||||||
|  | 				// Initval is the same as the reset state. Matches hardware, nowt more to do
 | ||||||
|  | 				if (val == resetState) { | ||||||
|  | 					handled_initbits.insert(bit_q); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) { | ||||||
|  | 					std::string srmode = "LSR_OVER_CE"; | ||||||
|  | 					if (cell->hasParam("\\SRMODE")) | ||||||
|  | 						srmode = cell->getParam("\\SRMODE").decode_string(); | ||||||
|  | 					if (srmode == "ASYNC") { | ||||||
|  | 						log("Async reset value %c for FF cell %s inconsistent with init value %c.\n", | ||||||
|  | 							resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0'); | ||||||
|  | 					} else { | ||||||
|  | 						SigBit bit_lsr = sigmap(sig_lsr[0]); | ||||||
|  | 						Wire *new_bit_d = module->addWire(NEW_ID); | ||||||
|  | 						if (resetState == State::S0) { | ||||||
|  | 							module->addAndnotGate(NEW_ID, bit_d, bit_lsr, new_bit_d); | ||||||
|  | 						} else { | ||||||
|  | 							module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d); | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						cell->setPort("\\DI", new_bit_d); | ||||||
|  | 						cell->setPort("\\LSR", State::S0); | ||||||
|  | 
 | ||||||
|  | 						if(cell->hasPort("\\CE")) { | ||||||
|  | 							std::string cemux = "CE"; | ||||||
|  | 							if (cell->hasParam("\\CEMUX")) | ||||||
|  | 								cemux = cell->getParam("\\CEMUX").decode_string(); | ||||||
|  | 							SigSpec sig_ce = cell->getPort("\\CE"); | ||||||
|  | 							if (GetSize(sig_ce) >= 1) { | ||||||
|  | 								SigBit bit_ce = sigmap(sig_ce[0]); | ||||||
|  | 								Wire *new_bit_ce = module->addWire(NEW_ID); | ||||||
|  | 								if (cemux == "INV") | ||||||
|  | 									module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); | ||||||
|  | 								else | ||||||
|  | 									module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); | ||||||
|  | 								cell->setPort("\\CE", new_bit_ce); | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 						cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); | ||||||
|  | 						handled_initbits.insert(bit_q); | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); | ||||||
|  | 					handled_initbits.insert(bit_q); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			for (auto wire : init_wires) | ||||||
|  | 			{ | ||||||
|  | 				if (wire->attributes.count("\\init") == 0) | ||||||
|  | 					continue; | ||||||
|  | 
 | ||||||
|  | 				SigSpec wirebits = sigmap(wire); | ||||||
|  | 				Const &initval = wire->attributes.at("\\init"); | ||||||
|  | 				bool remove_attribute = true; | ||||||
|  | 
 | ||||||
|  | 				for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { | ||||||
|  | 					if (handled_initbits.count(wirebits[i])) | ||||||
|  | 						initval[i] = State::Sx; | ||||||
|  | 					else if (initval[i] != State::Sx) | ||||||
|  | 						remove_attribute = false; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (remove_attribute) | ||||||
|  | 					wire->attributes.erase("\\init"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } Ecp5FfinitPass; | ||||||
|  | 
 | ||||||
|  | PRIVATE_NAMESPACE_END | ||||||
|  | @ -255,10 +255,7 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 			run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); | 			run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); | ||||||
| 			run("opt_expr -mux_undef"); | 			run("opt_expr -mux_undef"); | ||||||
| 			run("simplemap"); | 			run("simplemap"); | ||||||
| 			// TODO
 |  | ||||||
| #if 0 |  | ||||||
| 			run("ecp5_ffinit"); | 			run("ecp5_ffinit"); | ||||||
| #endif |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map_luts")) | 		if (check_label("map_luts")) | ||||||
|  |  | ||||||
|  | @ -112,14 +112,14 @@ module GP_OBUFT(input IN, input OE, output OUT); | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module \$lut (A, Y); | module \$lut (A, Y); | ||||||
|   parameter WIDTH = 0; | 	parameter WIDTH = 0; | ||||||
|   parameter LUT = 0; | 	parameter LUT = 0; | ||||||
| 
 | 
 | ||||||
|   input [WIDTH-1:0] A; | 	input [WIDTH-1:0] A; | ||||||
|   output Y; | 	output Y; | ||||||
| 
 | 
 | ||||||
|   generate | 	generate | ||||||
|     if (WIDTH == 1) begin | 		if (WIDTH == 1) begin | ||||||
| 		if(LUT == 2'b01) begin | 		if(LUT == 2'b01) begin | ||||||
| 			GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) ); | 			GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) ); | ||||||
| 		end | 		end | ||||||
|  | @ -127,22 +127,22 @@ module \$lut (A, Y); | ||||||
| 			GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y), | 			GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y), | ||||||
| 				.IN0(A[0]), .IN1(1'b0)); | 				.IN0(A[0]), .IN1(1'b0)); | ||||||
| 		end | 		end | ||||||
|     end else | 		end else | ||||||
|     if (WIDTH == 2) begin | 		if (WIDTH == 2) begin | ||||||
|       GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | 			GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||||
|       	.IN0(A[0]), .IN1(A[1])); | 				.IN0(A[0]), .IN1(A[1])); | ||||||
|     end else | 		end else | ||||||
|     if (WIDTH == 3) begin | 		if (WIDTH == 3) begin | ||||||
|       GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | 			GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||||
|       	.IN0(A[0]), .IN1(A[1]), .IN2(A[2])); | 				.IN0(A[0]), .IN1(A[1]), .IN2(A[2])); | ||||||
|     end else | 		end else | ||||||
|     if (WIDTH == 4) begin | 		if (WIDTH == 4) begin | ||||||
|       GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | 			GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||||
|       	.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3])); | 				.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3])); | ||||||
|     end else begin | 		end else begin | ||||||
|       wire _TECHMAP_FAIL_ = 1; | 			wire _TECHMAP_FAIL_ = 1; | ||||||
|     end | 		end | ||||||
|   endgenerate | 	endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP); | module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| 
 | 
 | ||||||
| OBJS += techlibs/ice40/synth_ice40.o | OBJS += techlibs/ice40/synth_ice40.o | ||||||
|  | OBJS += techlibs/ice40/ice40_braminit.o | ||||||
| OBJS += techlibs/ice40/ice40_ffssr.o | OBJS += techlibs/ice40/ice40_ffssr.o | ||||||
| OBJS += techlibs/ice40/ice40_ffinit.o | OBJS += techlibs/ice40/ice40_ffinit.o | ||||||
| OBJS += techlibs/ice40/ice40_opt.o | OBJS += techlibs/ice40/ice40_opt.o | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ module \$__ICE40_RAM4K ( | ||||||
| 	input  [10:0] WADDR, | 	input  [10:0] WADDR, | ||||||
| 	input  [15:0] MASK, WDATA | 	input  [15:0] MASK, WDATA | ||||||
| ); | ); | ||||||
| 	parameter integer READ_MODE = 0; | 	parameter [1:0] READ_MODE = 0; | ||||||
| 	parameter integer WRITE_MODE = 0; | 	parameter [1:0] WRITE_MODE = 0; | ||||||
| 	parameter [0:0] NEGCLK_R = 0; | 	parameter [0:0] NEGCLK_R = 0; | ||||||
| 	parameter [0:0] NEGCLK_W = 0; | 	parameter [0:0] NEGCLK_W = 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -326,6 +326,8 @@ module SB_RAM40_4K ( | ||||||
| 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 
 | 
 | ||||||
|  | 	parameter INIT_FILE = ""; | ||||||
|  | 
 | ||||||
| `ifndef BLACKBOX | `ifndef BLACKBOX | ||||||
| 	wire [15:0] WMASK_I; | 	wire [15:0] WMASK_I; | ||||||
| 	wire [15:0] RMASK_I; | 	wire [15:0] RMASK_I; | ||||||
|  | @ -408,43 +410,27 @@ module SB_RAM40_4K ( | ||||||
| 	reg [15:0] memory [0:255]; | 	reg [15:0] memory [0:255]; | ||||||
| 
 | 
 | ||||||
| 	initial begin | 	initial begin | ||||||
| 		for (i=0; i<16; i=i+1) begin | 		if (INIT_FILE != "") | ||||||
| `ifdef YOSYS | 			$readmemh(INIT_FILE, memory); | ||||||
| 			memory[ 0*16 + i] <= INIT_0[16*i +: 16]; | 		else | ||||||
| 			memory[ 1*16 + i] <= INIT_1[16*i +: 16]; | 			for (i=0; i<16; i=i+1) begin | ||||||
| 			memory[ 2*16 + i] <= INIT_2[16*i +: 16]; | 				memory[ 0*16 + i] = INIT_0[16*i +: 16]; | ||||||
| 			memory[ 3*16 + i] <= INIT_3[16*i +: 16]; | 				memory[ 1*16 + i] = INIT_1[16*i +: 16]; | ||||||
| 			memory[ 4*16 + i] <= INIT_4[16*i +: 16]; | 				memory[ 2*16 + i] = INIT_2[16*i +: 16]; | ||||||
| 			memory[ 5*16 + i] <= INIT_5[16*i +: 16]; | 				memory[ 3*16 + i] = INIT_3[16*i +: 16]; | ||||||
| 			memory[ 6*16 + i] <= INIT_6[16*i +: 16]; | 				memory[ 4*16 + i] = INIT_4[16*i +: 16]; | ||||||
| 			memory[ 7*16 + i] <= INIT_7[16*i +: 16]; | 				memory[ 5*16 + i] = INIT_5[16*i +: 16]; | ||||||
| 			memory[ 8*16 + i] <= INIT_8[16*i +: 16]; | 				memory[ 6*16 + i] = INIT_6[16*i +: 16]; | ||||||
| 			memory[ 9*16 + i] <= INIT_9[16*i +: 16]; | 				memory[ 7*16 + i] = INIT_7[16*i +: 16]; | ||||||
| 			memory[10*16 + i] <= INIT_A[16*i +: 16]; | 				memory[ 8*16 + i] = INIT_8[16*i +: 16]; | ||||||
| 			memory[11*16 + i] <= INIT_B[16*i +: 16]; | 				memory[ 9*16 + i] = INIT_9[16*i +: 16]; | ||||||
| 			memory[12*16 + i] <= INIT_C[16*i +: 16]; | 				memory[10*16 + i] = INIT_A[16*i +: 16]; | ||||||
| 			memory[13*16 + i] <= INIT_D[16*i +: 16]; | 				memory[11*16 + i] = INIT_B[16*i +: 16]; | ||||||
| 			memory[14*16 + i] <= INIT_E[16*i +: 16]; | 				memory[12*16 + i] = INIT_C[16*i +: 16]; | ||||||
| 			memory[15*16 + i] <= INIT_F[16*i +: 16]; | 				memory[13*16 + i] = INIT_D[16*i +: 16]; | ||||||
| `else | 				memory[14*16 + i] = INIT_E[16*i +: 16]; | ||||||
| 			memory[ 0*16 + i] = INIT_0[16*i +: 16]; | 				memory[15*16 + i] = INIT_F[16*i +: 16]; | ||||||
| 			memory[ 1*16 + i] = INIT_1[16*i +: 16]; | 			end | ||||||
| 			memory[ 2*16 + i] = INIT_2[16*i +: 16]; |  | ||||||
| 			memory[ 3*16 + i] = INIT_3[16*i +: 16]; |  | ||||||
| 			memory[ 4*16 + i] = INIT_4[16*i +: 16]; |  | ||||||
| 			memory[ 5*16 + i] = INIT_5[16*i +: 16]; |  | ||||||
| 			memory[ 6*16 + i] = INIT_6[16*i +: 16]; |  | ||||||
| 			memory[ 7*16 + i] = INIT_7[16*i +: 16]; |  | ||||||
| 			memory[ 8*16 + i] = INIT_8[16*i +: 16]; |  | ||||||
| 			memory[ 9*16 + i] = INIT_9[16*i +: 16]; |  | ||||||
| 			memory[10*16 + i] = INIT_A[16*i +: 16]; |  | ||||||
| 			memory[11*16 + i] = INIT_B[16*i +: 16]; |  | ||||||
| 			memory[12*16 + i] = INIT_C[16*i +: 16]; |  | ||||||
| 			memory[13*16 + i] = INIT_D[16*i +: 16]; |  | ||||||
| 			memory[14*16 + i] = INIT_E[16*i +: 16]; |  | ||||||
| 			memory[15*16 + i] = INIT_F[16*i +: 16]; |  | ||||||
| `endif |  | ||||||
| 		end |  | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| 	always @(posedge WCLK) begin | 	always @(posedge WCLK) begin | ||||||
|  | @ -504,6 +490,8 @@ module SB_RAM40_4KNR ( | ||||||
| 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 
 | 
 | ||||||
|  | 	parameter INIT_FILE = ""; | ||||||
|  | 
 | ||||||
| 	SB_RAM40_4K #( | 	SB_RAM40_4K #( | ||||||
| 		.WRITE_MODE(WRITE_MODE), | 		.WRITE_MODE(WRITE_MODE), | ||||||
| 		.READ_MODE (READ_MODE ), | 		.READ_MODE (READ_MODE ), | ||||||
|  | @ -522,7 +510,8 @@ module SB_RAM40_4KNR ( | ||||||
| 		.INIT_C    (INIT_C    ), | 		.INIT_C    (INIT_C    ), | ||||||
| 		.INIT_D    (INIT_D    ), | 		.INIT_D    (INIT_D    ), | ||||||
| 		.INIT_E    (INIT_E    ), | 		.INIT_E    (INIT_E    ), | ||||||
| 		.INIT_F    (INIT_F    ) | 		.INIT_F    (INIT_F    ), | ||||||
|  | 		.INIT_FILE (INIT_FILE ) | ||||||
| 	) RAM ( | 	) RAM ( | ||||||
| 		.RDATA(RDATA), | 		.RDATA(RDATA), | ||||||
| 		.RCLK (~RCLKN), | 		.RCLK (~RCLKN), | ||||||
|  | @ -566,6 +555,8 @@ module SB_RAM40_4KNW ( | ||||||
| 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 
 | 
 | ||||||
|  | 	parameter INIT_FILE = ""; | ||||||
|  | 
 | ||||||
| 	SB_RAM40_4K #( | 	SB_RAM40_4K #( | ||||||
| 		.WRITE_MODE(WRITE_MODE), | 		.WRITE_MODE(WRITE_MODE), | ||||||
| 		.READ_MODE (READ_MODE ), | 		.READ_MODE (READ_MODE ), | ||||||
|  | @ -584,7 +575,8 @@ module SB_RAM40_4KNW ( | ||||||
| 		.INIT_C    (INIT_C    ), | 		.INIT_C    (INIT_C    ), | ||||||
| 		.INIT_D    (INIT_D    ), | 		.INIT_D    (INIT_D    ), | ||||||
| 		.INIT_E    (INIT_E    ), | 		.INIT_E    (INIT_E    ), | ||||||
| 		.INIT_F    (INIT_F    ) | 		.INIT_F    (INIT_F    ), | ||||||
|  | 		.INIT_FILE (INIT_FILE ) | ||||||
| 	) RAM ( | 	) RAM ( | ||||||
| 		.RDATA(RDATA), | 		.RDATA(RDATA), | ||||||
| 		.RCLK (RCLK ), | 		.RCLK (RCLK ), | ||||||
|  | @ -628,6 +620,8 @@ module SB_RAM40_4KNRNW ( | ||||||
| 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||||
| 
 | 
 | ||||||
|  | 	parameter INIT_FILE = ""; | ||||||
|  | 
 | ||||||
| 	SB_RAM40_4K #( | 	SB_RAM40_4K #( | ||||||
| 		.WRITE_MODE(WRITE_MODE), | 		.WRITE_MODE(WRITE_MODE), | ||||||
| 		.READ_MODE (READ_MODE ), | 		.READ_MODE (READ_MODE ), | ||||||
|  | @ -646,7 +640,8 @@ module SB_RAM40_4KNRNW ( | ||||||
| 		.INIT_C    (INIT_C    ), | 		.INIT_C    (INIT_C    ), | ||||||
| 		.INIT_D    (INIT_D    ), | 		.INIT_D    (INIT_D    ), | ||||||
| 		.INIT_E    (INIT_E    ), | 		.INIT_E    (INIT_E    ), | ||||||
| 		.INIT_F    (INIT_F    ) | 		.INIT_F    (INIT_F    ), | ||||||
|  | 		.INIT_FILE (INIT_FILE ) | ||||||
| 	) RAM ( | 	) RAM ( | ||||||
| 		.RDATA(RDATA), | 		.RDATA(RDATA), | ||||||
| 		.RCLK (~RCLKN), | 		.RCLK (~RCLKN), | ||||||
|  |  | ||||||
							
								
								
									
										159
									
								
								techlibs/ice40/ice40_braminit.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								techlibs/ice40/ice40_braminit.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,159 @@ | ||||||
|  | /*
 | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "kernel/yosys.h" | ||||||
|  | #include "kernel/sigtools.h" | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <bitset> | ||||||
|  | 
 | ||||||
|  | USING_YOSYS_NAMESPACE | ||||||
|  | PRIVATE_NAMESPACE_BEGIN | ||||||
|  | 
 | ||||||
|  | static void run_ice40_braminit(Module *module) | ||||||
|  | { | ||||||
|  | 	for (auto cell : module->selected_cells()) | ||||||
|  | 	{ | ||||||
|  | 		uint16_t mem[256]; | ||||||
|  | 
 | ||||||
|  | 		/* Only consider cells we're interested in */ | ||||||
|  | 		if (cell->type != "\\SB_RAM40_4K" && | ||||||
|  | 		    cell->type != "\\SB_RAM40_4KNR" && | ||||||
|  | 		    cell->type != "\\SB_RAM40_4KNW" && | ||||||
|  | 		    cell->type != "\\SB_RAM40_4KNRNW") | ||||||
|  | 			continue; | ||||||
|  | 		if (!cell->hasParam("\\INIT_FILE")) | ||||||
|  | 			continue; | ||||||
|  | 		std::string init_file = cell->getParam("\\INIT_FILE").decode_string(); | ||||||
|  | 		cell->unsetParam("\\INIT_FILE"); | ||||||
|  | 		if (init_file == "") | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		/* Open file */ | ||||||
|  | 		log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str()); | ||||||
|  | 
 | ||||||
|  | 		std::ifstream f; | ||||||
|  | 		f.open(init_file.c_str()); | ||||||
|  | 		if (f.fail()) { | ||||||
|  | 			log("Can not open file `%s`.\n", init_file.c_str()); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* Defaults to 0 */ | ||||||
|  | 		memset(mem, 0x00, sizeof(mem)); | ||||||
|  | 
 | ||||||
|  | 		/* Process each line */ | ||||||
|  | 		bool in_comment = false; | ||||||
|  | 		int cursor = 0; | ||||||
|  | 
 | ||||||
|  | 		while (!f.eof()) | ||||||
|  | 		{ | ||||||
|  | 			std::string line, token; | ||||||
|  | 			std::getline(f, line); | ||||||
|  | 
 | ||||||
|  | 			for (int i = 0; i < GetSize(line); i++) | ||||||
|  | 			{ | ||||||
|  | 				if (in_comment && line.substr(i, 2) == "*/") { | ||||||
|  | 					line[i] = ' '; | ||||||
|  | 					line[i+1] = ' '; | ||||||
|  | 					in_comment = false; | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				if (!in_comment && line.substr(i, 2) == "/*") | ||||||
|  | 					in_comment = true; | ||||||
|  | 				if (in_comment) | ||||||
|  | 					line[i] = ' '; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			while (1) | ||||||
|  | 			{ | ||||||
|  | 				bool set_cursor = false; | ||||||
|  | 				long value; | ||||||
|  | 
 | ||||||
|  | 				token = next_token(line, " \t\r\n"); | ||||||
|  | 				if (token.empty() || token.substr(0, 2) == "//") | ||||||
|  | 					break; | ||||||
|  | 
 | ||||||
|  | 				if (token[0] == '@') { | ||||||
|  | 					token = token.substr(1); | ||||||
|  | 					set_cursor = true; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				const char *nptr = token.c_str(); | ||||||
|  | 				char *endptr; | ||||||
|  | 				value = strtol(nptr, &endptr, 16); | ||||||
|  | 				if (!*nptr || *endptr) { | ||||||
|  | 					log("Can not parse %s `%s` for %s.\n", | ||||||
|  | 						set_cursor ? "address" : "value", | ||||||
|  | 						nptr, token.c_str() | ||||||
|  | 					); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (set_cursor) | ||||||
|  | 					cursor = value; | ||||||
|  | 				else if (cursor >= 0 && cursor < 256) | ||||||
|  | 					mem[cursor++] = value; | ||||||
|  | 				else | ||||||
|  | 					log("Attempt to initialize non existent address %d\n", cursor); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* Set attributes */ | ||||||
|  | 		const char *hex = "0123456789ABCDEF"; | ||||||
|  | 		for (int i=0; i<16; i++) { | ||||||
|  | 			std::string val = ""; | ||||||
|  | 			for (int j=15; j>=0; j--) | ||||||
|  | 				val += std::bitset<16>(mem[i*16+j]).to_string(); | ||||||
|  | 			cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct Ice40BRAMInitPass : public Pass { | ||||||
|  | 	Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { } | ||||||
|  | 	void help() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    ice40_braminit\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n"); | ||||||
|  | 		log("parameter and converts it into the required INIT_x attributes\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 	} | ||||||
|  | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		log_header(design, "Executing ICE40_BRAMINIT pass.\n"); | ||||||
|  | 
 | ||||||
|  | 		size_t argidx; | ||||||
|  | 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||||
|  | 			// if (args[argidx] == "-???") {
 | ||||||
|  | 			//  continue;
 | ||||||
|  | 			// }
 | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		extra_args(args, argidx, design); | ||||||
|  | 
 | ||||||
|  | 		for (auto module : design->selected_modules()) | ||||||
|  | 			run_ice40_braminit(module); | ||||||
|  | 	} | ||||||
|  | } Ice40BRAMInitPass; | ||||||
|  | 
 | ||||||
|  | PRIVATE_NAMESPACE_END | ||||||
|  | @ -257,6 +257,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 		{ | 		{ | ||||||
| 			run("memory_bram -rules +/ice40/brams.txt"); | 			run("memory_bram -rules +/ice40/brams.txt"); | ||||||
| 			run("techmap -map +/ice40/brams_map.v"); | 			run("techmap -map +/ice40/brams_map.v"); | ||||||
|  | 			run("ice40_braminit"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map")) | 		if (check_label("map")) | ||||||
|  |  | ||||||
|  | @ -1,17 +1,41 @@ | ||||||
| // module  \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule | module  \$_DFF_N_ (input D, C, output Q); | ||||||
|  |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|  | endmodule | ||||||
| 
 | 
 | ||||||
| module  \$_DFF_P_ (input D, C, output Q); | module  \$_DFF_P_ (input D, C, output Q); | ||||||
|   SLE _TECHMAP_REPLACE_ ( |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|     .D(D), | endmodule | ||||||
|     .CLK(C), | 
 | ||||||
|     .EN(1'b1), | module \$_DFF_NN0_ (input D, C, R, output Q); | ||||||
|     .ALn(1'b1), |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|     .ADn(1'b1), | endmodule | ||||||
|     .SLn(1'b1), | 
 | ||||||
|     .SD(1'b0), | module \$_DFF_NN1_ (input D, C, R, output Q); | ||||||
|     .LAT(1'b0), |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|     .Q(Q) | endmodule | ||||||
|   ); | 
 | ||||||
|  | module \$_DFF_NP0_ (input D, C, R, output Q); | ||||||
|  |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module \$_DFF_NP1_ (input D, C, R, output Q); | ||||||
|  |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module \$_DFF_PN0_ (input D, C, R, output Q); | ||||||
|  |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module \$_DFF_PN1_ (input D, C, R, output Q); | ||||||
|  |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module \$_DFF_PP0_ (input D, C, R, output Q); | ||||||
|  |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module \$_DFF_PP1_ (input D, C, R, output Q); | ||||||
|  |   SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // module  \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule | // module  \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule | ||||||
|  | @ -20,16 +44,6 @@ endmodule | ||||||
| // module  \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule | // module  \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule | ||||||
| // module  \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule | // module  \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule | ||||||
| // | // | ||||||
| // module  \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule |  | ||||||
| // module  \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule |  | ||||||
| // module  \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule |  | ||||||
| // module  \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule |  | ||||||
| //  |  | ||||||
| // module  \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule |  | ||||||
| // module  \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule |  | ||||||
| // module  \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule |  | ||||||
| // module  \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule |  | ||||||
| //  |  | ||||||
| // module  \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule | // module  \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule | ||||||
| // module  \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule | // module  \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule | ||||||
| // module  \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule | // module  \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule | ||||||
|  |  | ||||||
|  | @ -1,39 +1,25 @@ | ||||||
| module SLE ( | // https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf | ||||||
| 	output Q, | 
 | ||||||
| 	input ADn, | module ADD2 ( | ||||||
| 	input ALn, | 
 | ||||||
| 	input CLK, | 	input A, B, | ||||||
| 	input D, | 	output Y | ||||||
| 	input LAT, |  | ||||||
| 	input SD, |  | ||||||
| 	input EN, |  | ||||||
| 	input SLn |  | ||||||
| ); | ); | ||||||
| 	reg q_latch, q_ff; | 	assign Y = A & B; | ||||||
|  | endmodule | ||||||
| 
 | 
 | ||||||
| 	always @(posedge CLK, negedge ALn) begin | module ADD3 ( | ||||||
| 		if (!ALn) begin | 	input A, B, C, | ||||||
| 			q_ff <= !ADn; | 	output Y | ||||||
| 		end else if (EN) begin | ); | ||||||
| 			if (!SLn) | 	assign Y = A & B & C; | ||||||
| 				q_ff <= SD; | endmodule | ||||||
| 			else |  | ||||||
| 				q_ff <= D; |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 
 | 
 | ||||||
| 	always @* begin | module ADD4 ( | ||||||
| 		if (!ALn) begin | 	input A, B, C, D, | ||||||
| 			q_latch <= !ADn; | 	output Y | ||||||
| 		end else if (CLK && EN) begin | ); | ||||||
| 			if (!SLn) | 	assign Y = A & B & C & D; | ||||||
| 				q_ff <= SD; |  | ||||||
| 			else |  | ||||||
| 				q_ff <= D; |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 
 |  | ||||||
| 	assign Q = LAT ? q_latch : q_ff; |  | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module CFG1 ( | module CFG1 ( | ||||||
|  | @ -74,6 +60,238 @@ module CFG4 ( | ||||||
| 	assign Y = INIT >> {D, C, B, A}; | 	assign Y = INIT >> {D, C, B, A}; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | module BUFF ( | ||||||
|  | 	input A, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module BUFD ( | ||||||
|  | 	input A, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module CLKINT ( | ||||||
|  | 	input A, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module CLKINT_PRESERVE ( | ||||||
|  | 	input A, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module GCLKINT ( | ||||||
|  | 	input A, EN, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A & EN; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module RCLKINT ( | ||||||
|  | 	input A, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module RGCLKINT ( | ||||||
|  | 	input A, EN, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A & EN; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module SLE ( | ||||||
|  | 	output Q, | ||||||
|  | 	input ADn, | ||||||
|  | 	input ALn, | ||||||
|  | 	input CLK, | ||||||
|  | 	input D, | ||||||
|  | 	input LAT, | ||||||
|  | 	input SD, | ||||||
|  | 	input EN, | ||||||
|  | 	input SLn | ||||||
|  | ); | ||||||
|  | 	reg q_latch, q_ff; | ||||||
|  | 
 | ||||||
|  | 	always @(posedge CLK, negedge ALn) begin | ||||||
|  | 		if (!ALn) begin | ||||||
|  | 			q_ff <= !ADn; | ||||||
|  | 		end else if (EN) begin | ||||||
|  | 			if (!SLn) | ||||||
|  | 				q_ff <= SD; | ||||||
|  | 			else | ||||||
|  | 				q_ff <= D; | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | 
 | ||||||
|  | 	always @* begin | ||||||
|  | 		if (!ALn) begin | ||||||
|  | 			q_latch <= !ADn; | ||||||
|  | 		end else if (CLK && EN) begin | ||||||
|  | 			if (!SLn) | ||||||
|  | 				q_ff <= SD; | ||||||
|  | 			else | ||||||
|  | 				q_ff <= D; | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | 
 | ||||||
|  | 	assign Q = LAT ? q_latch : q_ff; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | // module AR1 | ||||||
|  | // module FCEND_BUFF | ||||||
|  | // module FCINIT_BUFF | ||||||
|  | // module FLASH_FREEZE | ||||||
|  | // module OSCILLATOR | ||||||
|  | // module SYSRESET | ||||||
|  | // module SYSCTRL_RESET_STATUS | ||||||
|  | // module LIVE_PROBE_FB | ||||||
|  | // module GCLKBUF | ||||||
|  | // module GCLKBUF_DIFF | ||||||
|  | // module GCLKBIBUF | ||||||
|  | // module DFN1 | ||||||
|  | // module DFN1C0 | ||||||
|  | // module DFN1E1 | ||||||
|  | // module DFN1E1C0 | ||||||
|  | // module DFN1E1P0 | ||||||
|  | // module DFN1P0 | ||||||
|  | // module DLN1 | ||||||
|  | // module DLN1C0 | ||||||
|  | // module DLN1P0 | ||||||
|  | 
 | ||||||
|  | module INV ( | ||||||
|  | 	input A, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module INVD ( | ||||||
|  | 	input A, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module MX2 ( | ||||||
|  | 	input A, B, S, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = S ? B : A; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module MX4 ( | ||||||
|  | 	input D0, D1, D2, D3, S0, S1, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module NAND2 ( | ||||||
|  | 	input A, B, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !(A & B); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module NAND3 ( | ||||||
|  | 	input A, B, C, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !(A & B & C); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module NAND4 ( | ||||||
|  | 	input A, B, C, D, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !(A & B & C & D); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module NOR2 ( | ||||||
|  | 	input A, B, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !(A | B); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module NOR3 ( | ||||||
|  | 	input A, B, C, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !(A | B | C); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module NOR4 ( | ||||||
|  | 	input A, B, C, D, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = !(A | B | C | D); | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module OR2 ( | ||||||
|  | 	input A, B, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A | B; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module OR3 ( | ||||||
|  | 	input A, B, C, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A | B | C; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module OR4 ( | ||||||
|  | 	input A, B, C, D, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A | B | C | D; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module XOR2 ( | ||||||
|  | 	input A, B, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A ^ B; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module XOR3 ( | ||||||
|  | 	input A, B, C, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A ^ B ^ C; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module XOR4 ( | ||||||
|  | 	input A, B, C, D, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A ^ B ^ C ^ D; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module XOR8 ( | ||||||
|  | 	input A, B, C, D, E, F, G, H, | ||||||
|  | 	output Y | ||||||
|  | ); | ||||||
|  | 	assign Y = A ^ B ^ C ^ D ^ E ^ F ^ G ^ H; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | // module UJTAG | ||||||
|  | // module BIBUF | ||||||
|  | // module BIBUF_DIFF | ||||||
|  | // module CLKBIBUF | ||||||
|  | 
 | ||||||
| module CLKBUF ( | module CLKBUF ( | ||||||
| 	input PAD, | 	input PAD, | ||||||
| 	output Y | 	output Y | ||||||
|  | @ -81,6 +299,8 @@ module CLKBUF ( | ||||||
| 	assign Y = PAD; | 	assign Y = PAD; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | // module CLKBUF_DIFF | ||||||
|  | 
 | ||||||
| module INBUF ( | module INBUF ( | ||||||
| 	input PAD, | 	input PAD, | ||||||
| 	output Y | 	output Y | ||||||
|  | @ -88,9 +308,20 @@ module INBUF ( | ||||||
| 	assign Y = PAD; | 	assign Y = PAD; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | // module INBUF_DIFF | ||||||
|  | 
 | ||||||
| module OUTBUF ( | module OUTBUF ( | ||||||
| 	input D, | 	input D, | ||||||
| 	output PAD | 	output PAD | ||||||
| ); | ); | ||||||
| 	assign PAD = D; | 	assign PAD = D; | ||||||
| endmodule | endmodule | ||||||
|  | 
 | ||||||
|  | // module OUTBUF_DIFF | ||||||
|  | // module TRIBUFF | ||||||
|  | // module TRIBUFF_DIFF | ||||||
|  | // module DDR_IN | ||||||
|  | // module DDR_OUT | ||||||
|  | // module RAM1K18 | ||||||
|  | // module RAM64x18 | ||||||
|  | // module MACC | ||||||
|  |  | ||||||
|  | @ -23,6 +23,136 @@ | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
|  | static void handle_iobufs(Module *module, bool clkbuf_mode) | ||||||
|  | { | ||||||
|  | 	SigMap sigmap(module); | ||||||
|  | 
 | ||||||
|  | 	pool<SigBit> clk_bits; | ||||||
|  | 	pool<SigBit> handled_io_bits; | ||||||
|  | 	dict<SigBit, SigBit> rewrite_bits; | ||||||
|  | 	vector<pair<Cell*, SigBit>> pad_bits; | ||||||
|  | 
 | ||||||
|  | 	for (auto cell : module->cells()) | ||||||
|  | 	{ | ||||||
|  | 		if (clkbuf_mode && cell->type == "\\SLE") { | ||||||
|  | 			for (auto bit : sigmap(cell->getPort("\\CLK"))) | ||||||
|  | 				clk_bits.insert(bit); | ||||||
|  | 		} | ||||||
|  | 		if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUFF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF", | ||||||
|  | 				"\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUFF_DIFF", "\\CLKBUF_DIFF", | ||||||
|  | 				"\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) { | ||||||
|  | 			for (auto bit : sigmap(cell->getPort("\\PAD"))) | ||||||
|  | 				handled_io_bits.insert(bit); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (auto wire : vector<Wire*>(module->wires())) | ||||||
|  | 	{ | ||||||
|  | 		if (!wire->port_input && !wire->port_output) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		for (int index = 0; index < GetSize(wire); index++) | ||||||
|  | 		{ | ||||||
|  | 			SigBit bit(wire, index); | ||||||
|  | 			SigBit canonical_bit = sigmap(bit); | ||||||
|  | 
 | ||||||
|  | 			if (handled_io_bits.count(canonical_bit)) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			if (wire->port_input && wire->port_output) | ||||||
|  | 				log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); | ||||||
|  | 
 | ||||||
|  | 			IdString buf_type, buf_port; | ||||||
|  | 
 | ||||||
|  | 			if (wire->port_output) { | ||||||
|  | 				buf_type = "\\OUTBUF"; | ||||||
|  | 				buf_port = "\\D"; | ||||||
|  | 			} else if (clkbuf_mode && clk_bits.count(canonical_bit)) { | ||||||
|  | 				buf_type = "\\CLKBUF"; | ||||||
|  | 				buf_port = "\\Y"; | ||||||
|  | 			} else { | ||||||
|  | 				buf_type = "\\INBUF"; | ||||||
|  | 				buf_port = "\\Y"; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			Cell *c = module->addCell(NEW_ID, buf_type); | ||||||
|  | 			SigBit new_bit = module->addWire(NEW_ID); | ||||||
|  | 			c->setPort(buf_port, new_bit); | ||||||
|  | 			pad_bits.push_back(make_pair(c, bit)); | ||||||
|  | 			rewrite_bits[canonical_bit] = new_bit; | ||||||
|  | 
 | ||||||
|  | 			log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	auto rewrite_function = [&](SigSpec &s) { | ||||||
|  | 		for (auto &bit : s) { | ||||||
|  | 			SigBit canonical_bit = sigmap(bit); | ||||||
|  | 			if (rewrite_bits.count(canonical_bit)) | ||||||
|  | 				bit = rewrite_bits.at(canonical_bit); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	module->rewrite_sigspecs(rewrite_function); | ||||||
|  | 
 | ||||||
|  | 	for (auto &it : pad_bits) | ||||||
|  | 		it.first->setPort("\\PAD", it.second); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void handle_clkint(Module *module) | ||||||
|  | { | ||||||
|  | 	SigMap sigmap(module); | ||||||
|  | 
 | ||||||
|  | 	pool<SigBit> clk_bits; | ||||||
|  | 	vector<SigBit> handled_clk_bits; | ||||||
|  | 
 | ||||||
|  | 	for (auto cell : module->cells()) | ||||||
|  | 	{ | ||||||
|  | 		if (cell->type == "\\SLE") { | ||||||
|  | 			for (auto bit : sigmap(cell->getPort("\\CLK"))) | ||||||
|  | 				clk_bits.insert(bit); | ||||||
|  | 		} | ||||||
|  | 		if (cell->type.in("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF", | ||||||
|  | 				"\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) { | ||||||
|  | 			for (auto bit : sigmap(cell->getPort("\\Y"))) | ||||||
|  | 				handled_clk_bits.push_back(bit); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (auto bit : handled_clk_bits) | ||||||
|  | 		clk_bits.erase(bit); | ||||||
|  | 
 | ||||||
|  | 	for (auto cell : vector<Cell*>(module->cells())) | ||||||
|  | 	for (auto &conn : cell->connections()) | ||||||
|  | 	{ | ||||||
|  | 		if (!cell->output(conn.first)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		SigSpec sig = conn.second; | ||||||
|  | 		bool did_something = false; | ||||||
|  | 
 | ||||||
|  | 		for (auto &bit : sig) { | ||||||
|  | 			SigBit canonical_bit = sigmap(bit); | ||||||
|  | 			if (clk_bits.count(canonical_bit)) { | ||||||
|  | 				Cell *c = module->addCell(NEW_ID, "\\CLKINT"); | ||||||
|  | 				SigBit new_bit = module->addWire(NEW_ID); | ||||||
|  | 				c->setPort("\\A", new_bit); | ||||||
|  | 				c->setPort("\\Y", bit); | ||||||
|  | 				log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit)); | ||||||
|  | 				clk_bits.erase(canonical_bit); | ||||||
|  | 				did_something = true; | ||||||
|  | 				bit = new_bit; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (did_something) | ||||||
|  | 			cell->setPort(conn.first, sig); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (auto bit : clk_bits) | ||||||
|  | 		log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct Sf2IobsPass : public Pass { | struct Sf2IobsPass : public Pass { | ||||||
| 	Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { } | 	Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { } | ||||||
| 	void help() YS_OVERRIDE | 	void help() YS_OVERRIDE | ||||||
|  | @ -31,20 +161,25 @@ struct Sf2IobsPass : public Pass { | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    sf2_iobs [options] [selection]\n"); | 		log("    sf2_iobs [options] [selection]\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Add SF2 I/O buffers to top module IOs as needed.\n"); | 		log("Add SF2 I/O buffers and global buffers to top module as needed.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -clkbuf\n"); | ||||||
|  | 		log("        Insert PAD->global_net clock buffers\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | 		bool clkbuf_mode = false; | ||||||
|  | 
 | ||||||
| 		log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n"); | 		log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n"); | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
| 		{ | 		{ | ||||||
| 			// if (args[argidx] == "-singleton") {
 | 			if (args[argidx] == "-clkbuf") { | ||||||
| 			// 	singleton_mode = true;
 | 				clkbuf_mode = true; | ||||||
| 			// 	continue;
 | 				continue; | ||||||
| 			// }
 | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
|  | @ -54,76 +189,8 @@ struct Sf2IobsPass : public Pass { | ||||||
| 		if (module == nullptr) | 		if (module == nullptr) | ||||||
| 			log_cmd_error("No top module found.\n"); | 			log_cmd_error("No top module found.\n"); | ||||||
| 
 | 
 | ||||||
| 		SigMap sigmap(module); | 		handle_iobufs(module, clkbuf_mode); | ||||||
| 
 | 		handle_clkint(module); | ||||||
| 		pool<SigBit> clk_bits; |  | ||||||
| 		pool<SigBit> handled_io_bits; |  | ||||||
| 		dict<SigBit, SigBit> rewrite_bits; |  | ||||||
| 		vector<pair<Cell*, SigBit>> pad_bits; |  | ||||||
| 
 |  | ||||||
| 		for (auto cell : module->cells()) |  | ||||||
| 		{ |  | ||||||
| 			if (cell->type == "\\SLE") { |  | ||||||
| 				for (auto bit : sigmap(cell->getPort("\\CLK"))) |  | ||||||
| 					clk_bits.insert(bit); |  | ||||||
| 			} |  | ||||||
| 			if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) { |  | ||||||
| 				for (auto bit : sigmap(cell->getPort("\\PAD"))) |  | ||||||
| 					handled_io_bits.insert(bit); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		for (auto wire : vector<Wire*>(module->wires())) |  | ||||||
| 		{ |  | ||||||
| 			if (!wire->port_input && !wire->port_output) |  | ||||||
| 				continue; |  | ||||||
| 
 |  | ||||||
| 			for (int index = 0; index < GetSize(wire); index++) |  | ||||||
| 			{ |  | ||||||
| 				SigBit bit(wire, index); |  | ||||||
| 				SigBit canonical_bit = sigmap(bit); |  | ||||||
| 
 |  | ||||||
| 				if (handled_io_bits.count(canonical_bit)) |  | ||||||
| 					continue; |  | ||||||
| 
 |  | ||||||
| 				if (wire->port_input && wire->port_output) |  | ||||||
| 					log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); |  | ||||||
| 
 |  | ||||||
| 				IdString buf_type, buf_port; |  | ||||||
| 
 |  | ||||||
| 				if (wire->port_output) { |  | ||||||
| 					buf_type = "\\OUTBUF"; |  | ||||||
| 					buf_port = "\\D"; |  | ||||||
| 				} else if (clk_bits.count(canonical_bit)) { |  | ||||||
| 					buf_type = "\\CLKBUF"; |  | ||||||
| 					buf_port = "\\Y"; |  | ||||||
| 				} else { |  | ||||||
| 					buf_type = "\\INBUF"; |  | ||||||
| 					buf_port = "\\Y"; |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				Cell *c = module->addCell(NEW_ID, buf_type); |  | ||||||
| 				SigBit new_bit = module->addWire(NEW_ID); |  | ||||||
| 				c->setPort(buf_port, new_bit); |  | ||||||
| 				pad_bits.push_back(make_pair(c, bit)); |  | ||||||
| 				rewrite_bits[canonical_bit] = new_bit; |  | ||||||
| 
 |  | ||||||
| 				log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		auto rewrite_function = [&](SigSpec &s) { |  | ||||||
| 			for (auto &bit : s) { |  | ||||||
| 				SigBit canonical_bit = sigmap(bit); |  | ||||||
| 				if (rewrite_bits.count(canonical_bit)) |  | ||||||
| 					bit = rewrite_bits.at(canonical_bit); |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		module->rewrite_sigspecs(rewrite_function); |  | ||||||
| 
 |  | ||||||
| 		for (auto &it : pad_bits) |  | ||||||
| 			it.first->setPort("\\PAD", it.second); |  | ||||||
| 	} | 	} | ||||||
| } Sf2IobsPass; | } Sf2IobsPass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -63,6 +63,9 @@ struct SynthSf2Pass : public ScriptPass | ||||||
| 		log("    -noiobs\n"); | 		log("    -noiobs\n"); | ||||||
| 		log("        run synthesis in \"block mode\", i.e. do not insert IO buffers\n"); | 		log("        run synthesis in \"block mode\", i.e. do not insert IO buffers\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -clkbuf\n"); | ||||||
|  | 		log("        insert direct PAD->global_net buffers\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -retime\n"); | 		log("    -retime\n"); | ||||||
| 		log("        run 'abc' with -dff option\n"); | 		log("        run 'abc' with -dff option\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -73,7 +76,7 @@ struct SynthSf2Pass : public ScriptPass | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string top_opt, edif_file, vlog_file, json_file; | 	string top_opt, edif_file, vlog_file, json_file; | ||||||
| 	bool flatten, retime, iobs; | 	bool flatten, retime, iobs, clkbuf; | ||||||
| 
 | 
 | ||||||
| 	void clear_flags() YS_OVERRIDE | 	void clear_flags() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | @ -84,6 +87,7 @@ struct SynthSf2Pass : public ScriptPass | ||||||
| 		flatten = true; | 		flatten = true; | ||||||
| 		retime = false; | 		retime = false; | ||||||
| 		iobs = true; | 		iobs = true; | ||||||
|  | 		clkbuf = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | @ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass | ||||||
| 				iobs = false; | 				iobs = false; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-clkbuf") { | ||||||
|  | 				clkbuf = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
|  | @ -201,8 +209,10 @@ struct SynthSf2Pass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map_iobs")) | 		if (check_label("map_iobs")) | ||||||
| 		{ | 		{ | ||||||
| 			if (iobs || help_mode) | 			if (help_mode) | ||||||
| 				run("sf2_iobs", "(unless -noiobs)"); | 				run("sf2_iobs [-clkbuf]", "(unless -noiobs)"); | ||||||
|  | 			else if (iobs) | ||||||
|  | 				run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs"); | ||||||
| 			run("clean"); | 			run("clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,7 +28,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v)) | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt)) | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt)) | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut2lut.v)) | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) | ||||||
|  | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) | ||||||
| 
 | 
 | ||||||
| $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) | $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) | ||||||
| $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) | $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) | ||||||
|  |  | ||||||
|  | @ -17,6 +17,9 @@ | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | // ============================================================================ | ||||||
|  | // LCU | ||||||
|  | 
 | ||||||
| (* techmap_celltype = "$lcu" *) | (* techmap_celltype = "$lcu" *) | ||||||
| module _80_xilinx_lcu (P, G, CI, CO); | module _80_xilinx_lcu (P, G, CI, CO); | ||||||
| 	parameter WIDTH = 2; | 	parameter WIDTH = 2; | ||||||
|  | @ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO); | ||||||
| 
 | 
 | ||||||
| 	wire _TECHMAP_FAIL_ = WIDTH <= 2; | 	wire _TECHMAP_FAIL_ = WIDTH <= 2; | ||||||
| 
 | 
 | ||||||
|  | 	genvar i; | ||||||
|  | 
 | ||||||
|  | `ifdef _CLB_CARRY | ||||||
|  | 
 | ||||||
|  | 	localparam CARRY4_COUNT = (WIDTH + 3) / 4; | ||||||
|  | 	localparam MAX_WIDTH    = CARRY4_COUNT * 4; | ||||||
|  | 	localparam PAD_WIDTH    = MAX_WIDTH - WIDTH; | ||||||
|  | 
 | ||||||
|  | 	wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, P & ~G}; | ||||||
|  | 	wire [MAX_WIDTH-1:0] C  = CO; | ||||||
|  | 
 | ||||||
|  | 	generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice | ||||||
|  | 
 | ||||||
|  | 		// Partially occupied CARRY4 | ||||||
|  | 		if ((i+1)*4 > WIDTH) begin | ||||||
|  | 
 | ||||||
|  | 			// First one | ||||||
|  | 			if (i == 0) begin | ||||||
|  | 				CARRY4 carry4_1st_part | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(CI), | ||||||
|  | 				.CI    (1'd0), | ||||||
|  | 				.DI    (G [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.S     (S [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.CO    (CO[(Y_WIDTH - 1):i*4]), | ||||||
|  | 				); | ||||||
|  | 			// Another one | ||||||
|  | 			end else begin | ||||||
|  | 				CARRY4 carry4_part | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(1'd0), | ||||||
|  | 				.CI    (C [i*4 - 1]), | ||||||
|  | 				.DI    (G [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.S     (S [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.CO    (CO[(Y_WIDTH - 1):i*4]), | ||||||
|  | 				); | ||||||
|  | 			end | ||||||
|  | 
 | ||||||
|  | 		// Fully occupied CARRY4 | ||||||
|  | 		end else begin | ||||||
|  | 
 | ||||||
|  | 			// First one | ||||||
|  | 			if (i == 0) begin | ||||||
|  | 				CARRY4 carry4_1st_full | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(CI), | ||||||
|  | 				.CI    (1'd0), | ||||||
|  | 				.DI    (G [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.S     (S [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.CO    (CO[((i+1)*4 - 1):i*4]), | ||||||
|  | 				); | ||||||
|  | 			// Another one | ||||||
|  | 			end else begin | ||||||
|  | 				CARRY4 carry4_full | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(1'd0), | ||||||
|  | 				.CI    (C [i*4 - 1]), | ||||||
|  | 				.DI    (G [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.S     (S [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.CO    (CO[((i+1)*4 - 1):i*4]), | ||||||
|  | 				); | ||||||
|  | 			end | ||||||
|  | 
 | ||||||
|  | 		end | ||||||
|  | 
 | ||||||
|  | 	end endgenerate | ||||||
|  | 
 | ||||||
|  | `elsif _EXPLICIT_CARRY | ||||||
|  | 
 | ||||||
| 	wire [WIDTH-1:0] C = {CO, CI}; | 	wire [WIDTH-1:0] C = {CO, CI}; | ||||||
| 	wire [WIDTH-1:0] S = P & ~G; | 	wire [WIDTH-1:0] S = P & ~G; | ||||||
| 
 | 
 | ||||||
| 	genvar i; |  | ||||||
| 	generate for (i = 0; i < WIDTH; i = i + 1) begin:slice | 	generate for (i = 0; i < WIDTH; i = i + 1) begin:slice | ||||||
| 		MUXCY muxcy ( | 		MUXCY muxcy ( | ||||||
| 			.CI(C[i]), | 			.CI(C[i]), | ||||||
|  | @ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO); | ||||||
| 			.O(CO[i]) | 			.O(CO[i]) | ||||||
| 		); | 		); | ||||||
| 	end endgenerate | 	end endgenerate | ||||||
|  | 
 | ||||||
|  | `else | ||||||
|  | 
 | ||||||
|  | 	wire [WIDTH-1:0] C = {CO, CI}; | ||||||
|  | 	wire [WIDTH-1:0] S = P & ~G; | ||||||
|  | 
 | ||||||
|  | 	generate for (i = 0; i < WIDTH; i = i + 1) begin:slice | ||||||
|  | 		MUXCY muxcy ( | ||||||
|  | 			.CI(C[i]), | ||||||
|  | 			.DI(G[i]), | ||||||
|  | 			.S(S[i]), | ||||||
|  | 			.O(CO[i]) | ||||||
|  | 		); | ||||||
|  | 	end endgenerate | ||||||
|  | `endif | ||||||
|  | 
 | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | // ============================================================================ | ||||||
|  | // ALU | ||||||
|  | 
 | ||||||
| (* techmap_celltype = "$alu" *) | (* techmap_celltype = "$alu" *) | ||||||
| module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); | module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); | ||||||
| 	parameter A_SIGNED = 0; | 	parameter A_SIGNED = 0; | ||||||
|  | @ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); | ||||||
| 	parameter A_WIDTH = 1; | 	parameter A_WIDTH = 1; | ||||||
| 	parameter B_WIDTH = 1; | 	parameter B_WIDTH = 1; | ||||||
| 	parameter Y_WIDTH = 1; | 	parameter Y_WIDTH = 1; | ||||||
|  | 	parameter _TECHMAP_CONSTVAL_CI_ = 0; | ||||||
|  | 	parameter _TECHMAP_CONSTMSK_CI_ = 0; | ||||||
| 
 | 
 | ||||||
| 	input [A_WIDTH-1:0] A; | 	input [A_WIDTH-1:0] A; | ||||||
| 	input [B_WIDTH-1:0] B; | 	input [B_WIDTH-1:0] B; | ||||||
|  | @ -66,16 +159,189 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); | ||||||
| 	wire [Y_WIDTH-1:0] AA = A_buf; | 	wire [Y_WIDTH-1:0] AA = A_buf; | ||||||
| 	wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; | 	wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; | ||||||
| 
 | 
 | ||||||
| 	wire [Y_WIDTH-1:0] P = AA ^ BB; | 	genvar i; | ||||||
| 	wire [Y_WIDTH-1:0] G = AA & BB; | 
 | ||||||
| 	wire [Y_WIDTH-1:0] C = {CO, CI}; | `ifdef _CLB_CARRY | ||||||
| 	wire [Y_WIDTH-1:0] S = P & ~G; | 
 | ||||||
|  | 	localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4; | ||||||
|  | 	localparam MAX_WIDTH    = CARRY4_COUNT * 4; | ||||||
|  | 	localparam PAD_WIDTH    = MAX_WIDTH - Y_WIDTH; | ||||||
|  | 
 | ||||||
|  | 	wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, AA ^ BB}; | ||||||
|  | 	wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB}; | ||||||
|  | 
 | ||||||
|  | 	wire [MAX_WIDTH-1:0] C  = CO; | ||||||
| 
 | 
 | ||||||
| 	genvar i; | 	genvar i; | ||||||
|  | 	generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice | ||||||
|  | 
 | ||||||
|  | 		// Partially occupied CARRY4 | ||||||
|  | 		if ((i+1)*4 > Y_WIDTH) begin | ||||||
|  | 
 | ||||||
|  | 			// First one | ||||||
|  | 			if (i == 0) begin | ||||||
|  | 				CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(CI), | ||||||
|  | 				.CI    (1'd0), | ||||||
|  | 				.DI    (DI[(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.S     (S [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.O     (Y [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.CO    (CO[(Y_WIDTH - 1):i*4]) | ||||||
|  | 				); | ||||||
|  | 			// Another one | ||||||
|  | 			end else begin | ||||||
|  | 				CARRY4 carry4_part | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(1'd0), | ||||||
|  | 				.CI    (C [i*4 - 1]), | ||||||
|  | 				.DI    (DI[(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.S     (S [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.O     (Y [(Y_WIDTH - 1):i*4]), | ||||||
|  | 				.CO    (CO[(Y_WIDTH - 1):i*4]) | ||||||
|  | 				); | ||||||
|  | 			end | ||||||
|  | 
 | ||||||
|  | 		// Fully occupied CARRY4 | ||||||
|  | 		end else begin | ||||||
|  | 
 | ||||||
|  | 			// First one | ||||||
|  | 			if (i == 0) begin | ||||||
|  | 				CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(CI), | ||||||
|  | 				.CI    (1'd0), | ||||||
|  | 				.DI    (DI[((i+1)*4 - 1):i*4]), | ||||||
|  | 				.S     (S [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.O     (Y [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.CO    (CO[((i+1)*4 - 1):i*4]) | ||||||
|  | 				); | ||||||
|  | 			// Another one | ||||||
|  | 			end else begin | ||||||
|  | 				CARRY4 carry4_full | ||||||
|  | 				( | ||||||
|  | 				.CYINIT(1'd0), | ||||||
|  | 				.CI    (C [i*4 - 1]), | ||||||
|  | 				.DI    (DI[((i+1)*4 - 1):i*4]), | ||||||
|  | 				.S     (S [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.O     (Y [((i+1)*4 - 1):i*4]), | ||||||
|  | 				.CO    (CO[((i+1)*4 - 1):i*4]) | ||||||
|  | 				); | ||||||
|  | 			end | ||||||
|  | 
 | ||||||
|  | 		end | ||||||
|  | 
 | ||||||
|  | 	end endgenerate | ||||||
|  | 
 | ||||||
|  | `elsif _EXPLICIT_CARRY | ||||||
|  | 
 | ||||||
|  | 	wire [Y_WIDTH-1:0] S = AA ^ BB; | ||||||
|  | 	wire [Y_WIDTH-1:0] DI = AA & BB; | ||||||
|  | 
 | ||||||
|  | 	wire CINIT; | ||||||
|  | 	// Carry chain. | ||||||
|  | 	// | ||||||
|  | 	// VPR requires that the carry chain never hit the fabric.	The CO input | ||||||
|  | 	// to this techmap is the carry outputs for synthesis, e.g. might hit the | ||||||
|  | 	// fabric. | ||||||
|  | 	// | ||||||
|  | 	// So we maintain two wire sets, CO_CHAIN is the carry that is for VPR, | ||||||
|  | 	// e.g. off fabric dedicated chain.  CO is the carry outputs that are | ||||||
|  | 	// available to the fabric. | ||||||
|  | 	wire [Y_WIDTH-1:0] CO_CHAIN; | ||||||
|  | 	wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT}; | ||||||
|  | 
 | ||||||
|  | 	// If carry chain is being initialized to a constant, techmap the constant | ||||||
|  | 	// source.	Otherwise techmap the fabric source. | ||||||
|  | 	generate for (i = 0; i < 1; i = i + 1) begin:slice | ||||||
|  | 		CARRY0 #(.CYINIT_FABRIC(1)) carry( | ||||||
|  | 			.CI_INIT(CI), | ||||||
|  | 			.DI(DI[0]), | ||||||
|  | 			.S(S[0]), | ||||||
|  | 			.CO_CHAIN(CO_CHAIN[0]), | ||||||
|  | 			.CO_FABRIC(CO[0]), | ||||||
|  | 			.O(Y[0]) | ||||||
|  | 		); | ||||||
|  | 	end endgenerate | ||||||
|  | 
 | ||||||
|  | 	generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice | ||||||
|  | 		if(i % 4 == 0) begin | ||||||
|  | 			CARRY0 carry ( | ||||||
|  | 				.CI(C[i]), | ||||||
|  | 				.DI(DI[i]), | ||||||
|  | 				.S(S[i]), | ||||||
|  | 				.CO_CHAIN(CO_CHAIN[i]), | ||||||
|  | 				.CO_FABRIC(CO[i]), | ||||||
|  | 				.O(Y[i]) | ||||||
|  | 			); | ||||||
|  | 		end | ||||||
|  | 		else | ||||||
|  | 		begin | ||||||
|  | 			CARRY carry ( | ||||||
|  | 				.CI(C[i]), | ||||||
|  | 				.DI(DI[i]), | ||||||
|  | 				.S(S[i]), | ||||||
|  | 				.CO_CHAIN(CO_CHAIN[i]), | ||||||
|  | 				.CO_FABRIC(CO[i]), | ||||||
|  | 				.O(Y[i]) | ||||||
|  | 			); | ||||||
|  | 		end | ||||||
|  | 	end endgenerate | ||||||
|  | 
 | ||||||
|  | 	generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice | ||||||
|  | 		if(i % 4 == 0) begin | ||||||
|  | 			CARRY0 top_of_carry ( | ||||||
|  | 				.CI(C[i]), | ||||||
|  | 				.DI(DI[i]), | ||||||
|  | 				.S(S[i]), | ||||||
|  | 				.CO_CHAIN(CO_CHAIN[i]), | ||||||
|  | 				.O(Y[i]) | ||||||
|  | 			); | ||||||
|  | 		end | ||||||
|  | 		else | ||||||
|  | 		begin | ||||||
|  | 			CARRY top_of_carry ( | ||||||
|  | 				.CI(C[i]), | ||||||
|  | 				.DI(DI[i]), | ||||||
|  | 				.S(S[i]), | ||||||
|  | 				.CO_CHAIN(CO_CHAIN[i]), | ||||||
|  | 				.O(Y[i]) | ||||||
|  | 			); | ||||||
|  | 		end | ||||||
|  | 		// Turns out CO_FABRIC and O both use [ABCD]MUX, so provide | ||||||
|  | 		// a non-congested path to output the top of the carry chain. | ||||||
|  | 		// Registering the output of the CARRY block would solve this, but not | ||||||
|  | 		// all designs do that. | ||||||
|  | 		if((i+1) % 4 == 0) begin | ||||||
|  | 			CARRY0 carry_output ( | ||||||
|  | 				.CI(CO_CHAIN[i]), | ||||||
|  | 				.DI(0), | ||||||
|  | 				.S(0), | ||||||
|  | 				.O(CO[i]) | ||||||
|  | 			); | ||||||
|  | 		end | ||||||
|  | 		else | ||||||
|  | 		begin | ||||||
|  | 			CARRY carry_output ( | ||||||
|  | 				.CI(CO_CHAIN[i]), | ||||||
|  | 				.DI(0), | ||||||
|  | 				.S(0), | ||||||
|  | 				.O(CO[i]) | ||||||
|  | 			); | ||||||
|  | 		end | ||||||
|  | 	end endgenerate | ||||||
|  | 
 | ||||||
|  | `else | ||||||
|  | 
 | ||||||
|  | 	wire [Y_WIDTH-1:0] S = AA ^ BB; | ||||||
|  | 	wire [Y_WIDTH-1:0] DI = AA & BB; | ||||||
|  | 
 | ||||||
|  | 	wire [Y_WIDTH-1:0] C = {CO, CI}; | ||||||
|  | 
 | ||||||
| 	generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice | 	generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice | ||||||
| 		MUXCY muxcy ( | 		MUXCY muxcy ( | ||||||
| 			.CI(C[i]), | 			.CI(C[i]), | ||||||
| 			.DI(G[i]), | 			.DI(DI[i]), | ||||||
| 			.S(S[i]), | 			.S(S[i]), | ||||||
| 			.O(CO[i]) | 			.O(CO[i]) | ||||||
| 		); | 		); | ||||||
|  | @ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); | ||||||
| 		); | 		); | ||||||
| 	end endgenerate | 	end endgenerate | ||||||
| 
 | 
 | ||||||
| 	assign X = P; | `endif | ||||||
|  | 
 | ||||||
|  | 	assign X = S; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,89 +1,21 @@ | ||||||
| 
 | /* | ||||||
| module  \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
| module  \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule |  * | ||||||
| 
 |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
| module  \$_DFFE_NP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule |  * | ||||||
| module  \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
| 
 |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
| module  \$_DFF_NN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule |  *  copyright notice and this permission notice appear in all copies. | ||||||
| module  \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule |  * | ||||||
| module  \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
| module  \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
| 
 |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
| module  \$_DFF_NN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
| module  \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
| module  \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
| module  \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
| 
 |  * | ||||||
| `ifndef NO_LUT |  */ | ||||||
| module \$lut (A, Y); |  | ||||||
|   parameter WIDTH = 0; |  | ||||||
|   parameter LUT = 0; |  | ||||||
| 
 |  | ||||||
|   input [WIDTH-1:0] A; |  | ||||||
|   output Y; |  | ||||||
| 
 |  | ||||||
|   generate |  | ||||||
|     if (WIDTH == 1) begin |  | ||||||
|       LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), |  | ||||||
|         .I0(A[0])); |  | ||||||
|     end else |  | ||||||
|     if (WIDTH == 2) begin |  | ||||||
|       LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), |  | ||||||
|         .I0(A[0]), .I1(A[1])); |  | ||||||
|     end else |  | ||||||
|     if (WIDTH == 3) begin |  | ||||||
|       LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2])); |  | ||||||
|     end else |  | ||||||
|     if (WIDTH == 4) begin |  | ||||||
|       LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3])); |  | ||||||
|     end else |  | ||||||
|     if (WIDTH == 5) begin |  | ||||||
|       LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4])); |  | ||||||
|     end else |  | ||||||
|     if (WIDTH == 6) begin |  | ||||||
|       LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); |  | ||||||
|     end else |  | ||||||
|     if (WIDTH == 7) begin |  | ||||||
|       wire T0, T1; |  | ||||||
|       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); |  | ||||||
|       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); |  | ||||||
|       MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); |  | ||||||
|     end else |  | ||||||
|     if (WIDTH == 8) begin |  | ||||||
|       wire T0, T1, T2, T3, T4, T5; |  | ||||||
|       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); |  | ||||||
|       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); |  | ||||||
|       LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); |  | ||||||
|       LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), |  | ||||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), |  | ||||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); |  | ||||||
|       MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); |  | ||||||
|       MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); |  | ||||||
|       MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); |  | ||||||
|     end else begin |  | ||||||
|       wire _TECHMAP_FAIL_ = 1; |  | ||||||
|     end |  | ||||||
|   endgenerate |  | ||||||
| endmodule |  | ||||||
| `endif |  | ||||||
| 
 | 
 | ||||||
| module \$__SHREG_ (input C, input D, input E, output Q); | module \$__SHREG_ (input C, input D, input E, output Q); | ||||||
|   parameter DEPTH = 0; |   parameter DEPTH = 0; | ||||||
|  |  | ||||||
|  | @ -1,3 +1,21 @@ | ||||||
|  | /* | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
| 
 | 
 | ||||||
| // See Xilinx UG953 and UG474 for a description of the cell types below. | // See Xilinx UG953 and UG474 for a description of the cell types below. | ||||||
| // http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf | // http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf | ||||||
|  | @ -104,6 +122,29 @@ module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); | ||||||
|   assign CO[3] = S[3] ? CO[2] : DI[3]; |   assign CO[3] = S[3] ? CO[2] : DI[3]; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | `ifdef _EXPLICIT_CARRY | ||||||
|  | 
 | ||||||
|  | module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S); | ||||||
|  |   parameter CYINIT_FABRIC = 0; | ||||||
|  |   wire CI_COMBINE; | ||||||
|  |   if(CYINIT_FABRIC) begin | ||||||
|  |     assign CI_COMBINE = CI_INIT; | ||||||
|  |   end else begin | ||||||
|  |     assign CI_COMBINE = CI; | ||||||
|  |   end | ||||||
|  |   assign CO_CHAIN = S ? CI_COMBINE : DI; | ||||||
|  |   assign CO_FABRIC = S ? CI_COMBINE : DI; | ||||||
|  |   assign O = S ^ CI_COMBINE; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S); | ||||||
|  |   assign CO_CHAIN = S ? CI : DI; | ||||||
|  |   assign CO_FABRIC = S ? CI : DI; | ||||||
|  |   assign O = S ^ CI; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | `endif | ||||||
|  | 
 | ||||||
| module FDRE (output reg Q, input C, CE, D, R); | module FDRE (output reg Q, input C, CE, D, R); | ||||||
|   parameter [0:0] INIT = 1'b0; |   parameter [0:0] INIT = 1'b0; | ||||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; |   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||||
|  | @ -156,6 +197,30 @@ module FDPE (output reg Q, input C, CE, D, PRE); | ||||||
|   endcase endgenerate |   endcase endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | module FDRE_1 (output reg Q, input C, CE, D, R); | ||||||
|  |   parameter [0:0] INIT = 1'b0; | ||||||
|  |   initial Q <= INIT; | ||||||
|  |   always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module FDSE_1 (output reg Q, input C, CE, D, S); | ||||||
|  |   parameter [0:0] INIT = 1'b1; | ||||||
|  |   initial Q <= INIT; | ||||||
|  |   always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module FDCE_1 (output reg Q, input C, CE, D, CLR); | ||||||
|  |   parameter [0:0] INIT = 1'b0; | ||||||
|  |   initial Q <= INIT; | ||||||
|  |   always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module FDPE_1 (output reg Q, input C, CE, D, PRE); | ||||||
|  |   parameter [0:0] INIT = 1'b1; | ||||||
|  |   initial Q <= INIT; | ||||||
|  |   always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| module RAM64X1D ( | module RAM64X1D ( | ||||||
|   output DPO, SPO, |   output DPO, SPO, | ||||||
|   input  D, WCLK, WE, |   input  D, WCLK, WE, | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ function xtract_cell_decl() | ||||||
| 	xtract_cell_decl PS7 | 	xtract_cell_decl PS7 | ||||||
| 	xtract_cell_decl PULLDOWN | 	xtract_cell_decl PULLDOWN | ||||||
| 	xtract_cell_decl PULLUP | 	xtract_cell_decl PULLUP | ||||||
| 	# xtract_cell_decl RAM128X1D | 	xtract_cell_decl RAM128X1D | ||||||
| 	xtract_cell_decl RAM128X1S | 	xtract_cell_decl RAM128X1S | ||||||
| 	xtract_cell_decl RAM256X1S | 	xtract_cell_decl RAM256X1S | ||||||
| 	xtract_cell_decl RAM32M | 	xtract_cell_decl RAM32M | ||||||
|  | @ -124,7 +124,7 @@ function xtract_cell_decl() | ||||||
| 	xtract_cell_decl RAM32X1S_1 | 	xtract_cell_decl RAM32X1S_1 | ||||||
| 	xtract_cell_decl RAM32X2S | 	xtract_cell_decl RAM32X2S | ||||||
| 	xtract_cell_decl RAM64M | 	xtract_cell_decl RAM64M | ||||||
| 	# xtract_cell_decl RAM64X1D | 	xtract_cell_decl RAM64X1D | ||||||
| 	xtract_cell_decl RAM64X1S | 	xtract_cell_decl RAM64X1S | ||||||
| 	xtract_cell_decl RAM64X1S_1 | 	xtract_cell_decl RAM64X1S_1 | ||||||
| 	xtract_cell_decl RAM64X2S | 	xtract_cell_decl RAM64X2S | ||||||
|  |  | ||||||
|  | @ -3695,6 +3695,25 @@ module RAM128X1S (...); | ||||||
|     input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE; |     input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | module RAM128X1D ( | ||||||
|  |   output       DPO, SPO, | ||||||
|  |   input        D, WCLK, WE, | ||||||
|  |   input  [6:0] A, DPRA | ||||||
|  | ); | ||||||
|  | 	parameter [127:0] INIT = 128'bx; | ||||||
|  | 	parameter IS_WCLK_INVERTED = 0; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | module RAM64X1D ( | ||||||
|  |   output DPO, SPO, | ||||||
|  |   input  D, WCLK, WE, | ||||||
|  |   input  A0, A1, A2, A3, A4, A5, | ||||||
|  |   input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 | ||||||
|  | ); | ||||||
|  | 	parameter [63:0] INIT = 64'bx; | ||||||
|  | 	parameter IS_WCLK_INVERTED = 0; | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
| module RAM256X1S (...); | module RAM256X1S (...); | ||||||
|     parameter [255:0] INIT = 256'h0; |     parameter [255:0] INIT = 256'h0; | ||||||
|     parameter [0:0] IS_WCLK_INVERTED = 1'b0; |     parameter [0:0] IS_WCLK_INVERTED = 1'b0; | ||||||
|  |  | ||||||
							
								
								
									
										42
									
								
								techlibs/xilinx/ff_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								techlibs/xilinx/ff_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | /* | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | // ============================================================================ | ||||||
|  | // FF mapping | ||||||
|  | 
 | ||||||
|  | `ifndef _NO_FFS | ||||||
|  | 
 | ||||||
|  | module  \$_DFF_N_   (input D, C, output Q);    FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule | ||||||
|  | module  \$_DFF_P_   (input D, C, output Q);    FDRE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); endmodule | ||||||
|  | module  \$_DFFE_PP_ (input D, C, E, output Q); FDRE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$_DFF_NN0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule | ||||||
|  | module  \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule | ||||||
|  | module  \$_DFF_PN0_ (input D, C, R, output Q); FDCE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule | ||||||
|  | module  \$_DFF_PP0_ (input D, C, R, output Q); FDCE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule | ||||||
|  | module  \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule | ||||||
|  | module  \$_DFF_PN1_ (input D, C, R, output Q); FDPE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule | ||||||
|  | module  \$_DFF_PP1_ (input D, C, R, output Q); FDPE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule | ||||||
|  | 
 | ||||||
|  | `endif | ||||||
|  | 
 | ||||||
|  | @ -1,65 +0,0 @@ | ||||||
| module LUT1(output O, input I0); |  | ||||||
|   parameter [1:0] INIT = 0; |  | ||||||
|   \$lut #( |  | ||||||
|     .WIDTH(1), |  | ||||||
|     .LUT(INIT) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .A(I0), |  | ||||||
|     .Y(O) |  | ||||||
|   ); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module LUT2(output O, input I0, I1); |  | ||||||
|   parameter [3:0] INIT = 0; |  | ||||||
|   \$lut #( |  | ||||||
|     .WIDTH(2), |  | ||||||
|     .LUT(INIT) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .A({I1, I0}), |  | ||||||
|     .Y(O) |  | ||||||
|   ); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module LUT3(output O, input I0, I1, I2); |  | ||||||
|   parameter [7:0] INIT = 0; |  | ||||||
|   \$lut #( |  | ||||||
|     .WIDTH(3), |  | ||||||
|     .LUT(INIT) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .A({I2, I1, I0}), |  | ||||||
|     .Y(O) |  | ||||||
|   ); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module LUT4(output O, input I0, I1, I2, I3); |  | ||||||
|   parameter [15:0] INIT = 0; |  | ||||||
|   \$lut #( |  | ||||||
|     .WIDTH(4), |  | ||||||
|     .LUT(INIT) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .A({I3, I2, I1, I0}), |  | ||||||
|     .Y(O) |  | ||||||
|   ); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module LUT5(output O, input I0, I1, I2, I3, I4); |  | ||||||
|   parameter [31:0] INIT = 0; |  | ||||||
|   \$lut #( |  | ||||||
|     .WIDTH(5), |  | ||||||
|     .LUT(INIT) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .A({I4, I3, I2, I1, I0}), |  | ||||||
|     .Y(O) |  | ||||||
|   ); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module LUT6(output O, input I0, I1, I2, I3, I4, I5); |  | ||||||
|   parameter [63:0] INIT = 0; |  | ||||||
|   \$lut #( |  | ||||||
|     .WIDTH(6), |  | ||||||
|     .LUT(INIT) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .A({I5, I4, I3, I2, I1, I0}), |  | ||||||
|     .Y(O) |  | ||||||
|   ); |  | ||||||
| endmodule |  | ||||||
							
								
								
									
										94
									
								
								techlibs/xilinx/lut_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								techlibs/xilinx/lut_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,94 @@ | ||||||
|  | /* | ||||||
|  |  *  yosys -- Yosys Open SYnthesis Suite | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||||
|  |  * | ||||||
|  |  *  Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  |  *  purpose with or without fee is hereby granted, provided that the above | ||||||
|  |  *  copyright notice and this permission notice appear in all copies. | ||||||
|  |  * | ||||||
|  |  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||||
|  |  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  |  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||||
|  |  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||||
|  |  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||||
|  |  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|  |  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | // ============================================================================ | ||||||
|  | // LUT mapping | ||||||
|  | 
 | ||||||
|  | `ifndef _NO_LUTS | ||||||
|  | 
 | ||||||
|  | module \$lut (A, Y); | ||||||
|  |   parameter WIDTH = 0; | ||||||
|  |   parameter LUT = 0; | ||||||
|  | 
 | ||||||
|  |   input [WIDTH-1:0] A; | ||||||
|  |   output Y; | ||||||
|  | 
 | ||||||
|  |   generate | ||||||
|  |     if (WIDTH == 1) begin | ||||||
|  |       LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|  |         .I0(A[0])); | ||||||
|  |     end else | ||||||
|  |     if (WIDTH == 2) begin | ||||||
|  |       LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|  |         .I0(A[0]), .I1(A[1])); | ||||||
|  |     end else | ||||||
|  |     if (WIDTH == 3) begin | ||||||
|  |       LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2])); | ||||||
|  |     end else | ||||||
|  |     if (WIDTH == 4) begin | ||||||
|  |       LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3])); | ||||||
|  |     end else | ||||||
|  |     if (WIDTH == 5) begin | ||||||
|  |       LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4])); | ||||||
|  |     end else | ||||||
|  |     if (WIDTH == 6) begin | ||||||
|  |       LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|  |     end else | ||||||
|  |     if (WIDTH == 7) begin | ||||||
|  |       wire T0, T1; | ||||||
|  |       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|  |       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|  |       MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); | ||||||
|  |     end else | ||||||
|  |     if (WIDTH == 8) begin | ||||||
|  |       wire T0, T1, T2, T3, T4, T5; | ||||||
|  |       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|  |       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|  |       LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|  |       LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), | ||||||
|  |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|  |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|  |       MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); | ||||||
|  |       MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); | ||||||
|  |       MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); | ||||||
|  |     end else begin | ||||||
|  |       wire _TECHMAP_FAIL_ = 1; | ||||||
|  |     end | ||||||
|  |   endgenerate | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | `endif | ||||||
|  | 
 | ||||||
|  | @ -63,6 +63,12 @@ struct SynthXilinxPass : public Pass | ||||||
| 		log("        generate an output netlist (and BLIF file) suitable for VPR\n"); | 		log("        generate an output netlist (and BLIF file) suitable for VPR\n"); | ||||||
| 		log("        (this feature is experimental and incomplete)\n"); | 		log("        (this feature is experimental and incomplete)\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -nobram\n"); | ||||||
|  | 		log("        disable infering of block rams\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -nodram\n"); | ||||||
|  | 		log("        disable infering of distributed rams\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -run <from_label>:<to_label>\n"); | 		log("    -run <from_label>:<to_label>\n"); | ||||||
| 		log("        only run the commands between the labels (see below). an empty\n"); | 		log("        only run the commands between the labels (see below). an empty\n"); | ||||||
| 		log("        from label is synonymous to 'begin', and empty to label is\n"); | 		log("        from label is synonymous to 'begin', and empty to label is\n"); | ||||||
|  | @ -90,11 +96,11 @@ struct SynthXilinxPass : public Pass | ||||||
| 		log("    coarse:\n"); | 		log("    coarse:\n"); | ||||||
| 		log("        synth -run coarse\n"); | 		log("        synth -run coarse\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    bram:\n"); | 		log("    bram: (only executed when '-nobram' is not given)\n"); | ||||||
| 		log("        memory_bram -rules +/xilinx/brams.txt\n"); | 		log("        memory_bram -rules +/xilinx/brams.txt\n"); | ||||||
| 		log("        techmap -map +/xilinx/brams_map.v\n"); | 		log("        techmap -map +/xilinx/brams_map.v\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    dram:\n"); | 		log("    dram: (only executed when '-nodram' is not given)\n"); | ||||||
| 		log("        memory_bram -rules +/xilinx/drams.txt\n"); | 		log("        memory_bram -rules +/xilinx/drams.txt\n"); | ||||||
| 		log("        techmap -map +/xilinx/drams_map.v\n"); | 		log("        techmap -map +/xilinx/drams_map.v\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -106,15 +112,17 @@ struct SynthXilinxPass : public Pass | ||||||
| 		log("        opt -full\n"); | 		log("        opt -full\n"); | ||||||
| 		log("        techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); | 		log("        techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); | ||||||
| 		log("        shregmap -init_msb_first -params -enpol any_or_none\n"); | 		log("        shregmap -init_msb_first -params -enpol any_or_none\n"); | ||||||
|  | 		log("        techmap -map +/xilinx/ff_map.v\n"); | ||||||
| 		log("        opt -fast\n"); | 		log("        opt -fast\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    map_luts:\n"); | 		log("    map_luts:\n"); | ||||||
| 		log("        abc -luts 2:2,3,6:5,10,20 [-dff]\n"); | 		log("        abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)\n"); | ||||||
|  | 		log("        abc -lut 5 [-dff] (with '-vpr' only!)\n"); | ||||||
| 		log("        clean\n"); | 		log("        clean\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    map_cells:\n"); | 		log("    map_cells:\n"); | ||||||
| 		log("        techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n"); | 		log("        techmap -map +/xilinx/cells_map.v\n"); | ||||||
| 		log("        dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n"); | 		log("        dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT\n"); | ||||||
| 		log("        clean\n"); | 		log("        clean\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    check:\n"); | 		log("    check:\n"); | ||||||
|  | @ -138,6 +146,8 @@ struct SynthXilinxPass : public Pass | ||||||
| 		bool flatten = false; | 		bool flatten = false; | ||||||
| 		bool retime = false; | 		bool retime = false; | ||||||
| 		bool vpr = false; | 		bool vpr = false; | ||||||
|  | 		bool nobram = false; | ||||||
|  | 		bool nodram = false; | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
|  | @ -174,6 +184,14 @@ struct SynthXilinxPass : public Pass | ||||||
| 				vpr = true; | 				vpr = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-nobram") { | ||||||
|  | 				nobram = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (args[argidx] == "-nodram") { | ||||||
|  | 				nodram = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
|  | @ -188,9 +206,18 @@ struct SynthXilinxPass : public Pass | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "begin")) | 		if (check_label(active, run_from, run_to, "begin")) | ||||||
| 		{ | 		{ | ||||||
| 			Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v"); | 			if (vpr) { | ||||||
|  | 				Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); | ||||||
|  | 			} else { | ||||||
|  | 				Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); | 			Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); | ||||||
| 			Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); | 
 | ||||||
|  | 			if (!nobram) { | ||||||
|  | 				Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str())); | 			Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str())); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -207,14 +234,18 @@ struct SynthXilinxPass : public Pass | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "bram")) | 		if (check_label(active, run_from, run_to, "bram")) | ||||||
| 		{ | 		{ | ||||||
| 			Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); | 			if (!nobram) { | ||||||
| 			Pass::call(design, "techmap -map +/xilinx/brams_map.v"); | 				Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); | ||||||
|  | 				Pass::call(design, "techmap -map +/xilinx/brams_map.v"); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "dram")) | 		if (check_label(active, run_from, run_to, "dram")) | ||||||
| 		{ | 		{ | ||||||
| 			Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); | 			if (!nodram) { | ||||||
| 			Pass::call(design, "techmap -map +/xilinx/drams_map.v"); | 				Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); | ||||||
|  | 				Pass::call(design, "techmap -map +/xilinx/drams_map.v"); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "fine")) | 		if (check_label(active, run_from, run_to, "fine")) | ||||||
|  | @ -224,8 +255,16 @@ struct SynthXilinxPass : public Pass | ||||||
| 			Pass::call(design, "dffsr2dff"); | 			Pass::call(design, "dffsr2dff"); | ||||||
| 			Pass::call(design, "dff2dffe"); | 			Pass::call(design, "dff2dffe"); | ||||||
| 			Pass::call(design, "opt -full"); | 			Pass::call(design, "opt -full"); | ||||||
| 			Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); | 
 | ||||||
|  | 			if (vpr) { | ||||||
|  | 				Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); | ||||||
|  | 			} else { | ||||||
|  | 				Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			Pass::call(design, "shregmap -init_msb_first -params -enpol any_or_none"); | 			Pass::call(design, "shregmap -init_msb_first -params -enpol any_or_none"); | ||||||
|  | 			Pass::call(design, "techmap -map +/xilinx/ff_map.v"); | ||||||
|  | 			Pass::call(design, "hierarchy -check"); | ||||||
| 			Pass::call(design, "opt -fast"); | 			Pass::call(design, "opt -fast"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -233,14 +272,13 @@ struct SynthXilinxPass : public Pass | ||||||
| 		{ | 		{ | ||||||
| 			Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); | 			Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); | ||||||
| 			Pass::call(design, "clean"); | 			Pass::call(design, "clean"); | ||||||
|  | 			Pass::call(design, "techmap -map +/xilinx/lut_map.v"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "map_cells")) | 		if (check_label(active, run_from, run_to, "map_cells")) | ||||||
| 		{ | 		{ | ||||||
| 			Pass::call(design, "techmap -map +/xilinx/cells_map.v"); | 			Pass::call(design, "techmap -map +/xilinx/cells_map.v"); | ||||||
| 			if (vpr) | 			Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT"); | ||||||
| 			    Pass::call(design, "techmap -map +/xilinx/lut2lut.v"); |  | ||||||
| 			Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT"); |  | ||||||
| 			Pass::call(design, "clean"); | 			Pass::call(design, "clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -254,7 +292,7 @@ struct SynthXilinxPass : public Pass | ||||||
| 		if (check_label(active, run_from, run_to, "edif")) | 		if (check_label(active, run_from, run_to, "edif")) | ||||||
| 		{ | 		{ | ||||||
| 			if (!edif_file.empty()) | 			if (!edif_file.empty()) | ||||||
| 				Pass::call(design, stringf("write_edif %s", edif_file.c_str())); | 				Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str())); | ||||||
| 		} | 		} | ||||||
| 		if (check_label(active, run_from, run_to, "blif")) | 		if (check_label(active, run_from, run_to, "blif")) | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ code_hdl_models_d_latch_gates.v	combinational loop | ||||||
| code_hdl_models_dff_async_reset.v	$adff | code_hdl_models_dff_async_reset.v	$adff | ||||||
| code_hdl_models_tff_async_reset.v	$adff | code_hdl_models_tff_async_reset.v	$adff | ||||||
| code_hdl_models_uart.v	$adff | code_hdl_models_uart.v	$adff | ||||||
| code_specman_switch_fabric.v	subfield assignment (bits() <= ...) |  | ||||||
| code_tidbits_asyn_reset.v	$adff | code_tidbits_asyn_reset.v	$adff | ||||||
| code_tidbits_reg_seq_example.v	$adff | code_tidbits_reg_seq_example.v	$adff | ||||||
| code_verilog_tutorial_always_example.v	empty module | code_verilog_tutorial_always_example.v	empty module | ||||||
|  |  | ||||||
|  | @ -120,3 +120,22 @@ module task_func_test04(input [7:0] in, output [7:0] out1, out2, out3, out4); | ||||||
| 	assign out3 = test3(in); | 	assign out3 = test3(in); | ||||||
| 	assign out4 = test4(in); | 	assign out4 = test4(in); | ||||||
| endmodule | endmodule | ||||||
|  | 
 | ||||||
|  | // ------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | // https://github.com/YosysHQ/yosys/issues/857 | ||||||
|  | module task_func_test05(data_in,data_out,clk); | ||||||
|  | 	output reg data_out; | ||||||
|  | 	input data_in; | ||||||
|  | 	input clk; | ||||||
|  | 
 | ||||||
|  | 	task myTask; | ||||||
|  | 		output out; | ||||||
|  | 		input in; | ||||||
|  | 		out = in; | ||||||
|  | 	endtask | ||||||
|  | 
 | ||||||
|  | 	always @(posedge clk) begin | ||||||
|  | 		myTask(data_out,data_in); | ||||||
|  | 	end | ||||||
|  | endmodule | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| # This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures. | # This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures. | ||||||
| arraycells.v	inst id[0] of | arraycells.v	inst id[0] of | ||||||
| dff_different_styles.v | dff_different_styles.v | ||||||
|  | dff_init.v	Initial value not supported | ||||||
| generate.v	combinational loop | generate.v	combinational loop | ||||||
| hierdefparam.v	inst id[0] of | hierdefparam.v	inst id[0] of | ||||||
| i2c_master_tests.v   $adff | i2c_master_tests.v   $adff | ||||||
|  | @ -12,7 +13,6 @@ multiplier.v	inst id[0] of | ||||||
| muxtree.v	drops modules | muxtree.v	drops modules | ||||||
| omsp_dbg_uart.v	$adff | omsp_dbg_uart.v	$adff | ||||||
| operators.v	$pow | operators.v	$pow | ||||||
| paramods.v	subfield assignment (bits() <= ...) |  | ||||||
| partsel.v	drops modules | partsel.v	drops modules | ||||||
| process.v	drops modules | process.v	drops modules | ||||||
| realexpr.v	drops modules | realexpr.v	drops modules | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ verbose=false | ||||||
| keeprunning=false | keeprunning=false | ||||||
| makejmode=false | makejmode=false | ||||||
| frontend="verilog" | frontend="verilog" | ||||||
| backend_opts="-noattr -noexpr" | backend_opts="-noattr -noexpr -siminit" | ||||||
| autotb_opts="" | autotb_opts="" | ||||||
| include_opts="" | include_opts="" | ||||||
| xinclude_opts="" | xinclude_opts="" | ||||||
|  | @ -49,7 +49,7 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do | ||||||
| 		r) | 		r) | ||||||
| 			backend_opts="$backend_opts -norename" ;; | 			backend_opts="$backend_opts -norename" ;; | ||||||
| 		e) | 		e) | ||||||
| 			backend_opts="$( echo " $backend_opts " | sed 's, -noexpr ,,; s,^ ,,; s, $,,;'; )" ;; | 			backend_opts="$( echo " $backend_opts " | sed 's, -noexpr , ,; s,^ ,,; s, $,,;'; )" ;; | ||||||
| 		f) | 		f) | ||||||
| 			frontend="$OPTARG" ;; | 			frontend="$OPTARG" ;; | ||||||
| 		s) | 		s) | ||||||
|  | @ -175,7 +175,7 @@ do | ||||||
| 			if [ -n "$firrtl2verilog" ]; then | 			if [ -n "$firrtl2verilog" ]; then | ||||||
| 			    if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then | 			    if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then | ||||||
| 				"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v | 				"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v | ||||||
| 				$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v  -X verilog | 				$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v | ||||||
| 				test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v | 				test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v | ||||||
| 			    fi | 			    fi | ||||||
| 			fi | 			fi | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue