From 7b11d3e1bd6a64a05251c900d7d8f78d5b54c3b9 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Thu, 12 Oct 2023 20:26:12 +0100 Subject: [PATCH] Add layout_of variant for signal types --- src/jit/jit-layout.c | 90 +++++++++++++++++++++++++++++++++++++++++- src/jit/jit-layout.h | 1 + src/vhpi/vhpi-model.c | 12 +++++- test/regress/vhpi9.vhd | 1 + test/test_jit.c | 25 ++++++++++++ test/vhpi/vhpi9.c | 30 ++++++++++++++ 6 files changed, 156 insertions(+), 3 deletions(-) diff --git a/src/jit/jit-layout.c b/src/jit/jit-layout.c index a7503eaa..2d94ae04 100644 --- a/src/jit/jit-layout.c +++ b/src/jit/jit-layout.c @@ -19,6 +19,7 @@ #include "common.h" #include "hash.h" #include "jit/jit-layout.h" +#include "thread.h" #include "type.h" #include @@ -54,8 +55,7 @@ const jit_layout_t *layout_of(type_t type) assert(type_frozen(type)); // Not safe to cache otherwise static hash_t *cache = NULL; - if (cache == NULL) - cache = hash_new(256); + INIT_ONCE(cache = hash_new(256)); jit_layout_t *l = hash_get(cache, type); if (l != NULL) @@ -155,3 +155,89 @@ const jit_layout_t *layout_of(type_t type) hash_put(cache, type, l); return l; } + +const jit_layout_t *signal_layout_of(type_t type) + { + assert(type_frozen(type)); // Not safe to cache otherwise + static hash_t *cache = NULL; + + INIT_ONCE(cache = hash_new(256)); + + jit_layout_t *l = hash_get(cache, type); + if (l != NULL) + return l; + + if (type_is_scalar(type) || type_const_bounds(type)) { + l = xcalloc_flex(sizeof(jit_layout_t), 2, sizeof(layout_part_t)); + l->nparts = 2; + l->size = 16; + l->align = 8; + + // Shared signal data pointer + l->parts[0].offset = 0; + l->parts[0].size = sizeof(void *); + l->parts[0].repeat = 1; + l->parts[0].align = sizeof(void *); + + // Offset + l->parts[1].offset = 8; + l->parts[1].size = 8; + l->parts[1].repeat = 1; + l->parts[1].align = 8; + } + else if (type_is_array(type)) { + const int ndims = dimension_of(type); + + l = xcalloc_flex(sizeof(jit_layout_t), 3, sizeof(layout_part_t)); + l->nparts = 3; + l->size = 16 + ndims * 2 * sizeof(int64_t); + l->align = 8; + + // Shared signal data pointer + l->parts[0].offset = 0; + l->parts[0].size = sizeof(void *); + l->parts[0].repeat = 1; + l->parts[0].align = sizeof(void *); + + // Offset + l->parts[1].offset = 8; + l->parts[1].size = 8; + l->parts[1].repeat = 1; + l->parts[1].align = 8; + + // Array bounds + l->parts[2].offset = 16; + l->parts[2].size = 8; + l->parts[2].repeat = ndims * 2; + l->parts[2].align = 8; + } + else if (type_is_record(type)) { + const int nfields = type_fields(type); + + l = xcalloc_flex(sizeof(jit_layout_t), nfields, sizeof(layout_part_t)); + l->nparts = nfields; + + int offset = 0; + for (int i = 0; i < nfields; i++) { + type_t ftype = tree_type(type_field(type, i)); + const jit_layout_t *fl = signal_layout_of(ftype); + + offset = ALIGN_UP(offset, fl->align); + + l->parts[i].offset = offset; + l->parts[i].size = fl->size; + l->parts[i].repeat = 1; + l->parts[i].align = fl->align; + + offset += fl->size; + } + + l->size = offset; + l->align = sizeof(void *); // Matches irgen_align_of + } + else + fatal_trace("cannot get layout for %s", type_pp(type)); + + hash_put(cache, type, l); + return l; +} diff --git a/src/jit/jit-layout.h b/src/jit/jit-layout.h index d7c259e3..edee65ac 100644 --- a/src/jit/jit-layout.h +++ b/src/jit/jit-layout.h @@ -35,5 +35,6 @@ typedef struct { } jit_layout_t; const jit_layout_t *layout_of(type_t type); +const jit_layout_t *signal_layout_of(type_t type); #endif // _JIT_LAYOUT_H diff --git a/src/vhpi/vhpi-model.c b/src/vhpi/vhpi-model.c index 4d3763d9..d3bf0d60 100644 --- a/src/vhpi/vhpi-model.c +++ b/src/vhpi/vhpi-model.c @@ -1450,7 +1450,17 @@ static void *vhpi_get_value_ptr(c_vhpiObject *obj) if (td == NULL) return NULL; - const jit_layout_t *l = layout_of(td->type); + const jit_layout_t *l; + switch (vhpi_get_prefix_kind(obj)) { + case vhpiPortDeclK: + case vhpiSigDeclK: + l = signal_layout_of(td->type); + break; + default: + l = layout_of(td->type); + break; + } + c_selectedName *sn = is_selectedName(obj); if (sn != NULL) { diff --git a/test/regress/vhpi9.vhd b/test/regress/vhpi9.vhd index 2d4a2439..60ef0a6d 100644 --- a/test/regress/vhpi9.vhd +++ b/test/regress/vhpi9.vhd @@ -15,6 +15,7 @@ package pack2 is type r is record f : bit_vector(1 to k); + g : bit_vector(k downto 1); end record; end package; diff --git a/test/test_jit.c b/test/test_jit.c index 3e8d019b..ecfe240b 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -836,6 +836,17 @@ START_TEST(test_layout) ck_assert_int_eq(l->parts[0].repeat, 1); ck_assert_int_eq(l->parts[0].align, 4); + l = signal_layout_of(std_type(NULL, STD_INTEGER)); + ck_assert_int_eq(l->nparts, 2); + ck_assert_int_eq(l->parts[0].offset, 0); + ck_assert_int_eq(l->parts[0].size, sizeof(void *)); + ck_assert_int_eq(l->parts[0].repeat, 1); + ck_assert_int_eq(l->parts[0].align, 8); + ck_assert_int_eq(l->parts[1].offset, 8); + ck_assert_int_eq(l->parts[1].size, 8); + ck_assert_int_eq(l->parts[1].repeat, 1); + ck_assert_int_eq(l->parts[1].align, 8); + l = layout_of(std_type(NULL, STD_REAL)); ck_assert_int_eq(l->nparts, 1); ck_assert_int_eq(l->parts[0].offset, 0); @@ -867,6 +878,20 @@ START_TEST(test_layout) ck_assert_int_eq(l->parts[1].size, sizeof(int64_t)); ck_assert_int_eq(l->parts[1].repeat, 2); + l = signal_layout_of(std_type(NULL, STD_STRING)); + ck_assert_int_eq(l->nparts, 3); + ck_assert_int_eq(l->parts[0].offset, 0); + ck_assert_int_eq(l->parts[0].size, sizeof(void *)); + ck_assert_int_eq(l->parts[0].repeat, 1); + ck_assert_int_eq(l->parts[0].align, 8); + ck_assert_int_eq(l->parts[1].offset, 8); + ck_assert_int_eq(l->parts[1].size, 8); + ck_assert_int_eq(l->parts[1].repeat, 1); + ck_assert_int_eq(l->parts[1].align, 8); + ck_assert_int_eq(l->parts[2].offset, 16); + ck_assert_int_eq(l->parts[2].size, sizeof(int64_t)); + ck_assert_int_eq(l->parts[2].repeat, 2); + input_from_file(TESTDIR "/jit/layout.vhd"); tree_t p = parse(); diff --git a/test/vhpi/vhpi9.c b/test/vhpi/vhpi9.c index dae2a763..ddf3ffca 100644 --- a/test/vhpi/vhpi9.c +++ b/test/vhpi/vhpi9.c @@ -95,6 +95,36 @@ static void end_of_init(const vhpiCbDataT *cb_data) vhpi_printf("s3.f right bound %d", vhpi_get(vhpiRightBoundP, s3f_range)); fail_unless(vhpi_get(vhpiLeftBoundP, s3f_range) == 1); fail_unless(vhpi_get(vhpiRightBoundP, s3f_range) == 4); + fail_unless(vhpi_get(vhpiIsUpP, s3f_range)); + + vhpiHandleT s3g = vhpi_handle_by_name("s3.g", root); + check_error(); + fail_if(s3g == NULL); + fail_unless(vhpi_get(vhpiKindP, s3g) == vhpiSelectedNameK); + + vhpi_printf("s3.g size %d", vhpi_get(vhpiSizeP, s3g)); + fail_unless(vhpi_get(vhpiSizeP, s3g) == 4); + + vhpiHandleT s3g_type = vhpi_handle(vhpiBaseType, s3g); + check_error(); + fail_if(s3g_type == NULL); + vhpi_printf("s3.g type handle %p", s3g_type); + vhpi_printf("s3.g type name is %s", vhpi_get_str(vhpiNameP, s3g_type)); + + vhpiHandleT s3g_constrs = vhpi_iterator(vhpiConstraints, s3g_type); + check_error(); + fail_if(s3g_constrs == NULL); + + vhpiHandleT s3g_range = vhpi_scan(s3g_constrs); + check_error(); + fail_if(s3g_range == NULL); + fail_unless(vhpi_scan(s_constrs) == NULL); + vhpi_printf("s3.g type range handle %p", s3g_range); + vhpi_printf("s3.g left bound %d", vhpi_get(vhpiLeftBoundP, s3g_range)); + vhpi_printf("s3.g right bound %d", vhpi_get(vhpiRightBoundP, s3g_range)); + fail_unless(vhpi_get(vhpiLeftBoundP, s3g_range) == 4); + fail_unless(vhpi_get(vhpiRightBoundP, s3g_range) == 1); + fail_if(vhpi_get(vhpiIsUpP, s3g_range)); } void vhpi9_startup(void) -- 2.39.2