mirror of
https://github.com/YosysHQ/sby.git
synced 2025-08-13 08:40:56 +00:00
Add traces to database
Setting task property status accepts an optional trace id for associating a prop status with a trace. Where relevant, delays adding prop status(es) to the database until the corresponding tracefile is known, similar to how tracefiles and prop statuses are linked during the summary.
This commit is contained in:
parent
1d233405bf
commit
f0aca6c75e
4 changed files with 59 additions and 12 deletions
|
@ -233,7 +233,6 @@ def aigsmt_trace_callback(task, engine_idx, proc_status, *, run_aigsmt, smtbmc_v
|
||||||
cell_name = match[3] or match[2]
|
cell_name = match[3] or match[2]
|
||||||
prop = task.design.hierarchy.find_property(path, cell_name, trans_dict=smt2_trans)
|
prop = task.design.hierarchy.find_property(path, cell_name, trans_dict=smt2_trans)
|
||||||
prop.status = "FAIL"
|
prop.status = "FAIL"
|
||||||
task.status_db.set_task_property_status(prop, data=dict(source="aigsmt", engine=f"engine_{engine_idx}", step=current_step))
|
|
||||||
last_prop.append(prop)
|
last_prop.append(prop)
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
@ -241,7 +240,9 @@ def aigsmt_trace_callback(task, engine_idx, proc_status, *, run_aigsmt, smtbmc_v
|
||||||
if match:
|
if match:
|
||||||
tracefile = match[1]
|
tracefile = match[1]
|
||||||
trace = os.path.basename(tracefile)[:-4]
|
trace = os.path.basename(tracefile)[:-4]
|
||||||
|
trace_path = f"{task.workdir}/{tracefile}"
|
||||||
task.summary.add_event(engine_idx=engine_idx, trace=trace, path=tracefile)
|
task.summary.add_event(engine_idx=engine_idx, trace=trace, path=tracefile)
|
||||||
|
trace_id = task.status_db.add_task_trace(trace, trace_path)
|
||||||
|
|
||||||
if match and last_prop:
|
if match and last_prop:
|
||||||
for p in last_prop:
|
for p in last_prop:
|
||||||
|
@ -249,16 +250,20 @@ def aigsmt_trace_callback(task, engine_idx, proc_status, *, run_aigsmt, smtbmc_v
|
||||||
engine_idx=engine_idx, trace=trace,
|
engine_idx=engine_idx, trace=trace,
|
||||||
type=p.celltype, hdlname=p.hdlname, src=p.location, step=current_step)
|
type=p.celltype, hdlname=p.hdlname, src=p.location, step=current_step)
|
||||||
p.tracefiles.append(tracefile)
|
p.tracefiles.append(tracefile)
|
||||||
|
task.status_db.set_task_property_status(p, trace_id=trace_id, data=dict(source="aigsmt", engine=f"engine_{engine_idx}", step=current_step, trace_path=trace_path))
|
||||||
last_prop = []
|
last_prop = []
|
||||||
return line
|
return line
|
||||||
|
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def exit_callback2(retcode):
|
def exit_callback2(retcode):
|
||||||
|
nonlocal last_prop
|
||||||
if proc2_status is None:
|
if proc2_status is None:
|
||||||
task.error(f"engine_{engine_idx}: Could not determine aigsmt status.")
|
task.error(f"engine_{engine_idx}: Could not determine aigsmt status.")
|
||||||
if proc2_status != "FAIL":
|
if proc2_status != "FAIL":
|
||||||
task.error(f"engine_{engine_idx}: Unexpected aigsmt status.")
|
task.error(f"engine_{engine_idx}: Unexpected aigsmt status.")
|
||||||
|
if len(last_prop):
|
||||||
|
task.error(f"engine_{engine_idx}: Found properties without trace.")
|
||||||
|
|
||||||
proc2.output_callback = output_callback2
|
proc2.output_callback = output_callback2
|
||||||
proc2.register_exit_callback(exit_callback2)
|
proc2.register_exit_callback(exit_callback2)
|
||||||
|
|
|
@ -118,9 +118,12 @@ def run(mode, task, engine_idx, engine):
|
||||||
|
|
||||||
def make_exit_callback(suffix):
|
def make_exit_callback(suffix):
|
||||||
def exit_callback2(retcode):
|
def exit_callback2(retcode):
|
||||||
vcdpath = f"engine_{engine_idx}/trace{suffix}.vcd"
|
trace = f"trace{suffix}"
|
||||||
if os.path.exists(f"{task.workdir}/{vcdpath}"):
|
vcdpath = f"engine_{engine_idx}/{trace}.vcd"
|
||||||
task.summary.add_event(engine_idx=engine_idx, trace=f'trace{suffix}', path=vcdpath, type="$cover" if mode == "cover" else "$assert")
|
trace_path = f"{task.workdir}/{vcdpath}"
|
||||||
|
if os.path.exists(trace_path):
|
||||||
|
task.summary.add_event(engine_idx=engine_idx, trace=trace, path=vcdpath, type="$cover" if mode == "cover" else "$assert")
|
||||||
|
task.status_db.add_task_trace(trace, trace_path)
|
||||||
|
|
||||||
common_state.running_procs -= 1
|
common_state.running_procs -= 1
|
||||||
if (common_state.running_procs == 0):
|
if (common_state.running_procs == 0):
|
||||||
|
|
|
@ -245,7 +245,6 @@ def run(mode, task, engine_idx, engine):
|
||||||
cell_name = match[3] or match[2]
|
cell_name = match[3] or match[2]
|
||||||
prop = task.design.hierarchy.find_property(path, cell_name, trans_dict=smt2_trans)
|
prop = task.design.hierarchy.find_property(path, cell_name, trans_dict=smt2_trans)
|
||||||
prop.status = "FAIL"
|
prop.status = "FAIL"
|
||||||
task.status_db.set_task_property_status(prop, data=dict(source="smtbmc", engine=f"engine_{engine_idx}", step=current_step))
|
|
||||||
last_prop.append(prop)
|
last_prop.append(prop)
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
@ -255,7 +254,6 @@ def run(mode, task, engine_idx, engine):
|
||||||
cell_name = match[3] or match[2]
|
cell_name = match[3] or match[2]
|
||||||
prop = task.design.hierarchy.find_property(path, cell_name, trans_dict=smt2_trans)
|
prop = task.design.hierarchy.find_property(path, cell_name, trans_dict=smt2_trans)
|
||||||
prop.status = "PASS"
|
prop.status = "PASS"
|
||||||
task.status_db.set_task_property_status(prop, data=dict(source="smtbmc", engine=f"engine_{engine_idx}", step=current_step))
|
|
||||||
last_prop.append(prop)
|
last_prop.append(prop)
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
@ -264,8 +262,10 @@ def run(mode, task, engine_idx, engine):
|
||||||
if match:
|
if match:
|
||||||
tracefile = match[1]
|
tracefile = match[1]
|
||||||
trace = os.path.basename(tracefile)[:-4]
|
trace = os.path.basename(tracefile)[:-4]
|
||||||
|
trace_path = f"{task.workdir}/{tracefile}"
|
||||||
engine_case = mode.split('_')[1] if '_' in mode else None
|
engine_case = mode.split('_')[1] if '_' in mode else None
|
||||||
task.summary.add_event(engine_idx=engine_idx, trace=trace, path=tracefile, engine_case=engine_case)
|
task.summary.add_event(engine_idx=engine_idx, trace=trace, path=tracefile, engine_case=engine_case)
|
||||||
|
trace_id = task.status_db.add_task_trace(trace, trace_path, engine_case)
|
||||||
|
|
||||||
if match and last_prop:
|
if match and last_prop:
|
||||||
for p in last_prop:
|
for p in last_prop:
|
||||||
|
@ -273,6 +273,7 @@ def run(mode, task, engine_idx, engine):
|
||||||
engine_idx=engine_idx, trace=trace,
|
engine_idx=engine_idx, trace=trace,
|
||||||
type=p.celltype, hdlname=p.hdlname, src=p.location, step=current_step)
|
type=p.celltype, hdlname=p.hdlname, src=p.location, step=current_step)
|
||||||
p.tracefiles.append(tracefile)
|
p.tracefiles.append(tracefile)
|
||||||
|
task.status_db.set_task_property_status(p, trace_id=trace_id, data=dict(source="smtbmc", engine=f"engine_{engine_idx}", step=current_step, trace_path=trace_path))
|
||||||
last_prop = []
|
last_prop = []
|
||||||
return line
|
return line
|
||||||
else:
|
else:
|
||||||
|
@ -298,8 +299,11 @@ def run(mode, task, engine_idx, engine):
|
||||||
last_exit_callback()
|
last_exit_callback()
|
||||||
|
|
||||||
def exit_callback(retcode):
|
def exit_callback(retcode):
|
||||||
|
nonlocal last_prop
|
||||||
if proc_status is None:
|
if proc_status is None:
|
||||||
task.error(f"engine_{engine_idx}: Engine terminated without status.")
|
task.error(f"engine_{engine_idx}: Engine terminated without status.")
|
||||||
|
if len(last_prop):
|
||||||
|
task.error(f"engine_{engine_idx}: Found properties without trace.")
|
||||||
simple_exit_callback(retcode)
|
simple_exit_callback(retcode)
|
||||||
|
|
||||||
def last_exit_callback():
|
def last_exit_callback():
|
||||||
|
|
|
@ -44,10 +44,12 @@ CREATE TABLE task_property (
|
||||||
CREATE TABLE task_property_status (
|
CREATE TABLE task_property_status (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
task_property INTEGER,
|
task_property INTEGER,
|
||||||
|
task_trace INTEGER,
|
||||||
status TEXT,
|
status TEXT,
|
||||||
data TEXT,
|
data TEXT,
|
||||||
created REAL,
|
created REAL,
|
||||||
FOREIGN KEY(task_property) REFERENCES task_property(id)
|
FOREIGN KEY(task_property) REFERENCES task_property(id),
|
||||||
|
FOREIGN KEY(task_trace) REFERENCES task_trace(id)
|
||||||
);
|
);
|
||||||
CREATE TABLE task_property_data (
|
CREATE TABLE task_property_data (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
|
@ -56,6 +58,13 @@ CREATE TABLE task_property_data (
|
||||||
data TEXT,
|
data TEXT,
|
||||||
created REAL,
|
created REAL,
|
||||||
FOREIGN KEY(task_property) REFERENCES task_property(id)
|
FOREIGN KEY(task_property) REFERENCES task_property(id)
|
||||||
|
);
|
||||||
|
CREATE TABLE task_trace (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
trace TEXT,
|
||||||
|
path TEXT,
|
||||||
|
engine_case TEXT,
|
||||||
|
created REAL
|
||||||
);"""
|
);"""
|
||||||
|
|
||||||
def transaction(method: Fn) -> Fn:
|
def transaction(method: Fn) -> Fn:
|
||||||
|
@ -219,6 +228,7 @@ class SbyStatusDb:
|
||||||
self,
|
self,
|
||||||
property: SbyProperty,
|
property: SbyProperty,
|
||||||
status: Optional[str] = None,
|
status: Optional[str] = None,
|
||||||
|
trace_id: Optional[int] = None,
|
||||||
data: Any = None,
|
data: Any = None,
|
||||||
):
|
):
|
||||||
if status is None:
|
if status is None:
|
||||||
|
@ -228,15 +238,16 @@ class SbyStatusDb:
|
||||||
self.db.execute(
|
self.db.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO task_property_status (
|
INSERT INTO task_property_status (
|
||||||
task_property, status, data, created
|
task_property, task_trace, status, data, created
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
(SELECT id FROM task_property WHERE task = :task AND name = :name),
|
(SELECT id FROM task_property WHERE task = :task AND name = :name),
|
||||||
:status, :data, :now
|
:trace_id, :status, :data, :now
|
||||||
)
|
)
|
||||||
""",
|
""",
|
||||||
dict(
|
dict(
|
||||||
task=self.task_id,
|
task=self.task_id,
|
||||||
|
trace_id=trace_id,
|
||||||
name=json.dumps(property.path),
|
name=json.dumps(property.path),
|
||||||
status=status,
|
status=status,
|
||||||
data=json.dumps(data),
|
data=json.dumps(data),
|
||||||
|
@ -254,6 +265,7 @@ class SbyStatusDb:
|
||||||
property.location,
|
property.location,
|
||||||
property.kind,
|
property.kind,
|
||||||
property.status,
|
property.status,
|
||||||
|
data.get("trace_path", ""),
|
||||||
data.get("step", ""),
|
data.get("step", ""),
|
||||||
]
|
]
|
||||||
self.task.log(f"{click.style('csv', fg='yellow')}: {','.join(str(v) for v in csv)}")
|
self.task.log(f"{click.style('csv', fg='yellow')}: {','.join(str(v) for v in csv)}")
|
||||||
|
@ -280,6 +292,26 @@ class SbyStatusDb:
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def add_task_trace(self, trace: str, path: str, engine_case: Optional[str] = None):
|
||||||
|
now = time.time()
|
||||||
|
return self.db.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO task_trace (
|
||||||
|
trace, path, engine_case, created
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
:trace, :path, :engine_case, :now
|
||||||
|
)
|
||||||
|
""",
|
||||||
|
dict(
|
||||||
|
trace=trace,
|
||||||
|
path=path,
|
||||||
|
engine_case=engine_case,
|
||||||
|
now=now
|
||||||
|
)
|
||||||
|
).lastrowid
|
||||||
|
|
||||||
def all_tasks(self):
|
def all_tasks(self):
|
||||||
rows = self.db.execute(
|
rows = self.db.execute(
|
||||||
"""
|
"""
|
||||||
|
@ -385,10 +417,11 @@ class SbyStatusDb:
|
||||||
SELECT task.name as 'task_name', task.mode, task.created, task_property.kind,
|
SELECT task.name as 'task_name', task.mode, task.created, task_property.kind,
|
||||||
task_property.src as 'location', task_property.name, task_property.hdlname, task_property_status.status,
|
task_property.src as 'location', task_property.name, task_property.hdlname, task_property_status.status,
|
||||||
task_property_status.data, task_property_status.created as 'status_created',
|
task_property_status.data, task_property_status.created as 'status_created',
|
||||||
task_property_status.id
|
task_property_status.id, task_trace.path as 'trace_path'
|
||||||
FROM task
|
FROM task
|
||||||
INNER JOIN task_property ON task_property.task=task.id
|
INNER JOIN task_property ON task_property.task=task.id
|
||||||
INNER JOIN task_property_status ON task_property_status.task_property=task_property.id;
|
INNER JOIN task_property_status ON task_property_status.task_property=task_property.id
|
||||||
|
INNER JOIN task_trace ON task_property_status.task_trace=task_trace.id;
|
||||||
"""
|
"""
|
||||||
).fetchall()
|
).fetchall()
|
||||||
|
|
||||||
|
@ -414,6 +447,7 @@ class SbyStatusDb:
|
||||||
"location",
|
"location",
|
||||||
"kind",
|
"kind",
|
||||||
"status",
|
"status",
|
||||||
|
"trace",
|
||||||
"depth",
|
"depth",
|
||||||
]
|
]
|
||||||
print(','.join(csv_header))
|
print(','.join(csv_header))
|
||||||
|
@ -457,6 +491,7 @@ class SbyStatusDb:
|
||||||
prop_status['location'],
|
prop_status['location'],
|
||||||
prop_status['kind'],
|
prop_status['kind'],
|
||||||
status,
|
status,
|
||||||
|
prop_status['trace_path'],
|
||||||
depth,
|
depth,
|
||||||
]
|
]
|
||||||
print(','.join("" if v is None else str(v) for v in csv_line))
|
print(','.join("" if v is None else str(v) for v in csv_line))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue