From 0f928f155c779abe481918efc3df04dd1785f0e9 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 24 Feb 2024 11:04:25 +0000 Subject: [PATCH] Add support for Verilog supply net type. Issue #808 --- src/common.c | 4 +- src/elab.c | 4 +- src/object.c | 9 +--- src/vlog/Makemodule.am | 3 +- src/vlog/vlog-defs.h | 33 ++++++++++++++ src/vlog/vlog-lower.c | 13 +----- src/vlog/vlog-node.c | 19 ++++++++ src/vlog/vlog-node.h | 4 ++ src/vlog/vlog-number.c | 8 ++-- src/vlog/vlog-parse.y | 4 ++ src/vlog/vlog-phase.h | 1 + src/vlog/vlog-simp.c | 80 ++++++++++++++++++++++++++++++++++ src/vlog/vlog-trans.c | 16 ++++++- test/regress/gold/issue808.txt | 1 + test/regress/issue808.v | 12 +++++ test/regress/testlist.txt | 1 + 16 files changed, 184 insertions(+), 28 deletions(-) create mode 100644 src/vlog/vlog-defs.h create mode 100644 src/vlog/vlog-simp.c create mode 100644 test/regress/gold/issue808.txt create mode 100644 test/regress/issue808.v diff --git a/src/common.c b/src/common.c index eaaa1e01..db5426af 100644 --- a/src/common.c +++ b/src/common.c @@ -2384,8 +2384,10 @@ void analyse_file(const char *file, jit_t *jit, unit_registry_t *ur) if (error_count() == 0) { vlog_check(module); - if (error_count() == 0) + if (error_count() == 0) { + vlog_simp(module); lib_put_vlog(work, module); + } } } } diff --git a/src/elab.c b/src/elab.c index 43eb6cf1..55629d22 100644 --- a/src/elab.c +++ b/src/elab.c @@ -34,6 +34,7 @@ #include "psl/psl-phase.h" #include "thread.h" #include "type.h" +#include "vlog/vlog-defs.h" #include "vlog/vlog-node.h" #include "vlog/vlog-phase.h" @@ -43,9 +44,6 @@ #include #include -#define T_LOGIC "19NVC.VERILOG.T_LOGIC" -#define T_NET_VALUE "23NVC.VERILOG.T_NET_VALUE" - typedef A(tree_t) tree_list_t; typedef struct _elab_ctx elab_ctx_t; diff --git a/src/object.c b/src/object.c index 1932cec9..aba1bdd3 100644 --- a/src/object.c +++ b/src/object.c @@ -750,7 +750,8 @@ object_t *object_rewrite(object_t *object, object_rewrite_ctx_t *ctx) if (ctx->pre_fn[object->tag] != NULL) (*ctx->pre_fn[object->tag])(object, ctx->context); - const imask_t skip_mask = I_REF; + const imask_t skip_mask = + I_REF | ITEM_INT64 | ITEM_INT32 | ITEM_DOUBLE | ITEM_NUMBER | ITEM_TEXT; const object_class_t *class = classes[object->tag]; @@ -786,12 +787,6 @@ object_t *object_rewrite(object_t *object, object_rewrite_ctx_t *ctx) (*a)->count = wptr; } } - else if (ITEM_INT64 & mask) - ; - else if (ITEM_INT32 & mask) - ; - else if (ITEM_DOUBLE & mask) - ; else item_without_type(mask); } diff --git a/src/vlog/Makemodule.am b/src/vlog/Makemodule.am index 41c0a347..6218f0dc 100644 --- a/src/vlog/Makemodule.am +++ b/src/vlog/Makemodule.am @@ -6,7 +6,8 @@ lib_libnvc_a_SOURCES += \ src/vlog/vlog-lower.c \ src/vlog/vlog-number.h \ src/vlog/vlog-number.c \ - src/vlog/vlog-trans.c + src/vlog/vlog-trans.c \ + src/vlog/vlog-simp.c if ENABLE_VERILOG lib_libnvc_a_SOURCES += \ diff --git a/src/vlog/vlog-defs.h b/src/vlog/vlog-defs.h new file mode 100644 index 00000000..b420405b --- /dev/null +++ b/src/vlog/vlog-defs.h @@ -0,0 +1,33 @@ +// +// Copyright (C) 2024 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 +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef _VLOG_DEFS_H +#define _VLOG_DEFS_H + +#define T_LOGIC "19NVC.VERILOG.T_LOGIC" +#define T_PACKED_LOGIC "26NVC.VERILOG.T_PACKED_LOGIC" +#define T_INT64 "19NVC.VERILOG.T_INT64" +#define T_NET_VALUE "23NVC.VERILOG.T_NET_VALUE" +#define T_NET_ARRAY "23NVC.VERILOG.T_NET_ARRAY" + +typedef enum { + _X = 0, _SUPPLY0, _STRONG0, _PULL0, _LARGE0, _WEAK0, _MEDIUM0, + _SMALL0, _HIGHZ0, _HIGHZ1, _SMALL1, _MEDIUM1, _WEAK1, _LARGE1, + _PULL1, _STRONG1, _SUPPLY1 +} net_value_t; + +#endif // _VLOG_DEFS_H diff --git a/src/vlog/vlog-lower.c b/src/vlog/vlog-lower.c index 7d376545..49d81b04 100644 --- a/src/vlog/vlog-lower.c +++ b/src/vlog/vlog-lower.c @@ -21,6 +21,7 @@ #include "lower.h" #include "tree.h" #include "vcode.h" +#include "vlog/vlog-defs.h" #include "vlog/vlog-node.h" #include "vlog/vlog-number.h" #include "vlog/vlog-phase.h" @@ -39,18 +40,6 @@ const loc_t _old_loc = *vcode_last_loc(); \ emit_debug_info(vlog_loc((v))); \ -#define T_LOGIC "19NVC.VERILOG.T_LOGIC" -#define T_PACKED_LOGIC "26NVC.VERILOG.T_PACKED_LOGIC" -#define T_INT64 "19NVC.VERILOG.T_INT64" -#define T_NET_VALUE "23NVC.VERILOG.T_NET_VALUE" -#define T_NET_ARRAY "23NVC.VERILOG.T_NET_ARRAY" - -typedef enum { - _X = 0, _SUPPLY0, _STRONG0, _PULL0, _LARGE0, _WEAK0, _MEDIUM0, - _SMALL0, _HIGHZ0, _HIGHZ1, _SMALL1, _MEDIUM1, _WEAK1, _LARGE1, - _PULL1, _STRONG1, _SUPPLY1 -} net_value_t; - static void vlog_lower_stmts(lower_unit_t *lu, vlog_node_t v); static vcode_reg_t vlog_lower_rvalue(lower_unit_t *lu, vlog_node_t v); diff --git a/src/vlog/vlog-node.c b/src/vlog/vlog-node.c index 20f96624..c92674f8 100644 --- a/src/vlog/vlog-node.c +++ b/src/vlog/vlog-node.c @@ -454,6 +454,25 @@ void vlog_visit_only(vlog_node_t v, vlog_visit_fn_t fn, void *context, object_visit(&(v->object), &ctx); } +vlog_node_t vlog_rewrite(vlog_node_t v, vlog_rewrite_fn_t fn, void *context) +{ + object_arena_t *arena = object_arena(&(v->object)); + if (arena_frozen(arena)) + return v; + + object_rewrite_ctx_t ctx = { + .generation = object_next_generation(), + .context = context, + .arena = arena, + }; + + ctx.post_fn[OBJECT_TAG_VLOG] = (object_rewrite_post_fn_t)fn; + + object_t *result = object_rewrite(&(v->object), &ctx); + free(ctx.cache); + return container_of(result, struct _vlog_node, object); +} + object_t *vlog_to_object(vlog_node_t v) { return &(v->object); diff --git a/src/vlog/vlog-node.h b/src/vlog/vlog-node.h index 53d58e3f..9c17545a 100644 --- a/src/vlog/vlog-node.h +++ b/src/vlog/vlog-node.h @@ -190,6 +190,10 @@ void vlog_visit(vlog_node_t v, vlog_visit_fn_t fn, void *context); void vlog_visit_only(vlog_node_t v, vlog_visit_fn_t fn, void *context, vlog_kind_t kind); +typedef vlog_node_t (*vlog_rewrite_fn_t)(vlog_node_t t, void *context); + +vlog_node_t vlog_rewrite(vlog_node_t v, vlog_rewrite_fn_t fn, void *context); + void vlog_locus(vlog_node_t v, ident_t *unit, ptrdiff_t *offset); object_t *vlog_to_object(vlog_node_t v); diff --git a/src/vlog/vlog-number.c b/src/vlog/vlog-number.c index 6d3fdeae..32edd067 100644 --- a/src/vlog/vlog-number.c +++ b/src/vlog/vlog-number.c @@ -1,5 +1,5 @@ // -// Copyright (C) 2023 Nick Gasson +// Copyright (C) 2023-2024 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 @@ -17,6 +17,7 @@ #include "util.h" #include "diag.h" +#include "fbuf.h" #include "vlog/vlog-number.h" #include @@ -219,10 +220,11 @@ number_t number_pack(const uint8_t *bits, unsigned width) void number_write(number_t val, fbuf_t *f) { - + assert(val.tag); + fbuf_put_uint(f, val.bits); } number_t number_read(fbuf_t *f) { - return (number_t){ .bits = 0 }; + return (number_t){ .bits = fbuf_get_uint(f) }; } diff --git a/src/vlog/vlog-parse.y b/src/vlog/vlog-parse.y index d1c8b6d9..34d6bfe7 100644 --- a/src/vlog/vlog-parse.y +++ b/src/vlog/vlog-parse.y @@ -345,6 +345,9 @@ module_or_generate_item_declaration: net_declaration: net_type list_of_net_identifiers ';' { + for (node_list_t *it = $2; it; it = it->next) + vlog_set_subkind(it->value, $1); + $$ = $2; } | net_type '[' expression ':' expression ']' @@ -359,6 +362,7 @@ net_declaration: for (node_list_t *it = $7; it; it = it->next) { vlog_add_range(it->value, r); vlog_set_datatype(it->value, DT_LOGIC); + vlog_set_subkind(it->value, $1); } $$ = $7; diff --git a/src/vlog/vlog-phase.h b/src/vlog/vlog-phase.h index c65430d2..59a4f868 100644 --- a/src/vlog/vlog-phase.h +++ b/src/vlog/vlog-phase.h @@ -24,6 +24,7 @@ void vlog_preprocess(text_buf_t *tb); vlog_node_t vlog_parse(void); void vlog_check(vlog_node_t v); void vlog_dump(vlog_node_t v, int indent); +void vlog_simp(vlog_node_t mod); void vlog_trans(vlog_node_t mod, tree_t out); vcode_unit_t vlog_lower(unit_registry_t *ur, vlog_node_t mod); diff --git a/src/vlog/vlog-simp.c b/src/vlog/vlog-simp.c new file mode 100644 index 00000000..48854d82 --- /dev/null +++ b/src/vlog/vlog-simp.c @@ -0,0 +1,80 @@ +// +// Copyright (C) 2024 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 +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "util.h" +#include "diag.h" +#include "ident.h" +#include "vlog/vlog-node.h" +#include "vlog/vlog-number.h" +#include "vlog/vlog-phase.h" + +#include +#include +#include + +static vlog_node_t simp_net_decl(vlog_node_t decl, vlog_node_t mod) +{ + const vlog_net_kind_t kind = vlog_subkind(decl); + if (kind == V_NET_SUPPLY0 || kind == V_NET_SUPPLY1) { + vlog_node_t g = vlog_new(V_GATE_INST); + vlog_set_loc(g, vlog_loc(decl)); + + ident_t name = vlog_ident(decl); + ident_t id = ident_prefix(name, ident_new("pull"), '#'); + vlog_set_ident(g, id); + + vlog_node_t s = vlog_new(V_STRENGTH); + vlog_add_param(g, s); + + if (kind == V_NET_SUPPLY0) { + vlog_set_subkind(g, V_GATE_PULLDOWN); + vlog_set_subkind(s, V_STRENGTH_SUPPLY0); + } + else { + vlog_set_subkind(g, V_GATE_PULLUP); + vlog_set_subkind(s, V_STRENGTH_SUPPLY1); + } + + vlog_node_t target = vlog_new(V_REF); + vlog_set_loc(target, vlog_loc(decl)); + vlog_set_ident(target, name); + vlog_set_ref(target, decl); + + vlog_set_target(g, target); + + vlog_add_stmt(mod, g); + } + + return decl; +} + +static vlog_node_t vlog_simp_cb(vlog_node_t v, void *context) +{ + switch (vlog_kind(v)) { + case V_NET_DECL: + return simp_net_decl(v, context); + default: + return v; + } +} + +void vlog_simp(vlog_node_t mod) +{ + assert(vlog_kind(mod) == V_MODULE); + + vlog_rewrite(mod, vlog_simp_cb, mod); +} diff --git a/src/vlog/vlog-trans.c b/src/vlog/vlog-trans.c index 0a96b5f3..3b48e506 100644 --- a/src/vlog/vlog-trans.c +++ b/src/vlog/vlog-trans.c @@ -19,10 +19,13 @@ #include "common.h" #include "tree.h" #include "type.h" +#include "vlog/vlog-defs.h" #include "vlog/vlog-node.h" #include "vlog/vlog-number.h" #include "vlog/vlog-phase.h" +#include + #define CANNOT_HANDLE(v) do { \ fatal_at(vlog_loc(v), "cannot handle %s in %s" , \ vlog_kind_str(vlog_kind(v)), __FUNCTION__); \ @@ -134,11 +137,22 @@ static void trans_var_decl(vlog_node_t decl, tree_t out) static void trans_net_decl(vlog_node_t decl, tree_t out) { + type_t type = trans_net_type(decl); + tree_t t = tree_new(T_SIGNAL_DECL); tree_set_ident(t, vlog_ident(decl)); - tree_set_type(t, trans_net_type(decl)); + tree_set_type(t, type); tree_add_decl(out, t); + + const vlog_net_kind_t kind = vlog_subkind(decl); + if (kind == V_NET_SUPPLY0 || kind == V_NET_SUPPLY1) { + type_t base = type_base_recur(type_elem_recur(type)); + assert(type_kind(base) == T_ENUM); + + const net_value_t init = (kind == V_NET_SUPPLY0 ? _SUPPLY0 : _SUPPLY1); + tree_set_value(t, make_ref(type_enum_literal(base, init))); + } } void vlog_trans(vlog_node_t mod, tree_t out) diff --git a/test/regress/gold/issue808.txt b/test/regress/gold/issue808.txt new file mode 100644 index 00000000..6e8183b7 --- /dev/null +++ b/test/regress/gold/issue808.txt @@ -0,0 +1 @@ +0 1 diff --git a/test/regress/issue808.v b/test/regress/issue808.v new file mode 100644 index 00000000..462dde0a --- /dev/null +++ b/test/regress/issue808.v @@ -0,0 +1,12 @@ +module issue808; + supply0 gnd; + supply1 vcc; + + assign gnd = vcc; + + initial begin + $display("%x %x", gnd, vcc); + $finish; + end + +endmodule // issue808 diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 950e7045..d5eff261 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -944,3 +944,4 @@ conv14 normal,2008 issue850 shell vlog7 verilog,gold wait27 normal +issue808 verilog,gold -- 2.39.2