From 8eaae1660d47ca50da802d319ac542354ef80195 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Thu, 21 Sep 2023 22:13:41 +0100 Subject: [PATCH] Lowering for Verilog delay control --- lib/nvc.08/Makemodule.am | 10 +++- lib/nvc.08/deps.mk | 4 ++ lib/nvc.19/Makemodule.am | 10 +++- lib/nvc.19/deps.mk | 4 ++ lib/nvc/Makemodule.am | 14 ++++- lib/nvc/deps.mk | 4 ++ lib/nvc/verilog-body.vhd | 38 +++++++++++++ lib/nvc/verilog.vhd | 31 +++++++++++ src/lexer.l | 1 + src/rt/verilog.c | 35 ++++++++---- src/scan.c | 4 +- src/scan.h | 1 + src/vlog/vlog-lower.c | 104 +++++++++++++++++++++++++++--------- src/vlog/vlog-node.c | 13 +++-- src/vlog/vlog-node.h | 1 + src/vlog/vlog-number.c | 2 +- src/vlog/vlog-parse.y | 15 +++++- src/vlog/vlog-sem.c | 28 ++++++++++ test/regress/gold/vlog3.txt | 5 ++ test/regress/testlist.txt | 1 + test/regress/vlog3.v | 26 +++++++++ 21 files changed, 302 insertions(+), 49 deletions(-) create mode 100644 lib/nvc/verilog-body.vhd create mode 100644 lib/nvc/verilog.vhd create mode 100644 test/regress/gold/vlog3.txt create mode 100644 test/regress/vlog3.v diff --git a/lib/nvc.08/Makemodule.am b/lib/nvc.08/Makemodule.am index 688ab316..a79567eb 100644 --- a/lib/nvc.08/Makemodule.am +++ b/lib/nvc.08/Makemodule.am @@ -9,7 +9,9 @@ nvc_08_DATA = \ lib/nvc.08/NVC.TEXT_UTIL \ lib/nvc.08/NVC.TEXT_UTIL-body \ lib/nvc.08/NVC.PSL_SUPPORT \ - lib/nvc.08/NVC.PSL_SUPPORT-body + lib/nvc.08/NVC.PSL_SUPPORT-body \ + lib/nvc.08/NVC.VERILOG \ + lib/nvc.08/NVC.VERILOG-body EXTRA_DIST += \ lib/nvc.08/polyfill.vhd \ @@ -46,6 +48,12 @@ lib/nvc.08/NVC.PSL_SUPPORT: $(srcdir)/lib/nvc/psl_support.vhd @ifGNUmake@ | $(DR lib/nvc.08/NVC.PSL_SUPPORT-body: $(srcdir)/lib/nvc/psl_support-body.vhd @ifGNUmake@ | $(DRIVER) $(nvc) --std=2008 -L lib/ --work=lib/nvc.08 -a $(srcdir)/lib/nvc/psl_support-body.vhd +lib/nvc.08/NVC.VERILOG: $(srcdir)/lib/nvc/verilog.vhd @ifGNUmake@ | $(DRIVER) + $(nvc) --std=2008 -L lib/ --work=lib/nvc.08 -a $(srcdir)/lib/nvc/verilog.vhd + +lib/nvc.08/NVC.VERILOG-body: $(srcdir)/lib/nvc/verilog-body.vhd @ifGNUmake@ | $(DRIVER) + $(nvc) --std=2008 -L lib/ --work=lib/nvc.08 -a $(srcdir)/lib/nvc/verilog-body.vhd + gen-deps-nvc-08: $(nvc) --std=2008 -L lib/ --work=lib/nvc.08 --print-deps | \ $(deps_pp) > $(srcdir)/lib/nvc.08/deps.mk diff --git a/lib/nvc.08/deps.mk b/lib/nvc.08/deps.mk index ebe95728..af7c8098 100644 --- a/lib/nvc.08/deps.mk +++ b/lib/nvc.08/deps.mk @@ -16,3 +16,7 @@ lib/nvc.08/NVC.TEXT_UTIL-body: lib/std.08/STD.STANDARD lib/nvc.08/NVC.TEXT_UTIL lib/nvc.08/NVC.TEXT_UTIL: lib/std.08/STD.STANDARD $(top_srcdir)/lib/nvc/text_util.vhd +lib/nvc.08/NVC.VERILOG-body: lib/std.08/STD.STANDARD lib/nvc.08/NVC.VERILOG $(top_srcdir)/lib/nvc/verilog-body.vhd + +lib/nvc.08/NVC.VERILOG: lib/std.08/STD.STANDARD $(top_srcdir)/lib/nvc/verilog.vhd + diff --git a/lib/nvc.19/Makemodule.am b/lib/nvc.19/Makemodule.am index 112fd594..094358a2 100644 --- a/lib/nvc.19/Makemodule.am +++ b/lib/nvc.19/Makemodule.am @@ -9,7 +9,9 @@ nvc_19_DATA = \ lib/nvc.19/NVC.TEXT_UTIL \ lib/nvc.19/NVC.TEXT_UTIL-body \ lib/nvc.19/NVC.PSL_SUPPORT \ - lib/nvc.19/NVC.PSL_SUPPORT-body + lib/nvc.19/NVC.PSL_SUPPORT-body \ + lib/nvc.19/NVC.VERILOG \ + lib/nvc.19/NVC.VERILOG-body BOOTSTRAPLIBS += $(nvc_19_DATA) @@ -41,6 +43,12 @@ lib/nvc.19/NVC.PSL_SUPPORT: $(srcdir)/lib/nvc/psl_support.vhd @ifGNUmake@ | $(DR lib/nvc.19/NVC.PSL_SUPPORT-body: $(srcdir)/lib/nvc/psl_support-body.vhd @ifGNUmake@ | $(DRIVER) $(nvc) --std=2019 -L lib/ --work=lib/nvc.19 -a $(srcdir)/lib/nvc/psl_support-body.vhd +lib/nvc.19/NVC.VERILOG: $(srcdir)/lib/nvc/verilog.vhd @ifGNUmake@ | $(DRIVER) + $(nvc) --std=2019 -L lib/ --work=lib/nvc.19 -a $(srcdir)/lib/nvc/verilog.vhd + +lib/nvc.19/NVC.VERILOG-body: $(srcdir)/lib/nvc/verilog-body.vhd @ifGNUmake@ | $(DRIVER) + $(nvc) --std=2019 -L lib/ --work=lib/nvc.19 -a $(srcdir)/lib/nvc/verilog-body.vhd + gen-deps-nvc-19: $(nvc) --std=2019 -L lib/ --work=lib/nvc.19 --print-deps | \ $(deps_pp) > $(srcdir)/lib/nvc.19/deps.mk diff --git a/lib/nvc.19/deps.mk b/lib/nvc.19/deps.mk index 1b0a4325..42d732ad 100644 --- a/lib/nvc.19/deps.mk +++ b/lib/nvc.19/deps.mk @@ -16,3 +16,7 @@ lib/nvc.19/NVC.TEXT_UTIL-body: lib/std.19/STD.STANDARD lib/nvc.19/NVC.TEXT_UTIL lib/nvc.19/NVC.TEXT_UTIL: lib/std.19/STD.STANDARD $(top_srcdir)/lib/nvc/text_util.vhd +lib/nvc.19/NVC.VERILOG-body: lib/std.19/STD.STANDARD lib/nvc.19/NVC.VERILOG $(top_srcdir)/lib/nvc/verilog-body.vhd + +lib/nvc.19/NVC.VERILOG: lib/std.19/STD.STANDARD $(top_srcdir)/lib/nvc/verilog.vhd + diff --git a/lib/nvc/Makemodule.am b/lib/nvc/Makemodule.am index 5a477f29..a4abf976 100644 --- a/lib/nvc/Makemodule.am +++ b/lib/nvc/Makemodule.am @@ -8,7 +8,9 @@ nvc_DATA = \ lib/nvc/NVC.TEXT_UTIL \ lib/nvc/NVC.TEXT_UTIL-body \ lib/nvc/NVC.PSL_SUPPORT \ - lib/nvc/NVC.PSL_SUPPORT-body + lib/nvc/NVC.PSL_SUPPORT-body \ + lib/nvc/NVC.VERILOG \ + lib/nvc/NVC.VERILOG-body EXTRA_DIST += \ lib/nvc/sim_pkg.vhd \ @@ -17,7 +19,9 @@ EXTRA_DIST += \ lib/nvc/text_util.vhd \ lib/nvc/text_util-body.vhd \ lib/nvc/psl_support.vhd \ - lib/nvc/psl_support-body.vhd + lib/nvc/psl_support-body.vhd \ + lib/nvc/verilog.vhd \ + lib/nvc/verilog-body.vhd BOOTSTRAPLIBS += $(nvc_DATA) @@ -46,6 +50,12 @@ lib/nvc/NVC.PSL_SUPPORT: $(srcdir)/lib/nvc/psl_support.vhd @ifGNUmake@ | $(DRIVE lib/nvc/NVC.PSL_SUPPORT-body: $(srcdir)/lib/nvc/psl_support-body.vhd @ifGNUmake@ | $(DRIVER) $(nvc) --std=1993 -L lib/ --work=lib/nvc -a $(srcdir)/lib/nvc/psl_support-body.vhd +lib/nvc/NVC.VERILOG: $(srcdir)/lib/nvc/verilog.vhd @ifGNUmake@ | $(DRIVER) + $(nvc) --std=1993 -L lib/ --work=lib/nvc -a $(srcdir)/lib/nvc/verilog.vhd + +lib/nvc/NVC.VERILOG-body: $(srcdir)/lib/nvc/verilog-body.vhd @ifGNUmake@ | $(DRIVER) + $(nvc) --std=1993 -L lib/ --work=lib/nvc -a $(srcdir)/lib/nvc/verilog-body.vhd + gen-deps-nvc: $(nvc) --std=1993 -L lib/ --work=lib/nvc --print-deps | \ $(deps_pp) > $(srcdir)/lib/nvc/deps.mk diff --git a/lib/nvc/deps.mk b/lib/nvc/deps.mk index 33c0c8b3..f4b4dc1e 100644 --- a/lib/nvc/deps.mk +++ b/lib/nvc/deps.mk @@ -14,3 +14,7 @@ lib/nvc/NVC.TEXT_UTIL-body: lib/std/STD.STANDARD lib/nvc/NVC.TEXT_UTIL lib/nvc/N lib/nvc/NVC.TEXT_UTIL: lib/std/STD.STANDARD $(top_srcdir)/lib/nvc/text_util.vhd +lib/nvc/NVC.VERILOG-body: lib/std/STD.STANDARD lib/nvc/NVC.VERILOG $(top_srcdir)/lib/nvc/verilog-body.vhd + +lib/nvc/NVC.VERILOG: lib/std/STD.STANDARD $(top_srcdir)/lib/nvc/verilog.vhd + diff --git a/lib/nvc/verilog-body.vhd b/lib/nvc/verilog-body.vhd new file mode 100644 index 00000000..56adda34 --- /dev/null +++ b/lib/nvc/verilog-body.vhd @@ -0,0 +1,38 @@ +------------------------------------------------------------------------------- +-- Copyright (C) 2023 Nick Gasson +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +------------------------------------------------------------------------------- + +package body verilog is + + function to_integer (value : t_packed_logic) return integer is + begin + return 0; + end function; + + function to_time (value : t_packed_logic) return delay_length is + alias v : t_packed_logic(0 to value'length - 1) is value; + variable r : delay_length := 0 fs; + variable add : delay_length := 1 fs; + begin + for i in v'reverse_range loop + if v(i) = '1' then + r := r + add; + end if; + add := add * 2; + end loop; + return r; + end function; + +end package body; diff --git a/lib/nvc/verilog.vhd b/lib/nvc/verilog.vhd new file mode 100644 index 00000000..bbed9591 --- /dev/null +++ b/lib/nvc/verilog.vhd @@ -0,0 +1,31 @@ +------------------------------------------------------------------------------- +-- Copyright (C) 2023 Nick Gasson +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- This package provides support routines for Verilog simulation +------------------------------------------------------------------------------- + +package verilog is + + type t_logic is ('0', '1', 'Z', 'X'); + + type t_packed_logic is array (natural range <>) of t_logic; + + function to_integer (value : t_packed_logic) return integer; + + function to_time (value : t_packed_logic) return delay_length; + +end package; diff --git a/src/lexer.l b/src/lexer.l index be8ff9bc..81eacd8b 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -444,6 +444,7 @@ UNION ?i:union <*>"[" { TOKEN(tLSQUARE); } <*>"]" { TOKEN(tRSQUARE); } <*>"=" { TOKEN(tEQ); } +<*>"#" { TOKEN(tHASH); } "**" { TOKEN(tPOWER); } ":=" { TOKEN(tASSIGN); } diff --git a/src/rt/verilog.c b/src/rt/verilog.c index e2d8c4d2..9710be8b 100644 --- a/src/rt/verilog.c +++ b/src/rt/verilog.c @@ -17,6 +17,7 @@ #include "util.h" #include "jit/jit.h" +#include "jit/jit-ffi.h" #include "rt/model.h" #include "vlog/vlog-number.h" @@ -25,12 +26,18 @@ #include #include -static void verilog_printf(jit_scalar_t *args) +static const void *next_arg(jit_scalar_t **args, unsigned *length) { - const int fmtlen = (*args++).integer; - assert(fmtlen >= 0); + void *ptr = (*args)[0].pointer; + *length = ffi_array_length((*args)[2].integer); + *args += 3; + return ptr; +} - const char *fmt = (*args++).pointer, *start = fmt, *p = fmt; +static void verilog_printf(jit_scalar_t *args) +{ + unsigned fmtlen; + const char *fmt = next_arg(&args, &fmtlen), *start = fmt, *p = fmt; for (; *p && p < fmt + fmtlen; p++) { if (*p == '%') { @@ -40,24 +47,30 @@ static void verilog_printf(jit_scalar_t *args) switch (*++p) { case 's': { - const int len = (*args++).integer; - const char *str = (*args++).pointer; - fwrite(str, 1, len, stdout); + unsigned len; + const char *str = next_arg(&args, &len); + fputs(str, stdout); } break; case 'd': case 'x': { - const int width = (*args++).integer; - const uint8_t *bits = (*args++).pointer; + unsigned width; + const uint8_t *bits = next_arg(&args, &width); number_t num = number_pack(bits, width); switch (*p) { case 'd': - printf("%*"PRIi64, width, number_integer(num)); + if (number_is_defined(num)) + printf("%*"PRIi64, width, number_integer(num)); + else + printf("x"); break; case 'x': - printf("%0*"PRIx64, width, number_integer(num)); + if (number_is_defined(num)) + printf("%0*"PRIx64, width, number_integer(num)); + else + printf("x"); break; } } diff --git a/src/scan.c b/src/scan.c index 84bc38dc..3abb60fd 100644 --- a/src/scan.c +++ b/src/scan.c @@ -214,7 +214,9 @@ const char *token_str(token_t tok) "restrict", "restrict_guarantee", "strong", "fairness", "cover", "property", "sequence", "const", "mutable", "hdltype", "boolean", "bit", "bitvector", "numeric", "string", "[*", "[+]", "[=", "[->", - "&&", "within", "system task", "view", "private" + "&&", "within", "system task", "view", "private" "prev", "stable", + "rose", "fell", "ended", "nondet", "nondetv", "untion", "translate on" + "translate off" }; if (tok > 0 && tok - 200 < ARRAY_LEN(token_strs)) diff --git a/src/scan.h b/src/scan.h index 44ecd7b1..35b49c2d 100644 --- a/src/scan.h +++ b/src/scan.h @@ -88,6 +88,7 @@ bool is_scanned_as_psl(void); #define tLSQUARE '[' #define tRSQUARE ']' #define tOVER '/' +#define tHASH '#' #define tID 200 #define tENTITY 201 diff --git a/src/vlog/vlog-lower.c b/src/vlog/vlog-lower.c index 36cd94a3..d2e8f6fc 100644 --- a/src/vlog/vlog-lower.c +++ b/src/vlog/vlog-lower.c @@ -55,21 +55,51 @@ static vcode_reg_t vlog_debug_locus(vlog_node_t v) return emit_debug_locus(unit, offset); } -static vcode_reg_t vlog_lower_width(vlog_node_t v) +static vcode_reg_t vlog_lower_wrap(lower_unit_t *lu, vcode_reg_t reg) { vcode_type_t voffset = vtype_offset(); + vcode_reg_t left_reg = emit_const(voffset, 0), right_reg, data_reg; + vcode_reg_t dir_reg = emit_const(voffset, RANGE_TO); - switch (vlog_kind(v)) { - case V_STRING: - return emit_const(voffset, strlen(vlog_text(v))); - case V_NUMBER: - return emit_const(voffset, number_width(vlog_number(v))); + switch (vcode_reg_kind(reg)) { + case VCODE_TYPE_CARRAY: + data_reg = emit_address_of(reg); + right_reg = emit_const(voffset, vtype_size(vcode_reg_type(reg)) - 1); + break; + case VCODE_TYPE_INT: + { + vcode_type_t vlogic = vlog_logic_type(); + ident_t name = ident_uniq("wrap_temp"); + vcode_var_t tmp = emit_var(vlogic, vlogic, name, VAR_TEMP); + emit_store(reg, tmp); + + data_reg = emit_index(tmp, VCODE_INVALID_REG); + right_reg = left_reg; + } + break; default: - CANNOT_HANDLE(v); + vcode_dump(); + fatal_trace("cannot wrap r%d", reg); } + + vcode_dim_t dims[1] = { + { left_reg, right_reg, dir_reg } + }; + return emit_wrap(data_reg, dims, 1); +} + +static vcode_reg_t vlog_lower_to_time(lower_unit_t *lu, vcode_reg_t reg) +{ + vcode_reg_t context_reg = emit_link_package(ident_new("NVC.VERILOG")); + vcode_reg_t wrap_reg = vlog_lower_wrap(lu, reg); + vcode_reg_t args[] = { context_reg, wrap_reg }; + vcode_type_t vtime = vtype_time(); + ident_t func = ident_new("NVC.VERILOG.TO_TIME(26NVC.VERILOG.T_PACKED_LOGIC)" + "25STD.STANDARD.DELAY_LENGTH"); + return emit_fcall(func, vtime, vtime, VCODE_CC_VHDL, args, ARRAY_LEN(args)); } -static void vlog_lower_port_decl(lower_unit_t *lu, vlog_node_t port) +static void vlog_lower_signal_decl(lower_unit_t *lu, vlog_node_t port) { vcode_type_t vlogic = vlog_logic_type(); vcode_type_t vsignal = vtype_signal(vlogic); @@ -96,7 +126,8 @@ static void vlog_lower_decls(lower_unit_t *lu, vlog_node_t scope) vlog_node_t d = vlog_decl(scope, i); switch (vlog_kind(d)) { case V_PORT_DECL: - vlog_lower_port_decl(lu, d); + case V_VAR_DECL: + vlog_lower_signal_decl(lu, d); break; default: CANNOT_HANDLE(d); @@ -210,8 +241,7 @@ static vcode_reg_t vlog_lower_rvalue(lower_unit_t *lu, vlog_node_t v) chars[i] = emit_const(vchar, text[i]); vcode_type_t vtype = vtype_carray(len, vchar, vchar); - vcode_reg_t array = emit_const_array(vtype, chars, len); - return emit_address_of(array); + return emit_const_array(vtype, chars, len); } case V_NUMBER: { @@ -226,7 +256,7 @@ static vcode_reg_t vlog_lower_rvalue(lower_unit_t *lu, vlog_node_t v) else { vcode_reg_t *bits LOCAL = xmalloc_array(width, sizeof(vcode_reg_t)); for (int i = 0; i < width; i++) - bits[i] = emit_const(vlogic, number_bit(num, width - i - 1 )); + bits[i] = emit_const(vlogic, number_bit(num, i)); vcode_type_t varray = vtype_carray(width, vlogic, vlogic); return emit_const_array(varray, bits, width); @@ -257,21 +287,40 @@ static void vlog_lower_sensitivity(lower_unit_t *lu, vlog_node_t v) static void vlog_lower_timing(lower_unit_t *lu, vlog_node_t v, bool is_static) { - vcode_reg_t test_reg = vlog_lower_rvalue(lu, vlog_value(v)); + vcode_block_t true_bb = emit_block(), false_bb = VCODE_INVALID_BLOCK; - vcode_block_t true_bb = emit_block(); - vcode_block_t false_bb = emit_block(); + vlog_node_t ctrl = vlog_value(v); + switch (vlog_kind(ctrl)) { + case V_DELAY_CONTROL: + { + vcode_reg_t delay_reg = vlog_lower_rvalue(lu, vlog_value(ctrl)); + emit_wait(true_bb, vlog_lower_to_time(lu, delay_reg)); - emit_cond(test_reg, true_bb, false_bb); + vcode_select_block(true_bb); + } + break; + case V_EVENT: + { + vcode_reg_t test_reg = vlog_lower_rvalue(lu, vlog_value(v)); - vcode_select_block(true_bb); + false_bb = emit_block(); + emit_cond(test_reg, true_bb, false_bb); + + vcode_select_block(true_bb); + } + break; + default: + CANNOT_HANDLE(ctrl); + } vlog_lower_stmts(lu, v); - if (!vcode_block_finished()) - emit_jump(false_bb); + if (false_bb != VCODE_INVALID_BLOCK) { + if (!vcode_block_finished()) + emit_jump(false_bb); - vcode_select_block(false_bb); + vcode_select_block(false_bb); + } } static void vlog_lower_nbassign(lower_unit_t *lu, vlog_node_t v) @@ -280,6 +329,9 @@ static void vlog_lower_nbassign(lower_unit_t *lu, vlog_node_t v) vcode_reg_t count_reg = emit_const(vtype_offset(), 1); vcode_reg_t value_reg = vlog_lower_rvalue(lu, vlog_value(v)); + if (vcode_reg_kind(value_reg) == VCODE_TYPE_CARRAY) + value_reg = emit_load_indirect(emit_address_of(value_reg)); // XXX + vcode_type_t vtime = vtype_time(); vcode_reg_t reject_reg = emit_const(vtime, 0); vcode_reg_t after_reg = emit_const(vtime, 0); @@ -302,16 +354,14 @@ static void vlog_lower_systask(lower_unit_t *lu, vlog_node_t v) case V_SYS_WRITE: { const int nparams = vlog_params(v); - vcode_reg_t *args LOCAL = - xmalloc_array(nparams * 2, sizeof(vcode_reg_t)); + vcode_reg_t *args LOCAL = xmalloc_array(nparams, sizeof(vcode_reg_t)); for (int i = 0; i < nparams; i++) { - vlog_node_t p = vlog_param(v, i); - args[i*2] = vlog_lower_width(p); - args[i*2 + 1] = vlog_lower_rvalue(lu, p); + vcode_reg_t p_reg = vlog_lower_rvalue(lu, vlog_param(v, i)); + args[i] = vlog_lower_wrap(lu, p_reg); } emit_fcall(ident_new(fns[kind]), VCODE_INVALID_TYPE, - VCODE_INVALID_TYPE, VCODE_CC_VARIADIC, args, nparams * 2); + VCODE_INVALID_TYPE, VCODE_CC_VARIADIC, args, nparams); } break; @@ -423,6 +473,8 @@ static void vlog_lower_initial(unit_registry_t *ur, lower_unit_t *parent, lower_unit_t *lu = lower_unit_new(ur, parent, vu, NULL, NULL); unit_registry_put(ur, lu); + vlog_visit(stmt, vlog_driver_cb, lu); + emit_return(VCODE_INVALID_REG); vcode_select_block(start_bb); diff --git a/src/vlog/vlog-node.c b/src/vlog/vlog-node.c index 44b3976e..276c7f93 100644 --- a/src/vlog/vlog-node.c +++ b/src/vlog/vlog-node.c @@ -82,14 +82,17 @@ static const imask_t has_map[V_LAST_NODE_KIND] = { // V_VAR_DECL (I_IDENT | I_RANGES), + + // V_DELAY_CONTROL + (I_VALUE), }; static const char *kind_text_map[V_LAST_NODE_KIND] = { - "V_MODULE", "V_PORT_DECL", "V_REF", "V_ALWAYS", - "V_TIMING", "V_NBASSIGN", "V_EVENT", "V_INITIAL", - "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_MODULE", "V_PORT_DECL", "V_REF", "V_ALWAYS", + "V_TIMING", "V_NBASSIGN", "V_EVENT", "V_INITIAL", + "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", }; static const change_allowed_t change_allowed[] = { diff --git a/src/vlog/vlog-node.h b/src/vlog/vlog-node.h index add6948d..a9f4b850 100644 --- a/src/vlog/vlog-node.h +++ b/src/vlog/vlog-node.h @@ -63,6 +63,7 @@ typedef enum { V_IF, V_COND, V_VAR_DECL, + V_DELAY_CONTROL, V_LAST_NODE_KIND } vlog_kind_t; diff --git a/src/vlog/vlog-number.c b/src/vlog/vlog-number.c index c0d6e32f..12723005 100644 --- a/src/vlog/vlog-number.c +++ b/src/vlog/vlog-number.c @@ -196,7 +196,7 @@ number_t number_pack(const uint8_t *bits, unsigned width) assert(width <= EMBED_WIDTH); uint64_t packed = 0; - for (int i = 0; i < width; i++) { + for (int i = width - 1; i >= 0; i--) { assert(bits[i] <= LOGIC_X); packed <<= 2; packed |= bits[i]; diff --git a/src/vlog/vlog-parse.y b/src/vlog/vlog-parse.y index 7f8ce87d..d66e6a03 100644 --- a/src/vlog/vlog-parse.y +++ b/src/vlog/vlog-parse.y @@ -114,6 +114,7 @@ static bool is_decl(vlog_node_t v) %type port initial_construct net_assignment %type seq_block system_task_enable string number %type decimal_number conditional_statement variable_type +%type delay_control delay_value %type identifier hierarchical_identifier %type module_item_list module_port_list_opt module_item %type list_of_port_declarations module_item_list_opt @@ -528,7 +529,19 @@ procedural_timing_control_statement: ; delay_or_event_control: - event_control + delay_control + | event_control + ; + +delay_control: '#' delay_value + { + $$ = vlog_new(V_DELAY_CONTROL); + vlog_set_loc($$, &@$); + vlog_set_value($$, $2); + } + ; + +delay_value: decimal_number ; event_control: '@' '(' event_expression ')' { $$ = $3; } diff --git a/src/vlog/vlog-sem.c b/src/vlog/vlog-sem.c index 497b1bba..0bb659ae 100644 --- a/src/vlog/vlog-sem.c +++ b/src/vlog/vlog-sem.c @@ -123,6 +123,11 @@ static void vlog_check_number(vlog_node_t num) } +static void vlog_check_string(vlog_node_t num) +{ + +} + static void vlog_check_nbassign(vlog_node_t stmt) { vlog_node_t target = vlog_target(stmt); @@ -169,6 +174,11 @@ static void vlog_check_event(vlog_node_t event) vlog_check(vlog_value(event)); } +static void vlog_check_delay_control(vlog_node_t delay) +{ + vlog_check(vlog_value(delay)); +} + static void vlog_check_always(vlog_node_t always) { const int nstmts = vlog_stmts(always); @@ -206,6 +216,10 @@ static void vlog_check_systask(vlog_node_t call) } vlog_set_subkind(call, kind); + + const int nparams = vlog_params(call); + for (int i = 0; i < nparams; i++) + vlog_check(vlog_param(call, i)); } static void vlog_check_port_decl(vlog_node_t port) @@ -218,6 +232,11 @@ static void vlog_check_net_decl(vlog_node_t net) vlog_insert_decl(net); } +static void vlog_check_var_decl(vlog_node_t var) +{ + vlog_insert_decl(var); +} + static void vlog_check_module(vlog_node_t module) { assert(top_scope == NULL); @@ -256,6 +275,9 @@ void vlog_check(vlog_node_t v) case V_EVENT: vlog_check_event(v); break; + case V_DELAY_CONTROL: + vlog_check_delay_control(v); + break; case V_NBASSIGN: vlog_check_nbassign(v); break; @@ -271,6 +293,9 @@ void vlog_check(vlog_node_t v) case V_NET_DECL: vlog_check_net_decl(v); break; + case V_VAR_DECL: + vlog_check_var_decl(v); + break; case V_SEQ_BLOCK: vlog_check_seq_block(v); break; @@ -280,6 +305,9 @@ void vlog_check(vlog_node_t v) case V_NUMBER: vlog_check_number(v); break; + case V_STRING: + vlog_check_string(v); + break; default: fatal_trace("cannot check verilog node %s", vlog_kind_str(vlog_kind(v))); } diff --git a/test/regress/gold/vlog3.txt b/test/regress/gold/vlog3.txt new file mode 100644 index 00000000..1eefe807 --- /dev/null +++ b/test/regress/gold/vlog3.txt @@ -0,0 +1,5 @@ +x ==> x +x ==> 1 +x ==> 1 +x ==> 0 +x ==> 0 diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 53e5c385..ae38e03f 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -875,3 +875,4 @@ shuffle1 normal,2002,shuffle vhpi11 normal,vhpi,2008 attr18 normal,2019 issue762 normal,vhpi +vlog3 verilog,gold diff --git a/test/regress/vlog3.v b/test/regress/vlog3.v new file mode 100644 index 00000000..bf109729 --- /dev/null +++ b/test/regress/vlog3.v @@ -0,0 +1,26 @@ +module vlog3; + reg x; + + initial begin + x <= 1; + $display("x ==> %d", x); + /*if (x) + $display("x is true"); + else + $display("x is false");*/ + #1; + $display("x ==> %d", x); + /*if (x) + $display("x is true"); + else + $display("x is false");*/ + #1 x <= 0; + $display("x ==> %d", x); + #1 x <= 4; + $display("x ==> %d", x); + #1; + $display("x ==> %d", x); + $finish; + end + +endmodule // vlog3 -- 2.39.2