mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into xaig_dff
This commit is contained in:
		
						commit
						09ee96e8c2
					
				
					 228 changed files with 35110 additions and 24029 deletions
				
			
		
							
								
								
									
										46
									
								
								CodingReadme
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								CodingReadme
									
										
									
									
									
								
							|  | @ -202,6 +202,52 @@ of how to use the Yosys API: | |||
| 	manual/PRESENTATION_Prog/my_cmd.cc | ||||
| 
 | ||||
| 
 | ||||
| Script Passes | ||||
| ------------- | ||||
| 
 | ||||
| The ScriptPass base class can be used to implement passes that just call other passes, | ||||
| like a script. Examples for such passes are: | ||||
| 
 | ||||
| 	techlibs/common/prep.cc | ||||
| 	techlibs/common/synth.cc | ||||
| 
 | ||||
| In some cases it is easier to implement such a pass as regular pass, for example when | ||||
| ScriptPass doesn't provide the type of flow control desired. (But many of the | ||||
| script passes in Yosys that don't use ScriptPass simply predate the ScriptPass base | ||||
| class.) Examples for such passes are: | ||||
| 
 | ||||
| 	passes/opt/opt.cc | ||||
| 	passes/proc/proc.cc | ||||
| 
 | ||||
| Whether they use the ScriptPass base-class or not, a pass should always either | ||||
| call other passes without doing any non-trivial work itself, or should implement | ||||
| a non-trivial algorithm but not call any other passes. The reason for this is that | ||||
| this helps containing complexity in individual passes and simplifies debugging the | ||||
| entire system. | ||||
| 
 | ||||
| Exceptions to this rule should be rare and limited to cases where calling other | ||||
| passes is optional and only happens when requested by the user (such as for | ||||
| example `techmap -autoproc`), or where it is about commands that are "top-level | ||||
| commands" in their own right, not components to be used in regular synthesis | ||||
| flows (such as the `bugpoint` command). | ||||
| 
 | ||||
| A pass that would "naturally" call other passes and also do some work itself | ||||
| should be re-written in one of two ways: | ||||
| 
 | ||||
| 1) It could be re-written as script pass with the parts that are not calls | ||||
| to other passes factored out into individual new passes. Usually in those | ||||
| cases the new sub passes share the same prefix as the top-level script pass. | ||||
| 
 | ||||
| 2) It could be re-written so that it already expects the design in a certain | ||||
| state, expecting the calling script to set up this state before calling the | ||||
| pass in questions. | ||||
| 
 | ||||
| Many back-ends are examples for the 2nd approach. For example, `write_aiger` | ||||
| does not convert the design into AIG representation, but expects the design | ||||
| to be already in this form, and prints an `Unsupported cell type` error | ||||
| message otherwise. | ||||
| 
 | ||||
| 
 | ||||
| Notes on the existing codebase | ||||
| ------------------------------ | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -147,9 +147,9 @@ $(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$ | |||
| include Makefile.conf | ||||
| endif | ||||
| 
 | ||||
| PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi) | ||||
| ifeq ($(ENABLE_PYOSYS),1) | ||||
| PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)" | ||||
| PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi) | ||||
| PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"") | ||||
| PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.) | ||||
| PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix) | ||||
|  | @ -708,11 +708,17 @@ test: $(TARGETS) $(EXTRA_TARGETS) | |||
| 	+cd tests/various && bash run-test.sh | ||||
| 	+cd tests/sat && bash run-test.sh | ||||
| 	+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/svtypes && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/proc && bash run-test.sh | ||||
| 	+cd tests/opt && bash run-test.sh | ||||
| 	+cd tests/aiger && bash run-test.sh $(ABCOPT) | ||||
| 	+cd tests/arch && bash run-test.sh | ||||
| 	+cd tests/ice40 && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/arch/ice40 && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/arch/xilinx && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/arch/ecp5 && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/arch/efinix && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/rpc && bash run-test.sh | ||||
| 	@echo "" | ||||
| 	@echo "  Passed \"make test\"." | ||||
|  |  | |||
|  | @ -510,6 +510,8 @@ from SystemVerilog: | |||
|   into a design with ``read_verilog``, all its packages are available to | ||||
|   SystemVerilog files being read into the same design afterwards. | ||||
| 
 | ||||
| - typedefs are supported (including inside packages) | ||||
| 
 | ||||
| - SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether | ||||
|   ports are inputs or outputs are supported. | ||||
| 
 | ||||
|  |  | |||
|  | @ -91,6 +91,9 @@ struct AigerWriter | |||
| 		} else | ||||
| 		if (alias_map.count(bit)) { | ||||
| 			a = bit2aig(alias_map.at(bit)); | ||||
| 		} else | ||||
| 		if (initstate_bits.count(bit)) { | ||||
| 			a = initstate_ff; | ||||
| 		} | ||||
| 
 | ||||
| 		if (bit == State::Sx || bit == State::Sz) | ||||
|  |  | |||
|  | @ -1070,7 +1070,12 @@ struct BtorWorker | |||
| 					bad_properties.push_back(nid_en_and_not_a); | ||||
| 				} else { | ||||
| 					int nid = next_nid++; | ||||
| 					btorf("%d bad %d\n", nid, nid_en_and_not_a); | ||||
| 					string infostr = log_id(cell); | ||||
| 					if (infostr[0] == '$' && cell->attributes.count("\\src")) { | ||||
| 						infostr = cell->attributes.at("\\src").decode_string().c_str(); | ||||
| 						std::replace(infostr.begin(), infostr.end(), ' ', '_'); | ||||
| 					} | ||||
| 					btorf("%d bad %d %s\n", nid, nid_en_and_not_a, infostr.c_str()); | ||||
| 				} | ||||
| 
 | ||||
| 				btorf_pop(log_id(cell)); | ||||
|  |  | |||
|  | @ -1032,12 +1032,17 @@ class MkVcd: | |||
|                 print("$var integer 32 t smt_step $end", file=self.f) | ||||
|                 print("$var event 1 ! smt_clock $end", file=self.f) | ||||
| 
 | ||||
|                 def vcdescape(n): | ||||
|                     if n.startswith("$") or ":" in n: | ||||
|                         return "\\" + n | ||||
|                     return n | ||||
| 
 | ||||
|                 scope = [] | ||||
|                 for path in sorted(self.nets): | ||||
|                     key, width = self.nets[path] | ||||
| 
 | ||||
|                     uipath = list(path) | ||||
|                     if "." in uipath[-1]: | ||||
|                     if "." in uipath[-1] and not uipath[-1].startswith("$"): | ||||
|                         uipath = uipath[0:-1] + uipath[-1].split(".") | ||||
|                     for i in range(len(uipath)): | ||||
|                         uipath[i] = re.sub(r"\[([^\]]*)\]", r"<\1>", uipath[i]) | ||||
|  | @ -1048,15 +1053,13 @@ class MkVcd: | |||
| 
 | ||||
|                     while uipath[:-1] != scope: | ||||
|                         scopename = uipath[len(scope)] | ||||
|                         if scopename.startswith("$"): | ||||
|                             scopename = "\\" + scopename | ||||
|                         print("$scope module %s $end" % scopename, file=self.f) | ||||
|                         print("$scope module %s $end" % vcdescape(scopename), file=self.f) | ||||
|                         scope.append(uipath[len(scope)]) | ||||
| 
 | ||||
|                     if path in self.clocks and self.clocks[path][1] == "event": | ||||
|                         print("$var event 1 %s %s $end" % (key, uipath[-1]), file=self.f) | ||||
|                         print("$var event 1 %s %s $end" % (key, vcdescape(uipath[-1])), file=self.f) | ||||
|                     else: | ||||
|                         print("$var wire %d %s %s $end" % (width, key, uipath[-1]), file=self.f) | ||||
|                         print("$var wire %d %s %s $end" % (width, key, vcdescape(uipath[-1])), file=self.f) | ||||
| 
 | ||||
|                 for i in range(len(scope)): | ||||
|                     print("$upscope $end", file=self.f) | ||||
|  |  | |||
|  | @ -33,11 +33,11 @@ | |||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit; | ||||
| int auto_name_counter, auto_name_offset, auto_name_digits; | ||||
| bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit; | ||||
| int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter; | ||||
| std::map<RTLIL::IdString, int> auto_name_map; | ||||
| std::set<RTLIL::IdString> reg_wires, reg_ct; | ||||
| std::string auto_prefix; | ||||
| std::string auto_prefix, extmem_prefix; | ||||
| 
 | ||||
| RTLIL::Module *active_module; | ||||
| dict<RTLIL::SigBit, RTLIL::State> active_initdata; | ||||
|  | @ -371,13 +371,14 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n', bool modattr = false, bool as_comment = false) | ||||
| void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n', bool modattr = false, bool regattr = false, bool as_comment = false) | ||||
| { | ||||
| 	if (noattr) | ||||
| 		return; | ||||
| 	if (attr2comment) | ||||
| 		as_comment = true; | ||||
| 	for (auto it = attributes.begin(); it != attributes.end(); ++it) { | ||||
| 		if (it->first == "\\init" && regattr) continue; | ||||
| 		f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str()); | ||||
| 		f << stringf(" = "); | ||||
| 		if (modattr && (it->second == State::S0 || it->second == Const(0))) | ||||
|  | @ -392,7 +393,7 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, | |||
| 
 | ||||
| void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) | ||||
| { | ||||
| 	dump_attributes(f, indent, wire->attributes); | ||||
| 	dump_attributes(f, indent, wire->attributes, '\n', /*modattr=*/false, /*regattr=*/reg_wires.count(wire->name)); | ||||
| #if 0 | ||||
| 	if (wire->port_input && !wire->port_output) | ||||
| 		f << stringf("%s" "input %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : ""); | ||||
|  | @ -1067,6 +1068,55 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) | |||
| 		//  end
 | ||||
| 		f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size+offset-1, offset); | ||||
| 		if (use_init) | ||||
| 		{ | ||||
| 			if (extmem) | ||||
| 			{ | ||||
| 				std::string extmem_filename = stringf("%s-%d.mem", extmem_prefix.c_str(), extmem_counter++); | ||||
| 
 | ||||
| 				std::string extmem_filename_esc; | ||||
| 				for (auto c : extmem_filename) | ||||
| 				{ | ||||
| 					if (c == '\n') | ||||
| 						extmem_filename_esc += "\\n"; | ||||
| 					else if (c == '\t') | ||||
| 						extmem_filename_esc += "\\t"; | ||||
| 					else if (c < 32) | ||||
| 						extmem_filename_esc += stringf("\\%03o", c); | ||||
| 					else if (c == '"') | ||||
| 						extmem_filename_esc += "\\\""; | ||||
| 					else if (c == '\\') | ||||
| 						extmem_filename_esc += "\\\\"; | ||||
| 					else | ||||
| 						extmem_filename_esc += c; | ||||
| 				} | ||||
| 				f << stringf("%s" "initial $readmemb(\"%s\", %s);\n", indent.c_str(), extmem_filename_esc.c_str(), mem_id.c_str()); | ||||
| 
 | ||||
| 				std::ofstream extmem_f(extmem_filename, std::ofstream::trunc); | ||||
| 				if (extmem_f.fail()) | ||||
| 					log_error("Can't open file `%s' for writing: %s\n", extmem_filename.c_str(), strerror(errno)); | ||||
| 				else | ||||
| 				{ | ||||
| 					for (int i=0; i<size; i++) | ||||
| 					{ | ||||
| 						RTLIL::Const element = cell->parameters["\\INIT"].extract(i*width, width); | ||||
| 						for (int j=0; j<element.size(); j++) | ||||
| 						{ | ||||
| 							switch (element[element.size()-j-1]) | ||||
| 							{ | ||||
| 								case State::S0: extmem_f << '0'; break; | ||||
| 								case State::S1: extmem_f << '1'; break; | ||||
| 								case State::Sx: extmem_f << 'x'; break; | ||||
| 								case State::Sz: extmem_f << 'z'; break; | ||||
| 								case State::Sa: extmem_f << '_'; break; | ||||
| 								case State::Sm: log_error("Found marker state in final netlist."); | ||||
| 							} | ||||
| 						} | ||||
| 						extmem_f << '\n'; | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				f << stringf("%s" "initial begin\n", indent.c_str()); | ||||
| 				for (int i=0; i<size; i++) | ||||
|  | @ -1077,6 +1127,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) | |||
| 				} | ||||
| 				f << stringf("%s" "end\n", indent.c_str()); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// create a map : "edge clk" -> expressions within that clock domain
 | ||||
| 		dict<std::string, std::vector<std::string>> clk_to_lof_body; | ||||
|  | @ -1521,7 +1572,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw | |||
| 
 | ||||
| 	bool got_default = false; | ||||
| 	for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { | ||||
| 		dump_attributes(f, indent + "  ", (*it)->attributes, '\n', /*modattr=*/false, /*as_comment=*/true); | ||||
| 		dump_attributes(f, indent + "  ", (*it)->attributes, '\n', /*modattr=*/false, /*regattr=*/false, /*as_comment=*/true); | ||||
| 		if ((*it)->compare.size() == 0) { | ||||
| 			if (got_default) | ||||
| 				continue; | ||||
|  | @ -1686,7 +1737,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	dump_attributes(f, indent, module->attributes, '\n', /*attr2comment=*/true); | ||||
| 	dump_attributes(f, indent, module->attributes, '\n', /*modattr=*/true); | ||||
| 	f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str()); | ||||
| 	bool keep_running = true; | ||||
| 	for (int port_id = 1; keep_running; port_id++) { | ||||
|  | @ -1776,8 +1827,16 @@ struct VerilogBackend : public Backend { | |||
| 		log("        deactivates this feature and instead will write string constants\n"); | ||||
| 		log("        as binary numbers.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -extmem\n"); | ||||
| 		log("        instead of initializing memories using assignments to individual\n"); | ||||
| 		log("        elements, use the '$readmemh' function to read initialization data\n"); | ||||
| 		log("        from a file. This data is written to a file named by appending\n"); | ||||
| 		log("        a sequential index to the Verilog filename and replacing the extension\n"); | ||||
| 		log("        with '.mem', e.g. 'write_verilog -extmem foo.v' writes 'foo-1.mem',\n"); | ||||
| 		log("        'foo-2.mem' and so on.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -defparam\n"); | ||||
| 		log("        Use 'defparam' statements instead of the Verilog-2001 syntax for\n"); | ||||
| 		log("        use 'defparam' statements instead of the Verilog-2001 syntax for\n"); | ||||
| 		log("        cell parameters.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -blackboxes\n"); | ||||
|  | @ -1811,6 +1870,7 @@ struct VerilogBackend : public Backend { | |||
| 		nodec = false; | ||||
| 		nohex = false; | ||||
| 		nostr = false; | ||||
| 		extmem = false; | ||||
| 		defparam = false; | ||||
| 		decimal = false; | ||||
| 		siminit = false; | ||||
|  | @ -1884,6 +1944,11 @@ struct VerilogBackend : public Backend { | |||
| 				nostr = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-extmem") { | ||||
| 				extmem = true; | ||||
| 				extmem_counter = 1; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-defparam") { | ||||
| 				defparam = true; | ||||
| 				continue; | ||||
|  | @ -1911,6 +1976,12 @@ struct VerilogBackend : public Backend { | |||
| 			break; | ||||
| 		} | ||||
| 		extra_args(f, filename, args, argidx); | ||||
| 		if (extmem) | ||||
| 		{ | ||||
| 			if (filename.empty()) | ||||
| 				log_cmd_error("Option -extmem must be used with a filename.\n"); | ||||
| 			extmem_prefix = filename.substr(0, filename.rfind('.')); | ||||
| 		} | ||||
| 
 | ||||
| 		design->sort(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,41 +1,10 @@ | |||
| // 50 MHz Clock | ||||
| IO_LOC "clk" D11; | ||||
| 
 | ||||
| // LEDs | ||||
| IO_LOC "leds[0]"  D22; | ||||
| IO_LOC "leds[1]"  E22; | ||||
| IO_LOC "leds[2]"  G22; | ||||
| IO_LOC "leds[3]"  J22; | ||||
| IO_LOC "leds[4]"  L22; | ||||
| IO_LOC "leds[5]"  L19; | ||||
| IO_LOC "leds[6]"  L20; | ||||
| IO_LOC "leds[7]"  M21; | ||||
| IO_LOC "leds[8]"  N19; | ||||
| IO_LOC "leds[9]"  R19; | ||||
| IO_LOC "leds[10]" T18; | ||||
| IO_LOC "leds[11]" AA22; | ||||
| IO_LOC "leds[12]" U18; | ||||
| IO_LOC "leds[13]" V20; | ||||
| IO_LOC "leds[14]" AA21; | ||||
| IO_LOC "leds[15]" AB21; | ||||
| 
 | ||||
| 
 | ||||
| // 7-Segment Display | ||||
| IO_LOC "seg7dig[0]" E20; | ||||
| IO_LOC "seg7dig[1]" G18; | ||||
| IO_LOC "seg7dig[2]" G20; | ||||
| IO_LOC "seg7dig[3]" F21; | ||||
| IO_LOC "seg7dig[4]" J20; | ||||
| IO_LOC "seg7dig[5]" H21; | ||||
| IO_LOC "seg7dig[6]" H18; | ||||
| IO_LOC "seg7dig[7]" D20; | ||||
| IO_LOC "seg7sel[0]" C19; | ||||
| IO_LOC "seg7sel[1]" B22; | ||||
| IO_LOC "seg7sel[2]" C20; | ||||
| IO_LOC "seg7sel[3]" C21; | ||||
| 
 | ||||
| // Switches | ||||
| IO_LOC "sw[0]" AB20; | ||||
| IO_LOC "sw[1]" AB19; | ||||
| IO_LOC "sw[2]" AB18; | ||||
| IO_LOC "sw[3]" AB17; | ||||
| IO_LOC "clk" 35; | ||||
| //IO_LOC "rst_n" 77; | ||||
| IO_LOC "leds[0]" 79; | ||||
| IO_LOC "leds[1]" 80; | ||||
| IO_LOC "leds[2]" 81; | ||||
| IO_LOC "leds[3]" 82; | ||||
| IO_LOC "leds[4]" 83; | ||||
| IO_LOC "leds[5]" 84; | ||||
| IO_LOC "leds[6]" 85; | ||||
| IO_LOC "leds[7]" 86; | ||||
|  | @ -1,9 +1,7 @@ | |||
| module demo ( | ||||
| 	input clk, | ||||
| 	input [3:0] sw, | ||||
| 	output [15:0] leds, | ||||
| 	output [7:0] seg7dig, | ||||
| 	output [3:0] seg7sel | ||||
| 	output unused | ||||
| ); | ||||
| 	localparam PRESCALE = 20; | ||||
| 	reg [PRESCALE+3:0] counter = 0; | ||||
|  |  | |||
							
								
								
									
										16
									
								
								examples/gowin/device.cfg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								examples/gowin/device.cfg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| set JTAG regular_io = false | ||||
| set SSPI regular_io = false | ||||
| set MSPI regular_io = false | ||||
| set READY regular_io = false | ||||
| set DONE regular_io = false | ||||
| set RECONFIG_N regular_io = false | ||||
| set MODE regular_io = false | ||||
| set CRC_check = true | ||||
| set compress = false | ||||
| set encryption = false | ||||
| set security_bit_enable = true | ||||
| set bsram_init_fuse_print = true | ||||
| set download_speed = 250/100 | ||||
| set spi_flash_address = 0x00FFF000 | ||||
| set format = txt | ||||
| set background_programming = false | ||||
							
								
								
									
										8
									
								
								examples/gowin/pnr.cfg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								examples/gowin/pnr.cfg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| -sdf | ||||
| -oc | ||||
| -ibs | ||||
| -posp | ||||
| -o | ||||
| -warning_all | ||||
| -tt | ||||
| -timing | ||||
|  | @ -1,8 +1,7 @@ | |||
| #!/bin/bash | ||||
| set -ex | ||||
| yosys -p "synth_gowin -top demo -vout demo_syn.v" demo.v | ||||
| $GOWIN_HOME/bin/gowin -d demo_syn.v -cst demo.cst -sdc demo.sdc -p GW2A55-PBGA484-6 \ | ||||
| 		-warning_all -out demo_out.v -rpt demo.rpt -tr demo_tr.html -bit demo.bit | ||||
| $GOWIN_HOME/bin/gowin -d demo_syn.v -cst demo.cst -sdc demo.sdc -p GW1NR-9-QFN88-6 -pn GW1NR-LV9QN88C6/I5 -cfg device.cfg -bit -tr -ph -timing -gpa -rpt -warning_all | ||||
| 
 | ||||
| # post place&route simulation (icarus verilog) | ||||
| if false; then | ||||
|  |  | |||
							
								
								
									
										9
									
								
								examples/gowin/run.tcl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								examples/gowin/run.tcl
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| # gw_sh run.tcl | ||||
| exec yosys -p "synth_gowin -top demo -vout demo_syn.v" demo.v | ||||
| add_file -cst demo.cst | ||||
| add_file -sdc demo.sdc | ||||
| add_file -vm demo_syn.v | ||||
| add_file -cfg device.cfg | ||||
| set_option -device GW1NR-9-QFN88-6 | ||||
| set_option -pn GW1NR-LV9QN88C6/I5 | ||||
| run_pnr -opt pnr.cfg | ||||
|  | @ -164,6 +164,8 @@ std::string AST::type2str(AstNodeType type) | |||
| 	X(AST_MODPORT) | ||||
| 	X(AST_MODPORTMEMBER) | ||||
| 	X(AST_PACKAGE) | ||||
| 	X(AST_WIRETYPE) | ||||
| 	X(AST_TYPEDEF) | ||||
| #undef X | ||||
| 	default: | ||||
| 		log_abort(); | ||||
|  | @ -206,6 +208,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch | |||
| 	was_checked = false; | ||||
| 	range_valid = false; | ||||
| 	range_swapped = false; | ||||
| 	is_custom_type = false; | ||||
| 	port_id = 0; | ||||
| 	range_left = -1; | ||||
| 	range_right = 0; | ||||
|  |  | |||
|  | @ -148,7 +148,10 @@ namespace AST | |||
| 		AST_INTERFACEPORTTYPE, | ||||
| 		AST_MODPORT, | ||||
| 		AST_MODPORTMEMBER, | ||||
| 		AST_PACKAGE | ||||
| 		AST_PACKAGE, | ||||
| 
 | ||||
| 		AST_WIRETYPE, | ||||
| 		AST_TYPEDEF | ||||
| 	}; | ||||
| 
 | ||||
| 	// convert an node type to a string (e.g. for debug output)
 | ||||
|  | @ -174,7 +177,7 @@ namespace AST | |||
| 		// node content - most of it is unused in most node types
 | ||||
| 		std::string str; | ||||
| 		std::vector<RTLIL::State> bits; | ||||
| 		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized; | ||||
| 		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type; | ||||
| 		int port_id, range_left, range_right; | ||||
| 		uint32_t integer; | ||||
| 		double realvalue; | ||||
|  |  | |||
|  | @ -863,6 +863,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | |||
| 	case AST_PACKAGE: | ||||
| 	case AST_MODPORT: | ||||
| 	case AST_MODPORTMEMBER: | ||||
| 	case AST_TYPEDEF: | ||||
| 		break; | ||||
| 	case AST_INTERFACEPORT: { | ||||
| 		// If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
 | ||||
|  |  | |||
|  | @ -318,7 +318,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 	} | ||||
| 
 | ||||
| 	// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
 | ||||
| 	if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) | ||||
| 	if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF) | ||||
| 		const_fold = true; | ||||
| 	if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) | ||||
| 		const_fold = true; | ||||
|  | @ -336,6 +336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 		std::map<std::string, AstNode*> this_wire_scope; | ||||
| 		for (size_t i = 0; i < children.size(); i++) { | ||||
| 			AstNode *node = children[i]; | ||||
| 
 | ||||
| 			if (node->type == AST_WIRE) { | ||||
| 				if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { | ||||
| 					for (auto c : node->children[0]->children) { | ||||
|  | @ -405,14 +406,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 				this_wire_scope[node->str] = node; | ||||
| 			} | ||||
| 			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || | ||||
| 					node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) { | ||||
| 					node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL || | ||||
| 					node->type == AST_TYPEDEF) { | ||||
| 				backup_scope[node->str] = current_scope[node->str]; | ||||
| 				current_scope[node->str] = node; | ||||
| 			} | ||||
| 		} | ||||
| 		for (size_t i = 0; i < children.size(); i++) { | ||||
| 			AstNode *node = children[i]; | ||||
| 			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY) | ||||
| 			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF) | ||||
| 				while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM)) | ||||
| 					did_something = true; | ||||
| 		} | ||||
|  | @ -780,6 +782,99 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 		delete_children(); | ||||
| 	} | ||||
| 
 | ||||
| 	// resolve typedefs
 | ||||
| 	if (type == AST_TYPEDEF) { | ||||
| 		log_assert(children.size() == 1); | ||||
| 		log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY); | ||||
| 		while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) | ||||
| 			did_something = true; | ||||
| 		log_assert(!children[0]->is_custom_type); | ||||
| 	} | ||||
| 
 | ||||
| 	// resolve types of wires
 | ||||
| 	if (type == AST_WIRE || type == AST_MEMORY) { | ||||
| 		if (is_custom_type) { | ||||
| 			log_assert(children.size() >= 1); | ||||
| 			log_assert(children[0]->type == AST_WIRETYPE); | ||||
| 			if (!current_scope.count(children[0]->str)) | ||||
| 				log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str()); | ||||
| 			AstNode *resolved_type = current_scope.at(children[0]->str); | ||||
| 			if (resolved_type->type != AST_TYPEDEF) | ||||
| 				log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str()); | ||||
| 			log_assert(resolved_type->children.size() == 1); | ||||
| 			AstNode *templ = resolved_type->children[0]; | ||||
| 			// Remove type reference
 | ||||
| 			delete children[0]; | ||||
| 			children.erase(children.begin()); | ||||
| 
 | ||||
| 			// Ensure typedef itself is fully simplified
 | ||||
| 			while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; | ||||
| 
 | ||||
| 			if (type == AST_WIRE) | ||||
| 				type = templ->type; | ||||
| 			is_reg = templ->is_reg; | ||||
| 			is_logic = templ->is_logic; | ||||
| 			is_signed = templ->is_signed; | ||||
| 			is_string = templ->is_string; | ||||
| 			is_custom_type = templ->is_custom_type; | ||||
| 
 | ||||
| 			range_valid = templ->range_valid; | ||||
| 			range_swapped = templ->range_swapped; | ||||
| 			range_left = templ->range_left; | ||||
| 			range_right = templ->range_right; | ||||
| 
 | ||||
| 			// Insert clones children from template at beginning
 | ||||
| 			for (int i  = 0; i < GetSize(templ->children); i++) | ||||
| 				children.insert(children.begin() + i, templ->children[i]->clone()); | ||||
| 			 | ||||
| 			if (type == AST_MEMORY && GetSize(children) == 1) { | ||||
| 				// Single-bit memories must have [0:0] range
 | ||||
| 				AstNode *rng = new AstNode(AST_RANGE); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				children.insert(children.begin(), rng); | ||||
| 			} | ||||
| 
 | ||||
| 			did_something = true; | ||||
| 		} | ||||
| 		log_assert(!is_custom_type); | ||||
| 	} | ||||
| 
 | ||||
| 	// resolve types of parameters
 | ||||
| 	if (type == AST_LOCALPARAM || type == AST_PARAMETER) { | ||||
| 		if (is_custom_type) { | ||||
| 			log_assert(children.size() == 2); | ||||
| 			log_assert(children[1]->type == AST_WIRETYPE); | ||||
| 			if (!current_scope.count(children[1]->str)) | ||||
| 				log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); | ||||
| 			AstNode *resolved_type = current_scope.at(children[1]->str); | ||||
| 			if (resolved_type->type != AST_TYPEDEF) | ||||
| 				log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str()); | ||||
| 			log_assert(resolved_type->children.size() == 1); | ||||
| 			AstNode *templ = resolved_type->children[0]; | ||||
| 			delete children[1]; | ||||
| 			children.pop_back(); | ||||
| 
 | ||||
| 			// Ensure typedef itself is fully simplified
 | ||||
| 			while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; | ||||
| 
 | ||||
| 			if (templ->type == AST_MEMORY) | ||||
| 				log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); | ||||
| 			is_signed = templ->is_signed; | ||||
| 			is_string = templ->is_string; | ||||
| 			is_custom_type = templ->is_custom_type; | ||||
| 
 | ||||
| 			range_valid = templ->range_valid; | ||||
| 			range_swapped = templ->range_swapped; | ||||
| 			range_left = templ->range_left; | ||||
| 			range_right = templ->range_right; | ||||
| 			for (auto template_child : templ->children) | ||||
| 				children.push_back(template_child->clone()); | ||||
| 			did_something = true; | ||||
| 		} | ||||
| 		log_assert(!is_custom_type); | ||||
| 	}	 | ||||
| 
 | ||||
| 	// resolve constant prefixes
 | ||||
| 	if (type == AST_PREFIX) { | ||||
| 		if (children[0]->type != AST_CONSTANT) { | ||||
|  | @ -1194,7 +1289,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 	if (type == AST_BLOCK && str.empty()) | ||||
| 	{ | ||||
| 		for (size_t i = 0; i < children.size(); i++) | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) | ||||
| 				log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n"); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1206,7 +1301,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 
 | ||||
| 		std::vector<AstNode*> new_children; | ||||
| 		for (size_t i = 0; i < children.size(); i++) | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) { | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) { | ||||
| 				children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 				current_ast_mod->children.push_back(children[i]); | ||||
| 				current_scope[children[i]->str] = children[i]; | ||||
|  | @ -2906,7 +3001,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) | ||||
| 	if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0) | ||||
| 		str = name_map[str]; | ||||
| 
 | ||||
| 	std::map<std::string, std::string> backup_name_map; | ||||
|  | @ -2914,7 +3009,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma | |||
| 	for (size_t i = 0; i < children.size(); i++) { | ||||
| 		AstNode *child = children[i]; | ||||
| 		if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || | ||||
| 				child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) { | ||||
| 				child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) { | ||||
| 			if (backup_name_map.size() == 0) | ||||
| 				backup_name_map = name_map; | ||||
| 			std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix; | ||||
|  | @ -2945,6 +3040,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma | |||
| 			child->expand_genblock(index_var, prefix, name_map); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	if (backup_name_map.size() > 0) | ||||
| 		name_map.swap(backup_name_map); | ||||
| } | ||||
|  | @ -2998,6 +3094,9 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg | |||
| 	uint32_t children_flags = 0; | ||||
| 	int lhs_children_counter = 0; | ||||
| 
 | ||||
| 	if (type == AST_TYPEDEF) | ||||
| 		return; // don't touch content of typedefs
 | ||||
| 
 | ||||
| 	if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) | ||||
| 	{ | ||||
| 		// mark all memories that are used in a complex expression on the left side of an assignment
 | ||||
|  | @ -3155,6 +3254,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, | |||
| 	if (type == AST_FUNCTION || type == AST_TASK) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (type == AST_TYPEDEF) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) | ||||
| 	{ | ||||
| 		log_assert(children[0]->type == AST_CONSTANT); | ||||
|  |  | |||
|  | @ -174,6 +174,12 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool | |||
| 			if (module == nullptr) | ||||
| 				goto error; | ||||
| 
 | ||||
| 			if (!strcmp(cmd, ".blackbox")) | ||||
| 			{ | ||||
| 				module->attributes["\\blackbox"] = RTLIL::Const(1); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!strcmp(cmd, ".end")) | ||||
| 			{ | ||||
| 				for (auto &wp : wideports_cache) | ||||
|  | @ -280,7 +286,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool | |||
| 					goto error_with_reason; | ||||
| 				} | ||||
| 
 | ||||
| 				module->rename(lastcell, p); | ||||
| 				module->rename(lastcell, RTLIL::escape_id(p)); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -787,7 +787,18 @@ void VerificImporter::merge_past_ffs(pool<RTLIL::Cell*> &candidates) | |||
| void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*> &nl_todo) | ||||
| { | ||||
| 	std::string netlist_name = nl->GetAtt(" \\top") ? nl->CellBaseName() : nl->Owner()->Name(); | ||||
| 	std::string module_name = nl->IsOperator() ? "$verific$" + netlist_name : RTLIL::escape_id(netlist_name); | ||||
| 	std::string module_name = netlist_name; | ||||
| 
 | ||||
| 	if (nl->IsOperator()) { | ||||
| 		module_name = "$verific$" + module_name; | ||||
| 	} else { | ||||
| 		if (*nl->Name()) { | ||||
| 			module_name += "("; | ||||
| 			module_name += nl->Name(); | ||||
| 			module_name += ")"; | ||||
| 		} | ||||
| 		module_name = "\\" + module_name; | ||||
| 	} | ||||
| 
 | ||||
| 	netlist = nl; | ||||
| 
 | ||||
|  | @ -1256,7 +1267,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se | |||
| 		if (inst->Type() == PRIM_SVA_ASSERT || inst->Type() == PRIM_SVA_IMMEDIATE_ASSERT) | ||||
| 			sva_asserts.insert(inst); | ||||
| 
 | ||||
| 		if (inst->Type() == PRIM_SVA_ASSUME || inst->Type() == PRIM_SVA_IMMEDIATE_ASSUME) | ||||
| 		if (inst->Type() == PRIM_SVA_ASSUME || inst->Type() == PRIM_SVA_IMMEDIATE_ASSUME || inst->Type() == PRIM_SVA_RESTRICT) | ||||
| 			sva_assumes.insert(inst); | ||||
| 
 | ||||
| 		if (inst->Type() == PRIM_SVA_COVER || inst->Type() == PRIM_SVA_IMMEDIATE_COVER) | ||||
|  | @ -1396,8 +1407,20 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se | |||
| 	import_verific_cells: | ||||
| 		nl_todo.insert(inst->View()); | ||||
| 
 | ||||
| 		RTLIL::Cell *cell = module->addCell(inst_name, inst->IsOperator() ? | ||||
| 				std::string("$verific$") + inst->View()->Owner()->Name() : RTLIL::escape_id(inst->View()->Owner()->Name())); | ||||
| 		std::string inst_type = inst->View()->Owner()->Name(); | ||||
| 
 | ||||
| 		if (inst->View()->IsOperator()) { | ||||
| 			inst_type = "$verific$" + inst_type; | ||||
| 		} else { | ||||
| 			if (*inst->View()->Name()) { | ||||
| 				inst_type += "("; | ||||
| 				inst_type += inst->View()->Name(); | ||||
| 				inst_type += ")"; | ||||
| 			} | ||||
| 			inst_type = "\\" + inst_type; | ||||
| 		} | ||||
| 
 | ||||
| 		RTLIL::Cell *cell = module->addCell(inst_name, inst_type); | ||||
| 
 | ||||
| 		if (inst->IsPrimitive() && mode_keep) | ||||
| 			cell->attributes["\\keep"] = 1; | ||||
|  | @ -1939,12 +1962,18 @@ struct VerificPass : public Pass { | |||
| 		log("Load the specified VHDL files into Verific.\n"); | ||||
| 		log("\n"); | ||||
| 		log("\n"); | ||||
| 		log("    verific -work <libname> {-sv|-vhdl|...} <hdl-file>\n"); | ||||
| 		log("    verific [-work <libname>] {-sv|-vhdl|...} <hdl-file>\n"); | ||||
| 		log("\n"); | ||||
| 		log("Load the specified Verilog/SystemVerilog/VHDL file into the specified library.\n"); | ||||
| 		log("(default library when -work is not present: \"work\")\n"); | ||||
| 		log("\n"); | ||||
| 		log("\n"); | ||||
| 		log("    verific [-L <libname>] {-sv|-vhdl|...} <hdl-file>\n"); | ||||
| 		log("\n"); | ||||
| 		log("Look up external definitions in the specified library.\n"); | ||||
| 		log("(-L may be used more than once)\n"); | ||||
| 		log("\n"); | ||||
| 		log("\n"); | ||||
| 		log("    verific -vlog-incdir <directory>..\n"); | ||||
| 		log("\n"); | ||||
| 		log("Add Verilog include directories.\n"); | ||||
|  | @ -2158,12 +2187,17 @@ struct VerificPass : public Pass { | |||
| 			goto check_error; | ||||
| 		} | ||||
| 
 | ||||
| 		veri_file::RemoveAllLOptions(); | ||||
| 		for (; argidx < GetSize(args); argidx++) | ||||
| 		{ | ||||
| 			if (args[argidx] == "-work" && argidx+1 < GetSize(args)) { | ||||
| 				work = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-L" && argidx+1 < GetSize(args)) { | ||||
| 				veri_file::AddLOption(args[++argidx].c_str()); | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -490,6 +490,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons | |||
| 			} | ||||
| 			while (newline_count-- > 0) | ||||
| 				return_char('\n'); | ||||
| 			if (strchr("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789", name[0])) { | ||||
| 				// printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str());
 | ||||
| 				defines_map[name] = value; | ||||
| 				if (state == 2) | ||||
|  | @ -497,6 +498,9 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons | |||
| 				else | ||||
| 					defines_with_args.erase(name); | ||||
| 				global_defines_cache[name] = std::pair<std::string, bool>(value, state == 2); | ||||
| 			} else { | ||||
| 				log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str()); | ||||
| 			} | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -553,6 +553,12 @@ struct VerilogDefines : public Pass { | |||
| 		log("    -Uname[=definition]\n"); | ||||
| 		log("        undefine the preprocessor symbol 'name'\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -reset\n"); | ||||
| 		log("        clear list of defined preprocessor symbols\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -list\n"); | ||||
| 		log("        list currently defined preprocessor symbols\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
|  | @ -588,6 +594,16 @@ struct VerilogDefines : public Pass { | |||
| 				design->verilog_defines.erase(name); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-reset") { | ||||
| 				design->verilog_defines.clear(); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-list") { | ||||
| 				for (auto &it : design->verilog_defines) { | ||||
| 					log("`define %s%s %s\n", it.first.c_str(), it.second.second ? "()" : "", it.second.first.c_str()); | ||||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -155,7 +155,7 @@ struct specify_rise_fall { | |||
| 
 | ||||
| %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 <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id | ||||
| %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id | ||||
| %type <boolean> opt_signed opt_property unique_case_attr | ||||
| %type <al> attr case_attr | ||||
| 
 | ||||
|  | @ -206,6 +206,7 @@ design: | |||
| 	task_func_decl design | | ||||
| 	param_decl design | | ||||
| 	localparam_decl design | | ||||
| 	typedef_decl design | | ||||
| 	package design | | ||||
| 	interface design | | ||||
| 	/* empty */; | ||||
|  | @ -290,6 +291,9 @@ hierarchical_id: | |||
| 		$$ = $1; | ||||
| 	}; | ||||
| 
 | ||||
| hierarchical_type_id: | ||||
| 	'(' hierarchical_id ')' { $$ = $2; }; | ||||
| 
 | ||||
| module: | ||||
| 	attr TOK_MODULE TOK_ID { | ||||
| 		do_not_require_port_stubs = false; | ||||
|  | @ -324,13 +328,13 @@ single_module_para: | |||
| 		astbuf1 = new AstNode(AST_PARAMETER); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_range single_param_decl | | ||||
| 	} param_type single_param_decl | | ||||
| 	attr TOK_LOCALPARAM { | ||||
| 		if (astbuf1) delete astbuf1; | ||||
| 		astbuf1 = new AstNode(AST_LOCALPARAM); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_range single_param_decl | | ||||
| 	} param_type single_param_decl | | ||||
| 	single_param_decl; | ||||
| 
 | ||||
| module_args_opt: | ||||
|  | @ -426,6 +430,7 @@ package_body: | |||
| 	package_body package_body_stmt |; | ||||
| 
 | ||||
| package_body_stmt: | ||||
| 	typedef_decl | | ||||
| 	localparam_decl; | ||||
| 
 | ||||
| interface: | ||||
|  | @ -452,7 +457,7 @@ interface_body: | |||
| 	interface_body interface_body_stmt |; | ||||
| 
 | ||||
| interface_body_stmt: | ||||
| 	param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | | ||||
| 	param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | | ||||
| 	modport_stmt; | ||||
| 
 | ||||
| non_opt_delay: | ||||
|  | @ -475,8 +480,14 @@ wire_type: | |||
| 	}; | ||||
| 
 | ||||
| wire_type_token_list: | ||||
| 	wire_type_token | wire_type_token_list wire_type_token | | ||||
| 	wire_type_token_io ; | ||||
| 	wire_type_token | | ||||
| 	wire_type_token_list wire_type_token | | ||||
| 	wire_type_token_io | | ||||
| 	hierarchical_type_id { | ||||
| 		astbuf3->is_custom_type = true; | ||||
| 		astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); | ||||
| 		astbuf3->children.back()->str = *$1; | ||||
| 	}; | ||||
| 
 | ||||
| wire_type_token_io: | ||||
| 	TOK_INPUT { | ||||
|  | @ -591,7 +602,7 @@ module_body: | |||
| 	/* empty */; | ||||
| 
 | ||||
| module_body_stmt: | ||||
| 	task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | | ||||
| 	task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | | ||||
| 	always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; | ||||
| 
 | ||||
| checker_decl: | ||||
|  | @ -1149,12 +1160,20 @@ param_range: | |||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| param_type: | ||||
| 	param_signed param_integer param_real param_range | | ||||
| 	hierarchical_type_id { | ||||
| 		astbuf1->is_custom_type = true; | ||||
| 		astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); | ||||
| 		astbuf1->children.back()->str = *$1; | ||||
| 	}; | ||||
| 
 | ||||
| param_decl: | ||||
| 	attr TOK_PARAMETER { | ||||
| 		astbuf1 = new AstNode(AST_PARAMETER); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_real param_range param_decl_list ';' { | ||||
| 	} param_type param_decl_list ';' { | ||||
| 		delete astbuf1; | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -1163,7 +1182,7 @@ localparam_decl: | |||
| 		astbuf1 = new AstNode(AST_LOCALPARAM); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_real param_range param_decl_list ';' { | ||||
| 	} param_type param_decl_list ';' { | ||||
| 		delete astbuf1; | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -1327,7 +1346,7 @@ wire_name: | |||
| 		if ($2 != NULL) { | ||||
| 			if (node->is_input || node->is_output) | ||||
| 				frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); | ||||
| 			if (!astbuf2) { | ||||
| 			if (!astbuf2 && !node->is_custom_type) { | ||||
| 				AstNode *rng = new AstNode(AST_RANGE); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
|  | @ -1377,6 +1396,45 @@ assign_expr: | |||
| 		ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); | ||||
| 	}; | ||||
| 
 | ||||
| typedef_decl: | ||||
| 	TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { | ||||
| 		astbuf1 = $2; | ||||
| 		astbuf2 = $3; | ||||
| 		if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { | ||||
| 			if (astbuf2) { | ||||
| 				frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); | ||||
| 			} else { | ||||
| 				astbuf2 = new AstNode(AST_RANGE); | ||||
| 				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); | ||||
| 				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); | ||||
| 			} | ||||
| 		} | ||||
| 		if (astbuf2 && astbuf2->children.size() != 2) | ||||
| 			frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]"); | ||||
| 		if (astbuf2) | ||||
| 			astbuf1->children.push_back(astbuf2); | ||||
| 
 | ||||
| 		if ($5 != NULL) { | ||||
| 			if (!astbuf2) { | ||||
| 				AstNode *rng = new AstNode(AST_RANGE); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				astbuf1->children.push_back(rng); | ||||
| 			} | ||||
| 			astbuf1->type = AST_MEMORY; | ||||
| 			auto *rangeNode = $5; | ||||
| 			if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { | ||||
| 				// SV array size [n], rewrite as [n-1:0] | ||||
| 				rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); | ||||
| 				rangeNode->children.push_back(AstNode::mkconst_int(0, false)); | ||||
| 			} | ||||
| 			astbuf1->children.push_back(rangeNode); | ||||
| 		} | ||||
| 
 | ||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); | ||||
| 		ast_stack.back()->children.back()->str = *$4; | ||||
| 	}; | ||||
| 
 | ||||
| cell_stmt: | ||||
| 	attr TOK_ID { | ||||
| 		astbuf1 = new AstNode(AST_CELL); | ||||
|  | @ -1823,7 +1881,7 @@ simple_behavioral_stmt: | |||
| 
 | ||||
| // this production creates the obligatory if-else shift/reduce conflict | ||||
| behavioral_stmt: | ||||
| 	defattr | assert | wire_decl | param_decl | localparam_decl | | ||||
| 	defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | | ||||
| 	non_opt_delay behavioral_stmt | | ||||
| 	simple_behavioral_stmt ';' | ';' | | ||||
| 	hierarchical_id attr { | ||||
|  |  | |||
|  | @ -253,6 +253,8 @@ class WContainer: | |||
| 			candidate = WType.from_string(arg.strip(), containing_file, line_number) | ||||
| 			if candidate == None: | ||||
| 				return None | ||||
| 			if candidate.name == "void": | ||||
| 				return None | ||||
| 			cont.args.append(candidate) | ||||
| 		return cont | ||||
| 
 | ||||
|  | @ -880,11 +882,8 @@ class WClass: | |||
| 				text += fun.gen_def_virtual() | ||||
| 		return text | ||||
| 
 | ||||
| 	def gen_boost_py(self): | ||||
| 		text = "\n\t\tclass_<" + self.name | ||||
| 		if self.link_type == link_types.derive: | ||||
| 			text += "Wrap, boost::noncopyable" | ||||
| 		text += ">(\"" + self.name + "\"" | ||||
| 	def gen_boost_py_body(self): | ||||
| 		text = "" | ||||
| 		if self.printable_constrs() == 0 or not self.contains_default_constr(): | ||||
| 			text += ", no_init" | ||||
| 		text += ")" | ||||
|  | @ -907,6 +906,21 @@ class WClass: | |||
| 		text += "\n\t\t\t;\n" | ||||
| 		return text | ||||
| 
 | ||||
| 	def gen_boost_py(self): | ||||
| 		body = self.gen_boost_py_body() | ||||
| 		if self.link_type == link_types.derive: | ||||
| 			text = "\n\t\tclass_<" + self.name + ">(\"Cpp" + self.name + "\"" | ||||
| 			text += body | ||||
| 			text += "\n\t\tclass_<" + self.name | ||||
| 			text += "Wrap, boost::noncopyable" | ||||
| 			text += ">(\"" + self.name + "\"" | ||||
| 			text += body | ||||
| 		else: | ||||
| 			text = "\n\t\tclass_<" + self.name + ">(\"" + self.name + "\"" | ||||
| 			text += body | ||||
| 		return text | ||||
| 	 | ||||
| 
 | ||||
| 	def contains_default_constr(self): | ||||
| 		for c in self.found_constrs: | ||||
| 			if len(c.args) == 0: | ||||
|  | @ -974,6 +988,7 @@ blacklist_methods = ["YOSYS_NAMESPACE::Pass::run_register", "YOSYS_NAMESPACE::Mo | |||
| enum_names = ["State","SyncType","ConstFlags"] | ||||
| 
 | ||||
| enums = [] #Do not edit | ||||
| glbls = [] | ||||
| 
 | ||||
| unowned_functions = [] | ||||
| 
 | ||||
|  | @ -1723,6 +1738,159 @@ class WMember: | |||
| 		text += ")" | ||||
| 		return text | ||||
| 
 | ||||
| class WGlobal: | ||||
| 	orig_text = None | ||||
| 	wtype = attr_types.default | ||||
| 	name = None | ||||
| 	containing_file = None | ||||
| 	namespace = "" | ||||
| 	is_const = False | ||||
| 
 | ||||
| 	def from_string(str_def, containing_file, line_number, namespace): | ||||
| 		glbl = WGlobal() | ||||
| 		glbl.orig_text = str_def | ||||
| 		glbl.wtype = None | ||||
| 		glbl.name = "" | ||||
| 		glbl.containing_file = containing_file | ||||
| 		glbl.namespace = namespace | ||||
| 		glbl.is_const = False | ||||
| 
 | ||||
| 		if not str.startswith(str_def, "extern"): | ||||
| 			return None | ||||
| 		str_def = str_def[7:] | ||||
| 
 | ||||
| 		if str.startswith(str_def, "const "): | ||||
| 			glbl.is_const = True | ||||
| 			str_def = str_def[6:] | ||||
| 
 | ||||
| 		if str_def.count(" ") == 0: | ||||
| 			return None | ||||
| 
 | ||||
| 		parts = split_list(str_def.strip(), " ") | ||||
| 
 | ||||
| 		prefix = "" | ||||
| 		i = 0 | ||||
| 		for part in parts: | ||||
| 			if part in ["unsigned", "long", "short"]: | ||||
| 				prefix += part + " " | ||||
| 				i += 1 | ||||
| 			else: | ||||
| 				break | ||||
| 		parts = parts[i:] | ||||
| 
 | ||||
| 		if len(parts) <= 1: | ||||
| 			return None | ||||
| 
 | ||||
| 		glbl.wtype = WType.from_string(prefix + parts[0], containing_file, line_number) | ||||
| 
 | ||||
| 		if glbl.wtype == None: | ||||
| 			return None | ||||
| 
 | ||||
| 		str_def = parts[1] | ||||
| 		for part in parts[2:]: | ||||
| 			str_def = str_def + " " + part | ||||
| 
 | ||||
| 		if str_def.find("(") != -1 or str_def.find(")") != -1 or str_def.find("{") != -1 or str_def.find("}") != -1: | ||||
| 			return None | ||||
| 
 | ||||
| 		found = str_def.find(";") | ||||
| 		if found == -1: | ||||
| 			return None | ||||
| 
 | ||||
| 		found_eq = str_def.find("=") | ||||
| 		if found_eq != -1: | ||||
| 			found = found_eq | ||||
| 
 | ||||
| 		glbl.name = str_def[:found] | ||||
| 		str_def = str_def[found+1:] | ||||
| 		if glbl.name.find("*") == 0: | ||||
| 			glbl.name = glbl.name.replace("*", "") | ||||
| 			glbl.wtype.attr_type = attr_types.star | ||||
| 		if glbl.name.find("&&") == 0: | ||||
| 			glbl.name = glbl.name.replace("&&", "") | ||||
| 			glbl.wtype.attr_type = attr_types.ampamp | ||||
| 		if glbl.name.find("&") == 0: | ||||
| 			glbl.name = glbl.name.replace("&", "") | ||||
| 			glbl.wtype.attr_type = attr_types.amp | ||||
| 
 | ||||
| 		if(len(str_def.strip()) != 0): | ||||
| 			return None | ||||
| 
 | ||||
| 		if len(glbl.name.split(",")) > 1: | ||||
| 			glbl_list = [] | ||||
| 			for name in glbl.name.split(","): | ||||
| 				name = name.strip(); | ||||
| 				glbl_list.append(WGlobal()) | ||||
| 				glbl_list[-1].orig_text = glbl.orig_text | ||||
| 				glbl_list[-1].wtype = glbl.wtype | ||||
| 				glbl_list[-1].name = name | ||||
| 				glbl_list[-1].containing_file = glbl.containing_file | ||||
| 				glbl_list[-1].namespace = glbl.namespace | ||||
| 				glbl_list[-1].is_const = glbl.is_const | ||||
| 			return glbl_list | ||||
| 
 | ||||
| 		return glbl | ||||
| 
 | ||||
| 	def gen_def(self): | ||||
| 		text = "\n\t" | ||||
| 		if self.is_const: | ||||
| 			text += "const " | ||||
| 		text += self.wtype.gen_text() + " get_var_py_" + self.name + "()" | ||||
| 		text += "\n\t{\n\t\t" | ||||
| 		if self.wtype.attr_type == attr_types.star: | ||||
| 			text += "if(" + self.namespace + "::" + self.name + " == NULL)\n\t\t\t" | ||||
| 			text += "throw std::runtime_error(\"" + self.namespace + "::" + self.name + " is NULL\");\n\t\t" | ||||
| 		if self.wtype.name in known_containers: | ||||
| 			text += self.wtype.gen_text_cpp() | ||||
| 		else: | ||||
| 			if self.is_const: | ||||
| 				text += "const " | ||||
| 			text += self.wtype.gen_text() | ||||
| 
 | ||||
| 		if self.wtype.name in classnames or (self.wtype.name in known_containers and self.wtype.attr_type == attr_types.star): | ||||
| 			text += "*" | ||||
| 		text += " ret_ = " | ||||
| 		if self.wtype.name in classnames: | ||||
| 			text += self.wtype.name + "::get_py_obj(" | ||||
| 			if self.wtype.attr_type != attr_types.star: | ||||
| 				text += "&" | ||||
| 		text += self.namespace + "::" + self.name | ||||
| 		if self.wtype.name in classnames: | ||||
| 			text += ")" | ||||
| 		text += ";" | ||||
| 		 | ||||
| 		if self.wtype.name in classnames: | ||||
| 			text += "\n\t\treturn *ret_;" | ||||
| 		elif self.wtype.name in known_containers: | ||||
| 			text += known_containers[self.wtype.name].translate_cpp("ret_", self.wtype.cont.args, "\n\t\t", self.wtype.attr_type == attr_types.star) | ||||
| 			text += "\n\t\treturn ret____tmp;" | ||||
| 		else: | ||||
| 			text += "\n\t\treturn ret_;" | ||||
| 		text += "\n\t}\n" | ||||
| 
 | ||||
| 		if self.is_const: | ||||
| 			return text | ||||
| 
 | ||||
| 		ret = Attribute(self.wtype, "rhs"); | ||||
| 
 | ||||
| 		if self.wtype.name in classnames: | ||||
| 			text += "\n\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " *rhs)" | ||||
| 		else: | ||||
| 			text += "\n\tvoid set_var_py_" + self.name + "(" + self.wtype.gen_text() + " rhs)" | ||||
| 		text += "\n\t{" | ||||
| 		text += ret.gen_translation() | ||||
| 		text += "\n\t\t" + self.namespace + "::" + self.name + " = " + ret.gen_call() + ";" | ||||
| 		text += "\n\t}\n"		 | ||||
| 
 | ||||
| 		return text; | ||||
| 
 | ||||
| 	def gen_boost_py(self): | ||||
| 		text = "\n\t\t\t.add_static_property(\"" + self.name + "\", &" + "YOSYS_PYTHON::get_var_py_" + self.name  | ||||
| 		if not self.is_const: | ||||
| 			text += ", &YOSYS_PYTHON::set_var_py_" + self.name | ||||
| 		text += ")" | ||||
| 		return text | ||||
| 
 | ||||
| def concat_namespace(tuple_list): | ||||
| 	if len(tuple_list) == 0: | ||||
| 		return "" | ||||
|  | @ -1859,6 +2027,16 @@ def parse_header(source): | |||
| 							else: | ||||
| 								debug("\t\tFound member \"" + candidate.name + "\" of class \"" + class_[0].name + "\" of type \"" + candidate.wtype.name + "\"", 2) | ||||
| 								class_[0].found_vars.append(candidate) | ||||
| 				if candidate == None and class_ == None: | ||||
| 					candidate = WGlobal.from_string(ugly_line, source.name, i, concat_namespace(namespaces)) | ||||
| 					if candidate != None: | ||||
| 						if type(candidate) == list: | ||||
| 							for c in candidate: | ||||
| 								glbls.append(c) | ||||
| 								debug("\tFound global \"" + c.name + "\" in namespace " + concat_namespace(namespaces), 2) | ||||
| 						else: | ||||
| 							glbls.append(candidate) | ||||
| 							debug("\tFound global \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces), 2) | ||||
| 
 | ||||
| 			j = i | ||||
| 			line = unpretty_string(line) | ||||
|  | @ -1888,6 +2066,17 @@ def parse_header(source): | |||
| 						debug("\t\tFound constructor of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2) | ||||
| 						class_[0].found_constrs.append(candidate) | ||||
| 						continue | ||||
| 				if class_ == None: | ||||
| 					candidate = WGlobal.from_string(line, source.name, i, concat_namespace(namespaces)) | ||||
| 					if candidate != None: | ||||
| 						if type(candidate) == list: | ||||
| 							for c in candidate: | ||||
| 								glbls.append(c) | ||||
| 								debug("\tFound global \"" + c.name + "\" in namespace " + concat_namespace(namespaces), 2) | ||||
| 						else: | ||||
| 							glbls.append(candidate) | ||||
| 							debug("\tFound global \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces), 2) | ||||
| 						continue | ||||
| 		if candidate != None: | ||||
| 			while i < j: | ||||
| 				i += 1 | ||||
|  | @ -1990,6 +2179,7 @@ def gen_wrappers(filename, debug_level_ = 0): | |||
| 			if len(class_.found_constrs) == 0: | ||||
| 				class_.found_constrs.append(WConstructor(source.name, class_)) | ||||
| 	debug(str(len(unowned_functions)) + " functions are unowned", 1) | ||||
| 	debug(str(len(unowned_functions)) + " global variables", 1) | ||||
| 	for enum in enums: | ||||
| 		debug("Enum " + assure_length(enum.name, len(max(enum_names, key=len)), True) + " contains " + assure_length(str(len(enum.values)), 2, False) + " values", 1) | ||||
| 	debug("-"*col, 1) | ||||
|  | @ -2025,10 +2215,15 @@ def gen_wrappers(filename, debug_level_ = 0): | |||
| #include <boost/python/wrapper.hpp> | ||||
| #include <boost/python/call.hpp> | ||||
| #include <boost/python.hpp> | ||||
| 
 | ||||
| #include <iosfwd> // std::streamsize | ||||
| #include <iostream> | ||||
| #include <boost/iostreams/concepts.hpp>	// boost::iostreams::sink | ||||
| #include <boost/iostreams/stream.hpp> | ||||
| USING_YOSYS_NAMESPACE | ||||
| 
 | ||||
| namespace YOSYS_PYTHON { | ||||
| 
 | ||||
| 	struct YosysStatics{}; | ||||
| """) | ||||
| 
 | ||||
| 	for source in sources: | ||||
|  | @ -2050,6 +2245,9 @@ namespace YOSYS_PYTHON { | |||
| 	for fun in unowned_functions: | ||||
| 		wrapper_file.write(fun.gen_def()) | ||||
| 
 | ||||
| 	for glbl in glbls: | ||||
| 		wrapper_file.write(glbl.gen_def()) | ||||
| 
 | ||||
| 	wrapper_file.write("""	struct Initializer | ||||
| 	{ | ||||
| 		Initializer() { | ||||
|  | @ -2068,12 +2266,89 @@ namespace YOSYS_PYTHON { | |||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
| 	/// source: https://stackoverflow.com/questions/26033781/converting-python-io-object-to-stdostream-when-using-boostpython?noredirect=1&lq=1 | ||||
| 	/// @brief Type that implements the Boost.IOStream's Sink and Flushable | ||||
| 	///        concept for writing data to Python object that support: | ||||
| 	///          n = object.write(str) # n = None or bytes written | ||||
| 	///          object.flush()        # if flush exists, then it is callable | ||||
| 	class PythonOutputDevice | ||||
| 	{ | ||||
| 	public: | ||||
| 
 | ||||
| 		// This class models both the Sink and Flushable concepts. | ||||
| 		struct category | ||||
| 			: boost::iostreams::sink_tag, | ||||
| 				boost::iostreams::flushable_tag | ||||
| 		{}; | ||||
| 
 | ||||
| 		explicit | ||||
| 		PythonOutputDevice(boost::python::object object) | ||||
| 			: object_(object) | ||||
| 		{} | ||||
| 
 | ||||
| 	// Sink concept. | ||||
| 	public: | ||||
| 
 | ||||
| 		typedef char char_type; | ||||
| 
 | ||||
| 		std::streamsize write(const char* buffer, std::streamsize buffer_size) | ||||
| 		{ | ||||
| 			namespace python = boost::python; | ||||
| 			// Copy the buffer to a python string. | ||||
| 			python::str data(buffer, buffer_size); | ||||
| 
 | ||||
| 			// Invoke write on the python object, passing in the data.	The following | ||||
| 			// is equivalent to: | ||||
| 			//	 n = object_.write(data) | ||||
| 			python::extract<std::streamsize> bytes_written( | ||||
| 				object_.attr("write")(data)); | ||||
| 
 | ||||
| 			// Per the Sink concept, return the number of bytes written.	If the | ||||
| 			// Python return value provides a numeric result, then use it.	Otherwise, | ||||
| 			// such as the case of a File object, use the buffer_size. | ||||
| 			return bytes_written.check() | ||||
| 				? bytes_written | ||||
| 				: buffer_size; | ||||
| 		} | ||||
| 
 | ||||
| 	// Flushable concept. | ||||
| 	public: | ||||
| 
 | ||||
| 		bool flush() | ||||
| 		{ | ||||
| 			// If flush exists, then call it. | ||||
| 			boost::python::object flush = object_.attr("flush"); | ||||
| 			if (!flush.is_none()) | ||||
| 			{ | ||||
| 				flush(); | ||||
| 			} | ||||
| 
 | ||||
| 			// Always return true.	If an error occurs, an exception should be thrown. | ||||
| 				return true; | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		boost::python::object object_; | ||||
| 	}; | ||||
| 
 | ||||
| 	/// @brief Use an auxiliary function to adapt the legacy function. | ||||
| 	void log_to_stream(boost::python::object object) | ||||
| 	{ | ||||
| 		// Create an ostream that delegates to the python object. | ||||
| 		boost::iostreams::stream<PythonOutputDevice>* output = new boost::iostreams::stream<PythonOutputDevice>(object); | ||||
| 		Yosys::log_streams.insert(Yosys::log_streams.begin(), output); | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
| 	BOOST_PYTHON_MODULE(libyosys) | ||||
| 	{ | ||||
| 		using namespace boost::python; | ||||
| 
 | ||||
| 		class_<Initializer>("Initializer"); | ||||
| 		scope().attr("_hidden") = new Initializer(); | ||||
| 
 | ||||
| 		def("log_to_stream", &log_to_stream); | ||||
| """) | ||||
| 
 | ||||
| 	for enum in enums: | ||||
|  | @ -2086,6 +2361,11 @@ namespace YOSYS_PYTHON { | |||
| 	for fun in unowned_functions: | ||||
| 		wrapper_file.write(fun.gen_boost_py()) | ||||
| 
 | ||||
| 	wrapper_file.write("\n\n\t\tclass_<YosysStatics>(\"Yosys\")\n") | ||||
| 	for glbl in glbls: | ||||
| 		wrapper_file.write(glbl.gen_boost_py()) | ||||
| 	wrapper_file.write("\t\t;\n") | ||||
| 
 | ||||
| 	wrapper_file.write("\n\t}\n}\n#endif") | ||||
| 
 | ||||
| def print_includes(): | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ OBJS += passes/cmds/design.o | |||
| OBJS += passes/cmds/select.o | ||||
| OBJS += passes/cmds/show.o | ||||
| OBJS += passes/cmds/rename.o | ||||
| OBJS += passes/cmds/autoname.o | ||||
| OBJS += passes/cmds/connect.o | ||||
| OBJS += passes/cmds/scatter.o | ||||
| OBJS += passes/cmds/setundef.o | ||||
|  |  | |||
							
								
								
									
										134
									
								
								passes/cmds/autoname.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								passes/cmds/autoname.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,134 @@ | |||
| /*
 | ||||
|  *  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" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| int autoname_worker(Module *module) | ||||
| { | ||||
| 	dict<Cell*, pair<int, IdString>> proposed_cell_names; | ||||
| 	dict<Wire*, pair<int, IdString>> proposed_wire_names; | ||||
| 	dict<Wire*, int> wire_score; | ||||
| 	int best_score = -1; | ||||
| 
 | ||||
| 	for (auto cell : module->selected_cells()) | ||||
| 	for (auto &conn : cell->connections()) | ||||
| 	for (auto bit : conn.second) | ||||
| 		if (bit.wire != nullptr) | ||||
| 			wire_score[bit.wire]++; | ||||
| 
 | ||||
| 	for (auto cell : module->selected_cells()) { | ||||
| 		if (cell->name[0] == '$') { | ||||
| 			for (auto &conn : cell->connections()) { | ||||
| 				string suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first)); | ||||
| 				for (auto bit : conn.second) | ||||
| 					if (bit.wire != nullptr && bit.wire->name[0] != '$') { | ||||
| 						IdString new_name(bit.wire->name.str() + suffix); | ||||
| 						int score = wire_score.at(bit.wire); | ||||
| 						if (cell->output(conn.first)) score = 0; | ||||
| 						score = 10000*score + new_name.size(); | ||||
| 						if (!proposed_cell_names.count(cell) || score < proposed_cell_names.at(cell).first) { | ||||
| 							if (best_score < 0 || score < best_score) | ||||
| 								best_score = score; | ||||
| 							proposed_cell_names[cell] = make_pair(score, new_name); | ||||
| 						} | ||||
| 					} | ||||
| 			} | ||||
| 		} else { | ||||
| 			for (auto &conn : cell->connections()) { | ||||
| 				string suffix = stringf("_%s", log_id(conn.first)); | ||||
| 				for (auto bit : conn.second) | ||||
| 					if (bit.wire != nullptr && bit.wire->name[0] == '$') { | ||||
| 						IdString new_name(cell->name.str() + suffix); | ||||
| 						int score = wire_score.at(bit.wire); | ||||
| 						if (cell->output(conn.first)) score = 0; | ||||
| 						score = 10000*score + new_name.size(); | ||||
| 						if (!proposed_wire_names.count(bit.wire) || score < proposed_wire_names.at(bit.wire).first) { | ||||
| 							if (best_score < 0 || score < best_score) | ||||
| 								best_score = score; | ||||
| 							proposed_wire_names[bit.wire] = make_pair(score, new_name); | ||||
| 						} | ||||
| 					} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto &it : proposed_cell_names) { | ||||
| 		if (best_score*2 < it.second.first) | ||||
| 			continue; | ||||
| 		IdString n = module->uniquify(it.second.second); | ||||
| 		log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); | ||||
| 		module->rename(it.first, n); | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto &it : proposed_wire_names) { | ||||
| 		if (best_score*2 < it.second.first) | ||||
| 			continue; | ||||
| 		IdString n = module->uniquify(it.second.second); | ||||
| 		log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); | ||||
| 		module->rename(it.first, n); | ||||
| 	} | ||||
| 
 | ||||
| 	return proposed_cell_names.size() + proposed_wire_names.size(); | ||||
| } | ||||
| 
 | ||||
| struct AutonamePass : public Pass { | ||||
| 	AutonamePass() : Pass("autoname", "automatically assign names to objects") { } | ||||
| 	void help() YS_OVERRIDE | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    autoname [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("Assign auto-generated public names to objects with private names (the ones\n"); | ||||
| 		log("with $-prefix).\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
| 		{ | ||||
| 			// if (args[argidx] == "-foo") {
 | ||||
| 			// 	foo = true;
 | ||||
| 			// 	continue;
 | ||||
| 			// }
 | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		log_header(design, "Executing AUTONAME pass.\n"); | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) | ||||
| 		{ | ||||
| 			int count = 0, iter = 0; | ||||
| 			while (1) { | ||||
| 				iter++; | ||||
| 				int n = autoname_worker(module); | ||||
| 				if (!n) break; | ||||
| 				count += n; | ||||
| 			} | ||||
| 			if (count > 0) | ||||
| 				log("Renamed %d objects in module %s (%d iterations).\n", count, log_id(module), iter); | ||||
| 		} | ||||
| 	} | ||||
| } AutonamePass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
|  | @ -158,22 +158,25 @@ static void detect_fsm(RTLIL::Wire *wire) | |||
| 		std::set<sig2driver_entry_t> cellport_list; | ||||
| 		sig2user.find(sig_q, cellport_list); | ||||
| 
 | ||||
| 		auto sig_q_bits = sig_q.to_sigbit_pool(); | ||||
| 
 | ||||
| 		for (auto &cellport : cellport_list) | ||||
| 		{ | ||||
| 			RTLIL::Cell *cell = cellport.first; | ||||
| 			bool set_output = false, clr_output = false; | ||||
| 
 | ||||
| 			if (cell->type == "$ne") | ||||
| 			if (cell->type.in("$ne", "$reduce_or", "$reduce_bool")) | ||||
| 				set_output = true; | ||||
| 
 | ||||
| 			if (cell->type == "$eq") | ||||
| 			if (cell->type.in("$eq", "$logic_not", "$reduce_and")) | ||||
| 				clr_output = true; | ||||
| 
 | ||||
| 			if (!set_output && !clr_output) { | ||||
| 				clr_output = true; | ||||
| 			if (set_output || clr_output) { | ||||
| 				for (auto &port_it : cell->connections()) | ||||
| 					if (port_it.first != "\\A" || port_it.first != "\\Y") | ||||
| 						clr_output = false; | ||||
| 					if (cell->input(port_it.first)) | ||||
| 						for (auto bit : assign_map(port_it.second)) | ||||
| 							if (bit.wire != nullptr && !sig_q_bits.count(bit)) | ||||
| 								goto next_cellport; | ||||
| 			} | ||||
| 
 | ||||
| 			if (set_output || clr_output) { | ||||
|  | @ -184,6 +187,7 @@ static void detect_fsm(RTLIL::Wire *wire) | |||
| 						ce.set(sig, val); | ||||
| 					} | ||||
| 			} | ||||
| 		next_cellport:; | ||||
| 		} | ||||
| 
 | ||||
| 		SigSpec sig_y = sig_d, sig_undef; | ||||
|  |  | |||
|  | @ -143,13 +143,18 @@ struct WreduceWorker | |||
| 
 | ||||
| 		SigSpec sig_d = mi.sigmap(cell->getPort(ID(D))); | ||||
| 		SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q))); | ||||
| 		Const initval; | ||||
| 		bool is_adff = (cell->type == ID($adff)); | ||||
| 		Const initval, arst_value; | ||||
| 
 | ||||
| 		int width_before = GetSize(sig_q); | ||||
| 
 | ||||
| 		if (width_before == 0) | ||||
| 			return; | ||||
| 
 | ||||
| 		if (cell->parameters.count(ID(ARST_VALUE))) { | ||||
| 			arst_value = cell->parameters[ID(ARST_VALUE)]; | ||||
| 		} | ||||
| 
 | ||||
| 		bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; | ||||
| 		bool sign_ext = !zero_ext; | ||||
| 
 | ||||
|  | @ -163,7 +168,8 @@ struct WreduceWorker | |||
| 
 | ||||
| 		for (int i = GetSize(sig_q)-1; i >= 0; i--) | ||||
| 		{ | ||||
| 			if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) { | ||||
| 			if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx) && | ||||
| 					(!is_adff || i >= GetSize(arst_value) || arst_value[i] == State::S0 || arst_value[i] == State::Sx)) { | ||||
| 				module->connect(sig_q[i], State::S0); | ||||
| 				remove_init_bits.insert(sig_q[i]); | ||||
| 				sig_d.remove(i); | ||||
|  | @ -171,7 +177,8 @@ struct WreduceWorker | |||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) { | ||||
| 			if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1] && | ||||
| 					(!is_adff || i >= GetSize(arst_value) || arst_value[i] == arst_value[i-1])) { | ||||
| 				module->connect(sig_q[i], sig_q[i-1]); | ||||
| 				remove_init_bits.insert(sig_q[i]); | ||||
| 				sig_d.remove(i); | ||||
|  | @ -214,7 +221,6 @@ struct WreduceWorker | |||
| 
 | ||||
| 		// Narrow ARST_VALUE parameter to new size.
 | ||||
| 		if (cell->parameters.count(ID(ARST_VALUE))) { | ||||
| 			Const arst_value = cell->getParam(ID(ARST_VALUE)); | ||||
| 			arst_value.bits.resize(GetSize(sig_q)); | ||||
| 			cell->setParam(ID(ARST_VALUE), arst_value); | ||||
| 		} | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| %_pm.h: passes/pmgen/pmgen.py %.pmg | ||||
| 	$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p $(subst _pm.h,,$(notdir $@)) $(filter-out $<,$^) | ||||
| 	$(P) mkdir -p passes/pmgen && $(PYTHON_EXECUTABLE) $< -o $@ -p $(subst _pm.h,,$(notdir $@)) $(filter-out $<,$^) | ||||
| 
 | ||||
| # --------------------------------------
 | ||||
| 
 | ||||
|  | @ -38,7 +38,7 @@ PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg | |||
| PEEPOPT_PATTERN += passes/pmgen/peepopt_dffmux.pmg | ||||
| 
 | ||||
| passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) | ||||
| 	$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^) | ||||
| 	$(P) mkdir -p passes/pmgen && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^) | ||||
| 
 | ||||
| # --------------------------------------
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										140
									
								
								passes/pmgen/generate.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								passes/pmgen/generate.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,140 @@ | |||
| /*
 | ||||
|  *  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. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef PMGEN_GENERATE | ||||
| #define PMGEN_GENERATE | ||||
| 
 | ||||
| #define GENERATE_PATTERN(pmclass, pattern) \ | ||||
| 	generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design) | ||||
| 
 | ||||
| void pmtest_addports(Module *module) | ||||
| { | ||||
| 	pool<SigBit> driven_bits, used_bits; | ||||
| 	SigMap sigmap(module); | ||||
| 	int icnt = 0, ocnt = 0; | ||||
| 
 | ||||
| 	for (auto cell : module->cells()) | ||||
| 	for (auto conn : cell->connections()) | ||||
| 	{ | ||||
| 		if (cell->input(conn.first)) | ||||
| 			for (auto bit : sigmap(conn.second)) | ||||
| 				used_bits.insert(bit); | ||||
| 		if (cell->output(conn.first)) | ||||
| 			for (auto bit : sigmap(conn.second)) | ||||
| 				driven_bits.insert(bit); | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto wire : vector<Wire*>(module->wires())) | ||||
| 	{ | ||||
| 		SigSpec ibits, obits; | ||||
| 		for (auto bit : sigmap(wire)) { | ||||
| 			if (!used_bits.count(bit)) | ||||
| 				obits.append(bit); | ||||
| 			if (!driven_bits.count(bit)) | ||||
| 				ibits.append(bit); | ||||
| 		} | ||||
| 		if (!ibits.empty()) { | ||||
| 			Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits)); | ||||
| 			w->port_input = true; | ||||
| 			module->connect(ibits, w); | ||||
| 		} | ||||
| 		if (!obits.empty()) { | ||||
| 			Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits)); | ||||
| 			w->port_output = true; | ||||
| 			module->connect(w, obits); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	module->fixup_ports(); | ||||
| } | ||||
| 
 | ||||
| template <class pm> | ||||
| void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design) | ||||
| { | ||||
| 	log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass); | ||||
| 
 | ||||
| 	int modcnt = 0; | ||||
| 	int maxmodcnt = 100; | ||||
| 	int maxsubcnt = 4; | ||||
| 	int timeout = 0; | ||||
| 	vector<Module*> mods; | ||||
| 
 | ||||
| 	while (modcnt < maxmodcnt) | ||||
| 	{ | ||||
| 		int submodcnt = 0, itercnt = 0, cellcnt = 0; | ||||
| 		Module *mod = design->addModule(NEW_ID); | ||||
| 
 | ||||
| 		while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000) | ||||
| 		{ | ||||
| 			if (timeout++ > 10000) | ||||
| 				log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n"); | ||||
| 
 | ||||
| 			pm matcher(mod, mod->cells()); | ||||
| 
 | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += modcnt; | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += submodcnt; | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += itercnt; | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += cellcnt; | ||||
| 			matcher.rng(1); | ||||
| 
 | ||||
| 			if (GetSize(mod->cells()) != cellcnt) | ||||
| 			{ | ||||
| 				bool found_match = false; | ||||
| 				run(matcher, [&](){ found_match = true; }); | ||||
| 				cellcnt = GetSize(mod->cells()); | ||||
| 
 | ||||
| 				if (found_match) { | ||||
| 					Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d", | ||||
| 							pmclass, pattern, modcnt++)); | ||||
| 					log("Creating module %s with %d cells.\n", log_id(m), cellcnt); | ||||
| 					mod->cloneInto(m); | ||||
| 					pmtest_addports(m); | ||||
| 					mods.push_back(m); | ||||
| 					submodcnt++; | ||||
| 					timeout = 0; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			matcher.generate_mode = true; | ||||
| 			run(matcher, [](){}); | ||||
| 		} | ||||
| 
 | ||||
| 		if (submodcnt && maxsubcnt < (1 << 16)) | ||||
| 			maxsubcnt *= 2; | ||||
| 
 | ||||
| 		design->remove(mod); | ||||
| 	} | ||||
| 
 | ||||
| 	Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern)); | ||||
| 	log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods)); | ||||
| 	for (auto mod : mods) { | ||||
| 		Cell *c = m->addCell(mod->name, mod->name); | ||||
| 		for (auto port : mod->ports) { | ||||
| 			Wire *w = m->addWire(NEW_ID, GetSize(mod->wire(port))); | ||||
| 			c->setPort(port, w); | ||||
| 		} | ||||
| 	} | ||||
| 	pmtest_addports(m); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -24,8 +24,11 @@ USING_YOSYS_NAMESPACE | |||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| bool did_something; | ||||
| dict<SigBit, State> initbits; | ||||
| pool<SigBit> rminitbits; | ||||
| 
 | ||||
| #include "passes/pmgen/peepopt_pm.h" | ||||
| #include "generate.h" | ||||
| 
 | ||||
| struct PeepoptPass : public Pass { | ||||
| 	PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { } | ||||
|  | @ -40,27 +43,86 @@ struct PeepoptPass : public Pass { | |||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		std::string genmode; | ||||
| 
 | ||||
| 		log_header(design, "Executing PEEPOPT pass (run peephole optimizers).\n"); | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
| 		{ | ||||
| 			// if (args[argidx] == "-singleton") {
 | ||||
| 			// 	singleton_mode = true;
 | ||||
| 			// 	continue;
 | ||||
| 			// }
 | ||||
| 			if (args[argidx] == "-generate" && argidx+1 < args.size()) { | ||||
| 				genmode = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) { | ||||
| 		if (!genmode.empty()) | ||||
| 		{ | ||||
| 			initbits.clear(); | ||||
| 			rminitbits.clear(); | ||||
| 
 | ||||
| 			if (genmode == "shiftmul") | ||||
| 				GENERATE_PATTERN(peepopt_pm, shiftmul); | ||||
| 			else if (genmode == "muldiv") | ||||
| 				GENERATE_PATTERN(peepopt_pm, muldiv); | ||||
| 			else if (genmode == "dffmux") | ||||
| 				GENERATE_PATTERN(peepopt_pm, dffmux); | ||||
| 			else | ||||
| 				log_abort(); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) | ||||
| 		{ | ||||
| 			did_something = true; | ||||
| 			while (did_something) { | ||||
| 
 | ||||
| 			while (did_something) | ||||
| 			{ | ||||
| 				did_something = false; | ||||
| 				peepopt_pm pm(module, module->selected_cells()); | ||||
| 				initbits.clear(); | ||||
| 				rminitbits.clear(); | ||||
| 
 | ||||
| 				peepopt_pm pm(module); | ||||
| 
 | ||||
| 				for (auto w : module->wires()) { | ||||
| 					auto it = w->attributes.find(ID(init)); | ||||
| 					if (it != w->attributes.end()) { | ||||
| 						SigSpec sig = pm.sigmap(w); | ||||
| 						Const val = it->second; | ||||
| 						int len = std::min(GetSize(sig), GetSize(val)); | ||||
| 						for (int i = 0; i < len; i++) { | ||||
| 							if (sig[i].wire == nullptr) | ||||
| 								continue; | ||||
| 							if (val[i] != State::S0 && val[i] != State::S1) | ||||
| 								continue; | ||||
| 							initbits[sig[i]] = val[i]; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				pm.setup(module->selected_cells()); | ||||
| 
 | ||||
| 				pm.run_shiftmul(); | ||||
| 				pm.run_muldiv(); | ||||
| 				pm.run_dffmux(); | ||||
| 
 | ||||
| 				for (auto w : module->wires()) { | ||||
| 					auto it = w->attributes.find(ID(init)); | ||||
| 					if (it != w->attributes.end()) { | ||||
| 						SigSpec sig = pm.sigmap(w); | ||||
| 						Const &val = it->second; | ||||
| 						int len = std::min(GetSize(sig), GetSize(val)); | ||||
| 						for (int i = 0; i < len; i++) { | ||||
| 							if (rminitbits.count(sig[i])) | ||||
| 								val[i] = State::Sx; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				initbits.clear(); | ||||
| 				rminitbits.clear(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -60,12 +60,13 @@ code | |||
| 	SigSpec Q = port(dff, \Q); | ||||
| 	int width = GetSize(D); | ||||
| 
 | ||||
| 	SigSpec &dffD = dff->connections_.at(\D); | ||||
| 	SigSpec &dffQ = dff->connections_.at(\Q); | ||||
| 	Const init; | ||||
| 	for (const auto &b : Q) { | ||||
| 		auto it = b.wire->attributes.find(\init); | ||||
| 		init.bits.push_back(it == b.wire->attributes.end() ? State::Sx : it->second[b.offset]); | ||||
| 	SigSpec dffD = dff->getPort(\D); | ||||
| 	SigSpec dffQ = dff->getPort(\Q); | ||||
| 
 | ||||
| 	Const initval; | ||||
| 	for (auto b : Q) { | ||||
| 		auto it = initbits.find(b); | ||||
| 		initval.bits.push_back(it == initbits.end() ? State::Sx : it->second); | ||||
| 	} | ||||
| 
 | ||||
| 	auto cmpx = [=](State lhs, State rhs) { | ||||
|  | @ -76,56 +77,68 @@ code | |||
| 
 | ||||
| 	int i = width-1; | ||||
| 	while (i > 1) { | ||||
| 		log_dump(i, D[i], D[i-1], rst[i], rst[i-1], init[i], init[i-1]); | ||||
| 		if (D[i] != D[i-1]) | ||||
| 			break; | ||||
| 		if (!cmpx(rst[i], rst[i-1])) | ||||
| 			break; | ||||
| 		if (!cmpx(init[i], init[i-1])) | ||||
| 		if (!cmpx(initval[i], initval[i-1])) | ||||
| 			break; | ||||
| 		if (!cmpx(rst[i], init[i])) | ||||
| 		if (!cmpx(rst[i], initval[i])) | ||||
| 			break; | ||||
| 		rminitbits.insert(Q[i]); | ||||
| 		module->connect(Q[i], Q[i-1]); | ||||
| 		i--; | ||||
| 	} | ||||
| 	if (i < width-1) { | ||||
| 		did_something = true; | ||||
| 		if (cemux) { | ||||
| 			SigSpec &ceA = cemux->connections_.at(\A); | ||||
| 			SigSpec &ceB = cemux->connections_.at(\B); | ||||
| 			SigSpec &ceY = cemux->connections_.at(\Y); | ||||
| 			SigSpec ceA = cemux->getPort(\A); | ||||
| 			SigSpec ceB = cemux->getPort(\B); | ||||
| 			SigSpec ceY = cemux->getPort(\Y); | ||||
| 			ceA.remove(i, width-1-i); | ||||
| 			ceB.remove(i, width-1-i); | ||||
| 			ceY.remove(i, width-1-i); | ||||
| 			cemux->setPort(\A, ceA); | ||||
| 			cemux->setPort(\B, ceB); | ||||
| 			cemux->setPort(\Y, ceY); | ||||
| 			cemux->fixup_parameters(); | ||||
| 			blacklist(cemux); | ||||
| 		} | ||||
| 		if (rstmux) { | ||||
| 			SigSpec &rstA = rstmux->connections_.at(\A); | ||||
| 			SigSpec &rstB = rstmux->connections_.at(\B); | ||||
| 			SigSpec &rstY = rstmux->connections_.at(\Y); | ||||
| 			SigSpec rstA = rstmux->getPort(\A); | ||||
| 			SigSpec rstB = rstmux->getPort(\B); | ||||
| 			SigSpec rstY = rstmux->getPort(\Y); | ||||
| 			rstA.remove(i, width-1-i); | ||||
| 			rstB.remove(i, width-1-i); | ||||
| 			rstY.remove(i, width-1-i); | ||||
| 			rstmux->setPort(\A, rstA); | ||||
| 			rstmux->setPort(\B, rstB); | ||||
| 			rstmux->setPort(\Y, rstY); | ||||
| 			rstmux->fixup_parameters(); | ||||
| 			blacklist(rstmux); | ||||
| 		} | ||||
| 		dffD.remove(i, width-1-i); | ||||
| 		dffQ.remove(i, width-1-i); | ||||
| 		dff->setPort(\D, dffD); | ||||
| 		dff->setPort(\Q, dffQ); | ||||
| 		dff->fixup_parameters(); | ||||
| 		blacklist(dff); | ||||
| 
 | ||||
| 		log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed top %d bits.\n", log_id(module), log_id(dff), log_id(cemux, "n/a"), log_id(rstmux, "n/a"), width-1-i); | ||||
| 		width = i+1; | ||||
| 	} | ||||
| 	if (cemux) { | ||||
| 		SigSpec &ceA = cemux->connections_.at(\A); | ||||
| 		SigSpec &ceB = cemux->connections_.at(\B); | ||||
| 		SigSpec &ceY = cemux->connections_.at(\Y); | ||||
| 		SigSpec ceA = cemux->getPort(\A); | ||||
| 		SigSpec ceB = cemux->getPort(\B); | ||||
| 		SigSpec ceY = cemux->getPort(\Y); | ||||
| 
 | ||||
| 		int count = 0; | ||||
| 		for (int i = width-1; i >= 0; i--) { | ||||
| 			if (D[i].wire) | ||||
| 				continue; | ||||
| 			if (cmpx(rst[i], D[i].data) && cmpx(init[i], D[i].data)) { | ||||
| 			if (cmpx(rst[i], D[i].data) && cmpx(initval[i], D[i].data)) { | ||||
| 				count++; | ||||
| 				rminitbits.insert(Q[i]); | ||||
| 				module->connect(Q[i], D[i]); | ||||
| 				ceA.remove(i); | ||||
| 				ceB.remove(i); | ||||
|  | @ -134,10 +147,21 @@ code | |||
| 				dffQ.remove(i); | ||||
| 			} | ||||
| 		} | ||||
| 		if (count > 0) { | ||||
| 		if (count > 0) | ||||
| 		{ | ||||
| 			did_something = true; | ||||
| 
 | ||||
| 			cemux->setPort(\A, ceA); | ||||
| 			cemux->setPort(\B, ceB); | ||||
| 			cemux->setPort(\Y, ceY); | ||||
| 			cemux->fixup_parameters(); | ||||
| 			blacklist(cemux); | ||||
| 
 | ||||
| 			dff->setPort(\D, dffD); | ||||
| 			dff->setPort(\Q, dffQ); | ||||
| 			dff->fixup_parameters(); | ||||
| 			blacklist(dff); | ||||
| 
 | ||||
| 			log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed %d constant bits.\n", log_id(module), log_id(dff), log_id(cemux), log_id(rstmux, "n/a"), count); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -362,6 +362,7 @@ with open(outfile, "w") as f: | |||
|     print("  Module *module;", file=f) | ||||
|     print("  SigMap sigmap;", file=f) | ||||
|     print("  std::function<void()> on_accept;", file=f) | ||||
|     print("  bool setup_done;", file=f) | ||||
|     print("  bool generate_mode;", file=f) | ||||
|     print("  int accept_cnt;", file=f) | ||||
|     print("", file=f) | ||||
|  | @ -477,7 +478,17 @@ with open(outfile, "w") as f: | |||
|     print("", file=f) | ||||
| 
 | ||||
|     print("  {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f) | ||||
|     print("      module(module), sigmap(module), generate_mode(false), rngseed(12345678) {", file=f) | ||||
|     print("      module(module), sigmap(module), setup_done(false), generate_mode(false), rngseed(12345678) {", file=f) | ||||
|     print("    setup(cells);", file=f) | ||||
|     print("  }", file=f) | ||||
|     print("", file=f) | ||||
| 
 | ||||
|     print("  {}_pm(Module *module) :".format(prefix), file=f) | ||||
|     print("      module(module), sigmap(module), setup_done(false), generate_mode(false), rngseed(12345678) {", file=f) | ||||
|     print("  }", file=f) | ||||
|     print("", file=f) | ||||
| 
 | ||||
|     print("  void setup(const vector<Cell*> &cells) {", file=f) | ||||
|     for current_pattern in sorted(patterns.keys()): | ||||
|         for s, t in sorted(udata_types[current_pattern].items()): | ||||
|             if t.endswith("*"): | ||||
|  | @ -485,6 +496,8 @@ with open(outfile, "w") as f: | |||
|             else: | ||||
|                 print("    ud_{}.{} = {}();".format(current_pattern, s, t), file=f) | ||||
|     current_pattern = None | ||||
|     print("    log_assert(!setup_done);", file=f) | ||||
|     print("    setup_done = true;", file=f) | ||||
|     print("    for (auto port : module->ports)", file=f) | ||||
|     print("      add_siguser(module->wire(port), nullptr);", file=f) | ||||
|     print("    for (auto cell : module->cells())", file=f) | ||||
|  | @ -539,6 +552,7 @@ with open(outfile, "w") as f: | |||
| 
 | ||||
|     for current_pattern in sorted(patterns.keys()): | ||||
|         print("  int run_{}(std::function<void()> on_accept_f) {{".format(current_pattern), file=f) | ||||
|         print("    log_assert(setup_done);", file=f) | ||||
|         print("    accept_cnt = 0;", file=f) | ||||
|         print("    on_accept = on_accept_f;", file=f) | ||||
|         print("    rollback = 0;", file=f) | ||||
|  |  | |||
|  | @ -23,13 +23,11 @@ | |||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| // for peepopt_pm
 | ||||
| bool did_something; | ||||
| 
 | ||||
| #include "passes/pmgen/test_pmgen_pm.h" | ||||
| #include "passes/pmgen/ice40_dsp_pm.h" | ||||
| #include "passes/pmgen/xilinx_srl_pm.h" | ||||
| #include "passes/pmgen/peepopt_pm.h" | ||||
| 
 | ||||
| #include "generate.h" | ||||
| 
 | ||||
| void reduce_chain(test_pmgen_pm &pm) | ||||
| { | ||||
|  | @ -118,123 +116,6 @@ void opt_eqpmux(test_pmgen_pm &pm) | |||
| 	log("    -> %s (%s)\n", log_id(c), log_id(c->type)); | ||||
| } | ||||
| 
 | ||||
| #define GENERATE_PATTERN(pmclass, pattern) \ | ||||
| 	generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design) | ||||
| 
 | ||||
| void pmtest_addports(Module *module) | ||||
| { | ||||
| 	pool<SigBit> driven_bits, used_bits; | ||||
| 	SigMap sigmap(module); | ||||
| 	int icnt = 0, ocnt = 0; | ||||
| 
 | ||||
| 	for (auto cell : module->cells()) | ||||
| 	for (auto conn : cell->connections()) | ||||
| 	{ | ||||
| 		if (cell->input(conn.first)) | ||||
| 			for (auto bit : sigmap(conn.second)) | ||||
| 				used_bits.insert(bit); | ||||
| 		if (cell->output(conn.first)) | ||||
| 			for (auto bit : sigmap(conn.second)) | ||||
| 				driven_bits.insert(bit); | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto wire : vector<Wire*>(module->wires())) | ||||
| 	{ | ||||
| 		SigSpec ibits, obits; | ||||
| 		for (auto bit : sigmap(wire)) { | ||||
| 			if (!used_bits.count(bit)) | ||||
| 				obits.append(bit); | ||||
| 			if (!driven_bits.count(bit)) | ||||
| 				ibits.append(bit); | ||||
| 		} | ||||
| 		if (!ibits.empty()) { | ||||
| 			Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits)); | ||||
| 			w->port_input = true; | ||||
| 			module->connect(ibits, w); | ||||
| 		} | ||||
| 		if (!obits.empty()) { | ||||
| 			Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits)); | ||||
| 			w->port_output = true; | ||||
| 			module->connect(w, obits); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	module->fixup_ports(); | ||||
| } | ||||
| 
 | ||||
| template <class pm> | ||||
| void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design) | ||||
| { | ||||
| 	log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass); | ||||
| 
 | ||||
| 	int modcnt = 0; | ||||
| 	int maxmodcnt = 100; | ||||
| 	int maxsubcnt = 4; | ||||
| 	int timeout = 0; | ||||
| 	vector<Module*> mods; | ||||
| 
 | ||||
| 	while (modcnt < maxmodcnt) | ||||
| 	{ | ||||
| 		int submodcnt = 0, itercnt = 0, cellcnt = 0; | ||||
| 		Module *mod = design->addModule(NEW_ID); | ||||
| 
 | ||||
| 		while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000) | ||||
| 		{ | ||||
| 			if (timeout++ > 10000) | ||||
| 				log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n"); | ||||
| 
 | ||||
| 			pm matcher(mod, mod->cells()); | ||||
| 
 | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += modcnt; | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += submodcnt; | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += itercnt; | ||||
| 			matcher.rng(1); | ||||
| 			matcher.rngseed += cellcnt; | ||||
| 			matcher.rng(1); | ||||
| 
 | ||||
| 			if (GetSize(mod->cells()) != cellcnt) | ||||
| 			{ | ||||
| 				bool found_match = false; | ||||
| 				run(matcher, [&](){ found_match = true; }); | ||||
| 				cellcnt = GetSize(mod->cells()); | ||||
| 
 | ||||
| 				if (found_match) { | ||||
| 					Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d", | ||||
| 							pmclass, pattern, modcnt++)); | ||||
| 					log("Creating module %s with %d cells.\n", log_id(m), cellcnt); | ||||
| 					mod->cloneInto(m); | ||||
| 					pmtest_addports(m); | ||||
| 					mods.push_back(m); | ||||
| 					submodcnt++; | ||||
| 					timeout = 0; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			matcher.generate_mode = true; | ||||
| 			run(matcher, [](){}); | ||||
| 		} | ||||
| 
 | ||||
| 		if (submodcnt && maxsubcnt < (1 << 16)) | ||||
| 			maxsubcnt *= 2; | ||||
| 
 | ||||
| 		design->remove(mod); | ||||
| 	} | ||||
| 
 | ||||
| 	Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern)); | ||||
| 	log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods)); | ||||
| 	for (auto mod : mods) { | ||||
| 		Cell *c = m->addCell(mod->name, mod->name); | ||||
| 		for (auto port : mod->ports) { | ||||
| 			Wire *w = m->addWire(NEW_ID, GetSize(mod->wire(port))); | ||||
| 			c->setPort(port, w); | ||||
| 		} | ||||
| 	} | ||||
| 	pmtest_addports(m); | ||||
| } | ||||
| 
 | ||||
| struct TestPmgenPass : public Pass { | ||||
| 	TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { } | ||||
| 	void help() YS_OVERRIDE | ||||
|  | @ -355,12 +236,6 @@ struct TestPmgenPass : public Pass { | |||
| 		if (pattern == "xilinx_srl.variable") | ||||
| 			return GENERATE_PATTERN(xilinx_srl_pm, variable); | ||||
| 
 | ||||
| 		if (pattern == "peepopt-muldiv") | ||||
| 			return GENERATE_PATTERN(peepopt_pm, muldiv); | ||||
| 
 | ||||
| 		if (pattern == "peepopt-shiftmul") | ||||
| 			return GENERATE_PATTERN(peepopt_pm, shiftmul); | ||||
| 
 | ||||
| 		log_cmd_error("Unknown pattern: %s\n", pattern.c_str()); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -98,16 +98,16 @@ code sigA sigB sigC sigD sigM clock | |||
| 	if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { | ||||
| 		// Only care about those bits that are used | ||||
| 		int i; | ||||
| 		for (i = 0; i < GetSize(P); i++) { | ||||
| 			if (nusers(P[i]) <= 1) | ||||
| 		for (i = GetSize(P)-1; i >= 0; i--) | ||||
| 			if (nusers(P[i]) > 1) | ||||
| 				break; | ||||
| 			sigM.append(P[i]); | ||||
| 		} | ||||
| 		i++; | ||||
| 		log_assert(nusers(P.extract_end(i)) <= 1); | ||||
| 		// This sigM could have no users if downstream sinks (e.g. $add) is | ||||
| 		//   narrower than $mul result, for example | ||||
| 		if (sigM.empty()) | ||||
| 		if (i == 0) | ||||
| 			reject; | ||||
| 		sigM = P.extract(0, i); | ||||
| 	} | ||||
| 	else | ||||
| 		sigM = P; | ||||
|  | @ -460,6 +460,8 @@ arg argD argQ clock | |||
| 
 | ||||
| code | ||||
| 	dff = nullptr; | ||||
| 	if (GetSize(argQ) == 0) | ||||
| 		reject; | ||||
| 	for (const auto &c : argQ.chunks()) { | ||||
| 		// Abandon matches when 'Q' is a constant | ||||
| 		if (!c.wire) | ||||
|  |  | |||
|  | @ -63,12 +63,12 @@ code sigC sigP clock | |||
| 	if (param(dsp, \USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY") { | ||||
| 		// Only care about those bits that are used | ||||
| 		int i; | ||||
| 		for (i = 0; i < GetSize(P); i++) { | ||||
| 			if (nusers(P[i]) <= 1) | ||||
| 		for (i = GetSize(P)-1; i >= 0; i--) | ||||
| 			if (nusers(P[i]) > 1) | ||||
| 				break; | ||||
| 			sigP.append(P[i]); | ||||
| 		} | ||||
| 		i++; | ||||
| 		log_assert(nusers(P.extract_end(i)) <= 1); | ||||
| 		sigP = P.extract(0, i); | ||||
| 	} | ||||
| 	else | ||||
| 		sigP = P; | ||||
|  |  | |||
|  | @ -262,10 +262,14 @@ struct ExtractFaWorker | |||
| 			pool<SigBit> new_leaves = leaves; | ||||
| 
 | ||||
| 			new_leaves.erase(bit); | ||||
| 			if (cell->hasPort(ID::A)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::A)))); | ||||
| 			if (cell->hasPort(ID::B)) new_leaves.insert(sigmap(SigBit(cell->getPort(ID::B)))); | ||||
| 			if (cell->hasPort(ID(C))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(C))))); | ||||
| 			if (cell->hasPort(ID(D))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(D))))); | ||||
| 			for (auto port : {ID::A, ID::B, ID(C), ID(D)}) { | ||||
| 				if (!cell->hasPort(port)) | ||||
| 					continue; | ||||
| 				auto bit = sigmap(SigBit(cell->getPort(port))); | ||||
| 				if (!bit.wire) | ||||
| 					continue; | ||||
| 				new_leaves.insert(bit); | ||||
| 			} | ||||
| 
 | ||||
| 			if (GetSize(new_leaves) > maxbreadth) | ||||
| 				continue; | ||||
|  |  | |||
|  | @ -394,7 +394,7 @@ struct FlowGraph | |||
| 
 | ||||
| 	pair<pool<RTLIL::SigBit>, pool<RTLIL::SigBit>> edge_cut() | ||||
| 	{ | ||||
| 		pool<RTLIL::SigBit> x, xi; | ||||
| 		pool<RTLIL::SigBit> x = {source}, xi; // X and X̅ in the paper
 | ||||
| 
 | ||||
| 		NodePrime source_prime = {source, true}; | ||||
| 		pool<NodePrime> visited; | ||||
|  | @ -437,6 +437,7 @@ struct FlowGraph | |||
| 		for (auto collapsed_node : collapsed[sink]) | ||||
| 			xi.insert(collapsed_node); | ||||
| 
 | ||||
| 		log_assert(x[source] && !xi[source]); | ||||
| 		log_assert(!x[sink] && xi[sink]); | ||||
| 		return {x, xi}; | ||||
| 	} | ||||
|  | @ -1050,7 +1051,7 @@ struct FlowmapWorker | |||
| 
 | ||||
| 				auto cut_inputs = cut_lut_at_gate(lut, lut_gate); | ||||
| 				pool<RTLIL::SigBit> gate_inputs = cut_inputs.first, other_inputs = cut_inputs.second; | ||||
| 				if (gate_inputs.empty() && (int)other_inputs.size() == order) | ||||
| 				if (gate_inputs.empty() && (int)other_inputs.size() >= order) | ||||
| 				{ | ||||
| 					if (debug_relax) | ||||
| 						log("      Breaking would result in a (k+1)-LUT.\n"); | ||||
|  |  | |||
|  | @ -9,12 +9,12 @@ GENFILES += techlibs/common/simcells_help.inc | |||
| 
 | ||||
| techlibs/common/simlib_help.inc: techlibs/common/cellhelp.py techlibs/common/simlib.v | ||||
| 	$(Q) mkdir -p techlibs/common | ||||
| 	$(P) python3 $^ > $@.new | ||||
| 	$(P) $(PYTHON_EXECUTABLE) $^ > $@.new | ||||
| 	$(Q) mv $@.new $@ | ||||
| 
 | ||||
| techlibs/common/simcells_help.inc: techlibs/common/cellhelp.py techlibs/common/simcells.v | ||||
| 	$(Q) mkdir -p techlibs/common | ||||
| 	$(P) python3 $^ > $@.new | ||||
| 	$(P) $(PYTHON_EXECUTABLE) $^ > $@.new | ||||
| 	$(Q) mv $@.new $@ | ||||
| 
 | ||||
| kernel/register.o: techlibs/common/simlib_help.inc techlibs/common/simcells_help.inc | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| // with n <= k inputs should be techmapped in this way, because this shortens the critical path | ||||
| // from n to 1 by avoiding carry chains. | ||||
| 
 | ||||
| (* techmap_celltype = "$eq $ne $lt $le $gt $ge" *) | ||||
| (* techmap_celltype = "$lt $le $gt $ge" *) | ||||
| module _90_lut_cmp_ (A, B, Y); | ||||
| 
 | ||||
| parameter A_SIGNED = 0; | ||||
|  |  | |||
|  | @ -27,12 +27,12 @@ EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk | |||
| 
 | ||||
| techlibs/ecp5/brams_init.mk: techlibs/ecp5/brams_init.py | ||||
| 	$(Q) mkdir -p techlibs/ecp5 | ||||
| 	$(P) python3 $< | ||||
| 	$(P) $(PYTHON_EXECUTABLE) $< | ||||
| 	$(Q) touch $@ | ||||
| 
 | ||||
| techlibs/ecp5/brams_connect.mk: techlibs/ecp5/brams_connect.py | ||||
| 	$(Q) mkdir -p techlibs/ecp5 | ||||
| 	$(P) python3 $< | ||||
| 	$(P) $(PYTHON_EXECUTABLE) $< | ||||
| 	$(Q) touch $@ | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -333,6 +333,13 @@ module ECLKSYNCB( | |||
| ); | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module ECLKBRIDGECS( | ||||
| 	input CLK0, CLK1, SEL, | ||||
| 	output ECSOUT | ||||
| ); | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module DCCA( | ||||
| 	input CLKI, CE, | ||||
|  |  | |||
|  | @ -23,15 +23,15 @@ module FD1S3JX(input PD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLI | |||
| // module FL1S3AY(); endmodule | ||||
| 
 | ||||
| // Diamond I/O registers | ||||
| module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| 
 | ||||
| module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule | ||||
| 
 | ||||
| // TODO: Diamond I/O latches | ||||
| // module IFS1S1B(input PD, D, SCLK, output Q); endmodule | ||||
|  |  | |||
|  | @ -297,6 +297,7 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 			run("simplemap"); | ||||
| 			run("ecp5_ffinit"); | ||||
| 			run("ecp5_gsr"); | ||||
| 			run("attrmvcp -copy -attr syn_useioff"); | ||||
| 			run("opt_clean"); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -313,9 +314,9 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 			if (abc9) { | ||||
| 				run("read_verilog -icells -lib +/ecp5/abc9_model.v"); | ||||
| 				if (nowidelut) | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200"); | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g_nowide.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); | ||||
| 				else | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200"); | ||||
| 					run("abc9 -lut +/ecp5/abc9_5g.lut -box +/ecp5/abc9_5g.box -W 200 -nomfs"); | ||||
| 				run("techmap -map +/ecp5/abc9_unmap.v"); | ||||
| 			} else { | ||||
| 				if (nowidelut) | ||||
|  | @ -338,6 +339,7 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 
 | ||||
| 		if (check_label("check")) | ||||
| 		{ | ||||
| 			run("autoname"); | ||||
| 			run("hierarchy -check"); | ||||
| 			run("stat"); | ||||
| 			run("check -noinit"); | ||||
|  |  | |||
|  | @ -17,6 +17,18 @@ module  \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE | |||
| module  \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule | ||||
| module  \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule | ||||
| 
 | ||||
| module \$_DLATCH_N_ (E, D, Q); | ||||
|   wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; | ||||
|   input E, D; | ||||
|   output Q = !E ? D : Q; | ||||
| endmodule | ||||
| 
 | ||||
| module \$_DLATCH_P_ (E, D, Q); | ||||
|   wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; | ||||
|   input E, D; | ||||
|   output Q = E ? D : Q; | ||||
| endmodule | ||||
| 
 | ||||
| `ifndef NO_LUT | ||||
| module \$lut (A, Y); | ||||
|   parameter WIDTH = 0; | ||||
|  |  | |||
|  | @ -60,6 +60,8 @@ module EFX_FF( | |||
|    assign sr = SR_POLARITY ? SR : ~SR; | ||||
|    assign d = D_POLARITY ? D : ~D; | ||||
| 
 | ||||
| 	initial Q = 1'b0; | ||||
| 
 | ||||
|    generate | ||||
|    	if (SR_SYNC == 1)  | ||||
|       begin | ||||
|  |  | |||
|  | @ -15,3 +15,13 @@ $(eval $(call add_share_file,share/gowin,techlibs/gowin/dram.txt)) | |||
| 
 | ||||
| $(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_init3.vh)) | ||||
| 
 | ||||
| EXTRA_OBJS += techlibs/gowin/brams_init.mk | ||||
| .SECONDARY: techlibs/gowin/brams_init.mk | ||||
| 
 | ||||
| techlibs/gowin/brams_init.mk: techlibs/gowin/brams_init.py | ||||
| 	$(Q) mkdir -p techlibs/gowin | ||||
| 	$(P) python3 $< | ||||
| 	$(Q) touch $@ | ||||
| 
 | ||||
| techlibs/gowin/bram_init_16.vh: techlibs/gowin/brams_init.mk | ||||
| $(eval $(call add_gen_share_file,share/gowin,techlibs/gowin/bram_init_16.vh)) | ||||
|  |  | |||
|  | @ -40,15 +40,15 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO); | |||
|    \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_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 = B_buf; | ||||
|    wire [Y_WIDTH-1:0] 	C = {CO, CI}; | ||||
| 
 | ||||
|    genvar 		i; | ||||
|    generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice | ||||
|       ALU #(.ALU_MODE(32'b0)) | ||||
|       ALU #(.ALU_MODE(2)) // ADDSUB I3 ? add : sub | ||||
|       alu(.I0(AA[i]), | ||||
| 	  .I1(BB[i]), | ||||
| 	  .I3(1'b0), | ||||
| 	  .I3(~BI), | ||||
| 	  .CIN(C[i]), | ||||
| 	  .COUT(CO[i]), | ||||
| 	  .SUM(Y[i]) | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| bram $__GW1NR_SDP | ||||
| # uncomment when done | ||||
| #  init 1 | ||||
|   init 1 | ||||
|   abits 9 @a9d36 | ||||
|   dbits 32 @a9d36 | ||||
|   abits 10 @a10d18 | ||||
|   dbits 16 @a10d18 | ||||
|   abits 11 @a11d9 | ||||
|  | @ -14,7 +15,8 @@ bram $__GW1NR_SDP | |||
|   groups 2 | ||||
|   ports  1 1 | ||||
|   wrmode 1 0 | ||||
|   enable 1 1 @a10d18 | ||||
|   enable 4 1 @a9d36 | ||||
|   enable 2 1 @a10d18 | ||||
|   enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 | ||||
|   transp 0 0 | ||||
|   clocks 2 3 | ||||
|  | @ -24,6 +26,6 @@ endbram | |||
| match $__GW1NR_SDP | ||||
|   min bits 2048 | ||||
|   min efficiency 5 | ||||
|   shuffle_enable B | ||||
|   shuffle_enable A | ||||
|   make_transp | ||||
| endmatch | ||||
|  |  | |||
							
								
								
									
										8
									
								
								techlibs/gowin/brams_init.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								techlibs/gowin/brams_init.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #!/usr/bin/env python3 | ||||
| 
 | ||||
| with open("techlibs/gowin/bram_init_16.vh", "w") as f: | ||||
|     for i in range(0, 0x40): | ||||
|         low = i << 8 | ||||
|         hi = ((i+1) << 8)-1 | ||||
|         snippet = "INIT[%d:%d]" % (hi, low) | ||||
|         print(".INIT_RAM_%02X({%s})," % (i, snippet), file=f) | ||||
|  | @ -8,8 +8,7 @@ | |||
| module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | ||||
| 	parameter CFG_ABITS = 10; | ||||
| 	parameter CFG_DBITS = 16; | ||||
| 	parameter CFG_ENABLE_A = 3; | ||||
| 
 | ||||
| 	parameter CFG_ENABLE_A = 1; | ||||
| 	parameter [16383:0] INIT = 16384'hx; | ||||
| 	parameter CLKPOL2 = 1; | ||||
| 	parameter CLKPOL3 = 1; | ||||
|  | @ -25,9 +24,12 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | |||
| 	output [CFG_DBITS-1:0] B1DATA; | ||||
| 	input B1EN; | ||||
| 
 | ||||
| 	wire [31-CFG_DBITS:0] open; | ||||
| 
 | ||||
| 	 | ||||
| 	generate if (CFG_DBITS == 1) begin | ||||
| 		SDP   #( | ||||
|       `include "bram_init_16.vh" | ||||
| 			.READ_MODE(0), | ||||
| 			.BIT_WIDTH_0(1), | ||||
| 			.BIT_WIDTH_1(1), | ||||
|  | @ -38,10 +40,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | |||
| 			.WREA(A1EN),   .OCE(1'b0), .CEA(1'b1), | ||||
| 			.WREB(1'b0),   .CEB(B1EN), | ||||
| 			.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000), | ||||
| 			.DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR) | ||||
| 			.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}), | ||||
| 			.DO({open, B1DATA}), | ||||
| 			.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}), | ||||
| 			.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}}) | ||||
| 		); | ||||
| 	end else if (CFG_DBITS == 2) begin | ||||
| 		SDP    #( | ||||
|       `include "bram_init_16.vh" | ||||
| 			.READ_MODE(0), | ||||
| 			.BIT_WIDTH_0(2), | ||||
| 			.BIT_WIDTH_1(2), | ||||
|  | @ -52,10 +58,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | |||
| 			.WREA(A1EN),   .OCE(1'b0), .CEA(1'b1), | ||||
| 			.WREB(1'b0),   .CEB(B1EN), | ||||
| 			.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000), | ||||
|                         .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR) | ||||
| 			.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}), | ||||
| 			.DO({open, B1DATA}), | ||||
| 			.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}), | ||||
| 			.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}}) | ||||
| 		); | ||||
| 	end else if (CFG_DBITS <= 4) begin | ||||
| 		SDP    #( | ||||
|       `include "bram_init_16.vh" | ||||
| 			.READ_MODE(0), | ||||
| 			.BIT_WIDTH_0(4), | ||||
| 			.BIT_WIDTH_1(4), | ||||
|  | @ -66,10 +76,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | |||
| 			.WREA(A1EN),   .OCE(1'b0), | ||||
| 			.WREB(1'b0),   .CEB(B1EN), .CEA(1'b1), | ||||
| 			.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000), | ||||
|                         .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR) | ||||
| 			.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}), | ||||
| 			.DO({open, B1DATA}), | ||||
| 			.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}), | ||||
| 			.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}}) | ||||
| 		); | ||||
| 	end else if (CFG_DBITS <= 8) begin | ||||
| 		SDP    #( | ||||
|       `include "bram_init_16.vh" | ||||
| 			.READ_MODE(0), | ||||
| 			.BIT_WIDTH_0(8), | ||||
| 			.BIT_WIDTH_1(8), | ||||
|  | @ -80,10 +94,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | |||
| 			.WREA(A1EN),   .OCE(1'b0), .CEA(1'b1), | ||||
| 			.WREB(1'b0),   .CEB(B1EN), | ||||
| 			.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000), | ||||
|                         .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR) | ||||
| 			.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}), | ||||
| 			.DO({open, B1DATA}), | ||||
| 			.ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}), | ||||
| 			.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}}) | ||||
| 		); | ||||
| 	end else if (CFG_DBITS <= 16) begin | ||||
| 		SDP    #( | ||||
|       `include "bram_init_16.vh" | ||||
| 			.READ_MODE(0), | ||||
| 			.BIT_WIDTH_0(16), | ||||
| 			.BIT_WIDTH_1(16), | ||||
|  | @ -91,10 +109,31 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | |||
| 			.RESET_MODE("SYNC") | ||||
| 		) _TECHMAP_REPLACE_ ( | ||||
| 			.CLKA(CLK2),   .CLKB(CLK3), | ||||
| 			.WREA(A1EN),   .OCE(1'b0), | ||||
| 			.WREA(|A1EN),   .OCE(1'b0), | ||||
| 			.WREB(1'b0),   .CEB(B1EN), .CEA(1'b1), | ||||
| 			.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000), | ||||
|                         .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR) | ||||
| 			.DI({{(32-CFG_DBITS){1'b0}}, A1DATA}), | ||||
| 			.DO({open, B1DATA}), | ||||
| 			.ADA({A1ADDR, {(12-CFG_ABITS){1'b0}}, A1EN}), | ||||
| 			.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}}) | ||||
| 		); | ||||
| 	end else if (CFG_DBITS <= 32) begin | ||||
| 		SDP    #( | ||||
|       `include "bram_init_16.vh" | ||||
| 			.READ_MODE(0), | ||||
| 			.BIT_WIDTH_0(32), | ||||
| 			.BIT_WIDTH_1(32), | ||||
| 			.BLK_SEL(3'b000), | ||||
| 			.RESET_MODE("SYNC") | ||||
| 		) _TECHMAP_REPLACE_ ( | ||||
| 			.CLKA(CLK2),   .CLKB(CLK3), | ||||
| 			.WREA(|A1EN),   .OCE(1'b0), | ||||
| 			.WREB(1'b0),   .CEB(B1EN), .CEA(1'b1), | ||||
| 			.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000), | ||||
| 			.DI(A1DATA), | ||||
| 			.DO(B1DATA), | ||||
| 			.ADA({A1ADDR, {(10-CFG_ABITS){1'b0}}, A1EN}), | ||||
| 			.ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}}) | ||||
| 		); | ||||
| 	end else begin | ||||
| 		wire TECHMAP_FAIL = 1'b1; | ||||
|  |  | |||
|  | @ -1,9 +1,83 @@ | |||
| module  \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule | ||||
| module  \$_DFF_P_ #(parameter INIT = 1'b0) (input D, C, output Q); DFF  #(.INIT(INIT)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule | ||||
| //All DFF* have INIT, but the hardware is always initialised to the reset | ||||
| //value regardless. The parameter is ignored. | ||||
| 
 | ||||
| // DFFN      D Flip-Flop with Negative-Edge Clock | ||||
| module  \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule | ||||
| // DFF       D Flip-Flop | ||||
| module  \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule | ||||
| 
 | ||||
| // DFFE      D Flip-Flop with Clock Enable | ||||
| module  \$_DFFE_PP_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule | ||||
| module  \$_DFFE_PN_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule | ||||
| 
 | ||||
| // DFFNE     D Flip-Flop with Negative-Edge Clock and Clock Enable | ||||
| module  \$_DFFE_NP_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule | ||||
| module  \$_DFFE_NN_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule | ||||
| 
 | ||||
| // DFFR      D Flip-Flop with Synchronous Reset | ||||
| module  \$__DFFS_PN0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule | ||||
| module  \$__DFFS_PP0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule | ||||
| module  \$__DFFS_PP1_ (input D, C, R, output Q); DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule | ||||
| 
 | ||||
| // DFFNR     D Flip-Flop with Negative-Edge Clock and Synchronous Reset | ||||
| module  \$__DFFS_NN0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule | ||||
| module  \$__DFFS_NP0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule | ||||
| 
 | ||||
| // DFFRE     D Flip-Flop with Clock Enable and Synchronous Reset | ||||
| module  \$__DFFSE_PN0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule | ||||
| module  \$__DFFSE_PP0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule | ||||
| 
 | ||||
| // DFFNRE    D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset | ||||
| module  \$__DFFNSE_PN0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule | ||||
| module  \$__DFFNSE_PP0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule | ||||
| 
 | ||||
| // DFFS      D Flip-Flop with Synchronous Set | ||||
| module  \$__DFFS_PN1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule | ||||
| module  \$__DFFS_PP1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule | ||||
| 
 | ||||
| // DFFNS     D Flip-Flop with Negative-Edge Clock and Synchronous Set | ||||
| module  \$__DFFS_NN1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule | ||||
| module  \$__DFFS_NP1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule | ||||
| 
 | ||||
| // DFFSE     D Flip-Flop with Clock Enable and Synchronous Set | ||||
| module  \$__DFFSE_PN1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule | ||||
| module  \$__DFFSE_PP1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule | ||||
| 
 | ||||
| // DFFNSE    D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set | ||||
| module  \$__DFFSE_NN1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule | ||||
| module  \$__DFFSE_NP1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule | ||||
| 
 | ||||
| // DFFP      D Flip-Flop with Asynchronous Preset | ||||
| module  \$_DFF_PP1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule | ||||
| module  \$_DFF_PN1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule | ||||
| 
 | ||||
| // DFFNP     D Flip-Flop with Negative-Edge Clock and Asynchronous Preset | ||||
| module  \$_DFF_NP1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule | ||||
| module  \$_DFF_NN1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule | ||||
| 
 | ||||
| // DFFC      D Flip-Flop with Asynchronous Clear | ||||
| module  \$_DFF_PP0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule | ||||
| module  \$_DFF_PN0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule | ||||
| 
 | ||||
| // DFFNC     D Flip-Flop with Negative-Edge Clock and Asynchronous Clear | ||||
| module  \$_DFF_NP0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule | ||||
| module  \$_DFF_NN0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule | ||||
| 
 | ||||
| // DFFPE     D Flip-Flop with Clock Enable and Asynchronous Preset | ||||
| module  \$__DFFE_PP1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule | ||||
| module  \$__DFFE_PN1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule | ||||
| 
 | ||||
| // DFFNPE    D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset | ||||
| module  \$__DFFE_NP1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule | ||||
| module  \$__DFFE_NN1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule | ||||
| 
 | ||||
| // DFFCE     D Flip-Flop with Clock Enable and Asynchronous Clear | ||||
| module  \$__DFFE_PP0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule | ||||
| module  \$__DFFE_PN0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule | ||||
| 
 | ||||
| // DFFNCE    D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear | ||||
| module  \$__DFFE_NP0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule | ||||
| module  \$__DFFE_NN0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule | ||||
| 
 | ||||
| 
 | ||||
| module \$lut (A, Y); | ||||
|   parameter WIDTH = 0; | ||||
|  | @ -28,6 +102,30 @@ module \$lut (A, Y); | |||
|     if (WIDTH == 4) begin | ||||
|       LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); | ||||
|     end else | ||||
|     if (WIDTH == 5) begin | ||||
|       wire f0, f1; | ||||
|       \$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0)); | ||||
|       \$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1)); | ||||
|       MUX2_LUT5 mux5(.I0(f0), .I1(f1), .S0(A[4]), .O(Y)); | ||||
|     end else | ||||
|     if (WIDTH == 6) begin | ||||
|       wire f0, f1; | ||||
|       \$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0)); | ||||
|       \$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1)); | ||||
|       MUX2_LUT6 mux6(.I0(f0), .I1(f1), .S0(A[5]), .O(Y)); | ||||
|     end else | ||||
|     if (WIDTH == 7) begin | ||||
|       wire f0, f1; | ||||
|       \$lut #(.LUT(LUT[63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0)); | ||||
|       \$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1)); | ||||
|       MUX2_LUT7 mux7(.I0(f0), .I1(f1), .S0(A[6]), .O(Y)); | ||||
|     end else | ||||
|     if (WIDTH == 8) begin | ||||
|       wire f0, f1; | ||||
|       \$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0)); | ||||
|       \$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1)); | ||||
|       MUX2_LUT8 mux8(.I0(f0), .I1(f1), .S0(A[7]), .O(Y)); | ||||
|     end else begin | ||||
|       wire _TECHMAP_FAIL_ = 1; | ||||
|     end | ||||
|  |  | |||
|  | @ -24,6 +24,41 @@ module LUT4(output F, input I0, I1, I2, I3); | |||
| 	assign F = I0 ? s1[1] : s1[0]; | ||||
| endmodule | ||||
| 
 | ||||
| module MUX2 (O, I0, I1, S0); | ||||
|   input I0,I1; | ||||
|   input S0; | ||||
|   output O; | ||||
|   assign O = S0 ? I1 : I0; | ||||
| endmodule | ||||
| 
 | ||||
| module MUX2_LUT5 (O, I0, I1, S0); | ||||
|   input I0,I1; | ||||
|   input S0; | ||||
|   output O; | ||||
|   MUX2 mux2_lut5 (O, I0, I1, S0); | ||||
| endmodule | ||||
| 
 | ||||
| module MUX2_LUT6 (O, I0, I1, S0); | ||||
|   input I0,I1; | ||||
|   input S0; | ||||
|   output O; | ||||
|   MUX2 mux2_lut6 (O, I0, I1, S0); | ||||
| endmodule | ||||
| 
 | ||||
| module MUX2_LUT7 (O, I0, I1, S0); | ||||
|   input I0,I1; | ||||
|   input S0; | ||||
|   output O; | ||||
|   MUX2 mux2_lut7 (O, I0, I1, S0); | ||||
| endmodule | ||||
| 
 | ||||
| module MUX2_LUT8 (O, I0, I1, S0); | ||||
|   input I0,I1; | ||||
|   input S0; | ||||
|   output O; | ||||
|   MUX2 mux2_lut8 (O, I0, I1, S0); | ||||
| endmodule | ||||
| 
 | ||||
| module DFF (output reg Q, input CLK, D); | ||||
| 	parameter [0:0] INIT = 1'b0; | ||||
| 	initial Q = INIT; | ||||
|  | @ -31,12 +66,39 @@ module DFF (output reg Q, input CLK, D); | |||
| 		Q <= D; | ||||
| endmodule | ||||
| 
 | ||||
| module DFFN (output reg Q, input CLK, D); | ||||
| module DFFE (output reg Q, input D, CLK, CE); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
| 	always @(negedge CLK) | ||||
|   always @(posedge CLK) begin | ||||
|     if (CE) | ||||
|       Q <= D; | ||||
| endmodule | ||||
|   end | ||||
| endmodule // DFFE (positive clock edge; clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFS (output reg Q, input D, CLK, SET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(posedge CLK) begin | ||||
|     if (SET) | ||||
|       Q <= 1'b1; | ||||
|     else | ||||
|       Q <= D;	 | ||||
|   end | ||||
| endmodule // DFFS (positive clock edge; synchronous set) | ||||
| 
 | ||||
| 
 | ||||
| module DFFSE (output reg Q, input D, CLK, CE, SET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(posedge CLK) begin | ||||
|     if (SET) | ||||
|       Q <= 1'b1; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
| end | ||||
| endmodule // DFFSE (positive clock edge; synchronous set takes precedence over clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFR (output reg Q, input D, CLK, RESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|  | @ -49,6 +111,181 @@ module DFFR (output reg Q, input D, CLK, RESET); | |||
|   end | ||||
| endmodule // DFFR (positive clock edge; synchronous reset) | ||||
| 
 | ||||
| 
 | ||||
| module DFFRE (output reg Q, input D, CLK, CE, RESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(posedge CLK) begin | ||||
|     if (RESET) | ||||
|       Q <= 1'b0; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFRE (positive clock edge; synchronous reset takes precedence over clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFP (output reg Q, input D, CLK, PRESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(posedge CLK or posedge PRESET) begin | ||||
|     if(PRESET) | ||||
|       Q <= 1'b1; | ||||
|     else | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFP (positive clock edge; asynchronous preset) | ||||
| 
 | ||||
| 
 | ||||
| module DFFPE (output reg Q, input D, CLK, CE, PRESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(posedge CLK or posedge PRESET) begin | ||||
|     if(PRESET) | ||||
|       Q <= 1'b1; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFPE (positive clock edge; asynchronous preset; clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFC (output reg Q, input D, CLK, CLEAR); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(posedge CLK or posedge CLEAR) begin | ||||
|     if(CLEAR) | ||||
|       Q <= 1'b0; | ||||
|     else | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFC (positive clock edge; asynchronous clear) | ||||
| 
 | ||||
| 
 | ||||
| module DFFCE (output reg Q, input D, CLK, CE, CLEAR); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(posedge CLK or posedge CLEAR) begin | ||||
|     if(CLEAR) | ||||
|       Q <= 1'b0; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFCE (positive clock edge; asynchronous clear; clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFN (output reg Q, input CLK, D); | ||||
| 	parameter [0:0] INIT = 1'b0; | ||||
| 	initial Q = INIT; | ||||
| 	always @(negedge CLK) | ||||
| 		Q <= D; | ||||
| endmodule | ||||
| 
 | ||||
| module DFFNE (output reg Q, input D, CLK, CE); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK) begin | ||||
|     if (CE) | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFNE (negative clock edge; clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNS (output reg Q, input D, CLK, SET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK) begin | ||||
|     if (SET) | ||||
|       Q <= 1'b1; | ||||
|     else | ||||
|       Q <= D;	 | ||||
|   end | ||||
| endmodule // DFFNS (negative clock edge; synchronous set) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNSE (output reg Q, input D, CLK, CE, SET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK) begin | ||||
|     if (SET) | ||||
|       Q <= 1'b1; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
| end | ||||
| endmodule // DFFNSE (negative clock edge; synchronous set takes precedence over clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNR (output reg Q, input D, CLK, RESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK) begin | ||||
|     if (RESET) | ||||
|       Q <= 1'b0; | ||||
|     else | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFNR (negative clock edge; synchronous reset) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNRE (output reg Q, input D, CLK, CE, RESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK) begin | ||||
|     if (RESET) | ||||
|       Q <= 1'b0; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFNRE (negative clock edge; synchronous reset takes precedence over clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNP (output reg Q, input D, CLK, PRESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK or posedge PRESET) begin | ||||
|     if(PRESET) | ||||
|       Q <= 1'b1; | ||||
|     else | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFNP (negative clock edge; asynchronous preset) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNPE (output reg Q, input D, CLK, CE, PRESET); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK or posedge PRESET) begin | ||||
|     if(PRESET) | ||||
|       Q <= 1'b1; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFNPE (negative clock edge; asynchronous preset; clock enable) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNC (output reg Q, input D, CLK, CLEAR); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK or posedge CLEAR) begin | ||||
|     if(CLEAR) | ||||
|       Q <= 1'b0; | ||||
|     else | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFNC (negative clock edge; asynchronous clear) | ||||
| 
 | ||||
| 
 | ||||
| module DFFNCE (output reg Q, input D, CLK, CE, CLEAR); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   initial Q = INIT; | ||||
|   always @(negedge CLK or posedge CLEAR) begin | ||||
|     if(CLEAR) | ||||
|       Q <= 1'b0; | ||||
|     else if (CE) | ||||
|       Q <= D; | ||||
|   end | ||||
| endmodule // DFFNCE (negative clock edge; asynchronous clear; clock enable) | ||||
| 
 | ||||
| // TODO add more DFF sim cells | ||||
| 
 | ||||
| module VCC(output V); | ||||
| 	assign V = 1; | ||||
| endmodule | ||||
|  | @ -65,14 +302,98 @@ module OBUF(output O, input I); | |||
| 	assign O = I; | ||||
| endmodule | ||||
| 
 | ||||
| module TBUF (O, I, OEN); | ||||
|   input I, OEN; | ||||
|   output O; | ||||
|   assign O = OEN ? I : 1'bz; | ||||
| endmodule | ||||
| 
 | ||||
| module IOBUF (O, IO, I, OEN); | ||||
|   input I,OEN; | ||||
|   output O; | ||||
|   inout IO; | ||||
|   assign IO = OEN ? I : 1'bz; | ||||
|   assign I = IO; | ||||
| endmodule | ||||
| 
 | ||||
| module GSR (input GSRI); | ||||
| 	wire GSRO = GSRI; | ||||
| endmodule | ||||
| 
 | ||||
| module ALU (input I0, input I1, input I3, input CIN, output COUT, output SUM); | ||||
|    parameter [3:0] ALU_MODE = 0; // default 0 = ADD | ||||
|    assign  {COUT, SUM} = CIN + I1 + I0; | ||||
| endmodule // alu | ||||
| module ALU (SUM, COUT, I0, I1, I3, CIN); | ||||
| 
 | ||||
| input I0; | ||||
| input I1; | ||||
| input I3; | ||||
| input CIN; | ||||
| output SUM; | ||||
| output COUT; | ||||
| 
 | ||||
| localparam ADD = 0; | ||||
| localparam SUB = 1; | ||||
| localparam ADDSUB = 2; | ||||
| localparam NE = 3; | ||||
| localparam GE = 4; | ||||
| localparam LE = 5; | ||||
| localparam CUP = 6; | ||||
| localparam CDN = 7; | ||||
| localparam CUPCDN = 8; | ||||
| localparam MULT = 9; | ||||
| 
 | ||||
| parameter ALU_MODE = 0; | ||||
| 
 | ||||
| reg S, C; | ||||
| 
 | ||||
| assign SUM = S ^ CIN; | ||||
| assign COUT = S? CIN : C; | ||||
| 
 | ||||
| always @* begin | ||||
| 	case (ALU_MODE) | ||||
| 		ADD: begin | ||||
| 			S = I0 ^ I1; | ||||
| 			C = I0; | ||||
| 		end | ||||
| 		SUB: begin | ||||
| 			S = I0 ^ ~I1; | ||||
| 			C = I0; | ||||
| 		end | ||||
| 		ADDSUB: begin | ||||
| 			S = I3? I0 ^ I1 : I0 ^ ~I1; | ||||
| 			C = I0; | ||||
| 		end | ||||
| 		NE: begin | ||||
| 			S = I0 ^ ~I1; | ||||
| 			C = 1'b1; | ||||
| 		end | ||||
| 		GE: begin | ||||
| 			S = I0 ^ ~I1; | ||||
| 			C = I0; | ||||
| 		end | ||||
| 		LE: begin | ||||
| 			S = ~I0 ^ I1; | ||||
| 			C = I1; | ||||
| 		end | ||||
| 		CUP: begin | ||||
| 			S = I0; | ||||
| 			C = 1'b0; | ||||
| 		end | ||||
| 		CDN: begin | ||||
| 			S = ~I0; | ||||
| 			C = 1'b1; | ||||
| 		end | ||||
| 		CUPCDN: begin | ||||
| 			S = I3? I0 : ~I0; | ||||
| 			C = I0; | ||||
| 		end | ||||
| 		MULT: begin | ||||
| 			S = I0 & I1; | ||||
| 			C = I0 & I1; | ||||
| 		end | ||||
| 	endcase | ||||
| end | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| module RAM16S4 (DO, DI, AD, WRE, CLK); | ||||
|    parameter WIDTH  = 4; | ||||
|  |  | |||
|  | @ -64,6 +64,12 @@ struct SynthGowinPass : public ScriptPass | |||
| 		log("    -retime\n"); | ||||
| 		log("        run 'abc' with -dff option\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nowidelut\n"); | ||||
| 		log("        do not use muxes to implement LUTs larger than LUT4s\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -abc9\n"); | ||||
| 		log("        use new ABC9 flow (EXPERIMENTAL)\n"); | ||||
| 		log("\n"); | ||||
| 		log("\n"); | ||||
| 		log("The following commands are executed by this synthesis command:\n"); | ||||
| 		help_script(); | ||||
|  | @ -71,7 +77,7 @@ struct SynthGowinPass : public ScriptPass | |||
| 	} | ||||
| 
 | ||||
| 	string top_opt, vout_file; | ||||
| 	bool retime, nobram, nodram, flatten, nodffe; | ||||
| 	bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9; | ||||
| 
 | ||||
| 	void clear_flags() YS_OVERRIDE | ||||
| 	{ | ||||
|  | @ -82,6 +88,8 @@ struct SynthGowinPass : public ScriptPass | |||
| 		nobram = false; | ||||
| 		nodffe = false; | ||||
| 		nodram = false; | ||||
| 		nowidelut = false; | ||||
| 		abc9 = false; | ||||
| 	} | ||||
| 
 | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
|  | @ -128,6 +136,14 @@ struct SynthGowinPass : public ScriptPass | |||
| 				flatten = false; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-nowidelut") { | ||||
| 				nowidelut = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-abc9") { | ||||
| 				abc9 = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
|  | @ -186,6 +202,7 @@ struct SynthGowinPass : public ScriptPass | |||
| 			run("techmap -map +/techmap.v"); | ||||
| 			if (retime || help_mode) | ||||
| 				run("abc -dff", "(only if -retime)"); | ||||
| 			run("splitnets"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_ffs")) | ||||
|  | @ -202,16 +219,25 @@ struct SynthGowinPass : public ScriptPass | |||
| 
 | ||||
| 		if (check_label("map_luts")) | ||||
| 		{ | ||||
| 			if (nowidelut && abc9) { | ||||
| 				run("abc9 -lut 4"); | ||||
| 			} else if (nowidelut && !abc9) { | ||||
| 				run("abc -lut 4"); | ||||
| 			} else if (!nowidelut && abc9) { | ||||
| 				run("abc9 -lut 4:8"); | ||||
| 			} else if (!nowidelut && !abc9) { | ||||
| 				run("abc -lut 4:8"); | ||||
| 			} | ||||
| 			run("clean"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_cells")) | ||||
| 		{ | ||||
| 			run("techmap -map +/gowin/cells_map.v"); | ||||
| 			run("hilomap -hicell VCC V -locell GND G"); | ||||
| 			run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O", "(unless -noiopads)"); | ||||
| 			run("dffinit  -ff DFF Q INIT"); | ||||
| 			run("setundef -undriven -params -zero"); | ||||
| 			run("hilomap -singleton -hicell VCC V -locell GND G"); | ||||
| 			run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O " | ||||
| 				"-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)"); | ||||
| 			run("clean"); | ||||
| 
 | ||||
| 		} | ||||
|  | @ -226,7 +252,7 @@ struct SynthGowinPass : public ScriptPass | |||
| 		if (check_label("vout")) | ||||
| 		{ | ||||
| 			if (!vout_file.empty() || help_mode) | ||||
| 				run(stringf("write_verilog -nodec -attr2comment -defparam -renameprefix gen %s", | ||||
| 				 run(stringf("write_verilog -decimal -attr2comment -defparam -renameprefix gen %s", | ||||
| 						help_mode ? "<file-name>" : vout_file.c_str())); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ EXTRA_OBJS += techlibs/ice40/brams_init.mk | |||
| 
 | ||||
| techlibs/ice40/brams_init.mk: techlibs/ice40/brams_init.py | ||||
| 	$(Q) mkdir -p techlibs/ice40 | ||||
| 	$(P) python3 $< | ||||
| 	$(P) $(PYTHON_EXECUTABLE) $< | ||||
| 	$(Q) touch techlibs/ice40/brams_init.mk | ||||
| 
 | ||||
| techlibs/ice40/brams_init1.vh: techlibs/ice40/brams_init.mk | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| 
 | ||||
| `timescale 1ps / 1ps | ||||
| `define SB_DFF_REG reg Q = 0 | ||||
| // `define SB_DFF_REG reg Q | ||||
| 
 | ||||
|  | @ -81,6 +81,37 @@ module SB_IO ( | |||
| 		if (PIN_TYPE[5:4] == 2'b11) assign PACKAGE_PIN = outena_q ? dout : 1'bz; | ||||
| 	endgenerate | ||||
| `endif | ||||
| `ifdef TIMING | ||||
| specify | ||||
| 	(INPUT_CLK => D_IN_0) = (0:0:0, 0:0:0); | ||||
| 	(INPUT_CLK => D_IN_1) = (0:0:0, 0:0:0); | ||||
| 	(PACKAGE_PIN => D_IN_0) = (0:0:0, 0:0:0); | ||||
| 	(OUTPUT_CLK => PACKAGE_PIN) = (0:0:0, 0:0:0); | ||||
| 	(D_OUT_0 => PACKAGE_PIN) = (0:0:0, 0:0:0); | ||||
| 	(OUTPUT_ENABLE => PACKAGE_PIN) = (0:0:0, 0:0:0); | ||||
| 
 | ||||
| 	$setuphold(posedge OUTPUT_CLK, posedge D_OUT_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge OUTPUT_CLK, negedge D_OUT_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge OUTPUT_CLK, posedge D_OUT_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge OUTPUT_CLK, negedge D_OUT_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge OUTPUT_CLK, posedge D_OUT_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge OUTPUT_CLK, negedge D_OUT_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge OUTPUT_CLK, posedge D_OUT_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge OUTPUT_CLK, negedge D_OUT_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge INPUT_CLK, posedge CLOCK_ENABLE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge INPUT_CLK, negedge CLOCK_ENABLE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge OUTPUT_CLK, posedge CLOCK_ENABLE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge OUTPUT_CLK, negedge CLOCK_ENABLE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge INPUT_CLK, posedge PACKAGE_PIN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge INPUT_CLK, negedge PACKAGE_PIN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge INPUT_CLK, posedge PACKAGE_PIN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge INPUT_CLK, negedge PACKAGE_PIN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge OUTPUT_CLK, posedge OUTPUT_ENABLE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge OUTPUT_CLK, negedge OUTPUT_ENABLE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge OUTPUT_CLK, posedge OUTPUT_ENABLE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge OUTPUT_CLK, negedge OUTPUT_ENABLE, 0:0:0, 0:0:0); | ||||
| endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| module SB_GB_IO ( | ||||
|  | @ -127,6 +158,11 @@ module SB_GB ( | |||
| 	output GLOBAL_BUFFER_OUTPUT | ||||
| ); | ||||
| 	assign GLOBAL_BUFFER_OUTPUT = USER_SIGNAL_TO_GLOBAL_BUFFER; | ||||
| `ifdef TIMING | ||||
| specify | ||||
| 	(USER_SIGNAL_TO_GLOBAL_BUFFER => GLOBAL_BUFFER_OUTPUT) = (0:0:0, 0:0:0); | ||||
| endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| // SiliconBlue Logic Cells | ||||
|  | @ -830,33 +866,81 @@ module ICESTORM_LC ( | |||
| 	parameter [0:0] CIN_CONST    = 0; | ||||
| 	parameter [0:0] CIN_SET      = 0; | ||||
| 
 | ||||
| 	wire I0_pd = (I0 === 1'bz) ? 1'b0 : I0; | ||||
| 	wire I1_pd = (I1 === 1'bz) ? 1'b0 : I1; | ||||
| 	wire I2_pd = (I2 === 1'bz) ? 1'b0 : I2; | ||||
| 	wire I3_pd = (I3 === 1'bz) ? 1'b0 : I3; | ||||
| 	wire SR_pd = (SR === 1'bz) ? 1'b0 : SR; | ||||
| 	wire CEN_pu = (CEN === 1'bz) ? 1'b1 : CEN; | ||||
| 
 | ||||
| 	wire mux_cin = CIN_CONST ? CIN_SET : CIN; | ||||
| 
 | ||||
| 	assign COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && mux_cin) : 1'bx; | ||||
| 	assign COUT = CARRY_ENABLE ? (I1_pd && I2_pd) || ((I1_pd || I2_pd) && mux_cin) : 1'bx; | ||||
| 
 | ||||
| 	wire [7:0] lut_s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0]; | ||||
| 	wire [3:0] lut_s2 = I2 ?   lut_s3[ 7:4] :   lut_s3[3:0]; | ||||
| 	wire [1:0] lut_s1 = I1 ?   lut_s2[ 3:2] :   lut_s2[1:0]; | ||||
| 	wire       lut_o  = I0 ?   lut_s1[   1] :   lut_s1[  0]; | ||||
| 	wire [7:0] lut_s3 = I3_pd ? LUT_INIT[15:8] : LUT_INIT[7:0]; | ||||
| 	wire [3:0] lut_s2 = I2_pd ?   lut_s3[ 7:4] :   lut_s3[3:0]; | ||||
| 	wire [1:0] lut_s1 = I1_pd ?   lut_s2[ 3:2] :   lut_s2[1:0]; | ||||
| 	wire       lut_o  = I0_pd ?   lut_s1[   1] :   lut_s1[  0]; | ||||
| 
 | ||||
| 	assign LO = lut_o; | ||||
| 
 | ||||
| 	wire polarized_clk; | ||||
| 	assign polarized_clk = CLK ^ NEG_CLK; | ||||
| 
 | ||||
| 	reg o_reg; | ||||
| 	reg o_reg = 1'b0; | ||||
| 	always @(posedge polarized_clk) | ||||
| 		if (CEN) | ||||
| 			o_reg <= SR ? SET_NORESET : lut_o; | ||||
| 		if (CEN_pu) | ||||
| 			o_reg <= SR_pd ? SET_NORESET : lut_o; | ||||
| 
 | ||||
| 	reg o_reg_async; | ||||
| 	reg o_reg_async = 1'b0; | ||||
| 	always @(posedge polarized_clk, posedge SR) | ||||
| 		if (SR) | ||||
| 			o_reg <= SET_NORESET; | ||||
| 		else if (CEN) | ||||
| 			o_reg <= lut_o; | ||||
| 		if (SR_pd) | ||||
| 			o_reg_async <= SET_NORESET; | ||||
| 		else if (CEN_pu) | ||||
| 			o_reg_async <= lut_o; | ||||
| 
 | ||||
| 	assign O = DFF_ENABLE ? ASYNC_SR ? o_reg_async : o_reg : lut_o; | ||||
| `ifdef TIMING | ||||
| specify | ||||
| 	(I0 => O) = (0:0:0, 0:0:0); | ||||
| 	(I1 => O) = (0:0:0, 0:0:0); | ||||
| 	(I2 => O) = (0:0:0, 0:0:0); | ||||
| 	(I3 => O) = (0:0:0, 0:0:0); | ||||
| 	(I0 => LO) = (0:0:0, 0:0:0); | ||||
| 	(I1 => LO) = (0:0:0, 0:0:0); | ||||
| 	(I2 => LO) = (0:0:0, 0:0:0); | ||||
| 	(I3 => LO) = (0:0:0, 0:0:0); | ||||
| 	(I1 => COUT) = (0:0:0, 0:0:0); | ||||
| 	(I2 => COUT) = (0:0:0, 0:0:0); | ||||
| 	(CIN => COUT) = (0:0:0, 0:0:0); | ||||
| 	(CLK => O) = (0:0:0, 0:0:0); | ||||
| 	(SR => O) = (0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, posedge I0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, negedge I0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, posedge I0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, negedge I0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, posedge I1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, negedge I1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, posedge I1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, negedge I1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, posedge I2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, negedge I2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, posedge I2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, negedge I2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, posedge I3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, negedge I3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, posedge I3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, negedge I3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, posedge CEN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, negedge CEN, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, posedge SR, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge CLK, negedge SR, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, posedge SR, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge CLK, negedge SR, 0:0:0, 0:0:0); | ||||
| endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| // SiliconBlue PLL Cells | ||||
|  | @ -1576,3 +1660,341 @@ module SB_MAC16 ( | |||
| 	assign LCI = (BOTADDSUB_CARRYSELECT == 0) ? 1'b0 : (BOTADDSUB_CARRYSELECT == 1) ? 1'b1 : (BOTADDSUB_CARRYSELECT == 2) ? ACCUMCI : CI; | ||||
| 	assign O = {Oh, Ol}; | ||||
| endmodule | ||||
| 
 | ||||
| // Post-place-and-route RAM model | ||||
| module ICESTORM_RAM( | ||||
| 	output RDATA_15, RDATA_14, RDATA_13, RDATA_12, RDATA_11, RDATA_10, RDATA_9, RDATA_8, RDATA_7, RDATA_6, RDATA_5, RDATA_4, RDATA_3, RDATA_2, RDATA_1, RDATA_0, | ||||
| 	input  RCLK, RCLKE, RE, | ||||
| 	input  RADDR_10, RADDR_9, RADDR_8, RADDR_7, RADDR_6, RADDR_5, RADDR_4, RADDR_3, RADDR_2, RADDR_1, RADDR_0, | ||||
| 	input  WCLK, WCLKE, WE, | ||||
| 	input  WADDR_10, WADDR_9, WADDR_8, WADDR_7, WADDR_6, WADDR_5, WADDR_4, WADDR_3, WADDR_2, WADDR_1, WADDR_0, | ||||
| 	input  MASK_15, MASK_14, MASK_13, MASK_12, MASK_11, MASK_10, MASK_9, MASK_8, MASK_7, MASK_6, MASK_5, MASK_4, MASK_3, MASK_2, MASK_1, MASK_0, | ||||
| 	input  WDATA_15, WDATA_14, WDATA_13, WDATA_12, WDATA_11, WDATA_10, WDATA_9, WDATA_8, WDATA_7, WDATA_6, WDATA_5, WDATA_4, WDATA_3, WDATA_2, WDATA_1, WDATA_0 | ||||
| ); | ||||
| 	parameter WRITE_MODE = 0; | ||||
| 	parameter READ_MODE = 0; | ||||
| 
 | ||||
| 	parameter NEG_CLK_R = 1'b0; | ||||
| 	parameter NEG_CLK_W = 1'b0; | ||||
| 
 | ||||
| 	parameter INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	// Pull-down and pull-up functions | ||||
| 	function pd; | ||||
| 		input x; | ||||
| 		begin | ||||
| 			pd = (x === 1'bz) ? 1'b0 : x; | ||||
| 		end | ||||
| 	endfunction | ||||
| 
 | ||||
| 	function pu; | ||||
| 		input x; | ||||
| 		begin | ||||
| 			pu = (x === 1'bz) ? 1'b1 : x; | ||||
| 		end | ||||
| 	endfunction | ||||
| 
 | ||||
| 	SB_RAM40_4K #( | ||||
| 		.WRITE_MODE(WRITE_MODE), | ||||
| 		.READ_MODE (READ_MODE ), | ||||
| 		.INIT_0    (INIT_0    ), | ||||
| 		.INIT_1    (INIT_1    ), | ||||
| 		.INIT_2    (INIT_2    ), | ||||
| 		.INIT_3    (INIT_3    ), | ||||
| 		.INIT_4    (INIT_4    ), | ||||
| 		.INIT_5    (INIT_5    ), | ||||
| 		.INIT_6    (INIT_6    ), | ||||
| 		.INIT_7    (INIT_7    ), | ||||
| 		.INIT_8    (INIT_8    ), | ||||
| 		.INIT_9    (INIT_9    ), | ||||
| 		.INIT_A    (INIT_A    ), | ||||
| 		.INIT_B    (INIT_B    ), | ||||
| 		.INIT_C    (INIT_C    ), | ||||
| 		.INIT_D    (INIT_D    ), | ||||
| 		.INIT_E    (INIT_E    ), | ||||
| 		.INIT_F    (INIT_F    ) | ||||
| 	) RAM ( | ||||
| 		.RDATA({RDATA_15, RDATA_14, RDATA_13, RDATA_12, RDATA_11, RDATA_10, RDATA_9, RDATA_8, RDATA_7, RDATA_6, RDATA_5, RDATA_4, RDATA_3, RDATA_2, RDATA_1, RDATA_0}), | ||||
| 		.RCLK (pd(RCLK) ^ NEG_CLK_R), | ||||
| 		.RCLKE(pu(RCLKE)), | ||||
| 		.RE   (pd(RE)), | ||||
| 		.RADDR({pd(RADDR_10), pd(RADDR_9), pd(RADDR_8), pd(RADDR_7), pd(RADDR_6), pd(RADDR_5), pd(RADDR_4), pd(RADDR_3), pd(RADDR_2), pd(RADDR_1), pd(RADDR_0)}), | ||||
| 		.WCLK (pd(WCLK) ^ NEG_CLK_W), | ||||
| 		.WCLKE(pu(WCLKE)), | ||||
| 		.WE   (pd(WE)), | ||||
| 		.WADDR({pd(WADDR_10), pd(WADDR_9), pd(WADDR_8), pd(WADDR_7), pd(WADDR_6), pd(WADDR_5), pd(WADDR_4), pd(WADDR_3), pd(WADDR_2), pd(WADDR_1), pd(WADDR_0)}), | ||||
| 		.MASK ({pd(MASK_15), pd(MASK_14), pd(MASK_13), pd(MASK_12), pd(MASK_11), pd(MASK_10), pd(MASK_9), pd(MASK_8), | ||||
| 			pd(MASK_7), pd(MASK_6), pd(MASK_5), pd(MASK_4), pd(MASK_3), pd(MASK_2), pd(MASK_1), pd(MASK_0)}), | ||||
| 		.WDATA({pd(WDATA_15), pd(WDATA_14), pd(WDATA_13), pd(WDATA_12), pd(WDATA_11), pd(WDATA_10), pd(WDATA_9), pd(WDATA_8), | ||||
| 			pd(WDATA_7), pd(WDATA_6), pd(WDATA_5), pd(WDATA_4), pd(WDATA_3), pd(WDATA_2), pd(WDATA_1), pd(WDATA_0)}) | ||||
| 	); | ||||
| 
 | ||||
| `ifdef TIMING | ||||
| specify | ||||
| 	(RCLK => RDATA_15) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_14) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_13) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_12) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_11) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_10) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_9) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_8) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_7) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_6) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_5) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_4) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_3) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_2) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_1) = (0:0:0, 0:0:0); | ||||
| 	(RCLK => RDATA_0) = (0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, posedge RADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge RCLK, negedge RADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, posedge RADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge RCLK, negedge RADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WCLKE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WE, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WADDR_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge MASK_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge MASK_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge MASK_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge MASK_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_15, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_14, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_13, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_12, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_11, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_10, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_9, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_8, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_7, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_6, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_5, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_4, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_3, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_2, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_1, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, posedge WDATA_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(posedge WCLK, negedge WDATA_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, posedge WDATA_0, 0:0:0, 0:0:0); | ||||
| 	$setuphold(negedge WCLK, negedge WDATA_0, 0:0:0, 0:0:0); | ||||
| 
 | ||||
| endspecify | ||||
| `endif | ||||
| endmodule | ||||
|  |  | |||
|  | @ -273,6 +273,7 @@ struct SynthIce40Pass : public ScriptPass | |||
| 			run("opt_expr"); | ||||
| 			run("opt_clean"); | ||||
| 			if (help_mode || dsp) { | ||||
| 				run("memory_dff"); | ||||
| 				run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 " | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 " | ||||
| 						"-D DSP_NAME=$__MUL16X16", "(if -dsp)"); | ||||
|  | @ -379,6 +380,7 @@ struct SynthIce40Pass : public ScriptPass | |||
| 
 | ||||
| 		if (check_label("check")) | ||||
| 		{ | ||||
| 			run("autoname"); | ||||
| 			run("hierarchy -check"); | ||||
| 			run("stat"); | ||||
| 			run("check -noinit"); | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ EXTRA_OBJS += techlibs/xilinx/brams_init.mk | |||
| 
 | ||||
| techlibs/xilinx/brams_init.mk: techlibs/xilinx/brams_init.py | ||||
| 	$(Q) mkdir -p techlibs/xilinx | ||||
| 	$(P) python3 $< | ||||
| 	$(P) $(PYTHON_EXECUTABLE) $< | ||||
| 	$(Q) touch $@ | ||||
| 
 | ||||
| techlibs/xilinx/brams_init_36.vh: techlibs/xilinx/brams_init.mk | ||||
|  | @ -25,16 +25,14 @@ techlibs/xilinx/brams_init_8.vh: techlibs/xilinx/brams_init.mk | |||
| 
 | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_sim.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_cells_xtra.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6v_cells_xtra.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_cells_xtra.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_cells_xtra.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/cells_xtra.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams.txt)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_brams_bb.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams.txt)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_xcu_brams.txt)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_bb.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_brams_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcup_urams.txt)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcup_urams_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams.txt)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) | ||||
|  | @ -42,7 +40,13 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_ff_map.v)) | |||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_ff_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3s_mult_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3sda_dsp_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_dsp_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc4v_dsp_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc5v_dsp_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v)) | ||||
| 
 | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v)) | ||||
|  |  | |||
|  | @ -38,6 +38,17 @@ module IBUF( | |||
|   assign O = I; | ||||
| endmodule | ||||
| 
 | ||||
| module IBUFG( | ||||
|     output O, | ||||
|     (* iopad_external_pin *) | ||||
|     input I); | ||||
|   parameter CAPACITANCE = "DONT_CARE"; | ||||
|   parameter IBUF_DELAY_VALUE = "0"; | ||||
|   parameter IBUF_LOW_PWR = "TRUE"; | ||||
|   parameter IOSTANDARD = "DEFAULT"; | ||||
|   assign O = I; | ||||
| endmodule | ||||
| 
 | ||||
| module OBUF( | ||||
|     (* iopad_external_pin *) | ||||
|     output O, | ||||
|  | @ -578,6 +589,515 @@ module SRLC32E ( | |||
|   endgenerate | ||||
| endmodule | ||||
| 
 | ||||
| // DSP | ||||
| 
 | ||||
| // Virtex 2, Virtex 2 Pro, Spartan 3. | ||||
| 
 | ||||
| // Asynchronous mode. | ||||
| 
 | ||||
| module MULT18X18 ( | ||||
|     input signed [17:0] A, | ||||
|     input signed [17:0] B, | ||||
|     output signed [35:0] P | ||||
| ); | ||||
| 
 | ||||
| assign P = A * B; | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // Synchronous mode. | ||||
| 
 | ||||
| module MULT18X18S ( | ||||
|     input signed [17:0] A, | ||||
|     input signed [17:0] B, | ||||
|     output reg signed [35:0] P, | ||||
|     (* clkbuf_sink *) | ||||
|     input C, | ||||
|     input CE, | ||||
|     input R | ||||
| ); | ||||
| 
 | ||||
| always @(posedge C) | ||||
| 	if (R) | ||||
| 		P <= 0; | ||||
| 	else if (CE) | ||||
| 		P <= A * B; | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // Spartan 3E, Spartan 3A. | ||||
| 
 | ||||
| module MULT18X18SIO ( | ||||
|     input signed [17:0] A, | ||||
|     input signed [17:0] B, | ||||
|     output signed [35:0] P, | ||||
|     (* clkbuf_sink *) | ||||
|     input CLK, | ||||
|     input CEA, | ||||
|     input CEB, | ||||
|     input CEP, | ||||
|     input RSTA, | ||||
|     input RSTB, | ||||
|     input RSTP, | ||||
|     input signed [17:0] BCIN, | ||||
|     output signed [17:0] BCOUT | ||||
| ); | ||||
| 
 | ||||
| parameter integer AREG = 1; | ||||
| parameter integer BREG = 1; | ||||
| parameter B_INPUT = "DIRECT"; | ||||
| parameter integer PREG = 1; | ||||
| 
 | ||||
| // The multiplier. | ||||
| wire signed [35:0] P_MULT; | ||||
| assign P_MULT = A_MULT * B_MULT; | ||||
| 
 | ||||
| // The cascade output. | ||||
| assign BCOUT = B_MULT; | ||||
| 
 | ||||
| // The B input multiplexer. | ||||
| wire signed [17:0] B_MUX; | ||||
| assign B_MUX = (B_INPUT == "DIRECT") ? B : BCIN; | ||||
| 
 | ||||
| // The registers. | ||||
| reg signed [17:0] A_REG; | ||||
| reg signed [17:0] B_REG; | ||||
| reg signed [35:0] P_REG; | ||||
| 
 | ||||
| initial begin | ||||
| 	A_REG = 0; | ||||
| 	B_REG = 0; | ||||
| 	P_REG = 0; | ||||
| end | ||||
| 
 | ||||
| always @(posedge CLK) begin | ||||
| 	if (RSTA) | ||||
| 		A_REG <= 0; | ||||
| 	else if (CEA) | ||||
| 		A_REG <= A; | ||||
| 
 | ||||
| 	if (RSTB) | ||||
| 		B_REG <= 0; | ||||
| 	else if (CEB) | ||||
| 		B_REG <= B_MUX; | ||||
| 
 | ||||
| 	if (RSTP) | ||||
| 		P_REG <= 0; | ||||
| 	else if (CEP) | ||||
| 		P_REG <= P_MULT; | ||||
| end | ||||
| 
 | ||||
| // The register enables. | ||||
| wire signed [17:0] A_MULT; | ||||
| wire signed [17:0] B_MULT; | ||||
| assign A_MULT = (AREG == 1) ? A_REG : A; | ||||
| assign B_MULT = (BREG == 1) ? B_REG : B_MUX; | ||||
| assign P = (PREG == 1) ? P_REG : P_MULT; | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // Spartan 3A DSP. | ||||
| 
 | ||||
| module DSP48A ( | ||||
|     input signed [17:0] A, | ||||
|     input signed [17:0] B, | ||||
|     input signed [47:0] C, | ||||
|     input signed [17:0] D, | ||||
|     input signed [47:0] PCIN, | ||||
|     input CARRYIN, | ||||
|     input [7:0] OPMODE, | ||||
|     output signed [47:0] P, | ||||
|     output signed [17:0] BCOUT, | ||||
|     output signed [47:0] PCOUT, | ||||
|     output CARRYOUT, | ||||
|     (* clkbuf_sink *) | ||||
|     input CLK, | ||||
|     input CEA, | ||||
|     input CEB, | ||||
|     input CEC, | ||||
|     input CED, | ||||
|     input CEM, | ||||
|     input CECARRYIN, | ||||
|     input CEOPMODE, | ||||
|     input CEP, | ||||
|     input RSTA, | ||||
|     input RSTB, | ||||
|     input RSTC, | ||||
|     input RSTD, | ||||
|     input RSTM, | ||||
|     input RSTCARRYIN, | ||||
|     input RSTOPMODE, | ||||
|     input RSTP | ||||
| ); | ||||
| 
 | ||||
| parameter integer A0REG = 0; | ||||
| parameter integer A1REG = 1; | ||||
| parameter integer B0REG = 0; | ||||
| parameter integer B1REG = 1; | ||||
| parameter integer CREG = 1; | ||||
| parameter integer DREG = 1; | ||||
| parameter integer MREG = 1; | ||||
| parameter integer CARRYINREG = 1; | ||||
| parameter integer OPMODEREG = 1; | ||||
| parameter integer PREG = 1; | ||||
| parameter CARRYINSEL = "CARRYIN"; | ||||
| parameter RSTTYPE = "SYNC"; | ||||
| 
 | ||||
| // This is a strict subset of Spartan 6 -- reuse its model. | ||||
| 
 | ||||
| DSP48A1 #( | ||||
| 	.A0REG(A0REG), | ||||
| 	.A1REG(A1REG), | ||||
| 	.B0REG(B0REG), | ||||
| 	.B1REG(B1REG), | ||||
| 	.CREG(CREG), | ||||
| 	.DREG(DREG), | ||||
| 	.MREG(MREG), | ||||
| 	.CARRYINREG(CARRYINREG), | ||||
| 	.CARRYOUTREG(0), | ||||
| 	.OPMODEREG(OPMODEREG), | ||||
| 	.PREG(PREG), | ||||
| 	.CARRYINSEL(CARRYINSEL), | ||||
| 	.RSTTYPE(RSTTYPE) | ||||
| ) upgrade ( | ||||
| 	.A(A), | ||||
| 	.B(B), | ||||
| 	.C(C), | ||||
| 	.D(D), | ||||
| 	.PCIN(PCIN), | ||||
| 	.CARRYIN(CARRYIN), | ||||
| 	.OPMODE(OPMODE), | ||||
| 	// M unconnected | ||||
| 	.P(P), | ||||
| 	.BCOUT(BCOUT), | ||||
| 	.PCOUT(PCOUT), | ||||
| 	.CARRYOUT(CARRYOUT), | ||||
| 	// CARRYOUTF unconnected | ||||
| 	.CLK(CLK), | ||||
| 	.CEA(CEA), | ||||
| 	.CEB(CEB), | ||||
| 	.CEC(CEC), | ||||
| 	.CED(CED), | ||||
| 	.CEM(CEM), | ||||
| 	.CECARRYIN(CECARRYIN), | ||||
| 	.CEOPMODE(CEOPMODE), | ||||
| 	.CEP(CEP), | ||||
| 	.RSTA(RSTA), | ||||
| 	.RSTB(RSTB), | ||||
| 	.RSTC(RSTC), | ||||
| 	.RSTD(RSTD), | ||||
| 	.RSTM(RSTM), | ||||
| 	.RSTCARRYIN(RSTCARRYIN), | ||||
| 	.RSTOPMODE(RSTOPMODE), | ||||
| 	.RSTP(RSTP) | ||||
| ); | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // Spartan 6. | ||||
| 
 | ||||
| module DSP48A1 ( | ||||
|     input signed [17:0] A, | ||||
|     input signed [17:0] B, | ||||
|     input signed [47:0] C, | ||||
|     input signed [17:0] D, | ||||
|     input signed [47:0] PCIN, | ||||
|     input CARRYIN, | ||||
|     input [7:0] OPMODE, | ||||
|     output signed [35:0] M, | ||||
|     output signed [47:0] P, | ||||
|     output signed [17:0] BCOUT, | ||||
|     output signed [47:0] PCOUT, | ||||
|     output CARRYOUT, | ||||
|     output CARRYOUTF, | ||||
|     (* clkbuf_sink *) | ||||
|     input CLK, | ||||
|     input CEA, | ||||
|     input CEB, | ||||
|     input CEC, | ||||
|     input CED, | ||||
|     input CEM, | ||||
|     input CECARRYIN, | ||||
|     input CEOPMODE, | ||||
|     input CEP, | ||||
|     input RSTA, | ||||
|     input RSTB, | ||||
|     input RSTC, | ||||
|     input RSTD, | ||||
|     input RSTM, | ||||
|     input RSTCARRYIN, | ||||
|     input RSTOPMODE, | ||||
|     input RSTP | ||||
| ); | ||||
| 
 | ||||
| parameter integer A0REG = 0; | ||||
| parameter integer A1REG = 1; | ||||
| parameter integer B0REG = 0; | ||||
| parameter integer B1REG = 1; | ||||
| parameter integer CREG = 1; | ||||
| parameter integer DREG = 1; | ||||
| parameter integer MREG = 1; | ||||
| parameter integer CARRYINREG = 1; | ||||
| parameter integer CARRYOUTREG = 1; | ||||
| parameter integer OPMODEREG = 1; | ||||
| parameter integer PREG = 1; | ||||
| parameter CARRYINSEL = "OPMODE5"; | ||||
| parameter RSTTYPE = "SYNC"; | ||||
| 
 | ||||
| wire signed [35:0] M_MULT; | ||||
| wire signed [47:0] P_IN; | ||||
| wire signed [17:0] A0_OUT; | ||||
| wire signed [17:0] B0_OUT; | ||||
| wire signed [17:0] A1_OUT; | ||||
| wire signed [17:0] B1_OUT; | ||||
| wire signed [17:0] B1_IN; | ||||
| wire signed [47:0] C_OUT; | ||||
| wire signed [17:0] D_OUT; | ||||
| wire signed [7:0] OPMODE_OUT; | ||||
| wire CARRYIN_OUT; | ||||
| wire CARRYOUT_IN; | ||||
| wire CARRYIN_IN; | ||||
| reg signed [47:0] XMUX; | ||||
| reg signed [47:0] ZMUX; | ||||
| 
 | ||||
| // The registers. | ||||
| reg signed [17:0] A0_REG; | ||||
| reg signed [17:0] A1_REG; | ||||
| reg signed [17:0] B0_REG; | ||||
| reg signed [17:0] B1_REG; | ||||
| reg signed [47:0] C_REG; | ||||
| reg signed [17:0] D_REG; | ||||
| reg signed [35:0] M_REG; | ||||
| reg signed [47:0] P_REG; | ||||
| reg [7:0] OPMODE_REG; | ||||
| reg CARRYIN_REG; | ||||
| reg CARRYOUT_REG; | ||||
| 
 | ||||
| initial begin | ||||
| 	A0_REG = 0; | ||||
| 	A1_REG = 0; | ||||
| 	B0_REG = 0; | ||||
| 	B1_REG = 0; | ||||
| 	C_REG = 0; | ||||
| 	D_REG = 0; | ||||
| 	M_REG = 0; | ||||
| 	P_REG = 0; | ||||
| 	OPMODE_REG = 0; | ||||
| 	CARRYIN_REG = 0; | ||||
| 	CARRYOUT_REG = 0; | ||||
| end | ||||
| 
 | ||||
| generate | ||||
| 
 | ||||
| if (RSTTYPE == "SYNC") begin | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTA) begin | ||||
| 			A0_REG <= 0; | ||||
| 			A1_REG <= 0; | ||||
| 		end else if (CEA) begin | ||||
| 			A0_REG <= A; | ||||
| 			A1_REG <= A0_OUT; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTB) begin | ||||
| 			B0_REG <= 0; | ||||
| 			B1_REG <= 0; | ||||
| 		end else if (CEB) begin | ||||
| 			B0_REG <= B; | ||||
| 			B1_REG <= B1_IN; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTC) begin | ||||
| 			C_REG <= 0; | ||||
| 		end else if (CEC) begin | ||||
| 			C_REG <= C; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTD) begin | ||||
| 			D_REG <= 0; | ||||
| 		end else if (CED) begin | ||||
| 			D_REG <= D; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTM) begin | ||||
| 			M_REG <= 0; | ||||
| 		end else if (CEM) begin | ||||
| 			M_REG <= M_MULT; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTP) begin | ||||
| 			P_REG <= 0; | ||||
| 		end else if (CEP) begin | ||||
| 			P_REG <= P_IN; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTOPMODE) begin | ||||
| 			OPMODE_REG <= 0; | ||||
| 		end else if (CEOPMODE) begin | ||||
| 			OPMODE_REG <= OPMODE; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK) begin | ||||
| 		if (RSTCARRYIN) begin | ||||
| 			CARRYIN_REG <= 0; | ||||
| 			CARRYOUT_REG <= 0; | ||||
| 		end else if (CECARRYIN) begin | ||||
| 			CARRYIN_REG <= CARRYIN_IN; | ||||
| 			CARRYOUT_REG <= CARRYOUT_IN; | ||||
| 		end | ||||
| 	end | ||||
| end else begin | ||||
| 	always @(posedge CLK, posedge RSTA) begin | ||||
| 		if (RSTA) begin | ||||
| 			A0_REG <= 0; | ||||
| 			A1_REG <= 0; | ||||
| 		end else if (CEA) begin | ||||
| 			A0_REG <= A; | ||||
| 			A1_REG <= A0_OUT; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK, posedge RSTB) begin | ||||
| 		if (RSTB) begin | ||||
| 			B0_REG <= 0; | ||||
| 			B1_REG <= 0; | ||||
| 		end else if (CEB) begin | ||||
| 			B0_REG <= B; | ||||
| 			B1_REG <= B1_IN; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK, posedge RSTC) begin | ||||
| 		if (RSTC) begin | ||||
| 			C_REG <= 0; | ||||
| 		end else if (CEC) begin | ||||
| 			C_REG <= C; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK, posedge RSTD) begin | ||||
| 		if (RSTD) begin | ||||
| 			D_REG <= 0; | ||||
| 		end else if (CED) begin | ||||
| 			D_REG <= D; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK, posedge RSTM) begin | ||||
| 		if (RSTM) begin | ||||
| 			M_REG <= 0; | ||||
| 		end else if (CEM) begin | ||||
| 			M_REG <= M_MULT; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK, posedge RSTP) begin | ||||
| 		if (RSTP) begin | ||||
| 			P_REG <= 0; | ||||
| 		end else if (CEP) begin | ||||
| 			P_REG <= P_IN; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK, posedge RSTOPMODE) begin | ||||
| 		if (RSTOPMODE) begin | ||||
| 			OPMODE_REG <= 0; | ||||
| 		end else if (CEOPMODE) begin | ||||
| 			OPMODE_REG <= OPMODE; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	always @(posedge CLK, posedge RSTCARRYIN) begin | ||||
| 		if (RSTCARRYIN) begin | ||||
| 			CARRYIN_REG <= 0; | ||||
| 			CARRYOUT_REG <= 0; | ||||
| 		end else if (CECARRYIN) begin | ||||
| 			CARRYIN_REG <= CARRYIN_IN; | ||||
| 			CARRYOUT_REG <= CARRYOUT_IN; | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| endgenerate | ||||
| 
 | ||||
| // The register enables. | ||||
| assign A0_OUT = (A0REG == 1) ? A0_REG : A; | ||||
| assign A1_OUT = (A1REG == 1) ? A1_REG : A0_OUT; | ||||
| assign B0_OUT = (B0REG == 1) ? B0_REG : B; | ||||
| assign B1_OUT = (B1REG == 1) ? B1_REG : B1_IN; | ||||
| assign C_OUT = (CREG == 1) ? C_REG : C; | ||||
| assign D_OUT = (DREG == 1) ? D_REG : D; | ||||
| assign M = (MREG == 1) ? M_REG : M_MULT; | ||||
| assign P = (PREG == 1) ? P_REG : P_IN; | ||||
| assign OPMODE_OUT = (OPMODEREG == 1) ? OPMODE_REG : OPMODE; | ||||
| assign CARRYIN_OUT = (CARRYINREG == 1) ? CARRYIN_REG : CARRYIN_IN; | ||||
| assign CARRYOUT = (CARRYOUTREG == 1) ? CARRYOUT_REG : CARRYOUT_IN; | ||||
| assign CARRYOUTF = CARRYOUT; | ||||
| 
 | ||||
| // The pre-adder. | ||||
| wire signed [17:0] PREADDER; | ||||
| assign B1_IN = OPMODE_OUT[4] ? PREADDER : B0_OUT; | ||||
| assign PREADDER = OPMODE_OUT[6] ? D_OUT - B0_OUT : D_OUT + B0_OUT; | ||||
| 
 | ||||
| // The multiplier. | ||||
| assign M_MULT = A1_OUT * B1_OUT; | ||||
| 
 | ||||
| // The carry in selection. | ||||
| assign CARRYIN_IN = (CARRYINSEL == "OPMODE5") ? OPMODE_OUT[5] : CARRYIN; | ||||
| 
 | ||||
| // The post-adder inputs. | ||||
| always @* begin | ||||
| 	case (OPMODE_OUT[1:0]) | ||||
| 		2'b00: XMUX <= 0; | ||||
| 		2'b01: XMUX <= M; | ||||
| 		2'b10: XMUX <= P; | ||||
| 		2'b11: XMUX <= {D_OUT[11:0], B1_OUT, A1_OUT}; | ||||
| 		default: XMUX <= 48'hxxxxxxxxxxxx; | ||||
| 	endcase | ||||
| end | ||||
| 
 | ||||
| always @* begin | ||||
| 	case (OPMODE_OUT[3:2]) | ||||
| 		2'b00: ZMUX <= 0; | ||||
| 		2'b01: ZMUX <= PCIN; | ||||
| 		2'b10: ZMUX <= P; | ||||
| 		2'b11: ZMUX <= C_OUT; | ||||
| 		default: ZMUX <= 48'hxxxxxxxxxxxx; | ||||
| 	endcase | ||||
| end | ||||
| 
 | ||||
| // The post-adder. | ||||
| wire signed [48:0] X_EXT; | ||||
| wire signed [48:0] Z_EXT; | ||||
| assign X_EXT = XMUX; | ||||
| assign Z_EXT = ZMUX; | ||||
| assign {CARRYOUT_IN, P_IN} = OPMODE_OUT[7] ? (Z_EXT - (X_EXT + CARRYIN_OUT)) : (Z_EXT + X_EXT + CARRYIN_OUT); | ||||
| 
 | ||||
| // Cascade outputs. | ||||
| assign BCOUT = B1_OUT; | ||||
| assign PCOUT = P; | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // TODO: DSP48 (Virtex 4). | ||||
| 
 | ||||
| // TODO: DSP48E (Virtex 5). | ||||
| 
 | ||||
| // Virtex 6, Series 7. | ||||
| 
 | ||||
| module DSP48E1 ( | ||||
|     output [29:0] ACOUT, | ||||
|     output [17:0] BCOUT, | ||||
|  | @ -1040,3 +1560,5 @@ module DSP48E1 ( | |||
|     endgenerate | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // TODO: DSP48E2 (Ultrascale). | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										29212
									
								
								techlibs/xilinx/cells_xtra.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29212
									
								
								techlibs/xilinx/cells_xtra.v
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -46,7 +46,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 		log("    -top <module>\n"); | ||||
| 		log("        use the specified module as top module\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -family {xcup|xcu|xc7|xc6v|xc6s}\n"); | ||||
| 		log("    -family {xcup|xcu|xc7|xc6v|xc5v|xc6s}\n"); | ||||
| 		log("        run synthesis for the specified Xilinx architecture\n"); | ||||
| 		log("        generate the synthesis netlist for the specified family.\n"); | ||||
| 		log("        default: xc7\n"); | ||||
|  | @ -93,6 +93,9 @@ struct SynthXilinxPass : public ScriptPass | |||
| 		log("    -noclkbuf\n"); | ||||
| 		log("        disable automatic clock buffer insertion\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -uram\n"); | ||||
| 		log("        infer URAM288s for large memories (xcup only)\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -widemux <int>\n"); | ||||
| 		log("        enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n"); | ||||
| 		log("        above this number of inputs (minimum value 2, recommended value >= 5).\n"); | ||||
|  | @ -119,7 +122,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 	} | ||||
| 
 | ||||
| 	std::string top_opt, edif_file, blif_file, family; | ||||
| 	bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9; | ||||
| 	bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9; | ||||
| 	bool flatten_before_abc; | ||||
| 	int widemux; | ||||
| 
 | ||||
|  | @ -143,6 +146,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 		nocarry = false; | ||||
| 		nowidelut = false; | ||||
| 		nodsp = false; | ||||
| 		uram = false; | ||||
| 		abc9 = false; | ||||
| 		flatten_before_abc = false; | ||||
| 		widemux = 0; | ||||
|  | @ -248,11 +252,15 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				nodsp = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-uram") { | ||||
| 				uram = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6v" && family != "xc6s") | ||||
| 		if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6v" && family != "xc5v" && family != "xc6s") | ||||
| 			log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str()); | ||||
| 
 | ||||
| 		if (widemux != 0 && widemux < 2) | ||||
|  | @ -289,24 +297,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 			read_args += " -lib +/xilinx/cells_sim.v"; | ||||
| 			run("read_verilog" + read_args); | ||||
| 
 | ||||
| 			if (help_mode) | ||||
| 				run("read_verilog -lib +/xilinx/{family}_cells_xtra.v"); | ||||
| 			else if (family == "xc6s") | ||||
| 				run("read_verilog -lib +/xilinx/xc6s_cells_xtra.v"); | ||||
| 			else if (family == "xc6v") | ||||
| 				run("read_verilog -lib +/xilinx/xc6v_cells_xtra.v"); | ||||
| 			else if (family == "xc7") | ||||
| 				run("read_verilog -lib +/xilinx/xc7_cells_xtra.v"); | ||||
| 			else if (family == "xcu" || family == "xcup") | ||||
| 				run("read_verilog -lib +/xilinx/xcu_cells_xtra.v"); | ||||
| 
 | ||||
| 			if (help_mode) { | ||||
| 				run("read_verilog -lib +/xilinx/{family}_brams_bb.v"); | ||||
| 			} else if (family == "xc6s") { | ||||
| 				run("read_verilog -lib +/xilinx/xc6s_brams_bb.v"); | ||||
| 			} else if (family == "xc6v" || family == "xc7") { | ||||
| 				run("read_verilog -lib +/xilinx/xc7_brams_bb.v"); | ||||
| 			} | ||||
| 			run("read_verilog -lib +/xilinx/cells_xtra.v"); | ||||
| 
 | ||||
| 			run(stringf("hierarchy -check %s", top_opt.c_str())); | ||||
| 		} | ||||
|  | @ -342,15 +333,53 @@ struct SynthXilinxPass : public ScriptPass | |||
| 
 | ||||
| 		if (check_label("map_dsp", "(skip if '-nodsp')")) { | ||||
| 			if (!nodsp || help_mode) { | ||||
| 				run("memory_dff"); // xilinx_dsp will merge registers, reserve memory port registers first
 | ||||
| 				// NB: Xilinx multipliers are signed only
 | ||||
| 				run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 " | ||||
| 					"-D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 "    // Partial multipliers are intentionally
 | ||||
| 				if (help_mode) | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options}"); | ||||
| 				else if (family == "xc2v" || family == "xc3s" || family == "xc3se" || family == "xc3sa") | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/xc3s_mult_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
 | ||||
| 						"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
 | ||||
| 						"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); | ||||
| 				else if (family == "xc3sda") | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/xc3sda_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
 | ||||
| 						"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
 | ||||
| 						"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); | ||||
| 				else if (family == "xc6s") | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/xc6s_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
 | ||||
| 						"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
 | ||||
| 						"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); | ||||
| 				else if (family == "xc4v") | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/xc4v_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
 | ||||
| 						"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
 | ||||
| 						"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); | ||||
| 				else if (family == "xc5v") | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/xc5v_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 " | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
 | ||||
| 						"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
 | ||||
| 						"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); | ||||
| 				else if (family == "xc6v" || family == "xc7") | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/xc7_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 " | ||||
| 						"-D DSP_A_MAXWIDTH_PARTIAL=18 "	// Partial multipliers are intentionally
 | ||||
| 										// limited to 18x18 in order to take
 | ||||
| 										// advantage of the (PCOUT << 17) -> PCIN
 | ||||
| 										// dedicated cascade chain capability
 | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
 | ||||
| 						"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
 | ||||
| 						"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); | ||||
| 				else if (family == "xcu" || family == "xcup") | ||||
| 					run("techmap -map +/mul2dsp.v -map +/xilinx/xcu_dsp_map.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=18 " | ||||
| 						"-D DSP_A_MAXWIDTH_PARTIAL=18 "	// Partial multipliers are intentionally
 | ||||
| 										// limited to 18x18 in order to take
 | ||||
| 										// advantage of the (PCOUT << 17) -> PCIN
 | ||||
| 										// dedicated cascade chain capability
 | ||||
| 						"-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
 | ||||
| 						"-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
 | ||||
| 						"-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL27X18"); | ||||
| 				run("select a:mul2dsp"); | ||||
| 				run("setattr -unset mul2dsp"); | ||||
| 				run("opt_expr -fine"); | ||||
|  | @ -371,6 +400,20 @@ struct SynthXilinxPass : public ScriptPass | |||
| 			run("opt_clean"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_uram", "(only if '-uram')")) { | ||||
| 			if (help_mode) { | ||||
| 				run("memory_bram -rules +/xilinx/{family}_urams.txt"); | ||||
| 				run("techmap -map +/xilinx/{family}_urams_map.v"); | ||||
| 			} else if (uram) { | ||||
| 				if (family == "xcup") { | ||||
| 					run("memory_bram -rules +/xilinx/xcup_urams.txt"); | ||||
| 					run("techmap -map +/xilinx/xcup_urams_map.v"); | ||||
| 				} else { | ||||
| 					log_warning("UltraRAM inference not supported for family %s.\n", family.c_str()); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_bram", "(skip if '-nobram')")) { | ||||
| 			if (help_mode) { | ||||
| 				run("memory_bram -rules +/xilinx/{family}_brams.txt"); | ||||
|  | @ -380,8 +423,11 @@ struct SynthXilinxPass : public ScriptPass | |||
| 					run("memory_bram -rules +/xilinx/xc6s_brams.txt"); | ||||
| 					run("techmap -map +/xilinx/xc6s_brams_map.v"); | ||||
| 				} else if (family == "xc6v" || family == "xc7") { | ||||
| 					run("memory_bram -rules +/xilinx/xc7_brams.txt"); | ||||
| 					run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt"); | ||||
| 					run("techmap -map +/xilinx/xc7_brams_map.v"); | ||||
| 				} else if (family == "xcu" || family == "xcup") { | ||||
| 					run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt"); | ||||
| 					run("techmap -map +/xilinx/xcu_brams_map.v");					 | ||||
| 				} else { | ||||
| 					log_warning("Block RAM inference not yet supported for family %s.\n", family.c_str()); | ||||
| 				} | ||||
|  |  | |||
							
								
								
									
										14
									
								
								techlibs/xilinx/xc3s_mult_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								techlibs/xilinx/xc3s_mult_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 	parameter A_WIDTH = 0; | ||||
| 	parameter B_WIDTH = 0; | ||||
| 	parameter Y_WIDTH = 0; | ||||
| 
 | ||||
| 	MULT18X18 _TECHMAP_REPLACE_ ( | ||||
| 		.A(A), | ||||
| 		.B(B), | ||||
| 		.P(Y) | ||||
| 	); | ||||
| endmodule | ||||
| 
 | ||||
							
								
								
									
										34
									
								
								techlibs/xilinx/xc3sda_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								techlibs/xilinx/xc3sda_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 	parameter A_WIDTH = 0; | ||||
| 	parameter B_WIDTH = 0; | ||||
| 	parameter Y_WIDTH = 0; | ||||
| 
 | ||||
| 	wire [47:0] P_48; | ||||
| 	DSP48A #( | ||||
| 		// Disable all registers | ||||
| 		.A0REG(0), | ||||
| 		.A1REG(0), | ||||
| 		.B0REG(0), | ||||
| 		.B1REG(0), | ||||
| 		.CARRYINREG(0), | ||||
| 		.CARRYINSEL("OPMODE5"), | ||||
| 		.CREG(0), | ||||
| 		.DREG(0), | ||||
| 		.MREG(0), | ||||
| 		.OPMODEREG(0), | ||||
| 		.PREG(0) | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		//Data path | ||||
| 		.A(A), | ||||
| 		.B(B), | ||||
| 		.C(48'b0), | ||||
| 		.D(18'b0), | ||||
| 		.P(P_48), | ||||
| 
 | ||||
| 		.OPMODE(8'b0000010) | ||||
| 	); | ||||
| 	assign Y = P_48; | ||||
| endmodule | ||||
| 
 | ||||
							
								
								
									
										38
									
								
								techlibs/xilinx/xc4v_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								techlibs/xilinx/xc4v_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 	parameter A_WIDTH = 0; | ||||
| 	parameter B_WIDTH = 0; | ||||
| 	parameter Y_WIDTH = 0; | ||||
| 
 | ||||
| 	wire [47:0] P_48; | ||||
| 	DSP48 #( | ||||
| 		// Disable all registers | ||||
| 		.AREG(0), | ||||
| 		.BREG(0), | ||||
| 		.B_INPUT("DIRECT"), | ||||
| 		.CARRYINREG(0), | ||||
| 		.CARRYINSELREG(0), | ||||
| 		.CREG(0), | ||||
| 		.MREG(0), | ||||
| 		.OPMODEREG(0), | ||||
| 		.PREG(0), | ||||
| 		.SUBTRACTREG(0), | ||||
| 		.LEGACY_MODE("MULT18X18") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		//Data path | ||||
| 		.A(A), | ||||
| 		.B(B), | ||||
| 		.C(48'b0), | ||||
| 		.P(P_48), | ||||
| 
 | ||||
| 		.SUBTRACT(1'b0), | ||||
| 		.OPMODE(7'b000101), | ||||
| 		.CARRYINSEL(2'b00), | ||||
| 
 | ||||
| 		.BCIN(18'b0), | ||||
| 		.PCIN(48'b0), | ||||
| 		.CARRYIN(1'b0) | ||||
| 	); | ||||
| 	assign Y = P_48; | ||||
| endmodule | ||||
							
								
								
									
										45
									
								
								techlibs/xilinx/xc5v_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								techlibs/xilinx/xc5v_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 	parameter A_WIDTH = 0; | ||||
| 	parameter B_WIDTH = 0; | ||||
| 	parameter Y_WIDTH = 0; | ||||
| 
 | ||||
| 	wire [47:0] P_48; | ||||
| 	DSP48E #( | ||||
| 		// Disable all registers | ||||
| 		.ACASCREG(0), | ||||
| 		.A_INPUT("DIRECT"), | ||||
| 		.ALUMODEREG(0), | ||||
| 		.AREG(0), | ||||
| 		.BCASCREG(0), | ||||
| 		.B_INPUT("DIRECT"), | ||||
| 		.BREG(0), | ||||
| 		.MULTCARRYINREG(0), | ||||
| 		.CARRYINREG(0), | ||||
| 		.CARRYINSELREG(0), | ||||
| 		.CREG(0), | ||||
| 		.MREG(0), | ||||
| 		.OPMODEREG(0), | ||||
| 		.PREG(0), | ||||
| 		.USE_MULT("MULT"), | ||||
| 		.USE_SIMD("ONE48") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		//Data path | ||||
| 		.A({{5{A[24]}}, A}), | ||||
| 		.B(B), | ||||
| 		.C(48'b0), | ||||
| 		.P(P_48), | ||||
| 
 | ||||
| 		.ALUMODE(4'b0000), | ||||
| 		.OPMODE(7'b000101), | ||||
| 		.CARRYINSEL(3'b000), | ||||
| 
 | ||||
| 		.ACIN(30'b0), | ||||
| 		.BCIN(18'b0), | ||||
| 		.PCIN(48'b0), | ||||
| 		.CARRYIN(1'b0) | ||||
| 	); | ||||
| 	assign Y = P_48; | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -1,223 +0,0 @@ | |||
| module RAMB8BWER ( | ||||
| 	(* clkbuf_sink *) | ||||
| 	input CLKAWRCLK, | ||||
| 	(* clkbuf_sink *) | ||||
| 	input CLKBRDCLK, | ||||
| 	input ENAWREN, | ||||
| 	input ENBRDEN, | ||||
| 	input REGCEA, | ||||
| 	input REGCEBREGCE, | ||||
| 	input RSTA, | ||||
| 	input RSTBRST, | ||||
| 
 | ||||
| 	input [12:0] ADDRAWRADDR, | ||||
| 	input [12:0] ADDRBRDADDR, | ||||
| 	input [15:0] DIADI, | ||||
| 	input [15:0] DIBDI, | ||||
| 	input [1:0] DIPADIP, | ||||
| 	input [1:0] DIPBDIP, | ||||
| 	input [1:0] WEAWEL, | ||||
| 	input [1:0] WEBWEU, | ||||
| 
 | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [15:0] DOADO, | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [15:0] DOBDO, | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [1:0] DOPADOP, | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [1:0] DOPBDOP | ||||
| ); | ||||
| 	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter RAM_MODE = "TDP"; | ||||
| 	parameter integer DOA_REG = 0; | ||||
| 	parameter integer DOB_REG = 0; | ||||
| 
 | ||||
| 	parameter integer DATA_WIDTH_A = 0; | ||||
| 	parameter integer DATA_WIDTH_B = 0; | ||||
| 
 | ||||
| 	parameter WRITE_MODE_A = "WRITE_FIRST"; | ||||
| 	parameter WRITE_MODE_B = "WRITE_FIRST"; | ||||
| 
 | ||||
| 	parameter EN_RSTRAM_A = "TRUE"; | ||||
| 	parameter EN_RSTRAM_B = "TRUE"; | ||||
| 
 | ||||
| 	parameter INIT_A = 18'h000000000; | ||||
| 	parameter INIT_B = 18'h000000000; | ||||
| 	parameter SRVAL_A = 18'h000000000; | ||||
| 	parameter SRVAL_B = 18'h000000000; | ||||
| 
 | ||||
| 	parameter RST_PRIORITY_A = "CE"; | ||||
| 	parameter RST_PRIORITY_B = "CE"; | ||||
| 
 | ||||
| 	parameter RSTTYPE = "SYNC"; | ||||
| 
 | ||||
| 	parameter SIM_COLLISION_CHECK = "ALL"; | ||||
| endmodule | ||||
| 
 | ||||
| module RAMB16BWER ( | ||||
| 	(* clkbuf_sink *) | ||||
| 	input CLKA, | ||||
| 	(* clkbuf_sink *) | ||||
| 	input CLKB, | ||||
| 	input ENA, | ||||
| 	input ENB, | ||||
| 	input REGCEA, | ||||
| 	input REGCEB, | ||||
| 	input RSTA, | ||||
| 	input RSTB, | ||||
| 
 | ||||
| 	input [13:0] ADDRA, | ||||
| 	input [13:0] ADDRB, | ||||
| 	input [31:0] DIA, | ||||
| 	input [31:0] DIB, | ||||
| 	input [3:0] DIPA, | ||||
| 	input [3:0] DIPB, | ||||
| 	input [3:0] WEA, | ||||
| 	input [3:0] WEB, | ||||
| 
 | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [31:0] DOA, | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [31:0] DOB, | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [3:0] DOPA, | ||||
| 	/* (* abc9_arrival=<TODO> *) */ | ||||
| 	output [3:0] DOPB | ||||
| ); | ||||
| 	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter integer DOA_REG = 0; | ||||
| 	parameter integer DOB_REG = 0; | ||||
| 
 | ||||
| 	parameter integer DATA_WIDTH_A = 0; | ||||
| 	parameter integer DATA_WIDTH_B = 0; | ||||
| 
 | ||||
| 	parameter WRITE_MODE_A = "WRITE_FIRST"; | ||||
| 	parameter WRITE_MODE_B = "WRITE_FIRST"; | ||||
| 
 | ||||
| 	parameter EN_RSTRAM_A = "TRUE"; | ||||
| 	parameter EN_RSTRAM_B = "TRUE"; | ||||
| 
 | ||||
| 	parameter INIT_A = 36'h000000000; | ||||
| 	parameter INIT_B = 36'h000000000; | ||||
| 	parameter SRVAL_A = 36'h000000000; | ||||
| 	parameter SRVAL_B = 36'h000000000; | ||||
| 
 | ||||
| 	parameter RST_PRIORITY_A = "CE"; | ||||
| 	parameter RST_PRIORITY_B = "CE"; | ||||
| 
 | ||||
| 	parameter RSTTYPE = "SYNC"; | ||||
| 
 | ||||
| 	parameter SIM_COLLISION_CHECK = "ALL"; | ||||
| endmodule | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										35
									
								
								techlibs/xilinx/xc6s_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								techlibs/xilinx/xc6s_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 	parameter A_WIDTH = 0; | ||||
| 	parameter B_WIDTH = 0; | ||||
| 	parameter Y_WIDTH = 0; | ||||
| 
 | ||||
| 	wire [47:0] P_48; | ||||
| 	DSP48A1 #( | ||||
| 		// Disable all registers | ||||
| 		.A0REG(0), | ||||
| 		.A1REG(0), | ||||
| 		.B0REG(0), | ||||
| 		.B1REG(0), | ||||
| 		.CARRYINREG(0), | ||||
| 		.CARRYINSEL("OPMODE5"), | ||||
| 		.CREG(0), | ||||
| 		.DREG(0), | ||||
| 		.MREG(0), | ||||
| 		.OPMODEREG(0), | ||||
| 		.PREG(0) | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		//Data path | ||||
| 		.A(A), | ||||
| 		.B(B), | ||||
| 		.C(48'b0), | ||||
| 		.D(18'b0), | ||||
| 		.P(P_48), | ||||
| 
 | ||||
| 		.OPMODE(8'b0000010) | ||||
| 	); | ||||
| 	assign Y = P_48; | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,349 +0,0 @@ | |||
| // Max delays from https://github.com/SymbiFlow/prjxray-db/blob/f8e0364116b2983ac72a3dc8c509ea1cc79e2e3d/artix7/timings/BRAM_L.sdf#L138-L147 | ||||
| 
 | ||||
| module RAMB18E1 ( | ||||
| 	(* clkbuf_sink *) | ||||
| 	(* invertible_pin = "IS_CLKARDCLK_INVERTED" *) | ||||
| 	input CLKARDCLK, | ||||
| 	(* clkbuf_sink *) | ||||
| 	(* invertible_pin = "IS_CLKBWRCLK_INVERTED" *) | ||||
| 	input CLKBWRCLK, | ||||
| 	(* invertible_pin = "IS_ENARDEN_INVERTED" *) | ||||
| 	input ENARDEN, | ||||
| 	(* invertible_pin = "IS_ENBWREN_INVERTED" *) | ||||
| 	input ENBWREN, | ||||
| 	input REGCEAREGCE, | ||||
| 	input REGCEB, | ||||
| 	(* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *) | ||||
| 	input RSTRAMARSTRAM, | ||||
| 	(* invertible_pin = "IS_RSTRAMB_INVERTED" *) | ||||
| 	input RSTRAMB, | ||||
| 	(* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *) | ||||
| 	input RSTREGARSTREG, | ||||
| 	(* invertible_pin = "IS_RSTREGB_INVERTED" *) | ||||
| 	input RSTREGB, | ||||
| 
 | ||||
| 	input [13:0] ADDRARDADDR, | ||||
| 	input [13:0] ADDRBWRADDR, | ||||
| 	input [15:0] DIADI, | ||||
| 	input [15:0] DIBDI, | ||||
| 	input [1:0] DIPADIP, | ||||
| 	input [1:0] DIPBDIP, | ||||
| 	input [1:0] WEA, | ||||
| 	input [3:0] WEBWE, | ||||
| 
 | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [15:0] DOADO, | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [15:0] DOBDO, | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [1:0] DOPADOP, | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [1:0] DOPBDOP | ||||
| ); | ||||
| 	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter IS_CLKARDCLK_INVERTED = 1'b0; | ||||
| 	parameter IS_CLKBWRCLK_INVERTED = 1'b0; | ||||
| 	parameter IS_ENARDEN_INVERTED = 1'b0; | ||||
| 	parameter IS_ENBWREN_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTRAMB_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTREGARSTREG_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTREGB_INVERTED = 1'b0; | ||||
| 
 | ||||
| 	parameter RAM_MODE = "TDP"; | ||||
| 	parameter integer DOA_REG = 0; | ||||
| 	parameter integer DOB_REG = 0; | ||||
| 
 | ||||
| 	parameter integer READ_WIDTH_A = 0; | ||||
| 	parameter integer READ_WIDTH_B = 0; | ||||
| 	parameter integer WRITE_WIDTH_A = 0; | ||||
| 	parameter integer WRITE_WIDTH_B = 0; | ||||
| 
 | ||||
| 	parameter WRITE_MODE_A = "WRITE_FIRST"; | ||||
| 	parameter WRITE_MODE_B = "WRITE_FIRST"; | ||||
| 
 | ||||
| 	parameter SIM_DEVICE = "VIRTEX6"; | ||||
| endmodule | ||||
| 
 | ||||
| module RAMB36E1 ( | ||||
| 	(* clkbuf_sink *) | ||||
| 	(* invertible_pin = "IS_CLKARDCLK_INVERTED" *) | ||||
| 	input CLKARDCLK, | ||||
| 	(* clkbuf_sink *) | ||||
| 	(* invertible_pin = "IS_CLKBWRCLK_INVERTED" *) | ||||
| 	input CLKBWRCLK, | ||||
| 	(* invertible_pin = "IS_ENARDEN_INVERTED" *) | ||||
| 	input ENARDEN, | ||||
| 	(* invertible_pin = "IS_ENBWREN_INVERTED" *) | ||||
| 	input ENBWREN, | ||||
| 	input REGCEAREGCE, | ||||
| 	input REGCEB, | ||||
| 	(* invertible_pin = "IS_RSTRAMARSTRAM_INVERTED" *) | ||||
| 	input RSTRAMARSTRAM, | ||||
| 	(* invertible_pin = "IS_RSTRAMB_INVERTED" *) | ||||
| 	input RSTRAMB, | ||||
| 	(* invertible_pin = "IS_RSTREGARSTREG_INVERTED" *) | ||||
| 	input RSTREGARSTREG, | ||||
| 	(* invertible_pin = "IS_RSTREGB_INVERTED" *) | ||||
| 	input RSTREGB, | ||||
| 
 | ||||
| 	input [15:0] ADDRARDADDR, | ||||
| 	input [15:0] ADDRBWRADDR, | ||||
| 	input [31:0] DIADI, | ||||
| 	input [31:0] DIBDI, | ||||
| 	input [3:0] DIPADIP, | ||||
| 	input [3:0] DIPBDIP, | ||||
| 	input [3:0] WEA, | ||||
| 	input [7:0] WEBWE, | ||||
| 
 | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [31:0] DOADO, | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [31:0] DOBDO, | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [3:0] DOPADOP, | ||||
| 	(* abc9_arrival=2454 *) | ||||
| 	output [3:0] DOPBDOP | ||||
| ); | ||||
| 	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INITP_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_40 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_41 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_42 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_43 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_44 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_45 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_46 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_47 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_48 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_49 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_4A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_4B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_4C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_4D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_4E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_4F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_50 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_51 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_52 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_53 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_54 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_55 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_56 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_57 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_58 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_59 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_5A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_5B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_5C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_5D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_5E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_5F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_60 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_61 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_62 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_63 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_64 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_65 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_66 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_67 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_68 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_69 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_6A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_6B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_6C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_6D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_6E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_6F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_70 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_71 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_72 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_73 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_74 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_75 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_76 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_77 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_78 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_79 = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_7A = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_7B = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_7C = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_7D = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_7E = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 	parameter INIT_7F = 256'h0000000000000000000000000000000000000000000000000000000000000000; | ||||
| 
 | ||||
| 	parameter IS_CLKARDCLK_INVERTED = 1'b0; | ||||
| 	parameter IS_CLKBWRCLK_INVERTED = 1'b0; | ||||
| 	parameter IS_ENARDEN_INVERTED = 1'b0; | ||||
| 	parameter IS_ENBWREN_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTRAMB_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTREGARSTREG_INVERTED = 1'b0; | ||||
| 	parameter IS_RSTREGB_INVERTED = 1'b0; | ||||
| 
 | ||||
| 	parameter RAM_MODE = "TDP"; | ||||
| 	parameter integer DOA_REG = 0; | ||||
| 	parameter integer DOB_REG = 0; | ||||
| 
 | ||||
| 	parameter integer READ_WIDTH_A = 0; | ||||
| 	parameter integer READ_WIDTH_B = 0; | ||||
| 	parameter integer WRITE_WIDTH_A = 0; | ||||
| 	parameter integer WRITE_WIDTH_B = 0; | ||||
| 
 | ||||
| 	parameter WRITE_MODE_A = "WRITE_FIRST"; | ||||
| 	parameter WRITE_MODE_B = "WRITE_FIRST"; | ||||
| 
 | ||||
| 	parameter SIM_DEVICE = "VIRTEX6"; | ||||
| endmodule | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										384
									
								
								techlibs/xilinx/xcu_brams_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								techlibs/xilinx/xcu_brams_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,384 @@ | |||
| module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | ||||
| 	parameter CLKPOL2 = 1; | ||||
| 	parameter CLKPOL3 = 1; | ||||
| 	parameter [36863:0] INIT = 36864'bx; | ||||
| 
 | ||||
| 	input CLK2; | ||||
| 	input CLK3; | ||||
| 
 | ||||
| 	input [8:0] A1ADDR; | ||||
| 	output [71:0] A1DATA; | ||||
| 	input A1EN; | ||||
| 
 | ||||
| 	input [8:0] B1ADDR; | ||||
| 	input [71:0] B1DATA; | ||||
| 	input [7:0] B1EN; | ||||
| 
 | ||||
| 	wire [15:0] A1ADDR_16 = {A1ADDR, 6'b0}; | ||||
| 	wire [15:0] B1ADDR_16 = {B1ADDR, 6'b0}; | ||||
| 
 | ||||
| 	wire [7:0] DIP, DOP; | ||||
| 	wire [63:0] DI, DO; | ||||
| 
 | ||||
| 	assign A1DATA = { DOP[7], DO[63:56], DOP[6], DO[55:48], DOP[5], DO[47:40], DOP[4], DO[39:32], | ||||
| 	                  DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; | ||||
| 
 | ||||
| 	assign { DIP[7], DI[63:56], DIP[6], DI[55:48], DIP[5], DI[47:40], DIP[4], DI[39:32], | ||||
| 	         DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; | ||||
| 
 | ||||
| 	RAMB36E2 #( | ||||
| 		.READ_WIDTH_A(72), | ||||
| 		.WRITE_WIDTH_B(72), | ||||
| 		.WRITE_MODE_A("READ_FIRST"), | ||||
| 		.WRITE_MODE_B("READ_FIRST"), | ||||
| 		.DOA_REG(0), | ||||
| 		.DOB_REG(0), | ||||
| 		.IS_CLKARDCLK_INVERTED(!CLKPOL2), | ||||
| 		.IS_CLKBWRCLK_INVERTED(!CLKPOL3), | ||||
| 		`include "brams_init_36.vh" | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		.DOUTBDOUT(DO[63:32]), | ||||
| 		.DOUTADOUT(DO[31:0]), | ||||
| 		.DOUTPBDOUTP(DOP[7:4]), | ||||
| 		.DOUTPADOUTP(DOP[3:0]), | ||||
| 		.DINBDIN(DI[63:32]), | ||||
| 		.DINADIN(DI[31:0]), | ||||
| 		.DINPBDINP(DIP[7:4]), | ||||
| 		.DINPADINP(DIP[3:0]), | ||||
| 
 | ||||
| 		.ADDRARDADDR(A1ADDR_16), | ||||
| 		.CLKARDCLK(CLK2), | ||||
| 		.ENARDEN(A1EN), | ||||
| 		.ADDRENA(|1), | ||||
| 		.REGCEAREGCE(|1), | ||||
| 		.RSTRAMARSTRAM(|0), | ||||
| 		.RSTREGARSTREG(|0), | ||||
| 		.WEA(4'b0), | ||||
| 
 | ||||
| 		.ADDRBWRADDR(B1ADDR_16), | ||||
| 		.CLKBWRCLK(CLK3), | ||||
| 		.ENBWREN(|1), | ||||
| 		.ADDRENB(|1), | ||||
| 		.REGCEB(|1), | ||||
| 		.RSTRAMB(|0), | ||||
| 		.RSTREGB(|0), | ||||
| 		.WEBWE(B1EN), | ||||
| 
 | ||||
| 		.SLEEP(|0) | ||||
| 	); | ||||
| endmodule | ||||
| 
 | ||||
| // ------------------------------------------------------------------------ | ||||
| 
 | ||||
| module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | ||||
| 	parameter CLKPOL2 = 1; | ||||
| 	parameter CLKPOL3 = 1; | ||||
| 	parameter [18431:0] INIT = 18432'bx; | ||||
| 
 | ||||
| 	input CLK2; | ||||
| 	input CLK3; | ||||
| 
 | ||||
| 	input [8:0] A1ADDR; | ||||
| 	output [35:0] A1DATA; | ||||
| 	input A1EN; | ||||
| 
 | ||||
| 	input [8:0] B1ADDR; | ||||
| 	input [35:0] B1DATA; | ||||
| 	input [3:0] B1EN; | ||||
| 
 | ||||
| 	wire [13:0] A1ADDR_14 = {A1ADDR, 5'b0}; | ||||
| 	wire [13:0] B1ADDR_14 = {B1ADDR, 5'b0}; | ||||
| 
 | ||||
| 	wire [3:0] DIP, DOP; | ||||
| 	wire [31:0] DI, DO; | ||||
| 
 | ||||
| 	assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; | ||||
| 	assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; | ||||
| 
 | ||||
| 	RAMB18E2 #( | ||||
| 		.READ_WIDTH_A(36), | ||||
| 		.WRITE_WIDTH_B(36), | ||||
| 		.WRITE_MODE_A("READ_FIRST"), | ||||
| 		.WRITE_MODE_B("READ_FIRST"), | ||||
| 		.DOA_REG(0), | ||||
| 		.DOB_REG(0), | ||||
| 		.IS_CLKARDCLK_INVERTED(!CLKPOL2), | ||||
| 		.IS_CLKBWRCLK_INVERTED(!CLKPOL3), | ||||
| 		`include "brams_init_18.vh" | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		.DOUTBDOUT(DO[31:16]), | ||||
| 		.DOUTADOUT(DO[15:0]), | ||||
| 		.DOUTPBDOUTP(DOP[3:2]), | ||||
| 		.DOUTPADOUTP(DOP[1:0]), | ||||
| 		.DINBDIN(DI[31:16]), | ||||
| 		.DINADIN(DI[15:0]), | ||||
| 		.DINPBDINP(DIP[3:2]), | ||||
| 		.DINPADINP(DIP[1:0]), | ||||
| 
 | ||||
| 		.ADDRARDADDR(A1ADDR_14), | ||||
| 		.CLKARDCLK(CLK2), | ||||
| 		.ENARDEN(A1EN), | ||||
| 		.ADDRENA(|1), | ||||
| 		.REGCEAREGCE(|1), | ||||
| 		.RSTRAMARSTRAM(|0), | ||||
| 		.RSTREGARSTREG(|0), | ||||
| 		.WEA(2'b0), | ||||
| 
 | ||||
| 		.ADDRBWRADDR(B1ADDR_14), | ||||
| 		.CLKBWRCLK(CLK3), | ||||
| 		.ENBWREN(|1), | ||||
| 		.ADDRENB(|1), | ||||
| 		.REGCEB(|1), | ||||
| 		.RSTRAMB(|0), | ||||
| 		.RSTREGB(|0), | ||||
| 		.WEBWE(B1EN), | ||||
| 
 | ||||
| 		.SLEEP(|0) | ||||
| 	); | ||||
| endmodule | ||||
| 
 | ||||
| // ------------------------------------------------------------------------ | ||||
| 
 | ||||
| module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | ||||
| 	parameter CFG_ABITS = 10; | ||||
| 	parameter CFG_DBITS = 36; | ||||
| 	parameter CFG_ENABLE_B = 4; | ||||
| 
 | ||||
| 	parameter CLKPOL2 = 1; | ||||
| 	parameter CLKPOL3 = 1; | ||||
| 	parameter [36863:0] INIT = 36864'bx; | ||||
| 
 | ||||
| 	input CLK2; | ||||
| 	input CLK3; | ||||
| 
 | ||||
| 	input [CFG_ABITS-1:0] A1ADDR; | ||||
| 	output [CFG_DBITS-1:0] A1DATA; | ||||
| 	input A1EN; | ||||
| 
 | ||||
| 	input [CFG_ABITS-1:0] B1ADDR; | ||||
| 	input [CFG_DBITS-1:0] B1DATA; | ||||
| 	input [CFG_ENABLE_B-1:0] B1EN; | ||||
| 
 | ||||
| 	wire [15:0] A1ADDR_16 = A1ADDR << (15 - CFG_ABITS); | ||||
| 	wire [15:0] B1ADDR_16 = B1ADDR << (15 - CFG_ABITS); | ||||
| 	wire [7:0] B1EN_8 = B1EN; | ||||
| 
 | ||||
| 	wire [3:0] DIP, DOP; | ||||
| 	wire [31:0] DI, DO; | ||||
| 
 | ||||
| 	wire [31:0] DOBDO; | ||||
| 	wire [3:0] DOPBDOP; | ||||
| 
 | ||||
| 	assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; | ||||
| 	assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; | ||||
| 
 | ||||
| 	generate if (CFG_DBITS > 8) begin | ||||
| 		RAMB36E2 #( | ||||
| 			.READ_WIDTH_A(CFG_DBITS), | ||||
| 			.READ_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_A(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_MODE_A("READ_FIRST"), | ||||
| 			.WRITE_MODE_B("READ_FIRST"), | ||||
| 			.DOA_REG(0), | ||||
| 			.DOB_REG(0), | ||||
| 			.IS_CLKARDCLK_INVERTED(!CLKPOL2), | ||||
| 			.IS_CLKBWRCLK_INVERTED(!CLKPOL3), | ||||
| 			`include "brams_init_36.vh" | ||||
| 		) _TECHMAP_REPLACE_ ( | ||||
| 			.DINADIN(32'hFFFFFFFF), | ||||
| 			.DINPADINP(4'hF), | ||||
| 			.DOUTADOUT(DO[31:0]), | ||||
| 			.DOUTPADOUTP(DOP[3:0]), | ||||
| 			.ADDRARDADDR(A1ADDR_16), | ||||
| 			.CLKARDCLK(CLK2), | ||||
| 			.ENARDEN(A1EN), | ||||
| 			.ADDRENA(|1), | ||||
| 			.REGCEAREGCE(|1), | ||||
| 			.RSTRAMARSTRAM(|0), | ||||
| 			.RSTREGARSTREG(|0), | ||||
| 			.WEA(4'b0), | ||||
| 
 | ||||
| 			.DINBDIN(DI), | ||||
| 			.DINPBDINP(DIP), | ||||
| 			.DOUTBDOUT(DOBDO), | ||||
| 			.DOUTPBDOUTP(DOPBDOP), | ||||
| 			.ADDRBWRADDR(B1ADDR_16), | ||||
| 			.CLKBWRCLK(CLK3), | ||||
| 			.ENBWREN(|1), | ||||
| 			.ADDRENB(|1), | ||||
| 			.REGCEB(|0), | ||||
| 			.RSTRAMB(|0), | ||||
| 			.RSTREGB(|0), | ||||
| 			.WEBWE(B1EN_8), | ||||
| 
 | ||||
| 			.SLEEP(|0) | ||||
| 		); | ||||
| 	end else begin | ||||
| 		RAMB36E2 #( | ||||
| 			.READ_WIDTH_A(CFG_DBITS), | ||||
| 			.READ_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_A(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_MODE_A("READ_FIRST"), | ||||
| 			.WRITE_MODE_B("READ_FIRST"), | ||||
| 			.DOA_REG(0), | ||||
| 			.DOB_REG(0), | ||||
| 			.IS_CLKARDCLK_INVERTED(!CLKPOL2), | ||||
| 			.IS_CLKBWRCLK_INVERTED(!CLKPOL3), | ||||
| 			`include "brams_init_32.vh" | ||||
| 		) _TECHMAP_REPLACE_ ( | ||||
| 			.DINADIN(32'hFFFFFFFF), | ||||
| 			.DINPADINP(4'hF), | ||||
| 			.DOUTADOUT(DO[31:0]), | ||||
| 			.DOUTPADOUTP(DOP[3:0]), | ||||
| 			.ADDRARDADDR(A1ADDR_16), | ||||
| 			.CLKARDCLK(CLK2), | ||||
| 			.ENARDEN(A1EN), | ||||
| 			.ADDRENA(|1), | ||||
| 			.REGCEAREGCE(|1), | ||||
| 			.RSTRAMARSTRAM(|0), | ||||
| 			.RSTREGARSTREG(|0), | ||||
| 			.WEA(4'b0), | ||||
| 
 | ||||
| 			.DINBDIN(DI), | ||||
| 			.DINPBDINP(DIP), | ||||
| 			.DOUTBDOUT(DOBDO), | ||||
| 			.DOUTPBDOUTP(DOPBDOP), | ||||
| 			.ADDRBWRADDR(B1ADDR_16), | ||||
| 			.CLKBWRCLK(CLK3), | ||||
| 			.ENBWREN(|1), | ||||
| 			.ADDRENB(|1), | ||||
| 			.REGCEB(|0), | ||||
| 			.RSTRAMB(|0), | ||||
| 			.RSTREGB(|0), | ||||
| 			.WEBWE(B1EN_8), | ||||
| 
 | ||||
| 			.SLEEP(|0) | ||||
| 		); | ||||
| 	end endgenerate | ||||
| endmodule | ||||
| 
 | ||||
| // ------------------------------------------------------------------------ | ||||
| 
 | ||||
| module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | ||||
| 	parameter CFG_ABITS = 10; | ||||
| 	parameter CFG_DBITS = 18; | ||||
| 	parameter CFG_ENABLE_B = 2; | ||||
| 
 | ||||
| 	parameter CLKPOL2 = 1; | ||||
| 	parameter CLKPOL3 = 1; | ||||
| 	parameter [18431:0] INIT = 18432'bx; | ||||
| 
 | ||||
| 	input CLK2; | ||||
| 	input CLK3; | ||||
| 
 | ||||
| 	input [CFG_ABITS-1:0] A1ADDR; | ||||
| 	output [CFG_DBITS-1:0] A1DATA; | ||||
| 	input A1EN; | ||||
| 
 | ||||
| 	input [CFG_ABITS-1:0] B1ADDR; | ||||
| 	input [CFG_DBITS-1:0] B1DATA; | ||||
| 	input [CFG_ENABLE_B-1:0] B1EN; | ||||
| 
 | ||||
| 	wire [13:0] A1ADDR_14 = A1ADDR << (14 - CFG_ABITS); | ||||
| 	wire [13:0] B1ADDR_14 = B1ADDR << (14 - CFG_ABITS); | ||||
| 	wire [3:0] B1EN_4 = B1EN; | ||||
| 
 | ||||
| 	wire [1:0] DIP, DOP; | ||||
| 	wire [15:0] DI, DO; | ||||
| 
 | ||||
| 	wire [15:0] DOBDO; | ||||
| 	wire [1:0] DOPBDOP; | ||||
| 
 | ||||
| 	assign A1DATA = { DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; | ||||
| 	assign { DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; | ||||
| 
 | ||||
| 	generate if (CFG_DBITS > 8) begin | ||||
| 		RAMB18E2 #( | ||||
| 			.READ_WIDTH_A(CFG_DBITS), | ||||
| 			.READ_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_A(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_MODE_A("READ_FIRST"), | ||||
| 			.WRITE_MODE_B("READ_FIRST"), | ||||
| 			.DOA_REG(0), | ||||
| 			.DOB_REG(0), | ||||
| 			.IS_CLKARDCLK_INVERTED(!CLKPOL2), | ||||
| 			.IS_CLKBWRCLK_INVERTED(!CLKPOL3), | ||||
| 			`include "brams_init_18.vh" | ||||
| 		) _TECHMAP_REPLACE_ ( | ||||
| 			.DINADIN(16'hFFFF), | ||||
| 			.DINPADINP(2'b11), | ||||
| 			.DOUTADOUT(DO), | ||||
| 			.DOUTPADOUTP(DOP), | ||||
| 			.ADDRARDADDR(A1ADDR_14), | ||||
| 			.CLKARDCLK(CLK2), | ||||
| 			.ENARDEN(A1EN), | ||||
| 			.ADDRENA(|1), | ||||
| 			.REGCEAREGCE(|1), | ||||
| 			.RSTRAMARSTRAM(|0), | ||||
| 			.RSTREGARSTREG(|0), | ||||
| 			.WEA(2'b0), | ||||
| 
 | ||||
| 			.DINBDIN(DI), | ||||
| 			.DINPBDINP(DIP), | ||||
| 			.DOUTBDOUT(DOBDO), | ||||
| 			.DOUTPBDOUTP(DOPBDOP), | ||||
| 			.ADDRBWRADDR(B1ADDR_14), | ||||
| 			.CLKBWRCLK(CLK3), | ||||
| 			.ENBWREN(|1), | ||||
| 			.ADDRENB(|1), | ||||
| 			.REGCEB(|0), | ||||
| 			.RSTRAMB(|0), | ||||
| 			.RSTREGB(|0), | ||||
| 			.WEBWE(B1EN_4), | ||||
| 
 | ||||
| 			.SLEEP(|0) | ||||
| 		); | ||||
| 	end else begin | ||||
| 		RAMB18E2 #( | ||||
| 			//.RAM_MODE("TDP"), | ||||
| 			.READ_WIDTH_A(CFG_DBITS), | ||||
| 			.READ_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_A(CFG_DBITS), | ||||
| 			.WRITE_WIDTH_B(CFG_DBITS), | ||||
| 			.WRITE_MODE_A("READ_FIRST"), | ||||
| 			.WRITE_MODE_B("READ_FIRST"), | ||||
| 			.DOA_REG(0), | ||||
| 			.DOB_REG(0), | ||||
| 			.IS_CLKARDCLK_INVERTED(!CLKPOL2), | ||||
| 			.IS_CLKBWRCLK_INVERTED(!CLKPOL3), | ||||
| 			`include "brams_init_16.vh" | ||||
| 		) _TECHMAP_REPLACE_ ( | ||||
| 			.DINADIN(16'hFFFF), | ||||
| 			.DINPADINP(2'b11), | ||||
| 			.DOUTADOUT(DO), | ||||
| 			.DOUTPADOUTP(DOP), | ||||
| 			.ADDRARDADDR(A1ADDR_14), | ||||
| 			.CLKARDCLK(CLK2), | ||||
| 			.ENARDEN(A1EN), | ||||
| 			.ADDRENA(|1), | ||||
| 			.REGCEAREGCE(|1), | ||||
| 			.RSTRAMARSTRAM(|0), | ||||
| 			.RSTREGARSTREG(|0), | ||||
| 			.WEA(2'b0), | ||||
| 
 | ||||
| 			.DINBDIN(DI), | ||||
| 			.DINPBDINP(DIP), | ||||
| 			.DOUTBDOUT(DOBDO), | ||||
| 			.DOUTPBDOUTP(DOPBDOP), | ||||
| 			.ADDRBWRADDR(B1ADDR_14), | ||||
| 			.CLKBWRCLK(CLK3), | ||||
| 			.ENBWREN(|1), | ||||
| 			.ADDRENB(|1), | ||||
| 			.REGCEB(|0), | ||||
| 			.RSTRAMB(|0), | ||||
| 			.RSTREGB(|0), | ||||
| 			.WEBWE(B1EN_4), | ||||
| 
 | ||||
| 			.SLEEP(|0) | ||||
| 		); | ||||
| 	end endgenerate | ||||
| endmodule | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										51
									
								
								techlibs/xilinx/xcu_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								techlibs/xilinx/xcu_dsp_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
| module \$__MUL27X18 (input [26:0] A, input [17:0] B, output [44:0] Y); | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 	parameter A_WIDTH = 0; | ||||
| 	parameter B_WIDTH = 0; | ||||
| 	parameter Y_WIDTH = 0; | ||||
| 
 | ||||
| 	wire [47:0] P_48; | ||||
| 	DSP48E2 #( | ||||
| 		// Disable all registers | ||||
| 		.ACASCREG(0), | ||||
| 		.ADREG(0), | ||||
| 		.A_INPUT("DIRECT"), | ||||
| 		.ALUMODEREG(0), | ||||
| 		.AREG(0), | ||||
| 		.BCASCREG(0), | ||||
| 		.B_INPUT("DIRECT"), | ||||
| 		.BREG(0), | ||||
| 		.CARRYINREG(0), | ||||
| 		.CARRYINSELREG(0), | ||||
| 		.CREG(0), | ||||
| 		.DREG(0), | ||||
| 		.INMODEREG(0), | ||||
| 		.MREG(0), | ||||
| 		.OPMODEREG(0), | ||||
| 		.PREG(0), | ||||
| 		.USE_MULT("MULTIPLY"), | ||||
| 		.USE_SIMD("ONE48"), | ||||
| 		.AMULTSEL("A"), | ||||
| 		.BMULTSEL("B") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		//Data path | ||||
| 		.A({{3{A[26]}}, A}), | ||||
| 		.B(B), | ||||
| 		.C(48'b0), | ||||
| 		.D(27'b0), | ||||
| 		.P(P_48), | ||||
| 
 | ||||
| 		.INMODE(5'b00000), | ||||
| 		.ALUMODE(4'b0000), | ||||
| 		.OPMODE(9'b00000101), | ||||
| 		.CARRYINSEL(3'b000), | ||||
| 
 | ||||
| 		.ACIN(30'b0), | ||||
| 		.BCIN(18'b0), | ||||
| 		.PCIN(48'b0), | ||||
| 		.CARRYIN(1'b0) | ||||
| 	); | ||||
| 	assign Y = P_48; | ||||
| endmodule | ||||
| 
 | ||||
							
								
								
									
										19
									
								
								techlibs/xilinx/xcup_urams.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								techlibs/xilinx/xcup_urams.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| bram $__XILINX_URAM288 | ||||
|   init 0 | ||||
|   abits 12 | ||||
|   dbits 72 | ||||
|   groups 2 | ||||
|   ports  1 1 | ||||
|   wrmode 0 1 | ||||
|   enable 1 9 | ||||
|   transp 0 0 | ||||
|   clocks 2 2 | ||||
|   clkpol 2 2 | ||||
| endbram | ||||
| 
 | ||||
| match $__XILINX_URAM288 | ||||
|   min bits 131072 | ||||
|   min efficiency 15 | ||||
|   shuffle_enable B | ||||
|   make_transp | ||||
| endmatch | ||||
							
								
								
									
										47
									
								
								techlibs/xilinx/xcup_urams_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								techlibs/xilinx/xcup_urams_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | |||
| module \$__XILINX_URAM288 (CLK2, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); | ||||
| 	parameter CLKPOL2 = 1; | ||||
| 
 | ||||
| 	input CLK2; | ||||
| 
 | ||||
| 	input [11:0] A1ADDR; | ||||
| 	output [71:0] A1DATA; | ||||
| 	input A1EN; | ||||
| 
 | ||||
| 	input [11:0] B1ADDR; | ||||
| 	input [71:0] B1DATA; | ||||
| 	input [8:0] B1EN; | ||||
| 
 | ||||
| 
 | ||||
| 	URAM288 #( | ||||
| 		.BWE_MODE_A("PARITY_INDEPENDENT"), | ||||
| 		.BWE_MODE_B("PARITY_INDEPENDENT"), | ||||
| 		.EN_AUTO_SLEEP_MODE("FALSE"), | ||||
| 		.IREG_PRE_A("FALSE"), | ||||
| 		.IREG_PRE_B("FALSE"), | ||||
| 		.IS_CLK_INVERTED(!CLKPOL2), | ||||
| 		.OREG_A("FALSE"), | ||||
| 		.OREG_B("FALSE") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		.ADDR_A({11'b0, A1ADDR}), | ||||
| 		.BWE_A(9'b0), | ||||
| 		.DIN_A(72'b0), | ||||
| 		.EN_A(A1EN), | ||||
| 		.RDB_WR_A(1'b0), | ||||
| 		.INJECT_DBITERR_A(1'b0), | ||||
| 		.INJECT_SBITERR_A(1'b0), | ||||
| 		.RST_A(1'b0), | ||||
| 		.DOUT_A(A1DATA), | ||||
| 
 | ||||
| 		.ADDR_B({11'b0, B1ADDR}), | ||||
| 		.BWE_B(B1EN), | ||||
| 		.DIN_B(B1DATA), | ||||
| 		.EN_B(|B1EN), | ||||
| 		.RDB_WR_B(1'b1), | ||||
| 		.INJECT_DBITERR_B(1'b0), | ||||
| 		.INJECT_SBITERR_B(1'b0), | ||||
| 		.RST_B(1'b0), | ||||
| 
 | ||||
| 		.CLK(CLK2), | ||||
| 		.SLEEP(1'b0) | ||||
| 	); | ||||
| endmodule | ||||
							
								
								
									
										10
									
								
								tests/arch/anlogic/add_sub.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/arch/anlogic/add_sub.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| read_verilog ../common/add_sub.v | ||||
| hierarchy -top top | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd top # Constrain all select calls below inside the top module | ||||
| select -assert-count 10 t:AL_MAP_ADDER | ||||
| select -assert-count 4 t:AL_MAP_LUT1 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT1 t:AL_MAP_ADDER %% t:* %D | ||||
							
								
								
									
										11
									
								
								tests/arch/anlogic/counter.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/arch/anlogic/counter.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| read_verilog ../common/counter.v | ||||
| hierarchy -top top | ||||
| proc | ||||
| flatten | ||||
| equiv_opt -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd top # Constrain all select calls below inside the top module | ||||
| 
 | ||||
| select -assert-count 9 t:AL_MAP_ADDER | ||||
| select -assert-count 8 t:AL_MAP_SEQ | ||||
| select -assert-none t:AL_MAP_SEQ t:AL_MAP_ADDER %% t:* %D | ||||
							
								
								
									
										20
									
								
								tests/arch/anlogic/dffs.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tests/arch/anlogic/dffs.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| read_verilog ../common/dffs.v | ||||
| design -save read | ||||
| 
 | ||||
| hierarchy -top dff | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd dff # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:AL_MAP_SEQ | ||||
| select -assert-none t:AL_MAP_SEQ %% t:* %D | ||||
| 
 | ||||
| design -load read | ||||
| hierarchy -top dffe | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd dffe # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:AL_MAP_LUT3 | ||||
| select -assert-count 1 t:AL_MAP_SEQ | ||||
| select -assert-none t:AL_MAP_LUT3 t:AL_MAP_SEQ %% t:* %D | ||||
							
								
								
									
										18
									
								
								tests/arch/anlogic/fsm.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tests/arch/anlogic/fsm.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| read_verilog ../common/fsm.v | ||||
| hierarchy -top fsm | ||||
| proc | ||||
| flatten | ||||
| 
 | ||||
| equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic | ||||
| miter -equiv -make_assert -flatten gold gate miter | ||||
| sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter | ||||
| 
 | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd fsm # Constrain all select calls below inside the top module | ||||
| 
 | ||||
| select -assert-count 1 t:AL_MAP_LUT2 | ||||
| select -assert-count 5 t:AL_MAP_LUT5 | ||||
| select -assert-count 1 t:AL_MAP_LUT6 | ||||
| select -assert-count 6 t:AL_MAP_SEQ | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT2 t:AL_MAP_LUT5 t:AL_MAP_LUT6 t:AL_MAP_SEQ %% t:* %D | ||||
							
								
								
									
										33
									
								
								tests/arch/anlogic/latches.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tests/arch/anlogic/latches.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| read_verilog ../common/latches.v | ||||
| design -save read | ||||
| 
 | ||||
| hierarchy -top latchp | ||||
| proc | ||||
| # Can't run any sort of equivalence check because latches are blown to LUTs | ||||
| synth_anlogic | ||||
| cd latchp # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:AL_MAP_LUT3 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT3 %% t:* %D | ||||
| 
 | ||||
| 
 | ||||
| design -load read | ||||
| hierarchy -top latchn | ||||
| proc | ||||
| # Can't run any sort of equivalence check because latches are blown to LUTs | ||||
| synth_anlogic | ||||
| cd latchn # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:AL_MAP_LUT3 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT3 %% t:* %D | ||||
| 
 | ||||
| 
 | ||||
| design -load read | ||||
| hierarchy -top latchsr | ||||
| proc | ||||
| # Can't run any sort of equivalence check because latches are blown to LUTs | ||||
| synth_anlogic | ||||
| cd latchsr # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:AL_MAP_LUT5 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT5 %% t:* %D | ||||
							
								
								
									
										11
									
								
								tests/arch/anlogic/logic.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/arch/anlogic/logic.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| read_verilog ../common/logic.v | ||||
| hierarchy -top top | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd top # Constrain all select calls below inside the top module | ||||
| 
 | ||||
| select -assert-count 1 t:AL_MAP_LUT1 | ||||
| select -assert-count 6 t:AL_MAP_LUT2 | ||||
| select -assert-count 2 t:AL_MAP_LUT4 | ||||
| select -assert-none t:AL_MAP_LUT1 t:AL_MAP_LUT2 t:AL_MAP_LUT4 %% t:* %D | ||||
							
								
								
									
										21
									
								
								tests/arch/anlogic/memory.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/arch/anlogic/memory.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| read_verilog ../common/memory.v | ||||
| hierarchy -top top | ||||
| proc | ||||
| memory -nomap | ||||
| equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic | ||||
| memory | ||||
| opt -full | ||||
| 
 | ||||
| miter -equiv -flatten -make_assert -make_outputs gold gate miter | ||||
| #ERROR: Failed to import cell gate.mem.0.0.0 (type EG_LOGIC_DRAM16X4) to SAT database. | ||||
| #sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter | ||||
| 
 | ||||
| design -load postopt | ||||
| cd top | ||||
| 
 | ||||
| select -assert-count 8  t:AL_MAP_LUT2 | ||||
| select -assert-count 8  t:AL_MAP_LUT4 | ||||
| select -assert-count 8   t:AL_MAP_LUT5 | ||||
| select -assert-count 36 t:AL_MAP_SEQ | ||||
| select -assert-count 8  t:EG_LOGIC_DRAM16X4 #Why not AL_LOGIC_BRAM? | ||||
| select -assert-none t:AL_MAP_LUT2 t:AL_MAP_LUT4 t:AL_MAP_LUT5 t:AL_MAP_SEQ t:EG_LOGIC_DRAM16X4 %% t:* %D | ||||
							
								
								
									
										42
									
								
								tests/arch/anlogic/mux.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								tests/arch/anlogic/mux.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| read_verilog ../common/mux.v | ||||
| design -save read | ||||
| 
 | ||||
| hierarchy -top mux2 | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd mux2 # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:AL_MAP_LUT3 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT3 %% t:* %D | ||||
| 
 | ||||
| design -load read | ||||
| hierarchy -top mux4 | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd mux4 # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:AL_MAP_LUT6 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT6 %% t:* %D | ||||
| 
 | ||||
| design -load read | ||||
| hierarchy -top mux8 | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd mux8 # Constrain all select calls below inside the top module | ||||
| select -assert-count 3 t:AL_MAP_LUT4 | ||||
| select -assert-count 1 t:AL_MAP_LUT6 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT4 t:AL_MAP_LUT6 %% t:* %D | ||||
| 
 | ||||
| design -load read | ||||
| hierarchy -top mux16 | ||||
| proc | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd mux16 # Constrain all select calls below inside the top module | ||||
| select -assert-count 5 t:AL_MAP_LUT6 | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_LUT6 %% t:* %D | ||||
|  | @ -6,7 +6,7 @@ for x in *.ys; do | |||
| 	echo "all:: run-$x" | ||||
| 	echo "run-$x:" | ||||
| 	echo "	@echo 'Running $x..'" | ||||
| 	echo "	@../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x" | ||||
| 	echo "	@../../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x" | ||||
| done | ||||
| for s in *.sh; do | ||||
| 	if [ "$s" != "run-test.sh" ]; then | ||||
							
								
								
									
										10
									
								
								tests/arch/anlogic/shifter.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/arch/anlogic/shifter.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| read_verilog ../common/shifter.v | ||||
| hierarchy -top top | ||||
| proc | ||||
| flatten | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd top # Constrain all select calls below inside the top module | ||||
| select -assert-count 8 t:AL_MAP_SEQ | ||||
| 
 | ||||
| select -assert-none t:AL_MAP_SEQ %% t:* %D | ||||
							
								
								
									
										9
									
								
								tests/arch/anlogic/tribuf.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/arch/anlogic/tribuf.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| read_verilog ../common/tribuf.v | ||||
| hierarchy -top tristate | ||||
| proc | ||||
| flatten | ||||
| equiv_opt -assert -map +/anlogic/cells_sim.v -map +/simcells.v synth_anlogic # equivalency check | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| cd tristate # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:$_TBUF_ | ||||
| select -assert-none t:$_TBUF_ %% t:* %D | ||||
							
								
								
									
										12
									
								
								tests/arch/common/add_sub.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/arch/common/add_sub.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| module top | ||||
| ( | ||||
|     input [3:0] x, | ||||
|     input [3:0] y, | ||||
| 
 | ||||
|     output [3:0] A, | ||||
|     output [3:0] B | ||||
| ); | ||||
| 
 | ||||
|     assign A =  x + y; | ||||
|     assign B =  x - y; | ||||
| endmodule | ||||
							
								
								
									
										43
									
								
								tests/arch/common/adffs.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								tests/arch/common/adffs.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| module adff( input d, clk, clr, output reg q ); | ||||
|     initial begin | ||||
|         q = 0; | ||||
|     end | ||||
| 	  always @( posedge clk, posedge clr ) | ||||
|       if ( clr ) | ||||
|         q <= 1'b0; | ||||
|       else | ||||
|         q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| module adffn( input d, clk, clr, output reg q ); | ||||
|     initial begin | ||||
|       q = 0; | ||||
|     end | ||||
| 	  always @( posedge clk, negedge clr ) | ||||
| 		  if ( !clr ) | ||||
| 			  q <= 1'b0; | ||||
|   		else | ||||
|         q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| module dffs( input d, clk, pre, clr, output reg q ); | ||||
|     initial begin | ||||
|       q = 0; | ||||
|     end | ||||
|     always @( posedge clk ) | ||||
|       if ( pre ) | ||||
|         q <= 1'b1; | ||||
|       else | ||||
|         q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| module ndffnr( input d, clk, pre, clr, output reg q ); | ||||
|     initial begin | ||||
|       q = 0; | ||||
|     end | ||||
|     always @( negedge clk ) | ||||
|       if ( !clr ) | ||||
|         q <= 1'b0; | ||||
|       else | ||||
|         q <= d; | ||||
| endmodule | ||||
							
								
								
									
										11
									
								
								tests/arch/common/counter.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/arch/common/counter.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| module top ( out, clk, reset ); | ||||
|     output [7:0] out; | ||||
|     input clk, reset; | ||||
|     reg [7:0] out; | ||||
| 
 | ||||
|     always @(posedge clk, posedge reset) | ||||
|       if (reset) | ||||
|           out <= 8'b0; | ||||
|       else | ||||
|           out <= out + 1; | ||||
| endmodule | ||||
							
								
								
									
										13
									
								
								tests/arch/common/dffs.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/arch/common/dffs.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| module dff ( input d, clk, output reg q ); | ||||
| 	  always @( posedge clk ) | ||||
|         q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| module dffe( input d, clk, en, output reg q ); | ||||
|     initial begin | ||||
|         q = 0; | ||||
|     end | ||||
| 	  always @( posedge clk ) | ||||
|         if ( en ) | ||||
|               q <= d; | ||||
| endmodule | ||||
							
								
								
									
										51
									
								
								tests/arch/common/fsm.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tests/arch/common/fsm.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
|  module fsm ( clock, reset, req_0, req_1, gnt_0, gnt_1 ); | ||||
|     input   clock,reset,req_0,req_1; | ||||
|     output  gnt_0,gnt_1; | ||||
|     wire    clock,reset,req_0,req_1; | ||||
|     reg     gnt_0,gnt_1; | ||||
| 
 | ||||
|     parameter SIZE = 3; | ||||
|     parameter IDLE = 3'b001; | ||||
|     parameter GNT0 = 3'b010; | ||||
|     parameter GNT1 = 3'b100; | ||||
|     parameter GNT2 = 3'b101; | ||||
| 
 | ||||
|     reg [SIZE-1:0] state; | ||||
|     reg [SIZE-1:0] next_state; | ||||
| 
 | ||||
|     always @ (posedge clock) | ||||
|         begin : FSM | ||||
|           if (reset == 1'b1) begin | ||||
|             state <=  #1  IDLE; | ||||
|             gnt_0 <= 0; | ||||
|             gnt_1 <= 0; | ||||
|           end  | ||||
|           else | ||||
|             case(state) | ||||
|               IDLE :  if (req_0 == 1'b1) begin | ||||
|                           state <=  #1  GNT0; | ||||
|                           gnt_0 <= 1; | ||||
|                       end else if (req_1 == 1'b1) begin | ||||
|                           gnt_1 <= 1; | ||||
|                           state <=  #1  GNT0; | ||||
|                       end else begin | ||||
|                           state <=  #1  IDLE; | ||||
|                       end | ||||
|               GNT0 :  if (req_0 == 1'b1) begin | ||||
|                           state <=  #1  GNT0; | ||||
|                       end else begin | ||||
|                           gnt_0 <= 0; | ||||
|                           state <=  #1  IDLE; | ||||
|                       end | ||||
|               GNT1 :  if (req_1 == 1'b1) begin | ||||
|                           state <=  #1  GNT2; | ||||
|                           gnt_1 <= req_0; | ||||
|                       end | ||||
|               GNT2 :  if (req_0 == 1'b1) begin | ||||
|                           state <=  #1  GNT1; | ||||
|                           gnt_1 <= req_1; | ||||
|                       end | ||||
|               default : state <=  #1  IDLE; | ||||
|             endcase | ||||
|         end | ||||
| endmodule | ||||
							
								
								
									
										21
									
								
								tests/arch/common/latches.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/arch/common/latches.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| module latchp ( input d, clk, en, output reg q ); | ||||
| 	always @* | ||||
| 		if ( en ) | ||||
| 			q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| module latchn ( input d, clk, en, output reg q ); | ||||
| 	always @* | ||||
| 		if ( !en ) | ||||
| 			q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| module latchsr ( input d, clk, en, clr, pre, output reg q ); | ||||
| 	always @* | ||||
| 		if ( clr ) | ||||
| 			q <= 1'b0; | ||||
| 		else if ( pre ) | ||||
| 			q <= 1'b1; | ||||
| 		else if ( en ) | ||||
| 			q <= d; | ||||
| endmodule | ||||
							
								
								
									
										16
									
								
								tests/arch/common/logic.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								tests/arch/common/logic.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| module top | ||||
| ( | ||||
|     input [0:7] in, | ||||
|     output B1,B2,B3,B4,B5,B6,B7,B8,B9,B10 | ||||
| ); | ||||
|     assign B1 =  in[0] & in[1]; | ||||
|     assign B2 =  in[0] | in[1]; | ||||
|     assign B3 =  in[0] ~& in[1]; | ||||
|     assign B4 =  in[0] ~| in[1]; | ||||
|     assign B5 =  in[0] ^ in[1]; | ||||
|     assign B6 =  in[0] ~^ in[1]; | ||||
|     assign B7 =  ~in[0]; | ||||
|     assign B8 =  in[0]; | ||||
|     assign B9 =  in[0:1] && in [2:3]; | ||||
|     assign B10 =  in[0:1] || in [2:3]; | ||||
| endmodule | ||||
							
								
								
									
										9
									
								
								tests/arch/common/mul.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/arch/common/mul.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| module top | ||||
| ( | ||||
|     input [5:0] x, | ||||
|     input [5:0] y, | ||||
| 
 | ||||
|     output [11:0] A, | ||||
| ); | ||||
|     assign A =  x * y; | ||||
| endmodule | ||||
							
								
								
									
										60
									
								
								tests/arch/common/mux.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								tests/arch/common/mux.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| module mux2 (S,A,B,Y); | ||||
|     input S; | ||||
|     input A,B; | ||||
|     output reg Y; | ||||
| 
 | ||||
|     always @(*) | ||||
| 		Y = (S)? B : A; | ||||
| endmodule | ||||
| 
 | ||||
| module mux4 ( S, D, Y ); | ||||
|     input[1:0] S; | ||||
|     input[3:0] D; | ||||
|     output Y; | ||||
| 
 | ||||
|     reg Y; | ||||
|     wire[1:0] S; | ||||
|     wire[3:0] D; | ||||
| 
 | ||||
|     always @* | ||||
|     begin | ||||
|         case( S ) | ||||
|             0 : Y = D[0]; | ||||
|             1 : Y = D[1]; | ||||
|             2 : Y = D[2]; | ||||
|             3 : Y = D[3]; | ||||
|         endcase | ||||
|     end | ||||
| endmodule | ||||
| 
 | ||||
| module mux8 ( S, D, Y ); | ||||
|     input[2:0] S; | ||||
|     input[7:0] D; | ||||
|     output Y; | ||||
| 
 | ||||
|     reg Y; | ||||
|     wire[2:0] S; | ||||
|     wire[7:0] D; | ||||
| 
 | ||||
|     always @* | ||||
|     begin | ||||
|         case( S ) | ||||
|             0 : Y = D[0]; | ||||
|             1 : Y = D[1]; | ||||
|             2 : Y = D[2]; | ||||
|             3 : Y = D[3]; | ||||
|             4 : Y = D[4]; | ||||
|             5 : Y = D[5]; | ||||
|             6 : Y = D[6]; | ||||
|             7 : Y = D[7]; | ||||
|         endcase | ||||
|     end | ||||
| endmodule | ||||
| 
 | ||||
| module mux16 (D, S, Y); | ||||
|  	input  [15:0] D; | ||||
|  	input  [3:0] S; | ||||
|  	output Y; | ||||
| 
 | ||||
|     assign Y = D[S]; | ||||
| endmodule | ||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue