mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	clang-format smtlib.cc
This commit is contained in:
		
							parent
							
								
									94ddbc9577
								
							
						
					
					
						commit
						4109fcedcf
					
				
					 1 changed files with 199 additions and 253 deletions
				
			
		|  | @ -17,333 +17,279 @@ | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "kernel/yosys.h" |  | ||||||
| #include "kernel/functionalir.h" | #include "kernel/functionalir.h" | ||||||
|  | #include "kernel/yosys.h" | ||||||
| 
 | 
 | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| struct SmtScope { | struct SmtScope { | ||||||
|   pool<std::string> used_names; | 	pool<std::string> used_names; | ||||||
|   dict<IdString, std::string> name_map; | 	dict<IdString, std::string> name_map; | ||||||
| 
 | 
 | ||||||
|   SmtScope() {} | 	SmtScope() {} | ||||||
|      |  | ||||||
|   void reserve(const std::string& name) { |  | ||||||
|     used_names.insert(name); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string insert(IdString id) { | 	void reserve(const std::string &name) { used_names.insert(name); } | ||||||
|     std::string name = RTLIL::unescape_id(id); |  | ||||||
|     if (used_names.count(name) == 0) { |  | ||||||
|       used_names.insert(name); |  | ||||||
|       name_map[id] = name; |  | ||||||
|       return name; |  | ||||||
|     } |  | ||||||
|     for (int idx = 0;; ++idx) { |  | ||||||
|       std::string new_name = name + "_" + std::to_string(idx); |  | ||||||
|       if (used_names.count(new_name) == 0) { |  | ||||||
| 	used_names.insert(new_name); |  | ||||||
| 	name_map[id] = new_name; |  | ||||||
| 	return new_name; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string operator[](IdString id) { | 	std::string insert(IdString id) | ||||||
|     if (name_map.count(id)) { | 	{ | ||||||
|       return name_map[id]; | 		std::string name = RTLIL::unescape_id(id); | ||||||
|     } else { | 		if (used_names.count(name) == 0) { | ||||||
|       return insert(id); | 			used_names.insert(name); | ||||||
|     } | 			name_map[id] = name; | ||||||
|   } | 			return name; | ||||||
|  | 		} | ||||||
|  | 		for (int idx = 0;; ++idx) { | ||||||
|  | 			std::string new_name = name + "_" + std::to_string(idx); | ||||||
|  | 			if (used_names.count(new_name) == 0) { | ||||||
|  | 				used_names.insert(new_name); | ||||||
|  | 				name_map[id] = new_name; | ||||||
|  | 				return new_name; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	std::string operator[](IdString id) | ||||||
|  | 	{ | ||||||
|  | 		if (name_map.count(id)) { | ||||||
|  | 			return name_map[id]; | ||||||
|  | 		} else { | ||||||
|  | 			return insert(id); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SmtWriter { | struct SmtWriter { | ||||||
|   std::ostream& stream; | 	std::ostream &stream; | ||||||
| 
 | 
 | ||||||
|   SmtWriter(std::ostream& out) : stream(out) {} | 	SmtWriter(std::ostream &out) : stream(out) {} | ||||||
| 
 | 
 | ||||||
|   void print(const char* fmt, ...) { | 	void print(const char *fmt, ...) | ||||||
|     va_list args; | 	{ | ||||||
|     va_start(args, fmt); | 		va_list args; | ||||||
|     stream << vstringf(fmt, args); | 		va_start(args, fmt); | ||||||
|     va_end(args); | 		stream << vstringf(fmt, args); | ||||||
|   } | 		va_end(args); | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template<class NodeNames> | template <class NodeNames> struct SmtPrintVisitor { | ||||||
| struct SmtPrintVisitor { | 	using Node = FunctionalIR::Node; | ||||||
|   using Node = FunctionalIR::Node; | 	NodeNames np; | ||||||
|   NodeNames np; | 	SmtScope &scope; | ||||||
|   SmtScope &scope; |  | ||||||
| 
 | 
 | ||||||
|   SmtPrintVisitor(NodeNames np, SmtScope &scope) | 	SmtPrintVisitor(NodeNames np, SmtScope &scope) : np(np), scope(scope) {} | ||||||
|     : np(np), scope(scope) {} |  | ||||||
| 
 | 
 | ||||||
|   template<class T> | 	template <class T> std::string arg_to_string(T n) { return std::to_string(n); } | ||||||
|   std::string arg_to_string(T n) { return std::to_string(n); } |  | ||||||
| 
 | 
 | ||||||
|   std::string arg_to_string(std::string n) { return n; } | 	std::string arg_to_string(std::string n) { return n; } | ||||||
| 
 | 
 | ||||||
|   std::string arg_to_string(Node n) { return np(n); } | 	std::string arg_to_string(Node n) { return np(n); } | ||||||
| 
 | 
 | ||||||
|   template<typename... Args> | 	template <typename... Args> std::string format(std::string fmt, Args &&...args) | ||||||
|   std::string format(std::string fmt, Args&&... args) { | 	{ | ||||||
|     std::vector<std::string> arg_strings = { arg_to_string(std::forward<Args>(args))... }; | 		std::vector<std::string> arg_strings = {arg_to_string(std::forward<Args>(args))...}; | ||||||
|     for (size_t i = 0; i < arg_strings.size(); ++i) { | 		for (size_t i = 0; i < arg_strings.size(); ++i) { | ||||||
|       std::string placeholder = "%" + std::to_string(i); | 			std::string placeholder = "%" + std::to_string(i); | ||||||
|       size_t pos = 0; | 			size_t pos = 0; | ||||||
|       while ((pos = fmt.find(placeholder, pos)) != std::string::npos) { | 			while ((pos = fmt.find(placeholder, pos)) != std::string::npos) { | ||||||
| 	fmt.replace(pos, placeholder.length(), arg_strings[i]); | 				fmt.replace(pos, placeholder.length(), arg_strings[i]); | ||||||
| 	pos += arg_strings[i].length(); | 				pos += arg_strings[i].length(); | ||||||
|       } | 			} | ||||||
|     } | 		} | ||||||
|     return fmt; | 		return fmt; | ||||||
|   } | 	} | ||||||
|   std::string buf(Node, Node n) { return np(n); } | 	std::string buf(Node, Node n) { return np(n); } | ||||||
| 
 | 
 | ||||||
|   std::string slice(Node, Node a, int, int offset, int out_width) { | 	std::string slice(Node, Node a, int, int offset, int out_width) | ||||||
|     return format("(_ extract %1 %2 %0)", np(a), offset, offset + out_width - 1); | 	{ | ||||||
|   } | 		return format("(_ extract %1 %2 %0)", np(a), offset, offset + out_width - 1); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|   std::string zero_extend(Node, Node a, int, int out_width) { | 	std::string zero_extend(Node, Node a, int, int out_width) { return format("((_ zero_extend %1) %0)", np(a), out_width - a.width()); } | ||||||
|     return format("((_ zero_extend %1) %0)", np(a), out_width - a.width()); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string sign_extend(Node, Node a, int, int out_width) { | 	std::string sign_extend(Node, Node a, int, int out_width) { return format("((_ sign_extend %1) %0)", np(a), out_width - a.width()); } | ||||||
|     return format("((_ sign_extend %1) %0)", np(a), out_width - a.width()); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string concat(Node, Node a, int, Node b, int) { | 	std::string concat(Node, Node a, int, Node b, int) { return format("(concat %0 %1)", np(a), np(b)); } | ||||||
|     return format("(concat %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string add(Node, Node a, Node b, int) { | 	std::string add(Node, Node a, Node b, int) { return format("(bvadd %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvadd %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string sub(Node, Node a, Node b, int) { | 	std::string sub(Node, Node a, Node b, int) { return format("(bvsub %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvsub %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string bitwise_and(Node, Node a, Node b, int) { | 	std::string bitwise_and(Node, Node a, Node b, int) { return format("(bvand %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvand %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string bitwise_or(Node, Node a, Node b, int) { | 	std::string bitwise_or(Node, Node a, Node b, int) { return format("(bvor %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvor %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string bitwise_xor(Node, Node a, Node b, int) { | 	std::string bitwise_xor(Node, Node a, Node b, int) { return format("(bvxor %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvxor %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string bitwise_not(Node, Node a, int) { | 	std::string bitwise_not(Node, Node a, int) { return format("(bvnot %0)", np(a)); } | ||||||
|     return format("(bvnot %0)", np(a)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string unary_minus(Node, Node a, int) { | 	std::string unary_minus(Node, Node a, int) { return format("(bvneg %0)", np(a)); } | ||||||
|     return format("(bvneg %0)", np(a)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string reduce_and(Node, Node a, int) { | 	std::string reduce_and(Node, Node a, int) { return format("(= %0 #b1)", np(a)); } | ||||||
|     return format("(= %0 #b1)", np(a)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string reduce_or(Node, Node a, int) { | 	std::string reduce_or(Node, Node a, int) | ||||||
|     std::stringstream ss; | 	{ | ||||||
|     // We use ite to set the result to bit vector, to ensure appropriate type
 | 		std::stringstream ss; | ||||||
|     ss << "(ite (= " << np(a) << " #b" << std::string(a.width(), '0') << ") #b0 #b1)"; | 		// We use ite to set the result to bit vector, to ensure appropriate type
 | ||||||
|     return ss.str(); | 		ss << "(ite (= " << np(a) << " #b" << std::string(a.width(), '0') << ") #b0 #b1)"; | ||||||
|   } | 		return ss.str(); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|   std::string reduce_xor(Node, Node a, int) { | 	std::string reduce_xor(Node, Node a, int) { return format("(bvxor_reduce %0)", np(a)); } | ||||||
|     return format("(bvxor_reduce %0)", np(a)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string equal(Node, Node a, Node b, int) { | 	std::string equal(Node, Node a, Node b, int) { return format("(= %0 %1)", np(a), np(b)); } | ||||||
|     return format("(= %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string not_equal(Node, Node a, Node b, int) { | 	std::string not_equal(Node, Node a, Node b, int) { return format("(distinct %0 %1)", np(a), np(b)); } | ||||||
|     return format("(distinct %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string signed_greater_than(Node, Node a, Node b, int) { | 	std::string signed_greater_than(Node, Node a, Node b, int) { return format("(bvsgt %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvsgt %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string signed_greater_equal(Node, Node a, Node b, int) { | 	std::string signed_greater_equal(Node, Node a, Node b, int) { return format("(bvsge %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvsge %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string unsigned_greater_than(Node, Node a, Node b, int) { | 	std::string unsigned_greater_than(Node, Node a, Node b, int) { return format("(bvugt %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvugt %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string unsigned_greater_equal(Node, Node a, Node b, int) { | 	std::string unsigned_greater_equal(Node, Node a, Node b, int) { return format("(bvuge %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvuge %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string logical_shift_left(Node, Node a, Node b, int, int) { | 	std::string logical_shift_left(Node, Node a, Node b, int, int) { return format("(bvshl %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvshl %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string logical_shift_right(Node, Node a, Node b, int, int) { | 	std::string logical_shift_right(Node, Node a, Node b, int, int) { return format("(bvlshr %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvlshr %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string arithmetic_shift_right(Node, Node a, Node b, int, int) { | 	std::string arithmetic_shift_right(Node, Node a, Node b, int, int) { return format("(bvashr %0 %1)", np(a), np(b)); } | ||||||
|     return format("(bvashr %0 %1)", np(a), np(b)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string mux(Node, Node a, Node b, Node s, int) { | 	std::string mux(Node, Node a, Node b, Node s, int) { return format("(ite %2 %0 %1)", np(a), np(b), np(s)); } | ||||||
|     return format("(ite %2 %0 %1)", np(a), np(b), np(s)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string pmux(Node, Node a, Node b, Node s, int, int) { | 	std::string pmux(Node, Node a, Node b, Node s, int, int) | ||||||
|     // Assume s is a bit vector, combine a and b based on the selection bits
 | 	{ | ||||||
|     return format("(pmux %0 %1 %2)", np(a), np(b), np(s)); | 		// Assume s is a bit vector, combine a and b based on the selection bits
 | ||||||
|   } | 		return format("(pmux %0 %1 %2)", np(a), np(b), np(s)); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|   std::string constant(Node, RTLIL::Const value) { | 	std::string constant(Node, RTLIL::Const value) { return format("#b%1", value.as_string()); } | ||||||
|     return format("#b%1", value.as_string()); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string input(Node, IdString name) { | 	std::string input(Node, IdString name) { return format("%0", scope[name]); } | ||||||
|     return format("%0", scope[name]); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string state(Node, IdString name) { | 	std::string state(Node, IdString name) { return format("%0", scope[name]); } | ||||||
|     return format("%0", scope[name]); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string memory_read(Node, Node mem, Node addr, int, int) { | 	std::string memory_read(Node, Node mem, Node addr, int, int) { return format("(select %0 %1)", np(mem), np(addr)); } | ||||||
|     return format("(select %0 %1)", np(mem), np(addr)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string memory_write(Node, Node mem, Node addr, Node data, int, int) { | 	std::string memory_write(Node, Node mem, Node addr, Node data, int, int) { return format("(store %0 %1 %2)", np(mem), np(addr), np(data)); } | ||||||
|     return format("(store %0 %1 %2)", np(mem), np(addr), np(data)); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   std::string undriven(Node, int width) { | 	std::string undriven(Node, int width) { return format("#b%0", std::string(width, '0')); } | ||||||
|     return format("#b%0", std::string(width, '0')); |  | ||||||
|   } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SmtModule { | struct SmtModule { | ||||||
|   std::string name; | 	std::string name; | ||||||
|   SmtScope scope; | 	SmtScope scope; | ||||||
|   FunctionalIR ir; | 	FunctionalIR ir; | ||||||
| 
 | 
 | ||||||
|   SmtModule(const std::string& module_name, FunctionalIR ir)  | 	SmtModule(const std::string &module_name, FunctionalIR ir) : name(module_name), ir(std::move(ir)) {} | ||||||
|     : name(module_name), ir(std::move(ir)) {} |  | ||||||
| 
 | 
 | ||||||
|   std::string replaceCharacters(const std::string& input) { | 	std::string replaceCharacters(const std::string &input) | ||||||
|     std::string result = input; | 	{ | ||||||
|     std::replace(result.begin(), result.end(), '$', '_');  // Replace $ with _
 | 		std::string result = input; | ||||||
|      | 		std::replace(result.begin(), result.end(), '$', '_'); // Replace $ with _
 | ||||||
|     // Since \ is an escape character, we use a loop to replace it
 |  | ||||||
|     size_t pos = 0; |  | ||||||
|     while ((pos = result.find('\\', pos)) != std::string::npos) { |  | ||||||
|         result.replace(pos, 1, "_"); |  | ||||||
|         pos += 1;  // Move past the replaced character
 |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   void write(std::ostream& out) { |  | ||||||
|     SmtWriter writer(out); |  | ||||||
|      |  | ||||||
|     writer.print("(declare-fun %s () Bool)\n", name.c_str()); |  | ||||||
|     writer.print("(declare-datatypes () ((Inputs (mk_inputs"); |  | ||||||
|     for (const auto& input : ir.inputs()) { |  | ||||||
|       std::string input_name = scope[input.first]; |  | ||||||
|       writer.print(" (%s (_ BitVec %d))", input_name.c_str(), input.second.width()); |  | ||||||
|     } |  | ||||||
|     writer.print("))))\n"); |  | ||||||
| 
 | 
 | ||||||
|     writer.print("(declare-datatypes () ((Outputs (mk_outputs"); | 		// Since \ is an escape character, we use a loop to replace it
 | ||||||
|     for (const auto& output : ir.outputs()) { | 		size_t pos = 0; | ||||||
|       std::string output_name = scope[output.first]; | 		while ((pos = result.find('\\', pos)) != std::string::npos) { | ||||||
|       writer.print(" (%s (_ BitVec %d))", output_name.c_str(), output.second.width()); | 			result.replace(pos, 1, "_"); | ||||||
|     } | 			pos += 1; // Move past the replaced character
 | ||||||
|     writer.print("))))\n"); | 		} | ||||||
| 
 | 
 | ||||||
|     writer.print("(declare-fun state () (_ BitVec 1))\n"); | 		return result; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|     writer.print("(define-fun %s_step ((state (_ BitVec 1)) (inputs Inputs)) Outputs\n", name.c_str()); | 	void write(std::ostream &out) | ||||||
|     writer.print("  (let (\n"); | 	{ | ||||||
|     for (const auto& input : ir.inputs()) { | 		SmtWriter writer(out); | ||||||
|       std::string input_name = scope[input.first]; |  | ||||||
|       writer.print("    (%s (%s inputs))\n", input_name.c_str(), input_name.c_str()); |  | ||||||
|     } |  | ||||||
|     writer.print("  )\n"); |  | ||||||
| 
 | 
 | ||||||
|     auto node_to_string = [&](FunctionalIR::Node n) { return scope[n.name()]; }; | 		writer.print("(declare-fun %s () Bool)\n", name.c_str()); | ||||||
|     SmtPrintVisitor<decltype(node_to_string)> visitor(node_to_string, scope); | 		writer.print("(declare-datatypes () ((Inputs (mk_inputs"); | ||||||
|  | 		for (const auto &input : ir.inputs()) { | ||||||
|  | 			std::string input_name = scope[input.first]; | ||||||
|  | 			writer.print(" (%s (_ BitVec %d))", input_name.c_str(), input.second.width()); | ||||||
|  | 		} | ||||||
|  | 		writer.print("))))\n"); | ||||||
| 
 | 
 | ||||||
|     std::string nested_lets; | 		writer.print("(declare-datatypes () ((Outputs (mk_outputs"); | ||||||
|     for (auto it = ir.begin(); it != ir.end(); ++it) { | 		for (const auto &output : ir.outputs()) { | ||||||
|       const FunctionalIR::Node& node = *it; | 			std::string output_name = scope[output.first]; | ||||||
|  | 			writer.print(" (%s (_ BitVec %d))", output_name.c_str(), output.second.width()); | ||||||
|  | 		} | ||||||
|  | 		writer.print("))))\n"); | ||||||
| 
 | 
 | ||||||
|       if (ir.inputs().count(node.name()) > 0) continue; | 		writer.print("(declare-fun state () (_ BitVec 1))\n"); | ||||||
|        |  | ||||||
|       std::string node_name = replaceCharacters(scope[node.name()]); |  | ||||||
|       std::string node_expr = node.visit(visitor); |  | ||||||
|        |  | ||||||
|       nested_lets += "(let (\n      (" + node_name + " " + node_expr + "))\n"; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     nested_lets += "          (let (\n"; | 		writer.print("(define-fun %s_step ((state (_ BitVec 1)) (inputs Inputs)) Outputs", name.c_str()); | ||||||
|     for (const auto& output : ir.outputs()) { | 		writer.print("  (let ("); | ||||||
|       std::string output_name = scope[output.first]; | 		for (const auto &input : ir.inputs()) { | ||||||
|       const std::string output_assignment = ir.get_output_node(output.first).name().c_str(); | 			std::string input_name = scope[input.first]; | ||||||
|       nested_lets += "            (" + output_name + " " + replaceCharacters(output_assignment).substr(1) + ")\n"; | 			writer.print("    (%s (%s inputs))", input_name.c_str(), input_name.c_str()); | ||||||
|     } | 		} | ||||||
|     nested_lets += "          )\n"; | 		writer.print("  )"); | ||||||
|     nested_lets += "            (mk_outputs\n"; |  | ||||||
| 
 | 
 | ||||||
|     for (const auto& output : ir.outputs()) { | 		auto node_to_string = [&](FunctionalIR::Node n) { return scope[n.name()]; }; | ||||||
|       std::string output_name = scope[output.first]; | 		SmtPrintVisitor<decltype(node_to_string)> visitor(node_to_string, scope); | ||||||
|       nested_lets += "              " + output_name + "\n"; |  | ||||||
|     } |  | ||||||
|     nested_lets += "            )\n"; |  | ||||||
|     nested_lets += "          )\n"; |  | ||||||
| 
 | 
 | ||||||
|     // Close the nested lets
 | 		std::string nested_lets; | ||||||
|     for (size_t i = 0; i < ir.size() - ir.inputs().size(); ++i) { | 		for (auto it = ir.begin(); it != ir.end(); ++it) { | ||||||
|       nested_lets += "    )\n"; | 			const FunctionalIR::Node &node = *it; | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     writer.print("%s", nested_lets.c_str()); | 			if (ir.inputs().count(node.name()) > 0) | ||||||
|     writer.print("  )\n"); | 				continue; | ||||||
|     writer.print(")\n"); | 
 | ||||||
|   } | 			std::string node_name = replaceCharacters(scope[node.name()]); | ||||||
|  | 			std::string node_expr = node.visit(visitor); | ||||||
|  | 
 | ||||||
|  | 			nested_lets += "(let (      (" + node_name + " " + node_expr + "))"; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		nested_lets += "          (let ("; | ||||||
|  | 		for (const auto &output : ir.outputs()) { | ||||||
|  | 			std::string output_name = scope[output.first]; | ||||||
|  | 			const std::string output_assignment = ir.get_output_node(output.first).name().c_str(); | ||||||
|  | 			nested_lets += "            (" + output_name + " " + replaceCharacters(output_assignment).substr(1) + ")"; | ||||||
|  | 		} | ||||||
|  | 		nested_lets += "          )"; | ||||||
|  | 		nested_lets += "            (mk_outputs"; | ||||||
|  | 
 | ||||||
|  | 		for (const auto &output : ir.outputs()) { | ||||||
|  | 			std::string output_name = scope[output.first]; | ||||||
|  | 			nested_lets += "              " + output_name; | ||||||
|  | 		} | ||||||
|  | 		nested_lets += "            )"; | ||||||
|  | 		nested_lets += "          )"; | ||||||
|  | 
 | ||||||
|  | 		// Close the nested lets
 | ||||||
|  | 		for (size_t i = 0; i < ir.size() - ir.inputs().size(); ++i) { | ||||||
|  | 			nested_lets += "    )"; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		writer.print("%s", nested_lets.c_str()); | ||||||
|  | 		writer.print("  )"); | ||||||
|  | 		writer.print(")\n"); | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct FunctionalSmtBackend : public Backend { | struct FunctionalSmtBackend : public Backend { | ||||||
|   FunctionalSmtBackend() : Backend("functional_smt2", "Generate SMT-LIB from Functional IR") {} | 	FunctionalSmtBackend() : Backend("functional_smt2", "Generate SMT-LIB from Functional IR") {} | ||||||
| 
 | 
 | ||||||
|   void help() override { | 	void help() override { log("\nFunctional SMT Backend.\n\n"); } | ||||||
|     log("\nFunctional SMT Backend.\n\n"); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   void execute(std::ostream*& f, std::string filename, std::vector<std::string> args, RTLIL::Design* design) override { | 	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override | ||||||
|     log_header(design, "Executing Functional SMT Backend.\n"); | 	{ | ||||||
|  | 		log_header(design, "Executing Functional SMT Backend.\n"); | ||||||
| 
 | 
 | ||||||
|     size_t argidx = 1; | 		size_t argidx = 1; | ||||||
|     extra_args(f, filename, args, argidx, design); | 		extra_args(f, filename, args, argidx, design); | ||||||
| 
 | 
 | ||||||
|     for (auto module : design->selected_modules()) { | 		for (auto module : design->selected_modules()) { | ||||||
|       log("Processing module `%s`.\n", module->name.c_str()); | 			log("Processing module `%s`.\n", module->name.c_str()); | ||||||
|       auto ir = FunctionalIR::from_module(module); | 			auto ir = FunctionalIR::from_module(module); | ||||||
|       SmtModule smt(RTLIL::unescape_id(module->name), ir); | 			SmtModule smt(RTLIL::unescape_id(module->name), ir); | ||||||
|       smt.write(*f); | 			smt.write(*f); | ||||||
|     } | 		} | ||||||
|   } | 	} | ||||||
| } FunctionalSmtBackend; | } FunctionalSmtBackend; | ||||||
| 
 | 
 | ||||||
| PRIVATE_NAMESPACE_END | PRIVATE_NAMESPACE_END | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue