mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Improved handling of reg init in opt_share and opt_rmdff
This commit is contained in:
		
							parent
							
								
									9e938aa32a
								
							
						
					
					
						commit
						ecdf1f5577
					
				
					 2 changed files with 48 additions and 7 deletions
				
			
		|  | @ -24,7 +24,7 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| static SigMap assign_map; | ||||
| static SigMap assign_map, dff_init_map; | ||||
| static SigSet<RTLIL::Cell*> mux_drivers; | ||||
| 
 | ||||
| static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) | ||||
|  | @ -73,6 +73,14 @@ static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) | |||
| 	assign_map.apply(sig_c); | ||||
| 	assign_map.apply(sig_r); | ||||
| 
 | ||||
| 	bool has_init; | ||||
| 	RTLIL::Const val_init; | ||||
| 	for (auto bit : dff_init_map(sig_q).to_sigbit_vector()) { | ||||
| 		if (bit.wire == NULL) | ||||
| 			has_init = true; | ||||
| 		val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); | ||||
| 	} | ||||
| 
 | ||||
| 	if (dff->type == "$dff" && mux_drivers.has(sig_d)) { | ||||
| 		std::set<RTLIL::Cell*> muxes; | ||||
| 		mux_drivers.find(sig_d, muxes); | ||||
|  | @ -92,31 +100,41 @@ static bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (sig_c.is_fully_const()) { | ||||
| 	if (sig_c.is_fully_const() && (!sig_r.width || !has_init)) { | ||||
| 		if (val_rv.bits.size() == 0) | ||||
| 			val_rv = RTLIL::Const(RTLIL::State::Sx, sig_q.width); | ||||
| 			val_rv = val_init; | ||||
| 		RTLIL::SigSig conn(sig_q, val_rv); | ||||
| 		mod->connections.push_back(conn); | ||||
| 		goto delete_dff; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sig_d.is_fully_undef() && sig_d.width == int(val_rv.bits.size())) { | ||||
| 	if (sig_d.is_fully_undef() && sig_r.width && !has_init) { | ||||
| 		RTLIL::SigSig conn(sig_q, val_rv); | ||||
| 		mod->connections.push_back(conn); | ||||
| 		goto delete_dff; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sig_d.is_fully_const() && sig_r.width == 0) { | ||||
| 	if (sig_d.is_fully_undef() && !sig_r.width && has_init) { | ||||
| 		RTLIL::SigSig conn(sig_q, val_init); | ||||
| 		mod->connections.push_back(conn); | ||||
| 		goto delete_dff; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sig_d.is_fully_const() && !sig_r.width && !has_init) { | ||||
| 		RTLIL::SigSig conn(sig_q, sig_d); | ||||
| 		mod->connections.push_back(conn); | ||||
| 		goto delete_dff; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sig_d == sig_q) { | ||||
| 		if (sig_r.width > 0) { | ||||
| 	if (sig_d == sig_q && !(sig_r.width && has_init)) { | ||||
| 		if (sig_r.width) { | ||||
| 			RTLIL::SigSig conn(sig_q, val_rv); | ||||
| 			mod->connections.push_back(conn); | ||||
| 		} | ||||
| 		if (has_init) { | ||||
| 			RTLIL::SigSig conn(sig_q, val_init); | ||||
| 			mod->connections.push_back(conn); | ||||
| 		} | ||||
| 		goto delete_dff; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -155,6 +173,10 @@ struct OptRmdffPass : public Pass { | |||
| 				continue; | ||||
| 
 | ||||
| 			assign_map.set(mod_it.second); | ||||
| 			dff_init_map.set(mod_it.second); | ||||
| 			for (auto &it : mod_it.second->wires) | ||||
| 				if (it.second->attributes.count("\\init") != 0) | ||||
| 					dff_init_map.add(it.second, it.second->attributes.at("\\init")); | ||||
| 			mux_drivers.clear(); | ||||
| 
 | ||||
| 			std::vector<std::string> dff_list; | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ struct OptShareWorker | |||
| 	RTLIL::Design *design; | ||||
| 	RTLIL::Module *module; | ||||
| 	SigMap assign_map; | ||||
| 	SigMap dff_init_map; | ||||
| 
 | ||||
| 	CellTypes ct; | ||||
| 	int total_count; | ||||
|  | @ -178,6 +179,16 @@ struct OptShareWorker | |||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
| 		if (cell1->type.substr(0, 1) == "$" && conn1.count("\\Q") != 0) { | ||||
| 			std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->connections.at("\\Q")).to_sigbit_vector(); | ||||
| 			std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->connections.at("\\Q")).to_sigbit_vector(); | ||||
| 			for (size_t i = 0; i < q1.size(); i++) | ||||
| 				if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) { | ||||
| 					lt = q1.at(i) < q2.at(i); | ||||
| 					return true; | ||||
| 				} | ||||
| 		} | ||||
| 
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -189,6 +200,9 @@ struct OptShareWorker | |||
| 		if (!ct.cell_known(cell1->type)) | ||||
| 			return cell1 < cell2; | ||||
| 
 | ||||
| 		if (cell1->get_bool_attribute("\\keep") || cell2->get_bool_attribute("\\keep")) | ||||
| 			return cell1 < cell2; | ||||
| 
 | ||||
| 		bool lt; | ||||
| 		if (compare_cell_parameters_and_connections(cell1, cell2, lt)) | ||||
| 			return lt; | ||||
|  | @ -222,6 +236,11 @@ struct OptShareWorker | |||
| 		log("Finding identical cells in module `%s'.\n", module->name.c_str()); | ||||
| 		assign_map.set(module); | ||||
| 
 | ||||
| 		dff_init_map.set(module); | ||||
| 		for (auto &it : module->wires) | ||||
| 			if (it.second->attributes.count("\\init") != 0) | ||||
| 				dff_init_map.add(it.second, it.second->attributes.at("\\init")); | ||||
| 
 | ||||
| 		bool did_something = true; | ||||
| 		while (did_something) | ||||
| 		{ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue