static Nodes * circbreak1(ASTNode *n) { ASTNode *idx; BitSet *visit; ASTNode *m; int r; if(n->t == ASTASS && n->n2 != nil && n->n2->t == ASTISUB) { idx = n->n2->n1; assert(idx != nil && idx->t == ASTIDX); if(n->n1->t == ASTSSA && idx->n1->t == ASTSSA && idx->n1->semv == idx->n1->semv->sym->semc[1]) { visit = bsnew(nvars); r = findcircles(idx->n1->semv, n->n1->semv, visit); bsfree(visit); if(r) { m = nodedup(n); m->n2 = nodedup(m->n2); m->n2->n1 = nodedup(m->n2->n1); m->n2->n1->n1 = node(ASTSSA, idx->n1->semv->sym->semc[0]); circbroken++; return nl(m); } } } return nl(n); }
/* copy blocks and create definitions for the primed values as needed */ static void makenext(void) { SemBlock *b, *c; BitSet *copy; int i, j, ch; copy = bsnew(nblocks); for(i = 0; i < nblocks; i++) { b = blocks[i]; if(descendsum(b->phi, countnext) + descendsum(b->cont, countnext) > 0) bsadd(copy, i); } do { ch = 0; for(i = -1; i = bsiter(copy, i), i >= 0; ) { b = blocks[i]; for(j = 0; j < b->nto; j++) ch += bsadd(copy, b->to[j]->idx) == 0; for(j = 0; j < b->nfrom; j++) ch += bsadd(copy, b->from[j]->idx) == 0; } } while(ch != 0); dupl = emalloc(nblocks * sizeof(SemBlock *)); for(i = -1; i = bsiter(copy, i), i >= 0; ) dupl[i] = newblock(); for(i = -1; i = bsiter(copy, i), i >= 0; ) { b = blocks[i]; c = dupl[i]; c->nto = b->nto; c->to = emalloc(sizeof(SemBlock *) * c->nto); c->nfrom = b->nfrom; c->from = emalloc(sizeof(SemBlock *) * c->nfrom); for(j = 0; j < b->nto; j++) { c->to[j] = dupl[b->to[j]->idx]; assert(c->to[j] != nil); } for(j = 0; j < b->nfrom; j++) { c->from[j] = dupl[b->from[j]->idx]; assert(c->from[j] != nil); } c->phi = mkblock(descend(b->phi, nil, makenext1)); c->cont = mkblock(descend(b->cont, nil, makenext1)); c->jump = mkblock(descend(b->jump, nil, makenext1)); } for(i = 0; i < nblocks; i++) { b = blocks[i]; b->phi = mkblock(descend(b->phi, nil, deldefs)); b->cont = mkblock(descend(b->cont, nil, deldefs)); } bsfree(copy); }
static void doif(ASTNode *n, int ctxt) { BitSet *g, *k, *kp; BitSet *g1, *k1, *k1p; BitSet *g2, *k2, *k2p, *t; PipeStage *p; p = stcur; t = bsnew(p->nvars); findstages(n->n1, ctxt); g = p->gen; k = p->kill; kp = p->killp; p->gen = g1 = bsdup(g); p->kill = k1 = bsdup(k); p->killp = k1p = bsdup(kp); findstages(n->n2, ctxt); p->gen = g2 = bsdup(g); p->kill = k2 = bsdup(k); p->killp = k2p = bsdup(kp); findstages(n->n3, ctxt); bsunion(g, g1, g); bsunion(g, g2, g); bsunion(k, k1, k); bsunion(k, k2, k); bsunion(kp, k1p, kp); bsunion(kp, k2p, kp); bsminus(t, k1, k2); addeq(t, &n->n3, 0); bsunion(g, t, g); bsminus(t, k2, k1); addeq(t, &n->n2, 0); bsunion(g, t, g); bsminus(t, k1p, k2p); addeq(t, &n->n3, 1); bsunion(g, t, g); bsminus(t, k2p, k1p); addeq(t, &n->n2, 1); bsunion(g, t, g); p->gen = g; p->kill = k; p->killp = kp; bsfree(g1); bsfree(g2); bsfree(k1); bsfree(k2); bsfree(k1p); bsfree(k2p); bsfree(t); }
static void propsets(void) { PipeStage *s; for(s = stlist.next; s != &stlist; s = s->next) s->live = bsnew(s->nvars); for(s = stlist.prev; s != &stlist; s = s->prev){ bsunion(s->kill, s->kill, s->killp); if(s->next != &stlist) bsminus(s->live, s->next->live, s->kill); bsunion(s->live, s->live, s->gen); } }
static void circdefs(void) { int i; BitSet *visit; visit = bsnew(nvars); for(i = 0; i < nvars; i++) { bsreset(visit); if(vars[i] == vars[i]->sym->semc[0] && findcircles(vars[i], vars[i], visit)) error(vars[i]->sym, "combinational loop involving %s", vars[i]->sym->name); bsreset(visit); if(vars[i] == vars[i]->sym->semc[1] && findcircles(vars[i], vars[i], visit)) error(vars[i]->sym, "combinational loop involving %s'", vars[i]->sym->name); } bsfree(visit); }
static int l_loadbs( lua_State* L ) { gwlua_t* state = get_state( L ); const char* name = luaL_checkstring( L, 1 ); gwrom_entry_t entry; if ( gwrom_find( &entry, state->rom, name ) == GWROM_OK ) { void* bs = bsnew( entry.data ); if ( bs ) { lua_pushlightuserdata( L, bs ); lua_pushcclosure( L, l_bsread, 1 ); return 1; } } return 0; }
/* process synchronous initializations */ static int syncinit(void) { int i, rc, nb; SemBlock *b; nb = nblocks; sinitvisit = bsnew(nb); rc = 0; for(i = 0; i < nb; i++) { b = blocks[i]; if(b->nto != 0) continue; bsreset(sinitvisit); sinitvars = defsnew(); sinitsearch(b); sinitgather(); sinitbuild(b); rc += sinits != nil; free(sinitvars); } return rc; }
Nodes * findpipe(ASTNode *n) { Nodes *pipebl, *decls; Nodes *r; Symbol *go; if(n == nil || n->t != ASTPIPEL) return nl(n); curpipec = n; go = n->n2 != nil ? n->n2->sym : nil; stlist.next = stlist.prev = &stlist; findstages(n, 0); propsets(); mksym(n->st->up); stcur = nil; procvars(go, &pipebl, &decls); killed = bsnew(stlist.prev->nvars); r = decls; if(n->n2 != nil) r = nlcat(nl(n->n2), r); r = nlcat(r, process(n)); r = nlcat(r, nl(node(ASTBLOCK, pipebl))); return r; }
static void findstages(ASTNode *n, int ctxt) { PipeStage *p; Nodes *r; if(n == nil) return; switch(n->t){ case ASTPIPEL: for(r = n->nl; r != nil; r = r->next) findstages(r->n, ctxt); break; case ASTSTATE: p = emalloc(sizeof(PipeStage)); p->sym = n->sym; if(stcur != nil){ p->nvars = stcur->nvars; if(p->nvars != 0){ p->vars = emalloc(-(-p->nvars & -VARBLOCK) * sizeof(Symbol *)); memcpy(p->vars, stcur->vars, p->nvars * sizeof(Symbol *)); } } p->gen = bsnew(-(-p->nvars & -VARBLOCK)); p->kill = bsnew(-(-p->nvars & -VARBLOCK)); p->killp = bsnew(-(-p->nvars & -VARBLOCK)); p->prev = stlist.prev; p->next = &stlist; p->prev->next = p; p->next->prev = p; stcur = p; break; case ASTDECL: if(stcur == nil){ out: error(n, "statement outside of stage"); return; } if(stcur->nvars % VARBLOCK == 0){ stcur->vars = erealloc(stcur->vars, sizeof(Symbol *), stcur->nvars, VARBLOCK); stcur->gen = bsgrow(stcur->gen, stcur->nvars + VARBLOCK); stcur->kill = bsgrow(stcur->kill, stcur->nvars + VARBLOCK); stcur->killp = bsgrow(stcur->kill, stcur->nvars + VARBLOCK); } stcur->vars[stcur->nvars] = n->sym; n->sym->pipeidx = stcur->nvars; stcur->nvars++; break; case ASTASS: if(stcur == nil) goto out; findstages(n->n2, ctxt); findstages(n->n1, ctxt|LVAL); break; case ASTSYMB: if(stcur == nil) goto out; if(n->sym->pipeidx < 0) break; switch(ctxt & (LVAL|PRIME)){ case 0: if(!bstest(stcur->kill, n->sym->pipeidx)) bsadd(stcur->gen, n->sym->pipeidx); break; case LVAL: if(bstest(stcur->killp, n->sym->pipeidx)) error(n, "conflicting definitions for %s", n->sym->name); bsadd(stcur->kill, n->sym->pipeidx); break; case PRIME: if(!bstest(stcur->killp, n->sym->pipeidx)) error(n, "primed variable undefined"); break; case LVAL|PRIME: if(bstest(stcur->kill, n->sym->pipeidx)) error(n, "conflicting definitions for %s", n->sym->name); bsadd(stcur->killp, n->sym->pipeidx); break; } break; case ASTPRIME: findstages(n->n1, ctxt | PRIME); break; case ASTCINT: case ASTCONST: break; case ASTOP: case ASTTERN: case ASTIDX: case ASTMEMB: findstages(n->n1, ctxt); findstages(n->n2, ctxt); findstages(n->n3, ctxt); findstages(n->n4, ctxt); break; case ASTIF: doif(n, ctxt); break; default: error(n, "findstages: unknown %A", n->t); } }