From f760fa8fab7298c1901a79e2b864f8bf07ec3bc3 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 25 Mar 2024 20:04:49 +0000 Subject: [PATCH] Fix crashes with vhpiDepositPropagate --- src/rt/model.c | 14 ++++++++++--- src/rt/rt.h | 1 + src/vhpi/vhpi-model.c | 2 ++ src/vhpi/vhpi-util.c | 3 +++ src/vhpi/vhpi_user.h | 2 +- test/regress/vhpi12.vhd | 4 ++-- test/vhpi/vhpi12.c | 46 ++++++++++++++++++++++++++++++++++++++++- 7 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/rt/model.c b/src/rt/model.c index 6edd43ec..cf6058c8 100644 --- a/src/rt/model.c +++ b/src/rt/model.c @@ -1249,8 +1249,10 @@ static inline bool cmp_values(rt_nexus_t *n, rt_value_t a, rt_value_t b) static void check_multiple_sources(rt_nexus_t *n, source_kind_t kind) { - if (n->signal->resolution != NULL || kind == SOURCE_FORCING) + if (n->signal->resolution != NULL) return; + else if (kind == SOURCE_FORCING || kind == SOURCE_DEPOSIT) + return; // Pseudo-source diag_t *d; if (n->signal->parent->kind == SCOPE_SIGNAL) { @@ -2007,6 +2009,7 @@ static void *calculate_driving_value(rt_model_t *m, rt_nexus_t *n) if (unlikely(n->flags & NET_F_DEPOSIT)) { rt_source_t *src = get_pseudo_source(m, n, SOURCE_DEPOSIT); n->flags &= ~NET_F_DEPOSIT; + src->disconnected = 1; return value_ptr(n, &(src->u.deposit.value)); } @@ -3216,6 +3219,8 @@ static void model_cycle(rt_model_t *m) } } + global_event(m, RT_NEXT_CYCLE); + deferq_run(m, &m->driverq); while (heap_size(m->driving_heap) > 0) { @@ -3395,11 +3400,14 @@ void deposit_signal(rt_model_t *m, rt_signal_t *s, const void *values, count -= n->width; assert(count >= 0); - n->flags |= NET_F_DEPOSIT; - rt_source_t *src = get_pseudo_source(m, n, SOURCE_DEPOSIT); copy_value_ptr(n, &(src->u.deposit.value), vptr); + if (n->flags & NET_F_DEPOSIT) + continue; // Deposit already scheduled + + n->flags |= NET_F_DEPOSIT; + deltaq_insert_deposit(m, &(src->u.deposit)); vptr += n->width * n->size; } diff --git a/src/rt/rt.h b/src/rt/rt.h index c0b1e353..053601ae 100644 --- a/src/rt/rt.h +++ b/src/rt/rt.h @@ -84,6 +84,7 @@ typedef enum { RT_LAST_KNOWN_DELTA_CYCLE, RT_NEXT_TIME_STEP, RT_END_TIME_STEP, + RT_NEXT_CYCLE, RT_LAST_EVENT } rt_event_t; diff --git a/src/vhpi/vhpi-model.c b/src/vhpi/vhpi-model.c index 35f36fef..2b974e56 100644 --- a/src/vhpi/vhpi-model.c +++ b/src/vhpi/vhpi-model.c @@ -1566,6 +1566,8 @@ static int enable_cb(c_callback *cb) case vhpiCbEndOfTimeStep: case vhpiCbRepEndOfTimeStep: case vhpiCbEndOfInitialization: + case vhpiCbStartOfNextCycle: + case vhpiCbRepStartOfNextCycle: model_set_global_cb(vhpi_context()->model, vhpi_get_rt_event(cb->Reason), vhpi_global_cb, cb); return 0; diff --git a/src/vhpi/vhpi-util.c b/src/vhpi/vhpi-util.c index 3df9d3ba..f2dbf684 100644 --- a/src/vhpi/vhpi-util.c +++ b/src/vhpi/vhpi-util.c @@ -230,6 +230,9 @@ rt_event_t vhpi_get_rt_event(int reason) case vhpiCbNextTimeStep: case vhpiCbRepNextTimeStep: return RT_NEXT_TIME_STEP; + case vhpiCbStartOfNextCycle: + case vhpiCbRepStartOfNextCycle: + return RT_NEXT_CYCLE; case vhpiCbEndOfTimeStep: case vhpiCbRepEndOfTimeStep: return RT_END_TIME_STEP; diff --git a/src/vhpi/vhpi_user.h b/src/vhpi/vhpi_user.h index de4560f7..c03b5fd5 100644 --- a/src/vhpi/vhpi_user.h +++ b/src/vhpi/vhpi_user.h @@ -112,7 +112,7 @@ extern "C" { /* basic typedefs */ #ifndef VHPI_TYPES #define VHPI_TYPES -typedef struct vhpi_obj *vhpiHandleT; +typedef uint32_t *vhpiHandleT; typedef uint32_t vhpiEnumT; typedef uint8_t vhpiSmallEnumT; typedef int32_t vhpiIntT; diff --git a/test/regress/vhpi12.vhd b/test/regress/vhpi12.vhd index 0bef1ef3..437d8483 100644 --- a/test/regress/vhpi12.vhd +++ b/test/regress/vhpi12.vhd @@ -2,8 +2,8 @@ library ieee; use ieee.std_logic_1164.all; entity vhpi12 is - port ( d, clk : in std_logic; - q : out std_logic ); + port ( d, clk : in std_ulogic; + q : out std_ulogic ); end entity; architecture test of vhpi12 is diff --git a/test/vhpi/vhpi12.c b/test/vhpi/vhpi12.c index 2a7af610..407a99ba 100644 --- a/test/vhpi/vhpi12.c +++ b/test/vhpi/vhpi12.c @@ -71,6 +71,33 @@ static vhpiSmallEnumT get_q(void) return val.value.enumv; } +static void check_q_2(const vhpiCbDataT *cb_data) +{ + vhpi_printf("check q 2"); + + vhpiSmallEnumT q = get_q(); + vhpi_printf("q value %x", q); + fail_unless(q == vhpiH); // XXX: vhpi1 +} + +static void check_q_1(const vhpiCbDataT *cb_data) +{ + vhpi_printf("check q 1"); + + vhpiSmallEnumT q = get_q(); + vhpi_printf("q value %x", q); + fail_unless(q == vhpi1); // XXX: vhpiH + + set_clk(vhpi1); + + vhpiCbDataT next_cb = { + .reason = vhpiCbStartOfNextCycle, + .cb_rtn = check_q_2, + }; + vhpi_register_cb(&next_cb, 0); + check_error(); +} + static void toggle_clock(const vhpiCbDataT *cb_data) { vhpi_printf("toggle clock"); @@ -87,9 +114,24 @@ static void toggle_clock(const vhpiCbDataT *cb_data) vhpi_release_handle(h_timeout); - static int rep = 10; + static int rep = 11; if (rep-- > 0) register_timeout(); + else { + vhpiValueT val = { + .format = vhpiLogicVal, + .value = { .enumv = vhpiH }, + }; + + vhpi_put_value(h_q, &val, vhpiDepositPropagate); + + vhpiCbDataT next_cb = { + .reason = vhpiCbStartOfNextCycle, + .cb_rtn = check_q_1, + }; + vhpi_register_cb(&next_cb, 0); + check_error(); + } } static void register_timeout(void) @@ -132,6 +174,8 @@ static void start_of_sim(const vhpiCbDataT *cb_data) set_clk(vhpi0); set_d(vhpi1); + set_d(vhpi1); // Should not crash if called twice + register_timeout(); vhpi_release_handle(h_sos); -- 2.39.2