mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Add xilinx_dsp for register packing
This commit is contained in:
		
							parent
							
								
									42f8e68e76
								
							
						
					
					
						commit
						dd59375a66
					
				
					 3 changed files with 192 additions and 2 deletions
				
			
		
							
								
								
									
										3
									
								
								passes/pmgen/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								passes/pmgen/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,2 +1 @@ | |||
| /ice40_dsp_pm.h | ||||
| /peepopt_pm.h | ||||
| /%_pm.h | ||||
|  |  | |||
							
								
								
									
										120
									
								
								passes/pmgen/xilinx_dsp.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								passes/pmgen/xilinx_dsp.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | |||
| /*
 | ||||
|  *  yosys -- Yosys Open SYnthesis Suite | ||||
|  * | ||||
|  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||
|  * | ||||
|  *  Permission to use, copy, modify, and/or distribute this software for any | ||||
|  *  purpose with or without fee is hereby granted, provided that the above | ||||
|  *  copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "kernel/yosys.h" | ||||
| #include "kernel/sigtools.h" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| #include "passes/pmgen/xilinx_dsp_pm.h" | ||||
| 
 | ||||
| void create_xilinx_dsp(xilinx_dsp_pm &pm) | ||||
| { | ||||
| 	auto &st = pm.st_xilinx_dsp; | ||||
| 
 | ||||
| #if 0 | ||||
| 	log("\n"); | ||||
| 	log("ffA:   %s\n", log_id(st.ffA, "--")); | ||||
| 	log("ffB:   %s\n", log_id(st.ffB, "--")); | ||||
| 	log("mul:   %s\n", log_id(st.mul, "--")); | ||||
| 	log("ffY:   %s\n", log_id(st.ffY, "--")); | ||||
| #endif | ||||
| 
 | ||||
| 	log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.mul)); | ||||
| 
 | ||||
| 	Cell *cell = st.mul; | ||||
| 	log_assert(cell); | ||||
| 
 | ||||
| 	// Input Interface
 | ||||
| 
 | ||||
| 	cell->setPort("\\A", st.sigA); | ||||
| 	cell->setPort("\\B", st.sigB); | ||||
| 
 | ||||
| 	cell->setParam("\\AREG", st.ffA ? State::S1 : State::S0); | ||||
| 	cell->setParam("\\BREG", st.ffB ? State::S1 : State::S0); | ||||
| 
 | ||||
| 	if (st.clock != SigBit()) | ||||
| 	{ | ||||
| 		cell->setPort("\\CLK", st.clock); | ||||
| 
 | ||||
| 		if (st.ffA) { | ||||
| 			cell->setParam("\\AREG", State::S1); | ||||
| 			cell->setPort("\\CEA2", State::S1); | ||||
| 		} | ||||
| 		if (st.ffB) { | ||||
| 			cell->setParam("\\BREG", State::S1); | ||||
| 			cell->setPort("\\CEA2", State::S1); | ||||
| 		} | ||||
| 		if (st.ffY) { | ||||
| 			cell->setPort("\\PREG", State::S1); | ||||
| 			cell->setPort("\\CEP", State::S1); | ||||
| 		} | ||||
| 
 | ||||
| 		log("  clock: %s (%s)", log_signal(st.clock), "posedge"); | ||||
| 
 | ||||
| 		if (st.ffA) | ||||
| 			log(" ffA:%s", log_id(st.ffA)); | ||||
| 
 | ||||
| 		if (st.ffB) | ||||
| 			log(" ffB:%s", log_id(st.ffB)); | ||||
| 
 | ||||
| 		if (st.ffY) | ||||
| 			log(" ffY:%s", log_id(st.ffY)); | ||||
| 
 | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	// Output Interface
 | ||||
| 
 | ||||
| 	pm.autoremove(st.ffY); | ||||
| } | ||||
| 
 | ||||
| struct Ice40DspPass : public Pass { | ||||
| 	Ice40DspPass() : Pass("xilinx_dsp", "Xilinx: pack DSP registers") { } | ||||
| 	void help() YS_OVERRIDE | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    xilinx_dsp [options] [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("Pack registers into Xilinx DSPs\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		log_header(design, "Executing ICE40_DSP pass (map multipliers).\n"); | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
| 		{ | ||||
| 			// if (args[argidx] == "-singleton") {
 | ||||
| 			// 	singleton_mode = true;
 | ||||
| 			// 	continue;
 | ||||
| 			// }
 | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) | ||||
| 			xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(create_xilinx_dsp); | ||||
| 	} | ||||
| } Ice40DspPass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
							
								
								
									
										71
									
								
								passes/pmgen/xilinx_dsp.pmg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								passes/pmgen/xilinx_dsp.pmg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | |||
| pattern xilinx_dsp | ||||
| 
 | ||||
| state <SigBit> clock | ||||
| state <SigSpec> sigA sigB sigY sigS | ||||
| state <Cell*> addAB muxAB | ||||
| 
 | ||||
| match mul | ||||
| 	select mul->type.in($__MUL25X18) | ||||
| endmatch | ||||
| 
 | ||||
| match ffA | ||||
| 	select ffA->type.in($dff) /* TODO: $dffe */ | ||||
| 	// select nusers(port(ffA, \Q)) == 2 | ||||
| 	index <SigSpec> port(ffA, \Q) === port(mul, \A) | ||||
| 	// DSP48E1 does not support clock inversion | ||||
| 	index <SigBit> port(ffA, \CLK_POLARITY) === State::S1 | ||||
| 	optional | ||||
| endmatch | ||||
| 
 | ||||
| code sigA clock | ||||
| 	sigA = port(mul, \A); | ||||
| 
 | ||||
| 	if (ffA) { | ||||
| 		sigA = port(ffA, \D); | ||||
| 		clock = port(ffA, \CLK).as_bit(); | ||||
| 	} | ||||
| endcode | ||||
| 
 | ||||
| match ffB | ||||
| 	select ffB->type.in($dff) | ||||
| 	// select nusers(port(ffB, \Q)) == 2 | ||||
| 	index <SigSpec> port(ffB, \Q) === port(mul, \B) | ||||
| 	index <SigBit> port(ffB, \CLK_POLARITY) === State::S1 | ||||
| 	optional | ||||
| endmatch | ||||
| 
 | ||||
| code sigB clock  | ||||
| 	sigB = port(mul, \B); | ||||
| 
 | ||||
| 	if (ffB) { | ||||
| 		sigB = port(ffB, \D); | ||||
| 		SigBit c = port(ffB, \CLK).as_bit(); | ||||
| 
 | ||||
| 		if (clock != SigBit() && c != clock) | ||||
| 			reject; | ||||
| 
 | ||||
| 		clock = c; | ||||
| 	} | ||||
| endcode | ||||
| 
 | ||||
| match ffY | ||||
| 	select ffY->type.in($dff) | ||||
| 	select nusers(port(ffY, \D)) == 2 | ||||
| 	index <SigSpec> port(ffY, \D) === port(mul, \Y) | ||||
| 	index <SigBit> port(ffY, \CLK_POLARITY) === State::S1 | ||||
| 	optional | ||||
| endmatch | ||||
| 
 | ||||
| code sigY clock | ||||
| 	sigY = port(mul, \Y); | ||||
| 
 | ||||
| 	if (ffY) { | ||||
| 		sigY = port(ffY, \Q); | ||||
| 		SigBit c = port(ffY, \CLK).as_bit(); | ||||
| 
 | ||||
| 		if (clock != SigBit() && c != clock) | ||||
| 			reject; | ||||
| 
 | ||||
| 		clock = c; | ||||
| 	} | ||||
| endcode | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue