Skip to content

Commit 3ad97cf

Browse files
committed
Constrain ports during code generation. Fixes #809
1 parent 19f67b7 commit 3ad97cf

13 files changed

+298
-199
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ compile_commands.json
4646
www/*.html
4747
/debian
4848
/compile_flags.txt
49+
.cache
4950

5051
# Generated GUI files
5152
contrib/gui/node_modules

src/elab.c

+1-137
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ static bool elab_should_copy_tree(tree_t t, void *__ctx)
225225
switch (tree_kind(decl)) {
226226
case T_GENERIC_DECL:
227227
return true;
228-
case T_PORT_DECL:
229-
return !!(tree_flags(decl) & TREE_F_UNCONSTRAINED);
230228
case T_ENTITY:
231229
case T_ARCH:
232230
case T_BLOCK:
@@ -646,131 +644,6 @@ static void elab_hint_fn(diag_t *d, void *arg)
646644
}
647645
}
648646

649-
static tree_t elab_unconstrained_port(tree_t port, elab_ctx_t *ctx)
650-
{
651-
tree_t p2 = tree_new(T_PORT_DECL);
652-
tree_set_ident(p2, tree_ident(port));
653-
tree_set_loc(p2, tree_loc(port));
654-
tree_set_subkind(p2, tree_subkind(port));
655-
tree_set_class(p2, tree_class(port));
656-
657-
if (tree_has_value(port))
658-
tree_set_value(p2, tree_value(port));
659-
660-
// Abusing the generic rewriting mechanism to replace all
661-
// references to the unconstrained port
662-
if (ctx->generics == NULL)
663-
ctx->generics = hash_new(64);
664-
hash_put(ctx->generics, port, p2);
665-
666-
return p2;
667-
}
668-
669-
static void elab_constrain_port(tree_t orig, tree_t port, tree_t map)
670-
{
671-
if (orig == port)
672-
return; // Already fully constrained
673-
else if (tree_subkind(map) == P_NAMED) {
674-
tree_t name = tree_name(map);
675-
676-
const tree_kind_t kind = tree_kind(name);
677-
type_t type;
678-
if (kind == T_REF) {
679-
assert(!tree_has_type(port));
680-
tree_set_type(port, (type = tree_type(tree_value(map))));
681-
}
682-
else if (tree_has_type(port)) {
683-
type = tree_type(port);
684-
assert(type_kind(type) == T_SUBTYPE);
685-
}
686-
else {
687-
type_t base = tree_type(orig);
688-
assert(type_is_unconstrained(base));
689-
690-
tree_t cons = tree_new(T_CONSTRAINT);
691-
tree_set_subkind(cons, type_is_record(base) ? C_RECORD : C_INDEX);
692-
693-
type = type_new(T_SUBTYPE);
694-
type_set_base(type, base);
695-
type_add_constraint(type, cons);
696-
697-
tree_set_type(port, type);
698-
}
699-
700-
switch (tree_kind(name)) {
701-
case T_REF:
702-
break;
703-
case T_ARRAY_REF:
704-
{
705-
// The name is of the form X(I) so use this to derive
706-
// the bounds of a single-element array
707-
tree_t value = tree_value(tree_param(name, 0));
708-
709-
tree_t cons = type_constraint(type, 0);
710-
if (tree_ranges(cons) == 0) {
711-
tree_t r = tree_new(T_RANGE);
712-
tree_set_subkind(r, RANGE_TO);
713-
tree_set_left(r, value);
714-
tree_set_right(r, value);
715-
tree_set_type(r, tree_type(value));
716-
717-
tree_add_range(cons, r);
718-
}
719-
else {
720-
// Already encountered at least one association
721-
tree_t r = tree_range(cons, 0);
722-
723-
tree_t left = tree_left(r);
724-
tree_t right = tree_right(r);
725-
726-
int64_t ileft, iright, ivalue;
727-
const bool folded = folded_int(left, &ileft)
728-
&& folded_int(right, &iright)
729-
&& folded_int(value, &ivalue);
730-
731-
if (!folded) {
732-
error_at(tree_loc(name), "cannot determine bounds of "
733-
"unconstrained port %s", istr(tree_ident(port)));
734-
return;
735-
}
736-
737-
assert(tree_subkind(r) == RANGE_TO); // Set above
738-
if (ivalue < ileft)
739-
tree_set_left(r, value);
740-
else if (ivalue > iright)
741-
tree_set_right(r, value);
742-
}
743-
}
744-
break;
745-
case T_RECORD_REF:
746-
{
747-
tree_t f = find_record_field(name);
748-
assert(f != NULL);
749-
750-
type_t ftype = tree_type(f);
751-
if (!type_is_unconstrained(ftype))
752-
return;
753-
754-
tree_t elem = tree_new(T_ELEM_CONSTRAINT);
755-
tree_set_ident(elem, tree_ident(f));
756-
tree_set_ref(elem, f);
757-
tree_set_type(elem, tree_type(tree_value(map)));
758-
759-
tree_t cons = type_constraint(type, 0);
760-
tree_add_range(cons, elem);
761-
}
762-
break;
763-
default:
764-
error_at(tree_loc(name), "invalid formal name for unconstrained "
765-
"port %s", istr(tree_ident(port)));
766-
}
767-
}
768-
else {
769-
assert(!tree_has_type(port));
770-
tree_set_type(port, tree_type(tree_value(map)));
771-
}
772-
}
773-
774647
static void elab_ports(tree_t entity, tree_t comp, tree_t inst, elab_ctx_t *ctx)
775648
{
776649
const int nports = tree_ports(entity);
@@ -788,12 +661,9 @@ static void elab_ports(tree_t entity, tree_t comp, tree_t inst, elab_ctx_t *ctx)
788661
}
789662

790663
for (int i = 0; i < nports; i++) {
791-
tree_t p = tree_port(entity, i), bp = p, op = p, map = NULL;
664+
tree_t p = tree_port(entity, i), bp = p, map = NULL;
792665
ident_t pname = tree_ident(p);
793666

794-
if (tree_flags(p) & TREE_F_UNCONSTRAINED)
795-
p = elab_unconstrained_port(p, ctx);
796-
797667
if (i < nparams && !have_named && entity == comp) {
798668
tree_t m = tree_param(inst, i);
799669
if (tree_subkind(m) == P_POS) {
@@ -805,8 +675,6 @@ static void elab_ports(tree_t entity, tree_t comp, tree_t inst, elab_ctx_t *ctx)
805675

806676
tree_add_param(ctx->out, m2);
807677
map = m2;
808-
809-
elab_constrain_port(op, p, m);
810678
}
811679
}
812680
else if (binding != NULL && binding_nparams) {
@@ -872,8 +740,6 @@ static void elab_ports(tree_t entity, tree_t comp, tree_t inst, elab_ctx_t *ctx)
872740

873741
tree_add_param(ctx->out, map);
874742

875-
elab_constrain_port(op, p, m);
876-
877743
if (!have_named && !is_conv && ref == name) {
878744
tree_set_subkind(map, P_POS);
879745
tree_set_pos(map, i);
@@ -890,8 +756,6 @@ static void elab_ports(tree_t entity, tree_t comp, tree_t inst, elab_ctx_t *ctx)
890756
tree_set_loc(map, tree_loc(m));
891757
tree_set_value(map, tree_value(m));
892758

893-
elab_constrain_port(op, p, m);
894-
895759
if (!have_named) {
896760
tree_set_subkind(map, P_POS);
897761
tree_set_pos(map, i);

0 commit comments

Comments
 (0)