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