diff --git a/.github/PULL_REQUEST_TEMPLATE/api.md b/.github/PULL_REQUEST_TEMPLATE/api.md new file mode 100644 index 00000000..5fa05cbd --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/api.md @@ -0,0 +1,28 @@ + + +## Description + + +## Purpose of this API change + + + +## Types of changes + +- [ ] New API (non-breaking change, adds functionality) +- [ ] Modified API (breaking change) + +For any changes, please ensure that existing test cases pass. For any +API changes, please ensure that the [actflow](https://github.com/asyncvlsi/actflow) repo builds and test cases pass with the proposed changes. + +## How has this been tested? + + +## Checklist: + + +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. +- [ ] I have added tests to cover my changes. +- [ ] All new and existing tests passed. +- [ ] The [actflow](https://github.com/asyncvlsi/actflow) repository builds with the changes, and test cases pass. diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.md b/.github/PULL_REQUEST_TEMPLATE/bug.md new file mode 100644 index 00000000..e13945e8 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/bug.md @@ -0,0 +1,23 @@ + + +## Description of change + + +## Purpose of this change + + + +Please provide additional test cases that trigger this bug, i.e. which +break without the fix, and that pass with the proposed fix. + +## How has this been tested? + + +## Checklist: + + +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. +- [ ] I have added tests to cover my changes. +- [ ] All new and existing tests passed. +- [ ] The [actflow](https://github.com/asyncvlsi/actflow) repository builds with the changes, and test cases pass. diff --git a/.github/PULL_REQUEST_TEMPLATE/generic.md b/.github/PULL_REQUEST_TEMPLATE/generic.md new file mode 100644 index 00000000..30bbb1d8 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/generic.md @@ -0,0 +1,33 @@ + + +## Description + + +## Purpose of this change + + + +## Types of changes + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New API (non-breaking change, adds functionality) +- [ ] Modified API (breaking change) +- [ ] New language feature (non-breaking change which adds functionality; note: this is unlikely to be accepted without prior discussions with core developers.) + +For any changes, please ensure that existing test cases pass. For any +API changes, please ensure that the [actflow](https://github.com/asyncvlsi/actflow) repo builds and test cases pass with the proposed changes. + +For bug fixes, please provide additional test cases that would break without +the fix, and that pass with the proposed fixes. + +## How has this been tested? + + +## Checklist: + + +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. +- [ ] I have added tests to cover my changes. +- [ ] All new and existing tests passed. +- [ ] The [actflow](https://github.com/asyncvlsi/actflow) repository builds with the changes, and test cases pass. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..92c86dab --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,5 @@ +Please go to the `Preview` tab and select the appropriate sub-template: + +* [Bug fix](?expand=1&template=bug.md) : this request fixes a bug +* [API changes](?expand=1&template=api.md) : this request changes the ACT library API +* [Generic](?expand=1&template=generic.md) : a combination of the two or other change diff --git a/act/act.cc b/act/act.cc index 90c44ff8..71843bb7 100644 --- a/act/act.cc +++ b/act/act.cc @@ -576,6 +576,8 @@ static void _init_tr (ActTree *tr, TypeFactory *tf, ActNamespace *G) tr->special_id = 0; tr->special_id_sc = NULL; + + tr->allow_chan = false; } static void _free_tr (ActTree *tr) @@ -605,6 +607,9 @@ Act::Act (const char *s) num_inst_levels[i] = 0; } + /* empty genvars */ + _genVars = NULL; + /* initialize act library */ Act::Init (&argc, &argv); FREE (argv[0]); @@ -1223,6 +1228,27 @@ list_t *Act::getDecomp (Process *p) } } } + + if (_genVars) { + phash_bucket_t *pb; + phash_iter_t pit; + list_t *l = NULL; + phash_iter_init (_genVars, &pit); + while ((pb = phash_iter_next (_genVars, &pit))) { + if (p == (Process *)pb->v) { + if (!l) { + l = list_new (); + list_append (l, (ValueIdx *)(pb->key)); + } + } + } + if (l) { + if (!ret) { + ret = list_new (); + } + list_append (ret, l); + } + } return ret; } @@ -1323,3 +1349,56 @@ bool Act::LocalizeGlobal (const char *s) } return true; } + + + +/*------------------------------------------------------------------------ + * Expanding a process might result in a re-write that includes a + * freshly generated variable. These generated variables are not + * declared in the original ACT; during logic synthesis, these + * variables have to be declared, not overridden. + *------------------------------------------------------------------------ + */ +void Act::addGeneratedVar (Scope *sc, ValueIdx *vx) +{ + Assert (vx->t->isExpanded(), "Must be called only with expanded ValueIdx!"); + + if (!_genVars) { + _genVars = phash_new (4); + } + phash_bucket_t *b; + b = phash_add (_genVars, vx); + + while (sc && sc->getUserDef() == NULL) { + sc = sc->Parent (); + } + if (!sc) { + fatal_error ("Act::addGenerateVar(): Scope doesn't lead to a user-defined type."); + } + b->v = sc->getUserDef (); +} + +void Act::updateType (UserDef *from, UserDef *to) +{ + if (!_genVars) return; + phash_bucket_t *pb; + phash_iter_t pit; + + phash_iter_init (_genVars, &pit); + while ((pb = phash_iter_next (_genVars, &pit))) { + if (pb->v == from) { + pb->v = to; + } + } +} + +bool Act::isGeneratedVar (ValueIdx *vx) +{ + if (!_genVars) { + return false; + } + if (phash_lookup (_genVars, vx)) { + return true; + } + return false; +} diff --git a/act/act.h b/act/act.h index 22c75de5..1948f004 100644 --- a/act/act.h +++ b/act/act.h @@ -702,6 +702,13 @@ class Act { void incRefSteps(int nsteps = 1) { refine_steps += nsteps; } ///< increment the number of ///remaining refinement steps + + + void addGeneratedVar (Scope *sc, ValueIdx *vx); ///< add generated variable + void updateType (UserDef *from, UserDef *to); ///< update generated + ///type + bool isGeneratedVar (ValueIdx *vx); ///< check if variable was generated + private: TypeFactory *tf; ///< type factory for the Act instance ActNamespace *gns; ///< the global namespace pointer @@ -749,6 +756,12 @@ class Act { bool _finished_init; ///< set to true after the first file ///has been read + struct pHashtable *_genVars; ///< table that includes ValueIdx + ///pointers that were generated. Since + ///these pointers are unique per + ///process, we don't need to save the + ///process info. + static char *_getopt_string; ///< the string used for getopt /** diff --git a/act/act_array.h b/act/act_array.h index a85914a2..31483317 100644 --- a/act/act_array.h +++ b/act/act_array.h @@ -334,6 +334,16 @@ class Array { */ int Validate (Array *a); + /** + * Validate that the array indices specified in the argument are + * valid indicies for the array. This must be called on an expanded + * array. Skip any dynamic references. + * + * @param a is the Array that contains the indices of interest + * @return 1 if the de-reference is valid, 0 otherwise + */ + int weakValidate (Array *a); + /** * Checks to see if this array includes a dynamic de-reference * @@ -350,6 +360,14 @@ class Array { */ Expr *getDeref (int idx); + /** + * Must be called on an expanded array that is in fact an array + * dereference, and where the de-reference is non-const + * @param idx is the dimension of the array of interest + * @param e is the updated expression for the de-reference + */ + void setDeref (int idx, Expr *e); + /** * Given an array deference or subrange, returns the offset for the * first element of the sub-range/dereference in the standard linear diff --git a/act/array.cc b/act/array.cc index bfa8e25d..fb0579ef 100644 --- a/act/array.cc +++ b/act/array.cc @@ -636,6 +636,49 @@ int Array::Validate (Array *a) return 1; } +/*------------------------------------------------------------------------ + * "a" is an ExpandRef'ed array + * Returns 1 if "a" is a valid de-reference or subrange reference for + * the array, 0 otherwise. + *------------------------------------------------------------------------ + */ +int Array::weakValidate (Array *a) +{ + if (!expanded || !a->isExpanded()) { + fatal_error ("Array::weakValidate() should only be called for expanded arrays"); + } + Assert (dims == a->nDims(), "dimensions don't match!"); + + int i, d; + + for (i=0; i < dims; i++) { + /* a is going to be from an ID */ + if (a->r[i].u.ex.isrange == 2) continue; + d = a->r[i].u.ex.idx.hi; + if (r[i].u.ex.idx.lo > d || r[i].u.ex.idx.hi < d) { + if (next) { + return next->Validate (a); + } + else { + return 0; + } + } + if (a->r[i].u.ex.idx.lo != a->r[i].u.ex.idx.hi) { + /* subrange, check the extreme ends */ + d = a->r[i].u.ex.idx.lo; + if (r[i].u.ex.idx.lo > d || r[i].u.ex.idx.hi < d) { + if (next) { + return next->Validate (a); + } + else { + return 0; + } + } + } + } + return 1; +} + /*------------------------------------------------------------------------ * "a" is an ExpandRef'ed array @@ -1036,6 +1079,13 @@ Expr *Array::getDeref (int idx) } } +void Array::setDeref (int idx, Expr *e) +{ + Assert (0 <= idx && idx < dims, "Invalid dimension"); + Assert (r[idx].u.ex.isrange == 2, "Updating only for non-const derefs"); + r[idx].u.ex.deref = e; +} + /*------------------------------------------------------------------------ * * Array::stepper -- diff --git a/act/body.cc b/act/body.cc index 5f7640b8..88ef9eda 100644 --- a/act/body.cc +++ b/act/body.cc @@ -143,6 +143,10 @@ void ActBody_Inst::Expand (ActNamespace *ns, Scope *s) it = t->Expand (ns, s); act_error_setline (getLine()); + if (it->arrayInfo() && it->arrayInfo()->size() == 0) { + return; + } + if (it->arrayInfo() && it->arrayInfo()->size() == 0) { act_error_ctxt (stderr); fatal_error ("Instance `%s': zero-length array creation not permitted", id); @@ -405,6 +409,7 @@ void ActBody_Inst::Expand (ActNamespace *ns, Scope *s) } InstType *x = new InstType (s->getPType (vx->u.idx)); + x->MkCached (); x->setIfaceType (it); if (it->arrayInfo()) { x->MkArray (it->arrayInfo()); @@ -1241,10 +1246,15 @@ void ActBody_Lang::Expand (ActNamespace *ns, Scope *s) all_lang = ux->getlang(); } - if (ux && (ux->getRefineList() != NULL) && - ActNamespace::Act()->getRefSteps() >= - list_ivalue (list_first (ux->getRefineList()))) { - in_refinement = 1; + if (ux) { + /* check if there are nested refines that will override language + bodies, OR if there are pending refines that do the same */ + if ((ux->getRefineList() != NULL && + ActNamespace::Act()->getRefSteps() >= + list_ivalue (list_first (ux->getRefineList()))) || + ux->moreRefinesExist (ActNamespace::Act()->getRefSteps())) { + in_refinement = 1; + } } #if 0 @@ -1359,6 +1369,7 @@ void ActBody_Lang::Expand (ActNamespace *ns, Scope *s) if (ux->acceptRefine (ActNamespace::Act()->getRefSteps(), r->nsteps)) { list_t *old = ux->getRefineList (); + ux->pushRefine (r->nsteps, old); ux->setRefineList (r->refsublist); ActNamespace::Act()->decRefSteps(r->nsteps); @@ -1366,6 +1377,7 @@ void ActBody_Lang::Expand (ActNamespace *ns, Scope *s) r->b->Expandlist (ns, s); } ux->setRefineList (old); + ux->popRefine (); ActNamespace::Act()->incRefSteps(r->nsteps); } } @@ -1869,7 +1881,7 @@ ActBody *ActBody_Print::Clone(ActNamespace *replace, ActNamespace *newns) } -void ActBody::updateInstType (list_t *namelist, InstType *it) +void ActBody::updateInstType (list_t *namelist, InstType *it, bool handle_subref) { ActBody *b = this; listitem_t *li; @@ -1896,7 +1908,7 @@ void ActBody::updateInstType (list_t *namelist, InstType *it) else if (dynamic_cast (b)) { ActBody_Loop *bl = dynamic_cast (b); if (bl->getBody()) { - bl->getBody()->updateInstType (namelist, it); + bl->getBody()->updateInstType (namelist, it, handle_subref); } } else { @@ -1907,12 +1919,24 @@ void ActBody::updateInstType (list_t *namelist, InstType *it) else if (dynamic_cast (b)) { sel = dynamic_cast (b)->getGC(); } + else if (dynamic_cast (b) && handle_subref) { + ActBody_Lang *l = dynamic_cast (b); + if (l->gettype() == ActBody_Lang::LANG_REFINE) { + act_refine *r = (act_refine *) l->getlang(); + if (r->b && r->nsteps <= ActNamespace::Act()->getRefSteps ()) { + ActNamespace::Act()->decRefSteps (r->nsteps); + r->b->updateInstType (namelist, it, true); + ActNamespace::Act()->incRefSteps (r->nsteps); + } + } + sel = NULL; + } else { sel = NULL; } while (sel) { if (sel->getBody()) { - sel->getBody()->updateInstType (namelist, it); + sel->getBody()->updateInstType (namelist, it, handle_subref); } sel = sel->getNext(); } diff --git a/act/body.h b/act/body.h index 165a85e9..aecd9ee0 100644 --- a/act/body.h +++ b/act/body.h @@ -80,6 +80,10 @@ class ActBody { */ ActBody *Next () { return next; } + /** clear next pointer */ + void clrNext() { next = NULL; } + void setNext(ActBody *b) { next = b; } + /** * In cases when we are cloning a * body into a new namespace hierarchy, the "replace" pointer is @@ -115,9 +119,13 @@ class ActBody { * instance type to the new one specified. This is used to support * overrides. * @param namelist is a list of names (char * list) - * @param it is the updated instance type for the specified identifiers + * @param it is the updated instance type for the specified + * identifiers + * @param handle_subref is a flag. If it is true, then the update + * method also handles a nested refine within the body; otherwise + * those are ignored. */ - void updateInstType (list_t *namelist, InstType *it); + void updateInstType (list_t *namelist, InstType *it, bool handle_subref); /** * @return the saved away line number associated with a body diff --git a/act/check.cc b/act/check.cc index b9f533cf..e9268912 100644 --- a/act/check.cc +++ b/act/check.cc @@ -97,7 +97,7 @@ static void dumpflags(int f) #endif static InstType *_act_get_var_type (Scope *s, ActId *id, ActId **retid, - int *strict) + int *strict, bool subchan) { InstType *it; UserDef *u; @@ -124,16 +124,31 @@ static InstType *_act_get_var_type (Scope *s, ActId *id, ActId **retid, Assert (it, "This should have been caught during parsing!"); /* pstruct can be strict even if there is an id de-reference */ - if (TypeFactory::isPStructType (it) && id->Rest()) { + if (id->Rest() && TypeFactory::isPStructType (it)) { u = s->getUserDef (); if (u && u->isStrictPort (id->getName())) { is_strict = 1; } } + bool subchan_conv = false; + ActId *orig_id = id; + if (id->Rest ()) { while (id->Rest()) { + if (subchan && TypeFactory::isChanType (it->BaseType())) { + it = TypeFactory::getChanDataType (it); + subchan_conv = true; + } u = dynamic_cast(it->BaseType ()); + if (!u && !subchan) { + char *tmpbuf; + MALLOC (tmpbuf, char, 10240); + orig_id->sPrint (tmpbuf, 10240); + typecheck_err ("Identifier `%s' has an illegal use of `.' in this context.", tmpbuf); + FREE (tmpbuf); + return NULL; + } Assert (u, "This should have been caught during parsing!"); id = id->Rest(); it = u->Lookup (id); @@ -154,6 +169,10 @@ static InstType *_act_get_var_type (Scope *s, ActId *id, ActId **retid, *strict = is_strict; } *retid = id; + + if (subchan_conv) { + it = new InstType (s, TypeFactory::Factory()->NewChan (it, NULL)); + } return it; } @@ -205,6 +224,8 @@ static int _act_type_id_to_flags (InstType *it, ActId *id, int is_strict) return T_PROC|arr; } if (TypeFactory::isInterfaceType (t)) { + return T_IFACE|arr; + char *tmpbuf; MALLOC (tmpbuf, char, 10240); id->sPrint (tmpbuf, 10240); @@ -239,12 +260,15 @@ static int _act_type_id_to_flags (InstType *it, ActId *id, int is_strict) } } -int act_type_var (Scope *s, ActId *id, InstType **xit) +int act_type_var_gen (Scope *s, ActId *id, InstType **xit, bool subchan) { InstType *it; int is_strict; - it = _act_get_var_type (s, id, &id, &is_strict); + it = _act_get_var_type (s, id, &id, &is_strict, subchan); + if (!it) { + return T_ERR; + } if (!it->arrayInfo() && id->arrayInfo()) { char *tmpbuf; @@ -287,7 +311,8 @@ static InstType *_act_special_expr_insttype (Scope *s, Expr *e, int *islocal, if (e->type == E_VAR) { /* special case #1 */ - it = act_actual_insttype (s, (ActId *)e->u.e.l, islocal); + it = act_actual_insttype (s, (ActId *)e->u.e.l, islocal, + only_chan == 0 ? false : true); return it; } else if (e->type == E_FUNCTION) { @@ -337,7 +362,8 @@ static InstType *_act_special_expr_insttype (Scope *s, Expr *e, int *islocal, Assert (e->u.e.r->type == E_VAR, "What?"); it = act_actual_insttype (u->CurScope(), (ActId *) e->u.e.r->u.e.l, - islocal); + islocal, + only_chan == 0 ? false : true); return it; } else if (e->type == E_PSTRUCT) { @@ -396,7 +422,7 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) WIDTH_UPDATE(mode); \ return (((f) != (g) ? (g) : T_BOOL) & ~(T_PARAM|T_STRICT))|flgs; \ } \ - if ((f & T_REAL) && T_BASETYPE_ISNUM(lt) && T_BASETYPE_ISNUM(rt)) { \ + if ((T_BASETYPE (f) == T_REAL) && T_BASETYPE_ISNUM(lt) && T_BASETYPE_ISNUM(rt)) { \ if (T_BASETYPE(lt) == T_REAL || T_BASETYPE(rt) == T_REAL) { \ return (((f) != (g) ? (g) : T_REAL) & ~(T_PARAM|T_STRICT))|flgs; \ } \ @@ -667,7 +693,7 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) InstType *xit; long lo, hi; theid = (ActId *)e->u.e.l; - lt = act_type_var (s, theid, &xit); + lt = act_type_var_gen (s, theid, &xit, (only_chan == 0 ? false : true)); if (lt == T_ERR) return T_ERR; if (only_chan == 1 || (only_chan == 2 && !(T_BASETYPE_INT (lt)))) { if (TypeFactory::isChanType (xit)) { @@ -714,11 +740,13 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) typecheck_err ("Bitfield range is empty {%d..%d}", hi, lo); return T_ERR; } +#if 0 if ((TypeFactory::bitWidth (xit) >= 0 && hi+1 > TypeFactory::bitWidth (xit)) || lo < 0) { typecheck_err ("Bitfield range {%d..%d} is wider than operand (%d)", hi, lo, TypeFactory::bitWidth (xit)); return T_ERR; } +#endif if (width) { *width = hi - lo + 1; } @@ -757,11 +785,13 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) typecheck_err ("Bitfield range is empty {%d..%d}", hi, lo); return T_ERR; } +#if 0 if ((TypeFactory::bitWidth (xit) >= 0 && hi+1 > TypeFactory::bitWidth (xit)) || lo < 0) { typecheck_err ("Bitfield range {%d..%d} is wider than operand (%d)", hi, lo, TypeFactory::bitWidth (xit)); return T_ERR; } +#endif if (width) { *width = hi - lo + 1; } @@ -786,8 +816,8 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) typecheck_err ("bool(.) requires an integer argument"); return T_ERR; } - if (lt & T_INT) { - return (lt & ~T_INT) | T_BOOL; + if (T_FIXBASETYPE(lt) == T_INT) { + return (lt & ~T_MASK) | T_BOOL; } typecheck_err ("Invalid use of bool(.)"); return T_ERR; @@ -812,9 +842,9 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) if (width) { *width = 1; } - return (lt & ~(T_BOOL|T_DATA_BOOL))|T_INT; + return (lt & ~T_MASK)|T_INT; } - if (lt & T_REAL) { + if (T_BASETYPE (lt) == T_REAL) { if (width) { *width = 64; } @@ -843,7 +873,12 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) } return lt; } - typecheck_err ("int(.) takes only an int or bool argument"); + if (e->u.e.r) { + typecheck_err ("int(.,) takes only an int argument"); + } + else { + typecheck_err ("int(.) takes only an int or bool argument"); + } return T_ERR; break; @@ -907,7 +942,7 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) } if (!x->isConnectable (y, 1)) { - if ((TypeFactory::isIntType (x) && + if (((TypeFactory::isIntType (x) || TypeFactory::isEnum (x)) && (TypeFactory::isPIntType (y) || TypeFactory::isIntType (y))) || (TypeFactory::isBoolType (x) && TypeFactory::isPBoolType (y))) { @@ -919,6 +954,22 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) return T_ERR; } } + + if ((x->arrayInfo() && !y->arrayInfo()) || + (y->arrayInfo() && !x->arrayInfo())) { + typecheck_err ("Function `%s': arg #%d has an incompatible type", + fn->getName(), i); + return T_ERR; + } + else if (x->arrayInfo() && + y->arrayInfo() && x->arrayInfo()->isExpanded()) { + if (!x->arrayInfo()->isEqual (y->arrayInfo(), 0)) { + typecheck_err ("Function `%s': arg #%d has an incompatible type", + fn->getName(), i); + return T_ERR; + } + } + tmp = tmp->u.e.r; } @@ -1056,6 +1107,10 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) InstType *x; if (strcmp (um->getName(), "int") == 0) { x = new InstType (s, um->Parent(), 0); + // get struct arguments, if any! + if (y->getNumParams() > 0) { + x->appendParams (y->getNumParams(), y->allParams()); + } } else { x = TypeFactory::Factory()->NewInt (s, Type::direction::NONE, 0, @@ -1210,6 +1265,12 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) *width = TypeFactory::bitWidth (rtype); } } + else if (TypeFactory::isInterfaceType (rtype)) { + ret |= T_IFACE; + if (width) { + *width = -1; + } + } else { Assert (0, "Unknown return type"); } @@ -1222,13 +1283,21 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) case E_VAR: { InstType *xit; - lt = act_type_var (s, (ActId *)e->u.e.l, &xit); + + lt = act_type_var_gen (s, (ActId *)e->u.e.l, &xit, + (only_chan == 0 ? false : true)); + if (lt == T_ERR) return T_ERR; if (only_chan) { if (lt == T_CHAN) { ActId *tmp, *theid; theid = (ActId *) e->u.e.l; - InstType *it = _act_get_var_type (s, theid, &tmp, NULL); + InstType *it = _act_get_var_type (s, theid, &tmp, NULL, true); + Assert (it, "This should not happen"); + + Assert (TypeFactory::isChanType (it), "T_CHAN without channel type?"); + InstType *dit = TypeFactory::getChanDataType (it); + Assert (dit, "Hmm"); if (it->getDir() == Type::OUT) { InstType *it2 = s->FullLookup (theid->getName()); @@ -1248,13 +1317,13 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) return T_ERR; } - if (TypeFactory::boolType (it) == 1) { + if (TypeFactory::boolType (dit) == 1) { if (width) { *width = 1; } return T_BOOL; } - else { + else if (TypeFactory::isDataType (dit)) { if (width) { if (xit->isExpanded()) { *width = TypeFactory::bitWidth (xit); @@ -1265,6 +1334,10 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) } return T_INT; } + else { + Assert (TypeFactory::isStructure (dit), "Hmm"); + return T_DATA; + } } if (!(lt & T_ARRAYOF) && (lt & T_PARAM) && T_BASETYPE_ISINTBOOL (lt)) { if (width) { @@ -1465,7 +1538,7 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan) Returns the insttype for the ID. If islocal != NULL, set to 1 if this is a local id within the scope */ -InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal) +InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal, bool subchan) { InstType *it; @@ -1513,7 +1586,8 @@ InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal) Assert (it->isExpanded(), "What on earth?"); Assert (id->arrayInfo()->isExpanded(), "What on earth2?"); - if (!it->arrayInfo()->Validate (id->arrayInfo())) { + /* weak validate, because this can come from a CHP body */ + if (!it->arrayInfo()->weakValidate (id->arrayInfo())) { typecheck_err ("Array dereference out of range"); return NULL; } @@ -1527,6 +1601,10 @@ InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal) } UserDef *u; u = dynamic_cast(it->BaseType ()); + if (!u && subchan && TypeFactory::isChanType (it)) { + u = dynamic_cast + (TypeFactory::getChanDataType (it)->BaseType()); + } Assert (u, "This should have been caught during parsing!"); /* HERE: APPLY MAP! */ @@ -1534,12 +1612,21 @@ InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal) /* extract the real type */ InstType *itmp = it->getIfaceType(); Assert (itmp, "What?"); - Process *proc = dynamic_cast (it->BaseType()); - Assert (proc, "What?"); - list_t *map = proc->findMap (itmp); + list_t *map = NULL; + if (TypeFactory::isProcessType (it)) { + Process *proc = dynamic_cast (it->BaseType()); + Assert (proc, "What?"); + map = proc->findMap (itmp); + } + else { + Data *idat = dynamic_cast (it->BaseType()); + Assert (idat, "What?"); + map = idat->findMap (itmp); + } if (!map) { - fatal_error ("Missing interface `%s' from process `%s'?", - itmp->BaseType()->getName(), proc->getName()); + act_error_ctxt (stderr); + fatal_error ("Missing interface `%s' from type `%s'?", + itmp->BaseType()->getName(), it->BaseType()->getName()); } listitem_t *li; #if 0 @@ -1563,6 +1650,7 @@ InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal) li = list_next (li); } if (!li) { + act_error_ctxt (stderr); fatal_error ("Map for interface `%s' doesn't contain `%s'", itmp->BaseType()->getName(), id->Rest()->getName()); } @@ -1699,13 +1787,13 @@ InstType *act_expr_insttype (Scope *s, Expr *e, int *islocal, int only_chan) if (ret == (T_INT|T_PARAM)) { return TypeFactory::Factory()->NewPInt(); } - else if (ret == T_INT) { + else if (ret == T_INT || ret == T_DATA_INT) { return TypeFactory::Factory()->NewInt (s, Type::NONE, 0, const_expr (32)); } else if (ret == (T_BOOL|T_PARAM)) { return TypeFactory::Factory()->NewPBool (); } - else if (ret == T_BOOL) { + else if (ret == T_BOOL || ret == T_DATA_BOOL) { return TypeFactory::Factory()->NewBool (Type::NONE); } else if (ret == (T_REAL|T_PARAM)) { @@ -1737,7 +1825,7 @@ InstType *act_expr_insttype (Scope *s, Expr *e, int *islocal, int only_chan) } } else { - fatal_error ("Not sure what to do now"); + fatal_error ("Unexpected return code in typechecking: %x", ret); } return NULL; } @@ -2121,7 +2209,7 @@ int act_type_conn (Scope *s, ActId *id, AExpr *rae) */ int lhslocal; - InstType *lhs = act_actual_insttype (s, id, &lhslocal); + InstType *lhs = act_actual_insttype (s, id, &lhslocal, false); if (!lhs) return T_ERR; @@ -2180,8 +2268,15 @@ int type_chp_check_assignable (InstType *lhs, InstType *rhs) if (!TypeFactory::isDataType (lhs) && !TypeFactory::isPureStruct (lhs) && !TypeFactory::isPBoolType (lhs) && !TypeFactory::isPIntType (lhs)) { - typecheck_err ("Assignable variable requires data types!"); - return 0; + if (TypeFactory::isInterfaceType (lhs) && + TypeFactory::isInterfaceType (rhs) && + lhs->BaseType()->isEqual (rhs->BaseType())) { + return 1; + } + else { + typecheck_err ("Assignable variable requires data types!"); + return 0; + } } if (TypeFactory::isPBoolType (lhs)) { if (TypeFactory::isPBoolType (rhs)) { @@ -2304,6 +2399,7 @@ int act_type_chan (Scope *sc, Chan *ch, int is_send, Expr *e, ActId *id, } ret = 0; if (!TypeFactory::isDataType (it1) && !TypeFactory::isStructure (it1) && + !TypeFactory::isEnum (it1) && !TypeFactory::isPIntType (it1) && !TypeFactory::isPBoolType (it1)) { typecheck_err ("Channels require data types!"); } @@ -2330,11 +2426,27 @@ int act_type_chan (Scope *sc, Chan *ch, int is_send, Expr *e, ActId *id, if (type_connectivity_check (it1, ch->datatype(), 0)) { ret = 1; } + else { + typecheck_err ("Incompatible structures"); + } } else { typecheck_err ("Structure/non-structure types are incompatible."); } } + else if (TypeFactory::isEnum (ch->datatype())) { + if (TypeFactory::isEnum (it1)) { + if (type_connectivity_check (it1, ch->datatype(), 0)) { + ret = 1; + } + else { + typecheck_err ("Incompatible enumerations"); + } + } + else { + typecheck_err ("Enum/non-enum types are incompatible."); + } + } } } if (!ret) { @@ -2354,7 +2466,7 @@ int act_type_chan (Scope *sc, Chan *ch, int is_send, Expr *e, ActId *id, } ret = 0; if (!TypeFactory::isDataType (it2) && !TypeFactory::isStructure (it2) && - !TypeFactory::isPIntType (it2) && + !TypeFactory::isPIntType (it2) && !TypeFactory::isEnum (it2) && !TypeFactory::isPBoolType (it2)) { typecheck_err ("Channels require data types!"); } @@ -2382,11 +2494,27 @@ int act_type_chan (Scope *sc, Chan *ch, int is_send, Expr *e, ActId *id, if (type_connectivity_check (it2, ch->acktype(), 0)) { ret = 1; } + else { + typecheck_err ("Incompatible structures"); + } } else { typecheck_err ("Structure/non-structure types are incompatible."); } } + else if (TypeFactory::isEnum (ch->acktype())) { + if (TypeFactory::isEnum (it2)) { + if (type_connectivity_check (it2, ch->acktype(), 0)) { + ret = 1; + } + else { + typecheck_err ("Incompatible enumerations"); + } + } + else { + typecheck_err ("Enumeration/non-enumeration types are incompatible."); + } + } } } if (it1) { delete it1; } diff --git a/act/connect.cc b/act/connect.cc index 8f62ece2..9ee6bc76 100644 --- a/act/connect.cc +++ b/act/connect.cc @@ -543,12 +543,17 @@ static void mk_raw_skip_connection (UserDef *ux, { act_connection *c2p; act_connection *tmp = c2; + bool skip_delete = false; /* c1 is the root, not c2 */ if (c1 == c2) return; c2p = c2->primary (); + if (c2p == c1->primary()) { + skip_delete = true; + } + #ifdef DEBUG_SKIP_CONN printf ("\n[raw-skip] entry *****\n"); dump_conn_rec (c1); @@ -658,7 +663,9 @@ static void mk_raw_skip_connection (UserDef *ux, if (!c2->a) { /* no subconnections. done. */ - delete c2; + if (!skip_delete) { + delete c2; + } #ifdef DEBUG_SKIP_CONN printf ("[raw-skip/3b] return value...\n"); @@ -794,6 +801,7 @@ static void _merge_subtrees (UserDef *ux, #endif mk_raw_skip_connection (ux, c1->a[i], c2->a[i]); _verify_subconn_canonical (ux, c1->a[i]); + c2->a[i] = NULL; #ifdef DEBUG_MERGE_SUBTREE printf (" %d: end-skip\n", i); #endif diff --git a/act/defs.m4 b/act/defs.m4 index efe07176..d4c8d0d3 100644 --- a/act/defs.m4 +++ b/act/defs.m4 @@ -389,6 +389,12 @@ proc_body: } } } + + const char *r = $0->u_p->validateInterfaces (); + if (r) { + $E("%s: inconsistent/missing method", r); + } + return NULL; }} ; @@ -401,26 +407,37 @@ interface_spec: { interface_one_spec "," }* ; interface_one_spec: iface_inst_type -"{" { idmap "," }* "}" +"{" opt_idmap "}" {{X: listitem_t *li; list_t *ret; Interface *iface = dynamic_cast ($1->BaseType()); - ret = NULL; - for (li = list_first ($3); li; li = list_next (li)) { - list_t *tlist = (list_t *) list_value (li); - if (!ret) { - ret = tlist; - } - else { - list_concat (ret, tlist); - list_free (tlist); + if ($3 == NULL) { + ret = list_new (); + } + else { + ret = NULL; + for (li = list_first ($3); li; li = list_next (li)) { + list_t *tlist = (list_t *) list_value (li); + if (!ret) { + ret = tlist; + } + else { + list_concat (ret, tlist); + list_free (tlist); + } } } $A(iface); - $A($0->u_p); + if (!$0->u_p && !$0->u_d) { + $E("Interfaces can only be exported by processes and data types"); + } + if ($0->u_d && !TypeFactory::isStructure ($0->u_d)) { + $E("Interfaces can only be exported by structures"); + } + $A($0->u_p || $0->u_d); for (li = list_first (ret); li; li = list_next (li)) { if (!iface->isPort ((char *)list_value (li))) { $E("``%s'' is not a port in interface ``%s''", @@ -428,12 +445,25 @@ interface_one_spec: iface_inst_type } li = list_next (li); $A(li); - if (!$0->u_p->isPort ((char *)list_value (li))) { - $E("``%s'' is not a port in process ``%s''", - (char *)list_value (li), $0->u_p->getName()); + if ($0->u_p) { + if (!$0->u_p->isPort ((char *)list_value (li))) { + $E("``%s'' is not a port in process ``%s''", + (char *)list_value (li), $0->u_p->getName()); + } + } + else { + if (!$0->u_d->isPort ((char *)list_value (li))) { + $E("``%s'' is not a port in data type ``%s''", + (char *)list_value (li), $0->u_d->getName()); + } } } - $0->u_p->addIface ($1, ret); + if ($0->u_p) { + $0->u_p->addIface ($1, ret); + } + else { + $0->u_d->addIface ($1, ret); + } return NULL; }} ; @@ -445,7 +475,14 @@ idmap[list_t *]: ID "->" ID list_append (ret, $3); return ret; }} -; +; + +opt_idmap[list_t *]: { idmap "," }* +{{X: + return $1; +}} +| /* empty */ +; override_spec: override_one_spec override_spec {{X: return NULL; }} @@ -611,7 +648,7 @@ override_one_spec: user_type [ "+" ] bare_id_list ";" } /* walk through the body, editing instances */ if (b) { - b->updateInstType ($3, $1); + b->updateInstType ($3, $1, false); if (port_override_asserts) { b->Tail()->Append (port_override_asserts); } @@ -904,9 +941,12 @@ single_macro_port_item: physical_inst_type id_list UserDef *u; if (!TypeFactory::isDataType ($1) && !TypeFactory::isStructure($1)) { - r = (ActRet *) list_value (list_first ($2)); - $A(r->type == R_STRING); - $E("Parameter ``%s'': port parameter for a macro must be a data type", r->u.str); + if (!TypeFactory::isInterfaceType ($1)) { + /* allow F-bounded polymorphism */ + r = (ActRet *) list_value (list_first ($2)); + $A(r->type == R_STRING); + $E("Parameter ``%s'': port parameter for a macro must be a data type", r->u.str); + } } if ($0->u_p) { @@ -918,6 +958,9 @@ single_macro_port_item: physical_inst_type id_list else if ($0->u_d) { u = $0->u_d; } + else if ($0->u_i) { + u = $0->u_i; + } else { $A(0); } @@ -1150,7 +1193,9 @@ data_chan_body: ";" {{X: return NULL; }} -| [ "+{" override_spec "}" ] +| +[ ":>" interface_spec ] +[ "+{" override_spec "}" ] {{X: if ($0->u_c) { if ($0->u_c->isDefined ()) { @@ -1166,6 +1211,7 @@ data_chan_body: ";" $A(0); } OPT_FREE ($1); + OPT_FREE ($2); }} "{" base_body [ methods_body ] "}" {{X: @@ -1173,18 +1219,18 @@ data_chan_body: ";" UserDef *me; if ($0->u_c) { $0->u_c->MkDefined (); - $0->u_c->AppendBody ($3); + $0->u_c->AppendBody ($4); me = $0->u_c; } else if ($0->u_d) { $0->u_d->MkDefined(); - $0->u_d->AppendBody ($3); + $0->u_d->AppendBody ($4); me = $0->u_d; } else { $A(0); } - OPT_FREE ($4); + OPT_FREE ($5); parent = me->getParent (); if (parent && TypeFactory::isUserType (parent)) { @@ -1198,6 +1244,12 @@ data_chan_body: ";" } } } + if ($0->u_d) { + const char *r = $0->u_d->validateInterfaces (); + if (r) { + $E("%s: inconsistent/missing method", r); + } + } return NULL; }} ; @@ -1823,6 +1875,21 @@ ID else { $A($0->curns->CreateType($3, $0->u_f)); } + if ($0->u_f->getNumPorts() > 0) { + // we have a situation where this could be PURELY pstruct ports! + // In this case, we need to move them over to parameter types + bool convert = true; + for (int i=0; convert && i < $0->u_f->getNumPorts(); i++) { + InstType *it = $0->u_f->getPortType (i); + if (!TypeFactory::isParamType (it)) { + convert = false; + } + } + if (convert) { + $0->u_f->convPortsToParams(); + } + } + if ($0->u_f->getNumPorts() > 0 && TypeFactory::isParamType ($8)) { $E("Function ``%s'': return type incompatible with arguments", $3); } @@ -1878,7 +1945,7 @@ func_body[ActBody *]: ";" }} ; -func_body_items[ActBody *]: alias_or_inst_list lang_chp +func_body_items[ActBody *]: alias_or_inst_list gen_lang_chp {{X: ActBody *b; @@ -1893,6 +1960,55 @@ func_body_items[ActBody *]: alias_or_inst_list lang_chp }} ; + +gen_lang_chp[ActBody *]: lang_chp +{{X: + return $1; +}} +| "*[" +{{X: $0->in_cond++; }} +{ gc_1_v2 "[]" }* "]" [";"] +{{X: + return apply_X_loop_opt1 ($0, $2, $4); +}} +| "[" +{{X: $0->in_cond++; }} + guarded_cmds_v2 "]" [";"] +{{X: + $0->in_cond--; + OPT_FREE ($4); + return $2; +}} +| assertion +{{X: return $1; }} +| debug_output +{{X: return $1; }} +; + +gc_1_v2[ActBody_Select_gc *]: wbool_expr "->" func_body_items +{{X: + return apply_X_gc_1_opt0 ($0, $1, $3); +}} +| "(" "[]" ID +{{X: + lapply_X_gc_1_1_2 ($0, $3); +}} +":" !noreal wpint_expr [ ".." wpint_expr ] ":" wbool_expr "->" func_body_items ")" +{{X: + return apply_X_gc_1_opt1 ($0, $3, $5, $6, $8, $10); +}} +| "else" "->" func_body_items +{{X: + return apply_X_gc_1_opt2 ($0, $3); +}} +; + +guarded_cmds_v2[ActBody *]: { gc_1_v2 "[]" }* +{{X: + return apply_X_guarded_cmds_opt0 ($0, $1); +}} +; + alias_or_inst_list[ActBody *]: al_item alias_or_inst_list {{X: $1->Append ($2); @@ -2873,8 +2989,8 @@ defiface: [ template_spec ] /*printf ("Orig scope: %x\n", $0->scope);*/ $0->scope = $0->u_i->CurScope (); }} - "(" [ port_formal_list ] ")" ";" -{{X: + "(" [ port_formal_list ] ")" + {{X: /* Create type here */ UserDef *u; @@ -2894,12 +3010,108 @@ defiface: [ template_spec ] } OPT_FREE ($5); $0->strict_checking = 0; +}} +interface_methods +{{X: + $0->u_i->MkDefined (); + $0->u_i = NULL; $0->scope =$0->curns->CurScope(); return NULL; }} ; +interface_methods: "{" "methods" "{" method_decl_list "}" "}" +{{X: + return NULL; +}} +| ";" +{{X: + return NULL; +}} +; + +method_decl_list: one_method_decl method_decl_list +| one_method_decl +; + +one_method_decl: "macro" ID +{{X: + $A($0->u_i); + if (strcmp ($2, "int") == 0) { + $E("``int'' cannot be used as a macro name; it is built-in!"); + } + else if (strcmp ($2, $0->u_i->getName()) == 0) { + $E("``%s'' cannot be used as a macro name; it is built-in!", + $0->u_i->getName()); + } + $0->um = $0->u_i->newMacro ($2); + if (!$0->um) { + $E("Duplicate macro name: ``%s''", $2); + } + $0->scope = new Scope ($0->scope, 0); +}} +"(" [ macro_formal_list ] ")" ";" +{{X: + OPT_FREE ($4); + $0->um = NULL; + + Scope *tmp = $0->scope; + $0->scope = tmp->Parent (); + delete tmp; + + return NULL; +}} +| "function" ID +{{X: + $A($0->u_i); + if (strcmp ($2, "int") == 0) { + $E("``int'' cannot be used as a macro name; it is built-in!"); + } + else if (strcmp ($2, $0->u_i->getName()) == 0) { + $E("``%s'' cannot be used as a macro name; it is built-in!", + $0->u_i->getName()); + } + $0->um = $0->u_i->newMacro ($2); + if (!$0->um) { + $E("Duplicate macro name: ``%s''", $2); + } + $0->scope = new Scope ($0->scope, 0); +}} +"(" macro_fn_formal ")" ":" func_ret_type ";" +{{X: + if ($0->um->getNumPorts() > 0) { + if (TypeFactory::isParamType ($0->um->getPortType (0))) { + if (!TypeFactory::isParamType ($7)) { + $E("Macro function with parameter types: return type must be a parameter!"); + } + } + else { + if (TypeFactory::isParamType ($7)) { + $E("Macro function with non-parameter types: return type cannot be a parameter!"); + } + } + } + if (TypeFactory::isParamType ($7)) { + for (int i=0; i < $0->u_i->getNumParams (); i++) { + if ($0->um->addPort ($0->u_i->getPortType (-(i+1)), + $0->u_i->getPortName (-(i+1))) != 1) { + $E("Macro function `%s': duplicate port name for parameter type `%s'.", + $0->um->getName(), $0->u_i->getPortName (-(i+1))); + } + } + } + $0->um->setRetType ($7); + $0->um = NULL; + + Scope *tmp = $0->scope; + $0->scope = tmp->Parent (); + delete tmp; + + return NULL; +}} +; + /*------------------------------------------------------------------------ * * Parameter structure diff --git a/act/expr.m4 b/act/expr.m4 index 0b074ccf..e8340641 100644 --- a/act/expr.m4 +++ b/act/expr.m4 @@ -268,6 +268,11 @@ expr_id[ActId *]: { base_id "." }* } } + if (list_next (li) && $0->allow_chan && TypeFactory::isExactChanType (it)) { + it = TypeFactory::getChanDataType (it); + $A(it); + } + ud = NULL; for (li = list_next (li); li; li = list_next (li)) { /* it = the inst type of where we are so far; li has the next @@ -420,6 +425,11 @@ w_c_expr[Expr *]: expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldval = $0->special_id; + oldsc = $0->special_id_sc; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -437,6 +447,8 @@ w_c_expr[Expr *]: expr if ($0->strict_checking && ((tc & T_STRICT) == 0)) { $E("Expressions in port parameter list can only use strict template parameters"); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -445,6 +457,11 @@ w_expr[Expr *]: expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -460,6 +477,8 @@ w_expr[Expr *]: expr if ($0->strict_checking && ((tc & T_STRICT) == 0)) { $E("Expressions in port parameter list can only use strict template parameters"); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -470,6 +489,11 @@ w_expr_chp[Expr *]: EXTERN[fexpr] {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; e = (Expr *) $1; $A($0->scope); @@ -482,6 +506,8 @@ w_expr_chp[Expr *]: EXTERN[fexpr] if ($0->strict_checking && ((tc & T_STRICT) == 0)) { $E("Expressions in port parameter list can only use strict template parameters"); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -490,6 +516,11 @@ w_exprchp[Expr *]: expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -505,6 +536,8 @@ w_exprchp[Expr *]: expr if ($0->strict_checking && ((tc & T_STRICT) == 0)) { $E("Expressions in port parameter list can only use strict template parameters"); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -515,6 +548,11 @@ w_chan_int_expr[Expr *]: EXTERN[fexpr] {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; e = (Expr *) $1; @@ -528,6 +566,8 @@ w_chan_int_expr[Expr *]: EXTERN[fexpr] if ($0->strict_checking && ((tc & T_STRICT) == 0)) { $E("Expressions in port parameter list can only use strict template parameters"); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -537,6 +577,11 @@ wnumber_expr[Expr *]: expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -558,6 +603,8 @@ wnumber_expr[Expr *]: expr if (!(tc & T_PARAM)) { $E("Expression must be of type pint or preal"); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -566,6 +613,11 @@ wnumber_flav_expr[Expr *]: expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -576,6 +628,8 @@ wnumber_flav_expr[Expr *]: expr e = act_walk_X_expr ($0, $1); if ($0->skip_id_check == 2) { $0->skip_id_check = 0; + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; } $0->skip_id_check = 0; @@ -595,6 +649,8 @@ wnumber_flav_expr[Expr *]: expr if (!(tc & T_PARAM)) { $E("Expression must be of type pint or preal"); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -604,6 +660,11 @@ wint_or_bool_expr[Expr *]: expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -629,18 +690,25 @@ wint_or_bool_expr[Expr *]: expr fprintf ($f, "''\n"); exit (1); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; /* - CONSISTENCY: _wint_expr in prs.c + CONSISTENCY: _wint_expr in prs.cc */ wint_expr[Expr *]: int_expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -668,6 +736,8 @@ wint_expr[Expr *]: int_expr fprintf ($f, "''\n"); exit (1); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -676,6 +746,10 @@ wpint_expr[Expr *]: int_expr {{X: Expr *e; int tc; + int oldval = $0->special_id; + Scope *oldsc; + oldsc = $0->special_id_sc; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -706,6 +780,8 @@ wpint_expr[Expr *]: int_expr fprintf ($f, "''\n"); exit (1); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -715,6 +791,11 @@ wbool_expr[Expr *]: bool_expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -740,6 +821,8 @@ wbool_expr[Expr *]: bool_expr fprintf ($f, "''\n"); exit (1); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; @@ -748,6 +831,11 @@ wbool_allow_chan_expr[Expr *]: bool_expr {{X: Expr *e; int tc; + int oldval; + Scope *oldsc; + oldsc = $0->special_id_sc; + oldval = $0->special_id; + $0->special_id = 0; $0->line = $l; $0->column = $c; @@ -773,6 +861,8 @@ wbool_allow_chan_expr[Expr *]: bool_expr fprintf ($f, "''\n"); exit (1); } + $0->special_id = oldval; + $0->special_id_sc = oldsc; return e; }} ; diff --git a/act/expr2.cc b/act/expr2.cc index aebaacd6..652e0b86 100644 --- a/act/expr2.cc +++ b/act/expr2.cc @@ -502,15 +502,9 @@ static void _eval_function (ActNamespace *ns, Scope *s, Expr *fn, Expr **ret, } } for (int i=0; i < nargs; i++) { - if (!expr_is_a_const (args[i])) { - if (args[i]->type == E_ARRAY) { - act_error_ctxt (stderr); - fatal_error ("Arrays are not supported as function arguments."); - } - else { - act_error_ctxt (stderr); - Assert (expr_is_a_const (args[i]), "Argument is not a constant?"); - } + if (!expr_is_a_const (args[i]) && args[i]->type != E_ARRAY) { + act_error_ctxt (stderr); + Assert (expr_is_a_const (args[i]), "Argument is not a constant?"); } } e = x->eval (ns, nargs, args); @@ -854,6 +848,11 @@ static Expr *_expr_expand (int *width, Expr *e, UserDef *id_ux = NULL; if (id_it) { id_ux = dynamic_cast (id_it->BaseType()); + if (!id_ux && (flags & ACT_EXPR_EXFLAG_CHPEX)) { + Assert (TypeFactory::isChanType (id_it), "Should have been caught earlier"); + id_ux = dynamic_cast + (TypeFactory::getChanDataType (id_it)->BaseType()); + } Assert (id_ux, "What?"); um = id_ux->getMacro (um->getName()); if (!_idstack) { @@ -1003,7 +1002,7 @@ static Expr *_expr_expand (int *width, Expr *e, } act_chp_macro_check (s, (ActId *)te->u.e.l); InstType *it; - act_type_var (s, (ActId *)te->u.e.l, &it); + act_type_var_gen (s, (ActId *)te->u.e.l, &it, true); *width = TypeFactory::bitWidth (it); // now we have the bit-width! // now we convert the rest of the expression!!! @@ -1790,6 +1789,9 @@ static Expr *_expr_expand (int *width, Expr *e, else if (ret->u.e.l->type == E_REAL) { fprintf (stderr, "preal"); } + else if (ret->u.e.l->type == E_TRUE || ret->u.e.l->type == E_FALSE) { + fprintf (stderr, "pbool"); + } else { fprintf (stderr, "other"); } @@ -1800,6 +1802,9 @@ static Expr *_expr_expand (int *width, Expr *e, else if (ret->u.e.r->type == E_REAL) { fprintf (stderr, "preal"); } + else if (ret->u.e.r->type == E_TRUE || ret->u.e.r->type == E_FALSE) { + fprintf (stderr, "pbool"); + } else { fprintf (stderr, "other"); } @@ -2432,19 +2437,29 @@ static Expr *_expr_expand (int *width, Expr *e, else { if (flags & ACT_EXPR_EXFLAG_CHPEX) { /* chp mode expansion */ + int tmpex = Act::double_expand; + Act::double_expand = 0; xid = ((ActId *)e->u.e.l)->ExpandCHP (ns, s); + Act::double_expand = tmpex; te = xid->EvalCHP (ns, s, 0); if (te->type == E_VAR) { act_chp_macro_check (s, (ActId *)te->u.e.l); InstType *it; - act_type_var (s, (ActId *)te->u.e.l, &it); + act_type_var_gen (s, (ActId *)te->u.e.l, &it, true); *width = TypeFactory::bitWidth (it); } else if (te->type == E_INT) { + *width = act_expr_intwidth (te->u.ival.v); if (te->u.ival.v_extra == NULL) { - /* XXX: add stuff here */ + BigInt *btmp; + Expr *nte; + NEW (nte, Expr); + *nte = *te; + btmp = new BigInt(*width, 0, 1); + btmp->setVal (0, nte->u.ival.v); + nte->u.ival.v_extra = btmp; + te = nte; } - *width = act_expr_intwidth (te->u.ival.v); } else { *width = -1; @@ -2814,8 +2829,14 @@ static int _expr_bw_calc(struct pHashtable *H, Expr *e, Scope *s) case E_VAR: { InstType *xit; - lw = act_type_var (s, (ActId *)e->u.e.l, &xit); - width = TypeFactory::bitWidth (xit); + lw = act_type_var_gen (s, (ActId *)e->u.e.l, &xit, true); + if (xit->arrayInfo() && !((ActId *)e->u.e.l)->arrayInfo()) { + // not a de-reference + width = -1; + } + else { + width = TypeFactory::bitWidth (xit); + } } break; diff --git a/act/expr_api.h b/act/expr_api.h index 8ef714a9..14d004b0 100644 --- a/act/expr_api.h +++ b/act/expr_api.h @@ -314,6 +314,11 @@ Expr *expr_dag (Expr *e); */ void expr_dag_free (Expr *); +/** + * Return 1 if the expression is cached, 0 otherwise + */ +int expr_ex_is_cached (Expr *); + class UserMacro; /* diff --git a/act/expr_extra.c b/act/expr_extra.c index a35bfc41..95c6a3e6 100644 --- a/act/expr_extra.c +++ b/act/expr_extra.c @@ -33,7 +33,7 @@ static int tokxor, tokplus, tokmult; static int double_colon, comma; static int inttok, booltok; static int langle, rangle; -static int dot; +static int dot, lbrack; static void do_init (LFILE *l) { @@ -55,6 +55,7 @@ static void do_init (LFILE *l) inttok = file_addtoken (l, "int"); booltok = file_addtoken (l, "bool"); dot = file_addtoken (l, "."); + lbrack = file_addtoken (l, "["); init = 1; } } @@ -203,7 +204,7 @@ static Expr *_parse_expr_func2 (LFILE *l, int first_fn) return e; } } - else if (!found_dcolon && file_have (l, dot)) { + else if (!found_dcolon && (file_have (l, dot) || file_sym(l) == lbrack)) { if (pushed) { file_set_position (l); file_pop_position (l); @@ -1091,6 +1092,7 @@ int act_expr_parse_newtokens (LFILE *l) int act_expr_free_default (Expr *e) { + if (!e) return 0; if (e->type == E_ENUM_CONST) { FREE (e->u.fn.s); return 1; diff --git a/act/expr_print.cc b/act/expr_print.cc index 967b2127..abe77f73 100644 --- a/act/expr_print.cc +++ b/act/expr_print.cc @@ -1132,7 +1132,15 @@ AExprstep *AExpr::stepper() } - +int expr_ex_is_cached (Expr *e) +{ + if (!e) return 1; + if (e->type == E_TRUE || e->type == E_FALSE || + (e->type == E_INT && !e->u.ival.v_extra)) { + return 1; + } + return 0; +} static void efree_ex (Expr *e) @@ -1189,8 +1197,7 @@ static void efree_ex (Expr *e) if (e->u.e.r) efree_ex (e->u.e.r); break; } - if (e->type == E_TRUE || e->type == E_FALSE || - (e->type == E_INT && !e->u.ival.v_extra)) { + if (expr_ex_is_cached (e)) { /* cached */ } else { @@ -1417,10 +1424,26 @@ static void _expr_to_var (char **buf, int *len, int *sz, } static void _expr_to_string (char **buf, int *len, int *sz, + struct pHashtable *H, int *uid, list_t *ids, Expr *e, int *isassoc) { int iszero = 0; int tmp; + phash_bucket_t *b; + + b = phash_lookup (H, e); + if (b) { + _expr_expand_sz (buf, len, sz, 32); + (*buf)[*len] = 'w'; + *len = *len + 1; + snprintf (*buf + *len, *sz - *len, "%lu", (unsigned long)b->i); + *len += strlen (*buf + *len); + return; + } + b = phash_add (H, e); + b->i = *uid; + *uid = *uid + 1; + switch (e->type) { case E_PLUS: case E_MULT: @@ -1430,14 +1453,14 @@ static void _expr_to_string (char **buf, int *len, int *sz, } if (e->u.e.l->type == e->type) { (*isassoc) = (*isassoc) + 1; - _expr_to_string (buf, len, sz, ids, e->u.e.l, isassoc); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.l, isassoc); } else { tmp = 0; - _expr_to_string (buf, len, sz, ids, e->u.e.l, &tmp); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.l, &tmp); } tmp = 0; - _expr_to_string (buf, len, sz, ids, e->u.e.r, &tmp); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.r, &tmp); if (iszero) { _expr_append_char (buf, len, sz, _expr_type_char (e->type)); while (*isassoc) { @@ -1453,22 +1476,22 @@ static void _expr_to_string (char **buf, int *len, int *sz, case E_LT: case E_GT: case E_LE: case E_GE: case E_EQ: case E_NE: - _expr_to_string (buf, len, sz, ids, e->u.e.l, &iszero); - _expr_to_string (buf, len, sz, ids, e->u.e.r, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.r, &iszero); _expr_append_char (buf, len, sz, _expr_type_char (e->type)); break; case E_NOT: case E_UMINUS: case E_COMPLEMENT: - _expr_to_string (buf, len, sz, ids, e->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.l, &iszero); _expr_append_char (buf, len, sz, _expr_type_char (e->type)); break; case E_QUERY: - _expr_to_string (buf, len, sz, ids, e->u.e.l, &iszero); - _expr_to_string (buf, len, sz, ids, e->u.e.r->u.e.l, &iszero); - _expr_to_string (buf, len, sz, ids, e->u.e.r->u.e.r, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.r->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.r->u.e.r, &iszero); _expr_append_char (buf, len, sz, _expr_type_char (e->type)); break; @@ -1501,7 +1524,7 @@ static void _expr_to_string (char **buf, int *len, int *sz, { Expr *f = e; while (f) { - _expr_to_string (buf, len, sz, ids, f->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, f->u.e.l, &iszero); f = f->u.e.r; } _expr_append_char (buf, len, sz, _expr_type_char (e->type)); @@ -1513,21 +1536,21 @@ static void _expr_to_string (char **buf, int *len, int *sz, _expr_to_var (buf, len, sz, ids, (ActId *)e->u.e.l); _expr_append_char (buf, len, sz, _expr_type_char (e->type)); if (e->u.e.r->u.e.l) { - _expr_to_string (buf, len, sz, ids, e->u.e.r->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.r->u.e.l, &iszero); } - _expr_to_string (buf, len, sz, ids, e->u.e.r->u.e.r, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.r->u.e.r, &iszero); _expr_append_char (buf, len, sz, _expr_type_char (e->type)); break; case E_BUILTIN_BOOL: - _expr_to_string (buf, len, sz, ids, e->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.l, &iszero); _expr_append_char (buf, len, sz, _expr_type_char (e->type)); break; case E_BUILTIN_INT: - _expr_to_string (buf, len, sz, ids, e->u.e.l, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.l, &iszero); if (e->u.e.r) { - _expr_to_string (buf, len, sz, ids, e->u.e.r, &iszero); + _expr_to_string (buf, len, sz, H, uid, ids, e->u.e.r, &iszero); } _expr_append_char (buf, len, sz, _expr_type_char (e->type)); if (e->u.e.r) { @@ -1562,7 +1585,13 @@ char *act_expr_to_string (list_t *id_list, Expr *e) buf[0] = '\0'; len = 0; - _expr_to_string (&buf, &len, &sz, id_list, e, &iszero); + struct pHashtable *H = phash_new (8); + + int unique_id = 0; + + _expr_to_string (&buf, &len, &sz, H, &unique_id, id_list, e, &iszero); + + phash_free (H); char *ret = Strdup (buf); FREE (buf); diff --git a/act/fexpr.cc b/act/fexpr.cc index 3e49e23c..5efceda0 100644 --- a/act/fexpr.cc +++ b/act/fexpr.cc @@ -331,58 +331,66 @@ static Expr *expr_basecase (void) } } else { - if (v && expr_free_id) { - (*expr_free_id) (v); +#if 0 + printf (" -- got here, looking-at %s!\n", file_tokenstring (Tl)); +#endif + if (!file_have (Tl, T[E_LPAR])) { + if (v && expr_free_id) { + (*expr_free_id) (v); + } + SET (Tl); + POP (Tl); + return NULL; } - SET (Tl); -#if 1 - POP (Tl); - return NULL; -#else - /* - XXX: This is duplicate parsing code that is replicated in - expr_extra.c; so leave it in one place rather than having - multiple function call parsers. - */ - if (file_have (Tl, f_id) && file_sym (Tl) == T[E_LPAR]) { - e = newexpr (); - e->type = E_FUNCTION; - e->u.fn.s = Strdup (file_prev (Tl)); - e->u.fn.r = NULL; - f = e; - file_mustbe (Tl, T[E_LPAR]); - if (file_sym (Tl) != T[E_RPAR]) { - do { - f->u.e.r = newexpr (); /* wow! rely that this is the same - space as u.fn.r */ + expr_inc_parens (); + e = newexpr (); + e->type = E_USERMACRO; + NEW (e->u.e.l, Expr); + e->u.e.l->type = E_VAR; + e->u.e.l->u.e.l = (Expr *)v; + e->u.e.l->u.e.r = NULL; + e->u.e.r = NULL; + f = e; + if (file_sym (Tl) != T[E_RPAR]) { + do { + if (f == e) { + NEW (e->u.e.r, Expr); + f = e->u.e.r; + } + else { + NEW (f->u.e.r, Expr); f = f->u.e.r; - f->type = E_LT; - f->u.e.r = NULL; - f->u.e.l = expr_parse (); - if (!f->u.e.l) { - expr_free (e); - SET (Tl); - POP (Tl); - return NULL; - } - } while (file_have (Tl, T[E_COMMA])); - if (file_sym (Tl) != T[E_RPAR]) { + } + f->type = E_LT; + f->u.e.r = NULL; + f->u.e.l = expr_parse_any (Tl); + if (!f->u.e.l) { expr_free (e); + expr_dec_parens (); SET (Tl); POP (Tl); return NULL; } + } while (file_have (Tl, T[E_COMMA])); + if (file_sym (Tl) != T[E_RPAR]) { + expr_free (e); + expr_dec_parens (); + SET (Tl); + POP (Tl); + return NULL; } /* success! */ - POP (Tl); file_getsym (Tl); + expr_dec_parens (); + POP (Tl); + return e; } else { - SET (Tl); - POP (Tl); - return NULL; + /* eat the token */ + file_getsym (Tl); } -#endif + POP (Tl); + return e; } } } diff --git a/act/func.cc b/act/func.cc index aac7482e..610c98f0 100644 --- a/act/func.cc +++ b/act/func.cc @@ -129,12 +129,14 @@ act_inline_value Function::toInline (int nargs, act_inline_value *args) for (it = it.begin(); it != it.end(); it++) { ValueIdx *vx = (*it); if (TypeFactory::isParamType (vx->t)) continue; +#if 0 if (vx->t->arrayInfo()) { act_error_ctxt (stderr); warning ("Inlining failed; array declarations!"); act_error_pop (); return ret; } +#endif } /* @@ -169,9 +171,9 @@ act_inline_value Function::toInline (int nargs, act_inline_value *args) act_error_ctxt (stderr); fatal_error ("toInline(): arg #%d is a non-structure argument to structure field?", i); } - if (!args[i].is_struct_id && (nb + ni != args[i].numElems())) { + if (!args[i].is_just_id && (nb + ni != args[i].numStructElems())) { act_error_ctxt (stderr); - fatal_error ("toInline(): arg #%d structure count mismatch (%d vs %d)", i, nb + ni, args[i].numElems()); + fatal_error ("toInline(): arg #%d structure count mismatch (%d vs %d)", i, nb + ni, args[i].numStructElems()); } } else { @@ -180,6 +182,17 @@ act_inline_value Function::toInline (int nargs, act_inline_value *args) fatal_error ("toInline(): arg #%d is a structure argument to a non-struct field?", i); } } + if (getPortType (i)->arrayInfo()) { + if (!args[i].is_array) { + act_error_ctxt (stderr); + fatal_error ("toInline(): arg #%d is a non-array argument to array field?", i); + } + if (!args[i].is_just_id && getPortType(i)->arrayInfo()->size () != + args[i].numArrayElems()) { + act_error_ctxt (stderr); + fatal_error ("toInline(): arg #%d array count mismatch (%d vs %d)", i, getPortType (i)->arrayInfo()->size(), args[i].numArrayElems()); + } + } Assert (i < getNumPorts(), "Hmm..."); @@ -194,7 +207,7 @@ act_inline_value Function::toInline (int nargs, act_inline_value *args) printf (" > %p", args[i].u.val); } printf ("\n"); -#endif +#endif delete tmp; } @@ -312,9 +325,18 @@ void Function::_chk_inline (Expr *e) case E_TRUE: case E_FALSE: case E_REAL: + break; + case E_VAR: case E_PROBE: case E_BITFIELD: + { + ActId *id = (ActId *)e->u.e.l; + if (id->isDynamicDeref ()) { + is_simple_inline = 0; + return; + } + } break; case E_FUNCTION: @@ -552,7 +574,8 @@ Expr *Function::eval (ActNamespace *ns, int nargs, Expr **args) Assert (nargs == getNumParams(), "What?"); for (int i=0; i < nargs; i++) { - Assert (expr_is_a_const (args[i]), "Argument is not a constant?"); + Assert (args[i]->type == E_ARRAY || + expr_is_a_const (args[i]), "Argument is not a constant?"); } /* @@ -576,25 +599,48 @@ Expr *Function::eval (ActNamespace *ns, int nargs, Expr **args) expanded = 1; ValueIdx *vx; - + bool ext_err = false; + for (int i=0; i < getNumParams(); i++) { InstType *it; const char *name; + int count; it = getPortType (-(i+1)); name = getPortName (-(i+1)); - - I->Add (name, it); + + if (it->arrayInfo()) { + if (!it->arrayInfo()->isExpanded()) { + Array *xa = it->arrayInfo()->Expand (ns, ns->CurScope()); + count = xa->size(); + delete xa; + } + else { + count = it->arrayInfo()->size(); + } + ext_err = true; + } + else { + count = 1; + } + + if (it->isExpanded()) { + I->Add (name, it); + } + else { + InstType *xit = it->Expand (ns, ns->CurScope()); + xit->MkCached (); + I->Add (name, xit); + } vx = I->LookupVal (name); + Assert (vx, "Hmm"); - vx->init = 1; - if (TypeFactory::isPIntType (it)) { - vx->u.idx = I->AllocPInt(); - } - else if (TypeFactory::isPBoolType (it)) { - vx->u.idx = I->AllocPBool(); + if (TypeFactory::isPIntType (it) || + TypeFactory::isPBoolType (it) || + TypeFactory::isPRealType (it)) { + // okay } - else if (TypeFactory::isPRealType (it)) { - vx->u.idx = I->AllocPReal(); + else if (TypeFactory::isPStructType (it)) { + ext_err = true; } else { fatal_error ("Invalid type in function signature"); @@ -607,21 +653,26 @@ Expr *Function::eval (ActNamespace *ns, int nargs, Expr **args) I->Add ("self", getRetType ()->Expand (ns, I)); vx = I->LookupVal ("self"); Assert (vx, "Hmm"); - vx->init = 1; - if (TypeFactory::isPIntType (getRetType())) { - vx->u.idx = I->AllocPInt(); + int count; + if (vx->t->arrayInfo()) { + count = vx->t->arrayInfo()->size(); + ext_err = true; } - else if (TypeFactory::isPBoolType (getRetType())) { - vx->u.idx = I->AllocPBool(); + else { + count = 1; + } + if (TypeFactory::isPIntType (getRetType()) || + TypeFactory::isPBoolType (getRetType()) || + TypeFactory::isPRealType (getRetType())) { + // okay } - else if (TypeFactory::isPRealType (getRetType())) { - vx->u.idx = I->AllocPReal(); + else if (TypeFactory::isPStructType (getRetType())) { + ext_err = true; } else { fatal_error ("Invalid return type in function signature"); } - /* now run the chp body */ act_chp *c = NULL; @@ -655,6 +706,10 @@ Expr *Function::eval (ActNamespace *ns, int nargs, Expr **args) fatal_error ("Function `%s': no chp body, and no external definition", getName()); } + if (ext_err) { + act_error_ctxt (stderr); + fatal_error ("Function `%s': external functions can only have simple arguments and return types", getName()); + } long *eargs = NULL; if (nargs != 0) { MALLOC (eargs, long, nargs); @@ -693,51 +748,41 @@ Expr *Function::eval (ActNamespace *ns, int nargs, Expr **args) Expr *ret = NULL; - if (TypeFactory::isPIntType (getRetType())) { - if (ext_found) { + if (ext_found) { + if (TypeFactory::isPIntType (getRetType())) { ret = const_expr (nargs); } - else { - if (I->issetPInt (vx->u.idx)) { - ret = const_expr (I->getPInt (vx->u.idx)); - } - else { - act_error_ctxt (stderr); - fatal_error ("self is not assigned!"); - } - } - } - else if (TypeFactory::isPBoolType (getRetType())) { - if (ext_found) { + else if (TypeFactory::isPBoolType (getRetType())) { ret = const_expr_bool (nargs == 0 ? 0 : 1); } - else { - if (I->issetPBool (vx->u.idx)) { - ret = const_expr_bool (I->getPBool (vx->u.idx)); - } - else { - act_error_ctxt (stderr); - fatal_error ("self is not assigned!"); - } - } - } - else if (TypeFactory::isPRealType (getRetType())) { - if (ext_found) { + else if (TypeFactory::isPRealType (getRetType())) { ret = const_expr_real (nargs); } else { - if (I->issetPReal (vx->u.idx)) { - ret = const_expr_real (I->getPReal (vx->u.idx)); - } - else { - act_error_ctxt (stderr); - fatal_error ("self is not assigned!"); - } + fatal_error ("Invalid return type in function signature"); } } else { - fatal_error ("Invalid return type in function signature"); + ActId *res = new ActId (string_cache ("self")); + ret = res->Eval (ns, I); } return ret; } + +void Function::convPortsToParams () +{ + Assert (!isExpanded(), "Must be only called on unexpanded functions!"); + + Assert (nt == 0 && nports > 0, "What?"); + Assert (pt == NULL && port_t != NULL, "What?"); + Assert (pn == NULL && port_n != NULL, "What?"); + + pt = port_t; + port_t = NULL; + pn = port_n; + port_n = NULL; + nt = nports; + nports = 0; +} + diff --git a/act/global_generic.conf b/act/global_generic.conf index d6fe6448..462f713d 100644 --- a/act/global_generic.conf +++ b/act/global_generic.conf @@ -47,7 +47,7 @@ string_table instance_attr "i:s:pos_x" "i:s:pos_y" "i:s:size_x" "i:s:size_y" "i: # # Special characters that should be mangled during printing # -string mangle_chars ":()<>[],{}."$\" +string mangle_chars ":()<>[],{}."$\@" string mangle_letter "_" end diff --git a/act/id.cc b/act/id.cc index 3a02337b..1279dfe7 100644 --- a/act/id.cc +++ b/act/id.cc @@ -27,6 +27,7 @@ #include #include #include +#include //#define DEBUG_CONNECTIONS @@ -350,6 +351,11 @@ Expr *ActId::Eval (ActNamespace *ns, Scope *s, int is_lval, int is_chp) Assert (it->isExpanded(), "This should be expanded"); u = dynamic_cast(it->BaseType ()); + if (!u && is_chp) { + if (TypeFactory::isChanType (it)) { + u = dynamic_cast (TypeFactory::getChanDataType (it)->BaseType()); + } + } Assert (u, "This should have been caught earlier!"); if (TypeFactory::isPStructType (u)) { @@ -367,12 +373,25 @@ Expr *ActId::Eval (ActNamespace *ns, Scope *s, int is_lval, int is_chp) /* extract the real type */ InstType *itmp = it->getIfaceType(); Assert (itmp, "What?"); - Process *proc = dynamic_cast (it->BaseType()); - Assert (proc, "What?"); - list_t *map = proc->findMap (itmp); + list_t *map = NULL; + if (TypeFactory::isProcessType (it)) { + Process *proc = dynamic_cast (it->BaseType()); + Assert (proc, "What?"); + map = proc->findMap (itmp); + } + else if (TypeFactory::isDataType (it) || TypeFactory::isStructure (it)) { + Data *dat = dynamic_cast (it->BaseType()); + Assert (dat, "What?"); + map = dat->findMap (itmp); + } + else { + act_error_ctxt (stderr); + fatal_error ("Interfaces are only supported for process and data types; got `%s'?", it->BaseType()->getName()); + } if (!map) { - fatal_error ("Missing interface `%s' from process `%s'?", - itmp->BaseType()->getName(), proc->getName()); + act_error_ctxt (stderr); + fatal_error ("Missing interface `%s' from type `%s'?", + itmp->BaseType()->getName(), it->BaseType()->getName()); } listitem_t *li; #if 0 @@ -397,14 +416,50 @@ Expr *ActId::Eval (ActNamespace *ns, Scope *s, int is_lval, int is_chp) li = list_next (li); } if (!li) { - fatal_error ("Map for interface `%s' doesn't contain `%s'", - itmp->BaseType()->getName(), id->Rest()->getName()); + bool extra_check_passed = false; + if (is_chp && chp_processing_macro() != 0) { + // it may not be in the interface, but it may be in the + // actual type! we allow this for macros. + Scope *srch = s; + const char *pt = itmp->getPTypeID (); + if (pt) { + ValueIdx *vx = srch->LookupVal (pt); + while (!vx && srch && srch->Parent()) { + vx = srch->Parent()->LookupVal (pt); + srch = srch->Parent (); + } + if (vx) { + if (vx->init && srch->issetPType (vx->u.idx)) { + InstType *px = srch->getPType (vx->u.idx); + u = dynamic_cast(px->BaseType()); + if (u) { + // XXX: edit type in "s" for expanded scopes + if (s->isExpanded()) { + Assert (s->Lookup (id->getName()) == it, "What?"); + InstType *xtmp = new InstType (srch, u, 1); + s->refineBaseType (id->getName(), xtmp); + delete xtmp; + } + if (u->FindPort (id->Rest()->getName()) != 0) { + extra_check_passed = true; + id = id->Rest (); + } + } + } + } + } + } + if (!extra_check_passed) { + act_error_ctxt (stderr); + fatal_error ("Map for interface `%s' doesn't contain `%s'", + itmp->BaseType()->getName(), id->Rest()->getName()); + } } -#if 0 +#if 0 printf ("NEW ID rest: "); id->Print(stdout); printf ("\n"); -#endif +#endif } else { id = id->Rest (); @@ -1445,6 +1500,7 @@ act_connection *ActId::Canonical (Scope *s) li = list_next (li); } if (!li) { + act_error_ctxt (stderr); fatal_error ("Map for interface `%s' doesn't contain `%s'", itmp->BaseType()->getName(), id->Rest()->getName()); } @@ -1510,7 +1566,7 @@ act_connection *ActId::Canonical (Scope *s) #if 0 printf ("Type: %s, port %s\n", ux->getName(), idrest->getName()); -#endif +#endif portid = ux->FindPort (idrest->getName()); Assert (portid > 0, "What?"); diff --git a/act/inline.cc b/act/inline.cc index 60702d6f..b92829b5 100644 --- a/act/inline.cc +++ b/act/inline.cc @@ -123,16 +123,19 @@ void act_dump_table (act_inline_table *tab) static act_inline_value _lookup_binding (act_inline_table *Hs, - const char *name, ActId *rest, int err = 1) + const char *name, + Array *deref, + ActId *rest, int err = 1) { hash_bucket_t *b; act_inline_table *origHs = Hs; act_inline_value rv; + while (Hs) { b = hash_lookup (Hs->state, name); if (b) { int ni, nb; - int sz = 1; + int sz, array_sz; InstType *it = Hs->sc->Lookup (name); Data *d = NULL; @@ -146,6 +149,18 @@ _lookup_binding (act_inline_table *Hs, d->getStructCount (&nb, &ni); sz = nb + ni; } + else { + sz = -1; + } + + if (it->arrayInfo()) { + // XXX: deal with deref + array_sz = it->arrayInfo()->size(); + } + else { + array_sz = -1; + } + /* return a copy */ act_inline_value bval; bval = *((act_inline_value *)b->v); @@ -160,16 +175,29 @@ _lookup_binding (act_inline_table *Hs, Assert (off + sz2 <= sz, "What?"); Assert (sz2 > 0, "Hmm"); + int array_off = 0; + + if (array_sz != -1) { + Assert (deref, "Array var without deref?"); + array_off = it->arrayInfo()->Offset (deref); + act_error_ctxt (stderr); + fatal_error ("Access to index that is out of bounds in _lookup!"); + } + Assert (bval.is_struct, "What?"); - if (sz2 == 1) { - /* XXX: FIXME. This may or may not be a structure */ + // get type of the "rest" + InstType *rit; + act_type_var (d->CurScope(), rest, &rit); + Assert (rit, "Hmm"); + + if (sz2 == 1 && !TypeFactory::isStructure (rit)) { rv.is_struct = 0; } else { rv.is_struct = 1; } - rv.is_struct_id = 0; + rv.is_just_id = 0; if (rv.is_struct) { MALLOC (rv.u.arr, Expr *, sz2); rv.struct_count = sz2; @@ -192,6 +220,9 @@ _lookup_binding (act_inline_table *Hs, } Assert (bval.getVal()->type == E_VAR, "Hmm"); xnew = ((ActId *)bval.getVal()->u.e.l)->Clone (); + if (deref) { + xnew->Tail()->setArray (deref->Clone()); + } xnew->Tail()->Append (fields[i+off]->Clone()); NEW (bind_val, Expr); bind_val->type = E_VAR; @@ -199,7 +230,7 @@ _lookup_binding (act_inline_table *Hs, bind_val->u.e.l = (Expr *)xnew; } else { - bind_val = bval.u.arr[i+off]; + bind_val = bval.u.arr[array_off*sz+i+off]; } if (rv.is_struct) { rv.u.arr[i] = bind_val; @@ -222,11 +253,44 @@ _lookup_binding (act_inline_table *Hs, FREE (fields); } } + else if (deref) { + if (bval.isSimple()) { + ActId *xnew; + if (bval.getVal()->type != E_VAR) { + fprintf (stderr, " PTR is %p\n", bval.getVal()); + bval.Print (stderr); + fprintf (stderr, "\n"); + } + Assert (bval.getVal()->type == E_VAR, "Hmm"); + xnew = ((ActId *)bval.getVal()->u.e.l)->Clone (); + xnew->Tail()->setArray (deref->Clone()); + + Expr *bind_val; + NEW (bind_val, Expr); + bind_val->type = E_VAR; + bind_val->u.e.r = NULL; + bind_val->u.e.l = (Expr *)xnew; + rv.u.val = bind_val; + rv.is_just_id = 1; + } + else { + int array_off = it->arrayInfo()->Offset (deref); + Assert (array_off != -1, "Out of bounds?"); + rv.u.val = bval.u.arr[array_off]; + if (rv.u.val->type == E_VAR) { + rv.is_just_id = 1; + } + } + } else { + // either simple ID access or structure access rv = bval; if (!bval.isSimple()) { - Assert (bval.struct_count == sz, "What?"); - MALLOC (rv.u.arr, Expr *, bval.struct_count); + Assert (sz == -1 || bval.struct_count == sz, "What?"); + Assert (array_sz == -1 || bval.array_sz == array_sz, "What?!"); + MALLOC (rv.u.arr, Expr *, + (sz == -1 ? 1 : bval.struct_count)* + (array_sz == -1 ? 1 : bval.array_sz)); for (int i=0; i < sz; i++) { rv.u.arr[i] = bval.u.arr[i]; if (err) { @@ -318,6 +382,7 @@ static void _update_binding (act_inline_table *Hs, ActId *id, int sz = 1; Data *xd; int *widths; + Array *deref = id->arrayInfo(); #if 0 printf ("update binding for: "); @@ -363,7 +428,7 @@ static void _update_binding (act_inline_table *Hs, ActId *id, b = hash_lookup (Hs->state, id->getName()); if (!b) { act_inline_value lv, bindv; - lv = _lookup_binding (Hs, id->getName(), NULL, 0); + lv = _lookup_binding (Hs, id->getName(), id->arrayInfo(), NULL, 0); #if 0 printf ("I'm here, lv = "); lv.Print (stdout); @@ -372,13 +437,13 @@ static void _update_binding (act_inline_table *Hs, ActId *id, if (lv.isValid()) { // found a valid binding bindv = lv; - if (bindv.isSimple() && xd) { -#if 0 + if (bindv.isSimple() && (xd || xit->arrayInfo())) { +#if 0 printf ("| populate and elaborate binding\n"); #endif // structure, elaborate the binding - bindv.elaborateStructId (xd); -#if 0 + bindv.elaborateStructId (xd, xit->arrayInfo()); +#if 0 printf ("| "); bindv.Print (stdout); printf ("\n"); @@ -387,38 +452,67 @@ static void _update_binding (act_inline_table *Hs, ActId *id, } else { // create a dummy NULL binding - if (xd) { - bindv.is_struct = 1; - bindv.struct_count = sz; - MALLOC (bindv.u.arr, Expr *, sz); - for (int i=0; i < sz; i++) { + if (xd || xit->arrayInfo()) { + if (xd) { + bindv.is_struct = 1; + bindv.struct_count = sz; + } + + if (xit->arrayInfo()) { + bindv.is_array = 1; + bindv.array_sz = xit->arrayInfo()->size(); + } + + MALLOC (bindv.u.arr, Expr *, sz*(bindv.is_array ? bindv.array_sz : 1)); + + for (int i=0; i < sz*(bindv.is_array ? bindv.array_sz : 1); i++) { bindv.u.arr[i] = NULL; } + +#if 0 + printf ("| "); + bindv.Print (stdout); + printf ("\n"); +#endif } } b = hash_add (Hs->state, id->getName()); /* add int(.) wrapper if needed */ - if (xd) { - for (int i=0; i < sz; i++) { - if (!Hs->macro_mode && bindv.u.arr[i] && widths[i] > 0) { - bindv.u.arr[i] = _wrap_width (bindv.u.arr[i], widths[i]); + if (xd || xit->arrayInfo()) { + int tot = sz * (bindv.is_array ? bindv.array_sz : 1); + for (int i=0; i < tot; i++) { + if (!Hs->macro_mode && bindv.u.arr[i]) { + if (xd) { + if (widths[i % sz] > 0) { + bindv.u.arr[i] = _wrap_width (bindv.u.arr[i], widths[i]); + } + } + else { + if (widths[0] > 0) { + bindv.u.arr[i] = _wrap_width (bindv.u.arr[i], widths[0]); + } + } } } } else { if (!Hs->macro_mode && bindv.u.val && widths[0] > 0) { bindv.u.val = _wrap_width (bindv.u.val, widths[0]); + bindv.is_just_id = 0; } } b->v = new act_inline_value(); *((act_inline_value *)b->v) = bindv; - } - act_inline_value resv = _lookup_binding (Hs, id->getName(), NULL, 0); - if (id->Rest()) { - Assert (xd, "What?!"); - int sz2; +#if 0 + printf ("F| "); + bindv.Print (stdout); + printf ("\n"); +#endif + } + act_inline_value resv = _lookup_binding (Hs, id->getName(), + id->arrayInfo(), NULL, 0); #if 0 printf (" >> update scenario:\n "); @@ -429,12 +523,21 @@ static void _update_binding (act_inline_table *Hs, ActId *id, printf ("\n"); #endif + if (id->Rest()) { + Assert (xd, "What?!"); + int sz2; + int off = xd->getStructOffset (id->Rest(), &sz2); + int array_off = 0; + if (deref) { + array_off = xit->arrayInfo()->Offset (deref); + Assert (array_off != -1, "Invalid array index?"); + } Assert (off >= 0 && off < sz, "What?"); Assert (off + sz2 <= sz, "What?"); Assert (!update.isSimple() || sz2 == 1, "Hmm"); if (resv.isSimple()) { - resv.elaborateStructId (xd); + resv.elaborateStructId (xd, xit->arrayInfo()); } Assert (!resv.isSimple(), "Hmm"); for (int i=0; i < sz2; i++) { @@ -446,10 +549,10 @@ static void _update_binding (act_inline_table *Hs, ActId *id, updatev = update.u.arr[i]; } if (!Hs->macro_mode && updatev && widths[off+i] > 0) { - resv.u.arr[off+i] = _wrap_width (updatev, widths[off+i]); + resv.u.arr[array_off*sz + off+i] = _wrap_width (updatev, widths[off+i]); } else { - resv.u.arr[off+i] = updatev; + resv.u.arr[array_off*sz + off+i] = updatev; } #if 0 printf ("set offset %d to ", off+i); @@ -476,31 +579,64 @@ static void _update_binding (act_inline_table *Hs, ActId *id, #endif } else { - if (xd) { - if (update.isSimple()) { + if (xd || deref) { + if (update.isSimple() && !deref) { resv = update; } else { if (resv.isSimple()) { - resv.elaborateStructId (xd); + resv.elaborateStructId (xd, xit->arrayInfo()); + } + int array_off = 0; + if (deref) { + array_off = xit->arrayInfo()->Offset (deref); + Assert (array_off != -1, "Out of bounds"); } - for (int i=0; i < sz; i++) { - if (!Hs->macro_mode && update.u.arr[i] && widths[i] > 0) { - resv.u.arr[i] = _wrap_width (update.u.arr[i], widths[i]); + if (xd) { + for (int i=0; i < sz; i++) { + if (!Hs->macro_mode && update.u.arr[i] && widths[i] > 0) { + resv.u.arr[array_off*sz + i] = _wrap_width (update.u.arr[i], widths[i]); + } + else { + resv.u.arr[array_off*sz + i] = update.u.arr[i]; + } + } + } + else { + if (!Hs->macro_mode && update.u.val && widths[0] > 0) { + resv.u.arr[array_off] = _wrap_width (update.u.val, widths[0]); } else { - resv.u.arr[i] = update.u.arr[i]; + resv.u.arr[array_off] = update.u.val; } } } } else { Assert (update.isSimple(), "Hmm"); - if (!Hs->macro_mode && update.u.val && widths[0] > 0) { - resv.u.val = _wrap_width (update.u.val, widths[0]); + + if (resv.isValid()) { + if (resv.isSimple()) { + resv.u.val = update.u.val; + resv.is_just_id = update.is_just_id; + } + else { + if (resv.u.arr) { + FREE (resv.u.arr); + } + resv.u.val = update.u.val; + resv.is_just_id = update.is_just_id; + } } else { - resv.u.val = update.u.val; + resv = update; + } + + if (!Hs->macro_mode && update.u.val && widths[0] > 0) { + if (!xit->arrayInfo()) { + resv.u.val = _wrap_width (resv.u.val, widths[0]); + resv.is_just_id = 0; + } } } } @@ -580,6 +716,7 @@ static act_inline_value _expand_inline (act_inline_table *Hs, Expr *e, int recur only */ { lv = _lookup_binding (Hs, ((ActId *)e->u.e.l)->getName(), + ((ActId *)e->u.e.l)->arrayInfo(), ((ActId *)e->u.e.l)->Rest()); Assert (lv.isSimple(), "What?"); Expr *r = lv.getVal(); @@ -738,7 +875,7 @@ static act_inline_value _expand_inline (act_inline_table *Hs, Expr *e, int recur break; case E_SELF: - retv = _lookup_binding (Hs, "self", NULL); + retv = _lookup_binding (Hs, "self", NULL, NULL); break; case E_SELF_ACK: @@ -748,7 +885,8 @@ static act_inline_value _expand_inline (act_inline_table *Hs, Expr *e, int recur case E_VAR: { ActId *tid = (ActId *)e->u.e.l; - retv = _lookup_binding (Hs, tid->getName(), tid->Rest()); + retv = _lookup_binding (Hs, tid->getName(), + tid->arrayInfo(), tid->Rest()); } break; @@ -806,7 +944,7 @@ act_inline_table *act_inline_merge_tables (int nT, act_inline_table **T, act_inline_value vl; /* vl is the value before the merge, in the parent context */ - vl = _lookup_binding (Tret, b->key, NULL, 0); + vl = _lookup_binding (Tret, b->key, NULL, NULL, 0); InstType *et = sc->Lookup (b->key); Assert (et, "What?"); @@ -969,7 +1107,7 @@ void act_inline_setval (act_inline_table *Hs, ActId *id, act_inline_value act_inline_getval (act_inline_table *Hs, const char *s) { - return _lookup_binding (Hs, s, NULL); + return _lookup_binding (Hs, s, NULL, NULL); } @@ -979,17 +1117,41 @@ void act_inline_value::Print (FILE *fp) fprintf (fp, "@invalid@"); return; } + if (is_array && !is_just_id) { + fprintf (fp, "@arr[%d]", array_sz); + } fprintf (fp, "@%s", is_struct ? "struct" : "elem"); if (is_struct) { - if (is_struct_id) { + if (is_just_id) { fprintf (fp, " id: "); print_uexpr (fp, u.val); } else { fprintf (fp, "%d ", struct_count); - for (int i=0; i < struct_count; i++) { + for (int j=0; j < (array_sz == 0 ? 1 : array_sz); j++) { + if (j != 0) { + fprintf(fp, " | "); + } + for (int i=0; i < struct_count; i++) { + if (i != 0) { + fprintf (fp, " ; "); + } + if (u.arr[i+j*struct_count]) { + print_uexpr (fp, u.arr[i+j*struct_count]); + } + else { + fprintf (fp, "nul"); + } + } + } + } + } + else { + fprintf (fp, " "); + if (is_array && !is_just_id) { + for (int i=0; i < array_sz; i++) { if (i != 0) { - fprintf (fp, " ; "); + fprintf (fp, " | "); } if (u.arr[i]) { print_uexpr (fp, u.arr[i]); @@ -999,44 +1161,77 @@ void act_inline_value::Print (FILE *fp) } } } - } - else { - fprintf (fp, " "); - print_uexpr (fp, u.val); + else { + print_uexpr (fp, u.val); + } } fprintf (fp, "@"); } -void act_inline_value::elaborateStructId (Data *d) +void act_inline_value::elaborateStructId (Data *d, Array *a) { Assert (isSimple(), "hmm"); Assert (is_struct, "What?"); ActId **fields; - int *types; ActId *baseid; int ni, nb; - d->getStructCount (&nb, &ni); - int sz = ni + nb; - fields = d->getStructFields (&types); - FREE (types); + int sz; + + if (d) { + int *types; + d->getStructCount (&nb, &ni); + sz = ni + nb; + fields = d->getStructFields (&types); + FREE (types); + } + else { + sz = 1; + fields = NULL; + } Assert (getVal()->type == E_VAR, "Hmm"); baseid = (ActId *)getVal()->u.e.l; - MALLOC (u.arr, Expr *, sz); + + if (a) { + is_array = 1; + array_sz = a->size(); + MALLOC (u.arr, Expr *, sz*array_sz); + } + else { + is_array = 0; + array_sz = 0; + MALLOC (u.arr, Expr *, sz); + } struct_count = sz; - is_struct_id = 0; - - for (int i=0; i < sz; i++) { - ActId *varnew; - NEW (u.arr[i], Expr); - u.arr[i]->type = E_VAR; - u.arr[i]->u.e.r = NULL; - varnew = baseid->Clone(); - varnew->Append (fields[i]); - u.arr[i]->u.e.l = (Expr *) varnew; + is_just_id = 0; + + for (int arr=0; arr < (array_sz == 0 ? 1 : array_sz); arr++) { + Array *newa; + + if (a) { + newa = a->unOffset (arr); + } + else { + newa = NULL; + } + + for (int i=0; i < sz; i++) { + ActId *varnew; + NEW (u.arr[arr*sz + i], Expr); + u.arr[arr*sz + i]->type = E_VAR; + u.arr[arr*sz + i]->u.e.r = NULL; + varnew = baseid->Clone(); + if (fields) { + varnew->Append (fields[i]); + } + varnew->setArray (newa); + u.arr[arr*sz + i]->u.e.l = (Expr *) varnew; + } + } + if (fields) { + FREE (fields); } - FREE (fields); Assert (!isSimple(), "Hmm{"); Assert (isValid(), "Check"); } diff --git a/act/inline.h b/act/inline.h index 749084c1..00245e52 100644 --- a/act/inline.h +++ b/act/inline.h @@ -1,6 +1,6 @@ /************************************************************************* * - * Copyright (c) 2021 Rajit Manohar + * Copyright (c) 2021, 2025 Rajit Manohar * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,9 +29,11 @@ class Data; struct act_inline_table; struct act_inline_value { act_inline_value() { + is_just_id = 0; is_struct = 0; - is_struct_id = 0; struct_count = 0; + is_array = 0; + array_sz = 0; u.val = NULL; } @@ -45,24 +47,26 @@ struct act_inline_value { Expr *getVal() { return u.val; } bool isSimple() { - if (is_struct == 0 || is_struct_id) return true; + if ((is_struct == 0 && is_array == 0) || is_just_id) return true; return false; } - void elaborateStructId (Data *d); + void elaborateStructId (Data *d, Array *a = NULL); - int numElems() { return struct_count; } + int numStructElems() { return struct_count; } + int numArrayElems() { return array_sz; } // check if there is some legitimate binding stored here bool isValid() { if (isSimple()) { + // the binding is stored in u.val if (u.val == NULL) return false; - if (is_struct) { + if (is_just_id) { if (u.val->type != E_VAR) return false; } return true; } - if (struct_count == 0) return false; + if (struct_count == 0 && array_sz == 0) return false; if (u.arr == NULL) return false; return true; } @@ -70,9 +74,14 @@ struct act_inline_value { // check if everthing is valid bool isValidFull() { if (!isValid()) return false; - if (is_struct && !is_struct_id) { - for (int i=0; i < struct_count; i++) { - if (u.arr[i] == NULL) return false; + if (!is_just_id) { + int tot = (struct_count == 0 ? 1 : struct_count) * + (array_sz == 0 ? 1 : array_sz); + + if (!isSimple()) { + for (int i=0; i < tot; i++) { + if (u.arr[i] == NULL) return false; + } } } return true; @@ -81,8 +90,11 @@ struct act_inline_value { void Print (FILE *fp); unsigned int is_struct:1; /* is this a structure? */ - unsigned int is_struct_id:1; /* special case structure, ID map */ - unsigned int struct_count:30; /* size of array for sanity checking */ + unsigned int is_array:1; /* this is an array */ + unsigned int is_just_id:1; /* special case, ID */ + unsigned int struct_count:30; /* size of flattened struct for sanity checking */ + unsigned int array_sz:30; /* array size, if any */ + union { Expr *val; /* single value */ Expr **arr; /* flattened array of values */ diff --git a/act/inst.cc b/act/inst.cc index cbec8f2f..28472578 100644 --- a/act/inst.cc +++ b/act/inst.cc @@ -430,6 +430,10 @@ Type *InstType::isConnectable (InstType *it, int weak) /* Even if the base types are not the same, they might be connectable because they have a common root */ + if (TypeFactory::isInterfaceType (t) && t == it->t) { + return t; + } + /* EVENTUALLY insttype pointers will be unique, and so this will work! */ if (TypeFactory::isInterfaceType (t)) { @@ -450,10 +454,11 @@ Type *InstType::isConnectable (InstType *it, int weak) /* other valid case: ptype(x) to connect to y, where y exports interface x */ - if (TypeFactory::isPTypeType (t) && TypeFactory::isProcessType (it)) { + if (TypeFactory::isPTypeType (t) && + (TypeFactory::isProcessType (it) || TypeFactory::isStructure (it))) { /* ok there is hope - extract interface from ptype - - check that process exports this interface + - check that process/data type exports this interface */ if ((arrayInfo() && !arrayInfo()->isDeref()) || (it->arrayInfo() && !it->arrayInfo()->isDeref())) { @@ -463,18 +468,35 @@ Type *InstType::isConnectable (InstType *it, int weak) } PType *pt = dynamic_cast (t); InstType *iface = pt->getType(); - Process *rhs = dynamic_cast (it->BaseType()); - Assert (rhs, "What?"); - if (!iface) { - iface = this->getTypeParam (0); + if (TypeFactory::isProcessType (it)) { + Process *rhs = dynamic_cast (it->BaseType()); + Assert (rhs, "What?"); + if (!iface) { + iface = this->getTypeParam (0); + } + Assert (iface, "What?"); + if (!rhs->hasIface (iface, weak)) { + typecheck_err ("Process `%s' does not export interface `%s'\n", + rhs->getName(), iface->BaseType()->getName()); + return NULL; + } + return t; } - Assert (iface, "What?"); - if (!rhs->hasIface (iface, weak)) { - typecheck_err ("Process `%s' does not export interface `%s'\n", - rhs->getName(), iface->BaseType()->getName()); - return NULL; + else { + Assert (TypeFactory::isStructure (it), "I should not be here"); + Data *rhs = dynamic_cast (it->BaseType()); + Assert (rhs, "What?"); + if (!iface) { + iface = this->getTypeParam (0); + } + Assert (iface, "What?"); + if (!rhs->hasIface (iface, weak)) { + typecheck_err ("Data type `%s' does not export interface `%s'\n", + rhs->getName(), iface->BaseType()->getName()); + return NULL; + } + return t; } - return t; } return NULL; } @@ -917,8 +939,8 @@ InstType *InstType::Expand (ActNamespace *ns, Scope *s) } #if 0 - printf ("[%x] Name: %s\n", t, t->getName()); - printf ("[%x] Expanded: %s\n", xt, xt->getName()); + printf ("[%p] Name: %s\n", t, t->getName()); + printf ("[%p] Expanded: %s\n", xt, xt->getName()); #endif /* If parent is user-defined, we need to make sure we have the diff --git a/act/lang.h b/act/lang.h index 8db0af54..2da58f4b 100644 --- a/act/lang.h +++ b/act/lang.h @@ -885,10 +885,16 @@ act_dataflow *dflow_dup (act_dataflow *, ActNamespace *, ActNamespace *); act_chp *chp_expand (act_chp *, ActNamespace *, Scope *); /** - * Set the CHP expansion mode (1 if in macro, 0 otherwise) + * Set the CHP expansion mode (1/2 if in macro, 0 otherwise) + * 2 = macro in a process, 1 = other macro */ void chp_expand_macromode (int mode); +/** + * Get the CHP expansion mode: is it handling a macro? + */ +int chp_processing_macro (void); + /** * chp_expand helper for the items within the language block */ diff --git a/act/lang.m4 b/act/lang.m4 index 785f8954..8fd5c281 100644 --- a/act/lang.m4 +++ b/act/lang.m4 @@ -3099,6 +3099,7 @@ lang_dataflow[ActBody *]: "dataflow" "{" [ dataflow_ordering ] $0->line = $l; $0->column = $c; $0->file = $n; + $0->allow_chan = true; }} { dataflow_items ";" }* "}" {{X: @@ -3118,6 +3119,8 @@ lang_dataflow[ActBody *]: "dataflow" "{" [ dataflow_ordering ] } OPT_FREE ($3); + $0->allow_chan = false; + return new ActBody_Lang ($l, dflow); }} ; @@ -3162,6 +3165,9 @@ w_chan_int_expr "->" [ "[" wpint_expr [ "," wpint_expr ] "]" ] expr_id if (_act_id_is_true_false ($4)) { $E("Dataflow RHS can't be true/false!"); } + if (_act_id_is_enum_const ($0->os, $0->curns, $4)) { + $E("Can't use an enumeration constant in this context!"); + } InstType *it; if (act_type_var ($0->scope, $4, &it) != T_CHAN) { $e("Identifier on the RHS of a dataflow expression must be of channel type"); @@ -3453,6 +3459,9 @@ expr_id_or_star[ActId *]: expr_id if (_act_id_is_true_false ($1)) { $E("Can't use true/false in this context!"); } + if (_act_id_is_enum_const ($0->os, $0->curns, $1)) { + $E("Can't use an enumeration constant in this context!"); + } return $1; }} | "*" diff --git a/act/lang_chp.cc b/act/lang_chp.cc index e5e73b9a..e56ae286 100644 --- a/act/lang_chp.cc +++ b/act/lang_chp.cc @@ -57,6 +57,7 @@ static void _chp_expr_unstruct (list_t *l, Scope *s, Expr *e) char buf[1024]; snprintf (buf, 1024, "_us%d", _chp_freshvar_count); s->Add (buf, it); + ActNamespace::Act()->addGeneratedVar (s, s->LookupVal (buf)); NEW (c, act_chp_lang_t); c->space = NULL; c->label = NULL; @@ -264,12 +265,18 @@ void act_chp_free (act_chp_lang_t *c) } static int _chp_expanding_macro = 0; +static int _chp_still_in_macro = 0; void chp_expand_macromode (int v) { _chp_expanding_macro = v; } +int chp_processing_macro (void) +{ + return _chp_expanding_macro ? 1 : (_chp_still_in_macro ? 1 : 0); +} + void act_chp_macro_check (Scope *s, ActId *id) { if (_chp_expanding_macro) { @@ -1929,9 +1936,24 @@ static act_chp_lang_t *chp_expand_1 (act_chp_lang_t *c, ActNamespace *ns, Scope // also be fixed like STRUCT_REF Expr *te = chp_expr_expand (c->u.assign.e, ns, s); + list_t *xassign = chp_expr_unstruct (s, te); ret->u.assign.e = te; + + if (chp_processing_macro() == 0) { + int tr = act_type_expr (s, te, NULL, 2); + if (tr == T_ERR) { + fprintf (stderr, "Typechecking failed on CHP assignment\n"); + fprintf (stderr, " stmt: "); + ret->u.assign.id->Print (stderr, NULL); + fprintf (stderr, " := "); + print_uexpr (stderr, c->u.assign.e); + fprintf (stderr, "\n\t%s\n", act_type_errmsg ()); + exit (1); + } + } + if (xassign) { ret->label = NULL; list_append (xassign, ret); @@ -2144,7 +2166,7 @@ static act_chp_lang_t *chp_expand_1 (act_chp_lang_t *c, ActNamespace *ns, Scope case ACT_CHP_MACRO: { - ActId *x = expand_var_read (c->u.macro.id, ns, s); + ActId *x = expand_var_write (c->u.macro.id, ns, s); if (x->isNamespace()) { act_error_ctxt (stderr); fatal_error ("CHP macro and namespace globals don't mix"); @@ -2221,12 +2243,14 @@ static act_chp_lang_t *chp_expand_1 (act_chp_lang_t *c, ActNamespace *ns, Scope /*-- re-expand, do all the checks --*/ { + _chp_still_in_macro++; int tmp = Act::double_expand; act_chp_lang_t *oret = ret; Act::double_expand = 0; ret = chp_expand_1 (oret, ns, s); Act::double_expand = tmp; act_chp_free (oret); + _chp_still_in_macro--; } delete tsc; diff --git a/act/macros.cc b/act/macros.cc index 0f02ef96..1a87f806 100644 --- a/act/macros.cc +++ b/act/macros.cc @@ -73,7 +73,7 @@ UserMacro::~UserMacro () } -void UserMacro::Print (FILE *fp) +void UserMacro::Print (FILE *fp, bool header_only) { int templ = 0; int meta = 0; @@ -100,6 +100,10 @@ void UserMacro::Print (FILE *fp) fprintf (fp, " : "); rettype->Print (fp); } + if (header_only) { + fprintf (fp, ";\n"); + return; + } fprintf (fp, " {\n"); if (_exf && _exf->isExpanded()) { @@ -577,6 +581,14 @@ static void _replace_ids (ActId *id, act_inline_table *tab, Expr *e) if (e->type == E_INT && e->u.ival.v_extra) { e->u.ival.v_extra = (Expr *) new BigInt (*((BigInt *)e->u.ival.v_extra)); } + else if (e->type == E_VAR) { + e->u.e.l = (Expr *) ((ActId *)e->u.e.l)->Clone (); + } + else if (!expr_ex_is_cached (e)) { + Expr *f = expr_dup (e); + *e = *f; + FREE (f); + } } else { ActId *ret = id->Clone (); diff --git a/act/namespaces.cc b/act/namespaces.cc index 87b549eb..4dd7ba6d 100644 --- a/act/namespaces.cc +++ b/act/namespaces.cc @@ -590,8 +590,7 @@ void ActNamespace::Print (FILE *fp) fprintf (fp, ";\n"); } else if (TypeFactory::isInterfaceType (t)) { - u->PrintHeader (fp, "interface"); - fprintf (fp, ";\n"); + u->Print (fp); } else if (TypeFactory::isFuncType (t)) { Function *f = dynamic_cast (t); @@ -1021,8 +1020,51 @@ void ActNamespace::_updateClonedTypes (ActNamespace *root, hash_bucket_t *b, *bnew; // update the body type info, and re-construct scopes! + if (ActNamespace::Global()->B) { + ActBody *tmp; + ActBody *update = NULL; + ActBody *utail = NULL; + bool found = false; + + for (tmp = ActNamespace::Global()->B; tmp; tmp = tmp->Next()) { + if (dynamic_cast(tmp)) { + ActNamespace *tns = (dynamic_cast(tmp))->getNS(); + if (tns == this) { + found = true; + } + else { + found = false; + } + } + if (found) { + ActBody *tnext = tmp->Next(); + tmp->clrNext (); + ActBody *cpy = tmp->Clone (root, newroot); + tmp->setNext (tnext); + if (!update) { + update = cpy; + utail = update; + } + else { + utail->Append (cpy); + utail = cpy; + } + } + } + if (update) { + ActBody *tmp = new ActBody_Namespace (newns); + tmp->Append (update); + utail->Append (new ActBody_Namespace (ActNamespace::Global())); + ActNamespace::Global()->B->Append (tmp); + } + } if (B) { - newns->B = B->Clone (root, newroot); + if (newns->B) { + newns->B->Append (B->Clone (root, newroot)); + } + else { + newns->B = B->Clone (root, newroot); + } } hash_iter_init (N, &it); diff --git a/act/pass.cc b/act/pass.cc index 2af1e710..6d58b770 100644 --- a/act/pass.cc +++ b/act/pass.cc @@ -283,7 +283,8 @@ void ActPass::recursive_op (UserDef *p, int mode) FREE (tmp); } } - else { + else if (TypeFactory::isDataType (vx->t) || + TypeFactory::isStructure (vx->t)) { Data *x = dynamic_cast (vx->t->BaseType()); Assert (x, "what?"); if (x->isExpanded()) { @@ -298,6 +299,10 @@ void ActPass::recursive_op (UserDef *p, int mode) FREE (tmp); } } + else if (TypeFactory::isPStructType (vx->t)) { + /* nothing to do */ + } + // could be a pstruct! } } diff --git a/act/process.cc b/act/process.cc index 94dc4199..06363ed5 100644 --- a/act/process.cc +++ b/act/process.cc @@ -23,8 +23,11 @@ #include #include #include +#include #include +int _act_inc_rec_depth (); +void _act_dec_rec_depth(); /*------------------------------------------------------------------------ * @@ -78,6 +81,7 @@ Process *Process::Expand (ActNamespace *ns, Scope *s, int nt, inst_param *u) } xp = new Process (ux); + ActNamespace::Act()->updateType (ux, xp); delete ux; Assert (_ns->EditType (xp->name, xp) == 1, "What?"); @@ -99,6 +103,13 @@ Process *Process::Expand (ActNamespace *ns, Scope *s, int nt, inst_param *u) xp->ifaces = NULL; } + int recval = _act_inc_rec_depth (); + + if (recval >= Act::max_recurse_depth) { + act_error_ctxt (stderr); + fatal_error ("Exceeded maximum recursion depth of %d\n", Act::max_recurse_depth); + } + /*-- expand macros --*/ for (int i=0; i < A_LEN (um); i++) { A_NEW (xp->um, UserMacro *); @@ -106,6 +117,14 @@ Process *Process::Expand (ActNamespace *ns, Scope *s, int nt, inst_param *u) A_INC (xp->um); } + const char *ret = xp->validateInterfaces (); + if (ret) { + act_error_ctxt (stderr); + fatal_error ("Inconsistent/missing method\n\t%s", ret); + } + + _act_dec_rec_depth (); + return xp; } @@ -742,3 +761,24 @@ void Process::recordGlobal (ActId *id) if (findGlobal (id)) return; list_append (used_globals, id->Clone()); } + + +const char *Process::validateInterfaces () +{ + if (!ifaces) return NULL; + listitem_t *li; + for (li = list_first (ifaces); li; li = list_next (li)) { + InstType *x = (InstType *) list_value (li); + Interface *ix = dynamic_cast (x->BaseType()); + Assert (ix, "What?!"); + + // now typecheck macros + const char *ret = ix->validateMacros (this, um, A_LEN (um)); + if (ret) { + return ret; + } + + li = list_next (li); + } + return NULL; +} diff --git a/act/prs.cc b/act/prs.cc index 7896cc91..0cb58628 100644 --- a/act/prs.cc +++ b/act/prs.cc @@ -522,6 +522,12 @@ static Expr *_wint_expr (ActTree *a, Expr *e) if (!e) return NULL; + Scope *oldsc; + oldsc = a->special_id_sc; + int oldval; + oldval = a->special_id; + a->special_id = 0; + p.l = a->line; p.c = a->column; p.f = a->file; @@ -542,6 +548,8 @@ static Expr *_wint_expr (ActTree *a, Expr *e) if (!(tc & T_PARAM)) { act_parse_err (&p, "Expression must be of type pint"); } + a->special_id = oldval; + a->special_id_sc = oldsc; return e; } diff --git a/act/prs2net_opts.conf b/act/prs2net_opts.conf index c80b0c92..870e7eb9 100644 --- a/act/prs2net_opts.conf +++ b/act/prs2net_opts.conf @@ -35,6 +35,16 @@ int emit_parasitics 0 # string_table device "C" +begin fet_params + string width "W" + string length "L" + string fin "NFIN" + string area_src "AS" + string area_drain "AD" + string perim_src "PS" + string perim_drain "PD" +end + end # diff --git a/act/scope.cc b/act/scope.cc index 9a85cc00..90a3e88e 100644 --- a/act/scope.cc +++ b/act/scope.cc @@ -1255,7 +1255,7 @@ void Scope::BindParam (ActId *id, AExpr *ae) AExprstep *aes = NULL; if (subrange_info) { - actual = act_actual_insttype (this, id, NULL); + actual = act_actual_insttype (this, id, NULL, false); } else { actual = vx->t; @@ -1820,26 +1820,33 @@ void Scope::playBody (ActBody *b) Add (inst->getName(), inst->getType()); } } - else { - if (dynamic_cast(b)) { + else if (dynamic_cast(b)) { + ActBody_Lang *l = dynamic_cast(b); + if (l->gettype() == ActBody_Lang::LANG_REFINE) { + act_refine *r = (act_refine *) l->getlang(); + if (r->b) { + playBody (r->b); + } + } + } + else if (dynamic_cast(b)) { ActBody_Loop *l = dynamic_cast(b); playBody (l->getBody()); + } + else { + ActBody_Select_gc *sel; + if (dynamic_cast(b)) { + sel = dynamic_cast(b)->getGC(); + } + else if (dynamic_cast(b)) { + sel = dynamic_cast(b)->getGC(); } else { - ActBody_Select_gc *sel; - if (dynamic_cast(b)) { - sel = dynamic_cast(b)->getGC(); - } - else if (dynamic_cast(b)) { - sel = dynamic_cast(b)->getGC(); - } - else { - sel = NULL; - } - while (sel) { - playBody (sel->getBody()); - sel = sel->getNext(); - } + sel = NULL; + } + while (sel) { + playBody (sel->getBody()); + sel = sel->getNext(); } } } diff --git a/act/test/expand/10.act b/act/test/expand/10.act index 5a6d6c59..bbd81704 100644 --- a/act/test/expand/10.act +++ b/act/test/expand/10.act @@ -6,7 +6,7 @@ defproc foo (bool x[i]; bool y[i]) prs { (k:i: x[k] => y[k]-) } - foo f; + [ i > 0 -> foo f; ] } diff --git a/act/test/expand/18.act b/act/test/expand/18.act new file mode 100644 index 00000000..b6e9bca9 --- /dev/null +++ b/act/test/expand/18.act @@ -0,0 +1,10 @@ +template +defproc test(int a, b[N]) +{ + (i:N: a=b[i];) + a=b[0]; +} + +test<3> x; + +test<0> y; diff --git a/act/test/expand/19.act b/act/test/expand/19.act new file mode 100644 index 00000000..b264854c --- /dev/null +++ b/act/test/expand/19.act @@ -0,0 +1,12 @@ +defproc test() +{ + int a[0]; + int b; + + chp { + b := 0; + b := a[b] + } +} + +test t; diff --git a/act/test/expand/runs/10.act.stderr b/act/test/expand/runs/10.act.stderr index b420d3e3..e69de29b 100644 --- a/act/test/expand/runs/10.act.stderr +++ b/act/test/expand/runs/10.act.stderr @@ -1,7 +0,0 @@ -In expanding foo<0> (10.act:3) -In expanding foo<1> (10.act:3) -In expanding foo<2> (10.act:3) -In expanding foo<3> (10.act:3) -In expanding :: -Error on or near line number 9. -FATAL: Port `x': zero-length array creation not permitted diff --git a/act/test/expand/runs/18.act.stderr b/act/test/expand/runs/18.act.stderr new file mode 100644 index 00000000..2796ffce --- /dev/null +++ b/act/test/expand/runs/18.act.stderr @@ -0,0 +1,5 @@ +In expanding test<0> (18.act:1) +In expanding :: +Error on or near line number 5. + id: b[0] +FATAL: Identifer conditionally created, but used when it does not exist diff --git a/act/test/expand/runs/18.act.stdout b/act/test/expand/runs/18.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/expand/runs/19.act.stderr b/act/test/expand/runs/19.act.stderr new file mode 100644 index 00000000..8addfcdb --- /dev/null +++ b/act/test/expand/runs/19.act.stderr @@ -0,0 +1,5 @@ +In expanding test (19.act:1) +In expanding :: +Error on or near line number 6. + id: a[b] +FATAL: Identifer conditionally created, but used when it does not exist diff --git a/act/test/expand/runs/19.act.stdout b/act/test/expand/runs/19.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/func/53.act b/act/test/func/53.act new file mode 100644 index 00000000..bd8f015a --- /dev/null +++ b/act/test/func/53.act @@ -0,0 +1,16 @@ +function pfunc (pint a[4]) : pint +{ + chp { + self := a[0] + a[1] + a[2] + a[3] + } +} + +pint w[3]; + +w[0] = 5; +w[1] = 3; +w[2] = 17; + +pint res = pfunc (w); + +{ res = 10 : "What?" }; diff --git a/act/test/func/54.act b/act/test/func/54.act new file mode 100644 index 00000000..b3352f87 --- /dev/null +++ b/act/test/func/54.act @@ -0,0 +1,19 @@ +function pfunc (pint a[4]) : pint +{ + chp { + self := a[0] + a[1] + a[2] + a[3] + } +} + +pint w[4]; + +w[0] = 5; +w[1] = 3; +w[2] = 17; +w[3] = 2; + +pint res = pfunc (w); + +{ res = 27 : "Should match!" }; + +{ res = 10 : "What?" }; diff --git a/act/test/func/55.act b/act/test/func/55.act new file mode 100644 index 00000000..508aaed3 --- /dev/null +++ b/act/test/func/55.act @@ -0,0 +1,19 @@ +function pfunc (pint a[4]) : pint +{ + chp { + a[0] := a[0] + a[1] + a[2] + a[3] + } +} + +pint w[4]; + +w[0] = 5; +w[1] = 3; +w[2] = 17; +w[3] = 2; + +pint res = pfunc (w); + +{ res = 27 : "Should match!" }; + +{ res = 10 : "What?" }; diff --git a/act/test/func/56.act b/act/test/func/56.act new file mode 100644 index 00000000..ef22bc35 --- /dev/null +++ b/act/test/func/56.act @@ -0,0 +1,17 @@ +defptype foo (pint a; pbool b); + +function testme (foo x) : pint +{ + chp { + [ x.b -> self := x.a + 4 + [] else -> self := x.a - 1 + ] + } +} + +foo x; +x = foo (5, true); + +{ testme (x) = 9 : "Should pass!" }; + +{ testme (x) = 8 : "Should fail!" }; diff --git a/act/test/func/57.act b/act/test/func/57.act new file mode 100644 index 00000000..96535273 --- /dev/null +++ b/act/test/func/57.act @@ -0,0 +1,29 @@ +deftype mystruct (int a, b) +{ + methods { + function getsum() : int + { + chp { + self := a + b + } + } + function addone() : mystruct + { + chp { + self.a := a + 1; + self.b := b + 1 + } + } + } +} + +defproc test() +{ + mystruct s; + int a; + chp { + s := s.addone(); + a := s.getsum(); + a := s.addone().getsum() + } +} diff --git a/act/test/func/runs/53.act.stderr b/act/test/func/runs/53.act.stderr new file mode 100644 index 00000000..82f6d81f --- /dev/null +++ b/act/test/func/runs/53.act.stderr @@ -0,0 +1,5 @@ +In expanding pfunc (53.act:1) +In expanding :: +Error on or near line number 14. +Typechecking failed, pint[4] v/s pint[3] + Types `pint[4]' and `pint[3]' are not compatible diff --git a/act/test/func/runs/53.act.stdout b/act/test/func/runs/53.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/func/runs/54.act.stderr b/act/test/func/runs/54.act.stderr new file mode 100644 index 00000000..d68e35e1 --- /dev/null +++ b/act/test/func/runs/54.act.stderr @@ -0,0 +1,6 @@ +In expanding :: +Error on or near line number 19. +*** Assertion failed *** + assertion: res=10 + message: What? +FATAL: Aborted execution on failed assertion diff --git a/act/test/func/runs/54.act.stdout b/act/test/func/runs/54.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/func/runs/55.act.stderr b/act/test/func/runs/55.act.stderr new file mode 100644 index 00000000..74e15005 --- /dev/null +++ b/act/test/func/runs/55.act.stderr @@ -0,0 +1,5 @@ +In expanding pfunc (55.act:1) +In expanding :: +Error on or near line number 15. + id: self +FATAL: Uninitialized identifier diff --git a/act/test/func/runs/55.act.stdout b/act/test/func/runs/55.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/func/runs/56.act.stderr b/act/test/func/runs/56.act.stderr new file mode 100644 index 00000000..f6aa5c79 --- /dev/null +++ b/act/test/func/runs/56.act.stderr @@ -0,0 +1,6 @@ +In expanding :: +Error on or near line number 17. +*** Assertion failed *** + assertion: testme(x)=8 + message: Should fail! +FATAL: Aborted execution on failed assertion diff --git a/act/test/func/runs/56.act.stdout b/act/test/func/runs/56.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/func/runs/57.act.stderr b/act/test/func/runs/57.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/func/runs/57.act.stdout b/act/test/func/runs/57.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/intchan/runs/1.act.stderr b/act/test/intchan/runs/1.act.stderr index 4e7522d2..e383979a 100644 --- a/act/test/intchan/runs/1.act.stderr +++ b/act/test/intchan/runs/1.act.stderr @@ -1,3 +1,3 @@ ERROR: File `1.act', line 6, col 5 - User-defined channel data type must be a structure with pure data. + User-defined channel data type must be a structure with pure data or enumeration. Type: dualrail diff --git a/act/test/lang/137.act b/act/test/lang/137.act new file mode 100644 index 00000000..4af7a343 --- /dev/null +++ b/act/test/lang/137.act @@ -0,0 +1,13 @@ +deftype rec (int a, b) { } + +defproc test() +{ + chan(rec) a; + chan(int) x; + + dataflow { + a.a -> x + } +} + +test t; diff --git a/act/test/lang/138.act b/act/test/lang/138.act new file mode 100644 index 00000000..50d9a9eb --- /dev/null +++ b/act/test/lang/138.act @@ -0,0 +1,22 @@ +deftype rec (int a, b) { + methods { + function geta() : int + { + chp { + self := a + } + } + } +} + +defproc test() +{ + chan(rec) a; + chan(int) x; + + dataflow { + a.geta() -> x + } +} + +test t; diff --git a/act/test/lang/139.act b/act/test/lang/139.act new file mode 100644 index 00000000..9630fe12 --- /dev/null +++ b/act/test/lang/139.act @@ -0,0 +1,13 @@ +deftype rec (int a, b) { } + +defproc test() +{ + chan(rec) a; + chan(int) x; + + dataflow { + x -> a.a + } +} + +test t; diff --git a/act/test/lang/140.act b/act/test/lang/140.act new file mode 100644 index 00000000..ace1adb1 --- /dev/null +++ b/act/test/lang/140.act @@ -0,0 +1,13 @@ +deftype rec (int a, b) { } + +defproc test() +{ + chan(rec) a; + chan(int) x; + + dataflow { + a.a + a.b -> x + } +} + +test t; diff --git a/act/test/lang/141.act b/act/test/lang/141.act new file mode 100644 index 00000000..fd5492f5 --- /dev/null +++ b/act/test/lang/141.act @@ -0,0 +1,29 @@ +deftype rec (int a, b) { + methods { + function geta() : int + { + chp { + self := a + } + } + } +} + +deftype foo(rec b) { } + +defproc test() +{ + rec a[2]; + int x; + + foo b; + + chp { + x := b.b.geta(); + log ("got x: ", x); + x := a[0].geta(); + log ("got x: ", x) + } +} + +test t; diff --git a/act/test/lang/142.act b/act/test/lang/142.act new file mode 100644 index 00000000..5e13094c --- /dev/null +++ b/act/test/lang/142.act @@ -0,0 +1,29 @@ +deftype rec (int a, b) { + methods { + function geta() : int + { + chp { + self := a + } + } + } +} + +deftype foo(rec b) { } + +defproc test() +{ + rec a[2]; + int x; + + foo b; + + chp { + x := b.b.geta(); + log ("got x: ", x); + x := a[0].geta[2](); + log ("got x: ", x) + } +} + +test t; diff --git a/act/test/lang/143.act b/act/test/lang/143.act new file mode 100644 index 00000000..45f2ad40 --- /dev/null +++ b/act/test/lang/143.act @@ -0,0 +1,28 @@ +deftype rec (int a, b) { + methods { + function geta() : int + { + chp { + self := a + } + } + } +} + +deftype foo(rec b) { } + +defproc test() +{ + rec a[2]; + int x; + + foo b; + + chp { + x := b.b.geta(); + log ("got x: ", x); + [ a[0].geta() = 0 -> log ("equal zero") [] else -> skip ] + } +} + +test t; diff --git a/act/test/lang/144.act b/act/test/lang/144.act new file mode 100644 index 00000000..aada56bf --- /dev/null +++ b/act/test/lang/144.act @@ -0,0 +1,29 @@ +defproc bar(bool a, b) +{ + prs { + a => b- + } +} + +deftype myfoo <: bool (bool t, f) { } + + +deftype morefoo <: myfoo (bool q) { q = f; } + +defproc test() +{ + bool x, y, z; + prs { + + x => y- + } + + refine +{ myfoo x; } + { + bar q(x.t,y); + } + refine<2> +{ myfoo z; morefoo x; } + { bar q2(y,z.t); } +} + +test t; diff --git a/act/test/lang/145.act b/act/test/lang/145.act new file mode 100644 index 00000000..0a3dbf96 --- /dev/null +++ b/act/test/lang/145.act @@ -0,0 +1,29 @@ +deftype myint <: int () { } + +defproc p () +{ + int x; + chp { + *[ x:=0 ] + } + refine { + int y; + chp { + *[ y:=1 ] + } + } +} + +defproc p1 <: p () +{ + refine<2> + +{ + myint y; + } + { + chp { + *[ y:=2 ] + } + } +} + diff --git a/act/test/lang/runs/137.act.stderr b/act/test/lang/runs/137.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/137.act.stdout b/act/test/lang/runs/137.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/138.act.stderr b/act/test/lang/runs/138.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/138.act.stdout b/act/test/lang/runs/138.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/139.act.stderr b/act/test/lang/runs/139.act.stderr new file mode 100644 index 00000000..ca62da36 --- /dev/null +++ b/act/test/lang/runs/139.act.stderr @@ -0,0 +1,3 @@ +ERROR: File `139.act', line 9, col 6 + Identifier on the RHS of a dataflow expression must be of channel type + ID: a.a diff --git a/act/test/lang/runs/139.act.stdout b/act/test/lang/runs/139.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/140.act.stderr b/act/test/lang/runs/140.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/140.act.stdout b/act/test/lang/runs/140.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/141.act.stderr b/act/test/lang/runs/141.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/141.act.stdout b/act/test/lang/runs/141.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/142.act.stderr b/act/test/lang/runs/142.act.stderr new file mode 100644 index 00000000..f1479c7c --- /dev/null +++ b/act/test/lang/runs/142.act.stderr @@ -0,0 +1,2 @@ +ERROR: File `142.act', line 24, col 11 + Array de-reference for user macro: a[0].geta[2] diff --git a/act/test/lang/runs/142.act.stdout b/act/test/lang/runs/142.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/143.act.stderr b/act/test/lang/runs/143.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/143.act.stdout b/act/test/lang/runs/143.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/144.act.stderr b/act/test/lang/runs/144.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/144.act.stdout b/act/test/lang/runs/144.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/145.act.stderr b/act/test/lang/runs/145.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/lang/runs/145.act.stdout b/act/test/lang/runs/145.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/meta/runs/20.act.stderr b/act/test/meta/runs/20.act.stderr index 8dc06031..c65d4c1b 100644 --- a/act/test/meta/runs/20.act.stderr +++ b/act/test/meta/runs/20.act.stderr @@ -1,3 +1,3 @@ In expanding :: Error on or near line number 7. -FATAL: Argument to parameter structure constructor `mytype<>' is not a constant +FATAL: Argument to parameter structure constructor `mytype' is not a constant diff --git a/act/test/other/runs/14.act.stderr b/act/test/other/runs/14.act.stderr index a1b4a95e..49343b40 100644 --- a/act/test/other/runs/14.act.stderr +++ b/act/test/other/runs/14.act.stderr @@ -1,3 +1,4 @@ In expanding :: -Error on or near line number 1. -FATAL: Instance `x': zero-length array creation not permitted +Error on or near line number 3. + id: x +FATAL: Identifer conditionally created, but used when it does not exist diff --git a/act/test/print/34.act b/act/test/print/34.act new file mode 100644 index 00000000..026a3561 --- /dev/null +++ b/act/test/print/34.act @@ -0,0 +1,12 @@ +defproc test() +{ + pint W = 65; + int<128> q; + + chp { + q := 1 << (65 - 1); + q := 1 << (W - 1) + } +} + +test t; diff --git a/act/test/print/35.act b/act/test/print/35.act new file mode 100644 index 00000000..c43c0161 --- /dev/null +++ b/act/test/print/35.act @@ -0,0 +1,11 @@ +defproc test() +{ + pint W = 65; + + chp { + log(1 << (65 - 1)); + log(1 << (W - 1)) + } +} + +test t; diff --git a/act/test/print/runs/31.act.stdout b/act/test/print/runs/31.act.stdout index c6c988c7..06d811b8 100644 --- a/act/test/print/runs/31.act.stdout +++ b/act/test/print/runs/31.act.stdout @@ -9,7 +9,7 @@ int<4> x[4]; /* connections */ chp { -x[0]:=0x1;x[1]:=0x2;x[2]:=0x3;x[3]:=0x4;y:=x[0]*0+x[1]*1+x[2]*2+x[3]*3 +x[0]:=0x1;x[1]:=0x2;x[2]:=0x3;x[3]:=0x4;y:=x[0]*0x0+x[1]*0x1+x[2]*0x2+x[3]*0x3 } } diff --git a/act/test/print/runs/34.act.stderr b/act/test/print/runs/34.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/print/runs/34.act.stdout b/act/test/print/runs/34.act.stdout new file mode 100644 index 00000000..b61b7136 --- /dev/null +++ b/act/test/print/runs/34.act.stdout @@ -0,0 +1,19 @@ +defproc test (); + +defproc test () +{ + +/* instances */ +int<128> q; + +/* connections */ +chp { +q:=0x0000000000000000000000000000000010000000000000000;q:=0x0000000000000000000000000000000010000000000000000 +} +} + + +/* instances */ +test t; + +/* connections */ diff --git a/act/test/print/runs/35.act.stderr b/act/test/print/runs/35.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/print/runs/35.act.stdout b/act/test/print/runs/35.act.stdout new file mode 100644 index 00000000..8891b214 --- /dev/null +++ b/act/test/print/runs/35.act.stdout @@ -0,0 +1,18 @@ +defproc test (); + +defproc test () +{ + +/* instances */ + +/* connections */ +chp { +log(0x0000000000000000000000000000000010000000000000000);log(0x0000000000000000000000000000000010000000000000000) +} +} + + +/* instances */ +test t; + +/* connections */ diff --git a/act/test/types/65.act b/act/test/types/65.act new file mode 100644 index 00000000..920863cd --- /dev/null +++ b/act/test/types/65.act @@ -0,0 +1,32 @@ +template +interface linear(bool in[N], out[N]) +{ + methods { + macro sum(int x, y); + } +} + +template) p> +defproc foo () +{ + bool w[N]; + int a, b; + p y; + + y.in = w; + chp { + y.sum(a, b) + } +} + +defproc bar (bool in[4], out[4]) :> linear<4> { in -> in, out -> out } +{ + bool q[4]; + methods { + macro sum(int a, b) { + a := a + b + } + } +} + +foo<4, @bar> x; diff --git a/act/test/types/66.act b/act/test/types/66.act new file mode 100644 index 00000000..73f84c8a --- /dev/null +++ b/act/test/types/66.act @@ -0,0 +1,32 @@ +template +interface linear(bool in[N], out[N]) +{ + methods { + macro sum(int x, y); + } +} + +template) p> +defproc foo () +{ + bool w[N]; + int a, b; + p y; + + y.in = w; + chp { + y.sum(a, b) + } +} + +defproc bar (bool in[4], out[4]) :> linear<4> { in -> in, out -> out } +{ + bool q[4]; + methods { + macro sum(int a, b) { + a := a + b + } + } +} + +foo<4, @bar> x; diff --git a/act/test/types/67.act b/act/test/types/67.act new file mode 100644 index 00000000..8293bf22 --- /dev/null +++ b/act/test/types/67.act @@ -0,0 +1,18 @@ +defenum alu_ctrl { + ADD, SUB, AND, OR +}; + +defproc alu (chan?(int) A, B; chan?(alu_ctrl) ctrl; chan!(int) O) +{ + int a, b; + alu_ctrl c; + + chp { + *[ A?a, B?b, ctrl?c; + [ c = alu_ctrl.ADD -> O!(a+b) + [] c = alu_ctrl.SUB -> O!(a-b) + [] c = alu_ctrl.AND -> O!(a&b) + [] c = alu_ctrl.OR -> O!(a|b) + ] ] + } +} diff --git a/act/test/types/68.act b/act/test/types/68.act new file mode 100644 index 00000000..44b8c123 --- /dev/null +++ b/act/test/types/68.act @@ -0,0 +1,31 @@ +interface me() { + methods { + function sum (int x) : int; + } +} + +deftype myint (int xa) :> me { } +{ + methods { + function sum (int w) : int + { + chp { + self := w + xa + } + } + } +} + +template defproc test() +{ + x a; + int y; + + chp { + + y := 0; + y := a.sum(y) + } +} + +test<@myint> t; diff --git a/act/test/types/69.act b/act/test/types/69.act new file mode 100644 index 00000000..1773e926 --- /dev/null +++ b/act/test/types/69.act @@ -0,0 +1,30 @@ +/* F-bounded polymorphism */ +interface foo() { +methods { + function test (foo x) : bool; +} +} + +deftype mytype (int x) :> foo { } +{ + methods { + function test (mytype y) : bool + { + chp { + self := y.x > x ? true : false + } + } + } +} + +template +defproc test() +{ + t x; + bool w; + chp { + w := x.test(x) + } +} + +test<@mytype> x; diff --git a/act/test/types/70.act b/act/test/types/70.act new file mode 100644 index 00000000..8ef82893 --- /dev/null +++ b/act/test/types/70.act @@ -0,0 +1,30 @@ +/* F-bounded polymorphism */ +interface foo() { +methods { + function test (int x) : bool; +} +} + +deftype mytype (int x) :> foo { } +{ + methods { + function test (int<4> y) : bool + { + chp { + self := x > x ? true : false + } + } + } +} + +template +defproc test() +{ + t x; + bool w; + chp { + w := x.test(3) + } +} + +test<@mytype> x; diff --git a/act/test/types/71.act b/act/test/types/71.act new file mode 100644 index 00000000..7c60a351 --- /dev/null +++ b/act/test/types/71.act @@ -0,0 +1,32 @@ +/* F-bounded polymorphism */ +interface foo() { +methods { + function test (int x) : foo; +} +} + +deftype mytype (int x) :> foo { } +{ + methods { + function test (int y) : mytype + { + mytype ret; + chp { + ret.x := y; + self := ret + } + } + } +} + +template +defproc test() +{ + t x; + bool w; + chp { + x := x.test(3) + } +} + +test<@mytype> x; diff --git a/act/test/types/72.act b/act/test/types/72.act new file mode 100644 index 00000000..3eef001f --- /dev/null +++ b/act/test/types/72.act @@ -0,0 +1,30 @@ +interface foo() { +methods { + function plus (foo x) : foo; +} +} + +deftype mytype (int x) :> foo { } +{ + methods { + function plus (mytype y) : mytype + { + mytype ret; + chp { + ret.x := y.x; + self := ret + } + } + } +} + +template +defproc test() +{ + t x1, x2; + chp { + x1 := x1 + x2 + } +} + +test<@mytype> x; diff --git a/act/test/types/runs/29.act.stderr b/act/test/types/runs/29.act.stderr index ce7d12e2..d80aa3b5 100644 --- a/act/test/types/runs/29.act.stderr +++ b/act/test/types/runs/29.act.stderr @@ -1,3 +1,4 @@ -ERROR: File `29.act', line 17, col 4 - Typechecking failed on expression! - Identifier `y' is an interface type +ERROR: File `29.act', line 25, col 8 + Typechecking failed for template parameter #1 + Process `bitinv' does not export interface `linear' +Types `ptype' and `bitinv' are not compatible diff --git a/act/test/types/runs/46.act.stderr b/act/test/types/runs/46.act.stderr index de8ce208..ee9eca45 100644 --- a/act/test/types/runs/46.act.stderr +++ b/act/test/types/runs/46.act.stderr @@ -1,3 +1,3 @@ ERROR: File `46.act', line 6, col 5 - User-defined channel data type must be a structure with pure data. + User-defined channel data type must be a structure with pure data or enumeration. Type: dualrail diff --git a/act/test/types/runs/65.act.stderr b/act/test/types/runs/65.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/65.act.stdout b/act/test/types/runs/65.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/66.act.stderr b/act/test/types/runs/66.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/66.act.stdout b/act/test/types/runs/66.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/67.act.stderr b/act/test/types/runs/67.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/67.act.stdout b/act/test/types/runs/67.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/68.act.stderr b/act/test/types/runs/68.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/68.act.stdout b/act/test/types/runs/68.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/69.act.stderr b/act/test/types/runs/69.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/69.act.stdout b/act/test/types/runs/69.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/70.act.stderr b/act/test/types/runs/70.act.stderr new file mode 100644 index 00000000..aa69db42 --- /dev/null +++ b/act/test/types/runs/70.act.stderr @@ -0,0 +1,6 @@ +In expanding mytype (70.act:8) +In expanding test (70.act:20) +In expanding :: +Error on or near line number 30. +FATAL: Inconsistent/missing method + Method `test', interface `foo<>': arg #0 type mismatch diff --git a/act/test/types/runs/70.act.stdout b/act/test/types/runs/70.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/71.act.stderr b/act/test/types/runs/71.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/71.act.stdout b/act/test/types/runs/71.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/72.act.stderr b/act/test/types/runs/72.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/types/runs/72.act.stdout b/act/test/types/runs/72.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/userdef/82.act b/act/test/userdef/82.act new file mode 100644 index 00000000..ff2601a0 --- /dev/null +++ b/act/test/userdef/82.act @@ -0,0 +1,21 @@ +export deftype blah (int w) +{ + methods { + macro delay(int x) { + *[ x > 0 -> x := x - 1 ] + } + } +} + +defproc test() +{ + blah b; + int w; + + chp { + w := 100; + b.delay (w) + } +} + +test t; diff --git a/act/test/userdef/83.act b/act/test/userdef/83.act new file mode 100644 index 00000000..a347eb0e --- /dev/null +++ b/act/test/userdef/83.act @@ -0,0 +1,24 @@ +pint w=3; + +template deftype struct ( + int a; + int b; + int c +){} + +defproc test(){ + +int flat0; +struct str; + + chp{ + log("running"); + str.a:=1; + str.b:=int(2,1); + str.c:=1; + log("str.a: ",str.a,"%b str.b: ",str.b," str.c: ",str.c); + + flat0:=int(str); + log("%bflat0: ",flat0) + } +} diff --git a/act/test/userdef/84.act b/act/test/userdef/84.act new file mode 100644 index 00000000..d94181e4 --- /dev/null +++ b/act/test/userdef/84.act @@ -0,0 +1,30 @@ +deftype MyInnerType(int<16> a, b) { + methods { + function serialize() : int<32> { + chp { + self := a << 16 | b + } + } + } +} + +deftype MyOuterType(MyInnerType inner) { + methods { + function serialize() : int<32> { + chp { + self := inner.serialize() + } + } + } +} + +defproc test() { + MyInnerType ti; + MyOuterType to; + chp { + ti := MyInnerType(0x23 << 16 | 0x18); + to := MyOuterType(ti); + log("%x", ti.serialize()); + log("%x", to.serialize()) + } +} diff --git a/act/test/userdef/85.act b/act/test/userdef/85.act new file mode 100644 index 00000000..bf89af18 --- /dev/null +++ b/act/test/userdef/85.act @@ -0,0 +1,30 @@ +deftype MyInnerType(int<16> a, b) { + methods { + function serialize() : int<32> { + chp { + self := a << 16 | b + } + } + } +} + +deftype MyOuterType(MyInnerType inner) { + methods { + function serialize() : int<32> { + chp { + self := inner.serialize() + } + } + } +} + +defproc test() { + MyInnerType ti; + MyOuterType to; + chp { + ti := MyInnerType(0x23 << 16 | 0x18); + to.inner := ti; + log("%x", ti.serialize()); + log("%x", to.serialize()) + } +} diff --git a/act/test/userdef/runs/82.act.stderr b/act/test/userdef/runs/82.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/userdef/runs/82.act.stdout b/act/test/userdef/runs/82.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/userdef/runs/83.act.stderr b/act/test/userdef/runs/83.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/userdef/runs/83.act.stdout b/act/test/userdef/runs/83.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/userdef/runs/84.act.stderr b/act/test/userdef/runs/84.act.stderr new file mode 100644 index 00000000..5f645f3b --- /dev/null +++ b/act/test/userdef/runs/84.act.stderr @@ -0,0 +1,3 @@ +ERROR: File `84.act', line 26, col 27 + Typechecking failed on expression! + Built-in macro `MyOuterType': argument has an incompatible type diff --git a/act/test/userdef/runs/84.act.stdout b/act/test/userdef/runs/84.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/test/userdef/runs/85.act.stderr b/act/test/userdef/runs/85.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/act/test/userdef/runs/85.act.stdout b/act/test/userdef/runs/85.act.stdout new file mode 100644 index 00000000..e69de29b diff --git a/act/treetypes.h b/act/treetypes.h index 5d987534..2acc9e77 100644 --- a/act/treetypes.h +++ b/act/treetypes.h @@ -201,6 +201,9 @@ typedef struct { int special_id; /* special ID! for user macros */ Scope *special_id_sc; /* scope (if any) */ + + /* set this to true if a chan ID is in the expression */ + bool allow_chan; } ActTree; diff --git a/act/typecheck.h b/act/typecheck.h index 2397e59e..32dcda5c 100644 --- a/act/typecheck.h +++ b/act/typecheck.h @@ -60,6 +60,7 @@ #define T_DATA_ENUM 0xb ///< an enum that is not an int #define T_PTYPE 0x10 ///< used when the expression is a type #define T_PSTRUCT 0x11 ///< used when the expression is a pstruct +#define T_IFACE 0x12 ///< used for interfaces #define T_MASK 0x1f ///< mask for the list of options @@ -122,15 +123,28 @@ int act_type_expr (Scope *s, Expr *e, int *width, int only_chan = 0); /** - * Used to type-check a variable + * Used to type-check a variable. If the subchan flag is set to true, + * this permits A. to pass typechecking when A is a channel + * whose data type is a structure, and is a valid field + * reference. In this case, the type of the variable is going to be a + * channel of type , where is the type of . * * @param s is the scope in which to peform the type-checking * @param id is the variable to be checked * @param xit is used to return the actual InstType * for the * identifier, if xit is non-NULL + * @param subchan if this is true, then chan.sub is permitted for + * structure channels, and returns chan(foo) where foo is the type of + * the sub field. * @return a T_... flag that describes the result of the checking */ -int act_type_var (Scope *s, ActId *id, InstType **xit); +int act_type_var_gen (Scope *s, ActId *id, InstType **xit, bool subchan); + +/** + * This definition wraps the general act_type_var call setting subchan + * to false. + */ +#define act_type_var(a,b,c) act_type_var_gen((a),(b),(c),false) /** * Used to type-check a channel operation. The channel operation is of @@ -223,9 +237,10 @@ InstType *act_expr_insttype (Scope *s, Expr *e, int *islocal, int only_chan); * @param id is the identifier * @param islocal is used to return 1 if the identifier is only * accessible within the local scope specified, 0 otherwise + * @param subchan has the same meaning as act_type_var_gen * @return the type of the identifier (NULL if not found) */ -InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal); +InstType *act_actual_insttype (Scope *s, ActId *id, int *islocal, bool subchan); /** * Used to record the line, column, and file for error reporting diff --git a/act/typefactory.cc b/act/typefactory.cc index 67e705b8..b8de1aee 100644 --- a/act/typefactory.cc +++ b/act/typefactory.cc @@ -465,6 +465,9 @@ int TypeFactory::isValidChannelDataType (const Type *t) /* is an int/enum/bool */ return 1; } + if (isEnum (t)) { + return 1; + } if (!isStructure (t)) { return 0; } diff --git a/act/types.cc b/act/types.cc index 3c1cc6b6..16071412 100644 --- a/act/types.cc +++ b/act/types.cc @@ -329,7 +329,8 @@ UserDef::UserDef (ActNamespace *ns) file = NULL; lineno = 0; - has_refinement = 0; + has_refinement = NULL; + parent_refinement = NULL; inherited_templ = 0; inherited_param = NULL; @@ -425,6 +426,7 @@ void UserDef::MkCopy (UserDef *u) file = u->file; lineno = u->lineno; has_refinement = u->has_refinement; + parent_refinement = u->parent_refinement; inherited_templ = u->inherited_templ; inherited_param = u->inherited_param; @@ -493,6 +495,7 @@ void UserDef::Clone (UserDef *u) file = string_cache (u->file); lineno = u->lineno; has_refinement = list_dup (u->has_refinement); + parent_refinement = list_dup (u->parent_refinement); inherited_templ = u->inherited_templ; @@ -634,6 +637,7 @@ Data::Data (UserDef *u) : UserDef (u) is_eint = 0; b = NULL; enum_vals = NULL; + ifaces = NULL; for (i=0; i < ACT_NUM_STD_METHODS; i++) { methods[i] = NULL; @@ -711,6 +715,9 @@ int UserDef::isEqual (const UserDef *u) const static int recursion_depth = 0; +int _act_inc_rec_depth () { recursion_depth++; return recursion_depth; } +void _act_dec_rec_depth() { recursion_depth--; } + /*------------------------------------------------------------------------ * * Expand user-defined type! @@ -726,9 +733,9 @@ UserDef *UserDef::Expand (ActNamespace *ns, Scope *s, InstType *x, *p; Array *xa; - recursion_depth++; + int recval = _act_inc_rec_depth(); - if (recursion_depth >= Act::max_recurse_depth) { + if (recval >= Act::max_recurse_depth) { act_error_ctxt (stderr); fatal_error ("Exceeded maximum recursion depth of %d\n", Act::max_recurse_depth); } @@ -755,6 +762,7 @@ UserDef *UserDef::Expand (ActNamespace *ns, Scope *s, ux->file = file; ux->lineno = lineno; ux->has_refinement = has_refinement; + ux->parent_refinement = parent_refinement; if (defined) { ux->MkDefined(); @@ -785,11 +793,16 @@ UserDef *UserDef::Expand (ActNamespace *ns, Scope *s, int ii = 0; for (i=0; i < nt; i++) { - p = getPortType (-(i+1)); + p = getPortType (-(i+1)); Assert (p, "What?"); x = p->Expand (ns, ux->I); // this is the real type of the // parameter + if (x->arrayInfo() && x->arrayInfo()->size() == 0) { + // we just skip this one! + continue; + } + if (x->arrayInfo() && x->arrayInfo()->size() == 0) { act_error_ctxt (stderr); fatal_error ("Template parameter `%s': zero-length array creation not permitted", getPortName (-(i+1))); @@ -1166,7 +1179,7 @@ UserDef *UserDef::Expand (ActNamespace *ns, Scope *s, FREE (buf); /* we found one! */ delete ux; - recursion_depth--; + _act_dec_rec_depth (); *cache_hit = 1; return uy; } @@ -1200,8 +1213,43 @@ UserDef *UserDef::Expand (ActNamespace *ns, Scope *s, /*-- create ports --*/ for (int i=0; i < nports; i++) { InstType *chk; - Assert (ux->AddPort ((chk = getPortType(i)->Expand (ns, ux->I)), - getPortName (i)), "What?"); + chk = getPortType(i)->Expand (ns, ux->I); + + if (chk->arrayInfo() && chk->arrayInfo()->size() == 0) { + // skip the port! + continue; + } + + + /* + * XXX: This really needs to be "if this is a real type rather + * than part of an interface". Examples of "part of an interface" + * are interfaces themselves or functions within interfaces. + */ + if (is_proc != 2 && TypeFactory::isInterfaceType (chk)) { + /* this means that this was a ptype... we need to do more work */ + const char *pt = chk->getPTypeID(); + Assert (pt, "PType ID missing!"); + ValueIdx *vx = ux->CurScope()->LookupVal (pt); + Assert (vx, "PType ID not found?"); + if (!vx->init || !ux->CurScope()->issetPType (vx->u.idx)) { + act_error_ctxt (stderr); + fatal_error ("Ptype `%s' used to instantiate `%s' is not set", pt, + getPortName (i)); + } + + InstType *x = new InstType (ux->CurScope()->getPType (vx->u.idx)); + x->MkCached (); + x->setIfaceType (chk); + if (chk->arrayInfo()) { + x->MkArray (chk->arrayInfo()); + } + Assert (ux->AddPort (x, getPortName (i)), "Should succeed!"); + chk = x; + } + else { + Assert (ux->AddPort (chk, getPortName (i)), "Should succeed; what happened?!"); + } if (chk->arrayInfo() && chk->arrayInfo()->size() == 0) { act_error_ctxt (stderr); @@ -1266,7 +1314,9 @@ UserDef *UserDef::Expand (ActNamespace *ns, Scope *s, } ux->pending = 0; - recursion_depth--; + + _act_dec_rec_depth (); + return ux; } @@ -1303,8 +1353,31 @@ Data *Data::Expand (ActNamespace *ns, Scope *s, int nt, inst_param *u) xd->enum_vals = list_dup (enum_vals); } + if (ifaces) { + listitem_t *li; + xd->ifaces = list_new (); + for (li = list_first (ifaces); li; li = list_next (li)) { + InstType *iface = (InstType *)list_value (li); + Assert (list_next (li), "What?"); + list_t *lmap = (list_t *)list_value (list_next (li)); + li = list_next (li); + list_append (xd->ifaces, iface->Expand (ns, xd->I)); + list_append (xd->ifaces, lmap); + } + } + else { + xd->ifaces = NULL; + } + /*-- expand macros --*/ + int recval = _act_inc_rec_depth (); + + if (recval >= Act::max_recurse_depth) { + act_error_ctxt (stderr); + fatal_error ("Exceeded maximum recursion depth of %d\n", Act::max_recurse_depth); + } + /*-- do this in two phases: first, the built-in ones! --*/ for (int i=0; i < A_LEN (um); i++) { if (um[i]->isBuiltinMacro()) { @@ -1328,6 +1401,14 @@ Data *Data::Expand (ActNamespace *ns, Scope *s, int nt, inst_param *u) } } + const char *ret = xd->validateInterfaces (); + if (ret) { + act_error_ctxt (stderr); + fatal_error ("Inconsistent/missing method\n\t%s", ret); + } + + _act_dec_rec_depth (); + return xd; } @@ -1424,7 +1505,24 @@ Interface *Interface::Expand (ActNamespace *ns, Scope *s, int nt, inst_param *u) xd = new Interface (ux); delete ux; + int recval = _act_inc_rec_depth (); + + if (recval >= Act::max_recurse_depth) { + act_error_ctxt (stderr); + fatal_error ("Exceeded maximum recursion depth of %d\n", Act::max_recurse_depth); + } + Assert (_ns->EditType (xd->name, xd) == 1, "What?"); + + /*-- expand macros --*/ + for (int i=0; i < A_LEN (um); i++) { + A_NEW (xd->um, UserMacro *); + A_NEXT (xd->um) = um[i]->Expand (xd, ns, xd->I, 1); + A_INC (xd->um); + } + + _act_dec_rec_depth (); + return xd; } @@ -1450,7 +1548,6 @@ const char *PType::getName () return name; } - PStruct *PStruct::Expand (ActNamespace *ns, Scope *s, int _nt, inst_param *u) { if (nt < _nt) { @@ -1458,25 +1555,30 @@ PStruct *PStruct::Expand (ActNamespace *ns, Scope *s, int _nt, inst_param *u) fatal_error ("PStruct being expanded; too many parameters (%d v/s %d).", nt, _nt); } - PStruct *xd; - UserDef *ux; - int cache_hit; - if (isExpanded() && _nt == 0) { return this; } - ux = UserDef::Expand (ns, s, _nt, u, &cache_hit); + recursion_depth++; - if (cache_hit) { - return dynamic_cast(ux); + if (recursion_depth >= Act::max_recurse_depth) { + act_error_ctxt (stderr); + fatal_error ("Exceeded maximum recursion depth of %d\n", Act::max_recurse_depth); + } + + // in place expansion + I->FlushExpand (); + pending = 1; + expanded = 1; + for (int i =0; i < nt; i++) { + pt[i] = pt[i]->Expand (ns, s); + pt[i]->MkCached (); + I->Add (pn[i], pt[i]); } - xd = new PStruct (ux); - delete ux; - - Assert (_ns->EditType (xd->name, xd) == 1, "What?"); - return xd; + pending = 0; + recursion_depth--; + return this; } @@ -2724,23 +2826,79 @@ void Data::synthStructMacro () void UserDef::_apply_ref_overrides (ActBody *b, ActBody *srch) { + list_t *ol = NULL; + while (srch) { ActBody_Lang *l = dynamic_cast (srch); if (l) { if (l->gettype() == ActBody_Lang::LANG_REFINE) { act_refine *r = (act_refine *) l->getlang(); - if (acceptRefine (ActNamespace::Act()->getRefSteps(), r->nsteps) && - r->overrides) { - refine_override *rl = r->overrides; - /* apply overrides! */ + if (acceptRefine (ActNamespace::Act()->getRefSteps(), r->nsteps)) { + listitem_t *oi, *oprev; + if (!ol) { + ol = list_new (); + } + + /* insert the override into a sorted list of refinement levels */ + oi = list_first (ol); + oprev = NULL; + while (oi) { + act_refine *rl = (act_refine *) list_value (oi); + if (r->nsteps < rl->nsteps) { + if (!oprev) { + list_append_head (ol, r); + break; + } + else { + listitem_t *xtl = list_tail (ol); + list_append (ol, r); + list_tail (ol)->next = oi; + oprev->next = list_tail (ol); + list_tail (ol) = xtl; + xtl->next = NULL; + break; + } + } + oprev = oi; + oi = list_next (oi); + } + if (!oi) { + list_append (ol, r); + } + } + } + } + srch = srch->Next(); + } + /* apply overrides in refinement order */ + if (ol) { + for (listitem_t *oi = list_first (ol); oi; oi = list_next (oi)) { + act_refine *ri = (act_refine *) list_value (oi); + refine_override *rl = ri->overrides; + + while (rl) { + b->updateInstType (rl->ids, rl->it, false); + rl = rl->next; + } + + /* also propagate the refinement to the bodies of the earlier + refinement bodies! */ + + /** XXX: this doesn't correctly handle nested refinement blocks **/ + if (ri->overrides) { + for (listitem_t *op = list_first (ol); op != oi; op = list_next (op)) { + act_refine *rp = (act_refine *) list_value (op); + rl = ri->overrides; + Assert (rp->nsteps <= ActNamespace::Act()->getRefSteps(), "What?"); + ActNamespace::Act()->decRefSteps (rp->nsteps); while (rl) { - b->updateInstType (rl->ids, rl->it); + rp->b->updateInstType (rl->ids, rl->it, true); rl = rl->next; } + ActNamespace::Act()->incRefSteps (rp->nsteps); } } } - srch = srch->Next(); } } @@ -2917,3 +3075,176 @@ void UserDef::updateClonedTypes (ActNamespace */*root*/, { Assert (0, "This should not be called!"); } + + +void Data::addIface (InstType *iface, list_t *lmap) +{ + if (!ifaces) { + ifaces = list_new (); + } + list_append (ifaces, iface); + list_append (ifaces, lmap); +} + +int Data::hasIface (InstType *x, int weak) +{ + listitem_t *li; + if (!ifaces) return 0; + for (li = list_first (ifaces); li; li = list_next (li)) { + InstType *itmp = (InstType *)list_value (li); + Assert (itmp, "What?"); + Interface *tmp = dynamic_cast (itmp->BaseType()); + Assert (tmp, "What?"); + if (itmp->isEqual (x, weak)) { + return 1; + } + li = list_next (li); + } + return 0; +} + +list_t *Data::findMap (InstType *x) +{ + listitem_t *li; + + if (!ifaces) return NULL; + + Array *xtmp = x->arrayInfo(); + x->clrArray(); + + for (li = list_first (ifaces); li; li = list_next (li)) { + InstType *itmp = (InstType *)list_value (li); + Assert (itmp, "What?"); + Interface *tmp = dynamic_cast (itmp->BaseType()); + Assert (tmp, "What?"); + + if (itmp->isEqual (x)) { + x->MkArray (xtmp); + return (list_t *)list_value (list_next (li)); + } + li = list_next (li); + } + x->MkArray (xtmp); + return NULL; +} + +const char *Data::validateInterfaces () +{ + if (!ifaces) return NULL; + listitem_t *li; + for (li = list_first (ifaces); li; li = list_next (li)) { + InstType *x = (InstType *) list_value (li); + Interface *ix = dynamic_cast (x->BaseType()); + Assert (ix, "What?!"); + + // now typecheck macros + const char *ret = ix->validateMacros (this, um, A_LEN (um)); + if (ret) { + return ret; + } + + li = list_next (li); + } + return NULL; +} + +void Interface::Print (FILE *fp) +{ + PrintHeader (fp, "interface"); + if (A_LEN (um) > 0) { + fprintf (fp, "\n{ methods {\n"); + for (int i=0; i < A_LEN (um); i++) { + um[i]->Print (fp, true); + } + fprintf (fp, " }\n}\n"); + } + else { + fprintf (fp, ";\n"); + } +} + +const char *Interface::validateMacros (UserDef *u, UserMacro **macros, int count) +{ + static char buf[1024]; + int len; + // we have to try type substitutions for the interface name with the + // specified type name! + for (int i=0; i < A_LEN (um); i++) { + int idx; + int err; + for (idx=0; idx < count; idx++) { + if (strcmp (macros[idx]->getName(), um[i]->getName()) == 0) { + break; + } + } + + if (idx == count) { + snprintf (buf, 1024, "Method `%s' from interface '%s' is missing.", + um[i]->getName(), getName()); + return buf; + } + + /* now check that um[i] and macros[idx] match up! */ + if (um[i]->getNumPorts() != macros[idx]->getNumPorts()) { + snprintf (buf, 1024, "Method `%s', interface `%s': mismatch in port count (%d vs %d)", + um[i]->getName (), getName(), + um[i]->getNumPorts(), macros[idx]->getNumPorts()); + return buf; + } + + + /* match the types for each of the arguments as well as the return value */ + err = 0; + for (int j=0; j < um[i]->getNumPorts(); j++) { + /* 1. normal test for typechecking connections, and + 2. stricter check: the interface must be the same as the type + */ +#define _TYPEMATCH(t1,t2) \ + do { \ + if (TypeFactory::isInterfaceType (t1)) { \ + InstType *tmp = new InstType (u->CurScope(), u); \ + if (!type_connectivity_check ((t2), tmp) || \ + (!u->isEqual ((t2)->BaseType()))) { \ + delete tmp; \ + err = 1; \ + } \ + delete tmp; \ + } \ + else { \ + if (!type_connectivity_check (t1, t2)) { \ + err = 1; \ + } \ + } \ + } while (0) + _TYPEMATCH(um[i]->getPortType (j), macros[idx]->getPortType (j)); + if (err) { + snprintf (buf, 1024, "Method `%s', interface `%s': arg #%d type mismatch", + um[i]->getName (), getName(), j); + return buf; + } + } + + if (um[i]->getRetType()) { + if (!macros[idx]->getRetType()) { + snprintf (buf, 1024, "Method `%s', interface `%s': macro/function inconsistency", + um[i]->getName(), getName()); + return buf; + } + _TYPEMATCH (um[i]->getRetType(), macros[idx]->getRetType()); + if (err) { + snprintf (buf, 1024, "Method `%s', interface `%s': return type mismatch", + um[i]->getName (), getName()); + return buf; + } + } + else { + if (macros[idx]->getRetType()) { + snprintf (buf, 1024, "Method `%s', interface `%s': macro/function inconsistency", + um[i]->getName(), getName()); + return buf; + } + } +#undef _TYPEMATCH + } + return NULL; +} diff --git a/act/types.h b/act/types.h index 03b4d980..e10be934 100644 --- a/act/types.h +++ b/act/types.h @@ -729,18 +729,66 @@ class UserDef : public Type { void setRefineList(list_t *l) { has_refinement = l; } bool acceptRefine (int refsteps, int mysteps) { +#if 0 listitem_t *li; int k = 0; +#endif if (!has_refinement) { return false; } + if (refsteps >= mysteps) return true; +#if 0 + /* old refinement rule */ li = list_first (has_refinement); while (li && list_ivalue (li) <= refsteps) { k = list_ivalue (li); li = list_next (li); } if (k == mysteps) return true; +#endif + return false; + } + + + /** + * Parent list, used to check for additional refinements + */ + void pushRefine (int steps, list_t *reflist) { + if (!parent_refinement) { + parent_refinement = list_new (); + } + list_append_head (parent_refinement, reflist); + list_iappend_head (parent_refinement, steps); + } + + void popRefine () { + list_delete_head (parent_refinement); + list_delete_head (parent_refinement); + } + + /** + * Check parent list to see if futher refinements are possible + */ + bool moreRefinesExist (int steps) { + listitem_t *li; + + if (!parent_refinement) return false; + + for (li = list_first (parent_refinement); li; li = list_next (li)) { + int v = list_ivalue (li); + li = list_next (li); + list_t *rlist = (list_t *) list_value (li); + steps += v; + + for (listitem_t *mi = list_first (rlist); mi; mi = list_next (mi)) { + // the refinement would be accepted, and this is a higher + // level of refinement than the current one. + if (steps >= list_ivalue (mi) && v < list_ivalue (mi)) { + return true; + } + } + } return false; } @@ -814,6 +862,7 @@ class UserDef : public Type { const char *file; ///< file name (if known) where this was defined int lineno; ///< line number (if known) where this was defined + list_t *parent_refinement; ///< stack of (refinement#, reflist) taken so far list_t *has_refinement; ///< list of refinement levels in this type int inherited_templ; ///< number of inherited template parameters @@ -852,6 +901,10 @@ class Interface : public UserDef { ActNamespace *newroot, UserDef *orig); Interface *Expand (ActNamespace *ns, Scope *s, int nt, inst_param *u); + + const char *validateMacros (UserDef *u, UserMacro **um, int n); + + void Print (FILE *fp); }; /** @@ -972,6 +1025,15 @@ class Process : public UserDef { */ int hasIface (InstType *x, int weak); + /** + * Validate interfaces exported to make sure any macros/methods are + * defined. + * + * @return macro name that caused the error, if any. NULL return + * value means success. + */ + const char *validateInterfaces (); + /** * @return the port name map for the interface exported by this * process @@ -1163,6 +1225,13 @@ class Function : public UserDef { } return false; } + + /** + * The user-defined types in the function argument list are all + * template parameters; convert them from the port list to the + * template list. + */ + void convPortsToParams (); private: InstType *ret_type; ///< holds return type @@ -1404,7 +1473,41 @@ class Data : public UserDef { */ void synthStructMacro (); + /** + * Add an interface specification that this process exports. Note + * that a process can export multiple interfaces. + * + * @param iface is the interface exported + * @param imap is the name mapping from the process ports to the + * interface ports + */ + void addIface (InstType *iface, list_t *imap); + + /** + * Weak check for interface equality + */ + int hasIface (InstType *x, int weak); + + /** + * Validate interfaces exported to make sure any macros/methods are + * defined. + * + * @return macro name that caused the error, if any. NULL return + * value means success. + */ + const char *validateInterfaces (); + + /** + * @return the port name map for the interface exported by this + * type + */ + list_t *findMap (InstType *iface); + private: + list_t *ifaces; ///< a mixed list of interface, map + ///pairs. The map is also a list of + ///oldname, newname pairs + void _get_struct_count (int *nbools, int *nints); void _get_struct_fields (ActId **a, int *types, int *pos, ActId *prefix); @@ -1554,7 +1657,7 @@ class UserMacro { UserMacro (UserDef *u, const char *name); ~UserMacro (); - void Print (FILE *fp); + void Print (FILE *fp, bool header_only = false); /** * Expand a user-defined macro. The is_proc flag is used because @@ -2217,7 +2320,6 @@ class TypeFactory { /** * A UserDef that is a Data type can hold a structure. A data type * is a structure when it does not implement a built-in data type. - * Note that currently structures cannot contain arrays. * @return 1 if this is a structure, 0 otherwise */ static int isStructure (const Type *t); diff --git a/act/types.m4 b/act/types.m4 index d10c176b..52e2a65b 100644 --- a/act/types.m4 +++ b/act/types.m4 @@ -182,7 +182,7 @@ chan_type[InstType *]: "chan" [ chan_dir ] "(" physical_inst_type [ "," physical } if (!TypeFactory::isValidChannelDataType (t) || (ack && !TypeFactory::isValidChannelDataType (ack))) { - $e("User-defined channel data type must be a structure with pure data.\n"); + $e("User-defined channel data type must be a structure with pure data or enumeration.\n"); fprintf ($f, "\tType%s: ", ack ? "s" : ""); t->Print ($f); if (ack) { @@ -230,7 +230,13 @@ physical_inst_type[InstType *]: data_type | user_type {{X: if (TypeFactory::isInterfaceType ($1) && !$0->ptype_expand) { - $E("An interface type cannot be used in this context"); + if (TypeFactory::isInterfaceType ($1) && + $0->u_i && $0->u_i->isEqual ($1->BaseType())) { + /* F-bounded polymorphism! */ + } + else { + $E("An interface type cannot be used in this context"); + } } $0->ptype_expand = 0; return $1; diff --git a/act/wrap.cc b/act/wrap.cc index f1b8057b..3aedd4b6 100644 --- a/act/wrap.cc +++ b/act/wrap.cc @@ -286,7 +286,8 @@ static Expr *_check_overload (ActTree *cookie, Expr *e, const char *nm) if (!e) return e; if (act_expr_could_be_struct (e->u.e.l)) { InstType *it = act_expr_insttype (cookie->scope, e->u.e.l, NULL, 2); - if (it && TypeFactory::isPureStruct (it)) { + if (it && + (TypeFactory::isPureStruct (it) || TypeFactory::isInterfaceType (it))) { struct act_position p; p.l = cookie->line; p.c = cookie->column; @@ -336,7 +337,8 @@ static Expr *_check_overload_bool (ActTree *cookie, Expr *e, const char *nm) if (!e) return e; if (act_expr_could_be_struct (e->u.e.l)) { InstType *it = act_expr_insttype (cookie->scope, e->u.e.l, NULL, 2); - if (it && TypeFactory::isPureStruct (it)) { + if (it && + (TypeFactory::isPureStruct (it) || TypeFactory::isInterfaceType (it))) { struct act_position p; p.l = cookie->line; p.c = cookie->column; @@ -887,14 +889,19 @@ Expr *act_walk_X_expr (ActTree *cookie, Expr *e) u = NULL; prev = NULL; while (tmp->Rest()) { - it = sc->Lookup (tmp->getName()); + it = sc->FullLookup (tmp->getName()); if (!it) { act_parse_err (&p, "Field `%s' not found!", tmp->getName()); } u = dynamic_cast (it->BaseType()); if (!u) { - act_parse_err (&p, "Field `%s' isn't a user-defined type", - tmp->getName()); + if (cookie->allow_chan && TypeFactory::isChanType (it->BaseType())) { + u = dynamic_cast (TypeFactory::getChanDataType (it)->BaseType()); + } + if (!u) { + act_parse_err (&p, "Field `%s' isn't a user-defined type", + tmp->getName()); + } } sc = u->CurScope(); prev = tmp; diff --git a/miniscm/lispA-Z.h b/miniscm/lispA-Z.h index e560a07d..d436e755 100644 --- a/miniscm/lispA-Z.h +++ b/miniscm/lispA-Z.h @@ -37,106 +37,94 @@ /* * predicates */ -extern LispObj *LispIsBool (); -extern LispObj *LispIsSym (); -extern LispObj *LispIsList (); -extern LispObj *LispIsPair (); -extern LispObj *LispIsNumber (); -extern LispObj *LispIsString (); -extern LispObj *LispIsProc (); -extern LispObj *LispEqv (); +extern LispObj *LispIsBool (char *, Sexp *, Sexp *); +extern LispObj *LispIsSym (char *, Sexp *, Sexp *); +extern LispObj *LispIsList (char *, Sexp *, Sexp *); +extern LispObj *LispIsPair (char *, Sexp *, Sexp *); +extern LispObj *LispIsNumber (char *, Sexp *, Sexp *); +extern LispObj *LispIsString (char *, Sexp *, Sexp *); +extern LispObj *LispIsProc (char *, Sexp *, Sexp *); +extern LispObj *LispEqv (char *, Sexp *, Sexp *); /* * lists */ -extern LispObj *LispCar (); -extern LispObj *LispCdr (); -extern LispObj *LispCons (); -extern LispObj *LispNull (); -extern LispObj *LispList (); -extern LispObj *LispLength (); +extern LispObj *LispCar (char *, Sexp *, Sexp *); +extern LispObj *LispCdr (char *, Sexp *, Sexp *); +extern LispObj *LispCons (char *, Sexp *, Sexp *); +extern LispObj *LispNull (char *, Sexp *, Sexp *); +extern LispObj *LispList (char *, Sexp *, Sexp *); +extern LispObj *LispLength (char *, Sexp *, Sexp *); /* * controlling evaluation */ -extern LispObj *LispQuote (); -extern LispObj *Lispeval (); -extern LispObj *LispLambda (); -extern LispObj *Lispapply (); +extern LispObj *LispQuote (char *, Sexp *, Sexp *); +extern LispObj *Lispeval (char *, Sexp *, Sexp *); +extern LispObj *LispLambda (char *, Sexp *, Sexp *); +extern LispObj *Lispapply (char *, Sexp *, Sexp *); /* * definitions and side-effects */ -extern LispObj *LispDefine (); -extern LispObj *LispSetBang (); -extern LispObj *LispLet (); -extern LispObj *LispLetRec (); -extern LispObj *LispLetStar (); -extern LispObj *LispSetCarBang (); -extern LispObj *LispSetCdrBang (); +extern LispObj *LispDefine (char *, Sexp *, Sexp *); +extern LispObj *LispSetBang (char *, Sexp *, Sexp *); +extern LispObj *LispLet (char *, Sexp *, Sexp *); +extern LispObj *LispLetRec (char *, Sexp *, Sexp *); +extern LispObj *LispLetStar (char *, Sexp *, Sexp *); +extern LispObj *LispSetCarBang (char *, Sexp *, Sexp *); +extern LispObj *LispSetCdrBang (char *, Sexp *, Sexp *); /* * arithmetic */ -extern LispObj *LispAdd (); -extern LispObj *LispSub (); -extern LispObj *LispMult (); -extern LispObj *LispDiv (); -extern LispObj *LispTruncate (); -extern LispObj *LispZeroQ (); -extern LispObj *LispPositiveQ (); -extern LispObj *LispNegativeQ (); +extern LispObj *LispAdd (char *, Sexp *, Sexp *); +extern LispObj *LispSub (char *, Sexp *, Sexp *); +extern LispObj *LispMult (char *, Sexp *, Sexp *); +extern LispObj *LispDiv (char *, Sexp *, Sexp *); +extern LispObj *LispTruncate (char *, Sexp *, Sexp *); +extern LispObj *LispZeroQ (char *, Sexp *, Sexp *); +extern LispObj *LispPositiveQ (char *, Sexp *, Sexp *); +extern LispObj *LispNegativeQ (char *, Sexp *, Sexp *); /* * control flow */ -extern LispObj *LispBegin (); -extern LispObj *LispIf (); -extern LispObj *LispCond (); +extern LispObj *LispBegin (char *, Sexp *, Sexp *); +extern LispObj *LispIf (char *, Sexp *, Sexp *); +extern LispObj *LispCond (char *, Sexp *, Sexp *); /* * debugging */ -extern LispObj *LispShowFrame (); -extern LispObj *LispDisplayObj (); -extern LispObj *LispPrintObj (); -extern LispObj *LispError (); +extern LispObj *LispShowFrame (char *, Sexp *, Sexp *); +extern LispObj *LispDisplayObj (char *, Sexp *, Sexp *); +extern LispObj *LispPrintObj (char *, Sexp *, Sexp *); +extern LispObj *LispError (char *, Sexp *, Sexp *); /* * I/O */ -extern LispObj *LispLoad (); -extern LispObj *LispWrite (); -extern LispObj *LispSpawn (); -extern LispObj *LispWait (); +extern LispObj *LispLoad (char *, Sexp *, Sexp *); +extern LispObj *LispWrite (char *, Sexp *, Sexp *); +extern LispObj *LispSpawn (char *, Sexp *, Sexp *); +extern LispObj *LispWait (char *, Sexp *, Sexp *); /* * utilities */ -extern LispObj *LispCollectGarbage (); +extern LispObj *LispCollectGarbage (char *, Sexp *, Sexp *); /* * String functions */ -extern LispObj *LispStrCat (); -extern LispObj *LispSymbolToString (); -extern LispObj *LispStringToSymbol (); -extern LispObj *LispNumberToString (); -extern LispObj *LispStringToNumber (); -extern LispObj *LispStringLength (); -extern LispObj *LispStringCompare (); -extern LispObj *LispStringRef (); -extern LispObj *LispStringSet (); -extern LispObj *LispSubString (); - -/* - * magic interaction - */ -extern LispObj *LispGetPaint (); -extern LispObj *LispGetSelPaint (); -extern LispObj *LispGetbox (); -extern LispObj *LispGetPoint (); -extern LispObj *LispGetLabel (); -extern LispObj *LispGetSelLabel (); -extern LispObj *LispGetCellNames (); -extern LispObj *LispEvalMagic (); +extern LispObj *LispStrCat (char *, Sexp *, Sexp *); +extern LispObj *LispSymbolToString (char *, Sexp *, Sexp *); +extern LispObj *LispStringToSymbol (char *, Sexp *, Sexp *); +extern LispObj *LispNumberToString (char *, Sexp *, Sexp *); +extern LispObj *LispStringToNumber (char *, Sexp *, Sexp *); +extern LispObj *LispStringLength (char *, Sexp *, Sexp *); +extern LispObj *LispStringCompare (char *, Sexp *, Sexp *); +extern LispObj *LispStringRef (char *, Sexp *, Sexp *); +extern LispObj *LispStringSet (char *, Sexp *, Sexp *); +extern LispObj *LispSubString (char *, Sexp *, Sexp *); diff --git a/miniscm/lispEval.c b/miniscm/lispEval.c index 3570fa6a..d4e2f4b9 100644 --- a/miniscm/lispEval.c +++ b/miniscm/lispEval.c @@ -212,7 +212,7 @@ LispAddDynamicFunc (char *name, void *f) } for (i=0; i < DyTableNum; i++) { if (DyTable[i].id == id) { - DyTable[i].f = (LispObj *(*)())f; + DyTable[i].f = (LispObj *(*)(char *, Sexp *))f; return 1; } } @@ -228,7 +228,7 @@ LispAddDynamicFunc (char *name, void *f) } DyTable[DyTableNum].name = Strdup (name); DyTable[DyTableNum].id = id; - DyTable[DyTableNum].f = (LispObj *(*)()) f; + DyTable[DyTableNum].f = (LispObj *(*)(char *, Sexp *)) f; DyTableNum++; return 1; } diff --git a/passes/cells/cells.cc b/passes/cells/cells.cc index 4ca43565..5d744d6c 100644 --- a/passes/cells/cells.cc +++ b/passes/cells/cells.cc @@ -996,10 +996,12 @@ void ActCellPass::flush_pending (Scope *sc) //ac->Next()->Print (stdout); //printf (" --- \n"); - int oval = Act::double_expand; - Act::double_expand = 0; - ac->Expandlist (NULL, sc); - Act::double_expand = oval; + if (ac) { + int oval = Act::double_expand; + Act::double_expand = 0; + ac->Expandlist (NULL, sc); + Act::double_expand = oval; + } //printf ("---\n"); } A_FREE (groupprs); @@ -2299,6 +2301,11 @@ ActBody_Conn *ActCellPass::_build_connections (const char *name, Expr *idexpr; i = pi->nout + pi->nat; + + if (i == pi->nvars) { + // no inputs, so nothing to connect to + return NULL; + } Assert (i < pi->nvars, "No inputs?"); idexpr = _idexpr (i, pi); @@ -2515,11 +2522,12 @@ void ActCellPass::_collect_one_prs (Scope *sc, act_prs_lang_t *prs) //ac->Next()->Print (stdout); //printf (" --- \n"); - - int oval = Act::double_expand; - Act::double_expand = 0; - ac->Expandlist (NULL, sc); - Act::double_expand = oval; + if (ac) { + int oval = Act::double_expand; + Act::double_expand = 0; + ac->Expandlist (NULL, sc); + Act::double_expand = oval; + } if (pi->match_perm) { FREE (pi->match_perm); @@ -2621,11 +2629,12 @@ void ActCellPass::_collect_one_passgate (Scope *sc, act_prs_lang_t *prs) //ac->Next()->Print (stdout); //printf (" --- \n"); - - int oval = Act::double_expand; - Act::double_expand = 0; - ac->Expandlist (NULL, sc); - Act::double_expand = oval; + if (ac) { + int oval = Act::double_expand; + Act::double_expand = 0; + ac->Expandlist (NULL, sc); + Act::double_expand = oval; + } } void ActCellPass::_collect_one_cap (Scope *sc, act_prs_lang_t *prs) @@ -2707,11 +2716,12 @@ void ActCellPass::_collect_one_cap (Scope *sc, act_prs_lang_t *prs) //ac->Next()->Print (stdout); //printf (" --- \n"); - - int oval = Act::double_expand; - Act::double_expand = 0; - ac->Expandlist (NULL, sc); - Act::double_expand = oval; + if (ac) { + int oval = Act::double_expand; + Act::double_expand = 0; + ac->Expandlist (NULL, sc); + Act::double_expand = oval; + } } @@ -3011,18 +3021,33 @@ int ActCellPass::_collect_cells (ActNamespace *cells) fatal_error ("Unexpected cell `%s' in cell namespace (has parameters?)", p->getName()); } - if (p->getNumPorts() != 2) { + if (p->getNumPorts() != 2 && p->getNumPorts() != 1) { fatal_error ("Cell `%s::%s': More than two ports", cell_ns->getName(), p->getName()); } - if ((strcmp (p->getPortName (0), _inport_name) != 0) || - (strcmp (p->getPortName (1), _outport_name) != 0)) { - fatal_error ("Cell `%s::%s': Ports should be in/out", - cell_ns->getName(), p->getName()); + if (p->getNumPorts() == 2) { + if ((strcmp (p->getPortName (0), _inport_name) != 0) || + (strcmp (p->getPortName (1), _outport_name) != 0)) { + fatal_error ("Cell `%s::%s': Ports should be in/out", + cell_ns->getName(), p->getName()); + } + } + else if (p->getNumPorts() == 1) { + if (strcmp (p->getPortName (0), _outport_name) != 0) { + fatal_error ("Cell `%s::%s': Ports should be in/out", + cell_ns->getName(), p->getName()); + } } InstType *in_t, *out_t; - in_t = p->getPortType (0); - out_t = p->getPortType (1); + + if (p->getNumPorts() == 2) { + in_t = p->getPortType (0); + out_t = p->getPortType (1); + } + else { + in_t = NULL; + out_t = p->getPortType (0); + } #if 0 int id, version; @@ -3036,7 +3061,7 @@ int ActCellPass::_collect_cells (ActNamespace *cells) /* in_t must be a bool array or bool out_t must be a bool array or bool */ - if (!TypeFactory::isBoolType (in_t) || !TypeFactory::isBoolType (out_t)) { + if ((in_t && !TypeFactory::isBoolType (in_t)) || !TypeFactory::isBoolType (out_t)) { fatal_error ("Cell `%s::%s': Port base types must `bool'", cell_ns->getName(), p->getName()); } @@ -3082,8 +3107,10 @@ int ActCellPass::_collect_cells (ActNamespace *cells) } /* fine. now dump into celldb */ - pi = _gen_prs_attributes (l, in_t->arrayInfo() ? - in_t->arrayInfo()->size() : 1, + pi = _gen_prs_attributes (l, + in_t ? + (in_t->arrayInfo() ? + in_t->arrayInfo()->size() : 1) : 0, out_t->arrayInfo() ? out_t->arrayInfo()->size() : 1); pi->leak_adjust = prs->leak_adjust; diff --git a/passes/finline/finline.cc b/passes/finline/finline.cc index aa449c4d..3dec9852 100644 --- a/passes/finline/finline.cc +++ b/passes/finline/finline.cc @@ -215,7 +215,10 @@ act_inline_value ActCHPFuncInline::_inline_funcs (list_t *l, Expr *e) case E_SELF: case E_SELF_ACK: case E_PROBE: + break; + case E_VAR: + retv.is_just_id = 1; break; default: @@ -268,10 +271,14 @@ act_inline_value ActCHPFuncInline::_inline_funcs_general (list_t *l, Expr *e) ACT_EXPR_EXFLAG_DUPONLY|ACT_EXPR_EXFLAG_CHPEX); arglist[args++] = _inline_funcs (l, ex); + // this computes a pure inlined expression value + // now we need to set various flags if (TypeFactory::isStructure (fx->getPortType (args-1))) { - arglist[args-1].is_struct_id = 1; arglist[args-1].is_struct = 1; } + if (fx->getPortType (args-1)->arrayInfo()) { + arglist[args-1].is_array = 1; + } Assert (arglist[args-1].isValid(), "What?"); tmp = tmp->u.e.r; } @@ -555,10 +562,98 @@ void ActCHPFuncInline::_inline_funcs (list_t *l, act_chp_lang_t *c) c->u.comm.e = val.getVal(); } else { - if (c->type == ACT_CHP_SEND && c->u.comm.e && - c->u.comm.e->type != E_VAR) { - /* XXX: check special case of function that returns a structure */ - warning ("Structure return value inlining for send data not currently supported!"); + if (c->u.comm.e && c->u.comm.e->type != E_VAR) { + /* unstructure this if needed */ + + act_inline_value vals = _inline_funcs_general (l, c->u.comm.e); + Data *d; + int *types; + int nb, ni; + + if (vals.isValid()) { + /* simple inline */ + char buf[1024]; + _cursc->findFresh ("_us_", &_inline_idx); + snprintf (buf, 1024, "_us_%d", _inline_idx); + _inline_idx++; + _cursc->Add (buf, cx->datatype()); + ActNamespace::Act()->addGeneratedVar (_cursc, _cursc->LookupVal (buf)); + ActId *myid = new ActId (buf); + + d = dynamic_cast (cx->datatype()->BaseType()); + Assert (d, "Hmm"); + ActId **fields = d->getStructFields (&types); + FREE (types); + d->getStructCount (&nb, &ni); + int sz = nb + ni; + list_t *l = list_new (); + + //Assert (!vals.isSimple(), "Hmm"); + + for (int i=0; i < sz; i++) { + act_chp_lang_t *tc; + + if (vals.isSimple()) { + NEW (tc, act_chp_lang_t); + tc->type = ACT_CHP_ASSIGN; + tc->label = NULL; + tc->space = NULL; + tc->u.assign.id = myid->Clone(); + tc->u.assign.id->Tail()->Append (fields[i]); + NEW (tc->u.assign.e, Expr); + tc->u.assign.e->u.e.r = NULL; + tc->u.assign.e->type = E_VAR; + // structure expression can only be an actual + // structure variable + Assert (vals.getVal()->type == E_VAR, "What?"); + ActId *tmp = ((ActId *)vals.getVal()->u.e.l)->Clone (); + tmp->Tail()->Append (fields[i]->Clone()); + tc->u.assign.e->u.e.l = (Expr *) tmp; + list_append (l, tc); + } + else { + if (vals.u.arr[i]) { + NEW (tc, act_chp_lang_t); + tc->type = ACT_CHP_ASSIGN; + tc->label = NULL; + tc->space = NULL; + tc->u.assign.id = myid->Clone(); + tc->u.assign.id->Tail()->Append (fields[i]); + tc->u.assign.e = vals.u.arr[i]; + list_append (l, tc); + } + else { + delete fields[i]; + } + } + } + FREE (fields); + { + act_chp_lang_t *tc; + NEW (tc, act_chp_lang_t); + tc->type = c->type; + tc->label = NULL; + tc->space = NULL; + tc->u.comm.chan = c->u.comm.chan; + tc->u.comm.var = c->u.comm.var; + tc->u.comm.flavor = c->u.comm.flavor; + tc->u.comm.convert = c->u.comm.convert; + + // replace orig + c->type = ACT_CHP_SEMI; + c->u.semi_comma.cmd = l; + + NEW (tc->u.comm.e, Expr); + tc->u.comm.e->type = E_VAR; + tc->u.comm.e->u.e.r = NULL; + tc->u.comm.e->u.e.l = (Expr *)myid; + list_append (l, tc); + } + } + else { + act_inline_value vx = _inline_funcs_general (l, c->u.comm.e); + Assert (!vx.isValid(), "What?"); + } } } } @@ -586,9 +681,10 @@ void ActCHPFuncInline::_inline_funcs (list_t *l, act_chp_lang_t *c) ActId *origid = c->u.assign.id; if (unstruct_me) { char buf[1024]; - int idx = _get_fresh_idx ("_us", &_inline_idx); - snprintf (buf, 1024, "_us_%d", idx); + _cursc->findFresh ("_us_", &_inline_idx); + snprintf (buf, 1024, "_us_%d", _inline_idx++); _cursc->Add (buf, it); + ActNamespace::Act()->addGeneratedVar (_cursc, _cursc->LookupVal (buf)); myid = new ActId (buf); } @@ -600,23 +696,43 @@ void ActCHPFuncInline::_inline_funcs (list_t *l, act_chp_lang_t *c) int sz = nb + ni; list_t *l = list_new (); - Assert (!vals.isSimple(), "Hmm"); - + //Assert (!vals.isSimple(), "Hmm"); + for (int i=0; i < sz; i++) { act_chp_lang_t *tc; - if (vals.u.arr[i]) { + if (vals.isSimple()) { NEW (tc, act_chp_lang_t); tc->type = ACT_CHP_ASSIGN; tc->label = NULL; tc->space = NULL; tc->u.assign.id = myid->Clone(); tc->u.assign.id->Tail()->Append (fields[i]); - tc->u.assign.e = vals.u.arr[i]; + NEW (tc->u.assign.e, Expr); + tc->u.assign.e->u.e.r = NULL; + tc->u.assign.e->type = E_VAR; + // structure expression can only be an actual + // structure variable + Assert (vals.getVal()->type == E_VAR, "What?"); + ActId *tmp = ((ActId *)vals.getVal()->u.e.l)->Clone (); + tmp->Tail()->Append (fields[i]->Clone()); + tc->u.assign.e->u.e.l = (Expr *) tmp; list_append (l, tc); } else { - delete fields[i]; + if (vals.u.arr[i]) { + NEW (tc, act_chp_lang_t); + tc->type = ACT_CHP_ASSIGN; + tc->label = NULL; + tc->space = NULL; + tc->u.assign.id = myid->Clone(); + tc->u.assign.id->Tail()->Append (fields[i]); + tc->u.assign.e = vals.u.arr[i]; + list_append (l, tc); + } + else { + delete fields[i]; + } } } FREE (fields); @@ -687,20 +803,6 @@ void ActCHPFuncInline::_inline_funcs (list_t *l, act_chp_lang_t *c) } } - -int ActCHPFuncInline::_get_fresh_idx (const char *prefix, int *idx) -{ - char tmpnm[1024]; - int i = *idx; - - do { - snprintf (tmpnm, 1024, "%s_%d", prefix, i++); - } while (_cursc->Lookup (tmpnm)); - *idx = i; - - return i-1; -} - /*------------------------------------------------------------------------ * * Complex inlines: functions with loops @@ -738,14 +840,14 @@ void ActCHPFuncInline::_do_complex_inline (struct pHashtable *Hargs, list_t *l, if (!b) { struct fn_inline_args *args; NEW (args, struct fn_inline_args); - int idx; args->fx = fx; - idx = _get_fresh_idx ("fret", &ret_idx); - snprintf (tmpnm, 1024, "fret_%d", idx); + _cursc->findFresh ("fret_", &ret_idx); + snprintf (tmpnm, 1024, "fret_%d", ret_idx++); args->ret = new ActId (tmpnm); Assert (_cursc->Add (tmpnm, fx->getRetType()), "What?"); - + ActNamespace::Act()->addGeneratedVar (_cursc, _cursc->LookupVal (tmpnm)); + if (fx->getNumPorts() > 0) { MALLOC (args->args, ActId *, fx->getNumPorts()); } @@ -753,10 +855,11 @@ void ActCHPFuncInline::_do_complex_inline (struct pHashtable *Hargs, list_t *l, args->args = NULL; } for (int i=0; i < fx->getNumPorts(); i++) { - idx = _get_fresh_idx ("farg", &arg_idx); - snprintf (tmpnm, 1024, "farg_%d", idx); + _cursc->findFresh ("farg_", &arg_idx); + snprintf (tmpnm, 1024, "farg_%d", arg_idx++); args->args[i] = new ActId (tmpnm); Assert (_cursc->Add (tmpnm, fx->getPortType (i)), "What?"); + ActNamespace::Act()->addGeneratedVar (_cursc, _cursc->LookupVal (tmpnm)); } b = phash_add (Hargs, fx); b->v = args; @@ -791,9 +894,10 @@ void ActCHPFuncInline::_do_complex_inline (struct pHashtable *Hargs, list_t *l, if (!args->local_vars) { args->local_vars = hash_new (4); } - idx = _get_fresh_idx ("floc", &local_idx); - snprintf (tmpnm, 1024, "floc_%d", idx); + _cursc->findFresh ("floc_", &local_idx); + snprintf (tmpnm, 1024, "floc_%d", local_idx++); Assert (_cursc->Add (tmpnm, vx->t), "What?"); + ActNamespace::Act()->addGeneratedVar (_cursc, _cursc->LookupVal (tmpnm)); ab = hash_add (args->local_vars, vx->getName()); ab->v = new ActId (tmpnm); } @@ -1343,6 +1447,8 @@ void ActCHPFuncInline::_apply_complex_inlines (list_t *l, Expr *e) return; } +static Expr *_expr_clone_subst (struct fn_inline_args *fn, Expr *e); + static ActId *_find_subst (struct fn_inline_args *fn, ActId *id) { ActId *repl; @@ -1371,6 +1477,20 @@ static ActId *_find_subst (struct fn_inline_args *fn, ActId *id) if (id && id->Rest()) { repl->Append (id->Rest()->Clone()); } + + /*-- there might be arrays here, so include them --*/ + if (id && id->arrayInfo()) { + Array *c = id->arrayInfo()->Clone (); + + /* substitute any array derefs here as well */ + for (int i=0; i < c->nDims(); i++) { + Expr *e = c->getDeref (i); + if (e->type != E_INT) { + c->setDeref (i, _expr_clone_subst (fn, e)); + } + } + repl->setArray (c); + } return repl; } @@ -1607,36 +1727,83 @@ act_chp_lang_t *ActCHPFuncInline::_do_inline (struct pHashtable *H, /* -- inline this function -- */ for (int i=0; i < fn->fx->getNumPorts(); i++) { - NEW (tmpc, act_chp_lang_t); - tmpc->label = NULL; - tmpc->space = NULL; - tmpc->type = ACT_CHP_ASSIGN; - tmpc->u.assign.id = fn->args[i]->Clone(); - tmpc->u.assign.e = req->args[i]; - list_append (c->u.semi_comma.cmd, tmpc); + + if (fn->fx->getPortType (i)->arrayInfo()) { + // array assignment! + Array *xa = fn->fx->getPortType (i)->arrayInfo(); + for (int j=0; j < xa->size(); j++) { + Array *a = xa->unOffset (j); + NEW (tmpc, act_chp_lang_t); + tmpc->label = NULL; + tmpc->space = NULL; + tmpc->type = ACT_CHP_ASSIGN; + tmpc->u.assign.id = fn->args[i]->Clone (); + tmpc->u.assign.id->setArray (a); + if (req->args[i]->type != E_VAR) { + act_error_ctxt (stderr); + fatal_error ("Failed in complex inline in the presence of arrays?"); + } + tmpc->u.assign.e = expr_dup (req->args[i]); + Assert (((ActId *)tmpc->u.assign.e->u.e.l)->arrayInfo() == NULL, + "Hmm..."); + ((ActId *)tmpc->u.assign.e->u.e.l)->setArray (a->Clone ()); + list_append (c->u.semi_comma.cmd, tmpc); + } + } + else { + NEW (tmpc, act_chp_lang_t); + tmpc->label = NULL; + tmpc->space = NULL; + tmpc->type = ACT_CHP_ASSIGN; + tmpc->u.assign.id = fn->args[i]->Clone(); + tmpc->u.assign.e = req->args[i]; + list_append (c->u.semi_comma.cmd, tmpc); + } } list_append (c->u.semi_comma.cmd, _chp_clone_subst (fn, fn->fx->getlang()->getchp()->c)); - NEW (tmpc, act_chp_lang_t); - tmpc->label = NULL; - tmpc->space = NULL; - tmpc->type = ACT_CHP_ASSIGN; - NEW (tmpc->u.assign.e, Expr); - tmpc->u.assign.e->type = E_VAR; - tmpc->u.assign.e->u.e.r = NULL; - tmpc->u.assign.e->u.e.l = (Expr *) fn->ret->Clone(); - - int idx = _get_fresh_idx ("fuse", &_useidx); + // return value + _cursc->findFresh ("fuse_", &_useidx); char buf[1024]; - snprintf (buf, 1024, "fuse_%d", idx); + snprintf (buf, 1024, "fuse_%d", _useidx++); Assert (_cursc->Add (buf, fn->fx->getRetType()) == 1, "Hmm"); - tmpc->u.assign.id = new ActId (buf); + ActNamespace::Act()->addGeneratedVar (_cursc, _cursc->LookupVal (buf)); + + if (fn->fx->getRetType()->arrayInfo()) { + Array *xa = fn->fx->getRetType()->arrayInfo(); + for (int j=0; j < xa->size(); j++) { + Array *a = xa->unOffset (j); + NEW (tmpc, act_chp_lang_t); + tmpc->label = NULL; + tmpc->space = NULL; + tmpc->type = ACT_CHP_ASSIGN; + NEW (tmpc->u.assign.e, Expr); + tmpc->u.assign.e->type = E_VAR; + tmpc->u.assign.e->u.e.r = NULL; + tmpc->u.assign.e->u.e.l = (Expr *) fn->ret->Clone(); + Assert (tmpc->u.assign.e->u.e.l->type == E_VAR, "What?"); + Assert (((ActId*)tmpc->u.assign.e->u.e.l->u.e.l)->arrayInfo() == NULL, "Huh?"); + ((ActId*)tmpc->u.assign.e->u.e.l->u.e.l)->setArray (a); + tmpc->u.assign.id = new ActId (buf); + tmpc->u.assign.id->setArray (a->Clone ()); + list_append (c->u.semi_comma.cmd, tmpc); + } + } + else { + NEW (tmpc, act_chp_lang_t); + tmpc->label = NULL; + tmpc->space = NULL; + tmpc->type = ACT_CHP_ASSIGN; + NEW (tmpc->u.assign.e, Expr); + tmpc->u.assign.e->type = E_VAR; + tmpc->u.assign.e->u.e.r = NULL; + tmpc->u.assign.e->u.e.l = (Expr *) fn->ret->Clone(); + tmpc->u.assign.id = new ActId (buf); + list_append (c->u.semi_comma.cmd, tmpc); + } list_append (l, new ActId (buf)); - - list_append (c->u.semi_comma.cmd, tmpc); - } len--; } diff --git a/passes/finline/finline.h b/passes/finline/finline.h index c5b31237..e40ce683 100644 --- a/passes/finline/finline.h +++ b/passes/finline/finline.h @@ -52,7 +52,6 @@ class ActCHPFuncInline : public ActPass { void _structure_assign (act_chp_lang_t *c); - int _get_fresh_idx (const char *prefix, int *idx); int _useidx; }; diff --git a/passes/netgen/emit.cc b/passes/netgen/emit.cc index dc32a458..73e8f4e9 100644 --- a/passes/netgen/emit.cc +++ b/passes/netgen/emit.cc @@ -410,9 +410,9 @@ netlist_t *ActNetlistPass::emitNetlist (Process *p) fatal_error ("Device mapping for `%s' not defined in technology file.", devname); } fprintf (fp, " %s", config_get_string (devname)); - fprintf (fp, " W="); + fprintf (fp, " %s=", param_names.w); print_number (fp, w*manufacturing_grid*output_scale_factor); - fprintf (fp, " L="); + fprintf (fp, " %s=", param_names.l); if (len_repeat > 1 && discrete_len == 0 && il == len_repeat-1) { print_number (fp, (find_length_fit (e->l - (e->nlen-1)*l)* @@ -426,7 +426,10 @@ netlist_t *ActNetlistPass::emitNetlist (Process *p) if (_fin_width > 0) { Assert ((w % _fin_width) == 0, "Internal inconsistency in fin width value"); - fprintf (fp, " NFIN=%d", w/_fin_width); + if (!param_names.fin) { + fatal_error ("fin_width specified without fin name in fet parameters!"); + } + fprintf (fp, " %s=%d", param_names.fin, w/_fin_width); } /* print extra fet string */ @@ -459,9 +462,9 @@ netlist_t *ActNetlistPass::emitNetlist (Process *p) else { gap = fet_spacing_diffonly; } - fprintf (fp, "+ AS="); + fprintf (fp, "+ %s=", param_names.as); print_number (fp, (e->w/getGridsPerLambda()*gap)*(lambda2*oscale2)); - fprintf (fp, " PS="); + fprintf (fp, " %s=", param_names.ps); print_number (fp, 2*(e->w/getGridsPerLambda() + gap)* lambda*output_scale_factor); @@ -481,9 +484,9 @@ netlist_t *ActNetlistPass::emitNetlist (Process *p) else { gap = fet_spacing_diffonly; } - fprintf (fp, " AD="); + fprintf (fp, " %s=", param_names.ad); print_number (fp, (e->w/getGridsPerLambda()*gap)*(lambda2*oscale2)); - fprintf (fp, " PD="); + fprintf (fp, " %s=", param_names.pd); print_number (fp, 2*(e->w/getGridsPerLambda() + gap)* lambda*output_scale_factor); fprintf (fp, "\n"); diff --git a/passes/netgen/netlist.cc b/passes/netgen/netlist.cc index 79b222c7..37323b30 100644 --- a/passes/netgen/netlist.cc +++ b/passes/netgen/netlist.cc @@ -2629,6 +2629,14 @@ ActNetlistPass::ActNetlistPass (Act *a) : ActPass (a, "prs2net") weak_share_min = 1; weak_share_max = 1; + config_set_default_string ("net.fet_params.width", "W"); + config_set_default_string ("net.fet_params.length", "L"); + config_set_default_string ("net.fet_params.area_src", "AS"); + config_set_default_string ("net.fet_params.perim_src", "PS"); + config_set_default_string ("net.fet_params.area_drain", "AD"); + config_set_default_string ("net.fet_params.perim_drain", "PD"); + config_set_default_string ("net.fet_params.fin", "NFIN"); + default_load_cap = config_get_real ("net.default_load_cap"); p_n_ratio = config_get_real ("net.p_n_ratio"); weak_to_strong_ratio = config_get_real ("net.weak_to_strong_ratio"); @@ -2773,6 +2781,14 @@ ActNetlistPass::ActNetlistPass (Act *a) : ActPass (a, "prs2net") else { mangled_ports_actflat = true; } + + param_names.w = config_get_string ("net.fet_params.width"); + param_names.l = config_get_string ("net.fet_params.length"); + param_names.as = config_get_string ("net.fet_params.area_src"); + param_names.ps = config_get_string ("net.fet_params.perim_src"); + param_names.ad = config_get_string ("net.fet_params.area_drain"); + param_names.pd = config_get_string ("net.fet_params.perim_drain"); + param_names.fin = config_get_string ("net.fet_params.fin"); } ActNetlistPass::~ActNetlistPass() diff --git a/passes/netgen/netlist.h b/passes/netgen/netlist.h index dd3b427a..f2fea690 100644 --- a/passes/netgen/netlist.h +++ b/passes/netgen/netlist.h @@ -300,6 +300,15 @@ class ActNetlistPass : public ActPass { /* mangled cells for flat act output? */ bool mangled_ports_actflat; + /* strings for fet parameters */ + struct fet_param { + const char *w; + const char *l; + const char *fin; + const char *as, *ad; + const char *ps, *pd; + } param_names; + netlist_t *generate_netlist (Process *p); void generate_netgraph (netlist_t *N, int num_vdd_share, diff --git a/transform/prs2net/main.cc b/transform/prs2net/main.cc index 88e7831d..bdbf3098 100644 --- a/transform/prs2net/main.cc +++ b/transform/prs2net/main.cc @@ -214,9 +214,19 @@ int main (int argc, char **argv) a->Expand (); + Process *p = a->findProcess (proc); + + if (!p) { + fatal_error ("Could not find process `%s' in file `%s'", proc, argv[1]); + } + + if (!p->isExpanded()) { + p = p->Expand (ActNamespace::Global(), p->CurScope(), 0, NULL); + } + if (cell_file) { ActCellPass *cp = new ActCellPass (a); - cp->run(); + cp->run(p); FILE *oc = fopen (cell_file, "w"); if (!oc) { @@ -230,16 +240,6 @@ int main (int argc, char **argv) a->mangle (config_get_string ("net.mangle_chars")); } - Process *p = a->findProcess (proc); - - if (!p) { - fatal_error ("Could not find process `%s' in file `%s'", proc, argv[1]); - } - - if (!p->isExpanded()) { - p = p->Expand (ActNamespace::Global(), p->CurScope(), 0, NULL); - } - ActNetlistPass *np = new ActNetlistPass (a); if (enable_shared_stat) { np->enableSharedStat(); diff --git a/transform/prs2net/test/57.act b/transform/prs2net/test/57.act new file mode 100644 index 00000000..e88409e4 --- /dev/null +++ b/transform/prs2net/test/57.act @@ -0,0 +1,8 @@ +import xfoo; + +defproc foo() +{ +xfoo::test t; +} + +foo f; diff --git a/transform/prs2net/test/58.act b/transform/prs2net/test/58.act new file mode 100644 index 00000000..f6f70089 --- /dev/null +++ b/transform/prs2net/test/58.act @@ -0,0 +1,10 @@ +import xfoo; +open xfoo => xbar; + +defproc foo() +{ +xfoo::test t; +xbar::test t2; +} + +foo f; diff --git a/transform/prs2net/test/all.cells b/transform/prs2net/test/all.cells index 753d9899..eb48af89 100644 --- a/transform/prs2net/test/all.cells +++ b/transform/prs2net/test/all.cells @@ -202,6 +202,20 @@ export defcell g_0x5 (bool? in[1]; bool! out) } } +export defcell g_i0x0 (bool? in[0]; bool! out) +{ + prs { + false -> out- + } +} + +export defcell g_i1x0 (bool? in[0]; bool! out) +{ + prs { + true -> out- + } +} + export defcell g_vl0n3ax1 (bool? in[3]; bool! out) { prs { diff --git a/transform/prs2net/test/runs/20.act.fstderr b/transform/prs2net/test/runs/20.act.fstderr index 5273dda6..e69de29b 100644 --- a/transform/prs2net/test/runs/20.act.fstderr +++ b/transform/prs2net/test/runs/20.act.fstderr @@ -1,4 +0,0 @@ -In expanding g_i1x0 -In expanding foo<> (inst: f) (20.act:1) -In expanding -toplevel- -FATAL: Port `in': zero-length array creation not permitted diff --git a/transform/prs2net/test/runs/20.act.fstdout b/transform/prs2net/test/runs/20.act.fstdout index e69de29b..efb95ae2 100644 --- a/transform/prs2net/test/runs/20.act.fstdout +++ b/transform/prs2net/test/runs/20.act.fstdout @@ -0,0 +1,64 @@ +* +*---- act defproc: cell::g_i1x0<> ----- +* raw ports: out +* +.subckt _8_8cell_8_8g_i1x0 out +*.PININFO out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +M0_ out Vdd GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: g_i1x0<> ----- +* +*---- act defproc: cell::g_i0x0<> ----- +* raw ports: out +* +.subckt _8_8cell_8_8g_i0x0 out +*.PININFO out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +.ends +*---- end of process: g_i0x0<> ----- +* +*---- act defproc: cell::g_0x4<> ----- +* raw ports: in[0] out +* +.subckt _8_8cell_8_8g_0x4 in_20_3 out +*.PININFO in_20_3:I out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +M0_ out in_20_3 GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: g_0x4<> ----- +.subckt foo +xcpx1 cpx1_4out _8_8cell_8_8g_i1x0 +xcpx2 cpx2_4out _8_8cell_8_8g_i0x0 +xcpx0 a b _8_8cell_8_8g_0x4 +.ends diff --git a/transform/prs2net/test/runs/21.act.fstderr b/transform/prs2net/test/runs/21.act.fstderr index 24c3f350..e69de29b 100644 --- a/transform/prs2net/test/runs/21.act.fstderr +++ b/transform/prs2net/test/runs/21.act.fstderr @@ -1,4 +0,0 @@ -In expanding g_i1x0 -In expanding foo<> (inst: f) (21.act:1) -In expanding -toplevel- -FATAL: Port `in': zero-length array creation not permitted diff --git a/transform/prs2net/test/runs/21.act.fstdout b/transform/prs2net/test/runs/21.act.fstdout index e69de29b..efb95ae2 100644 --- a/transform/prs2net/test/runs/21.act.fstdout +++ b/transform/prs2net/test/runs/21.act.fstdout @@ -0,0 +1,64 @@ +* +*---- act defproc: cell::g_i1x0<> ----- +* raw ports: out +* +.subckt _8_8cell_8_8g_i1x0 out +*.PININFO out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +M0_ out Vdd GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: g_i1x0<> ----- +* +*---- act defproc: cell::g_i0x0<> ----- +* raw ports: out +* +.subckt _8_8cell_8_8g_i0x0 out +*.PININFO out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +.ends +*---- end of process: g_i0x0<> ----- +* +*---- act defproc: cell::g_0x4<> ----- +* raw ports: in[0] out +* +.subckt _8_8cell_8_8g_0x4 in_20_3 out +*.PININFO in_20_3:I out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +M0_ out in_20_3 GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: g_0x4<> ----- +.subckt foo +xcpx1 cpx1_4out _8_8cell_8_8g_i1x0 +xcpx2 cpx2_4out _8_8cell_8_8g_i0x0 +xcpx0 a b _8_8cell_8_8g_0x4 +.ends diff --git a/transform/prs2net/test/runs/22.act.fstderr b/transform/prs2net/test/runs/22.act.fstderr index 89ed061d..520cc133 100644 --- a/transform/prs2net/test/runs/22.act.fstderr +++ b/transform/prs2net/test/runs/22.act.fstderr @@ -1,4 +1,3 @@ -In expanding foo<> (inst: f) (22.act:1) -In expanding -toplevel- +In expanding foo<> (22.act:1) WARNING: Sizing directive {+20,-15} specified for already sized rule skipped signal: `b' diff --git a/transform/prs2net/test/runs/37.act.fstderr b/transform/prs2net/test/runs/37.act.fstderr index 1e836368..998496b1 100644 --- a/transform/prs2net/test/runs/37.act.fstderr +++ b/transform/prs2net/test/runs/37.act.fstderr @@ -1,5 +1,4 @@ -In expanding foo<> (inst: ct) (37.act:3) -In expanding -toplevel- +In expanding foo<> (37.act:3) WARNING: Local dynamic arrays cannot have other partial connections ID: x FATAL: Cannot proceed. Dynamic arrays used in unsupported ways. diff --git a/transform/prs2net/test/runs/39.act.fstderr b/transform/prs2net/test/runs/39.act.fstderr index 6777075f..e187d7e4 100644 --- a/transform/prs2net/test/runs/39.act.fstderr +++ b/transform/prs2net/test/runs/39.act.fstderr @@ -1,4 +1,3 @@ -In expanding foo<> (inst: ct) (39.act:1) -In expanding -toplevel- +In expanding foo<> (39.act:1) Channel: a FATAL: Receive action in multiple concurrent blocks! diff --git a/transform/prs2net/test/runs/40.act.fstderr b/transform/prs2net/test/runs/40.act.fstderr index 8d99d5bd..bdd4246c 100644 --- a/transform/prs2net/test/runs/40.act.fstderr +++ b/transform/prs2net/test/runs/40.act.fstderr @@ -1,6 +1,4 @@ -In expanding foo<> (inst: ct) (40.act:1) -In expanding -toplevel- +In expanding foo<> (40.act:1) WARNING: Probe, send, and receive in different processes? -In expanding foo<> (inst: ct) (40.act:1) -In expanding -toplevel- +In expanding foo<> (40.act:1) WARNING: Probe, send, and receive in different processes? diff --git a/transform/prs2net/test/runs/57.act.fstderr b/transform/prs2net/test/runs/57.act.fstderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/prs2net/test/runs/57.act.fstdout b/transform/prs2net/test/runs/57.act.fstdout new file mode 100644 index 00000000..326b37b3 --- /dev/null +++ b/transform/prs2net/test/runs/57.act.fstdout @@ -0,0 +1,24 @@ +* +*---- act defproc: cell::g0n_0x0<> ----- +* raw ports: in[0] out +* +.subckt _8_8cell_8_8g0n_0x0 in_20_3 out +*.PININFO in_20_3:I out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +M0_ out in_20_3 Vdd Vdd pch W=0.3U L=0.06U +M1_ out in_20_3 GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: g0n_0x0<> ----- +.subckt foo +xt_4cx0 t_4a t_4b _8_8cell_8_8g0n_0x0 +.ends diff --git a/transform/prs2net/test/runs/57.act.stderr b/transform/prs2net/test/runs/57.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/prs2net/test/runs/57.act.stdout b/transform/prs2net/test/runs/57.act.stdout new file mode 100644 index 00000000..0036bdd9 --- /dev/null +++ b/transform/prs2net/test/runs/57.act.stdout @@ -0,0 +1,33 @@ +* +*---- act defproc: xfoo::test<> ----- +* raw ports: a b +* +.subckt _8_8xfoo_8_8test a b +*.PININFO a:I b:O +*.POWER VDD _8_8xfoo_8_8VddN +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB _8_8xfoo_8_8VddN +* +* --- node flags --- +* +* b (combinational) +* +* --- end node flags --- +* +M0_ b a _8_8xfoo_8_8VddN _8_8xfoo_8_8VddN pch W=0.3U L=0.06U +M1_ b a GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: test<> ----- +* +*---- act defproc: foo<> ----- +* raw ports: +* +.subckt foo +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +xt t_4a t_4b _8_8xfoo_8_8test +.ends +*---- end of process: foo<> ----- diff --git a/transform/prs2net/test/runs/58.act.fstderr b/transform/prs2net/test/runs/58.act.fstderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/prs2net/test/runs/58.act.fstdout b/transform/prs2net/test/runs/58.act.fstdout new file mode 100644 index 00000000..3d51084c --- /dev/null +++ b/transform/prs2net/test/runs/58.act.fstdout @@ -0,0 +1,25 @@ +* +*---- act defproc: cell::g0n_0x0<> ----- +* raw ports: in[0] out +* +.subckt _8_8cell_8_8g0n_0x0 in_20_3 out +*.PININFO in_20_3:I out:O +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +* +* --- node flags --- +* +* out (combinational) +* +* --- end node flags --- +* +M0_ out in_20_3 Vdd Vdd pch W=0.3U L=0.06U +M1_ out in_20_3 GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: g0n_0x0<> ----- +.subckt foo +xt2_4cx0 t2_4a t2_4b _8_8cell_8_8g0n_0x0 +xt_4cx0 t_4a t_4b _8_8cell_8_8g0n_0x0 +.ends diff --git a/transform/prs2net/test/runs/58.act.stderr b/transform/prs2net/test/runs/58.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/prs2net/test/runs/58.act.stdout b/transform/prs2net/test/runs/58.act.stdout new file mode 100644 index 00000000..4dae6c6c --- /dev/null +++ b/transform/prs2net/test/runs/58.act.stdout @@ -0,0 +1,55 @@ +* +*---- act defproc: xbar::test<> ----- +* raw ports: a b +* +.subckt _8_8xbar_8_8test a b +*.PININFO a:I b:O +*.POWER VDD _8_8xbar_8_8VddN +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB _8_8xbar_8_8VddN +* +* --- node flags --- +* +* b (combinational) +* +* --- end node flags --- +* +M0_ b a _8_8xbar_8_8VddN _8_8xbar_8_8VddN pch W=0.3U L=0.06U +M1_ b a GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: test<> ----- +* +*---- act defproc: xfoo::test<> ----- +* raw ports: a b +* +.subckt _8_8xfoo_8_8test a b +*.PININFO a:I b:O +*.POWER VDD _8_8xfoo_8_8VddN +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB _8_8xfoo_8_8VddN +* +* --- node flags --- +* +* b (combinational) +* +* --- end node flags --- +* +M0_ b a _8_8xfoo_8_8VddN _8_8xfoo_8_8VddN pch W=0.3U L=0.06U +M1_ b a GND GND nch W=0.15U L=0.06U +.ends +*---- end of process: test<> ----- +* +*---- act defproc: foo<> ----- +* raw ports: +* +.subckt foo +*.POWER VDD Vdd +*.POWER GND GND +*.POWER NSUB GND +*.POWER PSUB Vdd +xt2 t2_4a t2_4b _8_8xbar_8_8test +xt t_4a t_4b _8_8xfoo_8_8test +.ends +*---- end of process: foo<> ----- diff --git a/transform/prs2net/test/xfoo.act b/transform/prs2net/test/xfoo.act new file mode 100644 index 00000000..b6a73aa6 --- /dev/null +++ b/transform/prs2net/test/xfoo.act @@ -0,0 +1,12 @@ +namespace xfoo { + +bool VddN; + +export defproc test(bool a, b) +{ + prs { + a => b- + } +} + +} diff --git a/transform/testing/inline/test/40.act b/transform/testing/inline/test/40.act new file mode 100644 index 00000000..8526dc6b --- /dev/null +++ b/transform/testing/inline/test/40.act @@ -0,0 +1,22 @@ +function testme (int x[4]) : int +{ + int a; + chp { + a := 3; + self := x[a] + } +} + + + +defproc test() +{ + int w[4]; + int a; + + chp { + a := testme (w) + } +} + +test t; diff --git a/transform/testing/inline/test/41.act b/transform/testing/inline/test/41.act new file mode 100644 index 00000000..c15de54c --- /dev/null +++ b/transform/testing/inline/test/41.act @@ -0,0 +1,25 @@ +deftype mystruct(int<4> a, b) +{ } + +function swap(mystruct m) : mystruct +{ + chp { + self.a := m.b; + self.b := m.a + } +} + +defproc test() +{ + mystruct m; + int y; + + chp { + m.a := 0x1; + m.b := 0x2; + m := swap(swap(m)); + skip + } +} + +test t; diff --git a/transform/testing/inline/test/42.act b/transform/testing/inline/test/42.act new file mode 100644 index 00000000..95698833 --- /dev/null +++ b/transform/testing/inline/test/42.act @@ -0,0 +1,20 @@ +function testme (int x[4]) : int +{ + chp { + self := x[3] + } +} + + + +defproc test() +{ + int w[4]; + int a; + + chp { + a := testme (w) + } +} + +test t; diff --git a/transform/testing/inline/test/43.act b/transform/testing/inline/test/43.act new file mode 100644 index 00000000..0e21f4f1 --- /dev/null +++ b/transform/testing/inline/test/43.act @@ -0,0 +1,23 @@ +deftype data (int a, b) +{ + methods { + function plus (data d) : data + { + chp { + self.a := d.a + a; + self.b := d.b + b + } + } + } +} + +defproc test() +{ + data d1, d2; + + chp { + d1 := d1 + d2 + } +} + +test t; diff --git a/transform/testing/inline/test/44.act b/transform/testing/inline/test/44.act new file mode 100644 index 00000000..7a586667 --- /dev/null +++ b/transform/testing/inline/test/44.act @@ -0,0 +1,24 @@ +deftype data (int a, b) +{ + methods { + function plus (data d) : data + { + chp { + self.a := d.a + a; + self.b := d.b + b + } + } + } +} + +defproc test() +{ + data d1, d2; + chan(data) O; + + chp { + O!(d1 + d2) + } +} + +test t; diff --git a/transform/testing/inline/test/45.act b/transform/testing/inline/test/45.act new file mode 100644 index 00000000..bfa4bfa6 --- /dev/null +++ b/transform/testing/inline/test/45.act @@ -0,0 +1,26 @@ +deftype pair(int x, y) {} + +function testme (pair p) : pair +{ + chp { + self := p + } +} + +defproc test(chan?(int) X, Y; chan!(int) O) { + pair p; + + chp { + *[ + X?p.x, + Y?p.y; + p.x := testme(p).x; + *[ p.x > p.y -> p.x := p.x - p.y + [] p.y > p.x -> p.y := p.y - p.x + ]; + O!p.x + ] + } +} + +test t; diff --git a/transform/testing/inline/test/runs/40.act.stderr b/transform/testing/inline/test/runs/40.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/testing/inline/test/runs/40.act.stdout b/transform/testing/inline/test/runs/40.act.stdout new file mode 100644 index 00000000..f5a15af5 --- /dev/null +++ b/transform/testing/inline/test/runs/40.act.stdout @@ -0,0 +1,37 @@ +defproc test (); +function testme (int<32> x[4]) : int<32>; + +defproc test () +{ + +/* instances */ +int<32> fuse_0; +int<32> farg_0[4]; +int<32> a; +int<32> w[4]; +int<32> floc_0; +int<32> fret_0; + +/* connections */ +chp { +farg_0[0]:=w[0];farg_0[1]:=w[1];farg_0[2]:=w[2];farg_0[3]:=w[3];floc_0:=0x3;fret_0:=farg_0[floc_0];fuse_0:=fret_0;a:=fuse_0 +} +} + +function testme (int<32> x[4]) : int<32> +{ + +/* instances */ +int<32> a; + +/* connections */ +chp { +a:=0x3;self:=x[a] +} +} + + +/* instances */ +test t; + +/* connections */ diff --git a/transform/testing/inline/test/runs/41.act.stderr b/transform/testing/inline/test/runs/41.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/testing/inline/test/runs/41.act.stdout b/transform/testing/inline/test/runs/41.act.stdout new file mode 100644 index 00000000..da9d1511 --- /dev/null +++ b/transform/testing/inline/test/runs/41.act.stdout @@ -0,0 +1,42 @@ +defproc test (); +function swap (mystruct m) : mystruct; +deftype mystruct (int<4> a; int<4> b); + +defproc test () +{ + +/* instances */ +mystruct _us_0; +int<32> y; +mystruct m; + +/* connections */ +chp { +m.a:=0x1;m.b:=0x2;_us_0.a:=int(m.a,4);_us_0.b:=int(m.b,4);m.a:=_us_0.a;m.b:=_us_0.b;skip +} +} + +function swap (mystruct m) : mystruct +{ + +/* instances */ + +/* connections */ +chp { +self.a:=m.b;self.b:=m.a +} +} + +deftype mystruct (int<4> a; int<4> b) +{ + +/* instances */ + +/* connections */ +} + + +/* instances */ +test t; + +/* connections */ diff --git a/transform/testing/inline/test/runs/42.act.stderr b/transform/testing/inline/test/runs/42.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/testing/inline/test/runs/42.act.stdout b/transform/testing/inline/test/runs/42.act.stdout new file mode 100644 index 00000000..e9bb77a4 --- /dev/null +++ b/transform/testing/inline/test/runs/42.act.stdout @@ -0,0 +1,32 @@ +defproc test (); +function testme (int<32> x[4]) : int<32>; + +defproc test () +{ + +/* instances */ +int<32> a; +int<32> w[4]; + +/* connections */ +chp { +a:=int(w[3],32) +} +} + +function testme (int<32> x[4]) : int<32> +{ + +/* instances */ + +/* connections */ +chp { +self:=x[3] +} +} + + +/* instances */ +test t; + +/* connections */ diff --git a/transform/testing/inline/test/runs/43.act.stderr b/transform/testing/inline/test/runs/43.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/testing/inline/test/runs/43.act.stdout b/transform/testing/inline/test/runs/43.act.stdout new file mode 100644 index 00000000..3a6ca847 --- /dev/null +++ b/transform/testing/inline/test/runs/43.act.stdout @@ -0,0 +1,40 @@ +defproc test (); +deftype data (int<32> a; int<32> b); + +defproc test () +{ + +/* instances */ +data _us_0; +data d2; +data d1; + +/* connections */ +chp { +_us_0.a:=int(d2.a+d1.a,32);_us_0.b:=int(d2.b+d1.b,32);d1.a:=_us_0.a;d1.b:=_us_0.b +} +} + +deftype data (int<32> a; int<32> b) +{ + +/* instances */ + +/* connections */ + methods { + function plus (data d) : data { + +/* instances */ + +/* connections */ + chp { self.a:=d.a+a;self.b:=d.b+b } + } + + } +} + + +/* instances */ +test t; + +/* connections */ diff --git a/transform/testing/inline/test/runs/44.act.stderr b/transform/testing/inline/test/runs/44.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/testing/inline/test/runs/44.act.stdout b/transform/testing/inline/test/runs/44.act.stdout new file mode 100644 index 00000000..a0bec022 --- /dev/null +++ b/transform/testing/inline/test/runs/44.act.stdout @@ -0,0 +1,41 @@ +defproc test (); +deftype data (int<32> a; int<32> b); + +defproc test () +{ + +/* instances */ +data _us_0; +chan(data) O; +data d2; +data d1; + +/* connections */ +chp { +_us_0.a:=int(d2.a+d1.a,32);_us_0.b:=int(d2.b+d1.b,32);O!_us_0 +} +} + +deftype data (int<32> a; int<32> b) +{ + +/* instances */ + +/* connections */ + methods { + function plus (data d) : data { + +/* instances */ + +/* connections */ + chp { self.a:=d.a+a;self.b:=d.b+b } + } + + } +} + + +/* instances */ +test t; + +/* connections */ diff --git a/transform/testing/inline/test/runs/45.act.stderr b/transform/testing/inline/test/runs/45.act.stderr new file mode 100644 index 00000000..e69de29b diff --git a/transform/testing/inline/test/runs/45.act.stdout b/transform/testing/inline/test/runs/45.act.stdout new file mode 100644 index 00000000..77c167a0 --- /dev/null +++ b/transform/testing/inline/test/runs/45.act.stdout @@ -0,0 +1,41 @@ +defproc test (chan(int<32>)? X; chan(int<32>)? Y; chan(int<32>)! O); +function testme (pair p) : pair; +deftype pair (int<32> x; int<32> y); + +defproc test (chan(int<32>)? X; chan(int<32>)? Y; chan(int<32>)! O) +{ + +/* instances */ +pair _us0; +pair p; + +/* connections */ +chp { +*[true -> X?p.x,Y?p.y;_us0.x:=p.x;_us0.y:=p.y;p.x:=_us0.x;*[p.x>p.y -> p.x:=p.x-p.y [] p.y>p.x -> p.y:=p.y-p.x];O!p.x] +} +} + +function testme (pair p) : pair +{ + +/* instances */ + +/* connections */ +chp { +self:=p +} +} + +deftype pair (int<32> x; int<32> y) +{ + +/* instances */ + +/* connections */ +} + + +/* instances */ +test t; + +/* connections */ diff --git a/transform/v2act/v2act.cy b/transform/v2act/v2act.cy index 033f99b5..55b7c47a 100644 --- a/transform/v2act/v2act.cy +++ b/transform/v2act/v2act.cy @@ -13,17 +13,27 @@ module: "module" ID {{X: module_t *m; int off = 0; - char buf[10240]; + char *buf; + + int len = strlen ($2); + if (len < 10) { + len = 10; + } if ($2[0] == '\\') { char *tmp; - MALLOC (tmp, char, strlen ($2)); + MALLOC (tmp, char, len); strcpy (tmp, $2+1); - $0->a->mangle_string (tmp, buf, 10240); + + MALLOC (buf, char, 2*len); + buf[0] = '\0'; + $0->a->mangle_string (tmp, buf, 2*len); FREE (tmp); } else { - snprintf (buf, 10240, "%s", $2); + MALLOC (buf, char, len+1); + buf[0] = '\0'; + snprintf (buf, len+1, "%s", $2); } NEW (m, module_t); @@ -66,6 +76,7 @@ module: "module" ID /* now that we've found it, it should no longer be missing! */ hash_delete ($0->missing, buf); } + FREE (buf); }} "(" port_list ")" ";" module_body ;