17dd7cddfSDavid du Colombier /***** tl_spin: tl_cache.c *****/
27dd7cddfSDavid du Colombier
3312a1df1SDavid du Colombier /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories. */
47dd7cddfSDavid du Colombier /* All Rights Reserved. This software is for educational purposes only. */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code. Permission is given to distribute this code provided that */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged. */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann. For tool documentation see: */
9312a1df1SDavid du Colombier /* http://spinroot.com/ */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com */
11312a1df1SDavid du Colombier
127dd7cddfSDavid du Colombier /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
137dd7cddfSDavid du Colombier /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier #include "tl.h"
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier typedef struct Cache {
187dd7cddfSDavid du Colombier Node *before;
197dd7cddfSDavid du Colombier Node *after;
207dd7cddfSDavid du Colombier int same;
217dd7cddfSDavid du Colombier struct Cache *nxt;
227dd7cddfSDavid du Colombier } Cache;
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier static Cache *stored = (Cache *) 0;
257dd7cddfSDavid du Colombier static unsigned long Caches, CacheHits;
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier static int ismatch(Node *, Node *);
287dd7cddfSDavid du Colombier extern void fatal(char *, char *);
297dd7cddfSDavid du Colombier int sameform(Node *, Node *);
307dd7cddfSDavid du Colombier
31*00d97012SDavid du Colombier void
ini_cache(void)32*00d97012SDavid du Colombier ini_cache(void)
33*00d97012SDavid du Colombier {
34*00d97012SDavid du Colombier stored = (Cache *) 0;
35*00d97012SDavid du Colombier Caches = 0;
36*00d97012SDavid du Colombier CacheHits = 0;
37*00d97012SDavid du Colombier }
38*00d97012SDavid du Colombier
39312a1df1SDavid du Colombier #if 0
407dd7cddfSDavid du Colombier void
417dd7cddfSDavid du Colombier cache_dump(void)
427dd7cddfSDavid du Colombier { Cache *d; int nr=0;
437dd7cddfSDavid du Colombier
447dd7cddfSDavid du Colombier printf("\nCACHE DUMP:\n");
457dd7cddfSDavid du Colombier for (d = stored; d; d = d->nxt, nr++)
467dd7cddfSDavid du Colombier { if (d->same) continue;
477dd7cddfSDavid du Colombier printf("B%3d: ", nr); dump(d->before); printf("\n");
487dd7cddfSDavid du Colombier printf("A%3d: ", nr); dump(d->after); printf("\n");
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier printf("============\n");
517dd7cddfSDavid du Colombier }
52312a1df1SDavid du Colombier #endif
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier Node *
in_cache(Node * n)557dd7cddfSDavid du Colombier in_cache(Node *n)
567dd7cddfSDavid du Colombier { Cache *d; int nr=0;
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier for (d = stored; d; d = d->nxt, nr++)
597dd7cddfSDavid du Colombier if (isequal(d->before, n))
607dd7cddfSDavid du Colombier { CacheHits++;
617dd7cddfSDavid du Colombier if (d->same && ismatch(n, d->before)) return n;
627dd7cddfSDavid du Colombier return dupnode(d->after);
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier return ZN;
657dd7cddfSDavid du Colombier }
667dd7cddfSDavid du Colombier
677dd7cddfSDavid du Colombier Node *
cached(Node * n)687dd7cddfSDavid du Colombier cached(Node *n)
697dd7cddfSDavid du Colombier { Cache *d;
707dd7cddfSDavid du Colombier Node *m;
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier if (!n) return n;
73312a1df1SDavid du Colombier if ((m = in_cache(n)) != ZN)
747dd7cddfSDavid du Colombier return m;
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier Caches++;
777dd7cddfSDavid du Colombier d = (Cache *) tl_emalloc(sizeof(Cache));
787dd7cddfSDavid du Colombier d->before = dupnode(n);
797dd7cddfSDavid du Colombier d->after = Canonical(n); /* n is released */
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier if (ismatch(d->before, d->after))
827dd7cddfSDavid du Colombier { d->same = 1;
837dd7cddfSDavid du Colombier releasenode(1, d->after);
847dd7cddfSDavid du Colombier d->after = d->before;
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier d->nxt = stored;
877dd7cddfSDavid du Colombier stored = d;
887dd7cddfSDavid du Colombier return dupnode(d->after);
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier void
cache_stats(void)927dd7cddfSDavid du Colombier cache_stats(void)
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier printf("cache stores : %9ld\n", Caches);
957dd7cddfSDavid du Colombier printf("cache hits : %9ld\n", CacheHits);
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier
987dd7cddfSDavid du Colombier void
releasenode(int all_levels,Node * n)997dd7cddfSDavid du Colombier releasenode(int all_levels, Node *n)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier if (!n) return;
1027dd7cddfSDavid du Colombier
1037dd7cddfSDavid du Colombier if (all_levels)
1047dd7cddfSDavid du Colombier { releasenode(1, n->lft);
1057dd7cddfSDavid du Colombier n->lft = ZN;
1067dd7cddfSDavid du Colombier releasenode(1, n->rgt);
1077dd7cddfSDavid du Colombier n->rgt = ZN;
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier tfree((void *) n);
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier
1127dd7cddfSDavid du Colombier Node *
tl_nn(int t,Node * ll,Node * rl)1137dd7cddfSDavid du Colombier tl_nn(int t, Node *ll, Node *rl)
1147dd7cddfSDavid du Colombier { Node *n = (Node *) tl_emalloc(sizeof(Node));
1157dd7cddfSDavid du Colombier
1167dd7cddfSDavid du Colombier n->ntyp = (short) t;
1177dd7cddfSDavid du Colombier n->lft = ll;
1187dd7cddfSDavid du Colombier n->rgt = rl;
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier return n;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier Node *
getnode(Node * p)1247dd7cddfSDavid du Colombier getnode(Node *p)
1257dd7cddfSDavid du Colombier { Node *n;
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier if (!p) return p;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier n = (Node *) tl_emalloc(sizeof(Node));
1307dd7cddfSDavid du Colombier n->ntyp = p->ntyp;
1317dd7cddfSDavid du Colombier n->sym = p->sym; /* same name */
1327dd7cddfSDavid du Colombier n->lft = p->lft;
1337dd7cddfSDavid du Colombier n->rgt = p->rgt;
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier return n;
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier Node *
dupnode(Node * n)1397dd7cddfSDavid du Colombier dupnode(Node *n)
1407dd7cddfSDavid du Colombier { Node *d;
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier if (!n) return n;
1437dd7cddfSDavid du Colombier d = getnode(n);
1447dd7cddfSDavid du Colombier d->lft = dupnode(n->lft);
1457dd7cddfSDavid du Colombier d->rgt = dupnode(n->rgt);
1467dd7cddfSDavid du Colombier return d;
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier int
one_lft(int ntyp,Node * x,Node * in)1507dd7cddfSDavid du Colombier one_lft(int ntyp, Node *x, Node *in)
1517dd7cddfSDavid du Colombier {
1527dd7cddfSDavid du Colombier if (!x) return 1;
1537dd7cddfSDavid du Colombier if (!in) return 0;
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier if (sameform(x, in))
1567dd7cddfSDavid du Colombier return 1;
1577dd7cddfSDavid du Colombier
1587dd7cddfSDavid du Colombier if (in->ntyp != ntyp)
1597dd7cddfSDavid du Colombier return 0;
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier if (one_lft(ntyp, x, in->lft))
1627dd7cddfSDavid du Colombier return 1;
1637dd7cddfSDavid du Colombier
1647dd7cddfSDavid du Colombier return one_lft(ntyp, x, in->rgt);
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier
1677dd7cddfSDavid du Colombier int
all_lfts(int ntyp,Node * from,Node * in)1687dd7cddfSDavid du Colombier all_lfts(int ntyp, Node *from, Node *in)
1697dd7cddfSDavid du Colombier {
1707dd7cddfSDavid du Colombier if (!from) return 1;
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier if (from->ntyp != ntyp)
1737dd7cddfSDavid du Colombier return one_lft(ntyp, from, in);
1747dd7cddfSDavid du Colombier
1757dd7cddfSDavid du Colombier if (!one_lft(ntyp, from->lft, in))
1767dd7cddfSDavid du Colombier return 0;
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier return all_lfts(ntyp, from->rgt, in);
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier
1817dd7cddfSDavid du Colombier int
sametrees(int ntyp,Node * a,Node * b)1827dd7cddfSDavid du Colombier sametrees(int ntyp, Node *a, Node *b)
1837dd7cddfSDavid du Colombier { /* toplevel is an AND or OR */
1847dd7cddfSDavid du Colombier /* both trees are right-linked, but the leafs */
1857dd7cddfSDavid du Colombier /* can be in different places in the two trees */
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier if (!all_lfts(ntyp, a, b))
1887dd7cddfSDavid du Colombier return 0;
1897dd7cddfSDavid du Colombier
1907dd7cddfSDavid du Colombier return all_lfts(ntyp, b, a);
1917dd7cddfSDavid du Colombier }
1927dd7cddfSDavid du Colombier
1937dd7cddfSDavid du Colombier int /* a better isequal() */
sameform(Node * a,Node * b)1947dd7cddfSDavid du Colombier sameform(Node *a, Node *b)
1957dd7cddfSDavid du Colombier {
1967dd7cddfSDavid du Colombier if (!a && !b) return 1;
1977dd7cddfSDavid du Colombier if (!a || !b) return 0;
1987dd7cddfSDavid du Colombier if (a->ntyp != b->ntyp) return 0;
1997dd7cddfSDavid du Colombier
2007dd7cddfSDavid du Colombier if (a->sym
2017dd7cddfSDavid du Colombier && b->sym
2027dd7cddfSDavid du Colombier && strcmp(a->sym->name, b->sym->name) != 0)
2037dd7cddfSDavid du Colombier return 0;
2047dd7cddfSDavid du Colombier
2057dd7cddfSDavid du Colombier switch (a->ntyp) {
2067dd7cddfSDavid du Colombier case TRUE:
2077dd7cddfSDavid du Colombier case FALSE:
2087dd7cddfSDavid du Colombier return 1;
2097dd7cddfSDavid du Colombier case PREDICATE:
2107dd7cddfSDavid du Colombier if (!a->sym || !b->sym) fatal("sameform...", (char *) 0);
2117dd7cddfSDavid du Colombier return !strcmp(a->sym->name, b->sym->name);
2127dd7cddfSDavid du Colombier
2137dd7cddfSDavid du Colombier case NOT:
2147dd7cddfSDavid du Colombier #ifdef NXT
2157dd7cddfSDavid du Colombier case NEXT:
2167dd7cddfSDavid du Colombier #endif
2177dd7cddfSDavid du Colombier return sameform(a->lft, b->lft);
2187dd7cddfSDavid du Colombier case U_OPER:
2197dd7cddfSDavid du Colombier case V_OPER:
2207dd7cddfSDavid du Colombier if (!sameform(a->lft, b->lft))
2217dd7cddfSDavid du Colombier return 0;
2227dd7cddfSDavid du Colombier if (!sameform(a->rgt, b->rgt))
2237dd7cddfSDavid du Colombier return 0;
2247dd7cddfSDavid du Colombier return 1;
2257dd7cddfSDavid du Colombier
2267dd7cddfSDavid du Colombier case AND:
2277dd7cddfSDavid du Colombier case OR: /* the hard case */
2287dd7cddfSDavid du Colombier return sametrees(a->ntyp, a, b);
2297dd7cddfSDavid du Colombier
2307dd7cddfSDavid du Colombier default:
2317dd7cddfSDavid du Colombier printf("type: %d\n", a->ntyp);
2327dd7cddfSDavid du Colombier fatal("cannot happen, sameform", (char *) 0);
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier
2357dd7cddfSDavid du Colombier return 0;
2367dd7cddfSDavid du Colombier }
2377dd7cddfSDavid du Colombier
2387dd7cddfSDavid du Colombier int
isequal(Node * a,Node * b)2397dd7cddfSDavid du Colombier isequal(Node *a, Node *b)
2407dd7cddfSDavid du Colombier {
2417dd7cddfSDavid du Colombier if (!a && !b)
2427dd7cddfSDavid du Colombier return 1;
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier if (!a || !b)
2457dd7cddfSDavid du Colombier { if (!a)
2467dd7cddfSDavid du Colombier { if (b->ntyp == TRUE)
2477dd7cddfSDavid du Colombier return 1;
2487dd7cddfSDavid du Colombier } else
2497dd7cddfSDavid du Colombier { if (a->ntyp == TRUE)
2507dd7cddfSDavid du Colombier return 1;
2517dd7cddfSDavid du Colombier }
2527dd7cddfSDavid du Colombier return 0;
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier if (a->ntyp != b->ntyp)
2557dd7cddfSDavid du Colombier return 0;
2567dd7cddfSDavid du Colombier
2577dd7cddfSDavid du Colombier if (a->sym
2587dd7cddfSDavid du Colombier && b->sym
2597dd7cddfSDavid du Colombier && strcmp(a->sym->name, b->sym->name) != 0)
2607dd7cddfSDavid du Colombier return 0;
2617dd7cddfSDavid du Colombier
2627dd7cddfSDavid du Colombier if (isequal(a->lft, b->lft)
2637dd7cddfSDavid du Colombier && isequal(a->rgt, b->rgt))
2647dd7cddfSDavid du Colombier return 1;
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier return sameform(a, b);
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier
2697dd7cddfSDavid du Colombier static int
ismatch(Node * a,Node * b)2707dd7cddfSDavid du Colombier ismatch(Node *a, Node *b)
2717dd7cddfSDavid du Colombier {
2727dd7cddfSDavid du Colombier if (!a && !b) return 1;
2737dd7cddfSDavid du Colombier if (!a || !b) return 0;
2747dd7cddfSDavid du Colombier if (a->ntyp != b->ntyp) return 0;
2757dd7cddfSDavid du Colombier
2767dd7cddfSDavid du Colombier if (a->sym
2777dd7cddfSDavid du Colombier && b->sym
2787dd7cddfSDavid du Colombier && strcmp(a->sym->name, b->sym->name) != 0)
2797dd7cddfSDavid du Colombier return 0;
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier if (ismatch(a->lft, b->lft)
2827dd7cddfSDavid du Colombier && ismatch(a->rgt, b->rgt))
2837dd7cddfSDavid du Colombier return 1;
2847dd7cddfSDavid du Colombier
2857dd7cddfSDavid du Colombier return 0;
2867dd7cddfSDavid du Colombier }
2877dd7cddfSDavid du Colombier
2887dd7cddfSDavid du Colombier int
any_term(Node * srch,Node * in)2897dd7cddfSDavid du Colombier any_term(Node *srch, Node *in)
2907dd7cddfSDavid du Colombier {
2917dd7cddfSDavid du Colombier if (!in) return 0;
2927dd7cddfSDavid du Colombier
2937dd7cddfSDavid du Colombier if (in->ntyp == AND)
2947dd7cddfSDavid du Colombier return any_term(srch, in->lft) ||
2957dd7cddfSDavid du Colombier any_term(srch, in->rgt);
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier return isequal(in, srch);
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier
3007dd7cddfSDavid du Colombier int
any_and(Node * srch,Node * in)3017dd7cddfSDavid du Colombier any_and(Node *srch, Node *in)
3027dd7cddfSDavid du Colombier {
3037dd7cddfSDavid du Colombier if (!in) return 0;
3047dd7cddfSDavid du Colombier
3057dd7cddfSDavid du Colombier if (srch->ntyp == AND)
3067dd7cddfSDavid du Colombier return any_and(srch->lft, in) &&
3077dd7cddfSDavid du Colombier any_and(srch->rgt, in);
3087dd7cddfSDavid du Colombier
3097dd7cddfSDavid du Colombier return any_term(srch, in);
3107dd7cddfSDavid du Colombier }
3117dd7cddfSDavid du Colombier
3127dd7cddfSDavid du Colombier int
any_lor(Node * srch,Node * in)3137dd7cddfSDavid du Colombier any_lor(Node *srch, Node *in)
3147dd7cddfSDavid du Colombier {
3157dd7cddfSDavid du Colombier if (!in) return 0;
3167dd7cddfSDavid du Colombier
3177dd7cddfSDavid du Colombier if (in->ntyp == OR)
3187dd7cddfSDavid du Colombier return any_lor(srch, in->lft) ||
3197dd7cddfSDavid du Colombier any_lor(srch, in->rgt);
3207dd7cddfSDavid du Colombier
3217dd7cddfSDavid du Colombier return isequal(in, srch);
3227dd7cddfSDavid du Colombier }
3237dd7cddfSDavid du Colombier
3247dd7cddfSDavid du Colombier int
anywhere(int tok,Node * srch,Node * in)3257dd7cddfSDavid du Colombier anywhere(int tok, Node *srch, Node *in)
3267dd7cddfSDavid du Colombier {
3277dd7cddfSDavid du Colombier if (!in) return 0;
3287dd7cddfSDavid du Colombier
3297dd7cddfSDavid du Colombier switch (tok) {
3307dd7cddfSDavid du Colombier case AND: return any_and(srch, in);
3317dd7cddfSDavid du Colombier case OR: return any_lor(srch, in);
3327dd7cddfSDavid du Colombier case 0: return any_term(srch, in);
3337dd7cddfSDavid du Colombier }
3347dd7cddfSDavid du Colombier fatal("cannot happen, anywhere", (char *) 0);
3357dd7cddfSDavid du Colombier return 0;
3367dd7cddfSDavid du Colombier }
337