Permalink
Browse files

Parsing and checking for selected signal assignment

  • Loading branch information...
1 parent e9f37c3 commit 65993e9f9684a4ea4ae63a3daf996c1df0f57e9a @nickg committed Apr 8, 2012
Showing with 115 additions and 12 deletions.
  1. +4 −0 src/lexer.l
  2. +45 −2 src/parse.y
  3. +29 −2 src/sem.c
  4. +6 −4 src/tree.c
  5. +3 −2 src/tree.h
  6. +5 −0 test/parse/conc.vhd
  7. +15 −1 test/sem/conc.vhd
  8. +5 −1 test/test_parse.c
  9. +3 −0 test/test_sem.c
View
@@ -158,6 +158,8 @@ TRANSPORT {T}{R}{A}{N}{S}{P}{O}{R}{T}
INERTIAL {I}{N}{E}{R}{T}{I}{A}{L}
REJECT {R}{E}{J}{E}{C}{T}
BLOCK {B}{L}{O}{C}{K}
+WITH {W}{I}{T}{H}
+SELECT {S}{E}{L}{E}{C}{T}
%%
@@ -236,6 +238,8 @@ BLOCK {B}{L}{O}{C}{K}
{REJECT} { TOKEN(tREJECT); }
{INERTIAL} { TOKEN(tINERTIAL); }
{BLOCK} { TOKEN(tBLOCK); }
+{WITH} { TOKEN(tWITH); }
+{SELECT} { TOKEN(tSELECT); }
"(" { TOKEN(tLPAREN); }
")" { TOKEN(tRPAREN); }
View
@@ -161,6 +161,7 @@
%type <t> waveform_element seq_stmt_without_label conc_assign_stmt
%type <t> comp_instance_stmt conc_stmt_without_label elsif_list
%type <t> delay_mechanism bit_string_literal block_stmt
+%type <t> conc_select_assign_stmt
%type <i> id opt_id selected_id func_name
%type <l> interface_object_decl interface_list
%type <l> port_clause generic_clause interface_decl signal_decl
@@ -184,7 +185,7 @@
%type <g> secondary_unit_decls constraint_list case_alt_list
%type <g> element_assoc_list index_constraint constraint choice_list
%type <b> element_assoc choice
-%type <g> param_list generic_map port_map
+%type <g> param_list generic_map port_map selected_waveforms
%type <c> object_class
%token tID tENTITY tIS tEND tGENERIC tPORT tCONSTANT tCOMPONENT
@@ -197,7 +198,7 @@
%token tOTHERS tASSERT tSEVERITY tON tMAP tTHEN tELSE tELSIF tBODY
%token tWHILE tLOOP tAFTER tALIAS tATTRIBUTE tPROCEDURE tEXIT
%token tWHEN tCASE tBAR tLSQUARE tRSQUARE tINERTIAL tTRANSPORT
-%token tREJECT tBITSTRING tBLOCK
+%token tREJECT tBITSTRING tBLOCK tWITH tSELECT
%left tAND tOR tNAND tNOR tXOR tXNOR
%left tEQ tNEQ tLT tLE tGT tGE
@@ -667,6 +668,7 @@ conc_stmt_without_label
: process_stmt
| comp_instance_stmt
| conc_assign_stmt
+| conc_select_assign_stmt
| block_stmt
/* | concurrent_procedure_call_statement
| concurrent_assertion_statement
@@ -979,6 +981,47 @@ conditional_waveforms
}
;
+conc_select_assign_stmt
+: tWITH expr tSELECT target tLE
+ delay_mechanism selected_waveforms tSEMI
+{
+ $$ = tree_new(T_SELECT);
+ tree_set_loc($$, &@$);
+ tree_set_value($$, $2);
+
+ for (list_t *it = $7; it != NULL; it = it->next) {
+ tree_set_target(it->item.assoc.value, $4);
+ set_delay_mechanism(it->item.assoc.value, $6);
+ tree_add_assoc($$, it->item.assoc);
+ }
+ list_free($7);
+}
+
+selected_waveforms
+: waveform tWHEN choice_list tCOMMA selected_waveforms
+ {
+ tree_t s = tree_new(T_SIGNAL_ASSIGN);
+ tree_set_loc(s, &@$);
+ copy_trees($1, tree_add_waveform, s);
+
+ for (list_t *it = $3; it != NULL; it = it->next)
+ it->item.assoc.value = s;
+
+ $$ = list_append($3, $5);
+ }
+| waveform tWHEN choice_list
+ {
+ tree_t s = tree_new(T_SIGNAL_ASSIGN);
+ tree_set_loc(s, &@$);
+ copy_trees($1, tree_add_waveform, s);
+
+ for (list_t *it = $3; it != NULL; it = it->next)
+ it->item.assoc.value = s;
+
+ $$ = $3;
+ }
+;
+
seq_stmt_list
: seq_stmt seq_stmt_list
{
View
@@ -70,11 +70,11 @@ static bool bootstrap = false;
static ident_t builtin_i;
static ident_t std_standard_i;
-#define sem_error(t, ...) { \
+#define sem_error(t, ...) do { \
error_at(t ? tree_loc(t) : NULL , __VA_ARGS__); \
errors++; \
return false; \
- }
+ } while (0)
static void scope_push(ident_t prefix)
{
@@ -3299,6 +3299,31 @@ static bool sem_check_exit(tree_t t)
return true;
}
+static bool sem_check_select(tree_t t)
+{
+ if (!sem_check(tree_value(t)))
+ return false;
+
+ type_t value_type = tree_type(tree_value(t));
+
+ for (unsigned i = 0; i < tree_assocs(t); i++) {
+ assoc_t a = tree_assoc(t, i);
+ if (a.kind == A_NAMED) {
+ if (!sem_check(a.name))
+ return false;
+ else if (!type_eq(tree_type(a.name), value_type))
+ sem_error(a.name, "choice must have type %s", type_pp(value_type));
+ else if (!sem_locally_static(a.name))
+ sem_error(a.name, "choice must be locally static");
+ }
+
+ if (!sem_check(a.value))
+ return false;
+ }
+
+ return true;
+}
+
static void sem_intern_strings(void)
{
// Intern some commonly used strings
@@ -3392,6 +3417,8 @@ bool sem_check(tree_t t)
return sem_check_concat(t);
case T_PCALL:
return sem_check_pcall(t);
+ case T_SELECT:
+ return sem_check_select(t);
default:
sem_error(t, "cannot check tree kind %d", tree_kind(t));
}
View
@@ -160,7 +160,7 @@ struct tree_rd_ctx {
|| IS(t, T_IF) || IS(t, T_NULL) || IS(t, T_RETURN) \
|| IS(t, T_CASSIGN) || IS(t, T_WHILE) || IS(t, T_FOR) \
|| IS(t, T_EXIT) || IS(t, T_PCALL) || IS(t, T_CASE) \
- || IS(t, T_BLOCK))
+ || IS(t, T_BLOCK) || IS(t, T_SELECT))
#define HAS_IDENT(t) \
(IS(t, T_ENTITY) || IS(t, T_PORT_DECL) || IS(t, T_FCALL) \
|| IS(t, T_ARCH) || IS(t, T_SIGNAL_DECL) || IS_STMT(t) \
@@ -171,7 +171,8 @@ struct tree_rd_ctx {
|| IS(t, T_FUNC_BODY) || IS(t, T_CASSIGN) || IS(t, T_WHILE) \
|| IS(t, T_ALIAS) || IS(t, T_ATTR_DECL) || IS(t, T_ATTR_SPEC) \
|| IS(t, T_PROC_DECL) || IS(t, T_PROC_BODY) || IS(t, T_EXIT) \
- || IS(t, T_PCALL) || IS(t, T_CASE) || IS(t, T_BLOCK))
+ || IS(t, T_PCALL) || IS(t, T_CASE) || IS(t, T_BLOCK) \
+ || IS(t, T_SELECT))
#define HAS_IDENT2(t) \
(IS(t, T_ARCH) || IS(t, T_ATTR_REF) || IS(t, T_INSTANCE) \
|| IS(t, T_FOR) || IS(t, T_ATTR_SPEC) || IS(t, T_PCALL))
@@ -208,7 +209,7 @@ struct tree_rd_ctx {
|| IS(t, T_ATTR_REF) || IS(t, T_ARRAY_REF) || IS(t, T_CASE) \
|| IS(t, T_ARRAY_SLICE) || IS(t, T_IF) || IS(t, T_RETURN) \
|| IS(t, T_WHILE) || IS(t, T_ALIAS) || IS(t, T_ATTR_SPEC) \
- || IS(t, T_EXIT) || IS(t, T_COND))
+ || IS(t, T_EXIT) || IS(t, T_COND) || IS(t, T_SELECT))
#define HAS_CONTEXT(t) \
(IS(t, T_ARCH) || IS(t, T_ENTITY) || IS(t, T_PACKAGE) \
|| IS(t, T_PACK_BODY) || IS(t, T_ELAB))
@@ -220,7 +221,8 @@ struct tree_rd_ctx {
(IS(t, T_SIGNAL_ASSIGN) || IS(t, T_COND))
#define HAS_RANGE(t) (IS(t, T_ARRAY_SLICE) || IS(t, T_FOR))
#define HAS_CLASS(t) (IS(t, T_PORT_DECL))
-#define HAS_ASSOCS(t) (IS(t, T_AGGREGATE) || IS(t, T_CASE))
+#define HAS_ASSOCS(t) \
+ (IS(t, T_AGGREGATE) || IS(t, T_CASE)|| IS(t, T_SELECT))
#define HAS_CONDS(t) (IS(t, T_CASSIGN))
#define HAS_REJECT(t) (IS(t, T_CASSIGN) || IS(t, T_SIGNAL_ASSIGN))
View
@@ -87,6 +87,7 @@ typedef enum tree_kind {
T_COND,
T_CONCAT,
T_TYPE_CONV,
+ T_SELECT,
T_LAST_TREE_KIND
} tree_kind_t;
@@ -185,7 +186,7 @@ void tree_set_literal(tree_t t, literal_t lit);
// T_PORT_DECL, T_SIGNAL_DECL, T_VAR_DECL, T_VAR_ASSIGN,
// T_QUALIFIED, T_CONST_DECL, T_ASSERT, T_ATTR_SPEC
// T_ARRAY_REF, T_IF, T_WHILE, T_REF, T_ALIAS, T_WAVEFORM
-// T_COND
+// T_COND, T_SELECT
bool tree_has_value(tree_t t);
tree_t tree_value(tree_t t);
void tree_set_value(tree_t t, tree_t v);
@@ -239,7 +240,7 @@ unsigned tree_contexts(tree_t t);
context_t tree_context(tree_t t, unsigned n);
void tree_add_context(tree_t t, context_t ctx);
-// T_AGGREGATE, T_CASE
+// T_AGGREGATE, T_CASE, T_SELECT
unsigned tree_assocs(tree_t t);
assoc_t tree_assoc(tree_t t, unsigned n);
void tree_add_assoc(tree_t t, assoc_t a);
View
@@ -6,5 +6,10 @@ begin
x <= 1 when foo
else 2 when bar
else 3;
+
+ with y select x <=
+ 1 when a,
+ 2 when b,
+ 3 when others;
end architecture;
View
@@ -16,5 +16,19 @@ begin
x <= 7 when 7 else 3; -- Condition not boolean
x <= reject 5 inertial 7; -- Reject not time
-
+
+ with y select x <= -- OK
+ 1 when 3,
+ 2 when 8,
+ 3 when others;
+
+ with y select x <=
+ 1 when y; -- Not locally static
+
+ with y select x <=
+ true when 5; -- Wrong type
+
+ with y select x <=
+ 6, 7 after 1 ns when false; -- Wrong type
+
end architecture;
View
@@ -1099,7 +1099,7 @@ START_TEST(test_conc)
a = parse();
fail_if(a == NULL);
fail_unless(tree_kind(a) == T_ARCH);
- fail_unless(tree_stmts(a) == 2);
+ fail_unless(tree_stmts(a) == 3);
s = tree_stmt(a, 0);
fail_unless(tree_kind(s) == T_CASSIGN);
@@ -1121,6 +1121,10 @@ START_TEST(test_conc)
fail_unless(tree_has_value(c));
fail_unless(tree_kind(tree_value(tree_waveform(c, 0))) == T_LITERAL);
+ s = tree_stmt(a, 2);
+ fail_unless(tree_kind(s) == T_SELECT);
+ fail_unless(tree_assocs(s) == 3);
+
a = parse();
fail_unless(a == NULL);
View
@@ -666,6 +666,9 @@ START_TEST(test_conc)
{ 12, "no suitable overload for identifier '4'" },
{ 16, "type of condition must be BOOLEAN" },
{ 18, "reject interval must have type TIME" },
+ { 26, "choice must be locally static" },
+ { 29, "no suitable overload for identifier TRUE" },
+ { 32, "choice must have type STD.STANDARD.INTEGER" },
{ -1, NULL }
};
expect_errors(expect);

0 comments on commit 65993e9

Please sign in to comment.