From 911ae02ee5d068ad82b0f46f54b275a20599ab6a Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 5 Jul 2025 12:40:57 +1200 Subject: [PATCH] Test property statuses for cover_assert Cover properties shouldn't be marked fail when the test failed early due to an assertion. This should fail without other changes. --- tests/statusdb/Makefile | 2 ++ tests/statusdb/mixed.py | 59 ++++++++++++++++++++++++++++++++++++++++ tests/statusdb/mixed.sby | 24 ++++++++++++++++ tests/statusdb/mixed.sh | 4 +++ tests/statusdb/mixed.v | 16 +++++++++++ 5 files changed, 105 insertions(+) create mode 100644 tests/statusdb/Makefile create mode 100644 tests/statusdb/mixed.py create mode 100644 tests/statusdb/mixed.sby create mode 100644 tests/statusdb/mixed.sh create mode 100644 tests/statusdb/mixed.v diff --git a/tests/statusdb/Makefile b/tests/statusdb/Makefile new file mode 100644 index 0000000..66f8e99 --- /dev/null +++ b/tests/statusdb/Makefile @@ -0,0 +1,2 @@ +SUBDIR=statusdb +include ../make/subdir.mk diff --git a/tests/statusdb/mixed.py b/tests/statusdb/mixed.py new file mode 100644 index 0000000..5daba53 --- /dev/null +++ b/tests/statusdb/mixed.py @@ -0,0 +1,59 @@ +import json +import sqlite3 +import sys + +def get_prop_type(prop: str): + prop = json.loads(prop or "[]") + name_parts = prop[-1].split("_") + if name_parts[0] == "\check": + # read_verilog style + # \check_cover_mixed_v... + return name_parts[1] + else: + # verific style + # \assert_auto_verificsva_cc... + return name_parts[0][1:] + +def main(): + workdir = sys.argv[1] + with open(f"{workdir}/status.path", "r") as status_path_file: + status_path = f"{workdir}/{status_path_file.read().rstrip()}" + # read only database + con = sqlite3.connect(f"file:{status_path}?mode=ro", uri=True) + db = con.cursor() + # custom sql to get all task property statuses for the current workdir + rows = db.execute( + """ + SELECT task.id, task_property.name, task_property.src, task_property_status.status + FROM task + LEFT JOIN task_property ON task_property.task=task.id + LEFT JOIN task_property_status ON task_property_status.task_property=task_property.id + WHERE task.workdir=:workdir; + """, + {"workdir": workdir} + ).fetchall() + # only check the most recent iteration of the test + last_id = 0 + for row_id, _, _, _ in rows: + if row_id > last_id: + last_id = row_id + for row_id, prop, src, status in rows: + if row_id != last_id: + continue + prop_type = get_prop_type(prop) + valid_status: list[None|str] = [] + if workdir in ["mixed_bmc", "mixed_assert"] and prop_type == "assert": + valid_status = ["FAIL"] + elif workdir == "mixed_bmc" and prop_type == "cover": + valid_status = [None, "UNKNOWN"] + elif workdir == "mixed_assert" and prop_type == "cover": + valid_status = ["PASS", None, "UNKNOWN"] + elif workdir == "mixed_no_assert" and prop_type == "assert": + valid_status = [None, "UNKNOWN"] + elif workdir == "mixed_no_assert" and prop_type == "cover": + valid_status = ["PASS"] + assert status in valid_status, f"Unexpected {prop_type} status {status} for {prop} ({src})" + + +if __name__ == "__main__": + main() diff --git a/tests/statusdb/mixed.sby b/tests/statusdb/mixed.sby new file mode 100644 index 0000000..7ad09c1 --- /dev/null +++ b/tests/statusdb/mixed.sby @@ -0,0 +1,24 @@ +[tasks] +no_assert cover +assert cover +bmc + +[options] +cover: mode cover +bmc: mode bmc +bmc: depth 1 + +assert: cover_assert on +no_assert: expect pass +~no_assert: expect fail + +[engines] +cover: smtbmc boolector +bmc: smtbmc boolector + +[script] +read -formal mixed.v +prep -top test + +[files] +mixed.v diff --git a/tests/statusdb/mixed.sh b/tests/statusdb/mixed.sh new file mode 100644 index 0000000..aca8be6 --- /dev/null +++ b/tests/statusdb/mixed.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -e +python3 $SBY_MAIN -f $SBY_FILE $TASK +python3 ${SBY_FILE%.sby}.py $WORKDIR diff --git a/tests/statusdb/mixed.v b/tests/statusdb/mixed.v new file mode 100644 index 0000000..16e1228 --- /dev/null +++ b/tests/statusdb/mixed.v @@ -0,0 +1,16 @@ +module test (input CP, CN, input A, B, output reg XP, XN); + reg [7:0] counter = 0; + always @* begin + assume (A || B); + assume (!A || !B); + assert (A == B); + cover (counter == 3 && A); + cover (counter == 3 && B); + end + always @(posedge CP) + counter <= counter + 1; + always @(posedge CP) + XP <= A; + always @(negedge CN) + XN <= B; +endmodule