mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	smt2: Use Mem helper.
This commit is contained in:
		
							parent
							
								
									ec483b7c3b
								
							
						
					
					
						commit
						f272c8b407
					
				
					 1 changed files with 253 additions and 195 deletions
				
			
		|  | @ -22,6 +22,7 @@ | ||||||
| #include "kernel/sigtools.h" | #include "kernel/sigtools.h" | ||||||
| #include "kernel/celltypes.h" | #include "kernel/celltypes.h" | ||||||
| #include "kernel/log.h" | #include "kernel/log.h" | ||||||
|  | #include "kernel/mem.h" | ||||||
| #include <string> | #include <string> | ||||||
| 
 | 
 | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
|  | @ -40,12 +41,15 @@ struct Smt2Worker | ||||||
| 	std::map<RTLIL::SigBit, RTLIL::Cell*> bit_driver; | 	std::map<RTLIL::SigBit, RTLIL::Cell*> bit_driver; | ||||||
| 	std::set<RTLIL::Cell*> exported_cells, hiercells, hiercells_queue; | 	std::set<RTLIL::Cell*> exported_cells, hiercells, hiercells_queue; | ||||||
| 	pool<Cell*> recursive_cells, registers; | 	pool<Cell*> recursive_cells, registers; | ||||||
|  | 	std::vector<Mem> memories; | ||||||
|  | 	dict<Cell*, Mem*> mem_cells; | ||||||
|  | 	std::set<Mem*> memory_queue; | ||||||
| 
 | 
 | ||||||
| 	pool<SigBit> clock_posedge, clock_negedge; | 	pool<SigBit> clock_posedge, clock_negedge; | ||||||
| 	vector<string> ex_state_eq, ex_input_eq; | 	vector<string> ex_state_eq, ex_input_eq; | ||||||
| 
 | 
 | ||||||
| 	std::map<RTLIL::SigBit, std::pair<int, int>> fcache; | 	std::map<RTLIL::SigBit, std::pair<int, int>> fcache; | ||||||
| 	std::map<Cell*, int> memarrays; | 	std::map<Mem*, int> memarrays; | ||||||
| 	std::map<int, int> bvsizes; | 	std::map<int, int> bvsizes; | ||||||
| 	dict<IdString, char*> ids; | 	dict<IdString, char*> ids; | ||||||
| 
 | 
 | ||||||
|  | @ -116,12 +120,73 @@ struct Smt2Worker | ||||||
| 
 | 
 | ||||||
| 		makebits(stringf("%s_is", get_id(module))); | 		makebits(stringf("%s_is", get_id(module))); | ||||||
| 
 | 
 | ||||||
|  | 		dict<IdString, Mem*> mem_dict; | ||||||
|  | 		memories = Mem::get_all_memories(module); | ||||||
|  | 		for (auto &mem : memories) | ||||||
|  | 		{ | ||||||
|  | 			mem_dict[mem.memid] = &mem; | ||||||
|  | 			for (auto &port : mem.wr_ports) | ||||||
|  | 			{ | ||||||
|  | 				if (port.clk_enable) { | ||||||
|  | 					SigSpec clk = sigmap(port.clk); | ||||||
|  | 					for (int i = 0; i < GetSize(clk); i++) | ||||||
|  | 					{ | ||||||
|  | 						if (clk[i].wire == nullptr) | ||||||
|  | 							continue; | ||||||
|  | 						if (port.clk_polarity) | ||||||
|  | 							clock_posedge.insert(clk[i]); | ||||||
|  | 						else | ||||||
|  | 							clock_negedge.insert(clk[i]); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				for (auto bit : sigmap(port.en)) | ||||||
|  | 					noclock.insert(bit); | ||||||
|  | 				for (auto bit : sigmap(port.addr)) | ||||||
|  | 					noclock.insert(bit); | ||||||
|  | 				for (auto bit : sigmap(port.data)) | ||||||
|  | 					noclock.insert(bit); | ||||||
|  | 			} | ||||||
|  | 			for (auto &port : mem.rd_ports) | ||||||
|  | 			{ | ||||||
|  | 				if (port.clk_enable) { | ||||||
|  | 					SigSpec clk = sigmap(port.clk); | ||||||
|  | 					for (int i = 0; i < GetSize(clk); i++) | ||||||
|  | 					{ | ||||||
|  | 						if (clk[i].wire == nullptr) | ||||||
|  | 							continue; | ||||||
|  | 						if (port.clk_polarity) | ||||||
|  | 							clock_posedge.insert(clk[i]); | ||||||
|  | 						else | ||||||
|  | 							clock_negedge.insert(clk[i]); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				for (auto bit : sigmap(port.en)) | ||||||
|  | 					noclock.insert(bit); | ||||||
|  | 				for (auto bit : sigmap(port.addr)) | ||||||
|  | 					noclock.insert(bit); | ||||||
|  | 				for (auto bit : sigmap(port.data)) | ||||||
|  | 					noclock.insert(bit); | ||||||
|  | 				Cell *driver = port.cell ? port.cell : mem.cell; | ||||||
|  | 				for (auto bit : sigmap(port.data)) { | ||||||
|  | 					if (bit_driver.count(bit)) | ||||||
|  | 						log_error("Found multiple drivers for %s.\n", log_signal(bit)); | ||||||
|  | 					bit_driver[bit] = driver; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		for (auto cell : module->cells()) | 		for (auto cell : module->cells()) | ||||||
| 		for (auto &conn : cell->connections()) | 		for (auto &conn : cell->connections()) | ||||||
| 		{ | 		{ | ||||||
| 			if (GetSize(conn.second) == 0) | 			if (GetSize(conn.second) == 0) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
|  | 			// Handled above.
 | ||||||
|  | 			if (cell->type.in(ID($mem), ID($memrd), ID($memwr), ID($meminit))) { | ||||||
|  | 				mem_cells[cell] = mem_dict[cell->parameters.at(ID::MEMID).decode_string()]; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			bool is_input = ct.cell_input(cell->type, conn.first); | 			bool is_input = ct.cell_input(cell->type, conn.first); | ||||||
| 			bool is_output = ct.cell_output(cell->type, conn.first); | 			bool is_output = ct.cell_output(cell->type, conn.first); | ||||||
| 
 | 
 | ||||||
|  | @ -135,24 +200,6 @@ struct Smt2Worker | ||||||
| 				log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n", | 				log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n", | ||||||
| 						log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type)); | 						log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type)); | ||||||
| 
 | 
 | ||||||
| 			if (cell->type.in(ID($mem)) && conn.first.in(ID::RD_CLK, ID::WR_CLK)) |  | ||||||
| 			{ |  | ||||||
| 				SigSpec clk = sigmap(conn.second); |  | ||||||
| 				for (int i = 0; i < GetSize(clk); i++) |  | ||||||
| 				{ |  | ||||||
| 					if (clk[i].wire == nullptr) |  | ||||||
| 						continue; |  | ||||||
| 
 |  | ||||||
| 					if (cell->getParam(conn.first == ID::RD_CLK ? ID::RD_CLK_ENABLE : ID::WR_CLK_ENABLE)[i] != State::S1) |  | ||||||
| 						continue; |  | ||||||
| 
 |  | ||||||
| 					if (cell->getParam(conn.first == ID::RD_CLK ? ID::RD_CLK_POLARITY : ID::WR_CLK_POLARITY)[i] == State::S1) |  | ||||||
| 						clock_posedge.insert(clk[i]); |  | ||||||
| 					else |  | ||||||
| 						clock_negedge.insert(clk[i]); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 			if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C)) | 			if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C)) | ||||||
| 			{ | 			{ | ||||||
| 				bool posedge = (cell->type == ID($_DFF_N_)) || (cell->type == ID($dff) && cell->getParam(ID::CLK_POLARITY).as_bool()); | 				bool posedge = (cell->type == ID($_DFF_N_)) || (cell->type == ID($dff) && cell->getParam(ID::CLK_POLARITY).as_bool()); | ||||||
|  | @ -647,27 +694,35 @@ struct Smt2Worker | ||||||
| 			// FIXME: $slice $concat
 | 			// FIXME: $slice $concat
 | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (memmode && cell->type == ID($mem)) | 		if (memmode && cell->type.in(ID($mem), ID($memrd), ID($memwr), ID($meminit))) | ||||||
| 		{ | 		{ | ||||||
| 			int arrayid = idcounter++; | 			Mem *mem = mem_cells[cell]; | ||||||
| 			memarrays[cell] = arrayid; |  | ||||||
| 
 | 
 | ||||||
| 			int abits = cell->getParam(ID::ABITS).as_int(); | 			if (memarrays.count(mem)) { | ||||||
| 			int width = cell->getParam(ID::WIDTH).as_int(); | 				recursive_cells.erase(cell); | ||||||
| 			int rd_ports = cell->getParam(ID::RD_PORTS).as_int(); | 				return; | ||||||
| 			int wr_ports = cell->getParam(ID::WR_PORTS).as_int(); |  | ||||||
| 
 |  | ||||||
| 			bool async_read = false; |  | ||||||
| 			if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_ones()) { |  | ||||||
| 				if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_zero()) |  | ||||||
| 					log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module)); |  | ||||||
| 				async_read = true; |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(cell), abits, width, rd_ports, wr_ports, async_read ? "async" : "sync")); | 			int arrayid = idcounter++; | ||||||
|  | 			memarrays[mem] = arrayid; | ||||||
|  | 
 | ||||||
|  | 			int abits = ceil_log2(mem->size); | ||||||
|  | 
 | ||||||
|  | 			bool has_sync_wr = false; | ||||||
|  | 			bool has_async_wr = false; | ||||||
|  | 			for (auto &port : mem->wr_ports) { | ||||||
|  | 				if (port.clk_enable) | ||||||
|  | 					has_sync_wr = true; | ||||||
|  | 				else | ||||||
|  | 					has_async_wr = true; | ||||||
|  | 			} | ||||||
|  | 			if (has_async_wr && has_sync_wr) | ||||||
|  | 				log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module)); | ||||||
|  | 
 | ||||||
|  | 			decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(mem->memid), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync")); | ||||||
| 
 | 
 | ||||||
| 			string memstate; | 			string memstate; | ||||||
| 			if (async_read) { | 			if (has_async_wr) { | ||||||
| 				memstate = stringf("%s#%d#final", get_id(module), arrayid); | 				memstate = stringf("%s#%d#final", get_id(module), arrayid); | ||||||
| 			} else { | 			} else { | ||||||
| 				memstate = stringf("%s#%d#0", get_id(module), arrayid); | 				memstate = stringf("%s#%d#0", get_id(module), arrayid); | ||||||
|  | @ -675,80 +730,79 @@ struct Smt2Worker | ||||||
| 
 | 
 | ||||||
| 			if (statebv) | 			if (statebv) | ||||||
| 			{ | 			{ | ||||||
| 				int mem_size = cell->getParam(ID::SIZE).as_int(); | 				makebits(memstate, mem->width*mem->size, get_id(mem->memid)); | ||||||
| 				int mem_offset = cell->getParam(ID::OFFSET).as_int(); |  | ||||||
| 
 |  | ||||||
| 				makebits(memstate, width*mem_size, get_id(cell)); |  | ||||||
| 				decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (_ BitVec %d) (|%s| state))\n", | 				decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (_ BitVec %d) (|%s| state))\n", | ||||||
| 						get_id(module), get_id(cell), get_id(module), width*mem_size, memstate.c_str())); | 						get_id(module), get_id(mem->memid), get_id(module), mem->width*mem->size, memstate.c_str())); | ||||||
| 
 | 
 | ||||||
| 				for (int i = 0; i < rd_ports; i++) | 				for (int i = 0; i < GetSize(mem->rd_ports); i++) | ||||||
| 				{ | 				{ | ||||||
| 					SigSpec addr_sig = cell->getPort(ID::RD_ADDR).extract(abits*i, abits); | 					auto &port = mem->rd_ports[i]; | ||||||
| 					SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(width*i, width); | 					SigSpec addr_sig = port.addr; | ||||||
|  | 					addr_sig.extend_u0(abits); | ||||||
| 					std::string addr = get_bv(addr_sig); | 					std::string addr = get_bv(addr_sig); | ||||||
| 
 | 
 | ||||||
| 					if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool()) | 					if (port.clk_enable) | ||||||
| 						log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " | 						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)); | 								"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module)); | ||||||
| 
 | 
 | ||||||
| 					decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | 					decls.push_back(stringf("(define-fun |%s_m:R%dA %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))); | 							get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); | ||||||
| 
 | 
 | ||||||
| 					std::string read_expr = "#b"; | 					std::string read_expr = "#b"; | ||||||
| 					for (int k = 0; k < width; k++) | 					for (int k = 0; k < mem->width; k++) | ||||||
| 						read_expr += "0"; | 						read_expr += "0"; | ||||||
| 
 | 
 | ||||||
| 					for (int k = 0; k < mem_size; k++) | 					for (int k = 0; k < mem->size; k++) | ||||||
| 						read_expr = stringf("(ite (= (|%s_m:R%dA %s| state) #b%s) ((_ extract %d %d) (|%s| state))\n  %s)", | 						read_expr = stringf("(ite (= (|%s_m:R%dA %s| state) #b%s) ((_ extract %d %d) (|%s| state))\n  %s)", | ||||||
| 								get_id(module), i, get_id(cell), Const(k+mem_offset, abits).as_string().c_str(), | 								get_id(module), i, get_id(mem->memid), Const(k+mem->start_offset, abits).as_string().c_str(), | ||||||
| 								width*(k+1)-1, width*k, memstate.c_str(), read_expr.c_str()); | 								mem->width*(k+1)-1, mem->width*k, memstate.c_str(), read_expr.c_str()); | ||||||
| 
 | 
 | ||||||
| 					decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d)\n  %s) ; %s\n", | 					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))); | 							get_id(module), idcounter, get_id(module), mem->width, read_expr.c_str(), log_signal(port.data))); | ||||||
| 
 | 
 | ||||||
| 					decls.push_back(stringf("(define-fun |%s_m:R%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n", | 					decls.push_back(stringf("(define-fun |%s_m:R%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)); | 							get_id(module), i, get_id(mem->memid), get_id(module), mem->width, get_id(module), idcounter)); | ||||||
| 
 | 
 | ||||||
| 					register_bv(data_sig, idcounter++); | 					register_bv(port.data, idcounter++); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				if (statedt) | 				if (statedt) | ||||||
| 					dtmembers.push_back(stringf("  (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | 					dtmembers.push_back(stringf("  (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | ||||||
| 							memstate.c_str(), abits, width, get_id(cell))); | 							memstate.c_str(), abits, mem->width, get_id(mem->memid))); | ||||||
| 				else | 				else | ||||||
| 					decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | 					decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | ||||||
| 							memstate.c_str(), get_id(module), abits, width, get_id(cell))); | 							memstate.c_str(), get_id(module), abits, mem->width, get_id(mem->memid))); | ||||||
| 
 | 
 | ||||||
| 				decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) (|%s| state))\n", | 				decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) (|%s| state))\n", | ||||||
| 						get_id(module), get_id(cell), get_id(module), abits, width, memstate.c_str())); | 						get_id(module), get_id(mem->memid), get_id(module), abits, mem->width, memstate.c_str())); | ||||||
| 
 | 
 | ||||||
| 				for (int i = 0; i < rd_ports; i++) | 				for (int i = 0; i < GetSize(mem->rd_ports); i++) | ||||||
| 				{ | 				{ | ||||||
| 					SigSpec addr_sig = cell->getPort(ID::RD_ADDR).extract(abits*i, abits); | 					auto &port = mem->rd_ports[i]; | ||||||
| 					SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(width*i, width); | 					SigSpec addr_sig = port.addr; | ||||||
|  | 					addr_sig.extend_u0(abits); | ||||||
| 					std::string addr = get_bv(addr_sig); | 					std::string addr = get_bv(addr_sig); | ||||||
| 
 | 
 | ||||||
| 					if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool()) | 					if (port.clk_enable) | ||||||
| 						log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " | 						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)); | 								"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module)); | ||||||
| 
 | 
 | ||||||
| 					decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | 					decls.push_back(stringf("(define-fun |%s_m:R%dA %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))); | 							get_id(module), i, get_id(mem->memid), 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| state) (|%s_m:R%dA %s| state))) ; %s\n", | 					decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) (select (|%s| state) (|%s_m:R%dA %s| state))) ; %s\n", | ||||||
| 							get_id(module), idcounter, get_id(module), width, memstate.c_str(), get_id(module), i, get_id(cell), log_signal(data_sig))); | 							get_id(module), idcounter, get_id(module), mem->width, memstate.c_str(), get_id(module), i, get_id(mem->memid), log_signal(port.data))); | ||||||
| 
 | 
 | ||||||
| 					decls.push_back(stringf("(define-fun |%s_m:R%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n", | 					decls.push_back(stringf("(define-fun |%s_m:R%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)); | 							get_id(module), i, get_id(mem->memid), get_id(module), mem->width, get_id(module), idcounter)); | ||||||
| 
 | 
 | ||||||
| 					register_bv(data_sig, idcounter++); | 					register_bv(port.data, idcounter++); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			registers.insert(cell); | 			memory_queue.insert(mem); | ||||||
| 			recursive_cells.erase(cell); | 			recursive_cells.erase(cell); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  | @ -977,7 +1031,7 @@ struct Smt2Worker | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (int iter = 1; !registers.empty(); iter++) | 		for (int iter = 1; !registers.empty() || !memory_queue.empty(); iter++) | ||||||
| 		{ | 		{ | ||||||
| 			pool<Cell*> this_regs; | 			pool<Cell*> this_regs; | ||||||
| 			this_regs.swap(registers); | 			this_regs.swap(registers); | ||||||
|  | @ -1010,152 +1064,156 @@ struct Smt2Worker | ||||||
| 					if (cell->type == ID($anyconst)) | 					if (cell->type == ID($anyconst)) | ||||||
| 						ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Y)).c_str(), get_bv(cell->getPort(ID::Y), "other_state").c_str())); | 						ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Y)).c_str(), get_bv(cell->getPort(ID::Y), "other_state").c_str())); | ||||||
| 				} | 				} | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 				if (cell->type == ID($mem)) | 			std::set<Mem*> this_mems; | ||||||
| 				{ | 			this_mems.swap(memory_queue); | ||||||
| 					int arrayid = memarrays.at(cell); |  | ||||||
| 
 | 
 | ||||||
| 					int abits = cell->getParam(ID::ABITS).as_int(); | 			for (auto mem : this_mems) | ||||||
| 					int width = cell->getParam(ID::WIDTH).as_int(); | 			{ | ||||||
| 					int wr_ports = cell->getParam(ID::WR_PORTS).as_int(); | 				int arrayid = memarrays.at(mem); | ||||||
| 
 | 
 | ||||||
| 					bool async_read = false; | 				int abits = ceil_log2(mem->size);; | ||||||
| 					string initial_memstate, final_memstate; |  | ||||||
| 
 | 
 | ||||||
| 					if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_ones()) { | 				bool has_sync_wr = false; | ||||||
| 						log_assert(cell->getParam(ID::WR_CLK_ENABLE).is_fully_zero()); | 				bool has_async_wr = false; | ||||||
| 						async_read = true; | 				for (auto &port : mem->wr_ports) { | ||||||
| 						initial_memstate = stringf("%s#%d#0", get_id(module), arrayid); | 					if (port.clk_enable) | ||||||
| 						final_memstate = stringf("%s#%d#final", get_id(module), arrayid); | 						has_sync_wr = true; | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					if (statebv) |  | ||||||
| 					{ |  | ||||||
| 						int mem_size = cell->getParam(ID::SIZE).as_int(); |  | ||||||
| 						int mem_offset = cell->getParam(ID::OFFSET).as_int(); |  | ||||||
| 
 |  | ||||||
| 						if (async_read) { |  | ||||||
| 							makebits(final_memstate, width*mem_size, get_id(cell)); |  | ||||||
| 						} |  | ||||||
| 
 |  | ||||||
| 						for (int i = 0; i < wr_ports; i++) |  | ||||||
| 						{ |  | ||||||
| 							SigSpec addr_sig = cell->getPort(ID::WR_ADDR).extract(abits*i, abits); |  | ||||||
| 							SigSpec data_sig = cell->getPort(ID::WR_DATA).extract(width*i, width); |  | ||||||
| 							SigSpec mask_sig = cell->getPort(ID::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:W%dA %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))); |  | ||||||
| 							addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(cell)); |  | ||||||
| 
 |  | ||||||
| 							decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", |  | ||||||
| 									get_id(module), i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig))); |  | ||||||
| 							data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(cell)); |  | ||||||
| 
 |  | ||||||
| 							decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", |  | ||||||
| 									get_id(module), i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig))); |  | ||||||
| 							mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), 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|)) (_ 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 | 					else | ||||||
|  | 						has_async_wr = true; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				string initial_memstate, final_memstate; | ||||||
|  | 
 | ||||||
|  | 				if (has_async_wr) { | ||||||
|  | 					log_assert(!has_sync_wr); | ||||||
|  | 					initial_memstate = stringf("%s#%d#0", get_id(module), arrayid); | ||||||
|  | 					final_memstate = stringf("%s#%d#final", get_id(module), arrayid); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (statebv) | ||||||
|  | 				{ | ||||||
|  | 					if (has_async_wr) { | ||||||
|  | 						makebits(final_memstate, mem->width*mem->size, get_id(mem->memid)); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					for (int i = 0; i < GetSize(mem->wr_ports); i++) | ||||||
| 					{ | 					{ | ||||||
| 						if (async_read) { | 						auto &port = mem->wr_ports[i]; | ||||||
| 							if (statedt) | 						SigSpec addr_sig = port.addr; | ||||||
| 								dtmembers.push_back(stringf("  (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | 						addr_sig.extend_u0(abits); | ||||||
| 										initial_memstate.c_str(), abits, width, get_id(cell))); | 
 | ||||||
| 							else | 						std::string addr = get_bv(addr_sig); | ||||||
| 								decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | 						std::string data = get_bv(port.data); | ||||||
| 										initial_memstate.c_str(), get_id(module), abits, width, get_id(cell))); | 						std::string mask = get_bv(port.en); | ||||||
|  | 
 | ||||||
|  | 						decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | ||||||
|  | 								get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); | ||||||
|  | 						addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(mem->memid)); | ||||||
|  | 
 | ||||||
|  | 						decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | ||||||
|  | 								get_id(module), i, get_id(mem->memid), get_id(module), mem->width, data.c_str(), log_signal(port.data))); | ||||||
|  | 						data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(mem->memid)); | ||||||
|  | 
 | ||||||
|  | 						decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | ||||||
|  | 								get_id(module), i, get_id(mem->memid), get_id(module), mem->width, mask.c_str(), log_signal(port.en))); | ||||||
|  | 						mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(mem->memid)); | ||||||
|  | 
 | ||||||
|  | 						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(), mem->width*(k+1)-1, mem->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->start_offset, abits).as_string().c_str(), new_data.c_str(), | ||||||
|  | 									mem->width*(k+1)-1, mem->width*k, get_id(module), arrayid, i); | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 						for (int i = 0; i < wr_ports; i++) | 						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), mem->width*mem->size, data_expr.c_str(), get_id(mem->memid))); | ||||||
| 							SigSpec addr_sig = cell->getPort(ID::WR_ADDR).extract(abits*i, abits); | 					} | ||||||
| 							SigSpec data_sig = cell->getPort(ID::WR_DATA).extract(width*i, width); | 				} | ||||||
| 							SigSpec mask_sig = cell->getPort(ID::WR_EN).extract(width*i, width); | 				else | ||||||
|  | 				{ | ||||||
|  | 					if (has_async_wr) { | ||||||
|  | 						if (statedt) | ||||||
|  | 							dtmembers.push_back(stringf("  (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | ||||||
|  | 									initial_memstate.c_str(), abits, mem->width, get_id(mem->memid))); | ||||||
|  | 						else | ||||||
|  | 							decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n", | ||||||
|  | 									initial_memstate.c_str(), get_id(module), abits, mem->width, get_id(mem->memid))); | ||||||
|  | 					} | ||||||
| 
 | 
 | ||||||
| 							std::string addr = get_bv(addr_sig); | 					for (int i = 0; i < GetSize(mem->wr_ports); i++) | ||||||
| 							std::string data = get_bv(data_sig); | 					{ | ||||||
| 							std::string mask = get_bv(mask_sig); | 						auto &port = mem->wr_ports[i]; | ||||||
|  | 						SigSpec addr_sig = port.addr; | ||||||
|  | 						addr_sig.extend_u0(abits); | ||||||
| 
 | 
 | ||||||
| 							decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | 						std::string addr = get_bv(addr_sig); | ||||||
| 									get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); | 						std::string data = get_bv(port.data); | ||||||
| 							addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(cell)); | 						std::string mask = get_bv(port.en); | ||||||
| 
 | 
 | ||||||
| 							decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | 						decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | ||||||
| 									get_id(module), i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig))); | 								get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); | ||||||
| 							data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(cell)); | 						addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(mem->memid)); | ||||||
| 
 | 
 | ||||||
| 							decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | 						decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | ||||||
| 									get_id(module), i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig))); | 								get_id(module), i, get_id(mem->memid), get_id(module), mem->width, data.c_str(), log_signal(port.data))); | ||||||
| 							mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(cell)); | 						data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(mem->memid)); | ||||||
| 
 | 
 | ||||||
| 							data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))", | 						decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", | ||||||
| 									data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str()); | 								get_id(module), i, get_id(mem->memid), get_id(module), mem->width, mask.c_str(), log_signal(port.en))); | ||||||
|  | 						mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(mem->memid)); | ||||||
| 
 | 
 | ||||||
| 							decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) " | 						data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))", | ||||||
| 									"(store (|%s#%d#%d| state) %s %s)) ; %s\n", | 								data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str()); | ||||||
| 									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|)) (Array (_ BitVec %d) (_ BitVec %d)) " | ||||||
|  | 								"(store (|%s#%d#%d| state) %s %s)) ; %s\n", | ||||||
|  | 								get_id(module), arrayid, i+1, get_id(module), abits, mem->width, | ||||||
|  | 								get_id(module), arrayid, i, addr.c_str(), data.c_str(), get_id(mem->memid))); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				std::string expr_d = stringf("(|%s#%d#%d| state)", get_id(module), arrayid, GetSize(mem->wr_ports)); | ||||||
|  | 				std::string expr_q = stringf("(|%s#%d#0| next_state)", get_id(module), arrayid); | ||||||
|  | 				trans.push_back(stringf("  (= %s %s) ; %s\n", expr_d.c_str(), expr_q.c_str(), get_id(mem->memid))); | ||||||
|  | 				ex_state_eq.push_back(stringf("(= (|%s#%d#0| state) (|%s#%d#0| other_state))", get_id(module), arrayid, get_id(module), arrayid)); | ||||||
|  | 
 | ||||||
|  | 				if (has_async_wr) | ||||||
|  | 					hier.push_back(stringf("  (= %s (|%s| state)) ; %s\n", expr_d.c_str(), final_memstate.c_str(), get_id(mem->memid))); | ||||||
|  | 
 | ||||||
|  | 				Const init_data = mem->get_init_data(); | ||||||
|  | 
 | ||||||
|  | 				for (int i = 0; i < mem->size; i++) | ||||||
|  | 				{ | ||||||
|  | 					if (i*mem->width >= GetSize(init_data)) | ||||||
|  | 						break; | ||||||
|  | 
 | ||||||
|  | 					Const initword = init_data.extract(i*mem->width, mem->width, State::Sx); | ||||||
|  | 					Const initmask = initword; | ||||||
|  | 					bool gen_init_constr = false; | ||||||
|  | 
 | ||||||
|  | 					for (int k = 0; k < GetSize(initword); k++) { | ||||||
|  | 						if (initword[k] == State::S0 || initword[k] == State::S1) { | ||||||
|  | 							gen_init_constr = true; | ||||||
|  | 							initmask[k] = State::S1; | ||||||
|  | 						} else { | ||||||
|  | 							initmask[k] = State::S0; | ||||||
|  | 							initword[k] = State::S0; | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					std::string expr_d = stringf("(|%s#%d#%d| state)", get_id(module), arrayid, wr_ports); | 					if (gen_init_constr) | ||||||
| 					std::string expr_q = stringf("(|%s#%d#0| next_state)", get_id(module), arrayid); |  | ||||||
| 					trans.push_back(stringf("  (= %s %s) ; %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell))); |  | ||||||
| 					ex_state_eq.push_back(stringf("(= (|%s#%d#0| state) (|%s#%d#0| other_state))", get_id(module), arrayid, get_id(module), arrayid)); |  | ||||||
| 
 |  | ||||||
| 					if (async_read) |  | ||||||
| 						hier.push_back(stringf("  (= %s (|%s| state)) ; %s\n", expr_d.c_str(), final_memstate.c_str(), get_id(cell))); |  | ||||||
| 
 |  | ||||||
| 					Const init_data = cell->getParam(ID::INIT); |  | ||||||
| 					int memsize = cell->getParam(ID::SIZE).as_int(); |  | ||||||
| 
 |  | ||||||
| 					for (int i = 0; i < memsize; i++) |  | ||||||
| 					{ | 					{ | ||||||
| 						if (i*width >= GetSize(init_data)) | 						if (statebv) | ||||||
| 							break; | 							/* FIXME */; | ||||||
| 
 | 						else | ||||||
| 						Const initword = init_data.extract(i*width, width, State::Sx); | 							init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]", | ||||||
| 						Const initmask = initword; | 									get_id(module), arrayid, Const(i, abits).as_string().c_str(), | ||||||
| 						bool gen_init_constr = false; | 									initmask.as_string().c_str(), initword.as_string().c_str(), get_id(mem->memid), i)); | ||||||
| 
 |  | ||||||
| 						for (int k = 0; k < GetSize(initword); k++) { |  | ||||||
| 							if (initword[k] == State::S0 || initword[k] == State::S1) { |  | ||||||
| 								gen_init_constr = true; |  | ||||||
| 								initmask[k] = State::S1; |  | ||||||
| 							} else { |  | ||||||
| 								initmask[k] = State::S0; |  | ||||||
| 								initword[k] = State::S0; |  | ||||||
| 							} |  | ||||||
| 						} |  | ||||||
| 
 |  | ||||||
| 						if (gen_init_constr) |  | ||||||
| 						{ |  | ||||||
| 							if (statebv) |  | ||||||
| 								/* FIXME */; |  | ||||||
| 							else |  | ||||||
| 								init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]", |  | ||||||
| 										get_id(module), arrayid, Const(i, abits).as_string().c_str(), |  | ||||||
| 										initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i)); |  | ||||||
| 						} |  | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | @ -1586,7 +1644,7 @@ struct Smt2Backend : public Backend { | ||||||
| 
 | 
 | ||||||
| 		for (auto module : sorted_modules) | 		for (auto module : sorted_modules) | ||||||
| 		{ | 		{ | ||||||
| 			if (module->get_blackbox_attribute() || module->has_memories_warn() || module->has_processes_warn()) | 			if (module->get_blackbox_attribute() || module->has_processes_warn()) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); | 			log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue