From 0ba0cfc90856325a74608fdd0dd0a6eac7cb4ce5 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 18 Feb 2018 18:46:23 +0000 Subject: [PATCH] Improve parsing of configurations. Issue #372 --- src/dump.c | 225 +++++++++++++++++++++++++++++------------- src/nvc.c | 2 +- src/parse.c | 48 ++++++--- src/sem.c | 35 +++++-- src/tree.c | 59 +++++------ src/tree.h | 5 +- src/util.c | 8 +- src/util.h | 1 + src/vcode.c | 6 ++ test/parse/vests1.vhd | 18 ++++ test/test_parse.c | 44 ++++++++- test/test_sem.c | 2 +- 12 files changed, 329 insertions(+), 124 deletions(-) create mode 100644 test/parse/vests1.vhd diff --git a/src/dump.c b/src/dump.c index 1e2f70f5..4f425351 100644 --- a/src/dump.c +++ b/src/dump.c @@ -32,6 +32,7 @@ static void dump_expr(tree_t t); static void dump_stmt(tree_t t, int indent); static void dump_port(tree_t t, int indent); static void dump_decl(tree_t t, int indent); +static void dump_decls(tree_t t, int indent); typedef tree_t (*get_fn_t)(tree_t, unsigned); @@ -50,6 +51,49 @@ static void cannot_dump(tree_t t, const char *hint) fatal("cannot dump %s kind %s", hint, tree_kind_str(tree_kind(t))); } +__attribute__((format(printf,1,2))) +static void syntax(const char *fmt, ...) +{ + LOCAL_TEXT_BUF tb = tb_new(); + bool highlighting = false; + bool comment = false; + for (const char *p = fmt; *p != '\0'; p++) { + if (comment) { + if (*p == '\n') { + comment = false; + tb_printf(tb, "$$"); + } + tb_append(tb, *p); + } + else if (*p == '#') { + tb_printf(tb, "$bold$$cyan$"); + highlighting = true; + } + else if (*p == '~') { + tb_printf(tb, "$yellow$"); + highlighting = true; + } + else if (*p == '-' && *(p + 1) == '-') { + tb_printf(tb, "$red$-"); + comment = true; + } + else if (!isalnum((int)*p) && *p != '_' && *p != '%' && highlighting) { + tb_printf(tb, "$$%c", *p); + highlighting = false; + } + else + tb_append(tb, *p); + } + + if (highlighting) + tb_printf(tb, "$$"); + + va_list ap; + va_start(ap, fmt); + color_vprintf(tb_get(tb), ap); + va_end(ap); +} + static void dump_params(tree_t t, get_fn_t get, int n, const char *prefix) { if (n > 0) { @@ -227,12 +271,32 @@ static void dump_expr(tree_t t) } } +static const char *dump_minify_type(const char *name) +{ + static const char *known[] = { + "STD.STANDARD.", + "IEEE.NUMERIC_STD.", + "IEEE.STD_LOGIC_1164.", + }; + + for (size_t i = 0; i < ARRAY_LEN(known); i++) { + const size_t len = strlen(known[i]); + if (strncmp(name, known[i], len) == 0) { + static char buf[256]; + checked_sprintf(buf, sizeof(buf), "~%s%%s", name + len); + return buf; + } + } + + return name; +} + static void dump_type(type_t type) { if (type_kind(type) == T_SUBTYPE && type_has_ident(type)) - printf("%s", type_pp(type)); + syntax(type_pp_minify(type, dump_minify_type), ""); else if (type_is_array(type) && !type_is_unconstrained(type)) { - printf("%s(", istr(type_ident(type))); + syntax(type_pp_minify(type, dump_minify_type), "("); const int ndims = array_dimension(type); for (int i = 0; i < ndims; i++) { if (i > 0) @@ -263,7 +327,7 @@ static void dump_type(type_t type) printf(")"); } else - printf("%s", type_pp(type)); + syntax(type_pp_minify(type, dump_minify_type), ""); } static void dump_op(tree_t t, int indent) @@ -326,13 +390,13 @@ static void dump_wait_level(tree_t t) { switch (tree_attr_int(t, wait_level_i, WAITS_MAYBE)) { case WAITS_NO: - printf(" -- Never waits"); + syntax(" -- Never waits"); break; case WAITS_MAYBE: - printf(" -- Maybe waits"); + syntax(" -- Maybe waits"); break; case WAITS_YES: - printf(" -- Waits"); + syntax(" -- Waits"); break; } } @@ -343,15 +407,15 @@ static void dump_decl(tree_t t, int indent) switch (tree_kind(t)) { case T_SIGNAL_DECL: - printf("signal %s : ", istr(tree_ident(t))); + syntax("#signal %s : ", istr(tree_ident(t))); break; case T_VAR_DECL: - printf("variable %s : ", istr(tree_ident(t))); + syntax("#variable %s : ", istr(tree_ident(t))); break; case T_CONST_DECL: - printf("constant %s : ", istr(tree_ident(t))); + syntax("#constant %s : ", istr(tree_ident(t))); break; case T_TYPE_DECL: @@ -448,6 +512,19 @@ static void dump_decl(tree_t t, int indent) } return; + case T_SPEC: + syntax("#for %s\n", istr(tree_ident(t))); + tab(indent); + syntax("#end #for;\n"); + return; + + case T_BLOCK_CONFIG: + syntax("#for %s\n", istr(tree_ident(t))); + dump_decls(t, indent + 2); + tab(indent); + syntax("#end #for;\n"); + return; + case T_ALIAS: printf("alias %s : ", istr(tree_ident(t))); dump_type(tree_type(t)); @@ -457,14 +534,14 @@ static void dump_decl(tree_t t, int indent) return; case T_ATTR_SPEC: - printf("attribute %s of %s : %s is ", istr(tree_ident(t)), + syntax("#attribute %s #of %s : #%s #is ", istr(tree_ident(t)), istr(tree_ident2(t)), class_str(tree_class(t))); dump_expr(tree_value(t)); printf(";\n"); return; case T_ATTR_DECL: - printf("attribute %s : ", istr(tree_ident(t))); + syntax("#attribute %s : ", istr(tree_ident(t))); dump_type(tree_type(t)); printf(";\n"); return; @@ -476,9 +553,9 @@ static void dump_decl(tree_t t, int indent) return; case T_FUNC_DECL: - printf("function %s", istr(tree_ident(t))); + syntax("#function %s", istr(tree_ident(t))); dump_ports(t, indent); - printf(" return %s;\n", type_pp(type_result(tree_type(t)))); + syntax(" #return %s;\n", type_pp(type_result(tree_type(t)))); return; case T_FUNC_BODY: @@ -510,7 +587,7 @@ static void dump_decl(tree_t t, int indent) return; case T_HIER: - printf("-- Enter scope %s\n", istr(tree_ident(t))); + syntax("-- Enter scope %s\n", istr(tree_ident(t))); return; case T_COMPONENT: @@ -539,15 +616,15 @@ static void dump_decl(tree_t t, int indent) return; case T_PROT_BODY: - printf("type %s is protected body\n", istr(tree_ident(t))); + syntax("type %s #is #protected #body\n", istr(tree_ident(t))); for (unsigned i = 0; i < tree_decls(t); i++) dump_decl(tree_decl(t, i), indent + 2); tab(indent); - printf("end protected body;\n"); + syntax("#end #protected #body;\n"); return; case T_FILE_DECL: - printf("file %s : ", istr(tree_ident(t))); + syntax("#file %s : ", istr(tree_ident(t))); dump_type(tree_type(t)); if (tree_has_value(t)) { printf(" open "); @@ -559,7 +636,7 @@ static void dump_decl(tree_t t, int indent) return; case T_USE: - printf("use %s", istr(tree_ident(t))); + syntax("#use %s", istr(tree_ident(t))); if (tree_has_ident2(t)) printf(".%s", istr(tree_ident2(t))); printf(";\n"); @@ -592,7 +669,7 @@ static void dump_stmt(tree_t t, int indent) switch (tree_kind(t)) { case T_PROCESS: - printf("process "); + syntax("#process "); if (tree_triggers(t) > 0) { printf("("); for (unsigned i = 0; i < tree_triggers(t); i++) { @@ -602,32 +679,31 @@ static void dump_stmt(tree_t t, int indent) } printf(") "); } - printf("is\n"); - for (unsigned i = 0; i < tree_decls(t); i++) - dump_decl(tree_decl(t, i), indent + 2); + syntax("#is\n"); + dump_decls(t, indent + 2); tab(indent); - printf("begin\n"); + syntax("#begin\n"); for (unsigned i = 0; i < tree_stmts(t); i++) dump_stmt(tree_stmt(t, i), indent + 2); tab(indent); - printf("end process;\n\n"); + syntax("#end #process;\n\n"); return; case T_SIGNAL_ASSIGN: dump_expr(tree_target(t)); - printf(" <= reject "); + syntax(" <= #reject "); if (tree_has_reject(t)) dump_expr(tree_reject(t)); else printf("0 ps"); - printf(" inertial "); + syntax(" #inertial "); for (unsigned i = 0; i < tree_waveforms(t); i++) { if (i > 0) printf(", "); tree_t w = tree_waveform(t, i); dump_expr(tree_value(w)); if (tree_has_delay(w)) { - printf(" after "); + syntax(" #after "); dump_expr(tree_delay(w)); } } @@ -640,9 +716,9 @@ static void dump_stmt(tree_t t, int indent) break; case T_WAIT: - printf("wait"); + syntax("#wait"); if (tree_triggers(t) > 0) { - printf(" on "); + syntax(" #on "); for (unsigned i = 0; i < tree_triggers(t); i++) { if (i > 0) printf(", "); @@ -650,31 +726,31 @@ static void dump_stmt(tree_t t, int indent) } } if (tree_has_delay(t)) { - printf(" for "); + syntax(" #for "); dump_expr(tree_delay(t)); } printf(";"); if (tree_attr_int(t, ident_new("static"), 0)) - printf(" -- static"); + syntax(" -- static"); printf("\n"); return; case T_BLOCK: - printf("block is\n"); + syntax("#block #is\n"); dump_block(t, indent); - printf("end block"); + syntax("#end #block"); break; case T_ASSERT: if (tree_has_value(t)) { - printf("assert "); + syntax("#assert "); dump_expr(tree_value(t)); } if (tree_has_message(t)) { - printf(" report "); + syntax(" #report "); dump_expr(tree_message(t)); } - printf(" severity "); + syntax(" #severity "); dump_expr(tree_severity(t)); break; @@ -684,27 +760,27 @@ static void dump_stmt(tree_t t, int indent) dump_expr(tree_value(t)); printf(" "); } - printf("loop\n"); + syntax("#loop\n"); for (unsigned i = 0; i < tree_stmts(t); i++) dump_stmt(tree_stmt(t, i), indent + 2); tab(indent); - printf("end loop"); + syntax("#end #loop"); break; case T_IF: - printf("if "); + syntax("#if "); dump_expr(tree_value(t)); - printf(" then\n"); + syntax(" #then\n"); for (unsigned i = 0; i < tree_stmts(t); i++) dump_stmt(tree_stmt(t, i), indent + 2); if (tree_else_stmts(t) > 0) { tab(indent); - printf("else\n"); + printf("#else\n"); for (unsigned i = 0; i < tree_else_stmts(t); i++) dump_stmt(tree_else_stmt(t, i), indent + 2); } tab(indent); - printf("end if"); + syntax("#end #if"); break; case T_EXIT: @@ -865,11 +941,11 @@ static void dump_context(tree_t t) switch (tree_kind(c)) { case T_LIBRARY: if (tree_ident(c) != std_i && tree_ident(c) != work_i) - printf("library %s;\n", istr(tree_ident(c))); + syntax("#library %s;\n", istr(tree_ident(c))); break; case T_USE: - printf("use %s", istr(tree_ident(c))); + syntax("#use %s", istr(tree_ident(c))); if (tree_has_ident2(c)) { printf(".%s", istr(tree_ident2(c))); } @@ -888,22 +964,21 @@ static void dump_context(tree_t t) static void dump_elab(tree_t t) { dump_context(t); - printf("entity %s is\nend entity;\n\n", istr(tree_ident(t))); - printf("architecture elab of %s is\n", istr(tree_ident(t))); - for (unsigned i = 0; i < tree_decls(t); i++) - dump_decl(tree_decl(t, i), 2); - printf("begin\n"); + syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t))); + syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t))); + dump_decls(t, 2); + syntax("#begin\n"); for (unsigned i = 0; i < tree_stmts(t); i++) dump_stmt(tree_stmt(t, i), 2); - printf("end architecture;\n"); + syntax("#end #architecture;\n"); } static void dump_entity(tree_t t) { dump_context(t); - printf("entity %s is\n", istr(tree_ident(t))); + syntax("#entity %s #is\n", istr(tree_ident(t))); if (tree_generics(t) > 0) { - printf(" generic (\n"); + syntax(" #generic (\n"); for (unsigned i = 0; i < tree_generics(t); i++) { if (i > 0) printf(";\n"); @@ -913,7 +988,7 @@ static void dump_entity(tree_t t) printf(" );\n"); } if (tree_ports(t) > 0) { - printf(" port (\n"); + syntax(" #port (\n"); for (unsigned i = 0; i < tree_ports(t); i++) { if (i > 0) printf(";\n"); @@ -923,43 +998,54 @@ static void dump_entity(tree_t t) printf(" );\n"); } if (tree_stmts(t) > 0) { - printf("begin\n"); + syntax("#begin\n"); for (unsigned i = 0; i < tree_stmts(t); i++) { dump_stmt(tree_stmt(t, i), 2); } } - printf("end entity;\n"); + syntax("#end #entity;\n"); +} + +static void dump_decls(tree_t t, int indent) +{ + const int ndecls = tree_decls(t); + for (unsigned i = 0; i < ndecls; i++) + dump_decl(tree_decl(t, i), indent); } static void dump_arch(tree_t t) { dump_context(t); - printf("architecture %s of %s is\n", + syntax("#architecture %s #of %s #is\n", istr(tree_ident(t)), istr(tree_ident2(t))); - for (unsigned i = 0; i < tree_decls(t); i++) - dump_decl(tree_decl(t, i), 2); - printf("begin\n"); + syntax("#begin\n"); for (unsigned i = 0; i < tree_stmts(t); i++) dump_stmt(tree_stmt(t, i), 2); - printf("end architecture;\n"); + syntax("#end #architecture;\n"); } static void dump_package(tree_t t) { dump_context(t); - printf("package %s is\n", istr(tree_ident(t))); - for (unsigned i = 0; i < tree_decls(t); i++) - dump_decl(tree_decl(t, i), 2); - printf("end package;\n"); + syntax("#package %s #is\n", istr(tree_ident(t))); + dump_decls(t, 2); + syntax("#end #package;\n"); } static void dump_package_body(tree_t t) { dump_context(t); - printf("package body %s is\n", istr(tree_ident(t))); - for (unsigned i = 0; i < tree_decls(t); i++) - dump_decl(tree_decl(t, i), 2); - printf("end package body;\n"); + syntax("#package #body %s #is\n", istr(tree_ident(t))); + dump_decls(t, 2); + syntax("#end #package #body;\n"); +} + +static void dump_configuration(tree_t t) +{ + syntax("#configuration %s #of %s #is\n", + istr(tree_ident(t)), istr(tree_ident2(t))); + dump_decls(t, 2); + syntax("#end #configuration\n"); } void dump(tree_t t) @@ -980,6 +1066,9 @@ void dump(tree_t t) case T_PACK_BODY: dump_package_body(t); break; + case T_CONFIGURATION: + dump_configuration(t); + break; case T_FCALL: case T_LITERAL: case T_AGGREGATE: diff --git a/src/nvc.c b/src/nvc.c index 7f86ca74..76169af9 100644 --- a/src/nvc.c +++ b/src/nvc.c @@ -632,7 +632,7 @@ static void list_walk_fn(ident_t ident, int kind, void *context) case T_ENTITY: pretty = "Entity"; break; case T_PACKAGE: pretty = "Package"; break; case T_PACK_BODY: pretty = "Package body"; break; - case T_CONFIG: pretty = "Configuration"; break; + case T_CONFIGURATION: pretty = "Configuration"; break; } printf("%-30s : %s\n", istr(ident), pretty); diff --git a/src/parse.c b/src/parse.c index 961853cf..3eb622fb 100644 --- a/src/parse.c +++ b/src/parse.c @@ -130,11 +130,10 @@ static tree_t p_subprogram_declaration(tree_t spec); static tree_t p_subprogram_body(tree_t spec); static tree_t p_subprogram_specification(void); static tree_t p_name(void); -static void p_block_configuration(tree_t unit); +static tree_t p_block_configuration(void); static tree_t p_protected_type_body(void); static bool p_cond_analysis_expr(void); -static const char *token_str(token_t tok); static bool consume(token_t tok); static bool optional(token_t tok); @@ -4347,10 +4346,28 @@ static void p_configuration_item(tree_t unit) const token_t third = peek_nth(3); if ((third == tCOLON) || (third == tCOMMA)) p_component_configuration(unit); + else + tree_add_decl(unit, p_block_configuration()); +} + +static void p_index_specification(void) +{ + // discrete_range | expression + + const look_params_t lookp = { + .look = { tDOWNTO, tTO, tRANGE, tREVRANGE }, + .stop = { tRPAREN, tCOMMA, tASSOC, tBAR }, + .abort = tSEMI, + .nest_in = tLPAREN, + .nest_out = tRPAREN, + .depth = 0 + }; + + if (look_for(&lookp)) { + p_discrete_range(); + } else { - consume(tFOR); - parse_error(&last_loc, "nested block configuration not supported"); - //p_block_configuration(unit); + p_expression(); } } @@ -4360,12 +4377,15 @@ static void p_block_specification(tree_t unit) BEGIN("block specification"); - tree_set_ident2(unit, ident_prefix(tree_ident2(unit), p_identifier(), '-')); + tree_set_ident(unit, p_identifier()); - // TODO: [ ( index_specification ) ] + if (optional(tLPAREN)) { + p_index_specification(); + consume(tRPAREN); + } } -static void p_block_configuration(tree_t unit) +static tree_t p_block_configuration(void) { // for block_specification { use_clause } { configuration_item } end for ; @@ -4373,14 +4393,18 @@ static void p_block_configuration(tree_t unit) consume(tFOR); - p_block_specification(unit); + tree_t b = tree_new(T_BLOCK_CONFIG); + + p_block_specification(b); while (not_at_token(tEND)) - p_configuration_item(unit); + p_configuration_item(b); consume(tEND); consume(tFOR); consume(tSEMI); + + return b; } static void p_configuration_declaration(tree_t unit) @@ -4392,7 +4416,7 @@ static void p_configuration_declaration(tree_t unit) consume(tCONFIGURATION); - tree_change_kind(unit, T_CONFIG); + tree_change_kind(unit, T_CONFIGURATION); tree_set_ident(unit, p_identifier()); consume(tOF); @@ -4404,7 +4428,7 @@ static void p_configuration_declaration(tree_t unit) while (not_at_token(tFOR)) p_configuration_declarative_part(unit); - p_block_configuration(unit); + tree_add_decl(unit, p_block_configuration()); consume(tEND); optional(tCONFIGURATION); diff --git a/src/sem.c b/src/sem.c index 0ef1a72f..5444b2ba 100644 --- a/src/sem.c +++ b/src/sem.c @@ -7410,7 +7410,7 @@ static bool sem_check_binding(tree_t t) break; case C_CONFIGURATION: - if (tree_kind(unit) != T_CONFIG) + if (tree_kind(unit) != T_CONFIGURATION) sem_error(t, "unit %s is not a configuration", istr(tree_ident(t))); break; @@ -7421,6 +7421,21 @@ static bool sem_check_binding(tree_t t) return true; } +static bool sem_check_block_config(tree_t t) +{ + scope_push(tree_ident(t)); + + bool ok = true; + const int ndecls = tree_decls(t); + for (int i = 0; i < ndecls; i++) + ok = sem_check(tree_decl(t, i)) && ok; + + ok = scope_run_deferred_checks() && ok; + + scope_pop(); + return ok; +} + static bool sem_copy_instances(tree_t t, void *context) { switch (tree_kind(t)) { @@ -7434,11 +7449,17 @@ static bool sem_copy_instances(tree_t t, void *context) static bool sem_check_configuration(tree_t t) { + const int ndecls = tree_decls(t); + tree_t block_config = tree_decl(t, ndecls - 1); + assert(tree_kind(block_config) == T_BLOCK_CONFIG); + lib_t work = lib_work(); - ident_t name_qual = ident_prefix(lib_name(work), tree_ident2(t), '.'); + ident_t name_qual = + ident_prefix(ident_prefix(lib_name(work), tree_ident2(t), '.'), + tree_ident(block_config), '-'); tree_t arch = lib_get(work, name_qual); - if (arch == NULL) + if (arch == NULL || tree_kind(arch) != T_ARCH) sem_error(t, "architecture %s of entity %s not found in library %s", istr(ident_rfrom(name_qual, '-')), istr(ident_until(name_qual, '-')), @@ -7449,6 +7470,7 @@ static bool sem_check_configuration(tree_t t) lib_put(lib_work(), copy); scope_push(NULL); + top_scope->unit = t; const int nadecls = tree_decls(copy); for (int i = 0; i < nadecls; i++) { @@ -7464,9 +7486,8 @@ static bool sem_check_configuration(tree_t t) scope_push(NULL); bool ok = true; - const int ndecls = tree_decls(t); for (int i = 0; i < ndecls; i++) - ok = sem_check(tree_decl(t, i)); + ok = sem_check(tree_decl(t, i)) && ok; ok = scope_run_deferred_checks() && ok; @@ -7689,7 +7710,7 @@ bool sem_check(tree_t t) return sem_check_binding(t); case T_LIBRARY: return sem_check_library_clause(t); - case T_CONFIG: + case T_CONFIGURATION: return sem_check_configuration(t); case T_PROT_BODY: return sem_check_prot_body(t); @@ -7697,6 +7718,8 @@ bool sem_check(tree_t t) return sem_check_context_decl(t); case T_CTXREF: return sem_check_context_ref(t); + case T_BLOCK_CONFIG: + return sem_check_block_config(t); default: sem_error(t, "cannot check %s", tree_kind_str(tree_kind(t))); } diff --git a/src/tree.c b/src/tree.c index 728bc2a9..101e5a80 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1,5 +1,5 @@ // -// Copyright (C) 2011-2017 Nick Gasson +// Copyright (C) 2011-2018 Nick Gasson // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -235,7 +235,7 @@ static const imask_t has_map[T_LAST_TREE_KIND] = { // T_DESIGN_UNIT (I_CONTEXT), - // T_CONFIG + // T_CONFIGURATION (I_IDENT | I_IDENT2 | I_DECLS), // T_PROT_BODY @@ -248,7 +248,10 @@ static const imask_t has_map[T_LAST_TREE_KIND] = { (I_IDENT | I_REF), // T_CONSTRAINT - (I_SUBKIND | I_RANGES) + (I_SUBKIND | I_RANGES), + + // T_BLOCK_CONFIG + (I_DECLS | I_IDENT | I_VALUE | I_RANGES), }; static const char *kind_text_map[T_LAST_TREE_KIND] = { @@ -269,33 +272,33 @@ static const char *kind_text_map[T_LAST_TREE_KIND] = { "T_CASSERT", "T_CPCALL", "T_UNIT_DECL", "T_NEXT", "T_GENVAR", "T_PARAM", "T_ASSOC", "T_USE", "T_HIER", "T_SPEC", "T_BINDING", "T_LIBRARY", - "T_DESIGN_UNIT", "T_CONFIG", "T_PROT_BODY", "T_CONTEXT", - "T_CTXREF", "T_CONSTRAINT" + "T_DESIGN_UNIT", "T_CONFIGURATION", "T_PROT_BODY", "T_CONTEXT", + "T_CTXREF", "T_CONSTRAINT", "T_BLOCK_CONFIG", }; static const change_allowed_t change_allowed[] = { - { T_REF, T_FCALL }, - { T_REF, T_PCALL }, - { T_ARRAY_REF, T_FCALL }, - { T_FCALL, T_ARRAY_REF }, - { T_FCALL, T_PCALL }, - { T_FCALL, T_TYPE_CONV }, - { T_REF, T_RECORD_REF }, - { T_ARRAY_REF, T_ARRAY_SLICE }, - { T_ASSERT, T_CASSERT }, - { T_DESIGN_UNIT, T_ENTITY }, - { T_DESIGN_UNIT, T_PACKAGE }, - { T_DESIGN_UNIT, T_PACK_BODY }, - { T_DESIGN_UNIT, T_ARCH }, - { T_DESIGN_UNIT, T_CONFIG }, - { T_DESIGN_UNIT, T_CONTEXT }, - { T_FUNC_DECL, T_FUNC_BODY }, - { T_PROC_DECL, T_PROC_BODY }, - { T_REF, T_ARRAY_SLICE }, - { T_FCALL, T_CPCALL }, - { T_REF, T_CPCALL }, - { T_ATTR_REF, T_ARRAY_REF }, - { -1, -1 } + { T_REF, T_FCALL }, + { T_REF, T_PCALL }, + { T_ARRAY_REF, T_FCALL }, + { T_FCALL, T_ARRAY_REF }, + { T_FCALL, T_PCALL }, + { T_FCALL, T_TYPE_CONV }, + { T_REF, T_RECORD_REF }, + { T_ARRAY_REF, T_ARRAY_SLICE }, + { T_ASSERT, T_CASSERT }, + { T_DESIGN_UNIT, T_ENTITY }, + { T_DESIGN_UNIT, T_PACKAGE }, + { T_DESIGN_UNIT, T_PACK_BODY }, + { T_DESIGN_UNIT, T_ARCH }, + { T_DESIGN_UNIT, T_CONFIGURATION }, + { T_DESIGN_UNIT, T_CONTEXT }, + { T_FUNC_DECL, T_FUNC_BODY }, + { T_PROC_DECL, T_PROC_BODY }, + { T_REF, T_ARRAY_SLICE }, + { T_FCALL, T_CPCALL }, + { T_REF, T_CPCALL }, + { T_ATTR_REF, T_ARRAY_REF }, + { -1, -1 } }; struct tree { @@ -324,7 +327,7 @@ static tree_kind_t decl_kinds[] = { T_ATTR_DECL, T_ATTR_SPEC, T_PROC_DECL, T_PROC_BODY, T_COMPONENT, T_FILE_DECL, T_FIELD_DECL, T_UNIT_DECL, T_GENVAR, T_HIER, T_SPEC, T_BINDING, - T_USE, T_PROT_BODY + T_USE, T_PROT_BODY, T_BLOCK_CONFIG }; object_class_t tree_object = { diff --git a/src/tree.h b/src/tree.h index f280d34e..68944bdc 100644 --- a/src/tree.h +++ b/src/tree.h @@ -1,5 +1,5 @@ // -// Copyright (C) 2011-2016 Nick Gasson +// Copyright (C) 2011-2018 Nick Gasson // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -151,11 +151,12 @@ typedef enum tree_kind { T_BINDING, T_LIBRARY, T_DESIGN_UNIT, - T_CONFIG, + T_CONFIGURATION, T_PROT_BODY, T_CONTEXT, T_CTXREF, T_CONSTRAINT, + T_BLOCK_CONFIG, T_LAST_TREE_KIND } tree_kind_t; diff --git a/src/util.c b/src/util.c index 63487985..791ec319 100644 --- a/src/util.c +++ b/src/util.c @@ -430,8 +430,14 @@ int color_printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - char *strp LOCAL = prepare_msg(fmt, ap, false); + int rc = color_vprintf(fmt, ap); va_end(ap); + return rc; +} + +int color_vprintf(const char *fmt, va_list ap) +{ + char *strp LOCAL = prepare_msg(fmt, ap, false); bool escape = false; int len = 0; diff --git a/src/util.h b/src/util.h index 3e66767c..17c60dd7 100644 --- a/src/util.h +++ b/src/util.h @@ -82,6 +82,7 @@ char *xasprintf(const char *fmt, ...) int color_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +int color_vprintf(const char *fmt, va_list ap); void errorf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); diff --git a/src/vcode.c b/src/vcode.c index 0e7d797e..6072d629 100644 --- a/src/vcode.c +++ b/src/vcode.c @@ -4955,6 +4955,9 @@ static void vcode_write_unit(vcode_unit_t unit, fbuf_t *f, for (size_t i = 0; i < op->resolution->count; i++) { ident_write(op->resolution->element[i].name, ident_wr_ctx); write_u32(op->resolution->element[i].type, f); + write_u32(op->resolution->element[i].ileft, f); + write_u32(op->resolution->element[i].kind, f); + write_u32(op->resolution->element[i].boundary, f); } } } @@ -5180,6 +5183,9 @@ static bool vcode_read_unit(fbuf_t *f, ident_rd_ctx_t ident_rd_ctx) for (size_t i = 0; i < count; i++) { op->resolution->element[i].name = ident_read(ident_rd_ctx); op->resolution->element[i].type = read_u32(f); + op->resolution->element[i].ileft = read_u32(f); + op->resolution->element[i].kind = read_u32(f); + op->resolution->element[i].boundary = read_u8(f); } } } diff --git a/test/parse/vests1.vhd b/test/parse/vests1.vhd new file mode 100644 index 00000000..7ef8d92f --- /dev/null +++ b/test/parse/vests1.vhd @@ -0,0 +1,18 @@ +configuration c01s03b01x00p12n01i00863cfg of c01s03b01x00p12n01i00863ent is + for c01s03b01x00p12n01i00863arch + for K + for T5:test use configuration work.testbench; + end for; + for G(3) + for T1:test + use configuration work.testbench; + end for; + end for; + for G(0 to 2) + for all:test + use configuration work.testbench; + end for; + end for; + end for; + end for; +end; diff --git a/test/test_parse.c b/test/test_parse.c index 170b00da..23f674e9 100644 --- a/test/test_parse.c +++ b/test/test_parse.c @@ -2489,20 +2489,25 @@ END_TEST START_TEST(test_config) { - tree_t c, s; + tree_t c, s, b; input_from_file(TESTDIR "/parse/config.vhd"); c = parse(); fail_if(c == NULL); - fail_unless(tree_kind(c) == T_CONFIG); + fail_unless(tree_kind(c) == T_CONFIGURATION); fail_unless(tree_ident(c) == ident_new("CONF")); - fail_unless(tree_ident2(c) == ident_new("ENT-ARCH")); - fail_unless(tree_decls(c) == 4); + fail_unless(tree_ident2(c) == ident_new("ENT")); + fail_unless(tree_decls(c) == 3); fail_unless(tree_kind(tree_decl(c, 0)) == T_USE); fail_unless(tree_kind(tree_decl(c, 1)) == T_ATTR_SPEC); - s = tree_decl(c, 2); + b = tree_decl(c, 2); + fail_unless(tree_kind(b) == T_BLOCK_CONFIG); + fail_unless(tree_ident(b) == ident_new("ARCH")); + fail_unless(tree_decls(b) == 2); + + s = tree_decl(b, 0); fail_unless(tree_kind(s) == T_SPEC); fail_unless(tree_ident(s) == ident_new("all")); fail_unless(tree_ident2(s) == ident_new("COMP")); @@ -2779,6 +2784,34 @@ START_TEST(test_issue369) } END_TEST; +START_TEST(test_vests1) +{ + input_from_file(TESTDIR "/parse/vests1.vhd"); + + tree_t c = parse(); + fail_if(c == NULL); + fail_unless(tree_kind(c) == T_CONFIGURATION); + fail_unless(tree_decls(c) == 1); + + tree_t b = tree_decl(c, 0); + fail_unless(tree_kind(b) == T_BLOCK_CONFIG); + fail_unless(tree_decls(b) == 1); + + tree_t b2 = tree_decl(b, 0); + fail_unless(tree_kind(b2) == T_BLOCK_CONFIG); + fail_unless(tree_decls(b2) == 3); + + tree_t b3 = tree_decl(b2, 2); + fail_unless(tree_kind(b3) == T_BLOCK_CONFIG); + fail_unless(tree_ident(b3) == ident_new("G")); + fail_unless(tree_decls(b3) == 1); + + fail_if(parse() != NULL); + + fail_unless(parse_errors() == 0); +} +END_TEST; + Suite *get_parse_tests(void) { Suite *s = suite_create("parse"); @@ -2824,6 +2857,7 @@ Suite *get_parse_tests(void) tcase_add_test(tc_core, test_issue360); tcase_add_test(tc_core, test_issue367); tcase_add_test(tc_core, test_issue369); + tcase_add_test(tc_core, test_vests1); suite_add_tcase(s, tc_core); return s; diff --git a/test/test_sem.c b/test/test_sem.c index 248a903c..474cad07 100644 --- a/test/test_sem.c +++ b/test/test_sem.c @@ -942,7 +942,7 @@ START_TEST(test_config) input_from_file(TESTDIR "/sem/config.vhd"); parse_and_check(T_ENTITY, T_ARCH, T_ENTITY, T_ARCH, T_ENTITY, - T_ARCH, T_CONFIG); + T_ARCH, T_CONFIGURATION); fail_unless(sem_errors() == 0); } -- 2.39.2