1 /***** spin: dstep.c *****/
4 * This file is part of the public release of Spin. It is subject to the
5 * terms in the LICENSE file that is included in this source directory.
6 * Tool documentation is available at http://spinroot.com
13 #define MAXDSTEP 2048 /* was 512 */
15 char *NextLab[64]; /* must match value in pangen2.c:41 */
16 int Level=0, GenCode=0, IsGuard=0, TestOnly=0;
18 static int Tj=0, Jt=0, LastGoto=0;
19 static int Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
20 static void putCode(FILE *, Element *, Element *, Element *, int);
22 extern int Pid, separate, OkBreak;
25 Sourced(int n, int special)
27 for (i = 0; i < Tj; i++)
31 fatal("d_step sequence too long", (char *)0);
32 Special[Tj] = special;
39 for (i = 0; i < Tj; i++)
42 for (i = 0; i < Jt; i++)
46 fatal("d_step sequence too long", (char *)0);
55 for (i = 0; i < Jt; i++)
56 { for (j = 0; j < Tj; j++)
57 if (Tojump[j] == Jumpto[i])
61 if (Jumpto[i] == OkBreak)
63 fprintf(fd, "S_%.3d_0: /* break-dest */\n",
66 sprintf(buf, "S_%.3d_0", Jumpto[i]);
67 non_fatal("goto %s breaks from d_step seq", buf);
69 for (j = 0; j < Tj; j++)
70 { for (i = 0; i < Jt; i++)
71 if (Tojump[j] == Jumpto[i])
74 if (i == Jt && !Special[i])
75 fprintf(fd, "\t\t/* no goto's to S_%.3d_0 */\n",
79 for (j = i = 0; j < Tj; j++)
82 { fatal("cannot happen (dstep.c)", (char *)0);
84 Tojump[i] = Tojump[j];
88 Tj = i; /* keep only the global exit-labels */
95 for (i = 0; i < Tj; i++)
97 return (Special[i] <= 1);
102 illegal(Element *e, char *str)
104 printf("illegal operator in 'd_step:' '");
105 comment(stdout, e->n, 0);
111 filterbad(Element *e)
113 switch (e->n->ntyp) {
117 /* run cannot be completely undone
118 * with sv_save-sv_restor
120 if (any_oper(e->n->lft, RUN))
121 illegal(e, "run operator in d_step");
123 /* remote refs inside d_step sequences
124 * would be okay, but they cannot always
125 * be interpreted by the simulator the
126 * same as by the verifier (e.g., for an
129 if (any_oper(e->n->lft, 'p'))
130 illegal(e, "remote reference in d_step");
133 illegal(e, "process termination");
136 illegal(e, "nested d_step sequence");
139 illegal(e, "nested atomic sequence");
147 CollectGuards(FILE *fd, Element *e, int inh)
148 { SeqList *h; Element *ee;
150 for (h = e->sub; h; h = h->nxt)
151 { ee = huntstart(h->this->frst);
153 switch (ee->n->ntyp) {
155 inh += CollectGuards(fd, ee->n->sl->this->frst, inh);
158 inh += CollectGuards(fd, ee, inh);
161 if (ee->nxt->n->ntyp == DO)
162 inh += CollectGuards(fd, ee->nxt, inh);
165 if (inh++ > 0) fprintf(fd, " || ");
166 /* 4.2.5 */ if (!pid_is_claim(Pid))
167 fprintf(fd, "(boq == -1 /* else */)");
169 fprintf(fd, "(1 /* else */)");
172 if (inh++ > 0) fprintf(fd, " || ");
173 fprintf(fd, "("); TestOnly=1;
174 putstmnt(fd, ee->n, ee->seqno);
175 fprintf(fd, ")"); TestOnly=0;
178 if (inh++ > 0) fprintf(fd, " || ");
179 fprintf(fd, "("); TestOnly=1;
180 putstmnt(fd, ee->n, ee->seqno);
181 fprintf(fd, ")"); TestOnly=0;
184 if (inh++ > 0) fprintf(fd, " || ");
185 fprintf(fd, "("); TestOnly=1;
186 /* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1) && ");
187 putstmnt(fd, ee->n, ee->seqno);
188 fprintf(fd, ")"); TestOnly=0;
191 if (inh++ > 0) fprintf(fd, " || ");
192 fprintf(fd, "("); TestOnly=1;
193 if (!pid_is_claim(Pid))
194 fprintf(fd, "(boq == -1 && ");
195 putstmnt(fd, ee->n->lft, e->seqno);
196 if (!pid_is_claim(Pid))
198 fprintf(fd, ")"); TestOnly=0;
205 putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln, int seqno)
209 NextLab[0] = "continue";
212 switch (s->frst->n->ntyp) {
214 non_fatal("'unless' inside d_step - ignored", (char *) 0);
215 return putcode(fd, s->frst->n->sl->this, nxt, 0, ln, seqno);
217 (void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln, seqno);
218 if (justguards) return 0; /* 6.2.5 */
221 fprintf(fd, "if (!(");
222 if (!CollectGuards(fd, s->frst, 0)) /* what about boq? */
224 fprintf(fd, "))\n\t\t\tcontinue;");
228 if (s->frst->nxt->n->ntyp == DO)
229 { fprintf(fd, "if (!(");
230 if (!CollectGuards(fd, s->frst->nxt, 0))
232 fprintf(fd, "))\n\t\t\tcontinue;");
236 case 'R': /* <- can't really happen (it's part of a 'c') */
237 fprintf(fd, "if (!("); TestOnly=1;
238 putstmnt(fd, s->frst->n, s->frst->seqno);
239 fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
242 fprintf(fd, "if (!("); TestOnly=1;
243 putstmnt(fd, s->frst->n, s->frst->seqno);
244 fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
249 /* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq != -1) || ");
251 fprintf(fd, "!("); TestOnly=1;
252 putstmnt(fd, s->frst->n, s->frst->seqno);
253 fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
256 fprintf(fd, "if (!(");
257 if (!pid_is_claim(Pid)) fprintf(fd, "boq == -1 && ");
259 putstmnt(fd, s->frst->n->lft, s->frst->seqno);
260 fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
263 fprintf(fd, "if (boq != -1 || (");
264 if (separate != 2) fprintf(fd, "trpt->");
265 fprintf(fd, "o_pm&1))\n\t\t\tcontinue;");
267 fprintf(th, "#ifndef ELSE_IN_GUARD\n");
268 fprintf(th, " #define ELSE_IN_GUARD\n");
269 fprintf(th, "#endif\n");
272 case ASGN: /* new 3.0.8 */
273 fprintf(fd, "IfNotBlocked");
276 fprintf(fd, "/* default %d */\n\t\t", s->frst->n->ntyp);
279 /* 6.2.5 : before TstOnly */
280 fprintf(fd, "\n\n\t\treached[%d][%d] = 1;\n\t\t", Pid, seqno);
281 fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid); /* next state */
282 fprintf(fd, "reached[%d][tt] = 1;\n", Pid); /* current state */
284 /* 6.2.5 : before sv_save() */
285 if (s->frst->n->ntyp != NON_ATOMIC)
286 fprintf(fd, "\n\t\tif (TstOnly) return 1;\n"); /* if called from enabled() */
288 if (justguards) return 0;
290 fprintf(fd, "\n\t\tsv_save();\n\t\t");
291 sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
293 putCode(fd, s->frst, s->extent, nxt, isg);
296 { extern Symbol *Fname;
299 if (FirstTime(nxt->Seqno)
300 && (!(nxt->status & DONE2) || !(nxt->status & D_ATOM)))
301 { fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno);
302 nxt->status |= DONE2;
305 Sourced(nxt->Seqno, 1);
310 unskip(s->frst->seqno);
315 putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard)
321 for (e = f; e; e = e->nxt)
322 { if (e->status & DONE2)
326 if (!(e->status & D_ATOM))
328 { fprintf(fd, "\t\tgoto S_%.3d_0;\n",
334 fprintf(fd, "S_%.3d_0: /* 2 */\n", e->Seqno);
336 Sourced(e->Seqno, 0);
340 switch (e->n->ntyp) {
343 putCode(fd, h->this->frst,
344 h->this->extent, e->nxt, 0);
349 { i = target( huntele(e->nxt,
350 e->status, -1))->Seqno;
351 fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
352 fprintf(fd, "/* 'break' */\n");
356 { fprintf(fd, "\t\tgoto S_%.3d_0;",
358 fprintf(fd, " /* NEXT */\n");
361 fatal("cannot interpret d_step", 0);
366 i = huntele( get_lab(e->n,1),
367 e->status, -1)->Seqno;
368 fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
369 fprintf(fd, "/* 'goto' */\n");
374 if (e->nxt && (e->nxt->status & DONE2))
376 fprintf(fd, "\t\tgoto S_%.3d_0;", i);
377 fprintf(fd, " /* '.' */\n");
383 GenCode = 1; IsGuard = isguard;
385 putstmnt(fd, e->n, e->seqno);
387 GenCode = IsGuard = isguard = LastGoto = 0;
390 i = e->nxt?e->nxt->Seqno:0;
391 if (e->nxt && (e->nxt->status & DONE2) && !LastGoto)
392 { fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
393 fprintf(fd, "/* ';' */\n");
398 { for (h = e->sub, i=1; h; h = h->nxt, i++)
399 { sprintf(NextOpt, "goto S_%.3d_%d",
401 NextLab[++Level] = NextOpt;
402 N = (e->n && e->n->ntyp == DO) ? e : e->nxt;
403 putCode(fd, h->this->frst,
404 h->this->extent, N, 1);
406 fprintf(fd, "%s: /* 3 */\n", &NextOpt[5]);
410 { fprintf(fd, "\t\tUerror(\"blocking sel ");
411 fprintf(fd, "in d_step (nr.%d, near line %d)\");\n",
412 bno++, (e->n)?e->n->ln:0);
417 { if (!LastGoto && next)
418 { fprintf(fd, "\t\tgoto S_%.3d_0;\n",