From bf7e23c1187cc01fe9673d0af2ac804a2b6fb04b Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 10 Oct 2023 19:47:17 +0100 Subject: [PATCH] Verilog blocking assignment --- src/vlog/vlog-dump.c | 18 ++++++++++++++++++ src/vlog/vlog-lower.c | 19 +++++++++++++++++++ src/vlog/vlog-node.c | 5 ++++- src/vlog/vlog-node.h | 5 +++++ src/vlog/vlog-parse.y | 14 +++++++++++++- src/vlog/vlog-sem.c | 34 +++++++++++++++++++++++++++------- test/dump/vlog1.v | 1 + test/regress/gold/vlog4.txt | 1 + test/regress/vlog4.v | 2 ++ test/test_dump.c | 1 + test/test_vlog.c | 3 +++ test/vlog/parse1.v | 1 + 12 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/vlog/vlog-dump.c b/src/vlog/vlog-dump.c index c885f713..d375c877 100644 --- a/src/vlog/vlog-dump.c +++ b/src/vlog/vlog-dump.c @@ -187,6 +187,21 @@ static void vlog_dump_nbassign(vlog_node_t v, int indent) print_syntax(";\n"); } +static void vlog_dump_bassign(vlog_node_t v, int indent) +{ + tab(indent); + vlog_dump(vlog_target(v), 0); + + switch (vlog_subkind(v)) { + case V_ASSIGN_EQUALS: + print_syntax(" = "); + break; + } + + vlog_dump(vlog_value(v), 0); + print_syntax(";\n"); +} + static void vlog_dump_assign(vlog_node_t v, int indent) { tab(indent); @@ -311,6 +326,9 @@ void vlog_dump(vlog_node_t v, int indent) case V_NBASSIGN: vlog_dump_nbassign(v, indent); break; + case V_BASSIGN: + vlog_dump_bassign(v, indent); + break; case V_ASSIGN: vlog_dump_assign(v, indent); break; diff --git a/src/vlog/vlog-lower.c b/src/vlog/vlog-lower.c index 9f9397a8..5a38eee2 100644 --- a/src/vlog/vlog-lower.c +++ b/src/vlog/vlog-lower.c @@ -431,6 +431,21 @@ static void vlog_lower_nbassign(lower_unit_t *lu, vlog_node_t v) emit_sched_waveform(nets_reg, count_reg, value_reg, reject_reg, after_reg); } +static void vlog_lower_bassign(lower_unit_t *lu, vlog_node_t v) +{ + vlog_lower_nbassign(lu, v); + + // Delay one delta cycle to see the update + + vcode_type_t vtime = vtype_time(); + vcode_reg_t delay_reg = emit_const(vtime, 0); + + vcode_block_t resume_bb = emit_block(); + emit_wait(resume_bb, delay_reg); + + vcode_select_block(resume_bb); +} + static void vlog_lower_systask(lower_unit_t *lu, vlog_node_t v) { const v_systask_kind_t kind = vlog_subkind(v); @@ -520,6 +535,9 @@ static void vlog_lower_stmts(lower_unit_t *lu, vlog_node_t v) case V_NBASSIGN: vlog_lower_nbassign(lu, s); break; + case V_BASSIGN: + vlog_lower_bassign(lu, s); + break; case V_SEQ_BLOCK: vlog_lower_stmts(lu, s); break; @@ -558,6 +576,7 @@ static void vlog_driver_cb(vlog_node_t v, void *context) switch (vlog_kind(v)) { case V_NBASSIGN: + case V_BASSIGN: case V_ASSIGN: vlog_lower_driver(lu, vlog_target(v)); break; diff --git a/src/vlog/vlog-node.c b/src/vlog/vlog-node.c index fa6a4cb4..e0135a74 100644 --- a/src/vlog/vlog-node.c +++ b/src/vlog/vlog-node.c @@ -88,6 +88,9 @@ static const imask_t has_map[V_LAST_NODE_KIND] = { // V_BINARY (I_LEFT | I_RIGHT | I_SUBKIND), + + // V_BASSIGN + (I_TARGET | I_VALUE | I_SUBKIND), }; static const char *kind_text_map[V_LAST_NODE_KIND] = { @@ -96,7 +99,7 @@ static const char *kind_text_map[V_LAST_NODE_KIND] = { "V_SEQ_BLOCK", "V_SYSTASK", "V_STRING", "V_NUMBER", "V_NET_DECL", "V_ASSIGN", "V_ROOT", "V_DIMENSION", "V_IF", "V_COND", "V_VAR_DECL", "V_DELAY_CONTROL", - "V_BINARY", + "V_BINARY", "V_BASSIGN", }; static const change_allowed_t change_allowed[] = { diff --git a/src/vlog/vlog-node.h b/src/vlog/vlog-node.h index 95af4255..6da7ee66 100644 --- a/src/vlog/vlog-node.h +++ b/src/vlog/vlog-node.h @@ -65,6 +65,7 @@ typedef enum { V_VAR_DECL, V_DELAY_CONTROL, V_BINARY, + V_BASSIGN, V_LAST_NODE_KIND } vlog_kind_t; @@ -85,6 +86,10 @@ typedef enum { V_BINARY_AND, } vlog_binary_t; +typedef enum { + V_ASSIGN_EQUALS, +} vlog_assign_t; + vlog_node_t vlog_new(vlog_kind_t kind); vlog_kind_t vlog_kind(vlog_node_t v); const char *vlog_kind_str(vlog_kind_t kind); diff --git a/src/vlog/vlog-parse.y b/src/vlog/vlog-parse.y index 47b9eac8..bec21c26 100644 --- a/src/vlog/vlog-parse.y +++ b/src/vlog/vlog-parse.y @@ -110,7 +110,7 @@ static bool is_decl(vlog_node_t v) %type procedural_timing_control_statement %type lvalue event_control event_expression %type nonblocking_assignment delay_or_event_control -%type port_declaration port_reference +%type port_declaration port_reference blocking_assignment %type port initial_construct net_assignment %type seq_block system_task_enable string number %type decimal_number conditional_statement variable_type @@ -436,6 +436,7 @@ initial_construct: statement: procedural_timing_control_statement | nonblocking_assignment ';' + | blocking_assignment ';' | seq_block | system_task_enable | conditional_statement @@ -552,6 +553,17 @@ nonblocking_assignment: } ; +blocking_assignment: + lvalue '=' expression + { + $$ = vlog_new(V_BASSIGN); + vlog_set_loc($$, &@$); + vlog_set_subkind($$, V_ASSIGN_EQUALS); + vlog_set_target($$, $1); + vlog_set_value($$, $3); + } + ; + procedural_timing_control_statement: delay_or_event_control statement_or_null { diff --git a/src/vlog/vlog-sem.c b/src/vlog/vlog-sem.c index e5f35c88..5cae9f11 100644 --- a/src/vlog/vlog-sem.c +++ b/src/vlog/vlog-sem.c @@ -134,6 +134,16 @@ static void vlog_check_binary(vlog_node_t op) vlog_check(vlog_right(op)); } +static void vlog_check_variable_target(vlog_node_t target) +{ + if (is_net(target)) { + diag_t *d = diag_new(DIAG_ERROR, vlog_loc(target)); + name_for_diag(d, target, "target"); + diag_printf(d, " cannot be assigned in a procedural block"); + diag_emit(d); + } +} + static void vlog_check_nbassign(vlog_node_t stmt) { vlog_node_t target = vlog_target(stmt); @@ -142,12 +152,18 @@ static void vlog_check_nbassign(vlog_node_t stmt) vlog_node_t value = vlog_value(stmt); vlog_check(value); - if (is_net(target)) { - diag_t *d = diag_new(DIAG_ERROR, vlog_loc(target)); - name_for_diag(d, target, "target"); - diag_printf(d, " cannot be assigned in a procedural block"); - diag_emit(d); - } + vlog_check_variable_target(target); +} + +static void vlog_check_bassign(vlog_node_t stmt) +{ + vlog_node_t target = vlog_target(stmt); + vlog_check(target); + + vlog_node_t value = vlog_value(stmt); + vlog_check(value); + + vlog_check_variable_target(target); } static void vlog_check_assign(vlog_node_t stmt) @@ -304,6 +320,9 @@ void vlog_check(vlog_node_t v) case V_NBASSIGN: vlog_check_nbassign(v); break; + case V_BASSIGN: + vlog_check_bassign(v); + break; case V_ASSIGN: vlog_check_assign(v); break; @@ -338,6 +357,7 @@ void vlog_check(vlog_node_t v) vlog_check_binary(v); break; default: - fatal_trace("cannot check verilog node %s", vlog_kind_str(vlog_kind(v))); + fatal_at(vlog_loc(v), "cannot check verilog node %s", + vlog_kind_str(vlog_kind(v))); } } diff --git a/test/dump/vlog1.v b/test/dump/vlog1.v index d654dc9b..236758a4 100644 --- a/test/dump/vlog1.v +++ b/test/dump/vlog1.v @@ -12,6 +12,7 @@ module mod2; if (bus) r <= 1 | r; $finish; + r = 1; end assign bus = 3; endmodule // mod2 diff --git a/test/regress/gold/vlog4.txt b/test/regress/gold/vlog4.txt index 7931ff74..ec23aea9 100644 --- a/test/regress/gold/vlog4.txt +++ b/test/regress/gold/vlog4.txt @@ -1,2 +1,3 @@ x ==> x x ==> 42 +x ==> 12 diff --git a/test/regress/vlog4.v b/test/regress/vlog4.v index 70e87bdb..8345411a 100644 --- a/test/regress/vlog4.v +++ b/test/regress/vlog4.v @@ -5,5 +5,7 @@ module vlog4; x <= 42; $display("x ==> %d", x); #1 $display("x ==> %d", x); + x = 12; + $display("x ==> %d", x); end endmodule // vlog4 diff --git a/test/test_dump.c b/test/test_dump.c index ad018905..c2bebacb 100644 --- a/test/test_dump.c +++ b/test/test_dump.c @@ -438,6 +438,7 @@ START_TEST(test_vlog1) " if (bus)\n" " r <= 5'b00001 | r;\n" " $finish;\n" + " r = 5'b00001;\n" " end\n" " assign bus = 5'b00011;\n" "endmodule // mod2\n\n"); diff --git a/test/test_vlog.c b/test/test_vlog.c index eced88b1..619c7d83 100644 --- a/test/test_vlog.c +++ b/test/test_vlog.c @@ -208,6 +208,9 @@ START_TEST(test_parse1) fail_unless(vlog_kind(s2or) == V_BINARY); fail_unless(vlog_subkind(s2or) == V_BINARY_OR); + vlog_node_t s1s0s5 = vlog_stmt(s1s0, 5); + fail_unless(vlog_kind(s1s0s5) == V_BASSIGN); + fail_unless(vlog_parse() == NULL); fail_if_errors(); diff --git a/test/vlog/parse1.v b/test/vlog/parse1.v index f13f4cbf..1f16d433 100644 --- a/test/vlog/parse1.v +++ b/test/vlog/parse1.v @@ -10,6 +10,7 @@ module parse1; if (x) $display("yes"); else if (z); else $display("no"); + z = 0; end assign x = x | y; endmodule // parse1 -- 2.39.2