1 /******************************************************************** 2 * AUTHORS: Vijay Ganesh 3 * 4 * BEGIN DATE: November, 2005 5 * 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 ********************************************************************/ 24 25 #ifndef STPMGR_H 26 #define STPMGR_H 27 28 #include "stp/AST/ASTBVConst.h" 29 #include "stp/AST/ASTInterior.h" 30 #include "stp/AST/ASTNode.h" 31 #include "stp/AST/ASTSymbol.h" 32 33 #include "stp/AST/AST.h" 34 #include "stp/AST/NodeFactory/HashingNodeFactory.h" 35 #include "stp/STPManager/UserDefinedFlags.h" 36 #include "stp/Sat/SATSolver.h" 37 #include "stp/Util/Attributes.h" 38 39 namespace stp 40 { 41 /* 42 * STP Node Manager. Tools for managing AST nodes. 43 */ 44 class STPMgr 45 { 46 friend class ASTNode; 47 friend class ASTInterior; 48 friend class ASTBVConst; 49 friend class ASTSymbol; 50 friend ASTNode HashingNodeFactory::CreateNode(const Kind kind, 51 const ASTVec& back_children); 52 53 private: 54 // Typedef for unique Interior node table. 55 typedef std::unordered_set<ASTInterior*, ASTInterior::ASTInteriorHasher, 56 ASTInterior::ASTInteriorEqual> 57 ASTInteriorSet; 58 59 // Typedef for unique Symbol node (leaf) table. 60 typedef std::unordered_set<ASTSymbol*, ASTSymbol::ASTSymbolHasher, 61 ASTSymbol::ASTSymbolEqual> 62 ASTSymbolSet; 63 64 // Typedef for unique BVConst node (leaf) table. 65 typedef std::unordered_set<ASTBVConst*, ASTBVConst::ASTBVConstHasher, 66 ASTBVConst::ASTBVConstEqual> 67 ASTBVConstSet; 68 69 // Unique node tables that enables common subexpression sharing 70 ASTInteriorSet _interior_unique_table; 71 72 // Table for variable names, let names etc. 73 ASTSymbolSet _symbol_unique_table; 74 75 // Table to uniquefy bvconst 76 ASTBVConstSet _bvconst_unique_table; 77 78 uint8_t last_iteration; 79 80 public: 81 HashingNodeFactory* hashingNodeFactory; 82 NodeFactory* defaultNodeFactory; 83 84 // frequently used nodes 85 ASTNode ASTFalse, ASTTrue, ASTUndefined; 86 87 bool soft_timeout_expired; 88 89 // No nodes should already have the iteration number that is returned from 90 // here. This never returns zero. getNextIteration()91 uint8_t getNextIteration() 92 { 93 if (last_iteration == 255) 94 { 95 resetIteration(); 96 last_iteration = 0; 97 } 98 99 uint8_t result = ++last_iteration; 100 assert(result != 0); 101 return result; 102 } 103 104 // Detauls the iteration count back to zero. resetIteration()105 void resetIteration() 106 { 107 for (ASTInteriorSet::iterator it = _interior_unique_table.begin(); 108 it != _interior_unique_table.end(); it++) 109 { 110 (*it)->iteration = 0; 111 } 112 113 for (ASTSymbolSet::iterator it = _symbol_unique_table.begin(); 114 it != _symbol_unique_table.end(); it++) 115 { 116 (*it)->iteration = 0; 117 } 118 119 for (ASTBVConstSet::iterator it = _bvconst_unique_table.begin(); 120 it != _bvconst_unique_table.end(); it++) 121 { 122 (*it)->iteration = 0; 123 } 124 } 125 getAssertLevel()126 size_t getAssertLevel() { return _asserts.size(); } 127 128 private: 129 // Stack of Logical Context. each entry in the stack is a logical 130 // context. A logical context is a vector of assertions. The 131 // logical context is represented by a ptr to a vector of 132 // assertions in that logical context. Logical contexts are 133 // created by PUSH/POP 134 vector<ASTVec*> _asserts; 135 136 // Memo table that tracks terms already seen 137 ASTNodeMap TermsAlreadySeenMap; 138 139 // The query for the current logical context. BUG probably wrongly handled 140 // and gets mixed up with the state, which it shouldn't (otherwise, next 141 // query will be affected) 142 ASTNode _current_query; 143 144 // Ptr to class that reports on the running time of various parts 145 // of the code 146 RunTimes* runTimes; 147 148 /**************************************************************** 149 * Private Member Functions * 150 ****************************************************************/ 151 152 // Destructively appends back_child nodes to front_child nodes. 153 // If back_child nodes is NULL, no appending is done. back_child 154 // nodes are not modified. Then it returns the hashed copy of the 155 // node, which is created if necessary. 156 ASTInterior* CreateInteriorNode(Kind kind, ASTInterior* new_node, 157 const ASTVec& back_children = _empty_ASTVec); 158 159 // Create unique ASTInterior node. 160 ASTInterior* LookupOrCreateInterior(ASTInterior* n); 161 162 // Create unique ASTSymbol node. 163 ASTSymbol* LookupOrCreateSymbol(ASTSymbol& s); 164 165 // Called whenever we want to make sure that the Symbol is 166 // declared during semantic analysis 167 bool LookupSymbol(ASTSymbol& s); 168 169 // Called by ASTNode constructors to uniqueify ASTBVConst 170 ASTBVConst* LookupOrCreateBVConst(ASTBVConst& s); 171 172 // Cache of zero/one/max BVConsts of different widths. 173 ASTVec zeroes; 174 ASTVec ones; 175 ASTVec max; 176 177 // Set of new symbols introduced that replace the array read terms 178 ASTNodeSet Introduced_SymbolsSet; 179 180 CBV CreateBVConstVal; 181 182 public: 183 bool LookupSymbol(const char* const name); 184 bool LookupSymbol(const char* const name, ASTNode& output); 185 186 /**************************************************************** 187 * Public Flags * 188 ****************************************************************/ 189 UserDefinedFlags UserFlags; 190 191 // This flag, when true, indicates that counterexample is being 192 // checked by the counterexample checker 193 bool counterexample_checking_during_refinement; 194 195 // This flag indicates as to whether the input has been determined 196 // to be valid or not by this tool 197 bool ValidFlag; 198 199 // Flags indicates that counterexample will now be checked by the 200 // counterexample checker, and hence simplifyterm must switch off 201 // certain optimizations. In particular, array write optimizations 202 bool SimplifyWrites_InPlace_Flag; 203 204 // count is used in the creation of new variables 205 unsigned int _symbol_count; 206 207 // The value to append to the filename when saving the CNF. 208 unsigned int CNFFileNameCounter; 209 210 /**************************************************************** 211 * Public Member Functions * 212 ****************************************************************/ 213 STPMgr()214 DLL_PUBLIC STPMgr() 215 : last_iteration(0), soft_timeout_expired(false), _symbol_count(0), 216 CNFFileNameCounter(0) 217 { 218 ValidFlag = false; 219 counterexample_checking_during_refinement = false; 220 SimplifyWrites_InPlace_Flag = false; 221 222 // Need to initiate the node factories before any nodes are created. 223 hashingNodeFactory = new HashingNodeFactory(*this); 224 defaultNodeFactory = hashingNodeFactory; 225 226 ASTFalse = CreateNode(FALSE); 227 ASTTrue = CreateNode(TRUE); 228 ASTUndefined = CreateNode(UNDEFINED); 229 runTimes = new RunTimes(); 230 _current_query = ASTUndefined; 231 CreateBVConstVal = NULL; 232 } 233 GetRunTimes(void)234 RunTimes* GetRunTimes(void) { return runTimes; } 235 236 unsigned int NodeSize(const ASTNode& a); 237 238 /**************************************************************** 239 * Create Symbol and BVConst functions * 240 ****************************************************************/ 241 242 // Create and return an ASTNode for a symbol 243 ASTNode LookupOrCreateSymbol(const char* const name); 244 245 // Create and return an ASTNode for a symbol Width is number of bits. 246 ASTNode CreateOneConst(unsigned int width); 247 ASTNode CreateTwoConst(unsigned int width); 248 ASTNode CreateMaxConst(unsigned int width); 249 ASTNode CreateZeroConst(unsigned int width); 250 DLL_PUBLIC ASTNode CreateBVConst(CBV bv, unsigned width); 251 ASTNode CreateBVConst(const char* strval, int base); 252 ASTNode CreateBVConst(std::string strval, int base, int bit_width); 253 ASTNode CreateBVConst(unsigned int width, unsigned long long int bvconst); 254 ASTNode charToASTNode(unsigned char* strval, int base, int bit_width); 255 256 /**************************************************************** 257 * Create Node functions * 258 ****************************************************************/ 259 260 DLL_PUBLIC inline ASTNode CreateSymbol(const char * const name,unsigned indexWidth,unsigned valueWidth)261 CreateSymbol(const char* const name, unsigned indexWidth, unsigned valueWidth) 262 { 263 return defaultNodeFactory->CreateSymbol(name, indexWidth, valueWidth); 264 } 265 266 // Create and return an interior ASTNode 267 DLL_PUBLIC inline ASTNode CreateNode(stp::Kind kind, 268 const ASTVec& children = _empty_ASTVec) 269 { 270 return defaultNodeFactory->CreateNode(kind, children); 271 } 272 273 DLL_PUBLIC inline ASTNode 274 CreateNode(Kind kind, const ASTNode& child0, 275 const ASTVec& back_children = _empty_ASTVec) 276 { 277 return defaultNodeFactory->CreateNode(kind, child0, back_children); 278 } 279 280 DLL_PUBLIC inline ASTNode 281 CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1, 282 const ASTVec& back_children = _empty_ASTVec) 283 { 284 return defaultNodeFactory->CreateNode(kind, child0, child1, back_children); 285 } 286 287 DLL_PUBLIC inline ASTNode 288 CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1, 289 const ASTNode& child2, const ASTVec& back_children = _empty_ASTVec) 290 { 291 return defaultNodeFactory->CreateNode(kind, child0, child1, child2, 292 back_children); 293 } 294 295 /**************************************************************** 296 * Create Term functions * 297 ****************************************************************/ 298 299 // Create and return an ASTNode for a term 300 inline ASTNode CreateTerm(stp::Kind kind, unsigned int width, 301 const ASTVec& children = _empty_ASTVec) 302 { 303 return defaultNodeFactory->CreateTerm(kind, width, children); 304 } 305 306 inline ASTNode CreateArrayTerm(stp::Kind kind, unsigned int indexWidth, 307 unsigned int width, 308 const ASTVec& children = _empty_ASTVec) 309 { 310 return defaultNodeFactory->CreateArrayTerm(kind, indexWidth, width, 311 children); 312 } 313 314 inline ASTNode CreateTerm(Kind kind, unsigned int width, 315 const ASTNode& child0, 316 const ASTVec& children = _empty_ASTVec) 317 { 318 return defaultNodeFactory->CreateTerm(kind, width, child0, children); 319 } 320 321 inline ASTNode CreateTerm(Kind kind, unsigned int width, 322 const ASTNode& child0, const ASTNode& child1, 323 const ASTVec& children = _empty_ASTVec) 324 { 325 return defaultNodeFactory->CreateTerm(kind, width, child0, child1, 326 children); 327 } 328 329 inline ASTNode CreateTerm(Kind kind, unsigned int width, 330 const ASTNode& child0, const ASTNode& child1, 331 const ASTNode& child2, 332 const ASTVec& /*children*/ = _empty_ASTVec) 333 { 334 return defaultNodeFactory->CreateTerm(kind, width, child0, child1, child2); 335 } 336 337 /**************************************************************** 338 * Functions that manage logical context * 339 ****************************************************************/ 340 341 void Pop(void); 342 void Push(void); 343 344 // Queries aren't maintained on a stack. 345 // Used by CVC & C-interface. 346 const ASTNode GetQuery(); 347 void SetQuery(const ASTNode& q); 348 349 const ASTVec GetAsserts(); 350 const ASTVec getVectorOfAsserts(); 351 352 // add a query/assertion to the current logical context 353 void AddAssert(const ASTNode& assert); 354 355 /**************************************************************** 356 * Toplevel printing and stats functions * 357 ****************************************************************/ 358 359 // For printing purposes 360 // Used just by the CVC parser. 361 ASTVec ListOfDeclaredVars; 362 363 // For printing purposes 364 // Used just via the C-interface. 365 // Note, not maintained properly wrt push/pops 366 vector<stp::ASTNode> decls; 367 368 // Nodes seen so far 369 ASTNodeSet PLPrintNodeSet; 370 371 // Map from ASTNodes to LetVars 372 ASTNodeMap NodeLetVarMap; 373 374 // This is a vector which stores the Node to LetVars pairs. It 375 // allows for sorted printing, as opposed to NodeLetVarMap 376 vector<std::pair<ASTNode, ASTNode>> NodeLetVarVec; 377 378 // A partial Map from ASTNodes to LetVars. Needed in order to 379 // correctly print shared subterms inside the LET itself 380 ASTNodeMap NodeLetVarMap1; 381 382 // prints statistics for the ASTNode. 383 void ASTNodeStats(const char* c, const ASTNode& a); 384 385 // Print variable to the input stream 386 void printVarDeclsToStream(ostream& os, ASTNodeSet& symbols); 387 388 // Print assertions to the input stream 389 void printAssertsToStream(ostream& os); 390 391 // Variables are added automatically to the introduced_symbolset. Variables 392 // in the set aren't printed out as part of the counter example. CreateFreshVariable(int indexWidth,int valueWidth,std::string prefix)393 ASTNode CreateFreshVariable(int indexWidth, int valueWidth, 394 std::string prefix) 395 { 396 char* d = (char*)alloca(sizeof(char) * (32 + prefix.length())); 397 sprintf(d, "%s_%d", prefix.c_str(), _symbol_count++); 398 assert(!LookupSymbol(d)); 399 400 ASTNode CurrentSymbol = CreateSymbol(d, indexWidth, valueWidth); 401 Introduced_SymbolsSet.insert(CurrentSymbol); 402 return CurrentSymbol; 403 } 404 FoundIntroducedSymbolSet(const ASTNode & in)405 bool FoundIntroducedSymbolSet(const ASTNode& in) 406 { 407 if (Introduced_SymbolsSet.find(in) != Introduced_SymbolsSet.end()) 408 { 409 return true; 410 } 411 return false; 412 } 413 414 bool VarSeenInTerm(const ASTNode& var, const ASTNode& term); 415 416 ASTNode NewParameterized_BooleanVar(const ASTNode& var, 417 const ASTNode& constant); 418 TermsAlreadySeenMap_Clear(void)419 void TermsAlreadySeenMap_Clear(void) { TermsAlreadySeenMap.clear(); } 420 421 // This is called before SAT solving, so only junk that isn't needed 422 // after SAT solving should be cleaned out. ClearAllTables(void)423 void ClearAllTables(void) 424 { 425 NodeLetVarMap.clear(); 426 NodeLetVarMap1.clear(); 427 PLPrintNodeSet.clear(); 428 TermsAlreadySeenMap.clear(); 429 NodeLetVarVec.clear(); 430 ListOfDeclaredVars.clear(); 431 } 432 433 DLL_PUBLIC ~STPMgr(); 434 435 // Used just via the C-Interface, to allow some nodes to be automaticaly deleted. 436 vector<stp::ASTNode*> persist; 437 print_stats()438 void print_stats() const 439 { 440 441 if (_interior_unique_table.size() > 0) 442 { 443 std::cerr << "Interiors:" << _interior_unique_table.size() << " of "; 444 std::cerr << sizeof(**_interior_unique_table.begin()) << " bytes each" 445 << std::endl; 446 } 447 448 std::map<Kind, int> freq; 449 for (auto it : _interior_unique_table) 450 { 451 freq[it->GetKind()]++; 452 } 453 454 for (auto it : freq) 455 std::cerr << it.first << " " << it.second << std::endl; 456 457 if (_symbol_unique_table.size() > 0) 458 { 459 std::cerr << "Symbols:" << _symbol_unique_table.size() << " of "; 460 std::cerr << sizeof(**_symbol_unique_table.begin()) << " bytes each" 461 << std::endl; 462 } 463 464 if (_bvconst_unique_table.size() > 0) 465 { 466 std::cerr << "BVConsts:" << _bvconst_unique_table.size() << " of "; 467 std::cerr << sizeof(**_bvconst_unique_table.begin()) << " bytes each" 468 << std::endl; 469 } 470 } 471 }; 472 473 } // end of namespace 474 475 #endif 476