mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +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 | /%_pm.h | ||||||
| /peepopt_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