mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	change smtlib backend to use list() function instead of SExpr{} constructor (leads to weird constructor overloading resolution issues)
This commit is contained in:
		
							parent
							
								
									9f660b1e4b
								
							
						
					
					
						commit
						c659ef29f4
					
				
					 1 changed files with 55 additions and 50 deletions
				
			
		| 
						 | 
					@ -48,14 +48,14 @@ struct SmtScope : public FunctionalTools::Scope<int> {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SExpr {
 | 
					class SExpr {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
	std::variant<std::vector<SExpr>, std::string> _v;
 | 
						std::variant<std::vector<SExpr>, std::string> _v;
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	SExpr(std::string a) : _v(std::move(a)) {}
 | 
						SExpr(std::string a) : _v(std::move(a)) {}
 | 
				
			||||||
    SExpr(const char *a) : _v(a) {}
 | 
					    SExpr(const char *a) : _v(a) {}
 | 
				
			||||||
	SExpr(int n) : _v(std::to_string(n)) {}
 | 
						SExpr(int n) : _v(std::to_string(n)) {}
 | 
				
			||||||
    SExpr(std::vector<SExpr> const &a) : _v(std::in_place_index<0>, a) {}
 | 
						SExpr(std::vector<SExpr> const &l) : _v(l) {}
 | 
				
			||||||
    SExpr(std::vector<SExpr> &&a) : _v(std::in_place_index<0>, std::move(a)) {}
 | 
						SExpr(std::vector<SExpr> &&l) : _v(std::move(l)) {}
 | 
				
			||||||
    SExpr(std::initializer_list<SExpr> a) : _v(std::in_place_index<0>, a) {}
 | 
					 | 
				
			||||||
    bool is_atom() const { return std::holds_alternative<std::string>(_v); }
 | 
					    bool is_atom() const { return std::holds_alternative<std::string>(_v); }
 | 
				
			||||||
    std::string const &atom() const { return std::get<std::string>(_v); }
 | 
					    std::string const &atom() const { return std::get<std::string>(_v); }
 | 
				
			||||||
    bool is_list() const { return std::holds_alternative<std::vector<SExpr>>(_v); }
 | 
					    bool is_list() const { return std::holds_alternative<std::vector<SExpr>>(_v); }
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,9 @@ public:
 | 
				
			||||||
		return ss.str();
 | 
							return ss.str();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					template<typename... Args> SExpr list(Args&&... args) {
 | 
				
			||||||
 | 
						return SExpr(std::vector<SExpr>{std::forward<Args>(args)...});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SExprWriter {
 | 
					class SExprWriter {
 | 
				
			||||||
    std::ostream &os;
 | 
					    std::ostream &os;
 | 
				
			||||||
| 
						 | 
					@ -209,9 +212,9 @@ struct SmtSort {
 | 
				
			||||||
	SmtSort(FunctionalIR::Sort sort) : sort(sort) {}
 | 
						SmtSort(FunctionalIR::Sort sort) : sort(sort) {}
 | 
				
			||||||
	SExpr to_sexpr() const {
 | 
						SExpr to_sexpr() const {
 | 
				
			||||||
		if(sort.is_memory()) {
 | 
							if(sort.is_memory()) {
 | 
				
			||||||
			return SExpr{"Array", {"_", "BitVec", sort.addr_width()}, {"_", "BitVec", sort.data_width()}};
 | 
								return list("Array", list("_", "BitVec", sort.addr_width()), list("_", "BitVec", sort.data_width()));
 | 
				
			||||||
		} else if(sort.is_signal()) {
 | 
							} else if(sort.is_signal()) {
 | 
				
			||||||
			return SExpr{"_", "BitVec", sort.width()};
 | 
								return list("_", "BitVec", sort.width());
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			log_error("unknown sort");
 | 
								log_error("unknown sort");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -235,15 +238,15 @@ public:
 | 
				
			||||||
		fields.emplace_back(Field{sort, accessor});
 | 
							fields.emplace_back(Field{sort, accessor});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	void write_definition(SExprWriter &w) {
 | 
						void write_definition(SExprWriter &w) {
 | 
				
			||||||
		w.open(SExpr{"declare-datatype", name});
 | 
							w.open(list("declare-datatype", name));
 | 
				
			||||||
		w.open(SExpr({}));
 | 
							w.open(list());
 | 
				
			||||||
		w.open(SExpr{name});
 | 
							w.open(list(name));
 | 
				
			||||||
		for(const auto &field : fields)
 | 
							for(const auto &field : fields)
 | 
				
			||||||
			w << SExpr{field.accessor, field.sort.to_sexpr()};
 | 
								w << list(field.accessor, field.sort.to_sexpr());
 | 
				
			||||||
		w.close(3);
 | 
							w.close(3);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	template<typename Fn> void write_value(SExprWriter &w, Fn fn) {
 | 
						template<typename Fn> void write_value(SExprWriter &w, Fn fn) {
 | 
				
			||||||
		w.open(SExpr(std::initializer_list<SExpr>{name}));
 | 
							w.open(list(name));
 | 
				
			||||||
		for(auto field_name : field_names) {
 | 
							for(auto field_name : field_names) {
 | 
				
			||||||
			w << fn(field_name);
 | 
								w << fn(field_name);
 | 
				
			||||||
			w.comment(RTLIL::unescape_id(field_name), true);
 | 
								w.comment(RTLIL::unescape_id(field_name), true);
 | 
				
			||||||
| 
						 | 
					@ -252,7 +255,7 @@ public:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SExpr access(SExpr record, IdString name) {
 | 
						SExpr access(SExpr record, IdString name) {
 | 
				
			||||||
		size_t i = field_names.at(name);
 | 
							size_t i = field_names.at(name);
 | 
				
			||||||
		return SExpr{fields[i].accessor, std::move(record)};
 | 
							return list(fields[i].accessor, std::move(record));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -272,64 +275,64 @@ struct SmtPrintVisitor {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SExpr from_bool(SExpr &&arg) {
 | 
						SExpr from_bool(SExpr &&arg) {
 | 
				
			||||||
		return SExpr{"ite", std::move(arg), "#b1", "#b0"};
 | 
							return list("ite", std::move(arg), "#b1", "#b0");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SExpr to_bool(SExpr &&arg) {
 | 
						SExpr to_bool(SExpr &&arg) {
 | 
				
			||||||
		return SExpr{"=", std::move(arg), "#b1"};
 | 
							return list("=", std::move(arg), "#b1");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SExpr extract(SExpr &&arg, int offset, int out_width = 1) {
 | 
						SExpr extract(SExpr &&arg, int offset, int out_width = 1) {
 | 
				
			||||||
		return SExpr{{"_", "extract", offset + out_width - 1, offset}, std::move(arg)};
 | 
							return list(list("_", "extract", offset + out_width - 1, offset), std::move(arg));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SExpr buf(Node, Node a) { return n(a); }
 | 
						SExpr buf(Node, Node a) { return n(a); }
 | 
				
			||||||
	SExpr slice(Node, Node a, int, int offset, int out_width) { return extract(n(a), offset, out_width); }
 | 
						SExpr slice(Node, Node a, int, int offset, int out_width) { return extract(n(a), offset, out_width); }
 | 
				
			||||||
	SExpr zero_extend(Node, Node a, int, int out_width) { return SExpr{{"_", "zero_extend", out_width - a.width()}, n(a)}; }
 | 
						SExpr zero_extend(Node, Node a, int, int out_width) { return list(list("_", "zero_extend", out_width - a.width()), n(a)); }
 | 
				
			||||||
	SExpr sign_extend(Node, Node a, int, int out_width) { return SExpr{{"_", "sign_extend", out_width - a.width()}, n(a)}; }
 | 
						SExpr sign_extend(Node, Node a, int, int out_width) { return list(list("_", "sign_extend", out_width - a.width()), n(a)); }
 | 
				
			||||||
	SExpr concat(Node, Node a, int, Node b, int) { return SExpr{"concat", n(a), n(b)}; }
 | 
						SExpr concat(Node, Node a, int, Node b, int) { return list("concat", n(a), n(b)); }
 | 
				
			||||||
	SExpr add(Node, Node a, Node b, int) { return SExpr{"bvadd", n(a), n(b)}; }
 | 
						SExpr add(Node, Node a, Node b, int) { return list("bvadd", n(a), n(b)); }
 | 
				
			||||||
	SExpr sub(Node, Node a, Node b, int) { return SExpr{"bvsub", n(a), n(b)}; }
 | 
						SExpr sub(Node, Node a, Node b, int) { return list("bvsub", n(a), n(b)); }
 | 
				
			||||||
	SExpr mul(Node, Node a, Node b, int) { return SExpr{"bvmul", n(a), n(b)}; }
 | 
						SExpr mul(Node, Node a, Node b, int) { return list("bvmul", n(a), n(b)); }
 | 
				
			||||||
	SExpr unsigned_div(Node, Node a, Node b, int) { return SExpr{"bvudiv", n(a), n(b)}; }
 | 
						SExpr unsigned_div(Node, Node a, Node b, int) { return list("bvudiv", n(a), n(b)); }
 | 
				
			||||||
	SExpr unsigned_mod(Node, Node a, Node b, int) { return SExpr{"bvurem", n(a), n(b)}; }
 | 
						SExpr unsigned_mod(Node, Node a, Node b, int) { return list("bvurem", n(a), n(b)); }
 | 
				
			||||||
	SExpr bitwise_and(Node, Node a, Node b, int) { return SExpr{"bvand", n(a), n(b)}; }
 | 
						SExpr bitwise_and(Node, Node a, Node b, int) { return list("bvand", n(a), n(b)); }
 | 
				
			||||||
	SExpr bitwise_or(Node, Node a, Node b, int) { return SExpr{"bvor", n(a), n(b)}; }
 | 
						SExpr bitwise_or(Node, Node a, Node b, int) { return list("bvor", n(a), n(b)); }
 | 
				
			||||||
	SExpr bitwise_xor(Node, Node a, Node b, int) { return SExpr{"bvxor", n(a), n(b)}; }
 | 
						SExpr bitwise_xor(Node, Node a, Node b, int) { return list("bvxor", n(a), n(b)); }
 | 
				
			||||||
	SExpr bitwise_not(Node, Node a, int) { return SExpr{"bvnot", n(a)}; }
 | 
						SExpr bitwise_not(Node, Node a, int) { return list("bvnot", n(a)); }
 | 
				
			||||||
	SExpr unary_minus(Node, Node a, int) { return SExpr{"bvneg", n(a)}; }
 | 
						SExpr unary_minus(Node, Node a, int) { return list("bvneg", n(a)); }
 | 
				
			||||||
	SExpr reduce_and(Node, Node a, int) { return from_bool(SExpr{"=", n(a), literal(RTLIL::Const(State::S1, a.width()))}); }
 | 
						SExpr reduce_and(Node, Node a, int) { return from_bool(list("=", n(a), literal(RTLIL::Const(State::S1, a.width())))); }
 | 
				
			||||||
	SExpr reduce_or(Node, Node a, int) { return from_bool(SExpr{"=", n(a), literal(RTLIL::Const(State::S0, a.width()))}); }
 | 
						SExpr reduce_or(Node, Node a, int) { return from_bool(list("=", n(a), literal(RTLIL::Const(State::S0, a.width())))); }
 | 
				
			||||||
	SExpr reduce_xor(Node, Node a, int) {
 | 
						SExpr reduce_xor(Node, Node a, int) {
 | 
				
			||||||
		vector<SExpr> s { "bvxor" };
 | 
							vector<SExpr> s { "bvxor" };
 | 
				
			||||||
		for(int i = 0; i < a.width(); i++)
 | 
							for(int i = 0; i < a.width(); i++)
 | 
				
			||||||
			s.push_back(extract(n(a), i));
 | 
								s.push_back(extract(n(a), i));
 | 
				
			||||||
		return s;
 | 
							return s;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SExpr equal(Node, Node a, Node b, int) { return from_bool(SExpr{"=", n(a), n(b)}); }
 | 
						SExpr equal(Node, Node a, Node b, int) { return from_bool(list("=", n(a), n(b))); }
 | 
				
			||||||
	SExpr not_equal(Node, Node a, Node b, int) { return from_bool(SExpr{"distinct", n(a), n(b)}); }
 | 
						SExpr not_equal(Node, Node a, Node b, int) { return from_bool(list("distinct", n(a), n(b))); }
 | 
				
			||||||
	SExpr signed_greater_than(Node, Node a, Node b, int) { return from_bool(SExpr{"bvsgt", n(a), n(b)}); }
 | 
						SExpr signed_greater_than(Node, Node a, Node b, int) { return from_bool(list("bvsgt", n(a), n(b))); }
 | 
				
			||||||
	SExpr signed_greater_equal(Node, Node a, Node b, int) { return from_bool(SExpr{"bvsge", n(a), n(b)}); }
 | 
						SExpr signed_greater_equal(Node, Node a, Node b, int) { return from_bool(list("bvsge", n(a), n(b))); }
 | 
				
			||||||
	SExpr unsigned_greater_than(Node, Node a, Node b, int) { return from_bool(SExpr{"bvugt", n(a), n(b)}); }
 | 
						SExpr unsigned_greater_than(Node, Node a, Node b, int) { return from_bool(list("bvugt", n(a), n(b))); }
 | 
				
			||||||
	SExpr unsigned_greater_equal(Node, Node a, Node b, int) { return from_bool(SExpr{"bvuge", n(a), n(b)}); }
 | 
						SExpr unsigned_greater_equal(Node, Node a, Node b, int) { return from_bool(list("bvuge", n(a), n(b))); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SExpr extend(SExpr &&a, int in_width, int out_width) {
 | 
						SExpr extend(SExpr &&a, int in_width, int out_width) {
 | 
				
			||||||
		if(in_width < out_width)
 | 
							if(in_width < out_width)
 | 
				
			||||||
			return SExpr{{"_", "zero_extend", out_width - in_width}, std::move(a)};
 | 
								return list(list("_", "zero_extend", out_width - in_width), std::move(a));
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			return std::move(a);
 | 
								return std::move(a);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SExpr logical_shift_left(Node, Node a, Node b, int, int) { return SExpr{"bvshl", n(a), extend(n(b), b.width(), a.width())}; }
 | 
						SExpr logical_shift_left(Node, Node a, Node b, int, int) { return list("bvshl", n(a), extend(n(b), b.width(), a.width())); }
 | 
				
			||||||
	SExpr logical_shift_right(Node, Node a, Node b, int, int) { return SExpr{"bvshr", n(a), extend(n(b), b.width(), a.width())}; }
 | 
						SExpr logical_shift_right(Node, Node a, Node b, int, int) { return list("bvshr", n(a), extend(n(b), b.width(), a.width())); }
 | 
				
			||||||
	SExpr arithmetic_shift_right(Node, Node a, Node b, int, int) { return SExpr{"bvasr", n(a), extend(n(b), b.width(), a.width())}; }
 | 
						SExpr arithmetic_shift_right(Node, Node a, Node b, int, int) { return list("bvasr", n(a), extend(n(b), b.width(), a.width())); }
 | 
				
			||||||
	SExpr mux(Node, Node a, Node b, Node s, int) { return SExpr{"ite", to_bool(n(s)), n(a), n(b)}; }
 | 
						SExpr mux(Node, Node a, Node b, Node s, int) { return list("ite", to_bool(n(s)), n(a), n(b)); }
 | 
				
			||||||
	SExpr pmux(Node, Node a, Node b, Node s, int, int) {
 | 
						SExpr pmux(Node, Node a, Node b, Node s, int, int) {
 | 
				
			||||||
		SExpr rv = n(a);
 | 
							SExpr rv = n(a);
 | 
				
			||||||
		for(int i = 0; i < s.width(); i++)
 | 
							for(int i = 0; i < s.width(); i++)
 | 
				
			||||||
			rv = SExpr{"ite", to_bool(extract(n(s), i)), extract(n(b), a.width() * i, a.width()), rv};
 | 
								rv = list("ite", to_bool(extract(n(s), i)), extract(n(b), a.width() * i, a.width()), rv);
 | 
				
			||||||
		return rv;
 | 
							return rv;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SExpr constant(Node, RTLIL::Const value) { return literal(value); }
 | 
						SExpr constant(Node, RTLIL::Const value) { return literal(value); }
 | 
				
			||||||
	SExpr memory_read(Node, Node mem, Node addr, int, int) { return SExpr{"select", n(mem), n(addr)}; }
 | 
						SExpr memory_read(Node, Node mem, Node addr, int, int) { return list("select", n(mem), n(addr)); }
 | 
				
			||||||
	SExpr memory_write(Node, Node mem, Node addr, Node data, int, int) { return SExpr{"store", n(mem), n(addr), n(data)}; }
 | 
						SExpr memory_write(Node, Node mem, Node addr, Node data, int, int) { return list("store", n(mem), n(addr), n(data)); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SExpr input(Node, IdString name) { return input_struct.access("inputs", name); }
 | 
						SExpr input(Node, IdString name) { return input_struct.access("inputs", name); }
 | 
				
			||||||
	SExpr state(Node, IdString name) { return state_struct.access("state", name); }
 | 
						SExpr state(Node, IdString name) { return state_struct.access("state", name); }
 | 
				
			||||||
| 
						 | 
					@ -370,13 +373,15 @@ struct SmtModule {
 | 
				
			||||||
		output_struct.write_definition(w);
 | 
							output_struct.write_definition(w);
 | 
				
			||||||
		state_struct.write_definition(w);
 | 
							state_struct.write_definition(w);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		w << SExpr{"declare-datatypes", {{"Pair", 2}}, {{"par", {"X", "Y"}, {{"pair", {"first", "X"}, {"second", "Y"}}}}}};
 | 
							w << list("declare-datatypes",
 | 
				
			||||||
 | 
								list(list("Pair", 2)),
 | 
				
			||||||
 | 
								list(list("par", list("X", "Y"), list(list("pair", list("first", "X"), list("second", "Y"))))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		w.push();
 | 
							w.push();
 | 
				
			||||||
		w.open(SExpr{"define-fun", name,
 | 
							w.open(list("define-fun", name,
 | 
				
			||||||
			{{"inputs", input_struct.name},
 | 
								list(list("inputs", input_struct.name),
 | 
				
			||||||
			 {"state", state_struct.name}},
 | 
								     list("state", state_struct.name)),
 | 
				
			||||||
			{"Pair", output_struct.name, state_struct.name}});
 | 
								list("Pair", output_struct.name, state_struct.name)));
 | 
				
			||||||
		auto inlined = [&](FunctionalIR::Node n) {
 | 
							auto inlined = [&](FunctionalIR::Node n) {
 | 
				
			||||||
			return n.fn() == FunctionalIR::Fn::constant ||
 | 
								return n.fn() == FunctionalIR::Fn::constant ||
 | 
				
			||||||
				   n.fn() == FunctionalIR::Fn::undriven;
 | 
									   n.fn() == FunctionalIR::Fn::undriven;
 | 
				
			||||||
| 
						 | 
					@ -391,10 +396,10 @@ struct SmtModule {
 | 
				
			||||||
		visitor.n = node_to_sexpr;
 | 
							visitor.n = node_to_sexpr;
 | 
				
			||||||
		for(auto n : ir)
 | 
							for(auto n : ir)
 | 
				
			||||||
			if(!inlined(n)) {
 | 
								if(!inlined(n)) {
 | 
				
			||||||
				w.open(SExpr{"let", {{node_to_sexpr(n), n.visit(visitor)}}}, false);
 | 
									w.open(list("let", list(list(node_to_sexpr(n), n.visit(visitor)))), false);
 | 
				
			||||||
				w.comment(SmtSort(n.sort()).to_sexpr().to_string(), true);
 | 
									w.comment(SmtSort(n.sort()).to_sexpr().to_string(), true);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		w.open(SExpr{"pair"});
 | 
							w.open(list("pair"));
 | 
				
			||||||
		output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.get_output_node(name)); });
 | 
							output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.get_output_node(name)); });
 | 
				
			||||||
		state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.get_state_next_node(name)); });
 | 
							state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.get_state_next_node(name)); });
 | 
				
			||||||
		w.pop();
 | 
							w.pop();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue