static void ungroup_proc_params(tree_t t, group_nets_ctx_t *ctx) { // Ungroup any signal that is passed to a procedure as in general we // cannot guarantee anything about the procedure's behaviour const int nparams = tree_params(t); for (int i = 0; i < nparams; i++) { tree_t value = tree_value(tree_param(t, i)); tree_kind_t kind = tree_kind(value); while (kind == T_ARRAY_REF || kind == T_ARRAY_SLICE) { value = tree_value(value); kind = tree_kind(value); } if (kind != T_REF) continue; tree_t decl = tree_ref(value); if (tree_kind(decl) != T_SIGNAL_DECL) continue; const int nnets = tree_nets(decl); for (int i = 0; i < nnets; i++) group_add(ctx, tree_net(decl, i), 1); } }
static void opt_elide_array_ref_bounds(tree_t t) { tree_t value = tree_value(t); if (tree_kind(value) != T_REF) return; tree_t decl = tree_ref(value); const int nparams = tree_params(t); for (int i = 0; i < nparams; i++) { tree_t index = tree_value(tree_param(t, i)); if (tree_kind(index) != T_REF) return; tree_t index_decl = tree_ref(index); tree_t range_var = tree_attr_tree(index_decl, range_var_i); if (range_var == NULL) return; if (range_var != decl) return; } tree_add_attr_int(t, elide_bounds_i, 1); }
static bool group_name(tree_t target, group_nets_ctx_t *ctx, int start, int n) { switch (tree_kind(target)) { case T_REF: group_ref(target, ctx, start, n); return true; case T_ARRAY_REF: { tree_t value = tree_value(target); type_t type = tree_type(value); if (type_is_unconstrained(type)) return false; int offset = 0; const int nparams = tree_params(target); for (int i = 0; i < nparams; i++) { tree_t index = tree_value(tree_param(target, i)); const int stride = type_width(type_elem(type)); if (tree_kind(index) != T_LITERAL) { if (i > 0) return false; const int twidth = type_width(type); for (int j = 0; j < twidth; j += stride) group_name(value, ctx, start + j, n); return true; } else { if (i > 0) { range_t type_r = range_of(type, i); int64_t low, high; range_bounds(type_r, &low, &high); offset *= high - low + 1; } offset += stride * rebase_index(type, i, assume_int(index)); } } return group_name(value, ctx, start + offset, n); } case T_ARRAY_SLICE: { tree_t value = tree_value(target); type_t type = tree_type(value); if (type_is_unconstrained(type)) return false; // Only in procedure range_t slice = tree_range(target, 0 ); if (tree_kind(slice.left) != T_LITERAL || tree_kind(slice.right) != T_LITERAL) return false; int64_t low, high; range_bounds(slice, &low, &high); const int64_t low0 = rebase_index(type, 0, assume_int(slice.left)); const int stride = type_width(type_elem(type)); return group_name(value, ctx, start + low0 * stride, n); } case T_RECORD_REF: { tree_t value = tree_value(target); type_t rec = tree_type(value); const int offset = record_field_to_net(rec, tree_ident(target)); return group_name(value, ctx, start + offset, n); } case T_AGGREGATE: case T_LITERAL: // This can appear due to assignments to open ports with a // default value return true; default: fatal_at(tree_loc(target), "tree kind %s not yet supported for offset " "calculation", tree_kind_str(tree_kind(target))); } }