mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-29 18:52:30 +00:00 
			
		
		
		
	Merge pull request #3778 from jix/yw_clk2fflogic
This commit is contained in:
		
						commit
						6f5d984bdb
					
				
					 7 changed files with 70 additions and 17 deletions
				
			
		|  | @ -736,6 +736,9 @@ struct AigerWriter | ||||||
| 				auto sig_qy = cell->getPort(cell->type.in(ID($anyconst), ID($anyseq)) ? ID::Y : ID::Q); | 				auto sig_qy = cell->getPort(cell->type.in(ID($anyconst), ID($anyseq)) ? ID::Y : ID::Q); | ||||||
| 				SigSpec sig = sigmap(sig_qy); | 				SigSpec sig = sigmap(sig_qy); | ||||||
| 
 | 
 | ||||||
|  | 				if (cell->get_bool_attribute(ID(clk2fflogic))) | ||||||
|  | 					sig_qy = cell->getPort(ID::D); // For a clk2fflogic $_FF_ the named signal is the D input not the Q output
 | ||||||
|  | 
 | ||||||
| 				for (int i = 0; i < GetSize(sig_qy); i++) { | 				for (int i = 0; i < GetSize(sig_qy); i++) { | ||||||
| 					if (sig_qy[i].wire == nullptr || sig[i].wire == nullptr) | 					if (sig_qy[i].wire == nullptr || sig[i].wire == nullptr) | ||||||
| 						continue; | 						continue; | ||||||
|  |  | ||||||
|  | @ -728,6 +728,9 @@ struct BtorWorker | ||||||
| 			else | 			else | ||||||
| 				btorf("%d state %d %s\n", nid, sid, log_id(symbol)); | 				btorf("%d state %d %s\n", nid, sid, log_id(symbol)); | ||||||
| 
 | 
 | ||||||
|  | 			if (cell->get_bool_attribute(ID(clk2fflogic))) | ||||||
|  | 				ywmap_state(cell->getPort(ID::D)); // For a clk2fflogic FF the named signal is the D input not the Q output
 | ||||||
|  | 			else | ||||||
| 				ywmap_state(sig_q); | 				ywmap_state(sig_q); | ||||||
| 
 | 
 | ||||||
| 			if (nid_init_val >= 0) { | 			if (nid_init_val >= 0) { | ||||||
|  |  | ||||||
|  | @ -626,8 +626,9 @@ struct Smt2Worker | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				bool init_only = cell->type.in(ID($anyconst), ID($anyinit), ID($allconst)); | 				bool init_only = cell->type.in(ID($anyconst), ID($anyinit), ID($allconst)); | ||||||
|  | 				bool clk2fflogic = cell->type == ID($anyinit) && cell->get_bool_attribute(ID(clk2fflogic)); | ||||||
| 				int smtoffset = 0; | 				int smtoffset = 0; | ||||||
| 				for (auto chunk : cell->getPort(QY).chunks()) { | 				for (auto chunk : cell->getPort(clk2fflogic ? ID::D : QY).chunks()) { | ||||||
| 					if (chunk.is_wire()) | 					if (chunk.is_wire()) | ||||||
| 						decls.push_back(witness_signal(init_only ? "init" : "seq", chunk.width, chunk.offset, "", idcounter, chunk.wire, smtoffset)); | 						decls.push_back(witness_signal(init_only ? "init" : "seq", chunk.width, chunk.offset, "", idcounter, chunk.wire, smtoffset)); | ||||||
| 					smtoffset += chunk.width; | 					smtoffset += chunk.width; | ||||||
|  |  | ||||||
|  | @ -139,7 +139,12 @@ static bool rename_witness(RTLIL::Design *design, dict<RTLIL::Module *, int> &ca | ||||||
| 
 | 
 | ||||||
| 		if (cell->type.in(ID($anyconst), ID($anyseq), ID($anyinit), ID($allconst), ID($allseq))) { | 		if (cell->type.in(ID($anyconst), ID($anyseq), ID($anyinit), ID($allconst), ID($allseq))) { | ||||||
| 			has_witness_signals = true; | 			has_witness_signals = true; | ||||||
| 			auto QY = cell->type == ID($anyinit) ? ID::Q : ID::Y; | 			IdString QY; | ||||||
|  | 			bool clk2fflogic = false; | ||||||
|  | 			if (cell->type == ID($anyinit)) | ||||||
|  | 				QY = (clk2fflogic = cell->get_bool_attribute(ID(clk2fflogic))) ? ID::D : ID::Q; | ||||||
|  | 			else | ||||||
|  | 				QY = ID::Y; | ||||||
| 			auto sig_out = cell->getPort(QY); | 			auto sig_out = cell->getPort(QY); | ||||||
| 
 | 
 | ||||||
| 			for (auto chunk : sig_out.chunks()) { | 			for (auto chunk : sig_out.chunks()) { | ||||||
|  | @ -151,6 +156,9 @@ static bool rename_witness(RTLIL::Design *design, dict<RTLIL::Module *, int> &ca | ||||||
| 					auto new_id = module->uniquify("\\_witness_." + name); | 					auto new_id = module->uniquify("\\_witness_." + name); | ||||||
| 					auto new_wire = module->addWire(new_id, GetSize(sig_out)); | 					auto new_wire = module->addWire(new_id, GetSize(sig_out)); | ||||||
| 					new_wire->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 }); | 					new_wire->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 }); | ||||||
|  | 					if (clk2fflogic) | ||||||
|  | 						module->connect({new_wire, sig_out}); | ||||||
|  | 					else | ||||||
| 						module->connect({sig_out, new_wire}); | 						module->connect({sig_out, new_wire}); | ||||||
| 					cell->setPort(QY, new_wire); | 					cell->setPort(QY, new_wire); | ||||||
| 					break; | 					break; | ||||||
|  |  | ||||||
|  | @ -292,10 +292,12 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos | ||||||
| 	if (!purge_mode) | 	if (!purge_mode) | ||||||
| 		for (auto &it : module->cells_) { | 		for (auto &it : module->cells_) { | ||||||
| 			RTLIL::Cell *cell = it.second; | 			RTLIL::Cell *cell = it.second; | ||||||
| 			if (ct_reg.cell_known(cell->type)) | 			if (ct_reg.cell_known(cell->type)) { | ||||||
|  | 				bool clk2fflogic = cell->get_bool_attribute(ID(clk2fflogic)); | ||||||
| 				for (auto &it2 : cell->connections()) | 				for (auto &it2 : cell->connections()) | ||||||
| 					if (ct_reg.cell_output(cell->type, it2.first)) | 					if (clk2fflogic ? it2.first == ID::D : ct_reg.cell_output(cell->type, it2.first)) | ||||||
| 						register_signals.add(it2.second); | 						register_signals.add(it2.second); | ||||||
|  | 			} | ||||||
| 			for (auto &it2 : cell->connections()) | 			for (auto &it2 : cell->connections()) | ||||||
| 				connected_signals.add(it2.second); | 				connected_signals.add(it2.second); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -80,15 +80,27 @@ struct Clk2fflogicPass : public Pass { | ||||||
| 		return module->Eqx(NEW_ID, {sampled_sig, sig}, polarity ? SigSpec {State::S0, State::S1} : SigSpec {State::S1, State::S0}); | 		return module->Eqx(NEW_ID, {sampled_sig, sig}, polarity ? SigSpec {State::S0, State::S1} : SigSpec {State::S1, State::S0}); | ||||||
| 	} | 	} | ||||||
| 	// Sampled and current value of a data signal.
 | 	// Sampled and current value of a data signal.
 | ||||||
| 	SampledSig sample_data(Module *module, SigSpec sig, RTLIL::Const init, bool is_fine) { | 	SampledSig sample_data(Module *module, SigSpec sig, RTLIL::Const init, bool is_fine, bool set_attribute = false) { | ||||||
| 		std::string sig_str = log_signal(sig); | 		std::string sig_str = log_signal(sig); | ||||||
| 		sig_str.erase(std::remove(sig_str.begin(), sig_str.end(), ' '), sig_str.end()); | 		sig_str.erase(std::remove(sig_str.begin(), sig_str.end(), ' '), sig_str.end()); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 		Wire *sampled_sig = module->addWire(NEW_ID_SUFFIX(stringf("%s#sampled", sig_str.c_str())), GetSize(sig)); | 		Wire *sampled_sig = module->addWire(NEW_ID_SUFFIX(stringf("%s#sampled", sig_str.c_str())), GetSize(sig)); | ||||||
| 		sampled_sig->attributes[ID::init] = init; | 		sampled_sig->attributes[ID::init] = init; | ||||||
|  | 
 | ||||||
|  | 		Cell *cell; | ||||||
| 		if (is_fine) | 		if (is_fine) | ||||||
| 			module->addFfGate(NEW_ID, sig, sampled_sig); | 			cell = module->addFfGate(NEW_ID, sig, sampled_sig); | ||||||
| 		else | 		else | ||||||
| 			module->addFf(NEW_ID, sig, sampled_sig); | 			cell = module->addFf(NEW_ID, sig, sampled_sig); | ||||||
|  | 
 | ||||||
|  | 		if (set_attribute) { | ||||||
|  | 			for (auto &chunk : sig.chunks()) | ||||||
|  | 				if (chunk.wire != nullptr) | ||||||
|  | 					chunk.wire->set_bool_attribute(ID::keep); | ||||||
|  | 			cell->set_bool_attribute(ID(clk2fflogic)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return {sampled_sig, sig}; | 		return {sampled_sig, sig}; | ||||||
| 	} | 	} | ||||||
| 	SigSpec mux(Module *module, SigSpec a, SigSpec b, SigSpec s, bool is_fine) { | 	SigSpec mux(Module *module, SigSpec a, SigSpec b, SigSpec s, bool is_fine) { | ||||||
|  | @ -213,7 +225,7 @@ struct Clk2fflogicPass : public Pass { | ||||||
| 					if (ff.has_clk) | 					if (ff.has_clk) | ||||||
| 						ff.unmap_ce_srst(); | 						ff.unmap_ce_srst(); | ||||||
| 
 | 
 | ||||||
| 					auto next_q = sample_data(module, ff.sig_q, ff.val_init, ff.is_fine).sampled; | 					auto next_q = sample_data(module, ff.sig_q, ff.val_init, ff.is_fine, true).sampled; | ||||||
| 
 | 
 | ||||||
| 					if (ff.has_clk) { | 					if (ff.has_clk) { | ||||||
| 						// The init value for the sampled d is never used, so we can set it to fixed zero, reducing uninit'd FFs
 | 						// The init value for the sampled d is never used, so we can set it to fixed zero, reducing uninit'd FFs
 | ||||||
|  |  | ||||||
|  | @ -140,6 +140,7 @@ struct SimInstance | ||||||
| 	dict<SigBit, pool<Wire*>> upd_outports; | 	dict<SigBit, pool<Wire*>> upd_outports; | ||||||
| 
 | 
 | ||||||
| 	dict<SigBit, SigBit> in_parent_drivers; | 	dict<SigBit, SigBit> in_parent_drivers; | ||||||
|  | 	dict<SigBit, SigBit> clk2fflogic_drivers; | ||||||
| 
 | 
 | ||||||
| 	pool<SigBit> dirty_bits; | 	pool<SigBit> dirty_bits; | ||||||
| 	pool<Cell*> dirty_cells; | 	pool<Cell*> dirty_cells; | ||||||
|  | @ -270,6 +271,11 @@ struct SimInstance | ||||||
| 				ff.past_srst = State::Sx; | 				ff.past_srst = State::Sx; | ||||||
| 				ff.data = ff_data; | 				ff.data = ff_data; | ||||||
| 				ff_database[cell] = ff; | 				ff_database[cell] = ff; | ||||||
|  | 
 | ||||||
|  | 				if (cell->get_bool_attribute(ID(clk2fflogic))) { | ||||||
|  | 					for (int i = 0; i < ff_data.width; i++) | ||||||
|  | 						clk2fflogic_drivers.emplace(sigmap(ff_data.sig_d[i]), sigmap(ff_data.sig_q[i])); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (cell->is_mem_cell()) | 			if (cell->is_mem_cell()) | ||||||
|  | @ -389,6 +395,10 @@ struct SimInstance | ||||||
| 			auto sigbit = sig[i]; | 			auto sigbit = sig[i]; | ||||||
| 			auto sigval = value[i]; | 			auto sigval = value[i]; | ||||||
| 
 | 
 | ||||||
|  | 			auto clk2fflogic_driver = clk2fflogic_drivers.find(sigbit); | ||||||
|  | 			if (clk2fflogic_driver != clk2fflogic_drivers.end()) | ||||||
|  | 				sigbit = clk2fflogic_driver->second; | ||||||
|  | 
 | ||||||
| 			auto in_parent_driver = in_parent_drivers.find(sigbit); | 			auto in_parent_driver = in_parent_drivers.find(sigbit); | ||||||
| 			if (in_parent_driver == in_parent_drivers.end()) | 			if (in_parent_driver == in_parent_drivers.end()) | ||||||
| 				set_state(sigbit, sigval); | 				set_state(sigbit, sigval); | ||||||
|  | @ -589,7 +599,7 @@ struct SimInstance | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool update_ph2(bool gclk) | 	bool update_ph2(bool gclk, bool stable_past_update = false) | ||||||
| 	{ | 	{ | ||||||
| 		bool did_something = false; | 		bool did_something = false; | ||||||
| 
 | 
 | ||||||
|  | @ -600,7 +610,7 @@ struct SimInstance | ||||||
| 
 | 
 | ||||||
| 			Const current_q = get_state(ff.data.sig_q); | 			Const current_q = get_state(ff.data.sig_q); | ||||||
| 
 | 
 | ||||||
| 			if (ff_data.has_clk) { | 			if (ff_data.has_clk && !stable_past_update) { | ||||||
| 				// flip-flops
 | 				// flip-flops
 | ||||||
| 				State current_clk = get_state(ff_data.sig_clk)[0]; | 				State current_clk = get_state(ff_data.sig_clk)[0]; | ||||||
| 				if (ff_data.pol_clk ? (ff.past_clk == State::S0 && current_clk != State::S0) : | 				if (ff_data.pol_clk ? (ff.past_clk == State::S0 && current_clk != State::S0) : | ||||||
|  | @ -621,7 +631,7 @@ struct SimInstance | ||||||
| 			if (ff_data.has_aload) { | 			if (ff_data.has_aload) { | ||||||
| 				State current_aload = get_state(ff_data.sig_aload)[0]; | 				State current_aload = get_state(ff_data.sig_aload)[0]; | ||||||
| 				if (current_aload == (ff_data.pol_aload ? State::S1 : State::S0)) { | 				if (current_aload == (ff_data.pol_aload ? State::S1 : State::S0)) { | ||||||
| 					current_q = ff_data.has_clk ? ff.past_ad : get_state(ff.data.sig_ad); | 					current_q = ff_data.has_clk && !stable_past_update ? ff.past_ad : get_state(ff.data.sig_ad); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			// async reset
 | 			// async reset
 | ||||||
|  | @ -672,6 +682,8 @@ struct SimInstance | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
|  | 					if (stable_past_update) | ||||||
|  | 						continue; | ||||||
| 					if (port.clk_polarity ? | 					if (port.clk_polarity ? | ||||||
| 							(mdb.past_wr_clk[port_idx] == State::S1 || get_state(port.clk) != State::S1) : | 							(mdb.past_wr_clk[port_idx] == State::S1 || get_state(port.clk) != State::S1) : | ||||||
| 							(mdb.past_wr_clk[port_idx] == State::S0 || get_state(port.clk) != State::S0)) | 							(mdb.past_wr_clk[port_idx] == State::S0 || get_state(port.clk) != State::S0)) | ||||||
|  | @ -701,7 +713,7 @@ struct SimInstance | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto it : children) | 		for (auto it : children) | ||||||
| 			if (it.second->update_ph2(gclk)) { | 			if (it.second->update_ph2(gclk, stable_past_update)) { | ||||||
| 				dirty_children.insert(it.second); | 				dirty_children.insert(it.second); | ||||||
| 				did_something = true; | 				did_something = true; | ||||||
| 			} | 			} | ||||||
|  | @ -1196,10 +1208,22 @@ struct SimWorker : SimShared | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void initialize_stable_past() | 	void initialize_stable_past() | ||||||
|  | 	{ | ||||||
|  | 
 | ||||||
|  | 		while (1) | ||||||
| 		{ | 		{ | ||||||
| 			if (debug) | 			if (debug) | ||||||
| 				log("\n-- ph1 (initialize) --\n"); | 				log("\n-- ph1 (initialize) --\n"); | ||||||
|  | 
 | ||||||
| 			top->update_ph1(); | 			top->update_ph1(); | ||||||
|  | 
 | ||||||
|  | 			if (debug) | ||||||
|  | 				log("\n-- ph2 (initialize) --\n"); | ||||||
|  | 
 | ||||||
|  | 			if (!top->update_ph2(false, true)) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if (debug) | 		if (debug) | ||||||
| 			log("\n-- ph3 (initialize) --\n"); | 			log("\n-- ph3 (initialize) --\n"); | ||||||
| 		top->update_ph3(true); | 		top->update_ph3(true); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue