dstep.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /***** spin: dstep.c *****/
  2. /* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* Permission is given to distribute this code provided that this intro- */
  5. /* ductory message is not removed and no monies are exchanged. */
  6. /* No guarantee is expressed or implied by the distribution of this code. */
  7. /* Software written by Gerard J. Holzmann as part of the book: */
  8. /* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4, */
  9. /* Prentice Hall, Englewood Cliffs, NJ, 07632. */
  10. /* Send bug-reports and/or questions to: gerard@research.bell-labs.com */
  11. #include "spin.h"
  12. #ifdef PC
  13. #include "y_tab.h"
  14. #else
  15. #include "y.tab.h"
  16. #endif
  17. #define MAXDSTEP 1024 /* was 512 */
  18. char *NextLab[64];
  19. int Level=0, GenCode=0, IsGuard=0, TestOnly=0;
  20. static int Tj=0, Jt=0, LastGoto=0;
  21. static int Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
  22. static void putCode(FILE *, Element *, Element *, Element *, int);
  23. extern int Pid, claimnr;
  24. static void
  25. Sourced(int n, int special)
  26. { int i;
  27. for (i = 0; i < Tj; i++)
  28. if (Tojump[i] == n)
  29. return;
  30. if (Tj >= MAXDSTEP)
  31. fatal("d_step sequence too long", (char *)0);
  32. Special[Tj] = special;
  33. Tojump[Tj++] = n;
  34. }
  35. static void
  36. Dested(int n)
  37. { int i;
  38. for (i = 0; i < Tj; i++)
  39. if (Tojump[i] == n)
  40. return;
  41. for (i = 0; i < Jt; i++)
  42. if (Jumpto[i] == n)
  43. return;
  44. if (Jt >= MAXDSTEP)
  45. fatal("d_step sequence too long", (char *)0);
  46. Jumpto[Jt++] = n;
  47. LastGoto = 1;
  48. }
  49. static void
  50. Mopup(FILE *fd)
  51. { int i, j; extern int OkBreak;
  52. for (i = 0; i < Jt; i++)
  53. { for (j = 0; j < Tj; j++)
  54. if (Tojump[j] == Jumpto[i])
  55. break;
  56. if (j == Tj)
  57. { char buf[12];
  58. if (Jumpto[i] == OkBreak)
  59. { if (!LastGoto)
  60. fprintf(fd, "S_%.3d_0: /* break-dest */\n",
  61. OkBreak);
  62. } else {
  63. sprintf(buf, "S_%.3d_0", Jumpto[i]);
  64. non_fatal("goto %s breaks from d_step seq", buf);
  65. } } }
  66. for (j = 0; j < Tj; j++)
  67. { for (i = 0; i < Jt; i++)
  68. if (Tojump[j] == Jumpto[i])
  69. break;
  70. #ifdef DEBUG
  71. if (i == Jt && !Special[i])
  72. fprintf(fd, "\t\t/* no goto's to S_%.3d_0 */\n",
  73. Tojump[j]);
  74. #endif
  75. }
  76. for (j = i = 0; j < Tj; j++)
  77. if (Special[j])
  78. { Tojump[i] = Tojump[j];
  79. Special[i] = 2;
  80. if (i >= MAXDSTEP)
  81. fatal("cannot happen (dstep.c)", (char *)0);
  82. i++;
  83. }
  84. Tj = i; /* keep only the global exit-labels */
  85. Jt = 0;
  86. }
  87. static int
  88. FirstTime(int n)
  89. { int i;
  90. for (i = 0; i < Tj; i++)
  91. if (Tojump[i] == n)
  92. return (Special[i] <= 1);
  93. return 1;
  94. }
  95. static void
  96. illegal(Element *e, char *str)
  97. {
  98. printf("illegal operator in 'd_step:' '");
  99. comment(stdout, e->n, 0);
  100. printf("'\n");
  101. fatal("'%s'", str);
  102. }
  103. static void
  104. filterbad(Element *e)
  105. {
  106. switch (e->n->ntyp) {
  107. case ASSERT:
  108. case PRINT:
  109. case 'c':
  110. /* run cannot be completely undone
  111. * with sv_save-sv_restor
  112. */
  113. if (any_oper(e->n->lft, RUN))
  114. illegal(e, "run operator in d_step");
  115. /* remote refs inside d_step sequences
  116. * would be okay, but they cannot always
  117. * be interpreted by the simulator the
  118. * same as by the verifier (e.g., for an
  119. * error trail)
  120. */
  121. if (any_oper(e->n->lft, 'p'))
  122. illegal(e, "remote reference in d_step");
  123. break;
  124. case '@':
  125. illegal(e, "process termination");
  126. break;
  127. case D_STEP:
  128. illegal(e, "nested d_step sequence");
  129. break;
  130. case ATOMIC:
  131. illegal(e, "nested atomic sequence");
  132. break;
  133. default:
  134. break;
  135. }
  136. }
  137. static int
  138. CollectGuards(FILE *fd, Element *e, int inh)
  139. { SeqList *h; Element *ee;
  140. for (h = e->sub; h; h = h->nxt)
  141. { ee = huntstart(h->this->frst);
  142. filterbad(ee);
  143. switch (ee->n->ntyp) {
  144. case NON_ATOMIC:
  145. inh += CollectGuards(fd, ee->n->sl->this->frst, inh);
  146. break;
  147. case IF:
  148. inh += CollectGuards(fd, ee, inh);
  149. break;
  150. case '.':
  151. if (ee->nxt->n->ntyp == DO)
  152. inh += CollectGuards(fd, ee->nxt, inh);
  153. break;
  154. case ELSE:
  155. if (inh++ > 0) fprintf(fd, " || ");
  156. fprintf(fd, "(1 /* else */)");
  157. break;
  158. case 'R':
  159. case 'r':
  160. case 's':
  161. if (inh++ > 0) fprintf(fd, " || ");
  162. fprintf(fd, "("); TestOnly=1;
  163. putstmnt(fd, ee->n, ee->seqno);
  164. fprintf(fd, ")"); TestOnly=0;
  165. break;
  166. case 'c':
  167. if (inh++ > 0) fprintf(fd, " || ");
  168. fprintf(fd, "("); TestOnly=1;
  169. if (Pid != claimnr)
  170. fprintf(fd, "(boq == -1 && ");
  171. putstmnt(fd, ee->n->lft, e->seqno);
  172. if (Pid != claimnr)
  173. fprintf(fd, ")");
  174. fprintf(fd, ")"); TestOnly=0;
  175. break;
  176. } }
  177. return inh;
  178. }
  179. int
  180. putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln)
  181. { int isg=0; char buf[64];
  182. NextLab[0] = "continue";
  183. filterbad(s->frst);
  184. switch (s->frst->n->ntyp) {
  185. case UNLESS:
  186. non_fatal("'unless' inside d_step - ignored", (char *) 0);
  187. return putcode(fd, s->frst->n->sl->this, nxt, 0, ln);
  188. case NON_ATOMIC:
  189. (void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln);
  190. break;
  191. case IF:
  192. fprintf(fd, "if (!(");
  193. if (!CollectGuards(fd, s->frst, 0))
  194. fprintf(fd, "1");
  195. fprintf(fd, "))\n\t\t\tcontinue;");
  196. isg = 1;
  197. break;
  198. case '.':
  199. if (s->frst->nxt->n->ntyp == DO)
  200. { fprintf(fd, "if (!(");
  201. if (!CollectGuards(fd, s->frst->nxt, 0))
  202. fprintf(fd, "1");
  203. fprintf(fd, "))\n\t\t\tcontinue;");
  204. isg = 1;
  205. }
  206. break;
  207. case 'R': /* <- can't really happen (it's part of a 'c') */
  208. case 'r':
  209. case 's':
  210. fprintf(fd, "if (!("); TestOnly=1;
  211. putstmnt(fd, s->frst->n, s->frst->seqno);
  212. fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
  213. break;
  214. case 'c':
  215. fprintf(fd, "if (!(");
  216. if (Pid != claimnr) fprintf(fd, "boq == -1 && ");
  217. TestOnly=1;
  218. putstmnt(fd, s->frst->n->lft, s->frst->seqno);
  219. fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
  220. break;
  221. case ASGN: /* new 3.0.8 */
  222. fprintf(fd, "IfNotBlocked");
  223. break;
  224. }
  225. if (justguards) return 0;
  226. fprintf(fd, "\n\t\tsv_save((char *)&now);\n");
  227. sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
  228. NextLab[0] = buf;
  229. putCode(fd, s->frst, s->extent, nxt, isg);
  230. if (nxt)
  231. { if (FirstTime(nxt->Seqno)
  232. && (!(nxt->status & DONE2) || !(nxt->status & D_ATOM)))
  233. { fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno);
  234. nxt->status |= DONE2;
  235. LastGoto = 0;
  236. }
  237. Sourced(nxt->Seqno, 1);
  238. Mopup(fd);
  239. }
  240. unskip(s->frst->seqno);
  241. return LastGoto;
  242. }
  243. static void
  244. putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard)
  245. { Element *e, *N;
  246. SeqList *h; int i;
  247. char NextOpt[64];
  248. static int bno = 0;
  249. for (e = f; e; e = e->nxt)
  250. { if (e->status & DONE2)
  251. continue;
  252. e->status |= DONE2;
  253. if (!(e->status & D_ATOM))
  254. { if (!LastGoto)
  255. { fprintf(fd, "\t\tgoto S_%.3d_0;\n",
  256. e->Seqno);
  257. Dested(e->Seqno);
  258. }
  259. break;
  260. }
  261. fprintf(fd, "S_%.3d_0: /* 2 */\n", e->Seqno);
  262. LastGoto = 0;
  263. Sourced(e->Seqno, 0);
  264. if (!e->sub)
  265. { filterbad(e);
  266. switch (e->n->ntyp) {
  267. case NON_ATOMIC:
  268. h = e->n->sl;
  269. putCode(fd, h->this->frst,
  270. h->this->extent, e->nxt, 0);
  271. break;
  272. case BREAK:
  273. if (LastGoto) break;
  274. if (e->nxt)
  275. { i = target( huntele(e->nxt,
  276. e->status))->Seqno;
  277. fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
  278. fprintf(fd, "/* 'break' */\n");
  279. Dested(i);
  280. } else
  281. { if (next)
  282. { fprintf(fd, "\t\tgoto S_%.3d_0;",
  283. next->Seqno);
  284. fprintf(fd, " /* NEXT */\n");
  285. Dested(next->Seqno);
  286. } else
  287. fatal("cannot interpret d_step", 0);
  288. }
  289. break;
  290. case GOTO:
  291. if (LastGoto) break;
  292. i = huntele( get_lab(e->n,1),
  293. e->status)->Seqno;
  294. fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
  295. fprintf(fd, "/* 'goto' */\n");
  296. Dested(i);
  297. break;
  298. case '.':
  299. if (LastGoto) break;
  300. if (e->nxt && (e->nxt->status & DONE2))
  301. { i = e->nxt?e->nxt->Seqno:0;
  302. fprintf(fd, "\t\tgoto S_%.3d_0;", i);
  303. fprintf(fd, " /* '.' */\n");
  304. Dested(i);
  305. }
  306. break;
  307. default:
  308. putskip(e->seqno);
  309. GenCode = 1; IsGuard = isguard;
  310. fprintf(fd, "\t\t");
  311. putstmnt(fd, e->n, e->seqno);
  312. fprintf(fd, ";\n");
  313. GenCode = IsGuard = isguard = LastGoto = 0;
  314. break;
  315. }
  316. i = e->nxt?e->nxt->Seqno:0;
  317. if (e->nxt && e->nxt->status & DONE2 && !LastGoto)
  318. { fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
  319. fprintf(fd, "/* ';' */\n");
  320. Dested(i);
  321. break;
  322. }
  323. } else
  324. { for (h = e->sub, i=1; h; h = h->nxt, i++)
  325. { sprintf(NextOpt, "goto S_%.3d_%d",
  326. e->Seqno, i);
  327. NextLab[++Level] = NextOpt;
  328. N = (e->n->ntyp == DO) ? e : e->nxt;
  329. putCode(fd, h->this->frst,
  330. h->this->extent, N, 1);
  331. Level--;
  332. fprintf(fd, "%s: /* 3 */\n", &NextOpt[5]);
  333. LastGoto = 0;
  334. }
  335. if (!LastGoto)
  336. { fprintf(fd, "\t\tUerror(\"blocking sel ");
  337. fprintf(fd, "in d_step (nr.%d, near line %d)\");\n",
  338. bno++, (e->n)?e->n->ln:0);
  339. LastGoto = 0;
  340. }
  341. }
  342. if (e == last)
  343. { if (!LastGoto && next)
  344. { fprintf(fd, "\t\tgoto S_%.3d_0;\n",
  345. next->Seqno);
  346. Dested(next->Seqno);
  347. }
  348. break;
  349. } }
  350. }