metaSMT 2
|
00001 #pragma once 00002 00003 #include "../tags/QF_BV.hpp" 00004 #include "../tags/Array.hpp" 00005 #include "../result_wrapper.hpp" 00006 00007 extern "C" { 00008 #include <boolector.h> 00009 } 00010 00011 #include <iostream> 00012 #include <boost/mpl/map/map40.hpp> 00013 #include <boost/any.hpp> 00014 #include <boost/tuple/tuple.hpp> 00015 #include <list> 00016 00017 namespace metaSMT { 00018 namespace solver { 00019 00020 namespace predtags = ::metaSMT::logic::tag; 00021 namespace bvtags = ::metaSMT::logic::QF_BV::tag; 00022 namespace arraytags = ::metaSMT::logic::Array::tag; 00023 00024 00030 class Boolector { 00031 00032 struct BoolectorAssertion : public std::runtime_error { 00033 BoolectorAssertion(const char* what) 00034 : std::runtime_error(what) {} 00035 }; 00036 00037 static void _boolector_error(int ec) { 00038 throw BoolectorAssertion("internal error in boolector"); 00039 } 00040 00041 public: 00042 typedef BtorExp* result_type; 00043 00044 result_type ptr(BtorExp* expr) { 00045 _exprs.push_back(expr); 00046 return expr; 00047 } 00048 00049 Boolector () 00050 { 00051 _btor = boolector_new(); 00052 boolector_enable_model_gen(_btor); 00053 boolector_enable_inc_usage(_btor); 00054 boolector_abort_function(&Boolector::_boolector_error); 00055 } 00056 00057 ~Boolector() { 00058 for( std::list<BtorExp*>::iterator ite = _exprs.begin(); ite!=_exprs.end(); ++ite) 00059 { 00060 boolector_release(_btor, *ite); 00061 } 00062 boolector_delete(_btor); 00063 } 00064 00065 void assertion( result_type e ) { 00066 boolector_assert(_btor, e); 00067 } 00068 00069 void assumption( result_type e ) { 00070 boolector_assume(_btor, e); 00071 } 00072 00073 bool solve() { 00074 return boolector_sat(_btor) == BOOLECTOR_SAT; 00075 } 00076 00077 result_wrapper read_value(result_type var) 00078 { 00079 char* value = boolector_bv_assignment(_btor, var); 00080 std::string s(value); 00081 boolector_free_bv_assignment(_btor, value); 00082 return result_wrapper(s); 00083 } 00084 00085 result_type operator() (predtags::var_tag const & var, boost::any args ) 00086 { 00087 return ptr(boolector_var(_btor, 1, NULL)); 00088 } 00089 00090 result_type operator() (predtags::false_tag , boost::any arg ) { 00091 return ptr(boolector_false(_btor)); 00092 } 00093 00094 result_type operator() (predtags::true_tag , boost::any arg ) { 00095 return ptr(boolector_true(_btor)); 00096 } 00097 00098 result_type operator() (predtags::not_tag , result_type a) { 00099 return ptr(boolector_not(_btor, a) ); 00100 } 00101 00102 00103 result_type operator() (bvtags::var_tag const & var, boost::any args ) 00104 { 00105 assert ( var.width != 0 ); 00106 return ptr(boolector_var(_btor, var.width, NULL)); 00107 } 00108 00109 result_type operator() (bvtags::bit0_tag , boost::any arg ) { 00110 return ptr(boolector_false(_btor)); 00111 } 00112 00113 result_type operator() (bvtags::bit1_tag , boost::any arg ) { 00114 return ptr(boolector_true(_btor)); 00115 } 00116 00117 result_type operator() (bvtags::bvuint_tag , boost::any arg ) { 00118 typedef boost::tuple<unsigned long, unsigned long> P; 00119 P p = boost::any_cast<P>(arg); 00120 //std::cout << "bvuint "<< p << std::endl; 00121 unsigned value = boost::get<0>(p); 00122 unsigned width = boost::get<1>(p); 00123 return ptr(boolector_unsigned_int(_btor, value , width )); 00124 } 00125 00126 result_type operator() (bvtags::bvsint_tag , boost::any arg ) { 00127 typedef boost::tuple<long, unsigned long> P; 00128 P p = boost::any_cast<P>(arg); 00129 return ptr(boolector_int(_btor, boost::get<0>(p), boost::get<1>(p))); 00130 } 00131 00132 result_type operator() (bvtags::bvbin_tag , boost::any arg ) { 00133 std::string val = boost::any_cast<std::string>(arg); 00134 return ptr(boolector_const(_btor, val.c_str())); 00135 } 00136 00137 result_type operator() (bvtags::bvhex_tag , boost::any arg ) { 00138 std::string hex = boost::any_cast<std::string>(arg); 00139 std::string bin (hex.size()*4,'\0'); 00140 00141 for (unsigned i = 0; i < hex.size(); ++i) { 00142 switch ( tolower(hex[i]) ) { 00143 case '0': 00144 bin.replace(4*i,4, "0000"); 00145 break; 00146 case '1': 00147 bin.replace(4*i,4, "0001"); 00148 break; 00149 case '2': 00150 bin.replace(4*i,4, "0010"); 00151 break; 00152 case '3': 00153 bin.replace(4*i,4, "0011"); 00154 break; 00155 case '4': 00156 bin.replace(4*i,4, "0100"); 00157 break; 00158 case '5': 00159 bin.replace(4*i,4, "0101"); 00160 break; 00161 case '6': 00162 bin.replace(4*i,4, "0110"); 00163 break; 00164 case '7': 00165 bin.replace(4*i,4, "0111"); 00166 break; 00167 case '8': 00168 bin.replace(4*i,4, "1000"); 00169 break; 00170 case '9': 00171 bin.replace(4*i,4, "1001"); 00172 break; 00173 case 'a': 00174 bin.replace(4*i,4, "1010"); 00175 break; 00176 case 'b': 00177 bin.replace(4*i,4, "1011"); 00178 break; 00179 case 'c': 00180 bin.replace(4*i,4, "1100"); 00181 break; 00182 case 'd': 00183 bin.replace(4*i,4, "1101"); 00184 break; 00185 case 'e': 00186 bin.replace(4*i,4, "1110"); 00187 break; 00188 case 'f': 00189 bin.replace(4*i,4, "1111"); 00190 break; 00191 } 00192 } 00193 //std::cout << bin << std::endl; 00194 return ptr(boolector_const(_btor, bin.c_str())); 00195 } 00196 00197 result_type operator() (bvtags::bvnot_tag , result_type a ) { 00198 return ptr(boolector_not(_btor, a)); 00199 } 00200 00201 result_type operator() (bvtags::bvneg_tag , result_type a ) { 00202 return ptr(boolector_neg(_btor, a)); 00203 } 00204 00205 result_type operator() (bvtags::extract_tag const & 00206 , unsigned long upper, unsigned long lower 00207 , result_type e) 00208 { 00209 return ptr(boolector_slice(_btor, e, upper, lower)); 00210 } 00211 00212 result_type operator() (bvtags::zero_extend_tag const & 00213 , unsigned long width 00214 , result_type e) 00215 { 00216 return ptr(boolector_uext(_btor, e, width)); 00217 } 00218 00219 result_type operator() (bvtags::sign_extend_tag const & 00220 , unsigned long width 00221 , result_type e) 00222 { 00223 return ptr(boolector_sext(_btor, e, width)); 00224 } 00225 00226 result_type operator() (arraytags::array_var_tag const & var 00227 , boost::any args ) 00228 { 00229 return ptr(boolector_array(_btor, var.elem_width, var.index_width, NULL)); 00230 } 00231 00232 result_type operator() (arraytags::select_tag const & 00233 , result_type array 00234 , result_type index) { 00235 return ptr(boolector_read(_btor, array, index)); 00236 } 00237 00238 result_type operator() (arraytags::store_tag const & 00239 , result_type array 00240 , result_type index 00241 , result_type value) { 00242 return ptr(boolector_write(_btor, array, index, value)); 00243 } 00244 00245 result_type operator() (predtags::ite_tag tag, result_type a, result_type b, result_type c) { 00246 return ptr(boolector_cond(_btor, a, b, c)); 00247 } 00248 00250 // Fallback operators // 00252 00253 template <typename TagT> 00254 result_type operator() (TagT tag, boost::any args ) { 00255 return ptr(boolector_false(_btor)); 00256 } 00257 00258 00259 template <typename TagT> 00260 result_type operator() (TagT tag, result_type a ) { 00261 return ptr(boolector_false(_btor)); 00262 } 00263 00264 template< BtorExp* (*FN) (Btor*, BtorExp*, BtorExp*) > 00265 struct Btor_F2 { 00266 static BtorExp* exec(Btor* b , BtorExp* x, BtorExp* y) 00267 { return (*FN)(b,x,y);} 00268 }; 00269 00270 template <typename TagT> 00271 result_type operator() (TagT tag, result_type a, result_type b) { 00272 namespace mpl = boost::mpl; 00273 00274 typedef mpl::map35< 00275 // binary Logic tags 00276 mpl::pair<predtags::equal_tag, Btor_F2<&boolector_eq> > 00277 , mpl::pair<predtags::nequal_tag, Btor_F2<&boolector_ne> > 00278 , mpl::pair<predtags::and_tag, Btor_F2<&boolector_and> > 00279 , mpl::pair<predtags::nand_tag, Btor_F2<&boolector_nand> > 00280 , mpl::pair<predtags::or_tag, Btor_F2<&boolector_or> > 00281 , mpl::pair<predtags::nor_tag, Btor_F2<&boolector_nor> > 00282 , mpl::pair<predtags::xor_tag, Btor_F2<&boolector_xor> > 00283 , mpl::pair<predtags::xnor_tag, Btor_F2<&boolector_xnor> > 00284 , mpl::pair<predtags::implies_tag, Btor_F2<&boolector_implies> > 00285 // binary QF_BV tags 00286 , mpl::pair<bvtags::bvand_tag, Btor_F2<&boolector_and> > 00287 , mpl::pair<bvtags::bvnand_tag, Btor_F2<&boolector_nand> > 00288 , mpl::pair<bvtags::bvor_tag, Btor_F2<&boolector_or> > 00289 , mpl::pair<bvtags::bvnor_tag, Btor_F2<&boolector_nor> > 00290 , mpl::pair<bvtags::bvxor_tag, Btor_F2<&boolector_xor> > 00291 , mpl::pair<bvtags::bvxnor_tag, Btor_F2<&boolector_xnor> > 00292 , mpl::pair<bvtags::bvadd_tag, Btor_F2<&boolector_add> > 00293 , mpl::pair<bvtags::bvsub_tag, Btor_F2<&boolector_sub> > 00294 , mpl::pair<bvtags::bvmul_tag, Btor_F2<&boolector_mul> > 00295 , mpl::pair<bvtags::bvudiv_tag, Btor_F2<&boolector_udiv> > 00296 , mpl::pair<bvtags::bvurem_tag, Btor_F2<&boolector_urem> > 00297 , mpl::pair<bvtags::bvsdiv_tag, Btor_F2<&boolector_sdiv> > 00298 , mpl::pair<bvtags::bvsrem_tag, Btor_F2<&boolector_srem> > 00299 , mpl::pair<bvtags::bvcomp_tag, Btor_F2<&boolector_eq > > 00300 , mpl::pair<bvtags::bvslt_tag, Btor_F2<&boolector_slt > > 00301 , mpl::pair<bvtags::bvsle_tag, Btor_F2<&boolector_slte > > 00302 , mpl::pair<bvtags::bvsgt_tag, Btor_F2<&boolector_sgt > > 00303 , mpl::pair<bvtags::bvsge_tag, Btor_F2<&boolector_sgte > > 00304 , mpl::pair<bvtags::bvult_tag, Btor_F2<&boolector_ult > > 00305 , mpl::pair<bvtags::bvule_tag, Btor_F2<&boolector_ulte > > 00306 , mpl::pair<bvtags::bvugt_tag, Btor_F2<&boolector_ugt > > 00307 , mpl::pair<bvtags::bvuge_tag, Btor_F2<&boolector_ugte > > 00308 , mpl::pair<bvtags::concat_tag, Btor_F2<&boolector_concat > > 00309 , mpl::pair<bvtags::bvshl_tag, Btor_F2<&boolector_sll > > 00310 , mpl::pair<bvtags::bvshr_tag, Btor_F2<&boolector_srl > > 00311 , mpl::pair<bvtags::bvashr_tag, Btor_F2<&boolector_sra > > 00312 > Opcode_Map; 00313 00314 typedef 00315 typename mpl::has_key< Opcode_Map, TagT >::type 00316 _has_key; 00317 00318 if (_has_key::value ) { 00319 typedef typename mpl::eval_if< 00320 _has_key 00321 , mpl::at< Opcode_Map, TagT > 00322 , mpl::identity< Btor_F2<boolector_and> > 00323 >::type opcode; 00324 return ptr(opcode::exec(_btor, a, b)); 00325 } else { 00326 std::cout << "unknown operator: " << tag << std::endl; 00327 00328 assert(false && "unknown operator"); 00329 return ptr(boolector_false(_btor)); 00330 } 00331 } 00332 00333 00334 template <typename TagT> 00335 result_type operator() (TagT tag, result_type a, result_type b, result_type c) { 00336 return ptr(boolector_false(_btor)); 00337 } 00338 00339 00340 /* pseudo command */ 00341 void command ( Boolector const & ) { }; 00342 00343 private: 00344 Btor *_btor; 00345 std::list<BtorExp*> _exprs; 00346 }; 00347 00350 } // namespace solver 00351 } // namespace metaSMT 00352 00353 // vim: ft=cpp:ts=2:sw=2:expandtab