From 4e82c27c6ac477108aaa577889db2342e07a3f70 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 1 Jan 2022 14:21:27 +0800 Subject: [PATCH] Add object type for representing Verilog AST --- Makefile.am | 9 +- src/dump.c | 9 +- src/elab.c | 3 +- src/lib.c | 115 +++++++++------ src/lib.h | 1 + src/lower.c | 1 + src/object.c | 46 ++++-- src/object.h | 26 ++-- src/parse.c | 1 + src/prim.h | 1 + src/tree.c | 72 ++-------- src/tree.h | 11 +- src/type.c | 3 +- src/util.h | 2 +- src/vlog/Makemodule.am | 5 + src/vlog/vlog-dump.c | 258 +++++++++++++++++++++++++++++++++ src/vlog/vlog-node.c | 315 +++++++++++++++++++++++++++++++++++++++++ src/vlog/vlog-node.h | 111 +++++++++++++++ src/vlog/vlog-phase.h | 26 ++++ test/run_regr.c | 16 ++- test/test_jit.c | 1 + test/test_lib.c | 1 + test/test_value.c | 3 +- tools/run.sh | 9 +- 24 files changed, 900 insertions(+), 145 deletions(-) create mode 100644 src/vlog/Makemodule.am create mode 100644 src/vlog/vlog-dump.c create mode 100644 src/vlog/vlog-node.c create mode 100644 src/vlog/vlog-node.h create mode 100644 src/vlog/vlog-phase.h diff --git a/Makefile.am b/Makefile.am index dd59683c..c1834d6a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,11 +6,12 @@ man_MANS = nvc.1 AM_CPPFLAGS = -I$(top_srcdir)/thirdparty -I$(top_srcdir)/src AM_CFLAGS = -Wall $(EXTRA_CFLAGS) $(LTO_FLAG) +AM_CXXFLAGS = -Wall $(EXTRA_CFLAGS) $(LTO_FLAG) AM_LDFLAGS = $(EXTRA_LDFLAGS) $(LLVM_LDFLAGS) AM_CC = $(PTHREAD_CC) -AM_CFLAGS += $(PTHREAD_CFLAGS) -AM_LDFLAGS += $(PTHREAD_LIBS) +AM_CFLAGS += $(PTHREAD_CFLAGS) +AM_LDFLAGS += $(PTHREAD_LIBS) AM_CFLAGS += $(check_CFLAGS) $(libdw_CFLAGS) $(libffi_CFLAGS) @@ -36,6 +37,7 @@ include src/Makemodule.am include src/rt/Makemodule.am include src/jit/Makemodule.am include src/vhpi/Makemodule.am +include src/vlog/Makemodule.am include test/Makemodule.am include test/vhpi/Makemodule.am include lib/Makemodule.am @@ -55,7 +57,8 @@ include contrib/Makemodule.am compile-commands: $(MAKE) -C $(top_builddir) clean - bear -- $(MAKE) -j -C $(top_builddir) $(bin_PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) + bear -- $(MAKE) -j -C $(top_builddir) $(bin_PROGRAMS) \ + $(check_PROGRAMS) $(EXTRA_PROGRAMS) $(pkglibexec_PROGRAMS) clean-local: clean-test clean-libs diff --git a/src/dump.c b/src/dump.c index 1c2b8428..6197d90e 100644 --- a/src/dump.c +++ b/src/dump.c @@ -256,8 +256,13 @@ static void dump_expr(tree_t t) { printf("\""); const int nchars = tree_chars(t); - for (int i = 0; i < nchars; i++) - printf("%c", ident_char(tree_ident(tree_char(t, i)), 1)); + for (int i = 0; i < nchars; i++) { + ident_t rune = tree_ident(tree_char(t, i)); + if (ident_char(rune, 0) == '\'') + printf("%c", ident_char(rune, 1)); + else + printf("\" & %s & \"", istr(rune)); + } printf("\""); } break; diff --git a/src/elab.c b/src/elab.c index 36cfbdac..45709cd8 100644 --- a/src/elab.c +++ b/src/elab.c @@ -22,6 +22,7 @@ #include "eval.h" #include "hash.h" #include "lib.h" +#include "object.h" #include "opt.h" #include "phase.h" #include "type.h" @@ -1777,7 +1778,7 @@ static void elab_top_level(tree_t arch, const elab_ctx_t *ctx) elab_decls(entity, &new_ctx); simplify_global(arch_copy, new_ctx.generics, ctx->eval); - bounds_check(arch); + bounds_check(arch); // XXX: should be arch_copy if (error_count() == 0) elab_arch(arch_copy, &new_ctx); diff --git a/src/lib.c b/src/lib.c index 6fed1df3..2c72204b 100644 --- a/src/lib.c +++ b/src/lib.c @@ -24,6 +24,7 @@ #include "opt.h" #include "tree.h" #include "vcode.h" +#include "vlog/vlog-node.h" #include #include @@ -47,7 +48,8 @@ typedef struct _lib_unit lib_unit_t; #define INDEX_FILE_MAGIC 0x55225511 struct _lib_unit { - tree_t top; + object_t *object; + ident_t name; tree_kind_t kind; bool dirty; bool error; @@ -174,7 +176,7 @@ static void lib_read_index(lib_t lib) for (int i = 0; i < entries; i++) { ident_t name = ident_read(ictx); tree_kind_t kind = read_u16(f); - assert(kind < T_LAST_TREE_KIND); + assert(kind <= T_LAST_TREE_KIND); while (*insert && ident_compare((*insert)->name, name) < 0) insert = &((*insert)->next); @@ -262,13 +264,21 @@ static lib_index_t *lib_find_in_index(lib_t lib, ident_t name) return it; } -static lib_unit_t *lib_put_aux(lib_t lib, tree_t unit, bool dirty, bool error, - lib_mtime_t mtime, vcode_unit_t vu) +static lib_unit_t *lib_put_aux(lib_t lib, object_t *object, bool dirty, + bool error, lib_mtime_t mtime, vcode_unit_t vu) { assert(lib != NULL); - assert(unit != NULL); - ident_t name = tree_ident(unit); + tree_kind_t kind = T_LAST_TREE_KIND; + ident_t name; + tree_t tree; + if ((tree = tree_from_object(object))) { + name = tree_ident(tree); + kind = tree_kind(tree); + } + else + fatal_trace("unexpected object class in lib_put_aux"); + assert(ident_until(name, '.') == lib->name); bool fresh = false; @@ -278,7 +288,7 @@ static lib_unit_t *lib_put_aux(lib_t lib, tree_t unit, bool dirty, bool error, fresh = true; } else { - hash_delete(lib->lookup, where->top); + hash_delete(lib->lookup, object); if (where->vcode != NULL) { vcode_unit_unref(where->vcode); @@ -286,26 +296,27 @@ static lib_unit_t *lib_put_aux(lib_t lib, tree_t unit, bool dirty, bool error, } } - where->top = unit; - where->dirty = dirty; - where->error = error; - where->mtime = mtime; - where->kind = tree_kind(unit); - where->vcode = vu; + where->object = object; + where->name = name; + where->dirty = dirty; + where->error = error; + where->mtime = mtime; + where->kind = kind; + where->vcode = vu; if (fresh) { lib_unit_t **it; for (it = &(lib->units); *it; it = &(*it)->next) { - assert((*it)->top != unit); - assert(tree_ident((*it)->top) != name); + assert((*it)->object != object); + assert((*it)->name != name); } *it = where; } - lib_add_to_index(lib, name, tree_kind(unit)); + lib_add_to_index(lib, name, where->kind); hash_put(lib->lookup, name, where); - hash_put(lib->lookup, unit, where); + hash_put(lib->lookup, object, where); return where; } @@ -683,14 +694,21 @@ static lib_mtime_t lib_mtime_now(void) return ((lib_mtime_t)tv.tv_sec * 1000000) + tv.tv_usec; } +void lib_put_generic(lib_t lib, object_t *obj) +{ + lib_put_aux(lib, obj, true, false, lib_mtime_now(), NULL); +} + void lib_put(lib_t lib, tree_t unit) { - lib_put_aux(lib, unit, true, false, lib_mtime_now(), NULL); + object_t *obj = tree_to_object(unit); + lib_put_generic(lib, obj); } void lib_put_error(lib_t lib, tree_t unit) { - lib_put_aux(lib, unit, true, true, lib_mtime_now(), NULL); + object_t *obj = tree_to_object(unit); + lib_put_aux(lib, obj, true, true, lib_mtime_now(), NULL); } static lib_unit_t *lib_find_unit(lib_t lib, tree_t unit) @@ -748,13 +766,14 @@ static lib_unit_t *lib_read_unit(lib_t lib, const char *fname) loc_rd_ctx_t *loc_ctx = loc_read_begin(f); vcode_unit_t vu = NULL; - tree_t top = NULL; + object_t *obj = NULL; char tag; while ((tag = read_u8(f))) { switch (tag) { case 'T': - top = tree_read(f, lib_get_qualified, ident_ctx, loc_ctx); + obj = object_read(f, (object_load_fn_t)lib_get_qualified, + ident_ctx, loc_ctx); break; case 'V': vu = vcode_read(f, ident_ctx, loc_ctx); @@ -770,10 +789,10 @@ static lib_unit_t *lib_read_unit(lib_t lib, const char *fname) uint32_t checksum; fbuf_close(f, &checksum); - if (top == NULL) - fatal_trace("%s did not contain tree", fname); + if (obj == NULL) + fatal_trace("%s did not HDL design unit", fname); - arena_set_checksum(tree_arena(top), checksum); + arena_set_checksum(object_arena(obj), checksum); LOCAL_TEXT_BUF path = lib_file_path(lib, fname); @@ -782,8 +801,7 @@ static lib_unit_t *lib_read_unit(lib_t lib, const char *fname) fatal_errno("%s", fname); lib_mtime_t mt = lib_stat_mtime(&st); - - return lib_put_aux(lib, top, false, false, mt, vu); + return lib_put_aux(lib, obj, false, false, mt, vu); } static lib_unit_t *lib_get_aux(lib_t lib, ident_t ident) @@ -829,18 +847,16 @@ static lib_unit_t *lib_get_aux(lib_t lib, ident_t ident) "on disk", istr(lib->name), istr(ident)); if (lu != NULL && !opt_get_int(OPT_IGNORE_TIME)) { - const loc_t *loc = tree_loc(lu->top); - bool stale = false; + const char *file = loc_file_str(&(lu->object->loc)); struct stat st; - if (stat(loc_file_str(loc), &st) == 0) + if (stat(file, &st) == 0) stale = (lu->mtime < lib_stat_mtime(&st)); if (stale) { diag_t *d = diag_new(DIAG_WARN, NULL); diag_printf(d, "design unit %s is older than its source file " - "%s and should be reanalysed", - istr(ident), loc_file_str(loc)); + "%s and should be reanalysed", istr(ident), file); diag_hint(d, NULL, "you can use the $bold$--ignore-time$$ option " "to skip this check"); diag_emit(d); @@ -881,10 +897,15 @@ tree_t lib_get(lib_t lib, ident_t ident) lib_unit_t *lu = lib_get_aux(lib, ident); if (lu != NULL) { if (lu->error) - fatal_at(tree_loc(lu->top), "design unit %s was analysed with errors", - istr(tree_ident(lu->top))); - else - return lu->top; + fatal_at(&lu->object->loc, "design unit %s was analysed with errors", + istr(lu->name)); + else { + tree_t tree = tree_from_object(lu->object); + if (tree == NULL) + fatal_at(&lu->object->loc, "%s is not a VHDL design unit", + istr(lu->name)); + return tree; + } } else return NULL; @@ -895,7 +916,12 @@ tree_t lib_get_allow_error(lib_t lib, ident_t ident, bool *error) lib_unit_t *lu = lib_get_aux(lib, ident); if (lu != NULL) { *error = lu->error; - return lu->top; + + tree_t tree = tree_from_object(lu->object); + if (tree == NULL) + fatal_at(&lu->object->loc, "%s is not a VHDL design unit", + istr(lu->name)); + return tree; } else { *error = false; @@ -924,17 +950,19 @@ ident_t lib_name(lib_t lib) static void lib_save_unit(lib_t lib, lib_unit_t *unit) { - const char *name = istr(tree_ident(unit->top)); - fbuf_t *f = lib_fbuf_open(lib, name, FBUF_OUT, FBUF_CS_ADLER32); + fbuf_t *f = lib_fbuf_open(lib, istr(unit->name), FBUF_OUT, FBUF_CS_ADLER32); if (f == NULL) - fatal("failed to create %s in library %s", name, istr(lib->name)); + fatal("failed to create %s in library %s", istr(unit->name), + istr(lib->name)); write_u8('T', f); ident_wr_ctx_t ident_ctx = ident_write_begin(f); loc_wr_ctx_t *loc_ctx = loc_write_begin(f); - tree_write(unit->top, f, ident_ctx, loc_ctx); + object_arena_t *arena = object_arena(unit->object); + + object_write(unit->object, f, ident_ctx, loc_ctx); if (unit->vcode != NULL) { write_u8('V', f); @@ -949,7 +977,7 @@ static void lib_save_unit(lib_t lib, lib_unit_t *unit) uint32_t checksum; fbuf_close(f, &checksum); - arena_set_checksum(tree_arena(unit->top), checksum); + arena_set_checksum(arena, checksum); assert(unit->dirty); unit->dirty = false; @@ -963,11 +991,13 @@ void lib_save(lib_t lib) lib_ensure_writable(lib); file_write_lock(lib->lock_fd); + freeze_global_arena(); + for (lib_unit_t *lu = lib->units; lu; lu = lu->next) { if (lu->dirty) { if (lu->error) fatal_trace("attempting to save unit %s with errors", - istr(tree_ident(lu->top))); + istr(lu->name)); else lib_save_unit(lib, lu); } @@ -1004,6 +1034,7 @@ void lib_save(lib_t lib) if (stat(tb_get(index_path), &st) != 0) fatal_errno("stat: %s", tb_get(index_path)); + lib->index_mtime = lib_stat_mtime(&st); lib->index_size = st.st_size; diff --git a/src/lib.h b/src/lib.h index 98e26bb3..9f455c72 100644 --- a/src/lib.h +++ b/src/lib.h @@ -59,6 +59,7 @@ void lib_set_work(lib_t lib); void lib_put(lib_t lib, tree_t unit); void lib_put_error(lib_t lib, tree_t unit); +void lib_put_generic(lib_t lib, object_t *obj); tree_t lib_get(lib_t lib, ident_t ident); tree_t lib_get_allow_error(lib_t lib, ident_t ident, bool *error); tree_t lib_get_qualified(ident_t qual); diff --git a/src/lower.c b/src/lower.c index 455330c6..7f897eaa 100644 --- a/src/lower.c +++ b/src/lower.c @@ -21,6 +21,7 @@ #include "diag.h" #include "hash.h" #include "lib.h" +#include "object.h" #include "opt.h" #include "phase.h" #include "rt/cover.h" diff --git a/src/object.c b/src/object.c index 6da10280..daa6b2d9 100644 --- a/src/object.c +++ b/src/object.c @@ -87,10 +87,11 @@ static const char *item_text_map[] = { "????", "????", "????", "????", "I_PRIMARY", }; -static object_class_t *classes[4]; -static uint32_t format_digest; -static generation_t next_generation = 1; -static arena_array_t all_arenas; +static object_class_t *classes[4]; +static uint32_t format_digest; +static generation_t next_generation = 1; +static arena_array_t all_arenas; +static object_arena_t *global_arena = NULL; static inline bool object_in_arena_p(object_arena_t *arena, object_t *object) { @@ -345,12 +346,14 @@ void object_one_time_init(void) { extern object_class_t tree_object; extern object_class_t type_object; + extern object_class_t vlog_node_object; static bool done = false; if (unlikely(!done)) { object_init(&tree_object); object_init(&type_object); + object_init(&vlog_node_object); // Increment this each time a incompatible change is made to the // on-disk format not expressed in the object items table @@ -370,6 +373,9 @@ object_t *object_new(object_arena_t *arena, object_one_time_init(); + if (arena == NULL) + arena = global_arena; + if (unlikely(arena == NULL)) fatal_trace("allocating object without active arena"); @@ -565,17 +571,17 @@ void object_visit(object_t *object, object_visit_ctx_t *ctx) else if (object_marked_p(object, ctx->generation)) return; + const object_class_t *class = classes[object->tag]; + const bool visit = - (object->tag == OBJECT_TAG_TREE && object->kind == ctx->kind) - || ctx->kind == T_LAST_TREE_KIND; + (object->tag == ctx->tag && object->kind == ctx->kind) + || ctx->kind == class->last_kind; if (visit && ctx->preorder != NULL) - (*ctx->preorder)((tree_t)object, ctx->context); + (*ctx->preorder)(object, ctx->context); const imask_t deep_mask = I_TYPE | I_REF; - const object_class_t *class = classes[object->tag]; - const imask_t has = class->has_map[object->kind]; const int nitems = class->object_nitems[object->kind]; imask_t mask = 1; @@ -608,7 +614,7 @@ void object_visit(object_t *object, object_visit_ctx_t *ctx) if (visit) { if (ctx->postorder != NULL) - (*ctx->postorder)((tree_t)object, ctx->context); + (*ctx->postorder)(object, ctx->context); ctx->count++; } } @@ -1026,7 +1032,7 @@ static bool object_copy_mark(object_t *object, object_copy_ctx_t *ctx) object_t *copy = NULL; if (marked) { - copy = object_new(ctx->arena, class, object->kind); + copy = object_new(global_arena, class, object->kind); hash_put(ctx->copy_map, object, copy); } @@ -1061,7 +1067,7 @@ static bool object_copy_mark(object_t *object, object_copy_ctx_t *ctx) } if (marked && copy == NULL) { - copy = object_new(ctx->arena, class, object->kind); + copy = object_new(global_arena, class, object->kind); hash_put(ctx->copy_map, object, copy); } @@ -1145,7 +1151,7 @@ void object_copy(object_copy_ctx_t *ctx) if (opt_get_verbose(OPT_OBJECT_VERBOSE, NULL)) notef("copied %d objects into arena %s", ncopied, - istr(object_arena_name(ctx->arena))); + istr(object_arena_name(global_arena))); for (unsigned i = 0; i < ctx->nroots; i++) { object_t *copy = hash_get(ctx->copy_map, ctx->roots[i]); @@ -1285,3 +1291,17 @@ object_t *object_from_locus(ident_t module, ptrdiff_t offset, return obj; } + +void freeze_global_arena(void) +{ + if (global_arena != NULL) { + object_arena_freeze(global_arena); + global_arena = NULL; + } +} + +void make_new_arena(void) +{ + freeze_global_arena(); + global_arena = object_arena_new(object_arena_default_size(), standard()); +} diff --git a/src/object.h b/src/object.h index a6deb16b..4b668a61 100644 --- a/src/object.h +++ b/src/object.h @@ -96,8 +96,9 @@ typedef uint64_t imask_t; #define I_PRIMARY ONE_HOT(59) enum { - OBJECT_TAG_TREE = 0, - OBJECT_TAG_TYPE = 1, + OBJECT_TAG_TREE = 0, + OBJECT_TAG_TYPE = 1, + OBJECT_TAG_VLOG = 2, OBJECT_TAG_COUNT }; @@ -176,7 +177,6 @@ typedef struct { object_copy_pred_t should_copy[OBJECT_TAG_COUNT]; object_copy_fn_t callback[OBJECT_TAG_COUNT]; void *context; - object_arena_t *arena; hash_t *copy_map; unsigned nroots; object_t *roots[0]; @@ -195,14 +195,17 @@ typedef struct { object_arena_t *arena; } object_rewrite_ctx_t; +typedef void (*object_visit_fn_t)(object_t *, void *); + typedef struct { - unsigned count; - tree_visit_fn_t preorder; - tree_visit_fn_t postorder; - void *context; - tree_kind_t kind; - unsigned generation; - bool deep; + unsigned count; + object_visit_fn_t preorder; + object_visit_fn_t postorder; + void *context; + int kind; + int tag; + unsigned generation; + bool deep; } object_visit_ctx_t; typedef int change_allowed_t[2]; @@ -265,4 +268,7 @@ void object_locus(object_t *object, ident_t *module, ptrdiff_t *offset); object_t *object_from_locus(ident_t module, ptrdiff_t offset, object_load_fn_t loader); +void make_new_arena(void); +void freeze_global_arena(void); + #endif // _OBJECT_H diff --git a/src/parse.c b/src/parse.c index c9c85175..700e8389 100644 --- a/src/parse.c +++ b/src/parse.c @@ -22,6 +22,7 @@ #include "hash.h" #include "lib.h" #include "names.h" +#include "object.h" #include "opt.h" #include "phase.h" #include "scan.h" diff --git a/src/prim.h b/src/prim.h index 47f564ba..05b57054 100644 --- a/src/prim.h +++ b/src/prim.h @@ -32,6 +32,7 @@ typedef struct _object_arena object_arena_t; typedef struct trie *ident_t; typedef struct _tree *tree_t; typedef struct _type *type_t; +typedef struct _vlog_node *vlog_node_t; typedef struct loc loc_t; typedef struct _fbuf fbuf_t; typedef struct _hash hash_t; diff --git a/src/tree.c b/src/tree.c index 2e11f595..6e5e70f5 100644 --- a/src/tree.c +++ b/src/tree.c @@ -434,8 +434,6 @@ object_class_t tree_object = { .gc_num_roots = 9 }; -object_arena_t *global_arena = NULL; - static void tree_assert_kind(tree_t t, const tree_kind_t *list, size_t len, const char *what) { @@ -477,7 +475,8 @@ static inline void tree_array_add(item_t *item, tree_t t) tree_t tree_new(tree_kind_t kind) { - return (tree_t)object_new(global_arena, &tree_object, kind); + object_t *o = object_new(NULL, &tree_object, kind); + return container_of(o, struct _tree, object); } const loc_t *tree_loc(tree_t t) @@ -1150,21 +1149,7 @@ void tree_set_file_mode(tree_t t, tree_t m) unsigned tree_visit(tree_t t, tree_visit_fn_t fn, void *context) { - assert(t != NULL); - - object_visit_ctx_t ctx = { - .count = 0, - .postorder = fn, - .preorder = NULL, - .context = context, - .kind = T_LAST_TREE_KIND, - .generation = object_next_generation(), - .deep = false, - }; - - object_visit(&(t->object), &ctx); - - return ctx.count; + return tree_visit_only(t, fn, context, T_LAST_TREE_KIND); } unsigned tree_visit_only(tree_t t, tree_visit_fn_t fn, @@ -1174,10 +1159,11 @@ unsigned tree_visit_only(tree_t t, tree_visit_fn_t fn, object_visit_ctx_t ctx = { .count = 0, - .postorder = fn, + .postorder = (object_visit_fn_t)fn, .preorder = NULL, .context = context, .kind = kind, + .tag = OBJECT_TAG_TREE, .generation = object_next_generation(), .deep = false }; @@ -1187,37 +1173,19 @@ unsigned tree_visit_only(tree_t t, tree_visit_fn_t fn, return ctx.count; } -void tree_write(tree_t t, fbuf_t *f, ident_wr_ctx_t ident_ctx, - loc_wr_ctx_t *loc_ctx) -{ - if (global_arena != NULL) { - object_arena_freeze(global_arena); - global_arena = NULL; - } - - object_write(&(t->object), f, ident_ctx, loc_ctx); -} - -tree_t tree_read(fbuf_t *f, tree_load_fn_t find_deps_fn, - ident_rd_ctx_t ident_ctx, loc_rd_ctx_t *loc_ctx) -{ - object_t *o = object_read(f, (object_load_fn_t)find_deps_fn, - ident_ctx, loc_ctx); - assert(o->tag == OBJECT_TAG_TREE); - return container_of(o, struct _tree, object); -} - tree_t tree_rewrite(tree_t t, tree_rewrite_pre_fn_t pre_fn, tree_rewrite_post_fn_t tree_post_fn, type_rewrite_post_fn_t type_post_fn, void *context) { - assert(global_arena != NULL); + object_arena_t *arena = object_arena(&(t->object)); + if (arena_frozen(arena)) + return t; object_rewrite_ctx_t ctx = { .generation = object_next_generation(), .context = context, - .arena = global_arena, + .arena = arena, }; ctx.pre_fn[OBJECT_TAG_TREE] = (object_rewrite_pre_fn_t)pre_fn; @@ -1242,7 +1210,6 @@ void tree_copy(tree_t *roots, unsigned nroots, ctx->generation = object_next_generation(); ctx->context = context; - ctx->arena = global_arena; ctx->nroots = nroots; for (unsigned i = 0; i < nroots; i++) @@ -1265,20 +1232,6 @@ const char *tree_kind_str(tree_kind_t t) return kind_text_map[t]; } -void freeze_global_arena(void) -{ - if (global_arena != NULL) { - object_arena_freeze(global_arena); - global_arena = NULL; - } -} - -void make_new_arena(void) -{ - freeze_global_arena(); - global_arena = object_arena_new(object_arena_default_size(), standard()); -} - object_arena_t *tree_arena(tree_t t) { return object_arena(&(t->object)); @@ -1336,6 +1289,9 @@ object_t *tree_to_object(tree_t t) tree_t tree_from_object(object_t *obj) { - assert(obj->tag == OBJECT_TAG_TREE); - return container_of(obj, struct _tree, object); + assert(obj != NULL); + if (obj->tag == OBJECT_TAG_TREE) + return container_of(obj, struct _tree, object); + else + return NULL; } diff --git a/src/tree.h b/src/tree.h index abd4da80..7db78b4e 100644 --- a/src/tree.h +++ b/src/tree.h @@ -32,7 +32,7 @@ typedef enum port_mode { PORT_LINKAGE } port_mode_t; -typedef enum class { +typedef enum { C_DEFAULT, C_SIGNAL, C_VARIABLE, @@ -368,9 +368,6 @@ tree_kind_t tree_kind(tree_t t); void tree_change_kind(tree_t t, tree_kind_t kind); const char *tree_kind_str(tree_kind_t t); -void make_new_arena(void); -void freeze_global_arena(void); - const loc_t *tree_loc(tree_t t); void tree_set_loc(tree_t t, const loc_t *loc); @@ -548,12 +545,6 @@ void tree_copy(tree_t *roots, unsigned nroots, void *context); typedef tree_t (*tree_load_fn_t)(ident_t); - -void tree_write(tree_t t, fbuf_t *f, ident_wr_ctx_t ident_ctx, - loc_wr_ctx_t *loc_ctx); -tree_t tree_read(fbuf_t *f, tree_load_fn_t find_deps_fn, - ident_rd_ctx_t ident_ctx, loc_rd_ctx_t *loc_ctx); - typedef void (*tree_deps_fn_t)(ident_t, void *); object_arena_t *tree_arena(tree_t t); diff --git a/src/type.c b/src/type.c index dc191889..1ecf6526 100644 --- a/src/type.c +++ b/src/type.c @@ -130,7 +130,8 @@ static inline void type_array_add(item_t *item, type_t t) type_t type_new(type_kind_t kind) { - return (type_t)object_new(global_arena, &type_object, kind); + object_t *o = object_new(NULL, &type_object, kind); + return container_of(o, struct _type, object); } type_kind_t type_kind(type_t t) diff --git a/src/util.h b/src/util.h index 91d882c6..1e87a71e 100644 --- a/src/util.h +++ b/src/util.h @@ -48,7 +48,7 @@ #define GCC_VERSION 0 #endif -#if GCC_VERSION > 40600 +#if GCC_VERSION > 40600 && !defined __cplusplus #define STATIC_ASSERT(x) _Static_assert((x), "Static assertion failed"); #else #define STATIC_ASSERT(x) diff --git a/src/vlog/Makemodule.am b/src/vlog/Makemodule.am new file mode 100644 index 00000000..e8a256fb --- /dev/null +++ b/src/vlog/Makemodule.am @@ -0,0 +1,5 @@ +lib_libnvc_a_SOURCES += \ + src/vlog/vlog-node.h \ + src/vlog/vlog-node.c \ + src/vlog/vlog-phase.h \ + src/vlog/vlog-dump.c diff --git a/src/vlog/vlog-dump.c b/src/vlog/vlog-dump.c new file mode 100644 index 00000000..89de7205 --- /dev/null +++ b/src/vlog/vlog-dump.c @@ -0,0 +1,258 @@ +// +// Copyright (C) 2022 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 "ident.h" +#include "vlog/vlog-node.h" +#include "vlog/vlog-phase.h" + +#include + +static void vlog_dump_tab(vlog_node_t v, int indent); + +static void tab(int indent) +{ + while (indent--) + fputc(' ', stdout); +} + +__attribute__((format(printf,1,2))) +static void syntax(const char *fmt, ...) +{ + LOCAL_TEXT_BUF tb = tb_new(); + bool highlighting = false; + static bool comment = false; + for (const char *p = fmt; *p != '\0'; p++) { + if (comment) { + if (*p == '\n') { + comment = false; + tb_printf(tb, "$$"); + } + if (*p != '~' && *p != '#') + tb_append(tb, *p); + if (p > fmt && *p == '/' && *(p - 1) == '*') { + tb_printf(tb, "$$"); + comment = false; + } + } + else if (*p == '#') { + tb_printf(tb, "$bold$$cyan$"); + highlighting = true; + } + else if (*p == '~') { + tb_printf(tb, "$yellow$"); + highlighting = true; + } + else if ((*p == '-' && *(p + 1) == '-') + || (*p == '/' && *(p + 1) == '*') + || (*p == '/' && *(p + 1) == '/')) { + tb_printf(tb, "$red$%c", *p); + comment = true; + } + else if (!isalnum((int)*p) && *p != '_' && *p != '%' && highlighting) { + tb_printf(tb, "$$%c", *p); + highlighting = false; + } + else + tb_append(tb, *p); + } + + if (highlighting || comment) + tb_printf(tb, "$$"); + + va_list ap; + va_start(ap, fmt); + color_vprintf(tb_get(tb), ap); + va_end(ap); +} + +static void vlog_dump_module(vlog_node_t v, int indent) +{ + syntax("#module %s", istr(vlog_ident(v))); + + const int nports = vlog_ports(v); + if (nports > 0) { + printf(" ("); + for (int i = 0; i < nports; i++) { + if (i > 0) printf(", "); + vlog_dump(vlog_port(v, i)); + } + printf(")"); + } + + printf(";\n"); + + const int ndecls = vlog_decls(v); + for (int i = 0; i < ndecls; i++) + vlog_dump_tab(vlog_decl(v, i), indent + 2); + + const int nstmts = vlog_stmts(v); + for (int i = 0; i < nstmts; i++) + vlog_dump_tab(vlog_stmt(v, i), indent + 2); + + syntax("#endmodule // %s\n\n", istr(vlog_ident(v))); +} + +static void vlog_dump_port_decl(vlog_node_t v, int indent) +{ + tab(indent); + + switch (vlog_subkind(v)) { + case V_PORT_INPUT: syntax("#input"); break; + case V_PORT_INOUT: syntax("#inout"); break; + case V_PORT_OUTPUT: syntax("#output"); break; + case V_PORT_OUTPUT_REG: syntax("#output #reg"); break; + } + + printf(" %s;\n", istr(vlog_ident(v))); +} + +static void vlog_dump_always(vlog_node_t v, int indent) +{ + tab(indent); + + syntax("#always "); + vlog_dump_tab(vlog_stmt(v, 0), indent); +} + +static void vlog_dump_initial(vlog_node_t v, int indent) +{ + tab(indent); + + syntax("#initial "); + vlog_dump_tab(vlog_stmt(v, 0), indent); +} + +static void vlog_dump_seq_block(vlog_node_t v, int indent) +{ + syntax("#begin\n"); + + const int nstmts = vlog_stmts(v); + for (int i = 0; i < nstmts; i++) + vlog_dump_tab(vlog_stmt(v, i), indent + 2); + + tab(indent); + syntax("#end\n"); +} + +static void vlog_dump_timing(vlog_node_t v, int indent) +{ + printf("@("); + vlog_dump(vlog_value(v)); + printf(")\n"); + + if (vlog_stmts(v) > 0) + vlog_dump_tab(vlog_stmt(v, 0), indent + 2); + else + printf(";\n"); +} + +static void vlog_dump_event(vlog_node_t v) +{ + switch (vlog_subkind(v)) { + case V_EVENT_POSEDGE: syntax("#posedge "); break; + case V_EVENT_NEGEDGE: syntax("#negedge "); break; + } + + vlog_dump(vlog_value(v)); +} + +static void vlog_dump_nbassign(vlog_node_t v, int indent) +{ + tab(indent); + vlog_dump(vlog_target(v)); + printf(" <= "); + vlog_dump(vlog_value(v)); + printf(";\n"); +} + +static void vlog_dump_systask_enable(vlog_node_t v, int indent) +{ + tab(indent); + printf("%s", istr(vlog_ident(v))); + + const int nparams = vlog_params(v); + if (nparams > 0) { + printf("("); + for (int i = 0; i < nparams; i++) { + if (i > 0) printf(", "); + vlog_dump(vlog_param(v, i)); + } + printf(")"); + } + + printf(";\n"); +} + +static void vlog_dump_string(vlog_node_t v) +{ + //printf("\"%s\"", vlog_text(v)); +} + +static void vlog_dump_number(vlog_node_t v) +{ + //printf("'b%s", vlog_text(v)); +} + +static void vlog_dump_tab(vlog_node_t v, int indent) +{ + switch (vlog_kind(v)) { + case V_MODULE: + vlog_dump_module(v, indent); + break; + case V_REF: + printf("%s", istr(vlog_ident(v))); + break; + case V_PORT_DECL: + vlog_dump_port_decl(v, indent); + break; + case V_ALWAYS: + vlog_dump_always(v, indent); + break; + case V_INITIAL: + vlog_dump_initial(v, indent); + break; + case V_TIMING: + vlog_dump_timing(v, indent); + break; + case V_EVENT: + vlog_dump_event(v); + break; + case V_NBASSIGN: + vlog_dump_nbassign(v, indent); + break; + case V_SEQ_BLOCK: + vlog_dump_seq_block(v, indent); + break; + case V_SYSTASK_ENABLE: + vlog_dump_systask_enable(v, indent); + break; + case V_STRING: + vlog_dump_string(v); + break; + case V_NUMBER: + vlog_dump_number(v); + break; + default: + fatal_trace("cannot dump %s", vlog_kind_str(vlog_kind(v))); + } +} + +void vlog_dump(vlog_node_t v) +{ + vlog_dump_tab(v, 0); +} diff --git a/src/vlog/vlog-node.c b/src/vlog/vlog-node.c new file mode 100644 index 00000000..d3cc72ae --- /dev/null +++ b/src/vlog/vlog-node.c @@ -0,0 +1,315 @@ +// +// Copyright (C) 2022 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 "vlog/vlog-node.h" +#include "common.h" +#include "object.h" + +#include +#include +#include + +static const imask_t has_map[V_LAST_NODE_KIND] = { + // V_MODULE + (I_IDENT | I_PORTS | I_STMTS | I_DECLS | I_IDENT2), + + // V_PORT_DECL + (I_IDENT | I_SUBKIND | I_IDENT2), + + // V_REF + (I_IDENT | I_REF), + + // V_ALWAYS + (I_STMTS), + + // V_TIMING + (I_VALUE | I_STMTS), + + // V_NBASSIGN + (I_TARGET | I_VALUE), + + // V_EVENT + (I_SUBKIND | I_VALUE), + + // V_INITIAL + (I_STMTS), + + // V_SEQ_BLOCK + (I_STMTS), + + // V_SYSTASK_ENABLE + (I_IDENT | I_SUBKIND | I_PARAMS), + + // V_STRING + (0), + + // V_NUMBER + (0), +}; + +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_ENABLE", + "V_STRING", "V_NUMBER" +}; + +static const change_allowed_t change_allowed[] = { + { -1, -1 } +}; + +object_class_t vlog_node_object = { + .name = "v-node", + .change_allowed = change_allowed, + .has_map = has_map, + .kind_text_map = kind_text_map, + .tag = OBJECT_TAG_VLOG, + .last_kind = V_LAST_NODE_KIND, + .gc_roots = { V_MODULE }, + .gc_num_roots = 1 +}; + +struct _vlog_node { + object_t object; +}; + +static inline vlog_node_t vlog_array_nth(item_t *item, unsigned n) +{ + object_t *o = obj_array_nth(item->obj_array, n); + return container_of(o, struct _vlog_node, object); +} + +static inline void vlog_array_add(item_t *item, vlog_node_t v) +{ + obj_array_add(&(item->obj_array), &(v->object)); +} + +vlog_node_t vlog_new(vlog_kind_t kind) +{ + object_t *o = object_new(NULL, &vlog_node_object, kind); + return container_of(o, struct _vlog_node, object); +} + +vlog_kind_t vlog_kind(vlog_node_t v) +{ + return v->object.kind; +} + +const char *vlog_kind_str(vlog_kind_t kind) +{ + return kind_text_map[kind]; +} + +ident_t vlog_ident(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_IDENT); + assert(item->ident != NULL); + return item->ident; +} + +void vlog_set_ident(vlog_node_t v, ident_t i) +{ + lookup_item(&vlog_node_object, v, I_IDENT)->ident = i; +} + +ident_t vlog_ident2(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_IDENT2); + assert(item->ident != NULL); + return item->ident; +} + +void vlog_set_ident2(vlog_node_t v, ident_t i) +{ + lookup_item(&vlog_node_object, v, I_IDENT2)->ident = i; +} + +const loc_t *vlog_loc(vlog_node_t v) +{ + assert(v != NULL); + return &(v->object.loc); +} + +void vlog_set_loc(vlog_node_t v, const loc_t *loc) +{ + assert(v != NULL); + assert(loc != NULL); + v->object.loc = *loc; +} + +vlog_node_t vlog_ref(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_REF); + assert(item->object != NULL); + return container_of(item->object, struct _vlog_node, object); +} + +void vlog_set_ref(vlog_node_t v, vlog_node_t d) +{ + lookup_item(&vlog_node_object, v, I_REF)->object = &(d->object); + object_write_barrier(&(v->object), &(d->object)); +} + +unsigned vlog_stmts(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_STMTS); + return obj_array_count(item->obj_array); +} + +vlog_node_t vlog_stmt(vlog_node_t v, unsigned n) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_STMTS); + return vlog_array_nth(item, n); +} + +void vlog_add_stmt(vlog_node_t v, vlog_node_t s) +{ + assert(s != NULL); + vlog_array_add(lookup_item(&vlog_node_object, v, I_STMTS), s); + object_write_barrier(&(v->object), &(s->object)); +} + +unsigned vlog_ports(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_PORTS); + return obj_array_count(item->obj_array); +} + +vlog_node_t vlog_port(vlog_node_t v, unsigned n) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_PORTS); + return vlog_array_nth(item, n); +} + +void vlog_add_port(vlog_node_t v, vlog_node_t p) +{ + assert(p != NULL); + assert(p->object.kind == V_REF); + vlog_array_add(lookup_item(&vlog_node_object, v, I_PORTS), p); + object_write_barrier(&(v->object), &(p->object)); +} + +unsigned vlog_params(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_PARAMS); + return obj_array_count(item->obj_array); +} + +vlog_node_t vlog_param(vlog_node_t v, unsigned n) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_PARAMS); + return vlog_array_nth(item, n); +} + +void vlog_add_param(vlog_node_t v, vlog_node_t p) +{ + assert(p != NULL); + vlog_array_add(lookup_item(&vlog_node_object, v, I_PARAMS), p); + object_write_barrier(&(v->object), &(p->object)); +} + +unsigned vlog_decls(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_DECLS); + return obj_array_count(item->obj_array); +} + +vlog_node_t vlog_decl(vlog_node_t v, unsigned n) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_DECLS); + return vlog_array_nth(item, n); +} + +void vlog_add_decl(vlog_node_t v, vlog_node_t d) +{ + assert(d != NULL); + vlog_array_add(lookup_item(&vlog_node_object, v, I_DECLS), d); + object_write_barrier(&(v->object), &(d->object)); +} + +unsigned vlog_subkind(vlog_node_t v) +{ + return lookup_item(&vlog_node_object, v, I_SUBKIND)->ival; +} + +void vlog_set_subkind(vlog_node_t v, unsigned sub) +{ + lookup_item(&vlog_node_object, v, I_SUBKIND)->ival = sub; +} + +vlog_node_t vlog_value(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_VALUE); + assert(item->object != NULL); + return container_of(item->object, struct _vlog_node, object); +} + +void vlog_set_value(vlog_node_t v, vlog_node_t e) +{ + lookup_item(&vlog_node_object, v, I_VALUE)->object = &(e->object); + object_write_barrier(&(v->object), &(e->object)); +} + +vlog_node_t vlog_target(vlog_node_t v) +{ + item_t *item = lookup_item(&vlog_node_object, v, I_TARGET); + assert(item->object != NULL); + return container_of(item->object, struct _vlog_node, object); +} + +void vlog_set_target(vlog_node_t v, vlog_node_t e) +{ + lookup_item(&vlog_node_object, v, I_TARGET)->object = &(e->object); + object_write_barrier(&(v->object), &(e->object)); +} + +void vlog_visit(vlog_node_t v, vlog_visit_fn_t fn, void *context) +{ + vlog_visit_only(v, fn, context, V_LAST_NODE_KIND); +} + +void vlog_visit_only(vlog_node_t v, vlog_visit_fn_t fn, void *context, + vlog_kind_t kind) +{ + assert(v != NULL); + + object_visit_ctx_t ctx = { + .count = 0, + .postorder = (object_visit_fn_t)fn, + .preorder = NULL, + .context = context, + .kind = kind, + .tag = OBJECT_TAG_VLOG, + .generation = object_next_generation(), + .deep = false + }; + + object_visit(&(v->object), &ctx); +} + +object_t *vlog_to_object(vlog_node_t v) +{ + return &(v->object); +} + +vlog_node_t vlog_from_object(object_t *obj) +{ + assert(obj != NULL); + if (obj->tag == OBJECT_TAG_VLOG) + return container_of(obj, struct _vlog_node, object); + else + return NULL; +} diff --git a/src/vlog/vlog-node.h b/src/vlog/vlog-node.h new file mode 100644 index 00000000..e1ec2a79 --- /dev/null +++ b/src/vlog/vlog-node.h @@ -0,0 +1,111 @@ +// +// Copyright (C) 2022 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_NODE_H +#define _VLOG_NODE_H + +#include "prim.h" + +typedef enum { + V_EVENT_LEVEL, + V_EVENT_POSEDGE, + V_EVENT_NEGEDGE, +} v_event_kind_t; + +typedef enum { + V_PORT_INPUT, + V_PORT_OUTPUT, + V_PORT_OUTPUT_REG, + V_PORT_INOUT, +} v_port_kind_t; + +typedef enum { + V_SYS_DISPLAY, + V_SYS_WRITE, + V_SYS_FINISH, +} v_systask_kind_t; + +typedef enum { + V_MODULE, + V_PORT_DECL, + V_REF, + V_ALWAYS, + V_TIMING, + V_NBASSIGN, + V_EVENT, + V_INITIAL, + V_SEQ_BLOCK, + V_SYSTASK_ENABLE, + V_STRING, + V_NUMBER, + + V_LAST_NODE_KIND +} vlog_kind_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); + +void make_new_vlog_arena(void); + +const loc_t *vlog_loc(vlog_node_t v); +void vlog_set_loc(vlog_node_t v, const loc_t *loc); + +ident_t vlog_ident(vlog_node_t v); +void vlog_set_ident(vlog_node_t v, ident_t i); + +ident_t vlog_ident2(vlog_node_t v); +void vlog_set_ident2(vlog_node_t v, ident_t i); + +vlog_node_t vlog_ref(vlog_node_t v); +void vlog_set_ref(vlog_node_t v, vlog_node_t d); + +unsigned vlog_stmts(vlog_node_t v); +vlog_node_t vlog_stmt(vlog_node_t v, unsigned n); +void vlog_add_stmt(vlog_node_t v, vlog_node_t s); + +unsigned vlog_ports(vlog_node_t v); +vlog_node_t vlog_port(vlog_node_t v, unsigned n); +void vlog_add_port(vlog_node_t v, vlog_node_t p); + +unsigned vlog_params(vlog_node_t v); +vlog_node_t vlog_param(vlog_node_t v, unsigned n); +void vlog_add_param(vlog_node_t v, vlog_node_t p); + +unsigned vlog_decls(vlog_node_t v); +vlog_node_t vlog_decl(vlog_node_t v, unsigned n); +void vlog_add_decl(vlog_node_t v, vlog_node_t d); + +unsigned vlog_subkind(vlog_node_t v); +void vlog_set_subkind(vlog_node_t v, unsigned sub); + +vlog_node_t vlog_value(vlog_node_t v); +void vlog_set_value(vlog_node_t v, vlog_node_t e); + +vlog_node_t vlog_target(vlog_node_t v); +void vlog_set_target(vlog_node_t v, vlog_node_t e); + +typedef void (*vlog_visit_fn_t)(vlog_node_t v, void *context); + +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); + +object_t *vlog_to_object(vlog_node_t v); +vlog_node_t vlog_from_object(object_t *obj); + +#endif // _VLOG_NODE_H diff --git a/src/vlog/vlog-phase.h b/src/vlog/vlog-phase.h new file mode 100644 index 00000000..5408ef9b --- /dev/null +++ b/src/vlog/vlog-phase.h @@ -0,0 +1,26 @@ +// +// Copyright (C) 2022 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_PHASE_H +#define _VLOG_PHASE_H + +#include "prim.h" + +vlog_node_t vlog_parse(void); +void vlog_dump(vlog_node_t v); + +#endif // _VLOG_PHASE_H diff --git a/test/run_regr.c b/test/run_regr.c index 267dacf0..03529c79 100644 --- a/test/run_regr.c +++ b/test/run_regr.c @@ -67,6 +67,8 @@ #define F_SHELL (1 << 12) #define F_2002 (1 << 13) #define F_SLOW (1 << 14) +#define F_VERILOG (1 << 15) +#define F_MIXED (1 << 16) typedef struct test test_t; typedef struct param param_t; @@ -335,6 +337,10 @@ static bool parse_test_list(int argc, char **argv) test->flags |= F_SLOW; else if (strcmp(opt, "!windows") == 0) test->flags |= F_NOTWIN; + else if (strcmp(opt, "mixed") == 0) + test->flags |= F_MIXED; + else if (strcmp(opt, "verilog") == 0) + test->flags |= F_VERILOG; else if (strncmp(opt, "O", 1) == 0) { if (sscanf(opt + 1, "%u", &(test->olevel)) != 1) { fprintf(stderr, "Error on testlist line %d: invalid " @@ -668,8 +674,14 @@ static bool run_test(test_t *test) push_arg(&args, "-H%s", test->heapsz); push_arg(&args, "-a"); - push_arg(&args, "%s" DIR_SEP "regress" DIR_SEP "%s.vhd", - test_dir, test->name); + + if (!(test->flags & F_VERILOG)) + push_arg(&args, "%s" DIR_SEP "regress" DIR_SEP "%s.vhd", + test_dir, test->name); + + if (test->flags & (F_MIXED | F_VERILOG)) + push_arg(&args, "%s" DIR_SEP "regress" DIR_SEP "%s.v", + test_dir, test->name); if (test->flags & F_RELAX) push_arg(&args, "--relax=%s", test->relax); diff --git a/test/test_jit.c b/test/test_jit.c index 4e664e47..502e6abc 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -23,6 +23,7 @@ #include "jit/jit-priv.h" #include "jit/jit.h" #include "mask.h" +#include "object.h" #include "opt.h" #include "phase.h" #include "scan.h" diff --git a/test/test_lib.c b/test/test_lib.c index da5825a8..8b26c81e 100644 --- a/test/test_lib.c +++ b/test/test_lib.c @@ -18,6 +18,7 @@ #include "test_util.h" #include "common.h" #include "lib.h" +#include "object.h" #include "tree.h" #include "type.h" #include "util.h" diff --git a/test/test_value.c b/test/test_value.c index c95b1204..2fd0c912 100644 --- a/test/test_value.c +++ b/test/test_value.c @@ -16,9 +16,10 @@ // #include "test_util.h" -#include "type.h" #include "common.h" +#include "object.h" #include "tree.h" +#include "type.h" #include #include diff --git a/tools/run.sh b/tools/run.sh index efb44d5a..880ff7d5 100755 --- a/tools/run.sh +++ b/tools/run.sh @@ -6,5 +6,12 @@ if [ -e lib/$1.so ]; then vhpi="--load lib/$1.so --vhpi-trace" fi root=$(git rev-parse --show-toplevel) +regress=$root/test/regress +if [ -f $regress/$1.v ]; then + vlog=$regress/$1.v +fi +if [ -z "$vlog" ] || [ -f $regress/$1.vhd ]; then + vhd=$regress/$1.vhd +fi PATH="./bin:../bin:$PATH" -nvc --std=$std -a $root/test/regress/$1.vhd -e $* -r --trace --stats $vhpi +nvc --std=$std -a $vhd $vlog -e $* -r --trace --stats $vhpi -- 2.39.2