diff options
Diffstat (limited to 'passes')
| -rw-r--r-- | passes/opt/opt_rmdff.cc | 36 | ||||
| -rw-r--r-- | passes/opt/opt_share.cc | 19 | 
2 files changed, 48 insertions, 7 deletions
diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index a8e2c4121..02b7f77e7 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -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; diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 43d1a57e1..eb639d8ab 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -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)  		{  | 
