From 7dd41079090dcf7b3e20bdc9834be3018154eb3a Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 21 Jan 2024 19:38:37 +0000 Subject: [PATCH] Separate inner and outer block statement for component instantiation --- src/elab.c | 769 +++++++++++++++++------------------ src/lower.c | 8 - src/rt/wave.c | 8 + src/sem.c | 3 - src/vhpi/vhpi-model.c | 20 +- test/elab/comp3.vhd | 4 +- test/elab/jcore2.vhd | 87 ++++ test/parse/vests1.vhd | 18 + test/regress/gold/wave9.dump | 8 + test/regress/testlist.txt | 1 + test/regress/wave9.vhd | 30 ++ test/test_elab.c | 96 ++++- test/test_lower.c | 74 ++-- test/test_simp.c | 9 +- 14 files changed, 671 insertions(+), 464 deletions(-) create mode 100644 test/elab/jcore2.vhd create mode 100644 test/regress/gold/wave9.dump create mode 100644 test/regress/wave9.vhd diff --git a/src/elab.c b/src/elab.c index c37fde40..08447544 100644 --- a/src/elab.c +++ b/src/elab.c @@ -337,68 +337,6 @@ static tree_t elab_root_config(tree_t top, const elab_ctx_t *ctx) return arch; } -static bool elab_compatible_map(tree_t comp, tree_t entity, char *what, - tree_t inst, tree_formals_t tree_Fs, - tree_formal_t tree_F) -{ - const int comp_nf = (*tree_Fs)(comp); - const int entity_nf = (*tree_Fs)(entity); - - for (int i = 0; i < comp_nf; i++) { - tree_t comp_f = (*tree_F)(comp, i); - - bool found = false; - for (int j = 0; !found && j < entity_nf; j++) { - tree_t entity_f = (*tree_F)(entity, j); - - if (tree_ident(comp_f) != tree_ident(entity_f)) - continue; - - found = true; - - type_t entity_type = tree_type(entity_f); - type_t comp_type = tree_type(comp_f); - - if (!type_eq(entity_type, comp_type)) { - diag_t *d = diag_new(DIAG_ERROR, tree_loc(comp_f)); - diag_printf(d, "type of %s %s in component declaration %s is " - "%s which does not match type %s in entity %s", - what, istr(tree_ident(comp_f)), - istr(tree_ident(comp)), type_pp(comp_type), - type_pp(entity_type), istr(tree_ident(entity))); - diag_hint(d, tree_loc(comp), "in component declaration of %s", - istr(tree_ident(comp))); - diag_hint(d, tree_loc(comp_f), "port declared as %s", - type_pp(comp_type)); - diag_hint(d, tree_loc(entity_f), "entity port declared as %s", - type_pp(entity_type)); - diag_hint(d, tree_loc(inst), "while elaborating instance %s here", - istr(tree_ident(inst))); - diag_emit(d); - return false; - } - } - - if (!found) { - diag_t *d = diag_new(DIAG_ERROR, tree_loc(comp_f)); - diag_printf(d, "%s %s not found in entity %s", - what, istr(tree_ident(comp_f)), istr(tree_ident(entity))); - diag_hint(d, tree_loc(comp), "in component declaration of %s", - istr(tree_ident(comp))); - diag_hint(d, tree_loc(comp_f), "declaration of port %s", - istr(tree_ident(comp_f))); - diag_hint(d, tree_loc(inst), "while elaborating instance %s here", - istr(tree_ident(inst))); - diag_hint(d, tree_loc(entity), "entity %s has no port named %s", - istr(tree_ident(entity)), istr(tree_ident(comp_f))); - diag_emit(d); - return false; - } - } - - return true; -} - static bool elab_synth_binding_cb(lib_t lib, void *__ctx) { synth_binding_params_t *params = __ctx; @@ -468,17 +406,150 @@ static tree_t elab_default_binding(tree_t inst, const elab_ctx_t *ctx) // Check entity is compatible with component declaration - if (!elab_compatible_map(comp, entity, "generic", inst, - tree_generics, tree_generic)) - return NULL; + tree_t bind = tree_new(T_BINDING); + tree_set_ident(bind, tree_ident(arch)); + tree_set_loc(bind, tree_loc(arch)); + tree_set_ref(bind, arch); + tree_set_class(bind, C_ENTITY); - if (!elab_compatible_map(comp, entity, "port", inst, tree_ports, tree_port)) - return NULL; + const int c_ngenerics = tree_generics(comp); + const int e_ngenerics = tree_generics(entity); - return arch; + for (int i = 0; i < e_ngenerics; i++) { + tree_t eg = tree_generic(entity, i); + + tree_t match = NULL; + for (int j = 0; j < c_ngenerics; j++) { + tree_t cg = tree_generic(comp, j); + if (tree_ident(eg) == tree_ident(cg)) { + match = cg; + break; + } + } + + tree_t value; + if (match != NULL) { + type_t ctype = tree_type(match); + type_t etype = tree_type(eg); + if (!type_eq(ctype, etype)) { + diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst)); + diag_printf(d, "generic %s in component %s has type %s which is " + "incompatible with type %s in entity %s", + istr(tree_ident(match)), istr(tree_ident(comp)), + type_pp2(ctype, etype), type_pp2(etype, ctype), + istr(tree_ident(entity))); + diag_hint(d, tree_loc(match), "declaration of generic %s in " + "component", istr(tree_ident(match))); + diag_hint(d, tree_loc(eg), "declaration of generic %s in entity", + istr(tree_ident(eg))); + diag_emit(d); + return NULL; + } + + value = make_ref(match); + } + else if (tree_has_value(eg)) { + tree_t def = tree_value(eg); + if (is_literal(def) && tree_kind(def) != T_STRING) + value = def; + else { + tree_t open = tree_new(T_OPEN); + tree_set_loc(open, tree_loc(eg)); + tree_set_type(open, tree_type(eg)); + + value = open; + } + } + else { + diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst)); + diag_printf(d, "generic %s in entity %s without a default value " + "has no corresponding generic in component %s", + istr(tree_ident(eg)), istr(tree_ident(entity)), + istr(tree_ident(comp))); + diag_hint(d, tree_loc(eg), "declaration of generic %s in entity", + istr(tree_ident(eg))); + diag_emit(d); + return NULL; + } + + tree_t map = tree_new(T_PARAM); + tree_set_loc(map, tree_loc(inst)); + tree_set_value(map, value); + tree_set_subkind(map, P_POS); + tree_set_pos(map, i); + + tree_add_genmap(bind, map); + } + + const int c_nports = tree_ports(comp); + const int e_nports = tree_ports(entity); + + for (int i = 0; i < e_nports; i++) { + tree_t ep = tree_port(entity, i); + + tree_t match = NULL; + for (int j = 0; j < c_nports; j++) { + tree_t cp = tree_port(comp, j); + if (tree_ident(ep) == tree_ident(cp)) { + match = cp; + break; + } + } + + tree_t value; + if (match != NULL) { + type_t ctype = tree_type(match); + type_t etype = tree_type(ep); + if (!type_eq(ctype, etype)) { + diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst)); + diag_printf(d, "port %s in component %s has type %s which is " + "incompatible with type %s in entity %s", + istr(tree_ident(match)), istr(tree_ident(comp)), + type_pp2(ctype, etype), type_pp2(etype, ctype), + istr(tree_ident(entity))); + diag_hint(d, tree_loc(match), "declaration of port %s in component", + istr(tree_ident(match))); + diag_hint(d, tree_loc(ep), "declaration of port %s in entity", + istr(tree_ident(ep))); + diag_emit(d); + return NULL; + } + + value = make_ref(match); + } + else { + const bool open_ok = + tree_has_value(ep) + || (tree_subkind(ep) == PORT_OUT + && !type_is_unconstrained(tree_type(ep))); + + if (open_ok) { + tree_t open = tree_new(T_OPEN); + tree_set_loc(open, tree_loc(ep)); + tree_set_type(open, tree_type(ep)); + + value = open; + } + else { + diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst)); + diag_printf(d, "port %s in entity %s without a default value " + "has no corresponding port in component %s", + istr(tree_ident(ep)), istr(tree_ident(entity)), + istr(tree_ident(comp))); + diag_hint(d, tree_loc(ep), "port %s declared here", + istr(tree_ident(ep))); + diag_emit(d); + return NULL; + } + } + + add_param(bind, value, P_POS, NULL); + } + + return bind; } -static tree_t elab_binding(tree_t inst, tree_t spec, elab_ctx_t *ctx) +static tree_t elab_binding(tree_t inst, tree_t spec, const elab_ctx_t *ctx) { if (!tree_has_value(spec)) return NULL; @@ -592,77 +663,28 @@ static void elab_hint_fn(diag_t *d, void *arg) } } -static void elab_ports(tree_t entity, tree_t comp, tree_t inst, elab_ctx_t *ctx) +static void elab_ports(tree_t entity, tree_t bind, const elab_ctx_t *ctx) { const int nports = tree_ports(entity); - const int nparams = tree_params(inst); + const int nparams = tree_params(bind); bool have_named = false; - int binding_nparams = 0; - tree_t binding = NULL; - if (tree_kind(inst) == T_INSTANCE && tree_has_spec(inst)) { - tree_t spec = tree_spec(inst); - if (tree_has_value(spec)) { - binding = tree_value(spec); - binding_nparams = tree_params(binding); - } - } - for (int i = 0; i < nports; i++) { - tree_t p = tree_port(entity, i), bp = p, map = NULL; + tree_t p = tree_port(entity, i), map = NULL; ident_t pname = tree_ident(p); - if (i < nparams && !have_named && entity == comp) { - tree_t m = tree_param(inst, i); + if (i < nparams && !have_named) { + tree_t m = tree_param(bind, i); if (tree_subkind(m) == P_POS) { - tree_t m2 = tree_new(T_PARAM); - tree_set_loc(m2, tree_loc(m)); - tree_set_subkind(m2, P_POS); - tree_set_pos(m2, i); - tree_set_value(m2, tree_value(m)); - - tree_add_param(ctx->out, m2); - map = m2; - } - } - else if (binding != NULL && binding_nparams) { - // Binding may add another level of port map - tree_t remap = NULL; - if (i < binding_nparams) { - tree_t m = tree_param(binding, i); - if (tree_subkind(m) == P_POS) - remap = tree_value(m); - } - - if (remap == NULL) { - for (int j = 0; j < binding_nparams; j++) { - tree_t m = tree_param(binding, j); - if (tree_subkind(m) == P_NAMED) { - tree_t name = tree_name(m); - tree_t ref = name_to_ref(name); - assert(ref != NULL); - - if (tree_ident(ref) == pname) { - remap = tree_value(m); - break; - } - } - } - } - - if (remap != NULL) { - assert(tree_kind(remap) == T_REF); - - bp = tree_ref(remap); - assert(tree_kind(bp) == T_PORT_DECL); - - pname = tree_ident(bp); + assert(tree_pos(m) == i); + tree_add_param(ctx->out, m); + map = m; } } if (map == NULL) { for (int j = 0; j < nparams; j++) { - tree_t m = tree_param(inst, j); + tree_t m = tree_param(bind, j); if (tree_subkind(m) == P_NAMED) { tree_t name = tree_name(m), ref; bool is_conv = false; @@ -699,24 +721,6 @@ static void elab_ports(tree_t entity, tree_t comp, tree_t inst, elab_ctx_t *ctx) have_named = true; } } - else if (tree_ident(tree_port(comp, tree_pos(m))) == pname) { - map = tree_new(T_PARAM); - tree_set_loc(map, tree_loc(m)); - tree_set_value(map, tree_value(m)); - - if (!have_named) { - tree_set_subkind(map, P_POS); - tree_set_pos(map, i); - } - else { - tree_set_subkind(map, P_NAMED); - tree_set_name(map, make_ref(p)); - have_named = true; - } - - tree_add_param(ctx->out, map); - break; - } } } @@ -848,102 +852,30 @@ static tree_t elab_find_generic_override(tree_t g, const elab_ctx_t *ctx) return value; } -static void elab_generics(tree_t entity, tree_t comp, tree_t inst, - elab_ctx_t *ctx) +static void elab_generics(tree_t entity, tree_t bind, elab_ctx_t *ctx) { const int ngenerics = tree_generics(entity); - const int ngenmaps = tree_genmaps(inst); - - int binding_ngenmaps = 0; - tree_t binding = NULL; - if (tree_kind(inst) == T_INSTANCE && tree_has_spec(inst)) { - tree_t spec = tree_spec(inst); - if (tree_has_value(spec)) { - binding = tree_value(spec); - binding_ngenmaps = tree_genmaps(binding); - } - } - - if (ctx->generics == NULL && ngenerics > 0) - ctx->generics = hash_new(ngenerics * 2); + const int ngenmaps = tree_genmaps(bind); for (int i = 0; i < ngenerics; i++) { - tree_t eg = tree_generic(entity, i), cg = eg; - unsigned pos = i; - tree_t map = NULL, bind_expr = NULL; - - if (entity != comp) { - // Component generics may be in different order to entity - pos = UINT_MAX; - - const int ngenerics_comp = tree_generics(comp); - for (int j = 0; j < ngenerics_comp; j++) { - tree_t g = tree_generic(comp, j); - if (tree_ident(g) == tree_ident(eg)) { - cg = g; - pos = j; - break; - } - } - - if (binding_ngenmaps > 0) { - for (int j = 0; j < binding_ngenmaps; j++) { - tree_t m = tree_genmap(binding, j); - assert(tree_subkind(m) == P_POS); - if (tree_pos(m) != i) - continue; - - tree_t value = tree_value(m); - if (tree_kind(value) == T_OPEN) - break; - else if (tree_kind(value) == T_REF) { - tree_t decl = tree_ref(value); - if (tree_kind(decl) == T_GENERIC_DECL) { - cg = tree_ref(value); - pos = i; - break; - } - } - - bind_expr = value; - break; - } - } - } - - tree_add_generic(ctx->out, eg); + tree_t g = tree_generic(entity, i); + tree_add_generic(ctx->out, g); - if (pos < ngenmaps) { - map = tree_genmap(inst, pos); + tree_t map = NULL; + if (i < ngenmaps) { + map = tree_genmap(bind, i); assert(tree_subkind(map) == P_POS); + assert(tree_pos(map) == i); } - else if (tree_has_value(cg)) { + else if (tree_has_value(g)) { map = tree_new(T_PARAM); - tree_set_loc(map, tree_loc(cg)); + tree_set_loc(map, tree_loc(g)); tree_set_subkind(map, P_POS); tree_set_pos(map, i); - tree_set_value(map, tree_value(cg)); + tree_set_value(map, tree_value(g)); } - if (bind_expr != NULL) { - tree_t m = tree_new(T_PARAM); - tree_set_loc(m, tree_loc(cg)); - tree_set_subkind(m, P_POS); - tree_set_pos(m, i); - tree_set_value(m, bind_expr); - - // The binding expression may contain references to component - // generics that need to be folded - if (map != NULL) { - hash_put(ctx->generics, cg, tree_value(map)); - simplify_global(bind_expr, ctx->generics, ctx->jit, ctx->registry); - cg = eg; - } - - map = m; - } - - tree_t override = elab_find_generic_override(cg, ctx); + tree_t override = elab_find_generic_override(g, ctx); if (override != NULL) { map = tree_new(T_PARAM); tree_set_subkind(map, P_POS); @@ -952,8 +884,8 @@ static void elab_generics(tree_t entity, tree_t comp, tree_t inst, } if (map == NULL) { - error_at(tree_loc(inst), "missing value for generic %s with no " - "default", istr(tree_ident(cg))); + error_at(tree_loc(bind), "missing value for generic %s with no " + "default", istr(tree_ident(g))); continue; } @@ -963,7 +895,7 @@ static void elab_generics(tree_t entity, tree_t comp, tree_t inst, case T_REF: if (tree_kind(tree_ref(value)) == T_ENUM_LIT) break; - else if (tree_class(eg) == C_PACKAGE) + else if (tree_class(g) == C_PACKAGE) break; // Fall-through case T_ARRAY_REF: @@ -974,9 +906,7 @@ static void elab_generics(tree_t entity, tree_t comp, tree_t inst, ctx->parent->lowered, ctx->parent->context); - if (folded == value) - break; - else if (tree_arena(map) != tree_arena(ctx->out)) { + if (folded != value) { tree_t m = tree_new(T_PARAM); tree_set_loc(m, tree_loc(map)); tree_set_subkind(m, P_POS); @@ -985,22 +915,6 @@ static void elab_generics(tree_t entity, tree_t comp, tree_t inst, map = m; } - else - tree_set_value(map, (value = folded)); - } - break; - - case T_OPEN: - // Make sure the default value comes from the component - // declaration rather than the entity - // XXX: if we followed LRM 93 section 9.6.1 correctly this - // wouldn't be necessary - if (tree_kind(comp) == T_COMPONENT && tree_has_value(cg)) { - map = tree_new(T_PARAM); - tree_set_loc(map, tree_loc(cg)); - tree_set_subkind(map, P_POS); - tree_set_pos(map, tree_pos(map)); - tree_set_value(map, tree_value(cg)); } break; @@ -1013,8 +927,9 @@ static void elab_generics(tree_t entity, tree_t comp, tree_t inst, if (is_literal(value)) { // These values can be safely substituted for all references to // the generic name - hash_put(ctx->generics, eg, value); - if (eg != cg) hash_put(ctx->generics, cg, value); + if (ctx->generics == NULL) + ctx->generics = hash_new(ngenerics * 2); + hash_put(ctx->generics, g, value); } } } @@ -1140,12 +1055,10 @@ static void elab_lower(tree_t b, vcode_unit_t shape, elab_ctx_t *ctx) diag_remove_hint_fn(elab_hint_fn); } -static void elab_mixed_port_map(tree_t block, tree_t inst, vlog_node_t mod) +static void elab_mixed_port_map(tree_t block, vlog_node_t mod, + const elab_ctx_t *ctx) { - tree_t comp = tree_ref(inst); - assert(tree_kind(comp) == T_COMPONENT); - - const int nports = tree_ports(comp); + const int nports = tree_ports(block); const int ndecls = vlog_decls(mod); bit_mask_t have; @@ -1168,86 +1081,79 @@ static void elab_mixed_port_map(tree_t block, tree_t inst, vlog_node_t mod) ident_t name = vlog_ident2(mport); - int cpos = 0; - tree_t cport = NULL, bport = NULL; - for (; cpos < nports; cpos++) { - tree_t pj = tree_port(comp, cpos); + tree_t vport = tree_port(ctx->out, i); + assert(tree_ident(vport) == vlog_ident(mport)); + + int bpos = 0; + tree_t bport = NULL; + for (; bpos < nports; bpos++) { + tree_t pj = tree_port(block, bpos); if (tree_ident(pj) == name) { - cport = pj; - mask_set(&have, cpos); - bport = tree_port(block, cpos); // XXX: need two levels of block + bport = pj; + mask_set(&have, bpos); break; } } - if (cport == NULL) { + if (bport == NULL) { + tree_t comp = tree_ref(ctx->inst); + assert(tree_kind(comp) == T_COMPONENT); + error_at(tree_loc(comp), "missing matching VHDL port declaration for " "Verilog port %s in component %s", istr(vlog_ident(mport)), istr(tree_ident(comp))); return; } - if (vlog_ident2(mport) != tree_ident(cport)) { - error_at(tree_loc(cport), "expected VHDL port name %s to match " + if (vlog_ident2(mport) != tree_ident(bport)) { + tree_t comp = tree_ref(ctx->inst); + assert(tree_kind(comp) == T_COMPONENT); + + error_at(tree_loc(bport), "expected VHDL port name %s to match " "Verilog port name %s in component %s", - istr(tree_ident(cport)), istr(vlog_ident(mport)), + istr(tree_ident(bport)), istr(vlog_ident(mport)), istr(tree_ident(comp))); return; } - type_t type = tree_type(cport); + type_t type = tree_type(bport); if (!type_eq(type, std_logic)) { - error_at(tree_loc(cport), "Verilog module ports must have " + error_at(tree_loc(bport), "Verilog module ports must have " "type STD_LOGIC or STD_LOGIC_VECTOR"); return; } - tree_t map = tree_param(inst, cpos); - if (tree_subkind(map) != P_POS) { - error_at(tree_loc(map), "this form of port map is not supported when " - "instantiating a Verilog module"); - return; - } - - tree_t value = tree_value(map); - const tree_kind_t value_kind = tree_kind(value); - if (value_kind == T_TYPE_CONV || value_kind == T_CONV_FUNC) { - error_at(tree_loc(map), "type conversions are not supported in port " - "maps when instantiating a Verilog module"); - return; - } - if (vlog_subkind(mport) == V_PORT_INPUT) { tree_t conv = tree_new(T_CONV_FUNC); - tree_set_loc(conv, tree_loc(map)); + tree_set_loc(conv, tree_loc(bport)); tree_set_ref(conv, to_verilog); tree_set_ident(conv, tree_ident(to_verilog)); tree_set_type(conv, type_result(tree_type(to_verilog))); - tree_set_value(conv, value); + tree_set_value(conv, make_ref(bport)); if (have_named) - add_param(block, conv, P_NAMED, make_ref(bport)); + add_param(ctx->out, conv, P_NAMED, make_ref(vport)); else - add_param(block, conv, P_POS, NULL); + add_param(ctx->out, conv, P_POS, NULL); } else { tree_t conv = tree_new(T_CONV_FUNC); - tree_set_loc(conv, tree_loc(map)); + tree_set_loc(conv, tree_loc(bport)); tree_set_ref(conv, to_vhdl); tree_set_ident(conv, tree_ident(to_vhdl)); tree_set_type(conv, type_result(tree_type(to_vhdl))); - tree_set_value(conv, make_ref(bport)); + tree_set_value(conv, make_ref(vport)); - add_param(block, value, P_NAMED, conv); + add_param(ctx->out, make_ref(bport), P_NAMED, conv); have_named = true; } - cpos++; + bpos++; } for (int i = 0; i < nports; i++) { if (!mask_test(&have, i)) { - tree_t p = tree_port(comp, i); + tree_t p = tree_port(block, i); diag_t *d = diag_new(DIAG_ERROR, tree_loc(p)); diag_printf(d, "port %s not found in Verilog module %s", istr(tree_ident(p)), istr(vlog_ident2(mod))); @@ -1258,7 +1164,7 @@ static void elab_mixed_port_map(tree_t block, tree_t inst, vlog_node_t mod) mask_free(&have); } -static void elab_verilog_module(tree_t wrap, tree_t inst, elab_ctx_t *ctx) +static void elab_verilog_module(tree_t wrap, const elab_ctx_t *ctx) { vlog_node_t mod = tree_vlog(wrap); @@ -1268,7 +1174,29 @@ static void elab_verilog_module(tree_t wrap, tree_t inst, elab_ctx_t *ctx) hash_put(ctx->shapes, mod, shape); } - vlog_trans(mod, ctx->out); + ident_t label = ident_rfrom(vlog_ident(mod), '.'); + + const char *label_str = istr(label); + ident_t npath = hpathf(ctx->path_name, ':', "%s", label_str); + ident_t ninst = hpathf(ctx->inst_name, ':', "%s", label_str); + ident_t ndotted = ident_prefix(ctx->dotted, label, '.'); + + elab_ctx_t new_ctx = { + .path_name = npath, + .inst_name = ninst, + .dotted = ndotted, + }; + elab_inherit_context(&new_ctx, ctx); + + tree_t b = tree_new(T_BLOCK); + tree_set_ident(b, label); + tree_set_loc(b, tree_loc(ctx->out)); + + tree_add_stmt(ctx->out, b); + new_ctx.out = b; + + elab_push_scope(wrap, &new_ctx); + vlog_trans(mod, b); const int nstmts = vlog_stmts(mod); for (int i = 0; i < nstmts; i++) { @@ -1279,89 +1207,58 @@ static void elab_verilog_module(tree_t wrap, tree_t inst, elab_ctx_t *ctx) tree_set_loc(w, vlog_loc(s)); tree_set_vlog(w, s); - tree_add_stmt(ctx->out, w); + tree_add_stmt(b, w); } - if (inst != NULL) - elab_mixed_port_map(ctx->out, inst, mod); + if (ctx->inst != NULL) + elab_mixed_port_map(ctx->out, mod, &new_ctx); + + if (error_count() == 0) + elab_lower(b, shape, &new_ctx); - elab_lower(ctx->out, shape, ctx); + elab_pop_scope(&new_ctx); } -static void elab_instance(tree_t t, const elab_ctx_t *ctx) +static void elab_architecture(tree_t bind, tree_t arch, const elab_ctx_t *ctx) { - tree_t arch = NULL, config = NULL; + tree_t inst = NULL; + ident_t label, ninst = NULL, npath = NULL; + switch (tree_kind(bind)) { + case T_BINDING: + label = ident_rfrom(tree_ident(tree_primary(arch)), '.'); + break; + case T_INSTANCE: + { + label = tree_ident(bind); + inst = bind; - const char *label = istr(tree_ident(t)); - ident_t npath = hpathf(ctx->path_name, ':', "%s", label); - ident_t ninst = hpathf(ctx->inst_name, ':', "%s", label); - ident_t ndotted = ident_prefix(ctx->dotted, tree_ident(t), '.'); + const char *label_str = istr(label); + npath = hpathf(ctx->path_name, ':', "%s", label_str); + ninst = hpathf(ctx->inst_name, ':', "%s", label_str); + } + break; + default: + fatal_trace("unexpected binding kind %s in elab_architecture", + tree_kind_str(tree_kind(bind))); + } + + ident_t ndotted = ident_prefix(ctx->dotted, label, '.'); elab_ctx_t new_ctx = { .path_name = npath, .inst_name = ninst, .dotted = ndotted, - .inst = t, + .inst = inst, }; elab_inherit_context(&new_ctx, ctx); - tree_t ref = tree_ref(t); - switch (tree_kind(ref)) { - case T_ENTITY: - arch = elab_pick_arch(tree_loc(t), ref, &new_ctx); - break; - - case T_ARCH: - arch = ref; - break; - - case T_COMPONENT: - if (tree_has_spec(t)) - arch = elab_binding(t, tree_spec(t), &new_ctx); - else - arch = elab_default_binding(t, &new_ctx); - break; - - case T_CONFIGURATION: - { - config = ref; - arch = tree_ref(tree_decl(ref, 0)); - assert(tree_kind(arch) == T_ARCH); - } - break; - - default: - fatal_trace("unexpected tree kind %s in elab_instance", - tree_kind_str(tree_kind(ref))); - } - tree_t b = tree_new(T_BLOCK); - tree_set_ident(b, tree_ident(t)); - tree_set_loc(b, tree_loc(t)); + tree_set_ident(b, label); + tree_set_loc(b, tree_loc(bind)); tree_add_stmt(ctx->out, b); new_ctx.out = b; - if (arch == NULL) { - assert(tree_kind(ref) == T_COMPONENT); - - elab_push_scope(ref, &new_ctx); - elab_generics(ref, ref, t, &new_ctx); - elab_ports(ref, ref, t, &new_ctx); - - if (error_count() == 0) - elab_lower(b, NULL, &new_ctx); - - elab_pop_scope(&new_ctx); - return; - } - else if (tree_kind(arch) == T_VERILOG) { - elab_push_scope(arch, &new_ctx); - elab_verilog_module(arch, t, &new_ctx); - elab_pop_scope(&new_ctx); - return; - } - new_ctx.inst_name = hpathf(new_ctx.inst_name, '@', "%s(%s)", simple_name(istr(tree_ident2(arch))), simple_name(istr(tree_ident(arch)))); @@ -1369,22 +1266,16 @@ static void elab_instance(tree_t t, const elab_ctx_t *ctx) elab_subprogram_prefix(arch, &new_ctx); - tree_t arch_copy; - if (config != NULL) - arch_copy = elab_root_config(config, &new_ctx); - else - arch_copy = elab_copy(arch, &new_ctx); - + tree_t arch_copy = elab_copy(arch, &new_ctx); tree_t entity = tree_primary(arch_copy); - tree_t comp = primary_unit_of(tree_ref(t)); elab_push_scope(arch, &new_ctx); elab_context(entity); elab_context(arch_copy); - elab_generics(entity, comp, t, &new_ctx); + elab_generics(entity, bind, &new_ctx); elab_instance_fixup(arch_copy, &new_ctx); simplify_global(arch_copy, new_ctx.generics, ctx->jit, ctx->registry); - elab_ports(entity, comp, t, &new_ctx); + elab_ports(entity, bind, &new_ctx); elab_decls(entity, &new_ctx); if (error_count() == 0) @@ -1400,6 +1291,93 @@ static void elab_instance(tree_t t, const elab_ctx_t *ctx) elab_pop_scope(&new_ctx); } +static void elab_component(tree_t inst, tree_t comp, const elab_ctx_t *ctx) +{ + tree_t arch, bind; + if (tree_has_spec(inst)) { + tree_t spec = tree_spec(inst); + arch = elab_binding(inst, spec, ctx); + bind = arch ? tree_value(spec) : NULL; + } + else { + bind = elab_default_binding(inst, ctx); + if (bind == NULL) + arch = NULL; + else if (tree_kind(bind) == T_VERILOG) + arch = bind; // XXX: generate binding for Verilog module too + else + arch = tree_ref(bind); + } + + const char *label = istr(tree_ident(inst)); + ident_t npath = hpathf(ctx->path_name, ':', "%s", label); + ident_t ninst = hpathf(ctx->inst_name, ':', "%s", label); + ident_t ndotted = ident_prefix(ctx->dotted, tree_ident(inst), '.'); + + elab_ctx_t new_ctx = { + .path_name = npath, + .inst_name = ninst, + .dotted = ndotted, + .inst = inst, + }; + elab_inherit_context(&new_ctx, ctx); + + tree_t b = tree_new(T_BLOCK); + tree_set_ident(b, tree_ident(inst)); + tree_set_loc(b, tree_loc(inst)); + + tree_add_stmt(ctx->out, b); + new_ctx.out = b; + + elab_push_scope(comp, &new_ctx); + elab_generics(comp, inst, &new_ctx); + elab_ports(comp, inst, &new_ctx); + + if (error_count() == 0) + elab_lower(b, NULL, &new_ctx); + + if (arch == NULL) + ; // Unbound architecture + else if (tree_kind(arch) == T_VERILOG) + elab_verilog_module(arch, &new_ctx); + else if (error_count() == 0) + elab_architecture(bind, arch, &new_ctx); + + elab_pop_scope(&new_ctx); +} + +static void elab_instance(tree_t t, const elab_ctx_t *ctx) +{ + tree_t ref = tree_ref(t); + switch (tree_kind(ref)) { + case T_ENTITY: + { + tree_t arch = elab_pick_arch(tree_loc(t), ref, ctx); + elab_architecture(t, arch, ctx); + } + break; + + case T_ARCH: + elab_architecture(t, ref, ctx); + break; + + case T_COMPONENT: + elab_component(t, ref, ctx); + break; + + case T_CONFIGURATION: + { + tree_t arch = elab_root_config(ref, ctx); + elab_architecture(t, arch, ctx); + } + break; + + default: + fatal_trace("unexpected tree kind %s in elab_instance", + tree_kind_str(tree_kind(ref))); + } +} + static void elab_decls(tree_t t, const elab_ctx_t *ctx) { const int ndecls = tree_decls(t); @@ -1760,8 +1738,8 @@ static void elab_block(tree_t t, const elab_ctx_t *ctx) const int base_errors = error_count(); elab_push_scope(t, &new_ctx); - elab_generics(t, t, t, &new_ctx); - elab_ports(t, t, t, &new_ctx); + elab_generics(t, t, &new_ctx); + elab_ports(t, t, &new_ctx); elab_decls(t, &new_ctx); if (error_count() == base_errors) { @@ -1844,7 +1822,7 @@ static void elab_top_level(tree_t arch, ident_t ename, const elab_ctx_t *ctx) ident_t ninst = hpathf(ctx->inst_name, ':', ":%s(%s)", name, simple_name(istr(tree_ident(arch)))); ident_t npath = hpathf(ctx->path_name, ':', ":%s", name); - ident_t ndotted = ident_prefix(lib_name(ctx->library), ename, '.'); + ident_t ndotted = ident_prefix(ctx->dotted, ename, '.'); tree_t b = tree_new(T_BLOCK); tree_set_ident(b, ename); @@ -1887,38 +1865,6 @@ static void elab_top_level(tree_t arch, ident_t ename, const elab_ctx_t *ctx) elab_pop_scope(&new_ctx); } -static void elab_verilog_top_level(vlog_node_t mod, const elab_ctx_t *ctx) -{ - tree_t wrap = tree_new(T_VERILOG); - tree_set_loc(wrap, vlog_loc(mod)); - tree_set_ident(wrap, vlog_ident(mod)); - tree_set_vlog(wrap, mod); - - ident_t base = ident_rfrom(vlog_ident(mod), '.'); - - const char *name = simple_name(istr(base)); - ident_t ninst = hpathf(ctx->inst_name, ':', ":%s(verilog)", name); - ident_t npath = hpathf(ctx->path_name, ':', ":%s", name); - - tree_t b = tree_new(T_BLOCK); - tree_set_ident(b, base); - tree_set_loc(b, vlog_loc(mod)); - - tree_add_stmt(ctx->out, b); - - elab_ctx_t new_ctx = { - .out = b, - .path_name = npath, - .inst_name = ninst, - .dotted = vlog_ident(mod), - }; - elab_inherit_context(&new_ctx, ctx); - - elab_push_scope(wrap, &new_ctx); - elab_verilog_module(wrap, NULL, &new_ctx); - elab_pop_scope(&new_ctx); -} - void elab_set_generic(const char *name, const char *value) { ident_t id = ident_new(name); @@ -1957,16 +1903,19 @@ tree_t elab(object_t *top, jit_t *jit, unit_registry_t *ur, cover_data_t *cover) tree_set_ident(e, name); tree_set_loc(e, &(top->loc)); + lib_t work = lib_work(); + elab_ctx_t ctx = { .out = e, .root = e, .path_name = NULL, .inst_name = NULL, .cover = cover, - .library = lib_work(), + .library = work, .jit = jit, .registry = ur, .shapes = hash_new(16), + .dotted = lib_name(work), }; if (vhdl != NULL) { @@ -1990,8 +1939,14 @@ tree_t elab(object_t *top, jit_t *jit, unit_registry_t *ur, cover_data_t *cover) fatal("%s is not a suitable top-level unit", istr(tree_ident(vhdl))); } } - else - elab_verilog_top_level(vlog, &ctx); + else { + tree_t wrap = tree_new(T_VERILOG); + tree_set_loc(wrap, vlog_loc(vlog)); + tree_set_ident(wrap, vlog_ident(vlog)); + tree_set_vlog(wrap, vlog); + + elab_verilog_module(wrap, &ctx); + } hash_free(ctx.shapes); diff --git a/src/lower.c b/src/lower.c index 936bf37a..81411619 100644 --- a/src/lower.c +++ b/src/lower.c @@ -2995,14 +2995,6 @@ static vcode_reg_t lower_generic_ref(lower_unit_t *lu, tree_t decl, vcode_reg_t context = emit_link_package(tree_ident(unit)); ptr_reg = emit_link_var(context, tree_ident(decl), lower_type(type)); } - else if (vcode_unit_kind(lu->vunit) == VCODE_UNIT_INSTANCE) { - // This can happen when a type contains a reference to a - // component generic. The elaborator does not currently rewrite - // it to point at the corresponding entity generic. - - var = vcode_find_var(tree_ident(decl)); - assert(var != VCODE_INVALID_VAR); - } else if (lu->mode == LOWER_THUNK) { type_t type = tree_type(decl); emit_comment("Cannot resolve generic %s", istr(tree_ident(decl))); diff --git a/src/rt/wave.c b/src/rt/wave.c index 3fc80820..8430d91a 100644 --- a/src/rt/wave.c +++ b/src/rt/wave.c @@ -760,6 +760,7 @@ static void fst_process_hier(wave_dumper_t *wd, tree_t h, tree_t block) case T_FOR_GENERATE: st = FST_ST_VHDL_FOR_GENERATE; break; case T_IF_GENERATE: st = FST_ST_VHDL_IF_GENERATE; break; case T_PACKAGE: st = FST_ST_VHDL_PACKAGE; break; + case T_COMPONENT: st = FST_ST_VHDL_ARCHITECTURE; break; default: st = FST_ST_VHDL_ARCHITECTURE; warn_at(tree_loc(h), "no FST scope type for %s", @@ -797,6 +798,13 @@ static void fst_walk_design(wave_dumper_t *wd, tree_t block) ident_t hpath = tree_ident(h); + if (tree_subkind(h) == T_COMPONENT) { + // Skip over implicit block statement created for component + // instantiation + block = tree_stmt(block, 0); + assert(tree_kind(block) == T_BLOCK); + } + rt_scope_t *scope = find_scope(wd->model, block); if (scope == NULL) fatal_trace("missing scope for %s", istr(hpath)); diff --git a/src/sem.c b/src/sem.c index a08e9269..d6894f5c 100644 --- a/src/sem.c +++ b/src/sem.c @@ -6009,9 +6009,6 @@ static bool sem_check_spec(tree_t t, nametab_t *tab) return false; tree_t unit = tree_ref(bind); - if (tree_kind(unit) == T_CONFIGURATION) - return true; - tree_t entity = primary_unit_of(unit); assert(tree_kind(entity) == T_ENTITY); diff --git a/src/vhpi/vhpi-model.c b/src/vhpi/vhpi-model.c index 452b32ba..85e52a95 100644 --- a/src/vhpi/vhpi-model.c +++ b/src/vhpi/vhpi-model.c @@ -439,6 +439,7 @@ static void vhpi_lazy_block(c_abstractRegion *r); static void *vhpi_get_value_ptr(c_vhpiObject *obj); static c_typeDecl *vhpi_get_type(c_vhpiObject *obj); static vhpiClassKindT vhpi_get_prefix_kind(c_vhpiObject *obj); +static void vhpi_build_stmts(tree_t container, c_abstractRegion *region); static vhpi_context_t *global_context = NULL; // TODO: thread local @@ -3474,6 +3475,17 @@ static void vhpi_build_generics(tree_t unit, c_abstractRegion *region) } } +static void vhpi_lazy_component(c_abstractRegion *r) +{ + tree_t inner = tree_stmt(r->tree, 0); + assert(tree_kind(inner) == T_BLOCK); + + vhpi_build_generics(r->tree, r); + vhpi_build_ports(r->tree, r); + vhpi_build_decls(inner, r); + vhpi_build_stmts(inner, r); +} + static void vhpi_build_stmts(tree_t container, c_abstractRegion *region) { const int nstmts = tree_stmts(container); @@ -3489,9 +3501,15 @@ static void vhpi_build_stmts(tree_t container, c_abstractRegion *region) switch (tree_subkind(h)) { case T_BLOCK: r = build_blockStmt(s, region); + r->lazyfn = vhpi_lazy_block; break; case T_ARCH: r = build_compInstStmt(s, tree_ref(h), region); + r->lazyfn = vhpi_lazy_block; + break; + case T_COMPONENT: + r = build_compInstStmt(s, tree_ref(h), region); + r->lazyfn = vhpi_lazy_component; break; case T_FOR_GENERATE: r = build_forGenerate(s, region); @@ -3499,8 +3517,6 @@ static void vhpi_build_stmts(tree_t container, c_abstractRegion *region) default: continue; } - - r->lazyfn = vhpi_lazy_block; } break; default: diff --git a/test/elab/comp3.vhd b/test/elab/comp3.vhd index cf3306a4..eab677ee 100644 --- a/test/elab/comp3.vhd +++ b/test/elab/comp3.vhd @@ -33,8 +33,8 @@ architecture test of top is end component; begin - sub1_i: component sub1; + sub1_i: component sub1; -- Error - sub2_i: component sub2; + sub2_i: component sub2; -- Error end architecture; diff --git a/test/elab/jcore2.vhd b/test/elab/jcore2.vhd new file mode 100644 index 00000000..9a7fab4b --- /dev/null +++ b/test/elab/jcore2.vhd @@ -0,0 +1,87 @@ +entity bist_RF1 is + generic ( WIDTH : natural range 1 to 32 ); + port ( + D : in bit_vector(WIDTH-1 downto 0)); +begin +end bist_RF1; + +architecture bist of bist_RF1 is +begin +end bist; + +configuration bist_rf1_inferred of bist_RF1 is + for bist + end for; +end configuration; + +------------------------------------------------------------------------------- + +entity gpsif_regfile is +end gpsif_regfile; +architecture beh of gpsif_regfile is + +component bist_RF1 + generic ( WIDTH : natural range 1 to 32 ); + port ( D : in bit_vector(WIDTH-1 downto 0) ); +end component; + +signal x : bit_vector(19 downto 0); +signal y : bit_vector(29 downto 0); +begin + sftca_bank : bist_RF1 + generic map ( WIDTH => 20 ) + port map + (D => x); -- OK + pnco_bank : bist_RF1 + generic map ( WIDTH => 30 ) + port map + ( D => y); -- OK +end beh; + +------------------------------------------------------------------------------- + +entity gpsif is +end gpsif; +architecture beh of gpsif is +component gpsif_regfile is +end component; + +begin + regfile : gpsif_regfile; + +end beh; + +------------------------------------------------------------------------------- + +entity gpsif_top is +end entity; + +architecture arch of gpsif_top is + component gpsif is + end component; +begin + g : gpsif; +end architecture; + +------------------------------------------------------------------------------- + +configuration gpsif_sim of gpsif is + for beh + for regfile : gpsif_regfile + use entity work.gpsif_regfile(beh); + for beh + for all : bist_RF1 + use configuration work.bist_rf1_inferred; + end for; + end for; + end for; + end for; +end configuration; + +configuration gpsif_top_sim of gpsif_top is + for arch + for g : gpsif + use configuration work.gpsif_sim; + end for; + end for; +end configuration; diff --git a/test/parse/vests1.vhd b/test/parse/vests1.vhd index a4e77a08..9f1a13da 100644 --- a/test/parse/vests1.vhd +++ b/test/parse/vests1.vhd @@ -1,4 +1,22 @@ entity something is + port( + sigin1 : in boolean := false; + sigout1 : out boolean ; + sigin2 : in bit := '0'; + sigout2 : out bit ; + sigin4 : in severity_level := note ; + sigout4 : out severity_level ; + sigin5 : in integer := 0 ; + sigout5 : out integer ; + sigin6 : in real := 0.0; + sigout6 : out real ; + sigin7 : in time := 0 fs; + sigout7 : out time ; + sigin8 : in natural := 0 ; + sigout8 : out natural ; + sigin9 : in positive := 1 ; + sigout9 : out positive + ); end entity; architecture arch of something is diff --git a/test/regress/gold/wave9.dump b/test/regress/gold/wave9.dump new file mode 100644 index 00000000..ac93ea46 --- /dev/null +++ b/test/regress/gold/wave9.dump @@ -0,0 +1,8 @@ +$comment wave9.u.ii is aliased to x $end +$comment wave9.u.oo is aliased to y $end +#0 wave9.y 0 +#0 wave9.x 0 +#1000000 wave9.x 1 +#1001000 wave9.y 1 +#2000000 wave9.x 0 +#2001000 wave9.y 0 diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 77ddc1f4..b433b01a 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -934,3 +934,4 @@ bounds43 fail,gold signal35 normal,2008 comp3 normal conv13 normal +wave9 wave diff --git a/test/regress/wave9.vhd b/test/regress/wave9.vhd new file mode 100644 index 00000000..ea0a76ed --- /dev/null +++ b/test/regress/wave9.vhd @@ -0,0 +1,30 @@ +entity sub is + port ( ii : in bit; oo : out bit ); +end entity; + +architecture test of sub is +begin + oo <= ii after 1 ps; +end architecture; + +------------------------------------------------------------------------------- + +entity wave9 is +end entity; + +architecture test of wave9 is + component sub is + port ( i : in bit; o : out bit ); + end component; + + for u : sub use entity work.sub + port map ( ii => i, oo => o ); + + signal x, y : bit; +begin + + u: sub port map ( x, y ); + + x <= '1' after 1 ns, '0' after 2 ns; + +end architecture; diff --git a/test/test_elab.c b/test/test_elab.c index d61841d8..e469d4d1 100644 --- a/test/test_elab.c +++ b/test/test_elab.c @@ -107,8 +107,10 @@ START_TEST(test_comp) input_from_file(TESTDIR "/elab/comp.vhd"); const error_t expect[] = { - { 55, "port Y not found in entity WORK.E2" }, - { 62, "type of port X in component declaration E3 is BIT" }, + { 77, "port X in entity WORK.E2 without a default value has no " + "corresponding port in component E2" }, + { 83, "port X in component E3 has type BIT which is incompatible " + "with type INTEGER in entity WORK.E3" }, { -1, NULL } }; expect_errors(expect); @@ -678,7 +680,17 @@ START_TEST(test_issue373) tree_t e = run_elab(); - tree_t p0 = tree_stmt(tree_stmt(tree_stmt(e, 0), 0), 0); + tree_t unit = tree_stmt(tree_stmt(e, 0), 0); + fail_unless(tree_kind(unit) == T_BLOCK); + fail_unless(tree_ident(unit) == ident_new("UNIT")); + fail_unless(tree_stmts(unit) == 1); + + tree_t sub = tree_stmt(unit, 0); + fail_unless(tree_kind(sub) == T_BLOCK); + fail_unless(tree_ident(sub) == ident_new("SUB")); + fail_unless(tree_stmts(sub) == 1); + + tree_t p0 = tree_stmt(sub, 0); fail_unless(tree_kind(p0) == T_PROCESS); tree_t s0 = tree_stmt(p0, 0); fail_unless(tree_kind(s0) == T_ASSERT); @@ -767,8 +779,15 @@ START_TEST(test_comp2) fail_unless(tree_kind(top) == T_BLOCK); fail_unless(tree_stmts(top) == 2); - tree_t sub1 = tree_stmt(top, 0); + tree_t sub1_i = tree_stmt(top, 0); + fail_unless(tree_kind(sub1_i) == T_BLOCK); + fail_unless(tree_ident(sub1_i) == ident_new("SUB1_I")); + fail_unless(tree_generics(sub1_i) == 0); + fail_unless(tree_genmaps(sub1_i) == 0); + + tree_t sub1 = tree_stmt(sub1_i, 0); fail_unless(tree_kind(sub1) == T_BLOCK); + fail_unless(tree_ident(sub1) == ident_new("SUB1")); fail_unless(tree_generics(sub1) == 1); fail_unless(tree_genmaps(sub1) == 1); @@ -780,8 +799,15 @@ START_TEST(test_comp2) fail_unless(tree_kind(sub1_y) == T_LITERAL); fail_unless(tree_ival(sub1_y) == 4); - tree_t sub2 = tree_stmt(top, 1); + tree_t sub2_i = tree_stmt(top, 1); + fail_unless(tree_kind(sub2_i) == T_BLOCK); + fail_unless(tree_ident(sub2_i) == ident_new("SUB2_I")); + fail_unless(tree_generics(sub2_i) == 2); + fail_unless(tree_genmaps(sub2_i) == 2); + + tree_t sub2 = tree_stmt(sub2_i, 0); fail_unless(tree_kind(sub2) == T_BLOCK); + fail_unless(tree_ident(sub2) == ident_new("SUB2")); fail_unless(tree_generics(sub2) == 2); fail_unless(tree_genmaps(sub2) == 2); @@ -802,9 +828,13 @@ START_TEST(test_comp3) input_from_file(TESTDIR "/elab/comp3.vhd"); const error_t expect[] = { - { 36, "missing value for generic X with no default" }, - { 31, "type of generic X in component declaration SUB2 is BOOLEAN which" - " does not match type INTEGER in entity WORK.SUB2" }, + { 36, "generic X in entity WORK.SUB1 without a default value has no " + "corresponding generic in component SUB1" }, + { 0, "declaration of generic X in entity" }, + { 38, "generic X in component SUB2 has type BOOLEAN which is " + "incompatible with type INTEGER in entity WORK.SUB2" }, + { 0, "declaration of generic X in component" }, + { 0, "declaration of generic X in entity" }, { -1, NULL } }; expect_errors(expect); @@ -870,11 +900,20 @@ START_TEST(test_tc846) fail_unless(tree_ident(a1) == ident_new("A1")); fail_unless(tree_stmts(a1) == 1); - tree_t c1 = tree_stmt(a1, 0); + tree_t fa = tree_stmt(a1, 0); + fail_unless(tree_ident(fa) == ident_new("FULL_ADDER")); + fail_unless(tree_stmts(fa) == 1); + + tree_t c1 = tree_stmt(fa, 0); fail_unless(tree_ident(c1) == ident_new("C1")); - fail_unless(tree_stmts(c1) == 0); - fail_unless(tree_decls(c1) == 2); - fail_unless(tree_ident(tree_decl(c1, 1)) == ident_new("X")); + fail_unless(tree_stmts(c1) == 1); + + tree_t and2g = tree_stmt(c1, 0); + fail_unless(tree_ident(and2g) == ident_new("AND2G")); + fail_unless(tree_stmts(and2g) == 0); + + fail_unless(tree_decls(and2g) == 2); + fail_unless(tree_ident(tree_decl(and2g, 1)) == ident_new("X")); fail_if_errors(); } @@ -917,10 +956,15 @@ START_TEST(test_issue442) tree_t dut = tree_stmt(b0, 0); fail_unless(tree_ident(dut) == ident_new("DUT")); fail_unless(tree_kind(dut) == T_BLOCK); - fail_unless(tree_stmts(dut) == 0); + fail_unless(tree_stmts(dut) == 1); fail_unless(tree_genmaps(dut) == 2); - tree_t m1 = tree_value(tree_genmap(dut, 1)); + tree_t sample = tree_stmt(dut, 0); + fail_unless(tree_ident(sample) == ident_new("SAMPLE")); + fail_unless(tree_kind(sample) == T_BLOCK); + fail_unless(tree_genmaps(sample) == 2); + + tree_t m1 = tree_value(tree_genmap(sample, 1)); fail_unless(tree_kind(m1) == T_LITERAL); fail_unless(tree_ival(m1) == 4); @@ -942,10 +986,16 @@ START_TEST(test_issue448) tree_t tb = tree_stmt(b0, 0); fail_unless(tree_ident(tb) == ident_new("TB")); fail_unless(tree_kind(tb) == T_BLOCK); - fail_unless(tree_stmts(tb) == 0); - fail_unless(tree_genmaps(tb) == 6); + fail_unless(tree_stmts(tb) == 1); + fail_unless(tree_genmaps(tb) == 5); + + tree_t inner = tree_stmt(tb, 0); + fail_unless(tree_ident(inner) == + ident_new("IMAGE_STREAM_BUFFER_TEST_BENCH")); + fail_unless(tree_kind(inner) == T_BLOCK); + fail_unless(tree_genmaps(inner) == 6); - tree_t m1 = tree_value(tree_genmap(tb, 2)); + tree_t m1 = tree_value(tree_genmap(inner, 2)); fail_unless(tree_kind(m1) == T_LITERAL); fail_unless(tree_ival(m1) == 8192); @@ -1736,6 +1786,17 @@ START_TEST(test_bounds11) } END_TEST +START_TEST(test_jcore2) +{ + input_from_file(TESTDIR "/elab/jcore2.vhd"); + + tree_t e = run_elab(); + fail_if(e == NULL); + + fail_if_errors(); +} +END_TEST + Suite *get_elab_tests(void) { Suite *s = suite_create("elab"); @@ -1831,6 +1892,7 @@ Suite *get_elab_tests(void) tcase_add_test(tc, test_gentype1); tcase_add_test(tc, test_bounds7); tcase_add_test(tc, test_bounds11); + tcase_add_test(tc, test_jcore2); suite_add_tcase(s, tc); return s; diff --git a/test/test_lower.c b/test/test_lower.c index 87349aed..76bc61fd 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -3711,12 +3711,12 @@ START_TEST(test_issue426) run_elab(); - vcode_unit_t vu = find_unit("WORK.TEST_1_1.U"); + vcode_unit_t vu = find_unit("WORK.TEST_1_1.U.TEST_1"); vcode_select_unit(vu); EXPECT_BB(0) = { - { VCODE_OP_PACKAGE_INIT, .name = "STD.STANDARD" }, { VCODE_OP_PACKAGE_INIT, .name = "WORK.CORE" }, + { VCODE_OP_PACKAGE_INIT, .name = "STD.STANDARD" }, { VCODE_OP_INDEX, .name = "EXP_STATUS" }, { VCODE_OP_VAR_UPREF, .hops = 1, .name = "EXP_STATUS" }, { VCODE_OP_COPY }, @@ -3733,29 +3733,57 @@ START_TEST(test_instance1) run_elab(); - vcode_unit_t vu = find_unit("WORK.INSTANCE1.SUB_I"); - vcode_select_unit(vu); + { + vcode_unit_t vu = find_unit("WORK.INSTANCE1.SUB_I"); + vcode_select_unit(vu); - fail_unless(vcode_unit_kind(vu) == VCODE_UNIT_INSTANCE); + fail_unless(vcode_unit_kind(vu) == VCODE_UNIT_INSTANCE); - EXPECT_BB(0) = { - { VCODE_OP_PACKAGE_INIT, .name = "STD.STANDARD" }, - { VCODE_OP_CONST, .value = 5 }, - { VCODE_OP_CONST, .value = 0 }, - { VCODE_OP_STORE, .name = "WIDTH" }, - { VCODE_OP_CONST_ARRAY, .length = 5 }, - { VCODE_OP_ADDRESS_OF }, - { VCODE_OP_CONST, .value = 1 }, - { VCODE_OP_CONST, .value = 5 }, - { VCODE_OP_DEBUG_LOCUS }, - { VCODE_OP_CONST, .value = 0 }, - { VCODE_OP_INIT_SIGNAL }, - { VCODE_OP_STORE, .name = "X" }, - { VCODE_OP_MAP_CONST }, - { VCODE_OP_RETURN } - }; + EXPECT_BB(0) = { + { VCODE_OP_PACKAGE_INIT, .name = "STD.STANDARD" }, + { VCODE_OP_CONST, .value = 5 }, + { VCODE_OP_CONST, .value = 0 }, + { VCODE_OP_STORE, .name = "WIDTH" }, + { VCODE_OP_CONST_ARRAY, .length = 5 }, + { VCODE_OP_ADDRESS_OF }, + { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 5 }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_CONST, .value = 0 }, + { VCODE_OP_INIT_SIGNAL }, + { VCODE_OP_WRAP }, + { VCODE_OP_STORE, .name = "X" }, + { VCODE_OP_MAP_CONST }, + { VCODE_OP_RETURN } + }; - CHECK_BB(0); + CHECK_BB(0); + } + + { + vcode_unit_t vu = find_unit("WORK.INSTANCE1.SUB_I.SUB"); + vcode_select_unit(vu); + + fail_unless(vcode_unit_kind(vu) == VCODE_UNIT_INSTANCE); + + EXPECT_BB(0) = { + { VCODE_OP_PACKAGE_INIT, .name = "STD.STANDARD" }, + { VCODE_OP_CONST, .value = 5 }, + { VCODE_OP_STORE, .name = "WIDTH" }, + { VCODE_OP_VAR_UPREF, .hops = 1, .name = "X" }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_CONST, .value = 5 }, + { VCODE_OP_UARRAY_LEN }, + { VCODE_OP_LENGTH_CHECK }, + { VCODE_OP_UNWRAP }, + { VCODE_OP_STORE, .name = "X" }, + { VCODE_OP_RETURN } + }; + + CHECK_BB(0); + } } END_TEST @@ -5057,7 +5085,7 @@ START_TEST(test_link1) run_elab(); - vcode_unit_t vu = find_unit("WORK.LINK1.U"); + vcode_unit_t vu = find_unit("WORK.LINK1.U.SUB"); vcode_select_unit(vu); EXPECT_BB(0) = { diff --git a/test/test_simp.c b/test/test_simp.c index d3467906..1e170871 100644 --- a/test/test_simp.c +++ b/test/test_simp.c @@ -1383,9 +1383,14 @@ START_TEST(test_casefold1) tree_t uut = tree_stmt(b0, 1); fail_unless(tree_kind(uut) == T_BLOCK); fail_unless(tree_ident(uut) == ident_new("UUT")); - fail_unless(tree_stmts(uut) == 2); + fail_unless(tree_stmts(uut) == 1); - tree_t casep = tree_stmt(uut, 1); + tree_t mycomp = tree_stmt(uut, 0); + fail_unless(tree_kind(mycomp) == T_BLOCK); + fail_unless(tree_ident(mycomp) == ident_new("MYCOMP")); + fail_unless(tree_stmts(mycomp) == 2); + + tree_t casep = tree_stmt(mycomp, 1); fail_unless(tree_kind(casep) == T_PROCESS); fail_unless(tree_ident(casep) == ident_new("CASEP")); -- 2.39.2