Skip to content

Commit

Permalink
Add runtime checks for negative delays. Issue #633
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Feb 25, 2023
1 parent f62347a commit d079ff5
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 13 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
- The experimental `--jit` elaboration option defers native code
generation until run time. This can dramatically reduce total test
time for short-running simulations.
- Statements like `wait for X` where `X` is negative but not a constant
now produce an error at run time (#633).

## Version 1.8.2 - 2023-02-14
- Fixed "failed to suspend thread" crash on macOS.
Expand Down
39 changes: 26 additions & 13 deletions src/rt/model.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,26 +148,26 @@ static void async_fast_driver(void *context, void *arg);
static void async_update_driving(void *context, void *arg);
static void async_disconnect(void *context, void *arg);

static int fmt_time_r(char *buf, size_t len, uint64_t t)
static int fmt_time_r(char *buf, size_t len, int64_t t, const char *sep)
{
static const struct {
uint64_t time;
int64_t time;
const char *unit;
} units[] = {
{ UINT64_C(1), "fs" },
{ UINT64_C(1000), "ps" },
{ UINT64_C(1000000), "ns" },
{ UINT64_C(1000000000), "us" },
{ UINT64_C(1000000000000), "ms" },
{ INT64_C(1), "fs" },
{ INT64_C(1000), "ps" },
{ INT64_C(1000000), "ns" },
{ INT64_C(1000000000), "us" },
{ INT64_C(1000000000000), "ms" },
{ 0, NULL }
};

int u = 0;
while (units[u + 1].unit && (t % units[u + 1].time == 0))
++u;

return checked_sprintf(buf, len, "%"PRIu64"%s",
t / units[u].time, units[u].unit);
return checked_sprintf(buf, len, "%"PRIi64"%s%s",
t / units[u].time, sep, units[u].unit);
}

__attribute__((format(printf, 2, 3)))
Expand All @@ -184,7 +184,7 @@ static void __model_trace(rt_model_t *m, const char *fmt, ...)
fprintf(stderr, "TRACE (init): ");
else {
char buf[64];
fmt_time_r(buf, sizeof(buf), m->now);
fmt_time_r(buf, sizeof(buf), m->now, "");
fprintf(stderr, "TRACE %s+%d: ", buf, m->iteration);
}
vfprintf(stderr, fmt, ap);
Expand All @@ -201,7 +201,7 @@ static const char *trace_time(uint64_t value)
static __thread int which = 0;

which ^= 1;
fmt_time_r(buf[which], 32, value);
fmt_time_r(buf[which], 32, value, "");
return buf[which];
}

Expand All @@ -213,7 +213,7 @@ static void model_diag_cb(diag_t *d, void *arg)
diag_printf(d, "(init): ");
else {
char tmbuf[64];
fmt_time_r(tmbuf, sizeof(tmbuf), m->now);
fmt_time_r(tmbuf, sizeof(tmbuf), m->now, "");

diag_printf(d, "%s+%d: ", tmbuf, m->iteration);
}
Expand Down Expand Up @@ -2765,6 +2765,15 @@ static inline void check_reject_limit(rt_signal_t *s, uint64_t after,
trace_time(reject), trace_time(after));
}

static inline void check_delay(int64_t delay)
{
if (unlikely(delay < 0)) {
char buf[32];
fmt_time_r(buf, sizeof(buf), delay, " ");
jit_msg(NULL, DIAG_FATAL, "illegal negative delay %s", buf);
}
}

bool force_signal(rt_signal_t *s, const uint64_t *buf, size_t count)
{
RT_LOCK(s->lock);
Expand Down Expand Up @@ -2885,7 +2894,7 @@ void model_interrupt(rt_model_t *m)
model_stop(m);

char tmbuf[32];
fmt_time_r(tmbuf, sizeof(tmbuf), m->now);
fmt_time_r(tmbuf, sizeof(tmbuf), m->now, "");

if (active_proc != NULL)
jit_msg(NULL, DIAG_FATAL,
Expand Down Expand Up @@ -3039,6 +3048,8 @@ void x_sched_process(int64_t delay)
{
TRACE("schedule process %s delay=%s", istr(active_proc->name),
trace_time(delay));

check_delay(delay);
deltaq_insert_proc(get_model(), delay, active_proc);
}

Expand All @@ -3052,6 +3063,7 @@ void x_sched_waveform_s(sig_shared_t *ss, uint32_t offset, uint64_t scalar,
istr(tree_ident(s->where)), offset, scalar, trace_time(after),
trace_time(reject));

check_delay(after);
check_postponed(after);
check_reject_limit(s, after, reject);

Expand All @@ -3072,6 +3084,7 @@ void x_sched_waveform(sig_shared_t *ss, uint32_t offset, void *values,
istr(tree_ident(s->where)), offset, fmt_values(values, count),
count, trace_time(after), trace_time(reject));

check_delay(after);
check_postponed(after);
check_reject_limit(s, after, reject);

Expand Down
1 change: 1 addition & 0 deletions test/regress/gold/signal29.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1ns+0: illegal negative delay -10 ps
2 changes: 2 additions & 0 deletions test/regress/gold/wait26.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
6ns+0: illegal negative delay -3600000 ms

17 changes: 17 additions & 0 deletions test/regress/signal29.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
entity signal29 is
end entity;

architecture test of signal29 is
signal x : integer;
begin

p1: process is
variable delay : time;
begin
delay := -10 ps;
wait for 1 ns;
x <= 1, 2 after delay;
wait;
end process;

end architecture;
2 changes: 2 additions & 0 deletions test/regress/testlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -729,3 +729,5 @@ const10 normal
null3 normal
link4 normal
predef3 normal
wait26 fail,gold
signal29 fail,gold
19 changes: 19 additions & 0 deletions test/regress/wait26.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
entity wait26 is
end entity;

architecture test of wait26 is
begin

p1: process is
variable delay : time;
begin
delay := 5 ns;
wait for delay;
assert now = 5 ns;
delay := -1 hr;
wait for 1 ns;
wait for delay; -- Error
wait;
end process;

end architecture;

0 comments on commit d079ff5

Please sign in to comment.