From 51ba06dd30cb4a301c7e82fff78d676571b7269c Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 23 Apr 2024 22:46:54 +0100 Subject: [PATCH] Verilog "forever" loops --- src/lexer.l | 1 + src/scan.h | 1 + src/vlog/vlog-lower.c | 23 +++++++++++++++++++---- src/vlog/vlog-node.c | 5 ++++- src/vlog/vlog-node.h | 1 + src/vlog/vlog-parse.y | 12 +++++++++++- src/vlog/vlog-sem.c | 10 ++++++++++ test/regress/testlist.txt | 1 + test/regress/vlog9.v | 23 +++++++++++++++++++++++ 9 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 test/regress/vlog9.v diff --git a/src/lexer.l b/src/lexer.l index 1f8f6128..9efdcfd5 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -542,6 +542,7 @@ UNION ?i:union "supply1" { return tSUPPLY1; } "pulldown" { return tPULLDOWN; } "pullup" { return tPULLUP; } +"forever" { return tFOREVER; } "==" { return tLOGEQ; } "!=" { return tLOGNEQ; } "===" { return tCASEEQ; } diff --git a/src/scan.h b/src/scan.h index 6b53dd47..a33ff10e 100644 --- a/src/scan.h +++ b/src/scan.h @@ -304,5 +304,6 @@ bool is_scanned_as_psl(void); #define tATTRBEGIN 408 #define tATTREND 409 #define tNUMBER 410 +#define tFOREVER 411 #endif // _SCAN_H diff --git a/src/vlog/vlog-lower.c b/src/vlog/vlog-lower.c index f390817c..505c97f2 100644 --- a/src/vlog/vlog-lower.c +++ b/src/vlog/vlog-lower.c @@ -521,9 +521,8 @@ static vcode_reg_t vlog_lower_rvalue(lower_unit_t *lu, vlog_node_t v) number_t num = vlog_number(v); const int width = number_width(num); - if (width == 1) { - abort(); - } + if (width == 1) + return emit_const(vlogic, number_bit(num, 0)); else { vcode_reg_t *bits LOCAL = xmalloc_array(width, sizeof(vcode_reg_t)); for (int i = 0; i < width; i++) @@ -804,6 +803,18 @@ static void vlog_lower_if(lower_unit_t *lu, vlog_node_t v) vcode_select_block(skip_bb); } +static void vlog_lower_forever(lower_unit_t *lu, vlog_node_t v) +{ + vcode_block_t body_bb = emit_block(); + emit_jump(body_bb); + + vcode_select_block(body_bb); + + vlog_lower_stmts(lu, v); + + emit_jump(body_bb); +} + static void vlog_lower_stmts(lower_unit_t *lu, vlog_node_t v) { const int nstmts = vlog_stmts(v); @@ -828,6 +839,9 @@ static void vlog_lower_stmts(lower_unit_t *lu, vlog_node_t v) case V_IF: vlog_lower_if(lu, s); break; + case V_FOREVER: + vlog_lower_forever(lu, s); + break; default: CANNOT_HANDLE(s); } @@ -923,7 +937,8 @@ static void vlog_lower_initial(unit_registry_t *ur, lower_unit_t *parent, vlog_lower_stmts(lu, stmt); - emit_wait(start_bb, VCODE_INVALID_REG); + if (!vcode_block_finished()) + emit_return(VCODE_INVALID_REG); unit_registry_finalise(ur, lu); } diff --git a/src/vlog/vlog-node.c b/src/vlog/vlog-node.c index aa3c5d4a..cd5ec137 100644 --- a/src/vlog/vlog-node.c +++ b/src/vlog/vlog-node.c @@ -106,6 +106,9 @@ static const imask_t has_map[V_LAST_NODE_KIND] = { // V_SYSFUNC (I_IDENT | I_SUBKIND | I_PARAMS), + + // V_FOREVER + (I_STMTS), }; static const char *kind_text_map[V_LAST_NODE_KIND] = { @@ -115,7 +118,7 @@ static const char *kind_text_map[V_LAST_NODE_KIND] = { "V_NET_DECL", "V_ASSIGN", "V_DIMENSION", "V_IF", "V_COND", "V_VAR_DECL", "V_DELAY_CONTROL", "V_BINARY", "V_BASSIGN", "V_UNARY", "V_GATE_INST", "V_STRENGTH", - "V_MOD_INST", "V_BIT_SELECT", "V_SYSFUNC", + "V_MOD_INST", "V_BIT_SELECT", "V_SYSFUNC", "V_FOREVER", }; static const change_allowed_t change_allowed[] = { diff --git a/src/vlog/vlog-node.h b/src/vlog/vlog-node.h index 683f2005..962c2ed9 100644 --- a/src/vlog/vlog-node.h +++ b/src/vlog/vlog-node.h @@ -76,6 +76,7 @@ typedef enum { V_MOD_INST, V_BIT_SELECT, V_SYSFUNC, + V_FOREVER, V_LAST_NODE_KIND } vlog_kind_t; diff --git a/src/vlog/vlog-parse.y b/src/vlog/vlog-parse.y index 162a8547..e1da9994 100644 --- a/src/vlog/vlog-parse.y +++ b/src/vlog/vlog-parse.y @@ -139,7 +139,7 @@ static vlog_node_t make_strength(vlog_strength_t value, const loc_t *loc) %type decimal_number conditional_statement variable_type %type delay_control delay_value strength0 strength1 %type pull_gate_instance port_identifier module_instance -%type system_function_call +%type system_function_call loop_statement %type identifier hierarchical_identifier %type module_item_list module_port_list_opt module_item %type list_of_port_declarations module_item_list_opt @@ -189,6 +189,7 @@ static vlog_node_t make_strength(vlog_strength_t value, const loc_t *loc) %token tATTRBEGIN 408 "(*" %token tATTREND 409 "*)" %token tNUMBER 410 "number" +%token tFOREVER 411 "forever" %token tEOF 0 "end of file" @@ -592,6 +593,7 @@ statement: procedural_timing_control_statement | seq_block | system_task_enable | conditional_statement + | loop_statement ; statement_or_null: @@ -797,6 +799,14 @@ event_expression: } ; +loop_statement: tFOREVER statement + { + $$ = vlog_new(V_FOREVER); + vlog_set_loc($$, &@$); + vlog_add_stmt($$, $2); + } + ; + lvalue: hierarchical_identifier { $$ = vlog_new(V_REF); diff --git a/src/vlog/vlog-sem.c b/src/vlog/vlog-sem.c index c679567b..8e799bfd 100644 --- a/src/vlog/vlog-sem.c +++ b/src/vlog/vlog-sem.c @@ -446,6 +446,13 @@ static void vlog_check_bit_select(vlog_node_t bsel) vlog_check(vlog_param(bsel, i)); } +static void vlog_check_forever(vlog_node_t stmt) +{ + const int nstmts = vlog_stmts(stmt); + for (int i = 0; i < nstmts; i++) + vlog_check(vlog_stmt(stmt, i)); +} + void vlog_check(vlog_node_t v) { switch (vlog_kind(v)) { @@ -524,6 +531,9 @@ void vlog_check(vlog_node_t v) case V_BIT_SELECT: vlog_check_bit_select(v); break; + case V_FOREVER: + vlog_check_forever(v); + break; default: fatal_at(vlog_loc(v), "cannot check verilog node %s", vlog_kind_str(vlog_kind(v))); diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 73a56525..1d187230 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -967,3 +967,4 @@ issue877 normal,2008 issue878 wave,2008,dump-arrays ivtest2 verilog,gold ivtest3 verilog +vlog9 verilog diff --git a/test/regress/vlog9.v b/test/regress/vlog9.v new file mode 100644 index 00000000..538436e5 --- /dev/null +++ b/test/regress/vlog9.v @@ -0,0 +1,23 @@ +module vlog9; + reg clk; + reg [7:0] cnt; + + initial begin + cnt = 0; + clk = 1'b0; + forever #1 clk = ~clk; + end + + always @(posedge clk) + cnt = cnt + 1; + + initial begin + #20; + if (cnt === 10) + $display("PASSED"); + else + $display("FAILED -- %d", cnt); + $finish; + end + +endmodule // vlog9 -- 2.39.2