00001 package edu.ksu.cis.bandera.smv;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.io.*;
00036 import java.util.Vector;
00037 import java.util.Hashtable;
00038
00039 import edu.ksu.cis.bandera.bir.*;
00040 import edu.ksu.cis.bandera.checker.*;
00041 import java.util.List;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 public class SmvTrans extends AbstractExprSwitch implements BirConstants, Checker
00061 {
00062 TransSystem system;
00063 PrintWriter out;
00064
00065 boolean ranVerifier;
00066
00067 SmvOptions options;
00068 boolean liveness;
00069 boolean ctlproperty;
00070 boolean interleaving;
00071
00072 int indentLevel = 0;
00073 boolean newLine = true;
00074
00075 Hashtable varTable = new Hashtable();
00076 Vector varList = new Vector();
00077
00078 Hashtable guardTable = new Hashtable();
00079
00080
00081 int maxCollectionSize;
00082 String threadType;
00083
00084 Transformation currentTrans;
00085 SmvExpr currentGuard;
00086
00087 SmvVar choiceVar;
00088 SmvVar trapVar;
00089 SmvVar runningVar;
00090
00091
00092 final static SmvLit ZERO = new SmvLit("0");
00093 final static SmvLit ONE = new SmvLit("1");
00094 final static SmvLit NOTHREAD = new SmvLit("NoThread");
00095 final static String TRAP_TYPE =
00096 "{ None, NullPointerException, ArrayBoundsException, ClassCastException, RangeLimitException, CollectionLimitException, ArrayLimitException }";
00097
00098
00099 final static String LOCK_COUNT_TYPE = "0 .. 3";
00100
00101
00102 boolean doneParsing;
00103 boolean foundFalse;
00104 boolean foundTrace;
00105 int stateCount;
00106 Location [] threadLocs;
00107 Transformation lastTrans;
00108 Hashtable threadTable;
00109
00110
00111 static Runtime runtime = Runtime.getRuntime();
00112 static final int BUFSIZE = 50000;
00113 static byte [] buffer = new byte[BUFSIZE];
00114 SmvTrans(TransSystem system, SmvOptions options, PrintWriter out) {
00115 this.system = system;
00116 this.options = options;
00117 this.out = out;
00118 liveness = ! options.getSafety();
00119 ctlproperty = options.getProperty();
00120 interleaving = options.getInterleaving();
00121
00122
00123 ThreadVector threads = system.getThreads();
00124 threadType = "NoThread";
00125 for (int i = 0; i < threads.size(); i++)
00126 threadType += ", " + threads.elementAt(i).getName();
00127 threadType = "{ " + threadType + " }";
00128 }
00129
00130
00131 String activeVar(BirThread thread) {
00132 return thread.getName() + "_active";
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 SmvNaryExpr addConditionalContext(SmvNaryExpr expr, SmvCase context) {
00144 while (context != null) {
00145 expr.add(context.cond);
00146 context = context.parent.outerCase;
00147 }
00148 return expr;
00149 }
00150 SmvExpr and(SmvExpr expr1, SmvExpr expr2)
00151 {
00152 return new SmvBinaryExpr("&",expr1,expr2);
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 static SmvExpr becomes(SmvVar var, SmvExpr expr)
00166 {
00167 if (var.getComponents().size() > 0 && (expr instanceof SmvVar)) {
00168 SmvNaryExpr componentsEqual = new SmvNaryExpr("&",ONE,true);
00169 for (int i = 0; i < var.getComponents().size(); i++)
00170 componentsEqual.add(becomes(var.getComponent(i),
00171 ((SmvVar)expr).getComponent(i)));
00172 return componentsEqual;
00173 } else
00174 return new SmvBinaryExpr("=",new SmvNextExpr(var),expr);
00175 }
00176 String blockedVar(BirThread thread) {
00177 return thread.getName() + "_blocked";
00178 }
00179
00180
00181
00182
00183 SmvExpr buildTransExpr(Transformation trans, StateVarVector locals,
00184 SmvVar locVar) {
00185 currentTrans = trans;
00186 Expr guard = trans.getGuard();
00187
00188
00189
00190 currentGuard = (guard == null) ? ONE : translate(guard);
00191 guardTable.put(trans,currentGuard);
00192
00193 SmvNaryExpr transExpr = transTakenExpr(trans);
00194
00195
00196
00197 AssignAction localAssign = findLocalAssign(trans);
00198 if (localAssign == null)
00199 recordGlobalVarUpdates();
00200
00201
00202 StateVarVector liveLocals = locals;
00203 if (trans.getToLoc().getLiveVars() != null)
00204 liveLocals = trans.getToLoc().getLiveVars();
00205
00206
00207 for (int i = 0; i < liveLocals.size() ; i++) {
00208 StateVar local = liveLocals.elementAt(i);
00209 SmvVar localVar = getVar(local.getName());
00210 if (localAssign != null && localAssign.getLhs().equals(local)) {
00211 SmvExpr rhsExpr = translate(localAssign.getRhs());
00212 checkAssign(local,localAssign.getRhs(),localVar,rhsExpr);
00213 transExpr.add(becomes(localVar,rhsExpr));
00214 } else
00215 transExpr.add(becomes(localVar,localVar));
00216 }
00217
00218
00219 if (liveness) {
00220 SmvVar idleVar = getVar(idleVar(trans.getFromLoc().getThread()));
00221 transExpr.add(becomes(idleVar,ZERO));
00222 }
00223
00224 currentTrans = null;
00225 currentGuard = null;
00226 return transExpr;
00227 }
00228 public void caseAddExpr(AddExpr expr)
00229 {
00230 translateBinaryOp(expr.getOp1(), expr.getOp2(), "+");
00231 }
00232 public void caseAndExpr(AndExpr expr)
00233 {
00234 translateBinaryOp(expr.getOp1(), expr.getOp2(), "&");
00235 }
00236
00237
00238
00239
00240 public void caseArrayExpr(ArrayExpr expr) {
00241 SmvExpr array = translate(expr.getArray());
00242 SmvExpr index = translate(expr.getIndex());
00243 int size = ((Array)expr.getArray().getType()).getSize().getValue();
00244
00245 if (array instanceof SmvCaseExpr) {
00246 Vector cases = ((SmvCaseExpr)array).collectCases(new Vector());
00247 for (int i = 0; i < cases.size(); i++) {
00248 SmvCase smvCase = (SmvCase) cases.elementAt(i);
00249 SmvVar arrayVar = (SmvVar) smvCase.expr;
00250 SmvCaseExpr elemSelect = new SmvCaseExpr();
00251 for (int j = 0; j < size; j++) {
00252 SmvLit elemNum = new SmvLit("" + j);
00253 SmvExpr elemCond = new SmvBinaryExpr("=",index,elemNum);
00254 SmvVar elem = getVar(elementVar(arrayVar.getName(),j));
00255 elemSelect.addCase(elemCond,elem);
00256 }
00257 smvCase.updateCase(elemSelect);
00258 }
00259 setResult(array);
00260
00261 } else if (array instanceof SmvVar) {
00262 SmvVar arrayVar = (SmvVar) array;
00263 SmvCaseExpr elemSelect = new SmvCaseExpr();
00264 for (int j = 0; j < size; j++) {
00265 SmvLit elemNum = new SmvLit("" + j);
00266 SmvExpr elemCond = new SmvBinaryExpr("=",index,elemNum);
00267 SmvVar elem = getVar(elementVar(arrayVar.getName(),j));
00268 elemSelect.addCase(elemCond,elem);
00269 }
00270 setResult(elemSelect);
00271 } else
00272 throw new RuntimeException("Unexpected array expr: " + expr);
00273 }
00274 public void caseBoolLit(BoolLit expr)
00275 {
00276 setResult(new SmvLit(expr.getValue() ? "1" : "0"));
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 public void caseChooseExpr(ChooseExpr expr)
00294 {
00295 Vector choices = expr.getChoices();
00296 SmvCaseExpr choose = new SmvCaseExpr();
00297 for (int i = 0; i < choices.size() ; i++) {
00298 SmvExpr val = translate((Expr)choices.elementAt(i));
00299 SmvExpr test = (i + 1 == choices.size()) ? ONE :
00300 equal(choiceVar,new SmvLit("" + i));
00301 choose.addCase(test,val);
00302 }
00303 setResult(choose);
00304 }
00305 public void caseConstant(Constant expr)
00306 {
00307 setResult(new SmvLit(expr.getName()));
00308 }
00309
00310
00311
00312
00313 public void caseDerefExpr(DerefExpr expr) {
00314
00315 SmvVar refVar = (SmvVar) translate((StateVar)expr.getTarget());
00316 SmvVar refIndexVar = refVar.getComponent(0);
00317 SmvVar instNumVar = refVar.getComponent(1);
00318 StateVarVector targets =
00319 ((Ref)expr.getTarget().getType()).getTargets();
00320
00321 SmvCaseExpr colSelect = new SmvCaseExpr();
00322 for (int i = 0; i < targets.size(); i++) {
00323 StateVar target = targets.elementAt(i);
00324 SmvLit refIndexVal = new SmvLit("" + refIndex(target));
00325 SmvExpr cond = equal(refIndexVar,refIndexVal);
00326
00327
00328 if (target.getType().isKind(COLLECTION)) {
00329 SmvCaseExpr instSelect = new SmvCaseExpr();
00330 int size = ((Collection)target.getType()).getSize().getValue();
00331 for (int j = 0; j < size; j++) {
00332 SmvLit instNumVal = new SmvLit("" + j);
00333 SmvExpr instCond = equal(instNumVar,instNumVal);
00334 SmvVar inst = getVar(instanceVar(target.getName(),j));
00335 instSelect.addCase(instCond,inst);
00336 }
00337 colSelect.addCase(cond,instSelect);
00338 } else {
00339 SmvVar singleton = getVar(target.getName());
00340 colSelect.addCase(cond,singleton);
00341 }
00342 }
00343
00344
00345 SmvNaryExpr couldBeTaken = transCouldBeTakenExpr(currentTrans);
00346 couldBeTaken.add(equal(refIndexVar,ZERO));
00347 trapVar.addUpdate(couldBeTaken,
00348 becomes(trapVar,new SmvLit("NullPointerException")));
00349
00350 setResult(colSelect);
00351 }
00352 public void caseDivExpr(DivExpr expr)
00353 {
00354 translateBinaryOp(expr.getOp1(), expr.getOp2(), "/");
00355 }
00356 public void caseEqExpr(EqExpr expr)
00357 {
00358 SmvExpr expr1 = translate(expr.getOp1());
00359 SmvExpr expr2 = translate(expr.getOp2());
00360 setResult(equal(expr1,expr2));
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370 public void caseInstanceOfExpr(InstanceOfExpr expr)
00371 {
00372
00373
00374 if (! (expr.getRefExpr() instanceof StateVar))
00375 throw new RuntimeException("InstanceOf must apply to var");
00376 SmvVar refVar = (SmvVar) translate(expr.getRefExpr());
00377 SmvVar refIndexVar = getVar(refIndexVar(refVar.getName()));
00378 StateVarVector targets = expr.getRefType().getTargets();
00379 String indexSet = "";
00380 for (int j = 0; j < targets.size(); j++) {
00381 StateVar target = targets.elementAt(j);
00382 if (j > 0) indexSet += ", ";
00383 indexSet += refIndex(target);
00384 }
00385 SmvLit set = new SmvLit("{ " + indexSet + " }");
00386 setResult(new SmvBinaryExpr("in",refIndexVar,set));
00387 }
00388 public void caseIntLit(IntLit expr)
00389 {
00390 setResult(new SmvLit("" + expr.getValue()));
00391 }
00392 public void caseLeExpr(LeExpr expr)
00393 {
00394 translateBinaryOp(expr.getOp1(), expr.getOp2(), "<=");
00395 }
00396
00397
00398
00399
00400 public void caseLengthExpr(LengthExpr expr)
00401 {
00402 SmvExpr array = translate(expr.getArray());
00403 if (array instanceof SmvCaseExpr) {
00404 Vector cases = ((SmvCaseExpr)array).collectCases(new Vector());
00405 for (int i = 0; i < cases.size(); i++) {
00406 SmvCase smvCase = (SmvCase) cases.elementAt(i);
00407 SmvVar arrayVar = (SmvVar) smvCase.expr;
00408 SmvVar lengthVar = getVar(lengthVar(arrayVar.getName()));
00409 smvCase.updateCase(lengthVar);
00410 }
00411 setResult(array);
00412 } else if (array instanceof SmvVar) {
00413 SmvVar arrayVar = (SmvVar) array;
00414 SmvVar lengthVar = getVar(lengthVar(arrayVar.getName()));
00415 setResult(lengthVar);
00416 } else
00417 throw new RuntimeException("Unexpected array expr: " + expr);
00418 }
00419
00420
00421
00422
00423 public void caseLockTest(LockTest lockTest) {
00424 BirThread thread = lockTest.getThread();
00425 SmvExpr lock = translate(lockTest.getLockExpr());
00426 Vector cases;
00427 if (lock instanceof SmvCaseExpr) {
00428 cases = ((SmvCaseExpr)lock).collectCases(new Vector());
00429 setResult(lock);
00430 } else
00431 throw new RuntimeException("Unexpected lock expr: " + lock);
00432 switch (lockTest.getOperation()) {
00433 case LOCK_AVAILABLE:
00434 for (int i = 0; i < cases.size(); i++) {
00435 SmvCase smvCase = (SmvCase) cases.elementAt(i);
00436 SmvVar lockVar = (SmvVar) smvCase.expr;
00437 SmvVar ownerVar = getVar(ownerVar(lockVar.getName()));
00438 SmvExpr free = equal(ownerVar,NOTHREAD);
00439 SmvExpr relock = equal(ownerVar,new SmvLit(thread.getName()));
00440 SmvExpr avail = new SmvBinaryExpr("|",free,relock);
00441 smvCase.updateCase(avail);
00442 }
00443 return;
00444 case HAS_LOCK:
00445 setResult(ONE);
00446 return;
00447 case WAS_NOTIFIED:
00448 for (int i = 0; i < cases.size(); i++) {
00449 SmvCase smvCase = (SmvCase) cases.elementAt(i);
00450 SmvVar lockVar = (SmvVar) smvCase.expr;
00451 SmvVar waitVar = getVar(waitVar(lockVar.getName(),thread));
00452 smvCase.updateCase(not(waitVar));
00453 }
00454 return;
00455 }
00456 }
00457 public void caseLtExpr(LtExpr expr)
00458 {
00459 translateBinaryOp(expr.getOp1(), expr.getOp2(), "<");
00460 }
00461 public void caseMulExpr(MulExpr expr)
00462 {
00463 translateBinaryOp(expr.getOp1(), expr.getOp2(), "*");
00464 }
00465 public void caseNeExpr(NeExpr expr)
00466 {
00467 SmvExpr expr1 = translate(expr.getOp1());
00468 SmvExpr expr2 = translate(expr.getOp2());
00469 SmvExpr equals = equal(expr1,expr2);
00470 setResult(not(equals));
00471 }
00472
00473
00474
00475
00476
00477
00478 public void caseNewArrayExpr(NewArrayExpr expr)
00479 {
00480
00481
00482 StateVar target = expr.getCollection();
00483 String collectName = target.getName();
00484 int size = ((Collection)target.getType()).getSize().getValue();
00485 int refIndex = refIndex(target);
00486 SmvExpr setLength = translate(expr.getLength());
00487 SmvCaseExpr instNum = new SmvCaseExpr();
00488 for (int i = 0; i < size; i++) {
00489 SmvVar inuse = getVar(inUseVar(collectName,i));
00490 instNum.addCase(not(inuse), refValue(refIndex,i));
00491 }
00492
00493
00494
00495
00496 for (int i = 0; i < size; i++) {
00497 SmvNaryExpr taken = transTakenExpr(currentTrans);
00498 SmvVar inuse_i = getVar(inUseVar(collectName,i));
00499 for (int j = 0; j < i; j++) {
00500 SmvVar inuse_j = getVar(inUseVar(collectName,j));
00501 taken.add(equal(inuse_j,ONE));
00502 }
00503 taken.add(equal(inuse_i,ZERO));
00504 inuse_i.addUpdate(taken,becomes(inuse_i,ONE));
00505
00506
00507
00508 SmvVar instVar = getVar(instanceVar(collectName,i));
00509 Array type = (Array) ((Collection)target.getType()).getBaseType();
00510 int maxLen = type.getSize().getValue();
00511 SmvVar lengthVar = getVar(lengthVar(instVar.getName()));
00512 lengthVar.addUpdate(taken,becomes(lengthVar,setLength));
00513 for (int j = 0; j < maxLen; j++) {
00514 SmvVar elemVar = getVar(elementVar(instVar.getName(),j));
00515 initAllComponents(elemVar,taken);
00516 }
00517 }
00518
00519 setResult(instNum);
00520 }
00521
00522
00523
00524
00525 public void caseNewExpr(NewExpr expr)
00526 {
00527
00528
00529
00530
00531
00532
00533
00534 StateVar target = expr.getCollection();
00535 String collectName = target.getName();
00536 int refIndex = refIndex(target);
00537 int size = ((Collection)target.getType()).getSize().getValue();
00538 SmvCaseExpr instNum = new SmvCaseExpr();
00539 for (int i = 0; i < size; i++) {
00540 SmvVar inuse = getVar(inUseVar(collectName,i));
00541 instNum.addCase(not(inuse), refValue(refIndex,i));
00542 }
00543
00544
00545
00546
00547 for (int i = 0; i < size; i++) {
00548 SmvNaryExpr taken = transTakenExpr(currentTrans);
00549 SmvVar inuse_i = getVar(inUseVar(collectName,i));
00550 for (int j = 0; j < i; j++) {
00551 SmvVar inuse_j = getVar(inUseVar(collectName,j));
00552 taken.add(equal(inuse_j,ONE));
00553 }
00554 taken.add(equal(inuse_i,ZERO));
00555 inuse_i.addUpdate(taken,becomes(inuse_i,ONE));
00556
00557
00558 SmvVar instVar = getVar(instanceVar(collectName,i));
00559 initAllComponents(instVar,taken);
00560 }
00561
00562 setResult(instNum);
00563 }
00564 public void caseNotExpr(NotExpr expr)
00565 {
00566 translateUnaryOp(expr.getOp(),"!");
00567 }
00568 public void caseNullExpr(NullExpr expr)
00569 {
00570 setResult(ZERO);
00571 }
00572 public void caseOrExpr(OrExpr expr)
00573 {
00574 translateBinaryOp(expr.getOp1(), expr.getOp2(), "|");
00575 }
00576
00577
00578
00579
00580 public void caseRecordExpr(RecordExpr expr) {
00581 SmvExpr record = translate(expr.getRecord());
00582 Field field = expr.getField();
00583 if (record instanceof SmvCaseExpr) {
00584 Vector cases = ((SmvCaseExpr)record).collectCases(new Vector());
00585 for (int i = 0; i < cases.size(); i++) {
00586 SmvCase smvCase = (SmvCase) cases.elementAt(i);
00587 SmvVar recVar = (SmvVar) smvCase.expr;
00588 SmvVar fieldVar = getVar(fieldVar(recVar.getName(),field));
00589 smvCase.updateCase(fieldVar);
00590 }
00591 setResult(record);
00592
00593 } else if (record instanceof SmvVar) {
00594 setResult(getVar(fieldVar(((SmvVar)record).getName(),field)));
00595 } else
00596 throw new RuntimeException("Unexpected record expr: " + expr);
00597 }
00598 public void caseRefExpr(RefExpr expr)
00599 {
00600 setResult(refValue(refIndex(expr.getTarget()),0));
00601 }
00602 public void caseRemExpr(RemExpr expr)
00603 {
00604 translateBinaryOp(expr.getOp1(), expr.getOp2(), "mod");
00605 }
00606 public void caseStateVar(StateVar expr)
00607 {
00608 setResult(getVar(expr.getName()));
00609 }
00610 public void caseSubExpr(SubExpr expr)
00611 {
00612 translateBinaryOp(expr.getOp1(), expr.getOp2(), "-");
00613 }
00614 public void caseThreadLocTest(ThreadLocTest threadLocTest)
00615 {
00616 SmvVar threadLocVar = getVar(locVar(threadLocTest.getThread()));
00617 SmvLit locName = new SmvLit(locName(threadLocTest.getLocation()));
00618 SmvExpr testExpr = new SmvBinaryExpr("=",threadLocVar,locName);
00619 setResult(testExpr);
00620 }
00621 public void caseThreadTest(ThreadTest threadTest) {
00622 switch (threadTest.getOperation()) {
00623 case THREAD_TERMINATED:
00624 SmvVar activeVar = getVar(activeVar(threadTest.getThreadArg()));
00625 setResult(not(activeVar));
00626 return;
00627 }
00628 }
00629 public String check() { return runSmv(); }
00630
00631
00632
00633
00634
00635 void checkAssign(StateVar lhs, Expr rhs, SmvVar var, SmvExpr value) {
00636
00637 if (! rhs.getType().isSubtypeOf(lhs.getType())) {
00638
00639
00640 if (lhs.getType().isKind(REF) && ! (rhs instanceof NullExpr)) {
00641
00642 if (! (rhs instanceof StateVar))
00643 throw new RuntimeException("Can only check var to var ref assignments");
00644
00645
00646
00647
00648 SmvVar refIndexVar =
00649 getVar(refIndexVar(((StateVar)rhs).getName()));
00650 SmvNaryExpr couldBeTaken = transCouldBeTakenExpr(currentTrans);
00651 SmvNaryExpr notSupClass = new SmvNaryExpr("|",ONE,true);
00652 couldBeTaken.add(notSupClass);
00653 SmvLit trap = new SmvLit("ClassCastException");
00654 StateVarVector lhsTargets = ((Ref)lhs.getType()).getTargets();
00655 StateVarVector rhsTargets = ((Ref)rhs.getType()).getTargets();
00656 for (int j = 0; j < rhsTargets.size(); j++) {
00657 StateVar target = rhsTargets.elementAt(j);
00658 if (! lhsTargets.contains(target)) {
00659 SmvLit refIndex = new SmvLit("" + refIndex(target));
00660 notSupClass.add(equal(refIndexVar,refIndex));
00661 }
00662 }
00663 trapVar.addUpdate(couldBeTaken, becomes(trapVar,trap));
00664 }
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 }
00679 String countVar(String var) {
00680 return var + "_count";
00681 }
00682 static String currentDir() { return System.getProperty("user.dir"); }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 public SmvVar declareVar(String name, String smvType, StateVar source,
00695 String initValue, SmvVar aggregate,
00696 boolean constrained, SmvVar deadFlag) {
00697 SmvLit initVal = (initValue != null) ? new SmvLit(initValue) : null;
00698 SmvVar var = new SmvVar(name, smvType, source, initVal,
00699 constrained, deadFlag);
00700 if (varTable.get(name) != null)
00701 throw new RuntimeException("Error: name conflict " + name);
00702 if (aggregate != null) {
00703 aggregate.addComponent(var);
00704 var.setAggregate(aggregate);
00705 }
00706 varList.addElement(var);
00707 varTable.put(name,var);
00708 return var;
00709 }
00710
00711
00712
00713
00714
00715 void declareVariables() {
00716 SmvTypeDecl declarator = new SmvTypeDecl(this, system);
00717 StateVarVector stateVarVector = system.getStateVars();
00718
00719
00720
00721 if (interleaving)
00722 runningVar = declareVar("runningThread",threadType,null,null,
00723 null,false,null);
00724
00725
00726 ThreadVector threadVector = system.getThreads();
00727 for (int i = 0; i < threadVector.size(); i++) {
00728 BirThread thread = threadVector.elementAt(i);
00729 LocVector threadLocVector = thread.getLocations();
00730 String locType = "";
00731 for (int j = 0; j < threadLocVector.size(); j++) {
00732 Location loc = threadLocVector.elementAt(j);
00733 if (j > 0) locType += ", ";
00734 locType += locName(loc);
00735 }
00736 locType = "{ " + locType + " }";
00737 declareVar(locVar(thread), locType, null,
00738 locName(thread.getStartLoc()),null,false,null);
00739
00740
00741 if (! thread.isMain())
00742 declareVar(activeVar(thread),"boolean",null,"0",
00743 null,true,null);
00744
00745
00746
00747 if (liveness)
00748 declareVar(idleVar(thread),"boolean",null,"0",null,false,null);
00749
00750
00751
00752 declareVar(tempVar(thread), LOCK_COUNT_TYPE,
00753 null,null,null,true,null);
00754
00755
00756 for (int j = 0; j < stateVarVector.size(); j++) {
00757 StateVar var = stateVarVector.elementAt(j);
00758 if (var.getThread() == thread)
00759 var.getType().apply(declarator, var);
00760 }
00761 }
00762
00763
00764 for (int j = 0; j < stateVarVector.size(); j++) {
00765 StateVar var = stateVarVector.elementAt(j);
00766 if (var.getThread() == null)
00767 var.getType().apply(declarator, var);
00768 }
00769
00770
00771 choiceVar =
00772 declareVar("smv_choice","0 .. 31",null,null,null,false,null);
00773
00774
00775 trapVar =
00776 declareVar("smv_trap",TRAP_TYPE,null,"None",null,true,null);
00777
00778
00779 maxCollectionSize = declarator.getMaxCollectionSize();
00780 }
00781 public void defaultCase(Object obj)
00782 {
00783 throw new RuntimeException("Trans type not handled: " + obj);
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 void definitions() {
00796 Vector definitions = system.getDefinitions();
00797 println("DEFINE");
00798 println(" MAX_COLLECT_SIZE := " + maxCollectionSize + ";");
00799
00800
00801 for (int i = 0; i < definitions.size(); i++) {
00802 Definition def = (Definition) definitions.elementAt(i);
00803 if (def instanceof Constant)
00804 println(" " + def.getName() + " := " + def.getDef() +
00805 ";");
00806 else if (def instanceof Enumerated) {
00807 Enumerated enum = (Enumerated) def;
00808 for (int j = 0; j < enum.getEnumeratedSize(); j++) {
00809 String name = enum.getNameOf(enum.getFirstElement()+j);
00810 if (name != null)
00811 println(" " + name + " := " +
00812 (enum.getFirstElement()+j) + ";");
00813 }
00814 }
00815 }
00816
00817
00818 if (ctlproperty) {
00819
00820 Vector preds = system.getPredicates();
00821 for (int i = 0; i < preds.size(); i++) {
00822 Expr pred = (Expr) preds.elementAt(i);
00823 String name = system.predicateName(pred);
00824 println(" " + name + " := ");
00825 indent(2);
00826
00827
00828 println("true");
00829
00830 println(";");
00831 indent(-2);
00832 }
00833 } else {
00834
00835 ThreadVector threadVector = system.getThreads();
00836 for (int i = 0; i < threadVector.size(); i++) {
00837 BirThread thread = threadVector.elementAt(i);
00838 SmvExpr blocked = threadBlockedExpr(thread);
00839 println(" " + blockedVar(thread) + " := ");
00840 indent(2);
00841 blocked.print(this);
00842 println(";");
00843 indent(-2);
00844 SmvExpr terminated = threadTerminatedExpr(thread);
00845 println(" " + terminatedVar(thread) + " := ");
00846 indent(2);
00847 terminated.print(this);
00848 println(";");
00849 indent(-2);
00850 }
00851 }
00852 println();
00853 }
00854 String elementVar(String var, int i) {
00855 return var + "_e" + i;
00856 }
00857 SmvExpr equal(SmvExpr expr1, SmvExpr expr2)
00858 {
00859 return new SmvBinaryExpr("=",expr1,expr2);
00860 }
00861 String execAndWait(String command, boolean verbose) {
00862 try {
00863 if (verbose)
00864 System.out.println(command);
00865 Process p = runtime.exec(command);
00866 InputStream commandErr = p.getErrorStream();
00867 InputStream commandOut = p.getInputStream();
00868 int count = 0;
00869 int charsRead = 0;
00870 int charsAvail = 0;
00871 while ((count < BUFSIZE) && (charsRead >= 0)) {
00872 charsAvail = commandErr.available();
00873 if (charsAvail > 0)
00874 count += commandErr.read(buffer,count,charsAvail);
00875 charsRead = commandOut.read(buffer,count,BUFSIZE - count);
00876 if (charsRead > 0)
00877 count += charsRead;
00878 }
00879 p.waitFor();
00880 String output = new String(buffer,0,count);
00881 if (verbose && count > 0)
00882 System.out.println(output);
00883 return output;
00884 }
00885 catch (Exception e) {
00886 throw new RuntimeException("exec of command '" + command
00887 + "' was aborted: \n" + e);
00888 }
00889 }
00890
00891
00892
00893
00894
00895
00896
00897 void fairness() {
00898 ThreadVector threadVector = system.getThreads();
00899 for (int i = 0; i < threadVector.size(); i++) {
00900 BirThread thread = threadVector.elementAt(i);
00901 SmvNaryExpr expr = new SmvNaryExpr("|",ZERO,true);
00902 expr.add(not(getVar(idleVar(thread))));
00903 expr.add(new SmvVar(blockedVar(thread)));
00904 expr.add(new SmvVar(terminatedVar(thread)));
00905 println("FAIRNESS -- " + thread.getName());
00906 expr.print(this);
00907 println();
00908 }
00909 }
00910 String fieldVar(String var, Field type) {
00911 return var + "_" + type.getName();
00912 }
00913
00914
00915
00916
00917
00918 AssignAction findLocalAssign(Transformation trans) {
00919 if (trans.getActions().size() > 1)
00920 throw new RuntimeException("Multiple actions on transformation: " + trans);
00921 if (trans.getActions().size() == 0)
00922 return null;
00923 Action action = trans.getActions().elementAt(0);
00924 if (action.isAssignAction()) {
00925 AssignAction assign = (AssignAction) action;
00926 if (assign.getLhs() instanceof StateVar) {
00927 StateVar var = (StateVar) assign.getLhs();
00928 if (var.getThread() != null)
00929 return assign;
00930 }
00931 }
00932 return null;
00933 }
00934
00935
00936
00937 public List getCounterExample() {
00938 return null;
00939 }
00940 TransSystem getSystem() { return system; }
00941 String getThreadType() { return threadType; }
00942
00943
00944
00945
00946 SmvVar getVar(String name) {
00947 return (SmvVar) varTable.get(name);
00948 }
00949 SmvExpr greaterThan(SmvExpr expr1, SmvExpr expr2)
00950 {
00951 return new SmvBinaryExpr(">=",expr1,expr2);
00952 }
00953
00954
00955
00956
00957 void header() {
00958 println("-- SMV for transition system: "
00959 + system.getName());
00960 println();
00961 println("MODULE main");
00962 }
00963 String idleVar(BirThread thread) {
00964 return thread.getName() + "_idle";
00965 }
00966 void indent(int delta) {
00967 indentLevel += delta;
00968 }
00969
00970
00971
00972
00973
00974 void init() {
00975 println("INIT");
00976 SmvNaryExpr expr = new SmvNaryExpr("&", ONE, false);
00977 for (int i = 0; i < varList.size(); i++) {
00978 SmvVar var = (SmvVar)varList.elementAt(i);
00979
00980 if (var.getType() != null && var.getDeadFlag() == null) {
00981 SmvLit initVal = var.getInitValue();
00982
00983 if (initVal != null)
00984 expr.add(equal(var,initVal));
00985 }
00986 }
00987 expr.print(this);
00988 println();
00989 }
00990
00991
00992
00993
00994 void initAllComponents(SmvVar var, SmvExpr cond) {
00995 Vector components = var.getComponents();
00996
00997 if (components.size() > 0) {
00998 for (int i = 0; i < components.size(); i++)
00999 initAllComponents((SmvVar)components.elementAt(i),cond);
01000 } else {
01001
01002 if (var.getInitValue() != null) {
01003 var.addUpdate(cond,becomes(var,var.getInitValue()));
01004 }
01005 }
01006 }
01007 String instanceVar(String var, int i) {
01008 return var + "_i" + i;
01009 }
01010 String instNumVar(String var) {
01011 return var + "_instNum";
01012 }
01013 String inUseVar(String var, int i) {
01014 return var + "_inuse" + i;
01015 }
01016 String lengthVar(String var) {
01017 return var + "_length";
01018 }
01019 SmvExpr lessThan(SmvExpr expr1, SmvExpr expr2)
01020 {
01021 return new SmvBinaryExpr("<=",expr1,expr2);
01022 }
01023
01024
01025
01026
01027 String locName(Location loc) {
01028 return "loc" + loc.getId();
01029 }
01030 String locVar(BirThread thread) {
01031 return thread.getName() + "_loc";
01032 }
01033 SmvExpr minus1(SmvExpr expr)
01034 {
01035 return new SmvBinaryExpr("-",expr,ONE);
01036 }
01037 SmvExpr not(SmvExpr expr)
01038 {
01039 if (expr instanceof SmvUnaryExpr &&
01040 ((SmvUnaryExpr)expr).operator.equals("!"))
01041 return ((SmvUnaryExpr)expr).op;
01042 else
01043 return new SmvUnaryExpr("!",expr);
01044 }
01045 SmvExpr or(SmvExpr expr1, SmvExpr expr2)
01046 {
01047 return new SmvBinaryExpr("|",expr1,expr2);
01048 }
01049 String ownerVar(String var) {
01050 return var + "_owner";
01051 }
01052 static int parseInt(String s) {
01053 try {
01054 int result = Integer.parseInt(s);
01055 return result;
01056 } catch (NumberFormatException e) {
01057 throw new RuntimeException("Integer didn't parse: " + s);
01058 }
01059 }
01060
01061
01062
01063
01064 void parseLine(String line, BirTrace trace) {
01065 if (!doneParsing) {
01066
01067
01068 if (line.indexOf("is true") >= 0) {
01069 if (foundFalse) {
01070 foundTrace = false;
01071 } else {
01072 trace.setVerified(true);
01073 doneParsing = true;
01074 return;
01075 }
01076 }
01077 if (line.indexOf("is false") >= 0) {
01078 if (foundFalse) {
01079 foundTrace = false;
01080 } else {
01081 trace.setVerified(false);
01082 foundTrace = true;
01083 foundFalse = true;
01084 return;
01085 }
01086 }
01087
01088 if (foundTrace) {
01089 if (line.startsWith("State"))
01090 stateCount += 1;
01091
01092
01093 if (stateCount > 1 && line.indexOf("_loc =") >= 0)
01094 parseThreadStep(line, trace);
01095
01096
01097 if (stateCount > 1 && line.startsWith("smv_trap ="))
01098 parseTrap(line, trace);
01099 }
01100 }
01101 }
01102
01103
01104
01105
01106
01107
01108
01109 public BirTrace parseOutput() {
01110 if (! ranVerifier)
01111 throw new RuntimeException("Did not run verifier on input");
01112 try {
01113 BirTrace trace = new BirTrace(system);
01114 File smvFile = new File(currentDir(),
01115 system.getName() + ".smv");
01116 if (! smvFile.exists())
01117 throw new RuntimeException("Cannot find SMV output: \n"
01118 + smvFile);
01119 prepareParse();
01120 BufferedReader reader =
01121 new BufferedReader(new FileReader(smvFile));
01122 String line = reader.readLine();
01123 while (line != null) {
01124 parseLine(line,trace);
01125 line = reader.readLine();
01126 }
01127 reader.close();
01128 trace.done();
01129 return trace;
01130 } catch(IOException e) {
01131 throw new RuntimeException("Error parsing SMV output: \n" + e);
01132 }
01133 }
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 void parseThreadStep(String line, BirTrace trace) {
01146 int end = line.indexOf("_loc =");
01147 String threadName = line.substring(0,end);
01148 Integer threadNum = (Integer) threadTable.get(threadName);
01149 if (threadNum == null)
01150 return;
01151
01152
01153 Location fromLoc = threadLocs[threadNum.intValue()];
01154 int locPos = 3 + line.indexOf("loc",end + 5);
01155 int locId = parseInt(line.substring(locPos));
01156 Location toLoc = system.getLocation(locId);
01157
01158
01159 TransVector outTrans = fromLoc.getOutTrans();
01160 for (int i = 0; i < outTrans.size(); i++) {
01161 if (outTrans.elementAt(i).getToLoc() == toLoc) {
01162 threadLocs[threadNum.intValue()] = toLoc;
01163 lastTrans = outTrans.elementAt(i);
01164 trace.addTrans(lastTrans);
01165 return;
01166 }
01167 }
01168 throw new RuntimeException("Error parsing SMV output: can't find trans for " + threadName + " from location " + fromLoc + " to " + toLoc);
01169 }
01170
01171
01172
01173
01174 void parseTrap(String line, BirTrace trace) {
01175 int end = line.indexOf("=");
01176 String trapName = line.substring(end + 2);
01177 trace.setTrap(trapName,lastTrans,0);
01178 }
01179 SmvExpr plus1(SmvExpr expr)
01180 {
01181 return new SmvBinaryExpr("+",expr,ONE);
01182 }
01183
01184
01185
01186
01187 void prepareParse() {
01188 doneParsing = false;
01189 foundFalse = false;
01190 foundTrace = false;
01191 stateCount = 0;
01192 ThreadVector threads = system.getThreads();
01193 threadLocs = new Location[threads.size()];
01194 threadTable = new Hashtable();
01195 for (int i = 0; i < threadLocs.length; i++) {
01196 BirThread thread = threads.elementAt(i);
01197 threadTable.put(thread.getName(), new Integer(i));
01198 threadLocs[i] = thread.getStartLoc();
01199 }
01200 }
01201
01202
01203
01204
01205 void print(String s) {
01206 if (newLine) {
01207 for (int i = 0; i < indentLevel; i++)
01208 out.print(" ");
01209 newLine = false;
01210 }
01211 out.print(s);
01212 }
01213 void println() {
01214 if (! newLine) {
01215 out.println();
01216 newLine = true;
01217 }
01218 }
01219 void println(String s) {
01220 print(s);
01221 println();
01222 }
01223
01224
01225
01226
01227
01228
01229
01230 void printVariableDecls() {
01231 println("VAR");
01232 for (int i = 0; i < varList.size(); i++) {
01233 SmvVar var = (SmvVar)varList.elementAt(i);
01234 if (var.getType() != null)
01235 println(" " + var + " : " + var.getType() + ";");
01236 else {
01237 String comment = "";
01238 StateVar source = var.getSource();
01239 if (source != null
01240 && source.getType().isKind(COLLECTION|ARRAY|RECORD))
01241 comment = "(refIndex = " + refIndex(source) + ")";
01242 println(" -- Aggregate: " + var + " " + comment);
01243 }
01244 }
01245 println();
01246 }
01247 void property() {
01248 indent(2);
01249
01250 println("INVARSPEC");
01251 println("smv_trap = None");
01252
01253 indent(-2);
01254 if (ctlproperty) {
01255 println("SPEC");
01256
01257 File ctlFile = new File(currentDir(),
01258 system.getName() + ".smv.ctl");
01259 if (! ctlFile.exists())
01260 throw new RuntimeException("Cannot find CTL file: " +
01261 ctlFile.getAbsolutePath());
01262 if (! ctlFile.canRead())
01263 throw new RuntimeException("Cannot read CTL file: " +
01264 ctlFile.getAbsolutePath());
01265 try {
01266 BufferedReader in =
01267 new BufferedReader(new FileReader(ctlFile));
01268 String line;
01269 indent(2);
01270 while((line = in.readLine()) != null)
01271 println(line);
01272 in.close();
01273 } catch (IOException e) {
01274 }
01275 indent(-2);
01276 } else {
01277
01278
01279
01280 indent(2);
01281 println("INVARSPEC");
01282 ThreadVector threadVector = system.getThreads();
01283 indent(2);
01284 println("!(");
01285 indent(2);
01286 println("(");
01287 indent(2);
01288 for (int i = 0; i < threadVector.size(); i++) {
01289 BirThread thread = threadVector.elementAt(i);
01290 if (i < threadVector.size()-1)
01291 println("(" + blockedVar(thread) + " | " +
01292 terminatedVar(thread) + ") &");
01293 else
01294 println("(" + blockedVar(thread) + " | " +
01295 terminatedVar(thread) + ")");
01296 }
01297 indent(-2);
01298 println(") & (");
01299 indent(2);
01300 for (int i = 0; i < threadVector.size(); i++) {
01301 BirThread thread = threadVector.elementAt(i);
01302 if (i < threadVector.size()-1)
01303 println("!" + terminatedVar(thread) + " |");
01304 else
01305 println("!" + terminatedVar(thread));
01306 }
01307 indent(-2);
01308 println(")");
01309 indent(-2);
01310 println(")");
01311 indent(-2);
01312 }
01313 }
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330 void recordGlobalVarAssignments(SmvExpr lhs,
01331 SmvExpr rhs, SmvCase context) {
01332 if (lhs instanceof SmvVar) {
01333 SmvVar global = (SmvVar) lhs;
01334 SmvNaryExpr taken = transTakenExpr(currentTrans);
01335 addConditionalContext(taken,context);
01336 global.addUpdate(taken,becomes(global,rhs));
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348 } else if (lhs instanceof SmvCaseExpr) {
01349 Vector cases = ((SmvCaseExpr)lhs).getCases();
01350 for (int i = 0; i < cases.size(); i++) {
01351 SmvCase smvCase = (SmvCase)cases.elementAt(i);
01352 recordGlobalVarAssignments(smvCase.expr,rhs,smvCase);
01353 }
01354 } else
01355 throw new RuntimeException("Unknown LHS of assignment");
01356 }
01357
01358
01359
01360
01361 void recordGlobalVarUpdates() {
01362 if (currentTrans.getActions().size() == 0)
01363 return;
01364 Action action = currentTrans.getActions().elementAt(0);
01365 if (action.isAssignAction()) {
01366 AssignAction assign = (AssignAction) action;
01367 SmvExpr lhs = translate(assign.getLhs());
01368 SmvExpr rhs = translate(assign.getRhs());
01369 recordGlobalVarAssignments(lhs,rhs,null);
01370 } else if (action.isThreadAction(ANY)) {
01371 recordThreadStatusUpdates((ThreadAction)action);
01372 } else if (action.isLockAction(ANY)) {
01373 recordLockStatusUpdates((LockAction)action);
01374 }
01375 }
01376
01377
01378
01379
01380 void recordLockStatusUpdates(LockAction action) {
01381 ThreadVector threads = system.getThreads();
01382 BirThread currentThread = action.getThread();
01383 SmvLit currentThreadLit = new SmvLit(currentThread.getName());
01384
01385
01386 SmvCaseExpr lockExpr = (SmvCaseExpr) translate(action.getLockExpr());
01387 Vector cases = lockExpr.collectCases(new Vector());
01388
01389
01390 for (int i = 0; i < cases.size(); i++) {
01391
01392
01393 SmvNaryExpr taken = transTakenExpr(currentTrans);
01394 SmvCase smvCase = (SmvCase)cases.elementAt(i);
01395 addConditionalContext(taken,smvCase);
01396
01397
01398 SmvVar lockVar = (SmvVar) smvCase.expr;
01399 SmvVar ownerVar = getVar(ownerVar(lockVar.getName()));
01400 SmvVar countVar = getVar(countVar(lockVar.getName()));
01401 SmvVar waitVar = getVar(waitVar(lockVar.getName(),currentThread));
01402 SmvVar tempVar = getVar(tempVar(currentThread));
01403 SmvExpr update;
01404 SmvNaryExpr sum;
01405 SmvNaryExpr nextSum;
01406
01407 switch (action.getOperation()) {
01408 case LOCK:
01409
01410 update = becomes(ownerVar,currentThreadLit);
01411 ownerVar.addUpdate(taken,update);
01412
01413
01414 update = or(and(equal(ownerVar,NOTHREAD),
01415 becomes(countVar,ZERO)),
01416 and(equal(ownerVar,currentThreadLit),
01417 becomes(countVar,plus1(countVar))));
01418 countVar.addUpdate(taken,update);
01419 break;
01420
01421 case UNLOCK:
01422
01423
01424 update = or(and(equal(countVar,ZERO),
01425 becomes(ownerVar,NOTHREAD)),
01426 and(not(equal(countVar,ZERO)),
01427 becomes(ownerVar,currentThreadLit)));
01428 ownerVar.addUpdate(taken,update);
01429
01430
01431 update = or(equal(countVar,ZERO),
01432 and(not(equal(countVar,ZERO)),
01433 becomes(countVar,minus1(countVar))));
01434 countVar.addUpdate(taken,update);
01435 break;
01436
01437 case WAIT:
01438
01439 update = becomes(tempVar,countVar);
01440 tempVar.addUpdate(taken,update);
01441
01442 update = becomes(ownerVar,NOTHREAD);
01443 ownerVar.addUpdate(taken,update);
01444
01445 countVar.addUpdate(taken,ONE);
01446
01447 update = becomes(waitVar,ONE);
01448 waitVar.addUpdate(taken,update);
01449 break;
01450
01451 case UNWAIT:
01452
01453 update = becomes(countVar,tempVar);
01454 countVar.addUpdate(taken,update);
01455
01456 tempVar.addUpdate(taken,ONE);
01457
01458 update = becomes(ownerVar,currentThreadLit);
01459 ownerVar.addUpdate(taken,update);
01460 break;
01461
01462 case NOTIFY:
01463
01464
01465 sum = new SmvNaryExpr("+",ZERO,true);
01466 nextSum = new SmvNaryExpr("+",ZERO,true);
01467 for (int j = 0; j < threads.size(); j++) {
01468 BirThread thread = threads.elementAt(j);
01469 if (thread != currentThread) {
01470 SmvVar otherWaitVar =
01471 getVar(waitVar(lockVar.getName(),thread));
01472 sum.add(otherWaitVar);
01473 SmvExpr nextOtherWaitVar =
01474 new SmvNextExpr(otherWaitVar);
01475 nextSum.add(nextOtherWaitVar);
01476
01477
01478
01479 update = lessThan(nextOtherWaitVar,otherWaitVar);
01480 otherWaitVar.addUpdate(taken,update);
01481 }
01482 }
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492 update = and(becomes(waitVar,ZERO),
01493 or(equal(sum,ZERO),
01494 equal(nextSum,minus1(sum))));
01495 waitVar.addUpdate(taken,update);
01496 break;
01497
01498 case NOTIFYALL:
01499
01500 for (int j = 0; j < threads.size(); j++) {
01501 BirThread thread = threads.elementAt(j);
01502 if (thread != currentThread) {
01503 SmvVar otherWaitVar =
01504 getVar(waitVar(lockVar.getName(),thread));
01505 update = becomes(otherWaitVar,ZERO);
01506 otherWaitVar.addUpdate(taken,update);
01507 }
01508 }
01509 break;
01510 }
01511 }
01512 }
01513
01514
01515
01516
01517
01518
01519 void recordThreadStatusUpdates(ThreadAction action) {
01520 if (action.isThreadAction(START)) {
01521 BirThread thread = action.getThreadArg();
01522 SmvNaryExpr taken = transTakenExpr(currentTrans);
01523 SmvVar active = getVar(activeVar(thread));
01524 active.addUpdate(taken,becomes(active,ONE));
01525 }
01526 }
01527
01528
01529
01530
01531
01532 int refIndex(StateVar target) {
01533 return 1 + system.refAnyType().getTargets().indexOf(target);
01534 }
01535 String refIndexVar(String var) {
01536 return var + "_refIndex";
01537 }
01538
01539
01540
01541
01542 SmvLit refValue(int refIndex, int instNum) {
01543 return new SmvLit("(" + refIndex + " * MAX_COLLECT_SIZE + "
01544 + instNum + ")");
01545 }
01546
01547
01548
01549
01550 SmvTrans run() {
01551 header();
01552 stateVariables();
01553 init();
01554 transitions();
01555 if (liveness)
01556 fairness();
01557 definitions();
01558 property();
01559 return this;
01560 }
01561
01562
01563
01564
01565
01566
01567
01568
01569 public String runSmv() {
01570 try {
01571 File sourceFile = new File(currentDir(),
01572 system.getName() + ".trans");
01573 if (! sourceFile.exists())
01574 throw new RuntimeException("Cannot find SMV input file: " +
01575 sourceFile.getName());
01576 ranVerifier = true;
01577 String output = execAndWait("nusmv " + options.runOptions() + sourceFile.getName(), true);
01578
01579 File outFile = new File(currentDir(),
01580 system.getName() + ".smv");
01581 FileOutputStream streamOut = new FileOutputStream(outFile);
01582 PrintWriter writerOut = new PrintWriter(streamOut);
01583 writerOut.print(output);
01584 writerOut.close();
01585 System.out.println("Parsing output and printing BIR trace");
01586 parseOutput().print(true);
01587 return output;
01588 } catch(Exception e) {
01589 throw new RuntimeException("Could not produce SMV file (" + e + ")");
01590 }
01591 }
01592
01593
01594
01595
01596 void stateVariables() {
01597 declareVariables();
01598 printVariableDecls();
01599 }
01600 String tempVar(BirThread thread) {
01601 return thread.getName() + "_temp";
01602 }
01603 String terminatedVar(BirThread thread) {
01604 return thread.getName() + "_terminated";
01605 }
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615 SmvExpr threadBlockedExpr(BirThread thread) {
01616 LocVector locations = thread.getLocations();
01617 SmvVar locVar = getVar(locVar(thread));
01618 SmvNaryExpr blocked = new SmvNaryExpr("|",ZERO,true);
01619 for (int i = 0; i < locations.size(); i++) {
01620 SmvLit locLabel = new SmvLit(locName(locations.elementAt(i)));
01621
01622
01623 SmvNaryExpr blockedAtLoc = new SmvNaryExpr("&",ONE,true);
01624 TransVector transitions = locations.elementAt(i).getOutTrans();
01625 for (int j = 0; j < transitions.size(); j++) {
01626 SmvExpr guard =
01627 (SmvExpr) guardTable.get(transitions.elementAt(j));
01628 if (guard != null && ! guard.equals(ONE)) {
01629
01630 blockedAtLoc.add(not(guard));
01631 } else {
01632
01633 blockedAtLoc = null;
01634 break;
01635 }
01636 }
01637
01638
01639 if (blockedAtLoc != null && blockedAtLoc.size() > 0)
01640 blocked.add(and(equal(locVar,locLabel),blockedAtLoc));
01641 }
01642 return blocked;
01643 }
01644
01645
01646
01647
01648
01649
01650
01651 SmvExpr threadTerminatedExpr(BirThread thread) {
01652 LocVector locations = thread.getLocations();
01653 SmvVar locVar = getVar(locVar(thread));
01654 SmvNaryExpr terminated = new SmvNaryExpr("|",ZERO,true);
01655 for (int i = 0; i < locations.size(); i++) {
01656 SmvLit locLabel = new SmvLit(locName(locations.elementAt(i)));
01657 if (locations.elementAt(i).getOutTrans().size() == 0)
01658 terminated.add(equal(locVar,locLabel));
01659 }
01660 return terminated;
01661 }
01662
01663
01664
01665
01666
01667
01668
01669 SmvNaryExpr transCouldBeTakenExpr(Transformation trans) {
01670 SmvVar locVar = getVar(locVar(trans.getFromLoc().getThread()));
01671 SmvLit fromLoc = new SmvLit(locName(trans.getFromLoc()));
01672 SmvNaryExpr taken = new SmvNaryExpr("&",ONE,true);
01673 taken.add(equal(locVar,fromLoc));
01674 if (currentGuard != null && ! currentGuard.equals(ONE))
01675 taken.add(currentGuard);
01676 BirThread thread = trans.getFromLoc().getThread();
01677 if (! thread.isMain()
01678 && trans.getFromLoc().equals(thread.getStartLoc())) {
01679 SmvVar active = getVar(activeVar(trans.getFromLoc().getThread()));
01680 taken.add(equal(active,ONE));
01681 }
01682 return taken;
01683 }
01684
01685
01686
01687
01688 void transitions() {
01689
01690 ThreadVector threadVector = system.getThreads();
01691 for (int i = 0; i < threadVector.size(); i++) {
01692 BirThread thread = threadVector.elementAt(i);
01693 SmvExpr expr = translateThread(thread);
01694 println("TRANS -- " + thread.getName());
01695 expr.print(this);
01696 println();
01697 }
01698
01699
01700 for (int i = 0; i < varList.size(); i++) {
01701 SmvVar var = (SmvVar) varList.elementAt(i);
01702 if (var.isConstrained()) {
01703 SmvExpr expr = translateGlobal(var);
01704 println("TRANS -- " + var);
01705 expr.print(this);
01706 println();
01707 }
01708 }
01709 println();
01710 }
01711
01712
01713
01714
01715 SmvExpr translate(Expr expr) {
01716 expr.apply(this);
01717 return (SmvExpr) getResult();
01718 }
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730 public static SmvTrans translate(TransSystem system,
01731 SmvOptions options) {
01732 try {
01733 File sourceFile = new File(currentDir(),
01734 system.getName() + ".trans");
01735
01736 FileOutputStream streamOut = new FileOutputStream(sourceFile);
01737 PrintWriter writerOut = new PrintWriter(streamOut);
01738 SmvTrans result = translate(system, options, writerOut);
01739 writerOut.close();
01740 return result;
01741 } catch(IOException e) {
01742 throw new RuntimeException("Could not produce SMV file: " + e);
01743 }
01744 }
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754 public static SmvTrans translate(TransSystem system, SmvOptions options,
01755 PrintWriter out) {
01756 return (new SmvTrans(system,options,out)).run();
01757 }
01758 void translateBinaryOp(Expr e1, Expr e2, String op) {
01759 setResult(new SmvBinaryExpr(op,translate(e1),translate(e2)));
01760 }
01761
01762
01763
01764
01765 SmvExpr translateGlobal(SmvVar var) {
01766 SmvExpr updateExpr = var.getUpdateExpr();
01767 return updateExpr;
01768 }
01769
01770
01771
01772
01773 SmvExpr translateThread(BirThread thread) {
01774 StateVarVector locals = system.getLocalStateVars(thread);
01775 SmvNaryExpr threadExpr = new SmvNaryExpr("|",ZERO,true);
01776 SmvNaryExpr skipExpr = new SmvNaryExpr("&",ONE,true);
01777 SmvVar locVar = getVar(locVar(thread));
01778
01779
01780 skipExpr.add(becomes(locVar,locVar));
01781 for (int i = 0; i < locals.size(); i++) {
01782 SmvVar var = getVar(locals.elementAt(i).getName());
01783 skipExpr.add(becomes(var,var));
01784 }
01785 if (liveness) {
01786 SmvVar idleVar = getVar(idleVar(thread));
01787 skipExpr.add(becomes(idleVar,ONE));
01788 }
01789
01790 threadExpr.add(skipExpr);
01791
01792
01793 LocVector locs = thread.getLocations();
01794 for (int i = 0; i < locs.size(); i++) {
01795 TransVector transVector = locs.elementAt(i).getOutTrans();
01796 for (int j = 0; j < transVector.size(); j++) {
01797 SmvExpr transExpr = buildTransExpr(transVector.elementAt(j),
01798 locals, locVar);
01799 threadExpr.add(transExpr);
01800 }
01801 }
01802
01803 return threadExpr;
01804 }
01805 void translateUnaryOp(Expr e, String op) {
01806 setResult(new SmvUnaryExpr(op,translate(e)));
01807 }
01808
01809
01810
01811
01812 SmvNaryExpr transTakenExpr(Transformation trans) {
01813 SmvVar locVar = getVar(locVar(trans.getFromLoc().getThread()));
01814 SmvLit fromLoc = new SmvLit(locName(trans.getFromLoc()));
01815 SmvLit toLoc = new SmvLit(locName(trans.getToLoc()));
01816 SmvNaryExpr taken = new SmvNaryExpr("&",ONE,true);
01817
01818 taken.add(equal(locVar,fromLoc));
01819 taken.add(becomes(locVar,toLoc));
01820
01821 if (interleaving) {
01822 BirThread thread = trans.getFromLoc().getThread();
01823 taken.add(equal(runningVar,new SmvLit(thread.getName())));
01824 }
01825 BirThread thread = trans.getFromLoc().getThread();
01826
01827 if (! thread.isMain()
01828 && trans.getFromLoc().equals(thread.getStartLoc())) {
01829 SmvVar active = getVar(activeVar(trans.getFromLoc().getThread()));
01830 taken.add(equal(active,ONE));
01831 }
01832
01833 if (currentGuard != null && ! currentGuard.equals(ONE))
01834 taken.add(currentGuard);
01835 return taken;
01836 }
01837 String waitVar(String var, BirThread thread) {
01838 return var + "_wait_" + thread.getName();
01839 }
01840 }