mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Added "pmuxtree" command
This commit is contained in:
		
							parent
							
								
									1f33b2a490
								
							
						
					
					
						commit
						724cead61d
					
				
					 3 changed files with 164 additions and 0 deletions
				
			
		|  | @ -12,6 +12,7 @@ OBJS += passes/techmap/extract.o | |||
| OBJS += passes/techmap/alumacc.o | ||||
| OBJS += passes/techmap/dff2dffe.o | ||||
| OBJS += passes/techmap/dffinit.o | ||||
| OBJS += passes/techmap/pmuxtree.o | ||||
| OBJS += passes/techmap/muxcover.o | ||||
| endif | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										112
									
								
								passes/techmap/pmuxtree.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								passes/techmap/pmuxtree.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| /*
 | ||||
|  *  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 | ||||
| 
 | ||||
| static SigSpec or_generator(Module *module, const SigSpec &sig) | ||||
| { | ||||
| 	switch (GetSize(sig)) | ||||
| 	{ | ||||
| 	case 0: | ||||
| 		return State::S0; | ||||
| 	case 1: | ||||
| 		return sig; | ||||
| 	case 2: | ||||
| 		return module->Or(NEW_ID, sig[0], sig[1]); | ||||
| 	default: | ||||
| 		return module->ReduceOr(NEW_ID, sig); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data, const SigSpec &sig_sel, SigSpec &sig_or) | ||||
| { | ||||
| 	if (GetSize(sig_sel) == 1) { | ||||
| 		sig_or.append(sig_sel); | ||||
| 		return sig_data; | ||||
| 	} | ||||
| 
 | ||||
| 	int left_size = GetSize(sig_sel) / 2; | ||||
| 	int right_size = GetSize(sig_sel) - left_size; | ||||
| 	int stride = GetSize(sig_data) / GetSize(sig_sel); | ||||
| 
 | ||||
| 	SigSpec left_data = sig_data.extract(0, stride*left_size); | ||||
| 	SigSpec right_data = sig_data.extract(stride*left_size, stride*right_size); | ||||
| 
 | ||||
| 	SigSpec left_sel = sig_sel.extract(0, left_size); | ||||
| 	SigSpec right_sel = sig_sel.extract(left_size, right_size); | ||||
| 
 | ||||
| 	SigSpec left_or, left_result, right_result; | ||||
| 	 | ||||
| 	left_result = recursive_mux_generator(module, left_data, left_sel, left_or); | ||||
| 	right_result = recursive_mux_generator(module, right_data, right_sel, sig_or); | ||||
| 	left_or = or_generator(module, left_or); | ||||
| 	sig_or.append(left_or); | ||||
| 
 | ||||
| 	return module->Mux(NEW_ID, right_result, left_result, left_or); | ||||
| } | ||||
| 
 | ||||
| struct PmuxtreePass : public Pass { | ||||
| 	PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { } | ||||
| 	virtual void help() | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    pmuxtree [options] [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("This pass transforms $pmux cells to a trees of $mux cells.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		log_header("Executing PMUXTREE pass.\n"); | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) | ||||
| 		for (auto cell : module->selected_cells()) | ||||
| 		{ | ||||
| 			if (cell->type != "$pmux") | ||||
| 				continue; | ||||
| 
 | ||||
| 			SigSpec sig_data = cell->getPort("\\B"); | ||||
| 			SigSpec sig_sel = cell->getPort("\\S"); | ||||
| 
 | ||||
| 			if (!cell->getPort("\\A").is_fully_undef()) { | ||||
| 				sig_data.append(cell->getPort("\\A")); | ||||
| 				SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel); | ||||
| 				sig_sel.append(module->Not(NEW_ID, sig_sel_or)); | ||||
| 			} | ||||
| 
 | ||||
| 			SigSpec result, result_or; | ||||
| 			result = recursive_mux_generator(module, sig_data, sig_sel, result_or); | ||||
| 			module->connect(cell->getPort("\\Y"), result); | ||||
| 			module->remove(cell); | ||||
| 		} | ||||
| 	} | ||||
| } PmuxtreePass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
							
								
								
									
										51
									
								
								tests/various/muxcover.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tests/various/muxcover.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
| 
 | ||||
| read_verilog -formal <<EOT | ||||
|     module gate (input [2:0] A, B, C, D, X, output reg [2:0] Y); | ||||
|         always @* | ||||
|             (* parallel_case *) | ||||
|             casez (X) | ||||
|                 3'b??1: Y = A; | ||||
|                 3'b?1?: Y = B; | ||||
|                 3'b1??: Y = C; | ||||
|                 3'b000: Y = D; | ||||
|             endcase | ||||
|     endmodule | ||||
| EOT | ||||
| 
 | ||||
| 
 | ||||
| ## Examle usage for "pmuxtree" and "muxcover" | ||||
| 
 | ||||
| proc | ||||
| pmuxtree | ||||
| techmap | ||||
| muxcover -mux4 | ||||
| 
 | ||||
| splitnets -ports | ||||
| clean | ||||
| # show | ||||
| 
 | ||||
| 
 | ||||
| ## Equivalence checking | ||||
| 
 | ||||
| read_verilog -formal <<EOT | ||||
|     module gold (input [2:0] A, B, C, D, X, output reg [2:0] Y); | ||||
|         always @* | ||||
|             casez (X) | ||||
|                 3'b001: Y = A; | ||||
|                 3'b010: Y = B; | ||||
|                 3'b100: Y = C; | ||||
|                 3'b000: Y = D; | ||||
| 		default: Y = 'bx; | ||||
|             endcase | ||||
|     endmodule | ||||
| EOT | ||||
| 
 | ||||
| proc | ||||
| splitnets -ports | ||||
| techmap -map +/simcells.v t:$_MUX4_ | ||||
| 
 | ||||
| equiv_make gold gate equiv | ||||
| hierarchy -top equiv | ||||
| equiv_simple -undef | ||||
| equiv_status -assert | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue