00001 package gov.nasa.arc.ase.jpf;
00002
00003
00004 import gov.nasa.arc.ase.util.Debug;
00005 import java.util.Stack;
00006
00007 public class LTL implements iSearch {
00008 public static final boolean FIRST_DFS = true;
00009 public static final boolean SECOND_DFS = false;
00010
00011 public static final int OLD_OFF_STACK = -1;
00012 public static final int NEW = -2;
00013
00014 private boolean done = false;
00015 private boolean failed = false;
00016 private boolean deadlock = false;
00017 private Path errorPath;
00018 private ErrorTrailInterface error;
00019
00020 private Stack buchiStack;
00021 private Stack buchiSchStack;
00022 private Stack acptStack;
00023 private int buchiState;
00024 private Sch buchiSch;
00025 private SM buchi;
00026 private BuchiSet buchiSet;
00027 private Stack buchiSetStack;
00028
00029 public LTL() {
00030 Debug.println(Debug.MESSAGE, "LTL Search");
00031 initBuchi();
00032 }
00033 public int acptStack_peek() {
00034 if(acptStack.size() == 0) return -1;
00035
00036 return ((Integer)acptStack.peek()).intValue();
00037 }
00038 public void acptStack_pop(int index) {
00039 if(buchi.accepting[buchiState])
00040 acptStack.pop();
00041 }
00042 public void acptStack_push(int index) {
00043 if(buchi.accepting[buchiState])
00044 acptStack.push(new Integer(index));
00045 }
00046 public void buchi_backtrack() {
00047 buchi_pop();
00048 buchiSch_pop();
00049 }
00050 public boolean buchi_forward() {
00051 buchi_push();
00052 boolean buchi_move = buchi_next();
00053 buchiSch_push();
00054
00055 return buchi_move;
00056 }
00057 public boolean buchi_next() {
00058 SM b = buchi;
00059 b.setSch(buchiSch);
00060
00061 int nt = b.getTransitionCount(buchiState);
00062 int t = -1;
00063 boolean enabled = false;
00064 boolean first = buchiSch.getTransition() == 0 && buchiSch.getRandom() == 0;
00065
00066 if(!first) {
00067 while(buchiSch.getTransition() < nt) {
00068 t = buchiSch.getTransition();
00069 if(b.getGuard(buchiState, t) != null) {
00070 if(b.isEnabled(buchiState, t)) {
00071 enabled = true;
00072 break;
00073 } else
00074 buchiSch.getNextTransition();
00075 } else
00076 buchiSch.getNextTransition();
00077 }
00078 } else {
00079 while(buchiSch.getTransition() < nt) {
00080 t = buchiSch.getTransition();
00081 if(b.getGuard(buchiState, t) != null) {
00082 if(b.isEnabled(buchiState, t)) {
00083 enabled = true;
00084 break;
00085 } else
00086 buchiSch.getNextTransition();
00087 } else {
00088 enabled = true;
00089 break;
00090 }
00091 }
00092 }
00093
00094 if(!enabled) {
00095 buchiSch.getNextTransition();
00096 return false;
00097 }
00098
00099
00100
00101
00102 int r = buchiSch.getRandom();
00103 buchiState = b.execute(buchiState, t);
00104 if(r == buchiSch.getRandom())
00105 buchiSch.getNextTransition();
00106
00107
00108
00109
00110 return true;
00111 }
00112 public void buchi_pop() {
00113 buchiState = ((Integer)buchiStack.pop()).intValue();
00114 }
00115 public void buchi_push() {
00116 buchiStack.push(new Integer(buchiState));
00117 }
00118 public void buchi_undo() {
00119 int t = buchiSch.getTransition();
00120 int r = buchiSch.getRandom();
00121
00122 buchi.backtrack(buchiState, r == 0 ? t-1 : t);
00123 }
00124 public void buchiSch_pop() {
00125 buchiSch = (Sch)buchiSchStack.pop();
00126 }
00127 public void buchiSch_push() {
00128 buchiSchStack.push(buchiSch.copy());
00129 }
00130 private void buchiSet_get() {
00131 buchiSet = Engine.getJPF().vm.BuchiGet();
00132 }
00133 private void buchiSet_pop() {
00134 buchiSet = (BuchiSet)buchiSetStack.pop();
00135 }
00136 private void buchiSet_push() {
00137 buchiSetStack.push(buchiSet);
00138 buchiSet = null;
00139 }
00140 private void error() {
00141 failed = true;
00142 if (Engine.options.bandera) {
00143 errorPath = Engine.getJPF().vm.getErrorTrail1();
00144 } else {
00145 error = Engine.getJPF().vm.getErrorTrail();
00146 }
00147 done = !Engine.options.multiple_errors;
00148 }
00149 public ErrorTrailInterface getError() {
00150 return error;
00151 }
00152 public String getErrorMessage() {
00153 if(!failed) return "No Errors Found";
00154
00155 if(deadlock) return "Deadlock found";
00156
00157 return Engine.getJPF().vm.getErrorMessage();
00158 }
00159 public Path getErrorPath() {
00160 return errorPath;
00161 }
00162 public boolean hasFailed() {
00163 return failed;
00164 }
00165 public void initBuchi() {
00166 buchi = SM.load(Engine.options.buchi);
00167
00168 buchiStack = new Stack();
00169 buchiSchStack = new Stack();
00170 acptStack = new Stack();
00171 buchiSetStack = new Stack();
00172
00173 buchiState = 0;
00174 }
00175 private void off_stack(boolean first) {
00176 buchiSet.replace((first ? 0x80000000 : 0) | buchiState, OLD_OFF_STACK);
00177 }
00178 public void search() {
00179
00180
00181
00182 search(FIRST_DFS, 0);
00183
00184
00185
00186 }
00187 private boolean search(boolean first, int stack_start) {
00188 int index = stack_start;
00189 boolean up = false;
00190 iVirtualMachine vm = Engine.getJPF().vm;
00191 Status status = Engine.getJPF().status;
00192
00193 Down:
00194 while(true) {
00195 vm.BuchiInitSch();
00196 while(true) {
00197 boolean buchiSet_get = false;
00198
00199 if(!up) {
00200 int result = vm.BuchiForward();
00201
00202 if(TransitionResult.isError(result)) {
00203 error();
00204 return true;
00205 }
00206
00207 if(TransitionResult.isEnd(result)) {
00208
00209
00210
00211 break;
00212 }
00213
00214
00215
00216
00217
00218 buchiSch = new Sch();
00219 buchiSet_get = true;
00220 }
00221
00222 while(true) {
00223 if(up) {
00224
00225 Debug.println(Debug.MESSAGE, "Going up");
00226
00227 up = false; index--;
00228 buchiSet_pop();
00229 off_stack(first);
00230 acptStack_pop(index);
00231 buchi_backtrack();
00232 buchi_undo();
00233 continue;
00234 }
00235
00236 if(!buchi_forward()) {
00237
00238
00239
00240 buchi_backtrack();
00241 break;
00242 }
00243
00244
00245
00246
00247
00248 if(buchiSet_get) buchiSet_get();
00249 vm.BuchiSetState(buchiState);
00250 int currently = store(first, index);
00251
00252 if(buchi.trivial[buchiState])
00253 if(buchi.accepting[buchiState]) {
00254 error();
00255 return true;
00256 } else {
00257 Debug.println(Debug.ERROR, "Reached a non-accepting trivial state");
00258 buchi_backtrack();
00259 buchi_undo();
00260 break;
00261 }
00262
00263 if(currently == NEW) {
00264
00265
00266
00267 status.states++;
00268 if(index != 0) status.transitions++;
00269 acptStack_push(index);
00270 index++;
00271 buchiSet_push();
00272 continue Down;
00273 } else {
00274
00275
00276
00277 status.transitions++;
00278 if(currently != OLD_OFF_STACK) {
00279
00280
00281
00282 if(currently <= acptStack_peek()) {
00283 error();
00284 Debug.println(Debug.ERROR, "Cycle detected");
00285 return true;
00286 }
00287 } else {
00288
00289
00290
00291 }
00292 }
00293
00294 buchi_backtrack();
00295 buchi_undo();
00296 }
00297
00298 vm.BuchiBacktrack();
00299 }
00300
00301 if(first && buchi.accepting[buchiState]) {
00302 if(!buchi.persistant[buchiState]) {
00303
00304
00305
00306 vm.BuchiInitSch();
00307 boolean violation = search(SECOND_DFS, index);
00308
00309
00310
00311 if(violation) return true;
00312 }
00313 }
00314
00315 if(index == stack_start) break;
00316
00317
00318 Debug.println(Debug.MESSAGE, "Going up now");
00319
00320 up = true;
00321 }
00322
00323 return false;
00324 }
00325 private int store(boolean first, int index) {
00326 int b = 0x80000000 | buchiState;
00327
00328
00329
00330
00331
00332
00333 if(!first) {
00334 int d = buchiSet.get(b);
00335 if(d > OLD_OFF_STACK) {
00336
00337
00338
00339 return d;
00340 }
00341 b &= 0x7FFFFFFF;
00342 }
00343
00344 int d = buchiSet.get(b);
00345 if(d >= OLD_OFF_STACK) {
00346
00347
00348
00349 return d;
00350 }
00351
00352 buchiSet.add(b, index);
00353
00354 return NEW;
00355 }
00356 }