static tree_t rewrite_refs(tree_t t, void *context) { rewrite_params_t *params = context; if (tree_kind(t) != T_REF) return t; tree_t decl = tree_ref(t); for (int i = 0; i < params->count; i++) { if (decl != params->formals[i]) continue; // Do not rewrite references if they appear as formal names if (tree_attr_int(t, formal_i, 0)) continue; // Skip assignments to OPEN ports if (params->actuals[i] == NULL) continue; switch (tree_kind(params->actuals[i])) { case T_SIGNAL_DECL: case T_ENUM_LIT: tree_set_ref(t, params->actuals[i]); tree_set_type(t, tree_type(params->actuals[i])); return t; case T_LITERAL: case T_AGGREGATE: case T_REF: case T_ARRAY_SLICE: case T_ARRAY_REF: case T_FCALL: case T_CONCAT: return params->actuals[i]; case T_TYPE_CONV: // XXX: this only works in trivial cases return tree_value(tree_param(params->actuals[i], 0)); default: fatal_at(tree_loc(params->actuals[i]), "cannot handle tree kind %s " "in rewrite_refs", tree_kind_str(tree_kind(params->actuals[i]))); } } return t; }
void vcd_restart(void) { if (vcd_file == NULL) return; vcd_emit_header(); int next_key = 0; const int ndecls = tree_decls(vcd_top); for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(vcd_top, i); switch (tree_kind(d)) { case T_HIER: fprintf(vcd_file, "$scope module %s $end\n", istr(tree_ident(d))); break; case T_SIGNAL_DECL: if (wave_should_dump(d)) vcd_process_signal(d, &next_key); break; default: break; } int npop = tree_attr_int(d, ident_new("scope_pop"), 0); while (npop-- > 0) fprintf(vcd_file, "$upscope $end\n"); } fprintf(vcd_file, "$enddefinitions $end\n"); fprintf(vcd_file, "$dumpvars\n"); last_time = UINT64_MAX; for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(vcd_top, i); if (tree_kind(d) == T_SIGNAL_DECL) { vcd_data_t *data = tree_attr_ptr(d, vcd_data_i); if (likely(data != NULL)) vcd_event_cb(0, d, data->watch, data); } } fprintf(vcd_file, "$end\n"); }
static void cover_report_stmts_fn(tree_t t, void *context) { const int32_t *counts = context; const int tag = tree_attr_int(t, stmt_tag_i, -1); if (tag == -1) return; const loc_t *loc = tree_loc(t); cover_file_t *file = cover_file(loc); if (file == NULL) return; assert(loc->first_line < file->n_lines); cover_line_t *l = &(file->lines[loc->first_line - 1]); l->hits = MAX(counts[tag], l->hits); }
void group_nets(tree_t top) { const int nnets = tree_attr_int(top, nnets_i, 0); group_nets_ctx_t ctx; group_init_context(&ctx, nnets); tree_visit(top, group_nets_visit_fn, &ctx); group_write_netdb(top, &ctx); if (opt_get_int("verbose")) { int ngroups = 0; for (group_t *it = ctx.groups; it != NULL; it = it->next) ngroups++; notef("%d nets, %d groups", nnets, ngroups); notef("nets:groups ratio %.3f", (float)nnets / (float)ngroups); } group_free_list(ctx.groups); group_free_list(ctx.free_list); free(ctx.lookup); }
void fst_restart(void) { if (fst_ctx == NULL) return; const int ndecls = tree_decls(fst_top); for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(fst_top, i); switch (tree_kind(d)) { case T_SIGNAL_DECL: if (wave_should_dump(d)) fst_process_signal(d); break; case T_HIER: fst_process_hier(d); break; default: break; } int npop = tree_attr_int(d, ident_new("scope_pop"), 0); while (npop-- > 0) fstWriterSetUpscope(fst_ctx); } last_time = UINT64_MAX; for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(fst_top, i); if (tree_kind(d) == T_SIGNAL_DECL) { fst_data_t *data = tree_attr_ptr(d, fst_data_i); if (likely(data != NULL)) fst_event_cb(0, d, data->watch, data); } } }
static void fst_process_signal(tree_t d) { type_t type = tree_type(d); type_t base = type_base_recur(type); fst_data_t *data = xmalloc(sizeof(fst_data_t)); memset(data, '\0', sizeof(fst_data_t)); int msb = 0, lsb = 0; enum fstVarType vt; enum fstSupplementalDataType sdt; if (type_is_array(type)) { if (type_dims(type) > 1) { warn_at(tree_loc(d), "cannot represent multidimensional arrays " "in FST format"); free(data); return; } range_t r = type_dim(type, 0); int64_t low, high; range_bounds(r, &low, &high); data->dir = r.kind; data->size = high - low + 1; msb = assume_int(r.left); lsb = assume_int(r.right); type_t elem = type_elem(type); if (!fst_can_fmt_chars(elem, data, &vt, &sdt)) { warn_at(tree_loc(d), "cannot represent arrays of type %s " "in FST format", type_pp(elem)); free(data); return; } else { ident_t ident = type_ident(base); if (ident == unsigned_i) sdt = FST_SDT_VHDL_UNSIGNED; else if (ident == signed_i) sdt = FST_SDT_VHDL_SIGNED; } } else { switch (type_kind(base)) { case T_INTEGER: { ident_t ident = type_ident(type); if (ident == natural_i) sdt = FST_SDT_VHDL_NATURAL; else if (ident == positive_i) sdt = FST_SDT_VHDL_POSITIVE; else sdt = FST_SDT_VHDL_INTEGER; int64_t low, high; range_bounds(type_dim(type, 0), &low, &high); vt = FST_VT_VCD_INTEGER; data->size = ilog2(high - low + 1); data->fmt = fst_fmt_int; } break; case T_ENUM: if (!fst_can_fmt_chars(type, data, &vt, &sdt)) { ident_t ident = type_ident(base); if (ident == std_bool_i) sdt = FST_SDT_VHDL_BOOLEAN; else if (ident == std_char_i) sdt = FST_SDT_VHDL_CHARACTER; else sdt = FST_SDT_NONE; vt = FST_VT_GEN_STRING; data->size = 0; data->fmt = fst_fmt_enum; } else data->size = 1; break; case T_PHYSICAL: { sdt = FST_SDT_NONE; vt = FST_VT_GEN_STRING; data->size = 0; data->type.units = fst_make_unit_map(type); data->fmt = fst_fmt_physical; } break; default: warn_at(tree_loc(d), "cannot represent type %s in FST format", type_pp(type)); free(data); return; } } enum fstVarDir dir = FST_VD_IMPLICIT; switch (tree_attr_int(d, fst_dir_i, -1)) { case PORT_IN: dir = FST_VD_INPUT; break; case PORT_OUT: dir = FST_VD_OUTPUT; break; case PORT_INOUT: dir = FST_VD_INOUT; break; case PORT_BUFFER: dir = FST_VD_BUFFER; break; } const char *name_base = strrchr(istr(tree_ident(d)), ':') + 1; const size_t base_len = strlen(name_base); char name[base_len + 64]; strncpy(name, name_base, base_len + 64); if (type_is_array(type)) snprintf(name + base_len, 64, "[%d:%d]\n", msb, lsb); data->handle = fstWriterCreateVar2( fst_ctx, vt, dir, data->size, name, 0, type_pp(type), FST_SVT_VHDL_SIGNAL, sdt); tree_add_attr_ptr(d, fst_data_i, data); data->watch = rt_set_event_cb(d, fst_event_cb, data, true); }