dvsim 1.7.0__py3-none-any.whl → 1.7.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dvsim/cli/admin.py +3 -3
- dvsim/flow/base.py +1 -66
- dvsim/flow/factory.py +1 -1
- dvsim/flow/lint.py +4 -1
- dvsim/flow/one_shot.py +55 -6
- dvsim/job/deploy.py +4 -0
- dvsim/launcher/base.py +18 -15
- dvsim/report/data.py +1 -201
- dvsim/sim/__init__.py +5 -0
- dvsim/sim/data.py +259 -0
- dvsim/{flow/sim.py → sim/flow.py} +87 -5
- dvsim/{report/generate.py → sim/report.py} +4 -4
- dvsim/sim/tool/__init__.py +5 -0
- dvsim/{tool/sim.py → sim/tool/base.py} +1 -1
- dvsim/{tool → sim/tool}/vcs.py +1 -1
- dvsim/{tool → sim/tool}/xcelium.py +1 -1
- dvsim/templates/render.py +5 -2
- dvsim/tool/utils.py +3 -3
- {dvsim-1.7.0.dist-info → dvsim-1.7.2.dist-info}/METADATA +1 -1
- {dvsim-1.7.0.dist-info → dvsim-1.7.2.dist-info}/RECORD +23 -20
- {dvsim-1.7.0.dist-info → dvsim-1.7.2.dist-info}/WHEEL +0 -0
- {dvsim-1.7.0.dist-info → dvsim-1.7.2.dist-info}/entry_points.txt +0 -0
- {dvsim-1.7.0.dist-info → dvsim-1.7.2.dist-info}/licenses/LICENSE +0 -0
dvsim/cli/admin.py
CHANGED
|
@@ -35,9 +35,9 @@ def report() -> None:
|
|
|
35
35
|
)
|
|
36
36
|
def gen(json_path: Path, output_dir: Path) -> None:
|
|
37
37
|
"""Generate a report from a existing results JSON."""
|
|
38
|
-
from dvsim.
|
|
39
|
-
from dvsim.report
|
|
38
|
+
from dvsim.sim.data import SimResultsSummary
|
|
39
|
+
from dvsim.sim.report import gen_reports
|
|
40
40
|
|
|
41
|
-
results:
|
|
41
|
+
results: SimResultsSummary = SimResultsSummary.load(path=json_path)
|
|
42
42
|
|
|
43
43
|
gen_reports(summary=results, path=output_dir)
|
dvsim/flow/base.py
CHANGED
|
@@ -10,7 +10,6 @@ import pprint
|
|
|
10
10
|
import sys
|
|
11
11
|
from abc import ABC, abstractmethod
|
|
12
12
|
from collections.abc import Mapping, Sequence
|
|
13
|
-
from datetime import datetime, timezone
|
|
14
13
|
from pathlib import Path
|
|
15
14
|
from typing import TYPE_CHECKING, ClassVar
|
|
16
15
|
|
|
@@ -20,15 +19,12 @@ from dvsim.flow.hjson import set_target_attribute
|
|
|
20
19
|
from dvsim.job.data import CompletedJobStatus
|
|
21
20
|
from dvsim.launcher.factory import get_launcher_cls
|
|
22
21
|
from dvsim.logging import log
|
|
23
|
-
from dvsim.report.data import FlowResults, IPMeta, ResultsSummary
|
|
24
|
-
from dvsim.report.generate import gen_block_report, gen_reports
|
|
25
22
|
from dvsim.scheduler import Scheduler
|
|
26
23
|
from dvsim.utils import (
|
|
27
24
|
find_and_substitute_wildcards,
|
|
28
25
|
rm_path,
|
|
29
26
|
subst_wildcards,
|
|
30
27
|
)
|
|
31
|
-
from dvsim.utils.git import git_commit_hash
|
|
32
28
|
|
|
33
29
|
if TYPE_CHECKING:
|
|
34
30
|
from dvsim.job.deploy import Deploy
|
|
@@ -447,6 +443,7 @@ class FlowCfg(ABC):
|
|
|
447
443
|
interactive=self.interactive,
|
|
448
444
|
).run()
|
|
449
445
|
|
|
446
|
+
@abstractmethod
|
|
450
447
|
def gen_results(self, results: Sequence[CompletedJobStatus]) -> None:
|
|
451
448
|
"""Generate flow results.
|
|
452
449
|
|
|
@@ -454,68 +451,6 @@ class FlowCfg(ABC):
|
|
|
454
451
|
results: completed job status objects.
|
|
455
452
|
|
|
456
453
|
"""
|
|
457
|
-
reports_dir = Path(self.scratch_base_path) / "reports"
|
|
458
|
-
commit = git_commit_hash(path=Path(self.proj_root))
|
|
459
|
-
url = f"https://github.com/lowrisc/opentitan/tree/{commit}"
|
|
460
|
-
|
|
461
|
-
all_flow_results: Mapping[str, FlowResults] = {}
|
|
462
|
-
|
|
463
|
-
for item in self.cfgs:
|
|
464
|
-
item_results = [
|
|
465
|
-
res
|
|
466
|
-
for res in results
|
|
467
|
-
if res.block.name == item.name and res.block.variant == item.variant
|
|
468
|
-
]
|
|
469
|
-
|
|
470
|
-
flow_results: FlowResults = item._gen_json_results(
|
|
471
|
-
run_results=item_results,
|
|
472
|
-
commit=commit,
|
|
473
|
-
url=url,
|
|
474
|
-
)
|
|
475
|
-
|
|
476
|
-
# Convert to lowercase to match filename
|
|
477
|
-
block_result_index = (
|
|
478
|
-
f"{item.name}_{item.variant}" if item.variant else item.name
|
|
479
|
-
).lower()
|
|
480
|
-
|
|
481
|
-
all_flow_results[block_result_index] = flow_results
|
|
482
|
-
|
|
483
|
-
# Generate the block's JSON/HTML reports to the report area.
|
|
484
|
-
gen_block_report(
|
|
485
|
-
results=flow_results,
|
|
486
|
-
path=reports_dir,
|
|
487
|
-
)
|
|
488
|
-
|
|
489
|
-
self.errors_seen |= item.errors_seen
|
|
490
|
-
|
|
491
|
-
if self.is_primary_cfg:
|
|
492
|
-
# The timestamp for this run has been taken with `utcnow()` and is
|
|
493
|
-
# stored in a custom format. Store it in standard ISO format with
|
|
494
|
-
# explicit timezone annotation.
|
|
495
|
-
timestamp = (
|
|
496
|
-
datetime.strptime(self.timestamp, "%Y%m%d_%H%M%S")
|
|
497
|
-
.replace(tzinfo=timezone.utc)
|
|
498
|
-
.isoformat()
|
|
499
|
-
)
|
|
500
|
-
|
|
501
|
-
results_summary = ResultsSummary(
|
|
502
|
-
top=IPMeta(
|
|
503
|
-
name=self.name,
|
|
504
|
-
variant=self.variant,
|
|
505
|
-
commit=commit,
|
|
506
|
-
branch=self.branch,
|
|
507
|
-
url=url,
|
|
508
|
-
),
|
|
509
|
-
timestamp=timestamp,
|
|
510
|
-
flow_results=all_flow_results,
|
|
511
|
-
report_path=reports_dir,
|
|
512
|
-
)
|
|
513
|
-
|
|
514
|
-
# Generate all the JSON/HTML reports to the report area.
|
|
515
|
-
gen_reports(
|
|
516
|
-
summary=results_summary,
|
|
517
|
-
path=reports_dir,
|
|
518
|
-
)
|
|
519
454
|
|
|
520
455
|
def has_errors(self) -> bool:
|
|
521
456
|
"""Return error state."""
|
dvsim/flow/factory.py
CHANGED
|
@@ -11,9 +11,9 @@ from dvsim.flow.formal import FormalCfg
|
|
|
11
11
|
from dvsim.flow.hjson import load_hjson
|
|
12
12
|
from dvsim.flow.lint import LintCfg
|
|
13
13
|
from dvsim.flow.rdc import RdcCfg
|
|
14
|
-
from dvsim.flow.sim import SimCfg
|
|
15
14
|
from dvsim.flow.syn import SynCfg
|
|
16
15
|
from dvsim.logging import log
|
|
16
|
+
from dvsim.sim.flow import SimCfg
|
|
17
17
|
|
|
18
18
|
FLOW_HANDLERS = {
|
|
19
19
|
"cdc": CdcCfg,
|
dvsim/flow/lint.py
CHANGED
|
@@ -76,7 +76,10 @@ class LintCfg(OneShotCfg):
|
|
|
76
76
|
|
|
77
77
|
keys = self.totals.get_keys(self.report_severities)
|
|
78
78
|
for cfg in self.cfgs:
|
|
79
|
-
|
|
79
|
+
link_text = self.name.upper()
|
|
80
|
+
relative_link = Path(self.results_dir) / self.results_page
|
|
81
|
+
|
|
82
|
+
name_with_link = f"[{link_text}]({relative_link})"
|
|
80
83
|
|
|
81
84
|
row = [name_with_link]
|
|
82
85
|
row += cfg.result_summary.get_counts_md(keys)
|
dvsim/flow/one_shot.py
CHANGED
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
"""Class describing a one-shot build configuration object."""
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
from abc import abstractmethod
|
|
8
8
|
from collections import OrderedDict
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
from pathlib import Path
|
|
9
11
|
|
|
10
12
|
from dvsim.flow.base import FlowCfg
|
|
13
|
+
from dvsim.job.data import CompletedJobStatus
|
|
11
14
|
from dvsim.job.deploy import CompileOneShot
|
|
12
15
|
from dvsim.logging import log
|
|
13
16
|
from dvsim.modes import BuildMode, Mode
|
|
@@ -15,9 +18,7 @@ from dvsim.utils import rm_path
|
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
class OneShotCfg(FlowCfg):
|
|
18
|
-
"""Simple one-shot build flow for non-simulation targets like
|
|
19
|
-
linting, synthesis and FPV.
|
|
20
|
-
"""
|
|
21
|
+
"""Simple one-shot build flow for non-simulation targets like linting, synthesis and FPV."""
|
|
21
22
|
|
|
22
23
|
ignored_wildcards = [*FlowCfg.ignored_wildcards, "build_mode", "index", "test"]
|
|
23
24
|
|
|
@@ -134,8 +135,10 @@ class OneShotCfg(FlowCfg):
|
|
|
134
135
|
def _create_dirs(self) -> None:
|
|
135
136
|
"""Create initial set of directories."""
|
|
136
137
|
for link in self.links:
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
link_path = Path(self.links[link])
|
|
139
|
+
|
|
140
|
+
rm_path(link_path)
|
|
141
|
+
link_path.mkdir(parents=True)
|
|
139
142
|
|
|
140
143
|
def _create_deploy_objects(self) -> None:
|
|
141
144
|
"""Create deploy objects from build modes."""
|
|
@@ -149,3 +152,49 @@ class OneShotCfg(FlowCfg):
|
|
|
149
152
|
|
|
150
153
|
# Create initial set of directories before kicking off the regression.
|
|
151
154
|
self._create_dirs()
|
|
155
|
+
|
|
156
|
+
@abstractmethod
|
|
157
|
+
def _gen_results(self):
|
|
158
|
+
"""Generate results for this config."""
|
|
159
|
+
|
|
160
|
+
@abstractmethod
|
|
161
|
+
def gen_results_summary(self):
|
|
162
|
+
"""Gathers the aggregated results from all sub configs."""
|
|
163
|
+
|
|
164
|
+
def gen_results(self, results: Sequence[CompletedJobStatus]) -> None:
|
|
165
|
+
"""Generate flow results.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
results: completed job status objects.
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
for item in self.cfgs:
|
|
172
|
+
project = item.name
|
|
173
|
+
|
|
174
|
+
item_results = [
|
|
175
|
+
res
|
|
176
|
+
for res in results
|
|
177
|
+
if res.block.name == item.name and res.block.variant == item.variant
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
result = item._gen_results(item_results)
|
|
181
|
+
|
|
182
|
+
log.info("[results]: [%s]:\n%s\n", project, result)
|
|
183
|
+
log.info("[scratch_path]: [%s] [%s]", project, item.scratch_path)
|
|
184
|
+
|
|
185
|
+
# TODO: Implement HTML report using templates
|
|
186
|
+
|
|
187
|
+
results_dir = Path(self.results_dir)
|
|
188
|
+
results_dir.mkdir(exist_ok=True, parents=True)
|
|
189
|
+
|
|
190
|
+
# (results_dir / self.results_html_name).write_text(
|
|
191
|
+
# md_results_to_html(self.results_title, self.css_file, item.results_md)
|
|
192
|
+
# )
|
|
193
|
+
|
|
194
|
+
log.verbose("[report]: [%s] [%s/report.html]", project, item.results_dir)
|
|
195
|
+
|
|
196
|
+
self.errors_seen |= item.errors_seen
|
|
197
|
+
|
|
198
|
+
if self.is_primary_cfg:
|
|
199
|
+
self.gen_results_summary()
|
|
200
|
+
# self.write_results(self.results_html_name, self.results_summary_md)
|
dvsim/job/deploy.py
CHANGED
|
@@ -74,6 +74,10 @@ class Deploy:
|
|
|
74
74
|
# Cross ref the whole cfg object for ease.
|
|
75
75
|
self.sim_cfg = sim_cfg
|
|
76
76
|
self.flow = sim_cfg.name
|
|
77
|
+
|
|
78
|
+
if not hasattr(self.sim_cfg, "variant"):
|
|
79
|
+
self.sim_cfg.variant = ""
|
|
80
|
+
|
|
77
81
|
self._variant_suffix = f"_{self.sim_cfg.variant}" if self.sim_cfg.variant else ""
|
|
78
82
|
|
|
79
83
|
# A list of jobs on which this job depends.
|
dvsim/launcher/base.py
CHANGED
|
@@ -339,25 +339,28 @@ class Launcher(ABC):
|
|
|
339
339
|
# since it is devoid of the delays incurred due to infrastructure and
|
|
340
340
|
# setup overhead.
|
|
341
341
|
|
|
342
|
-
|
|
342
|
+
time = self.job_runtime_secs
|
|
343
|
+
unit = "s"
|
|
344
|
+
|
|
345
|
+
if self.job_spec.job_type in [
|
|
346
|
+
"CompileSim",
|
|
347
|
+
"RunTest",
|
|
348
|
+
"CovUnr",
|
|
349
|
+
"CovMerge",
|
|
350
|
+
"CovReport",
|
|
351
|
+
"CovAnalyze",
|
|
352
|
+
]:
|
|
353
|
+
plugin = get_sim_tool_plugin(tool=self.job_spec.tool.name)
|
|
343
354
|
|
|
344
|
-
try:
|
|
345
|
-
time, unit = plugin.get_job_runtime(log_text=lines)
|
|
346
|
-
self.job_runtime.set(time, unit)
|
|
347
|
-
|
|
348
|
-
except RuntimeError as e:
|
|
349
|
-
log.warning(
|
|
350
|
-
f"{self.job_spec.full_name}: {e} Using dvsim-maintained job_runtime instead."
|
|
351
|
-
)
|
|
352
|
-
self.job_runtime.set(self.job_runtime_secs, "s")
|
|
353
|
-
|
|
354
|
-
if self.job_spec.job_type == "RunTest":
|
|
355
355
|
try:
|
|
356
|
-
time, unit = plugin.
|
|
357
|
-
self.simulated_time.set(time, unit)
|
|
356
|
+
time, unit = plugin.get_job_runtime(log_text=lines)
|
|
358
357
|
|
|
359
358
|
except RuntimeError as e:
|
|
360
|
-
log.
|
|
359
|
+
log.warning(
|
|
360
|
+
f"{self.job_spec.full_name}: {e} Using dvsim-maintained job_runtime instead."
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
self.job_runtime.set(time, unit)
|
|
361
364
|
|
|
362
365
|
if chk_failed or chk_passed:
|
|
363
366
|
for cnt, line in enumerate(lines):
|
dvsim/report/data.py
CHANGED
|
@@ -4,17 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
"""Report data models."""
|
|
6
6
|
|
|
7
|
-
from collections.abc import Mapping
|
|
8
|
-
from datetime import datetime
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
7
|
from pydantic import BaseModel, ConfigDict
|
|
12
8
|
|
|
13
|
-
from dvsim.sim_results import BucketedFailures
|
|
14
|
-
|
|
15
9
|
__all__ = (
|
|
16
10
|
"IPMeta",
|
|
17
|
-
"
|
|
11
|
+
"ToolMeta",
|
|
18
12
|
)
|
|
19
13
|
|
|
20
14
|
|
|
@@ -45,197 +39,3 @@ class ToolMeta(BaseModel):
|
|
|
45
39
|
"""Name of the tool."""
|
|
46
40
|
version: str
|
|
47
41
|
"""Version of the tool."""
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
class TestResult(BaseModel):
|
|
51
|
-
"""Test result."""
|
|
52
|
-
|
|
53
|
-
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
54
|
-
|
|
55
|
-
max_time: float
|
|
56
|
-
"""Run time."""
|
|
57
|
-
sim_time: float
|
|
58
|
-
"""Simulation time."""
|
|
59
|
-
|
|
60
|
-
passed: int
|
|
61
|
-
"""Number of tests passed."""
|
|
62
|
-
total: int
|
|
63
|
-
"""Total number of tests run."""
|
|
64
|
-
percent: float
|
|
65
|
-
"""Percentage test pass rate."""
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class Testpoint(BaseModel):
|
|
69
|
-
"""Testpoint."""
|
|
70
|
-
|
|
71
|
-
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
72
|
-
|
|
73
|
-
tests: Mapping[str, TestResult]
|
|
74
|
-
"""Test results."""
|
|
75
|
-
|
|
76
|
-
passed: int
|
|
77
|
-
"""Number of tests passed."""
|
|
78
|
-
total: int
|
|
79
|
-
"""Total number of tests run."""
|
|
80
|
-
percent: float
|
|
81
|
-
"""Percentage test pass rate."""
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class TestStage(BaseModel):
|
|
85
|
-
"""Test stages."""
|
|
86
|
-
|
|
87
|
-
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
88
|
-
|
|
89
|
-
testpoints: Mapping[str, Testpoint]
|
|
90
|
-
"""Results by test point."""
|
|
91
|
-
|
|
92
|
-
passed: int
|
|
93
|
-
"""Number of tests passed."""
|
|
94
|
-
total: int
|
|
95
|
-
"""Total number of tests run."""
|
|
96
|
-
percent: float
|
|
97
|
-
"""Percentage test pass rate."""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class CodeCoverageMetrics(BaseModel):
|
|
101
|
-
"""CodeCoverage metrics."""
|
|
102
|
-
|
|
103
|
-
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
104
|
-
|
|
105
|
-
block: float | None
|
|
106
|
-
"""Block Coverage (%) - did this part of the code execute?"""
|
|
107
|
-
line_statement: float | None
|
|
108
|
-
"""Line/Statement Coverage (%) - did this part of the code execute?"""
|
|
109
|
-
branch: float | None
|
|
110
|
-
"""Branch Coverage (%) - did this if/case take all paths?"""
|
|
111
|
-
condition_expression: float | None
|
|
112
|
-
"""Condition/Expression Coverage (%) - did the logic evaluate to 0 & 1?"""
|
|
113
|
-
toggle: float | None
|
|
114
|
-
"""Toggle Coverage (%) - did the signal wiggle?"""
|
|
115
|
-
fsm: float | None
|
|
116
|
-
"""FSM Coverage (%) - did the state machine transition?"""
|
|
117
|
-
|
|
118
|
-
@property
|
|
119
|
-
def average(self) -> float | None:
|
|
120
|
-
"""Average code coverage (%)."""
|
|
121
|
-
all_cov = [
|
|
122
|
-
c
|
|
123
|
-
for c in [
|
|
124
|
-
self.line_statement,
|
|
125
|
-
self.branch,
|
|
126
|
-
self.condition_expression,
|
|
127
|
-
self.toggle,
|
|
128
|
-
self.fsm,
|
|
129
|
-
]
|
|
130
|
-
if c is not None
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
if len(all_cov) == 0:
|
|
134
|
-
return None
|
|
135
|
-
|
|
136
|
-
return sum(all_cov) / len(all_cov)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
class CoverageMetrics(BaseModel):
|
|
140
|
-
"""Coverage metrics."""
|
|
141
|
-
|
|
142
|
-
code: CodeCoverageMetrics | None
|
|
143
|
-
"""Code Coverage."""
|
|
144
|
-
assertion: float | None
|
|
145
|
-
"""Assertion Coverage."""
|
|
146
|
-
functional: float | None
|
|
147
|
-
"""Functional coverage."""
|
|
148
|
-
|
|
149
|
-
@property
|
|
150
|
-
def average(self) -> float | None:
|
|
151
|
-
"""Average code coverage (%) or None if there is no coverage."""
|
|
152
|
-
code = self.code.average if self.code is not None else None
|
|
153
|
-
all_cov = [
|
|
154
|
-
c
|
|
155
|
-
for c in [
|
|
156
|
-
code,
|
|
157
|
-
self.assertion,
|
|
158
|
-
self.functional,
|
|
159
|
-
]
|
|
160
|
-
if c is not None
|
|
161
|
-
]
|
|
162
|
-
|
|
163
|
-
if len(all_cov) == 0:
|
|
164
|
-
return None
|
|
165
|
-
|
|
166
|
-
return sum(all_cov) / len(all_cov)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
class FlowResults(BaseModel):
|
|
170
|
-
"""Flow results data."""
|
|
171
|
-
|
|
172
|
-
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
173
|
-
|
|
174
|
-
block: IPMeta
|
|
175
|
-
"""IP block metadata."""
|
|
176
|
-
tool: ToolMeta
|
|
177
|
-
"""Tool used in the simulation run."""
|
|
178
|
-
timestamp: datetime
|
|
179
|
-
"""Timestamp for when the test ran."""
|
|
180
|
-
|
|
181
|
-
stages: Mapping[str, TestStage]
|
|
182
|
-
"""Results per test stage."""
|
|
183
|
-
coverage: CoverageMetrics | None
|
|
184
|
-
"""Coverage metrics."""
|
|
185
|
-
|
|
186
|
-
failed_jobs: BucketedFailures
|
|
187
|
-
"""Bucketed failed job overview."""
|
|
188
|
-
|
|
189
|
-
passed: int
|
|
190
|
-
"""Number of tests passed."""
|
|
191
|
-
total: int
|
|
192
|
-
"""Total number of tests run."""
|
|
193
|
-
percent: float
|
|
194
|
-
"""Percentage test pass rate."""
|
|
195
|
-
|
|
196
|
-
@staticmethod
|
|
197
|
-
def load(path: Path) -> "FlowResults":
|
|
198
|
-
"""Load results from JSON file.
|
|
199
|
-
|
|
200
|
-
Transform the fields of the loaded JSON into a more useful schema for
|
|
201
|
-
report generation.
|
|
202
|
-
|
|
203
|
-
Args:
|
|
204
|
-
path: to the json file to load.
|
|
205
|
-
|
|
206
|
-
"""
|
|
207
|
-
return FlowResults.model_validate_json(path.read_text())
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
class ResultsSummary(BaseModel):
|
|
211
|
-
"""Summary of results."""
|
|
212
|
-
|
|
213
|
-
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
214
|
-
|
|
215
|
-
top: IPMeta
|
|
216
|
-
"""Meta data for the top level config."""
|
|
217
|
-
|
|
218
|
-
timestamp: datetime
|
|
219
|
-
"""Run time stamp."""
|
|
220
|
-
|
|
221
|
-
flow_results: Mapping[str, FlowResults]
|
|
222
|
-
"""Flow results."""
|
|
223
|
-
|
|
224
|
-
report_path: Path
|
|
225
|
-
"""Path to the report JSON file."""
|
|
226
|
-
|
|
227
|
-
@staticmethod
|
|
228
|
-
def load(path: Path) -> "ResultsSummary":
|
|
229
|
-
"""Load results from JSON file.
|
|
230
|
-
|
|
231
|
-
Transform the fields of the loaded JSON into a more useful schema for
|
|
232
|
-
report generation.
|
|
233
|
-
|
|
234
|
-
Args:
|
|
235
|
-
path: to the json file to load.
|
|
236
|
-
|
|
237
|
-
Returns:
|
|
238
|
-
The loaded ResultsSummary from JSON.
|
|
239
|
-
|
|
240
|
-
"""
|
|
241
|
-
return ResultsSummary.model_validate_json(path.read_text())
|
dvsim/sim/__init__.py
ADDED
dvsim/sim/data.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Copyright lowRISC contributors (OpenTitan project).
|
|
2
|
+
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""Simulation data models."""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Mapping
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, ConfigDict
|
|
12
|
+
|
|
13
|
+
from dvsim.report.data import IPMeta, ToolMeta
|
|
14
|
+
from dvsim.sim_results import BucketedFailures
|
|
15
|
+
|
|
16
|
+
__all__ = (
|
|
17
|
+
"CodeCoverageMetrics",
|
|
18
|
+
"CoverageMetrics",
|
|
19
|
+
"SimFlowResults",
|
|
20
|
+
"SimResultsSummary",
|
|
21
|
+
"TestResult",
|
|
22
|
+
"TestStage",
|
|
23
|
+
"Testpoint",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestResult(BaseModel):
|
|
28
|
+
"""Test result."""
|
|
29
|
+
|
|
30
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
31
|
+
|
|
32
|
+
max_time: float
|
|
33
|
+
"""Run time."""
|
|
34
|
+
sim_time: float
|
|
35
|
+
"""Simulation time."""
|
|
36
|
+
|
|
37
|
+
passed: int
|
|
38
|
+
"""Number of tests passed."""
|
|
39
|
+
total: int
|
|
40
|
+
"""Total number of tests run."""
|
|
41
|
+
percent: float
|
|
42
|
+
"""Percentage test pass rate."""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Testpoint(BaseModel):
|
|
46
|
+
"""Testpoint."""
|
|
47
|
+
|
|
48
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
49
|
+
|
|
50
|
+
tests: Mapping[str, TestResult]
|
|
51
|
+
"""Test results."""
|
|
52
|
+
|
|
53
|
+
passed: int
|
|
54
|
+
"""Number of tests passed."""
|
|
55
|
+
total: int
|
|
56
|
+
"""Total number of tests run."""
|
|
57
|
+
percent: float
|
|
58
|
+
"""Percentage test pass rate."""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TestStage(BaseModel):
|
|
62
|
+
"""Test stages."""
|
|
63
|
+
|
|
64
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
65
|
+
|
|
66
|
+
testpoints: Mapping[str, Testpoint]
|
|
67
|
+
"""Results by test point."""
|
|
68
|
+
|
|
69
|
+
passed: int
|
|
70
|
+
"""Number of tests passed."""
|
|
71
|
+
total: int
|
|
72
|
+
"""Total number of tests run."""
|
|
73
|
+
percent: float
|
|
74
|
+
"""Percentage test pass rate."""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class CodeCoverageMetrics(BaseModel):
|
|
78
|
+
"""CodeCoverage metrics."""
|
|
79
|
+
|
|
80
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
81
|
+
|
|
82
|
+
block: float | None
|
|
83
|
+
"""Block Coverage (%) - did this part of the code execute?"""
|
|
84
|
+
line_statement: float | None
|
|
85
|
+
"""Line/Statement Coverage (%) - did this part of the code execute?"""
|
|
86
|
+
branch: float | None
|
|
87
|
+
"""Branch Coverage (%) - did this if/case take all paths?"""
|
|
88
|
+
condition_expression: float | None
|
|
89
|
+
"""Condition/Expression Coverage (%) - did the logic evaluate to 0 & 1?"""
|
|
90
|
+
toggle: float | None
|
|
91
|
+
"""Toggle Coverage (%) - did the signal wiggle?"""
|
|
92
|
+
fsm: float | None
|
|
93
|
+
"""FSM Coverage (%) - did the state machine transition?"""
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def average(self) -> float | None:
|
|
97
|
+
"""Average code coverage (%)."""
|
|
98
|
+
all_cov = [
|
|
99
|
+
c
|
|
100
|
+
for c in [
|
|
101
|
+
self.line_statement,
|
|
102
|
+
self.branch,
|
|
103
|
+
self.condition_expression,
|
|
104
|
+
self.toggle,
|
|
105
|
+
self.fsm,
|
|
106
|
+
]
|
|
107
|
+
if c is not None
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
if len(all_cov) == 0:
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
return sum(all_cov) / len(all_cov)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class CoverageMetrics(BaseModel):
|
|
117
|
+
"""Coverage metrics."""
|
|
118
|
+
|
|
119
|
+
code: CodeCoverageMetrics | None
|
|
120
|
+
"""Code Coverage."""
|
|
121
|
+
assertion: float | None
|
|
122
|
+
"""Assertion Coverage."""
|
|
123
|
+
functional: float | None
|
|
124
|
+
"""Functional coverage."""
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def average(self) -> float | None:
|
|
128
|
+
"""Average code coverage (%) or None if there is no coverage."""
|
|
129
|
+
code = self.code.average if self.code is not None else None
|
|
130
|
+
all_cov = [
|
|
131
|
+
c
|
|
132
|
+
for c in [
|
|
133
|
+
code,
|
|
134
|
+
self.assertion,
|
|
135
|
+
self.functional,
|
|
136
|
+
]
|
|
137
|
+
if c is not None
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
if len(all_cov) == 0:
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
return sum(all_cov) / len(all_cov)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class FlowResults(BaseModel):
|
|
147
|
+
"""Flow results data."""
|
|
148
|
+
|
|
149
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
150
|
+
|
|
151
|
+
block: IPMeta
|
|
152
|
+
"""IP block metadata."""
|
|
153
|
+
tool: ToolMeta
|
|
154
|
+
"""Tool used in the simulation run."""
|
|
155
|
+
timestamp: datetime
|
|
156
|
+
"""Timestamp for when the test ran."""
|
|
157
|
+
|
|
158
|
+
stages: Mapping[str, TestStage]
|
|
159
|
+
"""Results per test stage."""
|
|
160
|
+
coverage: CoverageMetrics | None
|
|
161
|
+
"""Coverage metrics."""
|
|
162
|
+
|
|
163
|
+
failed_jobs: BucketedFailures
|
|
164
|
+
"""Bucketed failed job overview."""
|
|
165
|
+
|
|
166
|
+
passed: int
|
|
167
|
+
"""Number of tests passed."""
|
|
168
|
+
total: int
|
|
169
|
+
"""Total number of tests run."""
|
|
170
|
+
percent: float
|
|
171
|
+
"""Percentage test pass rate."""
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
def load(path: Path) -> "FlowResults":
|
|
175
|
+
"""Load results from JSON file.
|
|
176
|
+
|
|
177
|
+
Transform the fields of the loaded JSON into a more useful schema for
|
|
178
|
+
report generation.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
path: to the json file to load.
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
return FlowResults.model_validate_json(path.read_text())
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class SimFlowResults(BaseModel):
|
|
188
|
+
"""Flow results data."""
|
|
189
|
+
|
|
190
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
191
|
+
|
|
192
|
+
block: IPMeta
|
|
193
|
+
"""IP block metadata."""
|
|
194
|
+
tool: ToolMeta
|
|
195
|
+
"""Tool used in the simulation run."""
|
|
196
|
+
timestamp: datetime
|
|
197
|
+
"""Timestamp for when the test ran."""
|
|
198
|
+
|
|
199
|
+
stages: Mapping[str, TestStage]
|
|
200
|
+
"""Results per test stage."""
|
|
201
|
+
coverage: CoverageMetrics | None
|
|
202
|
+
"""Coverage metrics."""
|
|
203
|
+
|
|
204
|
+
failed_jobs: BucketedFailures
|
|
205
|
+
"""Bucketed failed job overview."""
|
|
206
|
+
|
|
207
|
+
passed: int
|
|
208
|
+
"""Number of tests passed."""
|
|
209
|
+
total: int
|
|
210
|
+
"""Total number of tests run."""
|
|
211
|
+
percent: float
|
|
212
|
+
"""Percentage test pass rate."""
|
|
213
|
+
|
|
214
|
+
@staticmethod
|
|
215
|
+
def load(path: Path) -> "FlowResults":
|
|
216
|
+
"""Load results from JSON file.
|
|
217
|
+
|
|
218
|
+
Transform the fields of the loaded JSON into a more useful schema for
|
|
219
|
+
report generation.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
path: to the json file to load.
|
|
223
|
+
|
|
224
|
+
"""
|
|
225
|
+
return FlowResults.model_validate_json(path.read_text())
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class SimResultsSummary(BaseModel):
|
|
229
|
+
"""Summary of results."""
|
|
230
|
+
|
|
231
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
232
|
+
|
|
233
|
+
top: IPMeta
|
|
234
|
+
"""Meta data for the top level config."""
|
|
235
|
+
|
|
236
|
+
timestamp: datetime
|
|
237
|
+
"""Run time stamp."""
|
|
238
|
+
|
|
239
|
+
flow_results: Mapping[str, SimFlowResults]
|
|
240
|
+
"""Flow results."""
|
|
241
|
+
|
|
242
|
+
report_path: Path
|
|
243
|
+
"""Path to the report JSON file."""
|
|
244
|
+
|
|
245
|
+
@staticmethod
|
|
246
|
+
def load(path: Path) -> "SimResultsSummary":
|
|
247
|
+
"""Load results from JSON file.
|
|
248
|
+
|
|
249
|
+
Transform the fields of the loaded JSON into a more useful schema for
|
|
250
|
+
report generation.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
path: to the json file to load.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
The loaded ResultsSummary from JSON.
|
|
257
|
+
|
|
258
|
+
"""
|
|
259
|
+
return SimResultsSummary.model_validate_json(path.read_text())
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import fnmatch
|
|
8
8
|
import sys
|
|
9
9
|
from collections import OrderedDict, defaultdict
|
|
10
|
-
from collections.abc import Sequence
|
|
10
|
+
from collections.abc import Mapping, Sequence
|
|
11
11
|
from datetime import datetime, timezone
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import ClassVar
|
|
@@ -25,12 +25,24 @@ from dvsim.job.deploy import (
|
|
|
25
25
|
from dvsim.logging import log
|
|
26
26
|
from dvsim.modes import BuildMode, Mode, RunMode, find_mode
|
|
27
27
|
from dvsim.regression import Regression
|
|
28
|
-
from dvsim.
|
|
28
|
+
from dvsim.sim.data import (
|
|
29
|
+
IPMeta,
|
|
30
|
+
SimFlowResults,
|
|
31
|
+
SimResultsSummary,
|
|
32
|
+
Testpoint,
|
|
33
|
+
TestResult,
|
|
34
|
+
TestStage,
|
|
35
|
+
ToolMeta,
|
|
36
|
+
)
|
|
37
|
+
from dvsim.sim.report import gen_block_report, gen_reports
|
|
29
38
|
from dvsim.sim_results import BucketedFailures, SimResults
|
|
30
39
|
from dvsim.test import Test
|
|
31
40
|
from dvsim.testplan import Testplan
|
|
32
41
|
from dvsim.tool.utils import get_sim_tool_plugin
|
|
33
42
|
from dvsim.utils import TS_FORMAT, rm_path
|
|
43
|
+
from dvsim.utils.git import git_commit_hash
|
|
44
|
+
|
|
45
|
+
__all__ = ("SimCfg",)
|
|
34
46
|
|
|
35
47
|
# This affects the bucketizer failure report.
|
|
36
48
|
_MAX_UNIQUE_TESTS = 5
|
|
@@ -574,13 +586,83 @@ class SimCfg(FlowCfg):
|
|
|
574
586
|
for item in self.cfgs:
|
|
575
587
|
item._cov_unr()
|
|
576
588
|
|
|
589
|
+
def gen_results(self, results: Sequence[CompletedJobStatus]) -> None:
|
|
590
|
+
"""Generate flow results.
|
|
591
|
+
|
|
592
|
+
Args:
|
|
593
|
+
results: completed job status objects.
|
|
594
|
+
|
|
595
|
+
"""
|
|
596
|
+
reports_dir = Path(self.scratch_base_path) / "reports"
|
|
597
|
+
commit = git_commit_hash(path=Path(self.proj_root))
|
|
598
|
+
url = f"https://github.com/lowrisc/opentitan/tree/{commit}"
|
|
599
|
+
|
|
600
|
+
all_flow_results: Mapping[str, SimFlowResults] = {}
|
|
601
|
+
|
|
602
|
+
for item in self.cfgs:
|
|
603
|
+
item_results = [
|
|
604
|
+
res
|
|
605
|
+
for res in results
|
|
606
|
+
if res.block.name == item.name and res.block.variant == item.variant
|
|
607
|
+
]
|
|
608
|
+
|
|
609
|
+
flow_results: SimFlowResults = item._gen_json_results(
|
|
610
|
+
run_results=item_results,
|
|
611
|
+
commit=commit,
|
|
612
|
+
url=url,
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
# Convert to lowercase to match filename
|
|
616
|
+
block_result_index = (
|
|
617
|
+
f"{item.name}_{item.variant}" if item.variant else item.name
|
|
618
|
+
).lower()
|
|
619
|
+
|
|
620
|
+
all_flow_results[block_result_index] = flow_results
|
|
621
|
+
|
|
622
|
+
# Generate the block's JSON/HTML reports to the report area.
|
|
623
|
+
gen_block_report(
|
|
624
|
+
results=flow_results,
|
|
625
|
+
path=reports_dir,
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
self.errors_seen |= item.errors_seen
|
|
629
|
+
|
|
630
|
+
if self.is_primary_cfg:
|
|
631
|
+
# The timestamp for this run has been taken with `utcnow()` and is
|
|
632
|
+
# stored in a custom format. Store it in standard ISO format with
|
|
633
|
+
# explicit timezone annotation.
|
|
634
|
+
timestamp = (
|
|
635
|
+
datetime.strptime(self.timestamp, "%Y%m%d_%H%M%S")
|
|
636
|
+
.replace(tzinfo=timezone.utc)
|
|
637
|
+
.isoformat()
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
results_summary = SimResultsSummary(
|
|
641
|
+
top=IPMeta(
|
|
642
|
+
name=self.name,
|
|
643
|
+
variant=self.variant,
|
|
644
|
+
commit=commit,
|
|
645
|
+
branch=self.branch,
|
|
646
|
+
url=url,
|
|
647
|
+
),
|
|
648
|
+
timestamp=timestamp,
|
|
649
|
+
flow_results=all_flow_results,
|
|
650
|
+
report_path=reports_dir,
|
|
651
|
+
)
|
|
652
|
+
|
|
653
|
+
# Generate all the JSON/HTML reports to the report area.
|
|
654
|
+
gen_reports(
|
|
655
|
+
summary=results_summary,
|
|
656
|
+
path=reports_dir,
|
|
657
|
+
)
|
|
658
|
+
|
|
577
659
|
def _gen_json_results(
|
|
578
660
|
self,
|
|
579
661
|
run_results: Sequence[CompletedJobStatus],
|
|
580
662
|
commit: str,
|
|
581
663
|
url: str,
|
|
582
|
-
) ->
|
|
583
|
-
"""Generate structured
|
|
664
|
+
) -> SimFlowResults:
|
|
665
|
+
"""Generate structured SimFlowResults from simulation run data.
|
|
584
666
|
|
|
585
667
|
Args:
|
|
586
668
|
run_results: completed job status.
|
|
@@ -700,7 +782,7 @@ class SimCfg(FlowCfg):
|
|
|
700
782
|
failures = BucketedFailures.from_job_status(results=run_results)
|
|
701
783
|
|
|
702
784
|
# --- Final result ---
|
|
703
|
-
return
|
|
785
|
+
return SimFlowResults(
|
|
704
786
|
block=block,
|
|
705
787
|
tool=tool,
|
|
706
788
|
timestamp=timestamp,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
9
|
from dvsim.logging import log
|
|
10
|
-
from dvsim.
|
|
10
|
+
from dvsim.sim.data import SimFlowResults, SimResultsSummary
|
|
11
11
|
from dvsim.templates.render import render_static, render_template
|
|
12
12
|
|
|
13
13
|
__all__ = (
|
|
@@ -17,7 +17,7 @@ __all__ = (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def gen_block_report(results:
|
|
20
|
+
def gen_block_report(results: SimFlowResults, path: Path) -> None:
|
|
21
21
|
"""Generate a block report.
|
|
22
22
|
|
|
23
23
|
Args:
|
|
@@ -47,7 +47,7 @@ def gen_block_report(results: FlowResults, path: Path) -> None:
|
|
|
47
47
|
)
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
def gen_summary_report(summary:
|
|
50
|
+
def gen_summary_report(summary: SimResultsSummary, path: Path) -> None:
|
|
51
51
|
"""Generate a summary report.
|
|
52
52
|
|
|
53
53
|
Args:
|
|
@@ -88,7 +88,7 @@ def gen_summary_report(summary: ResultsSummary, path: Path) -> None:
|
|
|
88
88
|
)
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
def gen_reports(summary:
|
|
91
|
+
def gen_reports(summary: SimResultsSummary, path: Path) -> None:
|
|
92
92
|
"""Generate a full set of reports for the given regression run.
|
|
93
93
|
|
|
94
94
|
Args:
|
dvsim/{tool → sim/tool}/vcs.py
RENAMED
|
@@ -9,7 +9,7 @@ from collections import OrderedDict
|
|
|
9
9
|
from collections.abc import Mapping, Sequence
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
-
from dvsim.
|
|
12
|
+
from dvsim.sim.data import CodeCoverageMetrics, CoverageMetrics
|
|
13
13
|
|
|
14
14
|
__all__ = ("Xcelium",)
|
|
15
15
|
|
dvsim/templates/render.py
CHANGED
|
@@ -10,6 +10,7 @@ DVSim. Templates can be referenced relative to this directory.
|
|
|
10
10
|
|
|
11
11
|
from collections.abc import Mapping
|
|
12
12
|
from importlib import resources
|
|
13
|
+
from pathlib import Path
|
|
13
14
|
|
|
14
15
|
from jinja2 import Environment, PackageLoader, select_autoescape
|
|
15
16
|
|
|
@@ -28,9 +29,11 @@ def render_static(path: str) -> str:
|
|
|
28
29
|
string containing the static file content
|
|
29
30
|
|
|
30
31
|
"""
|
|
32
|
+
full_path = Path("dvsim/templates/static") / path
|
|
33
|
+
|
|
31
34
|
return resources.read_text(
|
|
32
|
-
"
|
|
33
|
-
|
|
35
|
+
".".join(full_path.parts[:-1]), # Module path
|
|
36
|
+
full_path.name,
|
|
34
37
|
)
|
|
35
38
|
|
|
36
39
|
|
dvsim/tool/utils.py
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"""EDA Tool base."""
|
|
6
6
|
|
|
7
7
|
from dvsim.logging import log
|
|
8
|
-
from dvsim.tool.
|
|
9
|
-
from dvsim.tool.vcs import VCS
|
|
10
|
-
from dvsim.tool.xcelium import Xcelium
|
|
8
|
+
from dvsim.sim.tool.base import SimTool
|
|
9
|
+
from dvsim.sim.tool.vcs import VCS
|
|
10
|
+
from dvsim.sim.tool.xcelium import Xcelium
|
|
11
11
|
|
|
12
12
|
__all__ = ("get_sim_tool_plugin",)
|
|
13
13
|
|
|
@@ -10,29 +10,28 @@ dvsim/test.py,sha256=lMTieXHFIGEYQRJGJFsh_cP4bZ1_EadUolRWzIVmBvs,5610
|
|
|
10
10
|
dvsim/testplan.py,sha256=Qhne2FqlU8R9UGB5o3QOufMVh1xdbKFMhtLvjvyGyts,28389
|
|
11
11
|
dvsim/testplanner.py,sha256=kvgb6iAbmfaKmOLem1crKm49eygvOQX1q79Jv5UAHe0,1326
|
|
12
12
|
dvsim/cli/__init__.py,sha256=vggha7pCXj7dUK4VZChIR37MhKONBcJqt3j8l9xKM_U,238
|
|
13
|
-
dvsim/cli/admin.py,sha256=
|
|
13
|
+
dvsim/cli/admin.py,sha256=bBnz0ZX1gd8RBTLd4CB3ZFvm08ayIjUUszI-rauxIK4,1182
|
|
14
14
|
dvsim/cli/run.py,sha256=_S6ejDxGRyxMYKgNreCH6CC7vLFoJFRPmnCTPqQ6PBc,27968
|
|
15
15
|
dvsim/examples/testplanner/common_testplan.hjson,sha256=IDkf3AYleDdbuEarj8FItBhg5lMgoVrfgnAMzTU9_IM,806
|
|
16
16
|
dvsim/examples/testplanner/foo_dv_doc.md,sha256=AZkreUFyAehr2-6xh6Z7eRo4Eok9HFUH4TrDnByDor0,331
|
|
17
17
|
dvsim/examples/testplanner/foo_sim_results.hjson,sha256=WAx9FIwS11oybfw1BU7AmY_14tRDXWtoLBxAL0ZDh8I,1642
|
|
18
18
|
dvsim/examples/testplanner/foo_testplan.hjson,sha256=QQs4Egu77svReT9N3pIBSDP-xWCqoicQCo4Y_2-ZybA,2307
|
|
19
19
|
dvsim/flow/__init__.py,sha256=K6yruWpqvtuLCORlnTspPxwBjsIpQhMaCfQSqqtyvTQ,185
|
|
20
|
-
dvsim/flow/base.py,sha256=
|
|
20
|
+
dvsim/flow/base.py,sha256=2Ac15oc3rDpnAFlaKabLOMSOGwyi9ReVTd9zdeoLcgs,16602
|
|
21
21
|
dvsim/flow/cdc.py,sha256=87aDKAsHNDnFs4dRkclQSJ5-Pm_djY8BlSR-nzcPAMY,558
|
|
22
|
-
dvsim/flow/factory.py,sha256=
|
|
22
|
+
dvsim/flow/factory.py,sha256=Wtp3o87vqbGzZwku4I2zxAizEMzNyZRgDwgj7aWjw4U,3862
|
|
23
23
|
dvsim/flow/formal.py,sha256=DVu-MkKJP-bJrfskXBIfqnL_sQTbqbDRuNiLv9_QQ2E,9935
|
|
24
24
|
dvsim/flow/hjson.py,sha256=iKR8gAHZl1XsYNkTPaePwKSkAcPgqO8BlKNBs4ER3XY,6483
|
|
25
|
-
dvsim/flow/lint.py,sha256=
|
|
26
|
-
dvsim/flow/one_shot.py,sha256=
|
|
25
|
+
dvsim/flow/lint.py,sha256=YeLR8eegChWWkJj-jMtzqZp6VWN8grbuxz4kclaN9us,7063
|
|
26
|
+
dvsim/flow/one_shot.py,sha256=qtbqQvql_VMoO33lfEz9qM7aGpr_CKSG4nXA1gbooBQ,6772
|
|
27
27
|
dvsim/flow/rdc.py,sha256=pu7GKw-eNd3RXdhq6oFKidBOflMtr1joAokS3SosTi4,562
|
|
28
|
-
dvsim/flow/sim.py,sha256=iHGrJvz321WBPetGZWq_tXACRW0R8wHaVHt_Ea1E8kg,28009
|
|
29
28
|
dvsim/flow/syn.py,sha256=LnwDM6dUhxNXRoTcUCbESZ2VCpBYEFdfuur3jsojejQ,15996
|
|
30
29
|
dvsim/job/__init__.py,sha256=EtF6aoKkGy3sxCsfQMm2MAHgjYknmI1No90xvyjXRpY,186
|
|
31
30
|
dvsim/job/data.py,sha256=dsc4bnAvTMW74m8QItCGMKJTyXa50fjTWngPtkw2lUc,4460
|
|
32
|
-
dvsim/job/deploy.py,sha256=
|
|
31
|
+
dvsim/job/deploy.py,sha256=Ec5pmsGOtxGnwcAq4qh7b2B6URjlejyf6jLNwZo_aVg,31477
|
|
33
32
|
dvsim/job/time.py,sha256=RLQn16cIEGRKmRf5bQC1h1P8SaSBAIjvynyDyYrKUrY,5369
|
|
34
33
|
dvsim/launcher/__init__.py,sha256=P-A-eAsx-3Nz4b3mnautm9fGV02qVelwBrNX_PGfOUw,188
|
|
35
|
-
dvsim/launcher/base.py,sha256=
|
|
34
|
+
dvsim/launcher/base.py,sha256=TitiE4BTTkg0hcT-cKL9neYD6oudZXC0FpOGN_WpTfM,15027
|
|
36
35
|
dvsim/launcher/factory.py,sha256=zs4bJ4n2TeWbbVk1IRXAazC5viNg4mPUITofP0fqHEc,2620
|
|
37
36
|
dvsim/launcher/fake.py,sha256=ODtwNOzgaGYklPQPy3J69uWOlWbMGUw67sAmWQoENHQ,2426
|
|
38
37
|
dvsim/launcher/local.py,sha256=eoCYkmkm-uS-zezVn4oRp7OuTwCnWr20ewtUFnxFmg8,6816
|
|
@@ -46,10 +45,17 @@ dvsim/launcher/sge/qsubopts.py,sha256=RxjgULUI_JDrdsn1VxQnBSxW0Z-4nfzP8w6l9x3tm6
|
|
|
46
45
|
dvsim/linting/__init__.py,sha256=SOXGwiOyg_dBPIHSFwctNLKk2M84jXpDpZjjGyPmcPA,183
|
|
47
46
|
dvsim/linting/parser.py,sha256=19o4F5YTh43u1s9Hx7nPeGujYgo61v44JHpPiy-e-Hw,3722
|
|
48
47
|
dvsim/report/__init__.py,sha256=m58UrZ_U3jKI0QlB3r6cGdRb-QfgzN7t0udJpYa2DMs,196
|
|
49
|
-
dvsim/report/data.py,sha256=
|
|
50
|
-
dvsim/
|
|
48
|
+
dvsim/report/data.py,sha256=Li_FSIPT7yEdF5buLLEbx7DnTX3eHf1UZ5aBHk6C5Es,935
|
|
49
|
+
dvsim/sim/__init__.py,sha256=XU7GhNkaQxhHqsO_P5XDXnWURcT27iScKg630EQLJ40,195
|
|
50
|
+
dvsim/sim/data.py,sha256=J1PkWk2ivFZm0FLUmLexGb3KAAhgnT51KDE6oZ1FqNM,6369
|
|
51
|
+
dvsim/sim/flow.py,sha256=h1-zgd3_yGhODwD0EcKoknGU8xeVeWMb3uc1apQ1YI8,30552
|
|
52
|
+
dvsim/sim/report.py,sha256=ljpmFu_ln3plZyhNs2X2_xkRFqERk5Txhn_zXvFl4fU,2646
|
|
53
|
+
dvsim/sim/tool/__init__.py,sha256=VCe2PQYQUkthjXjbSVSxNALwO1t0Y6mVW6eszl_JtW4,192
|
|
54
|
+
dvsim/sim/tool/base.py,sha256=HQJDapJQEf6GsPGJPDsNpNA4omk7i0CqzzxT27-ytjk,2573
|
|
55
|
+
dvsim/sim/tool/vcs.py,sha256=qRxvr8KVaNJrcshPqpbwhCuyKq8o7dbb3X4cHh8wYSo,4813
|
|
56
|
+
dvsim/sim/tool/xcelium.py,sha256=z_fbSODH7IGI-5ivZQ1WPlideY9Qo2OcMra0HlJNpOM,6155
|
|
51
57
|
dvsim/templates/__init__.py,sha256=vZhkgLLCkdOPjOK_wGaa2AqDLs2fZLuc3_TJK62ttA8,195
|
|
52
|
-
dvsim/templates/render.py,sha256=
|
|
58
|
+
dvsim/templates/render.py,sha256=uAc798QYvZJBugTl53XFz1nft8ZK_YFsyIK0oQWWErQ,1582
|
|
53
59
|
dvsim/templates/reports/__init__.py,sha256=eu0aBRe908Or6yAc4K61fuxUx-48lhjqBpsslUtn5Z8,192
|
|
54
60
|
dvsim/templates/reports/block_report.html,sha256=3gP-v3uS2jpmgBjqS9UvSiQu6PZ4khAf9relJJZL1qo,9768
|
|
55
61
|
dvsim/templates/reports/redirect.html,sha256=nGUoYTSrNiVXWXpluFMoHjdP5QldtEXeZMGd6Y2rPzc,593
|
|
@@ -62,11 +68,8 @@ dvsim/templates/static/js/htmx.min.js,sha256=Iig-9oy3VFkU8KiKG97cclanA9HVgMHSVSF
|
|
|
62
68
|
dvsim/tool/__init__.py,sha256=Y8HxxxI8UTJGDg07FFytr1pVujdBsbtHulthnEOZHcI,197
|
|
63
69
|
dvsim/tool/ascentlint.py,sha256=reBueV8vqEgwwmcbBNncVM4Z4fAFqxqRzLv5rVgcCh8,4047
|
|
64
70
|
dvsim/tool/meridianrdc.py,sha256=RKAhQ5Rk6SfSc3DurZTQJP36qSpSAIej42plGq5ApL0,9675
|
|
65
|
-
dvsim/tool/
|
|
66
|
-
dvsim/tool/utils.py,sha256=bBK-y1PjTzuOBoEUsCjW7XcAkHKd5fcXFWGv9060ktI,834
|
|
67
|
-
dvsim/tool/vcs.py,sha256=G1J8N_8xQ0VHDGle16RtVhcTCanOYPtTol4rlOAs34E,4816
|
|
71
|
+
dvsim/tool/utils.py,sha256=lxLO1f0DdeATzW1XMQuJfzKOLVrmpyTD9lmgAmZM5U4,847
|
|
68
72
|
dvsim/tool/verilator.py,sha256=MQykIh1Ua7PcCHmwxLaieuDx43B48bNWrJ_oviVHtQs,3655
|
|
69
|
-
dvsim/tool/xcelium.py,sha256=T0X3H6_DP34jmi6IKha6S3LLbtnP9rt0qybljmcu_dk,6158
|
|
70
73
|
dvsim/utils/__init__.py,sha256=UYFviDvztoGOBA6btN9xBCwRhaaagK45X4M0Kc1xQwU,1102
|
|
71
74
|
dvsim/utils/check.py,sha256=b8bu_0zJHk4ieD5erlGfaG2F1GiDwadAvqB6kW4mOsU,994
|
|
72
75
|
dvsim/utils/fs.py,sha256=NqPmnRlP8l2l1Cy3nAkLsPvEn_o2yQavP5dsUanQ_ZU,3859
|
|
@@ -77,8 +80,8 @@ dvsim/utils/status_printer.py,sha256=azwNWS83rI-h7OfOYPIj-Sy46aIz35L3y_Yiwkx60ZE
|
|
|
77
80
|
dvsim/utils/subprocess.py,sha256=8jje9hmwZ_JH0zQ8JNwhsNldntgI3_SF6L5SUHQ9luo,1829
|
|
78
81
|
dvsim/utils/timer.py,sha256=jD4R3wB_rBxaefiMr-k34aH325xdcoqtHHRCtSczSC8,1604
|
|
79
82
|
dvsim/utils/wildcards.py,sha256=5WkByZLHyPlo5lD4rIXPuDjjrhrWqNpcTYxmQ5k294o,11701
|
|
80
|
-
dvsim-1.7.
|
|
81
|
-
dvsim-1.7.
|
|
82
|
-
dvsim-1.7.
|
|
83
|
-
dvsim-1.7.
|
|
84
|
-
dvsim-1.7.
|
|
83
|
+
dvsim-1.7.2.dist-info/METADATA,sha256=Mpw4nSelVLJwKDLZjhN6NW26vtic8yVcbH1mNyxARFM,5882
|
|
84
|
+
dvsim-1.7.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
85
|
+
dvsim-1.7.2.dist-info/entry_points.txt,sha256=6A-YOJ6XYbedSfSJ5dP56lRkoHYrLanJt0AYNH9w3r0,75
|
|
86
|
+
dvsim-1.7.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
87
|
+
dvsim-1.7.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|