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; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	SigSpec sig_e; | ||||
|  | @ -287,6 +456,7 @@ struct OptRmdffPass : public Pass { | |||
| 			mux_drivers.clear(); | ||||
| 
 | ||||
| 			std::vector<RTLIL::IdString> dff_list; | ||||
| 			std::vector<RTLIL::IdString> dffsr_list; | ||||
| 			std::vector<RTLIL::IdString> dlatch_list; | ||||
| 			for (auto cell : module->cells()) | ||||
| 			{ | ||||
|  | @ -304,6 +474,12 @@ struct OptRmdffPass : public Pass { | |||
| 				if (!design->selected(module, cell)) | ||||
| 					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_", | ||||
| 						"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", | ||||
| 						"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", | ||||
|  | @ -314,6 +490,12 @@ struct OptRmdffPass : public Pass { | |||
| 					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) { | ||||
| 				if (module->cell(id) != nullptr && | ||||
| 						handle_dff(module, module->cells_[id])) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue