Skip to content

Commit

Permalink
VHDL2019 assert api - partial (#748)
Browse files Browse the repository at this point in the history
  • Loading branch information
Blebowski authored Aug 4, 2023
1 parent e1429ee commit d00d562
Show file tree
Hide file tree
Showing 12 changed files with 373 additions and 9 deletions.
31 changes: 23 additions & 8 deletions lib/std.19/env-body.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -487,46 +487,61 @@ package body env is

impure function IsVhdlAssertFailed return boolean is
begin
report "not implemented" severity failure;
return IsVhdlAssertFailed(warning) or IsVhdlAssertFailed(error) or
IsVhdlAssertFailed(failure);
end function;

impure function IsVhdlAssertFailed (Level : severity_level)
return boolean is
function impl (Level : severity_level) return natural;
attribute foreign of impl : function is "_std_env_get_vhdl_assert_count";
begin
report "not implemented" severity failure;
return (impl(Level) > 0);
end function;

impure function GetVhdlAssertCount return natural is
begin
report "not implemented" severity failure;
return GetVhdlAssertCount(warning) + GetVhdlAssertCount(error) +
GetVhdlAssertCount(failure);
end function;

impure function GetVhdlAssertCount (Level : severity_level)
return natural is
function impl (Level : severity_level) return natural;
attribute foreign of impl : function is "_std_env_get_vhdl_assert_count";
begin
report "not implemented" severity failure;
return impl(Level);
end function;

procedure ClearVhdlAssert is
procedure impl;
attribute foreign of impl : procedure is "_std_env_clear_vhdl_assert";
begin
report "not implemented" severity failure;
impl;
end procedure;

procedure SetVhdlAssertEnable (Enable : boolean := true) is
begin
report "not implemented" severity failure;
SetVhdlAssertEnable (note, Enable);
SetVhdlAssertEnable (warning, Enable);
SetVhdlAssertEnable (error, Enable);
SetVhdlAssertEnable (failure, Enable);
end procedure;

procedure SetVhdlAssertEnable (Level : severity_level := note;
Enable : boolean := true) is
procedure impl (Level : severity_level; Enable : boolean);
attribute foreign of impl : procedure is "_std_env_set_vhdl_assert_enable";
begin
report "not implemented" severity failure;
impl(Level, enable);
end procedure;

impure function GetVhdlAssertEnable (Level : severity_level := note)
return boolean is
function impl (Level : severity_level) return boolean;
attribute foreign of impl : function is "_std_env_get_vhdl_assert_enable";
begin
report "not implemented" severity failure;
return impl(Level);
end function;

procedure SetVhdlAssertFormat(Level : SEVERITY_LEVEL;
Expand Down
12 changes: 12 additions & 0 deletions src/jit/jit-exits.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,12 @@ void __nvc_do_exit(jit_exit_t which, jit_anchor_t *anchor, jit_scalar_t *args,
int8_t hint_valid = args[5].integer;
object_t *where = args[6].pointer;

if (jit_has_runtime(thread->jit)) {
if (!get_vhdl_assert_enable(severity))
break;
increment_vhdl_assert_count(severity);
}

x_assert_fail(msg, len, severity, hint_left, hint_right,
hint_valid, where);
}
Expand All @@ -620,6 +626,12 @@ void __nvc_do_exit(jit_exit_t which, jit_anchor_t *anchor, jit_scalar_t *args,
int32_t severity = args[2].integer;
tree_t where = args[3].pointer;

if (jit_has_runtime(thread->jit)) {
if (!get_vhdl_assert_enable(severity))
break;
increment_vhdl_assert_count(severity);
}

x_report(msg, len, severity, where);
}
break;
Expand Down
55 changes: 55 additions & 0 deletions src/rt/model.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ typedef struct {
rt_scope_t *active_scope;
} __attribute__((aligned(64))) model_thread_t;

typedef struct _rt_asserts {
unsigned cnts[SEVERITY_FAILURE + 1];
bool enables[SEVERITY_FAILURE + 1];
} rt_asserts_t;

typedef struct _rt_model {
tree_t top;
hash_t *scopes;
Expand Down Expand Up @@ -111,6 +116,7 @@ typedef struct _rt_model {
memblock_t *memblocks;
model_thread_t *threads[MAX_THREADS];
ptr_list_t eventsigs;
rt_asserts_t asserts;
} rt_model_t;

#define FMT_VALUES_SZ 128
Expand Down Expand Up @@ -2059,6 +2065,14 @@ static void reset_coverage(rt_model_t *m)
fbuf_close(f, NULL);
}

static void reset_asserts(rt_model_t *m)
{
for (int i = SEVERITY_NOTE; i <= SEVERITY_FAILURE; i++) {
m->asserts.cnts[i] = 0;
m->asserts.enables[i] = true;
}
}

static void emit_coverage(rt_model_t *m)
{
if (m->cover != NULL) {
Expand Down Expand Up @@ -2216,6 +2230,7 @@ void model_reset(rt_model_t *m)
// Initialisation is described in LRM 93 section 12.6.4

reset_coverage(m);
reset_asserts(m);
reset_scope(m, m->root);

if (m->force_stop)
Expand Down Expand Up @@ -3487,6 +3502,46 @@ void get_forcing_value(rt_signal_t *s, uint8_t *value)
assert(p == value + s->shared.size);
}

int64_t get_vhdl_assert_count(int8_t severity)
{
rt_model_t *m = get_model();

assert(severity <= SEVERITY_FAILURE);
return m->asserts.cnts[severity];
}

void clear_vhdl_assert(void)
{
rt_model_t *m = get_model();

for (int i = SEVERITY_NOTE; i <= SEVERITY_FAILURE; i++)
m->asserts.cnts[i] = 0;
}

void increment_vhdl_assert_count(int8_t severity)
{
rt_model_t *m = get_model();

assert(severity <= SEVERITY_FAILURE);
m->asserts.cnts[severity]++;
}

void set_vhdl_assert_enable(int8_t severity, bool enable)
{
rt_model_t *m = get_model();

assert(severity <= SEVERITY_FAILURE);
m->asserts.enables[severity] = enable;
}

bool get_vhdl_assert_enable(int8_t severity)
{
rt_model_t *m = get_model();

assert(severity <= SEVERITY_FAILURE);
return m->asserts.enables[severity];
}

////////////////////////////////////////////////////////////////////////////////
// Entry points from compiled code

Expand Down
6 changes: 6 additions & 0 deletions src/rt/rt.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ typedef uint16_t delta_cycle_t;

void *rt_tlab_alloc(size_t size);

int64_t get_vhdl_assert_count(int8_t severity);
void increment_vhdl_assert_count(int8_t severity);
void clear_vhdl_assert(void);
void set_vhdl_assert_enable(int8_t severity, bool enable);
bool get_vhdl_assert_enable(int8_t severity);

void _std_standard_init(void);
void _std_env_init(void);
void _std_reflection_init(void);
Expand Down
26 changes: 26 additions & 0 deletions src/rt/stdenv.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "common.h"
#include "jit/jit.h"
#include "jit/jit-ffi.h"
#include "jit/jit-exits.h"
#include "scan.h"
#include "rt/rt.h"

Expand Down Expand Up @@ -661,6 +662,31 @@ int64_t _std_env_seconds_to_time(double real)
return (int64_t)whole * UINT64_C(1000000000000000) + (int64_t)(frac * 1e15);
}

DLLEXPORT
int64_t _std_env_get_vhdl_assert_count(vhdl_severity_t severity_level)
{
return get_vhdl_assert_count(severity_level);
}

DLLEXPORT
void _std_env_clear_vhdl_assert(void)
{
clear_vhdl_assert();
}

DLLEXPORT
void _std_env_set_vhdl_assert_enable(vhdl_severity_t severity_level,
bool enable)
{
set_vhdl_assert_enable(severity_level, enable);
}

DLLEXPORT
bool _std_env_get_vhdl_assert_enable(vhdl_severity_t severity_level)
{
return get_vhdl_assert_enable(severity_level);
}

void _std_env_init(void)
{
// Dummy function to force linking
Expand Down
4 changes: 4 additions & 0 deletions src/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
_std_env_stop;
_std_env_tool_version;
_std_env_vhdl_version;
_std_env_get_vhdl_assert_count;
_std_env_clear_vhdl_assert;
_std_env_set_vhdl_assert_enable;
_std_env_get_vhdl_assert_enable;

# Exported from src/rt/simpkg.c
_nvc_current_delta;
Expand Down
146 changes: 146 additions & 0 deletions test/regress/assert8.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
entity assert8 is
end entity;

use std.env.all;

architecture test of assert8 is
begin

process is
begin

assert (IsVhdlAssertFailed = false);
assert (IsVhdlAssertFailed(note) = false);
assert (IsVhdlAssertFailed(warning) = false);
assert (IsVhdlAssertFailed(error) = false);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 0);
assert (GetVhdlAssertCount(note) = 0);
assert (GetVhdlAssertCount(warning) = 0);
assert (GetVhdlAssertCount(error) = 0);
assert (GetVhdlAssertCount(failure) = 0);


assert (False) report "First note" severity note;

assert (IsVhdlAssertFailed = false);
assert (IsVhdlAssertFailed(note) = true);
assert (IsVhdlAssertFailed(warning) = false);
assert (IsVhdlAssertFailed(error) = false);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 0);
assert (GetVhdlAssertCount(note) = 1);
assert (GetVhdlAssertCount(warning) = 0);
assert (GetVhdlAssertCount(error) = 0);
assert (GetVhdlAssertCount(failure) = 0);


assert (False) report "First warning" severity warning;

assert (IsVhdlAssertFailed = true);
assert (IsVhdlAssertFailed(note) = true);
assert (IsVhdlAssertFailed(warning) = true);
assert (IsVhdlAssertFailed(error) = false);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 1);
assert (GetVhdlAssertCount(note) = 1);
assert (GetVhdlAssertCount(warning) = 1);
assert (GetVhdlAssertCount(error) = 0);
assert (GetVhdlAssertCount(failure) = 0);


assert (False) report "First error" severity error;

assert (IsVhdlAssertFailed = true);
assert (IsVhdlAssertFailed(note) = true);
assert (IsVhdlAssertFailed(warning) = true);
assert (IsVhdlAssertFailed(error) = true);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 2);
assert (GetVhdlAssertCount(note) = 1);
assert (GetVhdlAssertCount(warning) = 1);
assert (GetVhdlAssertCount(error) = 1);
assert (GetVhdlAssertCount(failure) = 0);


assert (False) report "Second note" severity note;

assert (IsVhdlAssertFailed = true);
assert (IsVhdlAssertFailed(note) = true);
assert (IsVhdlAssertFailed(warning) = true);
assert (IsVhdlAssertFailed(error) = true);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 2);
assert (GetVhdlAssertCount(note) = 2);
assert (GetVhdlAssertCount(warning) = 1);
assert (GetVhdlAssertCount(error) = 1);
assert (GetVhdlAssertCount(failure) = 0);


assert (False) report "Second warning" severity warning;

assert (IsVhdlAssertFailed = true);
assert (IsVhdlAssertFailed(note) = true);
assert (IsVhdlAssertFailed(warning) = true);
assert (IsVhdlAssertFailed(error) = true);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 3);
assert (GetVhdlAssertCount(note) = 2);
assert (GetVhdlAssertCount(warning) = 2);
assert (GetVhdlAssertCount(error) = 1);
assert (GetVhdlAssertCount(failure) = 0);


assert (False) report "Second error" severity error;

assert (IsVhdlAssertFailed = true);
assert (IsVhdlAssertFailed(note) = true);
assert (IsVhdlAssertFailed(warning) = true);
assert (IsVhdlAssertFailed(error) = true);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 4);
assert (GetVhdlAssertCount(note) = 2);
assert (GetVhdlAssertCount(warning) = 2);
assert (GetVhdlAssertCount(error) = 2);
assert (GetVhdlAssertCount(failure) = 0);


report "Clearing VHDL asserts";
ClearVhdlAssert;

assert (IsVhdlAssertFailed = false);
assert (IsVhdlAssertFailed(note) = false);
assert (IsVhdlAssertFailed(warning) = false);
assert (IsVhdlAssertFailed(error) = false);
assert (IsVhdlAssertFailed(failure) = false);

assert (GetVhdlAssertCount = 0);
assert (GetVhdlAssertCount(note) = 0);
assert (GetVhdlAssertCount(warning) = 0);
assert (GetVhdlAssertCount(error) = 0);
assert (GetVhdlAssertCount(failure) = 0);


report "Note report" severity note;
report "Warning report" severity warning;
report "Error report" severity error;

assert (GetVhdlAssertCount = 2);
assert (GetVhdlAssertCount(note) = 1);
assert (GetVhdlAssertCount(warning) = 1);
assert (GetVhdlAssertCount(error) = 1);
assert (GetVhdlAssertCount(failure) = 0);

-- TODO: How to test failure severity when it always stops simulation?

finish;
end process;

end architecture;
Loading

0 comments on commit d00d562

Please sign in to comment.