diff options
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/aiger/aiger.cc | 112 | ||||
| -rw-r--r-- | backends/smt2/smt2.cc | 275 | ||||
| -rw-r--r-- | backends/smt2/smtbmc.py | 8 | ||||
| -rw-r--r-- | backends/smt2/smtio.py | 2 | 
4 files changed, 325 insertions, 72 deletions
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index ab1fba6f1..02871a6fd 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -46,11 +46,13 @@ struct AigerWriter  	dict<SigBit, SigBit> not_map, ff_map;  	dict<SigBit, pair<SigBit, SigBit>> and_map;  	vector<pair<SigBit, SigBit>> asserts, assumes; +	vector<pair<SigBit, SigBit>> liveness, fairness;  	pool<SigBit> initstate_bits;  	vector<pair<int, int>> aig_gates;  	vector<int> aig_latchin, aig_latchinit, aig_outputs; -	int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0, aig_b = 0, aig_c = 0; +	int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; +	int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0;  	dict<SigBit, int> aig_map;  	dict<SigBit, int> ordered_outputs; @@ -163,6 +165,22 @@ struct AigerWriter  				continue;  			} +			if (cell->type == "$live") +			{ +				SigBit A = sigmap(cell->getPort("\\A").as_bit()); +				SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); +				liveness.push_back(make_pair(A, EN)); +				continue; +			} + +			if (cell->type == "$fair") +			{ +				SigBit A = sigmap(cell->getPort("\\A").as_bit()); +				SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); +				fairness.push_back(make_pair(A, EN)); +				continue; +			} +  			if (cell->type == "$anyconst")  			{  				for (auto bit : sigmap(cell->getPort("\\Y"))) @@ -198,6 +216,12 @@ struct AigerWriter  			}  		} +		int fair_live_inputs_cnt = GetSize(liveness); +		int fair_live_inputs_m = aig_m; + +		aig_m += fair_live_inputs_cnt; +		aig_i += fair_live_inputs_cnt; +  		for (auto it : ff_map) {  			aig_m++, aig_l++;  			aig_map[it.first] = 2*aig_m; @@ -214,6 +238,16 @@ struct AigerWriter  			aig_latchinit.push_back(0);  		} +		int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness); +		int fair_live_latches_m = aig_m; +		int fair_live_latches_l = aig_l; + +		aig_m += fair_live_latches_cnt; +		aig_l += fair_live_latches_cnt; + +		for (int i = 0; i < fair_live_latches_cnt; i++) +			aig_latchinit.push_back(0); +  		if (zinit_mode)  		{  			for (auto it : ff_map) @@ -263,23 +297,67 @@ struct AigerWriter  			int bit_en = bit2aig(it.second);  			aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1);  		} + +		for (auto it : liveness) +		{ +			int input_m = ++fair_live_inputs_m; +			int latch_m1 = ++fair_live_latches_m; +			int latch_m2 = ++fair_live_latches_m; + +			log_assert(GetSize(aig_latchin) == fair_live_latches_l); +			fair_live_latches_l += 2; + +			int bit_a = bit2aig(it.first); +			int bit_en = bit2aig(it.second); +			int bit_s = 2*input_m; +			int bit_q1 = 2*latch_m1; +			int bit_q2 = 2*latch_m2; + +			int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1; +			int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1; + +			aig_j++; +			aig_latchin.push_back(bit_d1); +			aig_latchin.push_back(bit_d2); +			aig_outputs.push_back(mkgate(bit_q1, bit_q2^1)); +		} + +		for (auto it : fairness) +		{ +			int latch_m = ++fair_live_latches_m; + +			log_assert(GetSize(aig_latchin) == fair_live_latches_l); +			fair_live_latches_l += 1; + +			int bit_a = bit2aig(it.first); +			int bit_en = bit2aig(it.second); +			int bit_q = 2*latch_m; + +			aig_f++; +			aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1)); +			aig_outputs.push_back(bit_q^1); +		}  	}  	void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode)  	{ +		int aig_obc = aig_o + aig_b + aig_c; +		int aig_obcj = aig_obc + aig_j; +		int aig_obcjf = aig_obcj + aig_f; +  		log_assert(aig_m == aig_i + aig_l + aig_a);  		log_assert(aig_l == GetSize(aig_latchin));  		log_assert(aig_l == GetSize(aig_latchinit)); -		log_assert((aig_o + aig_b + aig_c) == GetSize(aig_outputs)); +		log_assert(aig_obcjf == GetSize(aig_outputs));  		if (miter_mode) { -			if (aig_b || aig_c) -				log_error("Running AIGER back-end in -miter mode, but design contains $assert and/or $assume cells!\n"); +			if (aig_b || aig_c || aig_j || aig_f) +				log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n");  			f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o);  		} else {  			f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); -			if (aig_b || aig_c) -				f << stringf(" %d %d", aig_b, aig_c); +			if (aig_b || aig_c || aig_j || aig_f) +				f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f);  			f << stringf("\n");  		} @@ -297,7 +375,16 @@ struct AigerWriter  					f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2);  			} -			for (int i = 0; i < aig_o + aig_b + aig_c; i++) +			for (int i = 0; i < aig_obc; i++) +				f << stringf("%d\n", aig_outputs.at(i)); + +			for (int i = aig_obc; i < aig_obcj; i++) +				f << stringf("1\n"); + +			for (int i = aig_obc; i < aig_obcj; i++) +				f << stringf("%d\n", aig_outputs.at(i)); + +			for (int i = aig_obcj; i < aig_obcjf; i++)  				f << stringf("%d\n", aig_outputs.at(i));  			for (int i = 0; i < aig_a; i++) @@ -314,7 +401,16 @@ struct AigerWriter  					f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2);  			} -			for (int i = 0; i < aig_o + aig_b + aig_c; i++) +			for (int i = 0; i < aig_obc; i++) +				f << stringf("%d\n", aig_outputs.at(i)); + +			for (int i = aig_obc; i < aig_obcj; i++) +				f << stringf("1\n"); + +			for (int i = aig_obc; i < aig_obcj; i++) +				f << stringf("%d\n", aig_outputs.at(i)); + +			for (int i = aig_obcj; i < aig_obcjf; i++)  				f << stringf("%d\n", aig_outputs.at(i));  			for (int i = 0; i < aig_a; i++) { diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 932f5cd68..6c2100f05 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -32,8 +32,9 @@ struct Smt2Worker  	CellTypes ct;  	SigMap sigmap;  	RTLIL::Module *module; -	bool bvmode, memmode, wiresmode, verbose; -	int idcounter; +	bool bvmode, memmode, wiresmode, verbose, statebv; +	dict<IdString, int> &mod_stbv_width; +	int idcounter, statebv_width;  	std::vector<std::string> decls, trans, hier;  	std::map<RTLIL::SigBit, RTLIL::Cell*> bit_driver; @@ -63,12 +64,39 @@ struct Smt2Worker  		return get_id(obj->name);  	} -	Smt2Worker(RTLIL::Module *module, bool bvmode, bool memmode, bool wiresmode, bool verbose) : -			ct(module->design), sigmap(module), module(module), bvmode(bvmode), memmode(memmode), -			wiresmode(wiresmode), verbose(verbose), idcounter(0) +	void makebits(std::string name, int width = 0, std::string comment = std::string())  	{ -		decls.push_back(stringf("(declare-sort |%s_s| 0)\n", get_id(module))); -		decls.push_back(stringf("(declare-fun |%s_is| (|%s_s|) Bool)\n", get_id(module), get_id(module))); +		std::string decl_str; + +		if (statebv) +		{ +			if (width == 0) { +				decl_str = stringf("(define-fun |%s| ((state |%s_s|)) Bool (= ((_ extract %d %d) state) #b1))", name.c_str(), get_id(module), statebv_width, statebv_width); +				statebv_width += 1; +			} else { +				decl_str = stringf("(define-fun |%s| ((state |%s_s|)) (_ BitVec %d) ((_ extract %d %d) state))", name.c_str(), get_id(module), width, statebv_width+width-1, statebv_width); +				statebv_width += width; +			} +		} +		else +		{ +			if (width == 0) { +				decl_str = stringf("(declare-fun |%s| (|%s_s|) Bool)\n", name.c_str(), get_id(module)); +			} else { +				decl_str = stringf("(declare-fun |%s| (|%s_s|) (_ BitVec %d))", name.c_str(), get_id(module), width); +			} +		} + +		if (!comment.empty()) +			decl_str += " ; " + comment; +		decls.push_back(decl_str + "\n"); +	} + +	Smt2Worker(RTLIL::Module *module, bool bvmode, bool memmode, bool wiresmode, bool verbose, bool statebv, dict<IdString, int> &mod_stbv_width) : +			ct(module->design), sigmap(module), module(module), bvmode(bvmode), memmode(memmode), wiresmode(wiresmode), +			verbose(verbose), statebv(statebv), mod_stbv_width(mod_stbv_width), idcounter(0), statebv_width(0) +	{ +		makebits(stringf("%s_is", get_id(module)));  		for (auto cell : module->cells())  		for (auto &conn : cell->connections()) { @@ -162,8 +190,7 @@ struct Smt2Worker  		if (fcache.count(bit) == 0) {  			if (verbose) log("%*s-> external bool: %s\n", 2+2*GetSize(recursive_cells), "",  					log_signal(bit)); -			decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n", -					get_id(module), idcounter, get_id(module), log_signal(bit))); +			makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(bit));  			register_bool(bit, idcounter++);  		} @@ -237,8 +264,7 @@ struct Smt2Worker  					log_signal(sig.extract(i, j)));  			for (auto bit : sig.extract(i, j))  				log_assert(bit_driver.count(bit) == 0); -			decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n", -					get_id(module), idcounter, get_id(module), j, log_signal(sig.extract(i, j)))); +			makebits(stringf("%s#%d", get_id(module), idcounter), j, log_signal(sig.extract(i, j)));  			subexpr.push_back(stringf("(|%s#%d| %s)", get_id(module), idcounter, state_name));  			register_bv(sig.extract(i, j), idcounter++);  		} @@ -382,8 +408,7 @@ struct Smt2Worker  		if (cell->type.in("$_FF_", "$_DFF_P_", "$_DFF_N_"))  		{  			registers.insert(cell); -			decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n", -					get_id(module), idcounter, get_id(module), log_signal(cell->getPort("\\Q")))); +			makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(cell->getPort("\\Q")));  			register_bool(cell->getPort("\\Q"), idcounter++);  			recursive_cells.erase(cell);  			return; @@ -410,8 +435,7 @@ struct Smt2Worker  			if (cell->type.in("$ff", "$dff"))  			{  				registers.insert(cell); -				decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n", -						get_id(module), idcounter, get_id(module), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q")))); +				makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q")));  				register_bv(cell->getPort("\\Q"), idcounter++);  				recursive_cells.erase(cell);  				return; @@ -422,8 +446,7 @@ struct Smt2Worker  				registers.insert(cell);  				decls.push_back(stringf("; yosys-smt2-%s %s#%d %s\n", cell->type.c_str() + 1, get_id(module), idcounter,  						cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell))); -				decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n", -						get_id(module), idcounter, get_id(module), GetSize(cell->getPort("\\Y")), log_signal(cell->getPort("\\Y")))); +				makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort("\\Y")), log_signal(cell->getPort("\\Y")));  				register_bv(cell->getPort("\\Y"), idcounter++);  				recursive_cells.erase(cell);  				return; @@ -513,30 +536,80 @@ struct Smt2Worker  			int abits = cell->getParam("\\ABITS").as_int();  			int width = cell->getParam("\\WIDTH").as_int();  			int rd_ports = cell->getParam("\\RD_PORTS").as_int(); +			int wr_ports = cell->getParam("\\WR_PORTS").as_int(); + +			decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d\n", get_id(cell), abits, width, rd_ports, wr_ports)); + +			if (statebv) +			{ +				int mem_size = cell->getParam("\\SIZE").as_int(); +				int mem_offset = cell->getParam("\\OFFSET").as_int(); + +				makebits(stringf("%s#%d#0", get_id(module), arrayid), width*mem_size, get_id(cell)); + +				decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d#0| state))\n", +						get_id(module), get_id(cell), get_id(module), width*mem_size, get_id(module), arrayid)); + +				for (int i = 0; i < rd_ports; i++) +				{ +					SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits); +					SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width); +					std::string addr = get_bv(addr_sig); + +					if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool()) +						log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " +								"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module)); + +					decls.push_back(stringf("(define-fun |%s_m:%d %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +							get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); + +					std::string read_expr = "#b"; +					for (int k = 0; k < width; k++) +						read_expr += "0"; -			decls.push_back(stringf("(declare-fun |%s#%d#0| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", -					get_id(module), arrayid, get_id(module), abits, width, get_id(cell))); +					for (int k = 0; k < mem_size; k++) +						read_expr = stringf("(ite (= (|%s_m:%d %s| state) #b%s) ((_ extract %d %d) (|%s#%d#0| state))\n  %s)", +								get_id(module), i, get_id(cell), Const(k+mem_offset, abits).as_string().c_str(), +								width*(k+1)-1, width*k, get_id(module), arrayid, read_expr.c_str()); -			decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d\n", get_id(cell), abits, width, rd_ports)); -			decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) (|%s#%d#0| state))\n", -					get_id(module), get_id(cell), get_id(module), abits, width, get_id(module), arrayid)); +					decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d)\n  %s) ; %s\n", +							get_id(module), idcounter, get_id(module), width, read_expr.c_str(), log_signal(data_sig))); -			for (int i = 0; i < rd_ports; i++) +					decls.push_back(stringf("(define-fun |%s_m:%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n", +							get_id(module), i, get_id(cell), get_id(module), width, get_id(module), idcounter)); + +					register_bv(data_sig, idcounter++); +				} +			} +			else  			{ -				SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits); -				SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width); -				std::string addr = get_bv(addr_sig); +				decls.push_back(stringf("(declare-fun |%s#%d#0| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", +						get_id(module), arrayid, get_id(module), abits, width, get_id(cell))); + +				decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) (|%s#%d#0| state))\n", +						get_id(module), get_id(cell), get_id(module), abits, width, get_id(module), arrayid)); + +				for (int i = 0; i < rd_ports; i++) +				{ +					SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits); +					SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width); +					std::string addr = get_bv(addr_sig); -				if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool()) -					log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " -							"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module)); +					if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool()) +						log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " +								"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module)); -				decls.push_back(stringf("(define-fun |%s_m:%d %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", -						get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); +					decls.push_back(stringf("(define-fun |%s_m:%d %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +							get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); -				decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) (select (|%s#%d#0| state) %s)) ; %s\n", -						get_id(module), idcounter, get_id(module), width, get_id(module), arrayid, addr.c_str(), log_signal(data_sig))); -				register_bv(data_sig, idcounter++); +					decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) (select (|%s#%d#0| state) (|%s_m:%d %s| state))) ; %s\n", +							get_id(module), idcounter, get_id(module), width, get_id(module), arrayid, get_id(module), i, get_id(cell), log_signal(data_sig))); + +					decls.push_back(stringf("(define-fun |%s_m:%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n", +							get_id(module), i, get_id(cell), get_id(module), width, get_id(module), idcounter)); + +					register_bv(data_sig, idcounter++); +				}  			}  			registers.insert(cell); @@ -559,26 +632,26 @@ struct Smt2Worker  				if (w->port_output && !w->port_input) {  					if (GetSize(w) > 1) {  						if (bvmode) { -							decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n", -									get_id(module), idcounter, get_id(module), GetSize(w), log_signal(sig))); +							makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(w), log_signal(sig));  							register_bv(sig, idcounter++);  						} else {  							for (int i = 0; i < GetSize(w); i++) { -								decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n", -										get_id(module), idcounter, get_id(module), log_signal(sig[i]))); +								makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(sig[i]));  								register_bool(sig[i], idcounter++);  							}  						}  					} else { -						decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n", -								get_id(module), idcounter, get_id(module), log_signal(sig))); +						makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(sig));  						register_bool(sig, idcounter++);  					}  				}  			} -			decls.push_back(stringf("(declare-fun |%s_h %s| (|%s_s|) |%s_s|)\n", -					get_id(module), get_id(cell->name), get_id(module), get_id(cell->type))); +			if (statebv) +				makebits(stringf("%s_h %s", get_id(module), get_id(cell->name)), mod_stbv_width.at(cell->type)); +			else +				decls.push_back(stringf("(declare-fun |%s_h %s| (|%s_s|) |%s_s|)\n", +						get_id(module), get_id(cell->name), get_id(module), get_id(cell->type)));  			hiercells.insert(cell);  			hiercells_queue.insert(cell); @@ -719,21 +792,82 @@ struct Smt2Worker  					int abits = cell->getParam("\\ABITS").as_int();  					int width = cell->getParam("\\WIDTH").as_int(); +					int rd_ports = cell->getParam("\\RD_PORTS").as_int();  					int wr_ports = cell->getParam("\\WR_PORTS").as_int(); -					for (int i = 0; i < wr_ports; i++) +					if (statebv)  					{ -						std::string addr = get_bv(cell->getPort("\\WR_ADDR").extract(abits*i, abits)); -						std::string data = get_bv(cell->getPort("\\WR_DATA").extract(width*i, width)); -						std::string mask = get_bv(cell->getPort("\\WR_EN").extract(width*i, width)); - -						data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))", -								data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str()); +						int mem_size = cell->getParam("\\SIZE").as_int(); +						int mem_offset = cell->getParam("\\OFFSET").as_int(); + +						for (int i = 0; i < wr_ports; i++) +						{ +							SigSpec addr_sig = cell->getPort("\\WR_ADDR").extract(abits*i, abits); +							SigSpec data_sig = cell->getPort("\\WR_DATA").extract(width*i, width); +							SigSpec mask_sig = cell->getPort("\\WR_EN").extract(width*i, width); + +							std::string addr = get_bv(addr_sig); +							std::string data = get_bv(data_sig); +							std::string mask = get_bv(mask_sig); + +							decls.push_back(stringf("(define-fun |%s_m:%d %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +									get_id(module), rd_ports+i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); +							addr = stringf("(|%s_m:%d %s| state)", get_id(module), rd_ports+i, get_id(cell)); + +							decls.push_back(stringf("(define-fun |%s_m:%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +									get_id(module), rd_ports+i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig))); +							data = stringf("(|%s_m:%dD %s| state)", get_id(module), rd_ports+i, get_id(cell)); + +							decls.push_back(stringf("(define-fun |%s_m:%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +									get_id(module), rd_ports+i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig))); +							mask = stringf("(|%s_m:%dM %s| state)", get_id(module), rd_ports+i, get_id(cell)); + +							std::string data_expr; + +							for (int k = mem_size-1; k >= 0; k--) { +								std::string new_data = stringf("(bvor (bvand %s %s) (bvand ((_ extract %d %d) (|%s#%d#%d| state)) (bvnot %s)))", +										data.c_str(), mask.c_str(), width*(k+1)-1, width*k, get_id(module), arrayid, i, mask.c_str()); +								data_expr += stringf("\n  (ite (= %s #b%s) %s ((_ extract %d %d) (|%s#%d#%d| state)))", +										addr.c_str(), Const(k+mem_offset, abits).as_string().c_str(), new_data.c_str(), +										width*(k+1)-1, width*k, get_id(module), arrayid, i); +							} -						decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) " -								"(store (|%s#%d#%d| state) %s %s)) ; %s\n", -								get_id(module), arrayid, i+1, get_id(module), abits, width, -								get_id(module), arrayid, i, addr.c_str(), data.c_str(), get_id(cell))); +							decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (_ BitVec %d) (concat%s)) ; %s\n", +									get_id(module), arrayid, i+1, get_id(module), width*mem_size, data_expr.c_str(), get_id(cell))); +						} +					} +					else +					{ +						for (int i = 0; i < wr_ports; i++) +						{ +							SigSpec addr_sig = cell->getPort("\\WR_ADDR").extract(abits*i, abits); +							SigSpec data_sig = cell->getPort("\\WR_DATA").extract(width*i, width); +							SigSpec mask_sig = cell->getPort("\\WR_EN").extract(width*i, width); + +							std::string addr = get_bv(addr_sig); +							std::string data = get_bv(data_sig); +							std::string mask = get_bv(mask_sig); + +							decls.push_back(stringf("(define-fun |%s_m:%d %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +									get_id(module), rd_ports+i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); +							addr = stringf("(|%s_m:%d %s| state)", get_id(module), rd_ports+i, get_id(cell)); + +							decls.push_back(stringf("(define-fun |%s_m:%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +									get_id(module), rd_ports+i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig))); +							data = stringf("(|%s_m:%dD %s| state)", get_id(module), rd_ports+i, get_id(cell)); + +							decls.push_back(stringf("(define-fun |%s_m:%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", +									get_id(module), rd_ports+i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig))); +							mask = stringf("(|%s_m:%dM %s| state)", get_id(module), rd_ports+i, get_id(cell)); + +							data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))", +									data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str()); + +							decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) " +									"(store (|%s#%d#%d| state) %s %s)) ; %s\n", +									get_id(module), arrayid, i+1, get_id(module), abits, width, +									get_id(module), arrayid, i, addr.c_str(), data.c_str(), get_id(cell))); +						}  					}  					std::string expr_d = stringf("(|%s#%d#%d| state)", get_id(module), arrayid, wr_ports); @@ -755,10 +889,14 @@ struct Smt2Worker  							if (bit == State::S0 || bit == State::S1)  								gen_init_constr = true; -						if (gen_init_constr) { -							init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]", -									get_id(module), arrayid, Const(i, abits).as_string().c_str(), -									initword.as_string().c_str(), get_id(cell), i)); +						if (gen_init_constr) +						{ +							if (statebv) +								/* FIXME */; +							else +								init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]", +										get_id(module), arrayid, Const(i, abits).as_string().c_str(), +										initword.as_string().c_str(), get_id(cell), i));  						}  					}  				} @@ -854,6 +992,12 @@ struct Smt2Worker  	{  		f << stringf("; yosys-smt2-module %s\n", get_id(module)); +		if (statebv) { +			f << stringf("(define-sort |%s_s| () (_ BitVec %d))\n", get_id(module), statebv_width); +			mod_stbv_width[module->name] = statebv_width; +		} else +			f << stringf("(declare-sort |%s_s| 0)\n", get_id(module)); +  		for (auto it : decls)  			f << it; @@ -924,6 +1068,11 @@ struct Smt2Backend : public Backend {  		log("    -verbose\n");  		log("        this will print the recursive walk used to export the modules.\n");  		log("\n"); +		log("    -stbv\n"); +		log("        Use a BitVec sort to represent a state instead of an uninterpreted\n"); +		log("        sort. As a side-effect this will prevent use of arrays to model\n"); +		log("        memories.\n"); +		log("\n");  		log("    -nobv\n");  		log("        disable support for BitVec (FixedSizeBitVectors theory). without this\n");  		log("        option multi-bit wires are represented using the BitVec sort and\n"); @@ -997,7 +1146,7 @@ struct Smt2Backend : public Backend {  	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)  	{  		std::ifstream template_f; -		bool bvmode = true, memmode = true, wiresmode = false, verbose = false; +		bool bvmode = true, memmode = true, wiresmode = false, verbose = false, statebv = false;  		log_header(design, "Executing SMT2 backend.\n"); @@ -1014,6 +1163,10 @@ struct Smt2Backend : public Backend {  				log_warning("Options -bv and -mem are now the default. Support for -bv and -mem will be removed in the future.\n");  				continue;  			} +			if (args[argidx] == "-stbv") { +				statebv = true; +				continue; +			}  			if (args[argidx] == "-nobv") {  				bvmode = false;  				memmode = false; @@ -1055,6 +1208,9 @@ struct Smt2Backend : public Backend {  		if (!memmode)  			*f << stringf("; yosys-smt2-nomem\n"); +		if (statebv) +			*f << stringf("; yosys-smt2-stbv\n"); +  		std::vector<RTLIL::Module*> sorted_modules;  		// extract module dependencies @@ -1084,6 +1240,7 @@ struct Smt2Backend : public Backend {  				module_deps.erase(sorted_modules.at(sorted_modules_idx++));  		} +		dict<IdString, int> mod_stbv_width;  		Module *topmod = design->top_module();  		std::string topmod_id; @@ -1094,7 +1251,7 @@ struct Smt2Backend : public Backend {  			log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); -			Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose); +			Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose, statebv, mod_stbv_width);  			worker.run();  			worker.write(*f); diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index d8b47504c..39ac181dd 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -613,12 +613,12 @@ def write_vlogtb_trace(steps_start, steps_stop, index):          mems = sorted(smt.hiermems(topmod))          for mempath in mems: -            abits, width, ports = smt.mem_info(topmod, mempath) +            abits, width, rports, wports = smt.mem_info(topmod, mempath)              mem = smt.mem_expr(topmod, "s%d" % steps_start, mempath)              addr_expr_list = list()              for i in range(steps_start, steps_stop): -                for j in range(ports): +                for j in range(rports):                      addr_expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, j))              addr_list = set() @@ -674,12 +674,12 @@ def write_constr_trace(steps_start, steps_stop, index):          mems = sorted(smt.hiermems(topmod))          for mempath in mems: -            abits, width, ports = smt.mem_info(topmod, mempath) +            abits, width, rports, wports = smt.mem_info(topmod, mempath)              mem = smt.mem_expr(topmod, "s%d" % steps_start, mempath)              addr_expr_list = list()              for i in range(steps_start, steps_stop): -                for j in range(ports): +                for j in range(rports):                      addr_expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, j))              addr_list = set((smt.bv2int(val) for val in smt.get_list(addr_expr_list))) diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 93cadd104..797539b9f 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -328,7 +328,7 @@ class SmtIo:              self.modinfo[self.curmod].wsize[fields[2]] = int(fields[3])          if fields[1] == "yosys-smt2-memory": -            self.modinfo[self.curmod].memories[fields[2]] = (int(fields[3]), int(fields[4]), int(fields[5])) +            self.modinfo[self.curmod].memories[fields[2]] = (int(fields[3]), int(fields[4]), int(fields[5]), int(fields[6]))          if fields[1] == "yosys-smt2-wire":              self.modinfo[self.curmod].wires.add(fields[2])  | 
