mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Add support for set-reset cell variants to opt_rmdff
This commit is contained in:
		
							parent
							
								
									159701962a
								
							
						
					
					
						commit
						007f29b9c2
					
				
					 1 changed files with 182 additions and 0 deletions
				
			
		|  | @ -39,6 +39,175 @@ void remove_init_attr(SigSpec sig) | ||||||
| 				wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx; | 				wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) | ||||||
|  | { | ||||||
|  | 	SigSpec sig_set, sig_clr; | ||||||
|  | 	State pol_set, pol_clr; | ||||||
|  | 
 | ||||||
|  | 	if (cell->hasPort("\\S")) | ||||||
|  | 		sig_set = cell->getPort("\\S"); | ||||||
|  | 
 | ||||||
|  | 	if (cell->hasPort("\\R")) | ||||||
|  | 		sig_clr = cell->getPort("\\R"); | ||||||
|  | 
 | ||||||
|  | 	if (cell->hasPort("\\SET")) | ||||||
|  | 		sig_set = cell->getPort("\\SET"); | ||||||
|  | 
 | ||||||
|  | 	if (cell->hasPort("\\CLR")) | ||||||
|  | 		sig_clr = cell->getPort("\\CLR"); | ||||||
|  | 
 | ||||||
|  | 	log_assert(GetSize(sig_set) == GetSize(sig_clr)); | ||||||
|  | 
 | ||||||
|  | 	if (cell->type.substr(0,8) == "$_DFFSR_") { | ||||||
|  | 		pol_set = cell->type[9] == 'P' ? State::S1 : State::S0; | ||||||
|  | 		pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0; | ||||||
|  | 	} else | ||||||
|  | 	if (cell->type.substr(0,11) == "$_DLATCHSR_") { | ||||||
|  | 		pol_set = cell->type[12] == 'P' ? State::S1 : State::S0; | ||||||
|  | 		pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0; | ||||||
|  | 	} else | ||||||
|  | 	if (cell->type == "$dffsr" || cell->type == "$dlatchsr") { | ||||||
|  | 		pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0; | ||||||
|  | 		pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0; | ||||||
|  | 	} else | ||||||
|  | 		log_abort(); | ||||||
|  | 
 | ||||||
|  | 	State npol_set = pol_set == State::S0 ? State::S1 : State::S0; | ||||||
|  | 	State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0; | ||||||
|  | 
 | ||||||
|  | 	SigSpec sig_d = cell->getPort("\\D"); | ||||||
|  | 	SigSpec sig_q = cell->getPort("\\Q"); | ||||||
|  | 
 | ||||||
|  | 	bool did_something = false; | ||||||
|  | 	bool proper_sr = false; | ||||||
|  | 	bool used_pol_set = false; | ||||||
|  | 	bool used_pol_clr = false; | ||||||
|  | 	bool hasreset = false; | ||||||
|  | 	Const reset_val; | ||||||
|  | 	SigSpec sig_reset; | ||||||
|  | 
 | ||||||
|  | 	for (int i = 0; i < GetSize(sig_set); i++) | ||||||
|  | 	{ | ||||||
|  | 		SigBit s = sig_set[i], c = sig_clr[i]; | ||||||
|  | 
 | ||||||
|  | 		if (s != npol_set || c != npol_clr) | ||||||
|  | 			hasreset = true; | ||||||
|  | 
 | ||||||
|  | 		if (s == pol_set || c == pol_clr) | ||||||
|  | 		{ | ||||||
|  | 			log("Constantly %s Q bit %s for SR cell %s (%s) from module %s.\n", | ||||||
|  | 					s == pol_set ? "set" : "cleared", log_signal(sig_q[i]), | ||||||
|  | 					log_id(cell), log_id(cell->type), log_id(mod)); | ||||||
|  | 
 | ||||||
|  | 			remove_init_attr(sig_q[i]); | ||||||
|  | 			mod->connect(sig_q[i], s == pol_set ? State::S1 : State::S0); | ||||||
|  | 			sig_set.remove(i); | ||||||
|  | 			sig_clr.remove(i); | ||||||
|  | 			sig_d.remove(i); | ||||||
|  | 			sig_q.remove(i--); | ||||||
|  | 			did_something = true; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (sig_reset.empty() && s.wire != nullptr) sig_reset = s; | ||||||
|  | 		if (sig_reset.empty() && c.wire != nullptr) sig_reset = c; | ||||||
|  | 
 | ||||||
|  | 		if (s.wire != nullptr && s != sig_reset) proper_sr = true; | ||||||
|  | 		if (c.wire != nullptr && c != sig_reset) proper_sr = true; | ||||||
|  | 
 | ||||||
|  | 		if ((s.wire == nullptr) != (c.wire == nullptr)) { | ||||||
|  | 			if (s.wire != nullptr) used_pol_set = true; | ||||||
|  | 			if (c.wire != nullptr) used_pol_clr = true; | ||||||
|  | 			reset_val.bits.push_back(c.wire == nullptr ? State::S1 : State::S0); | ||||||
|  | 		} else | ||||||
|  | 			proper_sr = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!hasreset) | ||||||
|  | 		proper_sr = false; | ||||||
|  | 
 | ||||||
|  | 	if (GetSize(sig_set) == 0) | ||||||
|  | 	{ | ||||||
|  | 		log("Removing %s (%s) from module %s.\n", log_id(cell), log_id(cell->type), log_id(mod)); | ||||||
|  | 		mod->remove(cell); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (cell->type == "$dffsr" || cell->type == "$dlatchsr") | ||||||
|  | 	{ | ||||||
|  | 		cell->setParam("\\WIDTH", GetSize(sig_d)); | ||||||
|  | 		cell->setPort("\\SET", sig_set); | ||||||
|  | 		cell->setPort("\\CLR", sig_clr); | ||||||
|  | 		cell->setPort("\\D", sig_d); | ||||||
|  | 		cell->setPort("\\Q", sig_q); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		cell->setPort("\\S", sig_set); | ||||||
|  | 		cell->setPort("\\R", sig_clr); | ||||||
|  | 		cell->setPort("\\D", sig_d); | ||||||
|  | 		cell->setPort("\\Q", sig_q); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (proper_sr) | ||||||
|  | 		return did_something; | ||||||
|  | 
 | ||||||
|  | 	if (used_pol_set && used_pol_clr && pol_set != pol_clr) | ||||||
|  | 		return did_something; | ||||||
|  | 
 | ||||||
|  | 	State unified_pol = used_pol_set ? pol_set : pol_clr; | ||||||
|  | 
 | ||||||
|  | 	if (cell->type == "$dffsr") | ||||||
|  | 	{ | ||||||
|  | 		if (hasreset) | ||||||
|  | 		{ | ||||||
|  | 			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod)); | ||||||
|  | 
 | ||||||
|  | 			cell->type = "$adff"; | ||||||
|  | 			cell->setParam("\\ARST_POLARITY", unified_pol); | ||||||
|  | 			cell->setParam("\\ARST_VALUE", reset_val); | ||||||
|  | 			cell->setPort("\\ARST", sig_reset); | ||||||
|  | 
 | ||||||
|  | 			cell->unsetParam("\\SET_POLARITY"); | ||||||
|  | 			cell->unsetParam("\\CLR_POLARITY"); | ||||||
|  | 			cell->unsetPort("\\SET"); | ||||||
|  | 			cell->unsetPort("\\CLR"); | ||||||
|  | 
 | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod)); | ||||||
|  | 
 | ||||||
|  | 			cell->type = "$dff"; | ||||||
|  | 			cell->unsetParam("\\SET_POLARITY"); | ||||||
|  | 			cell->unsetParam("\\CLR_POLARITY"); | ||||||
|  | 			cell->unsetPort("\\SET"); | ||||||
|  | 			cell->unsetPort("\\CLR"); | ||||||
|  | 
 | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		IdString new_type; | ||||||
|  | 
 | ||||||
|  | 		if (cell->type.substr(0,8) == "$_DFFSR_") | ||||||
|  | 			new_type = stringf("$_DFF_%c_", cell->type[8]); | ||||||
|  | 		else if (cell->type.substr(0,11) == "$_DLATCHSR_") | ||||||
|  | 			new_type = stringf("$_DLATCH_%c_", cell->type[11]); | ||||||
|  | 		else | ||||||
|  | 			log_abort(); | ||||||
|  | 
 | ||||||
|  | 		log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod)); | ||||||
|  | 
 | ||||||
|  | 		cell->type = new_type; | ||||||
|  | 		cell->unsetPort("\\S"); | ||||||
|  | 		cell->unsetPort("\\R"); | ||||||
|  | 
 | ||||||
|  | 		return did_something; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) | bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) | ||||||
| { | { | ||||||
| 	SigSpec sig_e; | 	SigSpec sig_e; | ||||||
|  | @ -287,6 +456,7 @@ struct OptRmdffPass : public Pass { | ||||||
| 			mux_drivers.clear(); | 			mux_drivers.clear(); | ||||||
| 
 | 
 | ||||||
| 			std::vector<RTLIL::IdString> dff_list; | 			std::vector<RTLIL::IdString> dff_list; | ||||||
|  | 			std::vector<RTLIL::IdString> dffsr_list; | ||||||
| 			std::vector<RTLIL::IdString> dlatch_list; | 			std::vector<RTLIL::IdString> dlatch_list; | ||||||
| 			for (auto cell : module->cells()) | 			for (auto cell : module->cells()) | ||||||
| 			{ | 			{ | ||||||
|  | @ -304,6 +474,12 @@ struct OptRmdffPass : public Pass { | ||||||
| 				if (!design->selected(module, cell)) | 				if (!design->selected(module, cell)) | ||||||
| 					continue; | 					continue; | ||||||
| 
 | 
 | ||||||
|  | 				if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_", | ||||||
|  | 						"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr", | ||||||
|  | 						"$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_", | ||||||
|  | 						"$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr")) | ||||||
|  | 					dffsr_list.push_back(cell->name); | ||||||
|  | 
 | ||||||
| 				if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_", | 				if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_", | ||||||
| 						"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", | 						"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", | ||||||
| 						"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", | 						"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", | ||||||
|  | @ -314,6 +490,12 @@ struct OptRmdffPass : public Pass { | ||||||
| 					dlatch_list.push_back(cell->name); | 					dlatch_list.push_back(cell->name); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			for (auto &id : dffsr_list) { | ||||||
|  | 				if (module->cell(id) != nullptr && | ||||||
|  | 						handle_dffsr(module, module->cells_[id])) | ||||||
|  | 					total_count++; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			for (auto &id : dff_list) { | 			for (auto &id : dff_list) { | ||||||
| 				if (module->cell(id) != nullptr && | 				if (module->cell(id) != nullptr && | ||||||
| 						handle_dff(module, module->cells_[id])) | 						handle_dff(module, module->cells_[id])) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue