blob: 5139cd1411f8f99d09edca4cfaa2a540c0912212 [file] [log] [blame] [view]
Srikrishna Iyer86169d02021-05-10 09:35:52 -07001---
2title: "Testplanner tool"
3---
4
5`testplanner` is a Python based tool for parsing testplans written in Hjson format into a data structure that can be used for:
6* Expanding the testplan inline within the DV document as a table;
7* Annotating the simulation results with testplan entries for a document driven DV execution;
8
9Please see [DV methodology]({{< relref "doc/ug/dv_methodology/index.md#documentation" >}}) for more details on the rationale and motivation for writing and maintaining testplans in a machine-parsable format (`Hjson`).
10This document will focus on the anatomy of an Hjson testplan, the list of features supported and some of the ways of using the tool.
11
12## Hjson testplan
13
14A testplan consists of a list of planned tests (testpoints) and a list of planned functional coverage items (covergroups).
15
16### Testpoints
17
18A testpoint is an entry in the testplan representing a planned test.
19Each testpoint maps one-to-one to a unique feature of the design.
20Additionally, a testpoint for each of the [key areas of focus]({{< relref "doc/ug/dv_methodology/index.md#key-test-focus-areas" >}}) (whichever ones are applicable) is also captured in the testplan.
21
22The following attributes are used to define each testpoint, at minimum:
23* **name: testpoint name**
24
25 This is a single `lower_snake_case` string that succinctly describes the intended feature being tested.
26 As an example, a smoke test, which is typically the first test written for a new testbench would simply be called `smoke`.
27 A testpoint that focuses on erasing a page within a `flash_ctrl` bank would be called `page_erase`.
28 The recommended naming convention to follow is `<main_feature>_<sub_feature>_<sub_sub_feature_or_type>_...`.
29 This is no need to suffix (or prefix) the testpoint name with "test".
30
31* **milestone: targeted verification milestone**
32
Srikrishna Iyerd0ff7c02021-10-05 21:52:11 -070033 This is either `V1`, `V2`, `V2S` or `V3`.
Srikrishna Iyer86169d02021-05-10 09:35:52 -070034 It helps us track whether all of the testing requirements of a milestone have been achieved.
35
36* **desc: testpoint description**
37
38 A multi-line string that briefly describes the intent of the test.
39 It is recommended, but not always necessary to add a high level goal, stimulus, and the checking procedure so that the reader gets a clear idea of what and how the said feature is going to be tested.
40
41 Full [Markdown]({{< relref "doc/rm/markdown_usage_style" >}}) syntax is supported when writing the description.
42
43* **tests: list of written test(s) for a testpoint**
44
45 The testplan is written in the initial work stage of the verification [life-cycle]({{< relref "doc/project/development_stages#hardware-verification-stages" >}}).
46 Later, when the DV engineer writes the tests, they may not map one-to-one to a testpoint - it may be possible that a written test satisfactorilly addresses multiple testpoints; OR it may also be possible that a testpoint needs to be split into multiple smaller tests.
47 To cater to these needs, we provide the ability to set a list of written tests for each testpoint.
48 It is used to not only indicate the current progress so far into each milestone, but also map the simulation results to the testpoints to generate the final report table.
49 This list is initially empty - it is gradually updated as tests are written.
50
51If the need arises, more attributes may be added relatively easily.
52
53Testpoints are added to the testplan using the `testpoints` key.
54Here's an example:
55```hjson
56 testpoints: [
57 {
58 name: feature1
59 milestone: V1
60 desc: '''**Goal**: High level goal of this test.
61
62 **Stimulus**: Describe the stimulus procedure.
63
64 **Check**: Describe the checking procedure.'''
65 tests: ["foo_feature1"]
66 }
67 {
68 name: feature2
69 milestone: V2
70 desc: '''**Goal**: High level goal of this test.
71
72 **Stimulus**: Describe the stimulus procedure.
73
74 **Check**: Describe the checking procedure.'''
75
76 // Below is the list of written (runnable) tests that maps to `feature2`.
77 // To satisfactorilly test `feature2`, three tests are written. There
78 // could be various reasons to split the written test, the most common
79 // being unacceptably long runtime.
80 tests: ["foo_feature2_test1",
81 "foo_feature2_test2",
82 "foo_feature2_test3"]
83 }
84 ...
85 ]
86```
87
88### Covergroups
89
90A list of covergroups documented in the testplan represents the functional coverage plan for the design.
91
92The following attributes are used to define each covergroup:
93* **name: name of the covergroup**
94
95 This is a single `lower_snake_case` string that succinctly describes the covergroup.
96 It needs to map to the actual written covergroup, so that it can be audited from the simulation results for tracking.
97 As indicated in our DV style guide, the covergroup name is suffixed with `_cg`.
98
99* **desc: description of the covergroup**
100
101 A multi-line string that briefly describes what functionality is captured by the covergroup.
102 It is recommended, but not necessary to list the individual coverpoints and crosses to ease the review.
103
104Covergroups are added to the testplan using the `covergroups` key.
105Here's an example:
106```hjson
107 covergroups: [
108 {
109 name: timer_cg
110 desc: '''Cover various combinations of rv_timer inputs when generating a
111 timeout. Cover appropriate ranges of values of step and prescaler
112 as coverpoint buckets and cross them with each other.
113 '''
114 }
115 ...
116 ]
117```
118### Import shared testplans
119
120Typically, there are tests that are common to more than one testbench and can be made a part of a 'shared' testplan that each DUT testplan can simply import.
121An example of this is running the automated UVM RAL CSR tests, which applies to almost all DUTs.
122This is achieved using the `import_testplans` key:
123```hjson
124 import_testplans: ["util/dvsim/examples/testplanner/common_testplan.hjson",
125 "hw/dv/tools/csr_testplan.hjson"]
126```
127
128Note that the paths to common testplans are relative to `$REPO_TOP`.
129
130For the sake of discussion below, we will refer to the 'main' or DUT testplan as the 'DUT' testplan and the shared testplans it imports as 'shared' or 'imported' testplans.
131
132The imported testplans actually present a problem: how can the written tests that map to the shared testpoint be generic enough that they apply to multiple DUTs?
133We currently solve this by providing substitution wildcards.
134These are single `lower_snake_case` strings indicated within braces `'{..}'`.
135A substitution value (or list of values) for the wildcard string is optionally provided in the DUT testplan.
136
137Here's an example:
138```hjson
139-------
140 // UART testplan:
141 name: uart
142
143-------
144 // Imported testplan:
145 {
146 name: csr
147 ...
148 tests: ["{name}{intf}_csr_hw_reset"]
149 }
150```
151
152In the example above, `{name}` and `{intf}` are wildcards used in the shared testplan for which substitution values are to be provided in the DUT testplan.
153When the tool parses the DUT testplan along with its imported testplans, it replaces the wildcards with its substitution values found in the DUT testplan.
154If a substitution is not available, the wildcard is replaced with an empty string.
155In the example above, the list of written tests resolves to `["uart_csr_hw_reset"]` after substituting `{name}` with `uart` and `{intf}` with an empty string.
156As many wildcards as needed can be added to tests in the shared testplans to support the various usecases across different testbenches.
157Also, the substitution value can be a list of strings, in which case, the list of written tests expands to all possible combinations of values.
158
159Here's an example:
160```hjson
161-------
162 // Chip testplan:
163 name: chip
164 intf: ["", "_jtag"]
165 foo: ["x", "y", "z"]
166
167-------
168 // Imported testplan:
169 {
170 name: csr
171 ...
172 tests: ["{name}{intf}_csr_hw_reset_{foo}"]
173 }
174```
175
176This will resolve to the following 6 tests:
177
178```
179["chip_csr_hw_reset_x", "chip_csr_hw_reset_y", "chip_csr_hw_reset_z",
180 "chip_jtag_csr_hw_reset_x", "chip_jtag_csr_hw_reset_y", "chip_jtag_csr_hw_reset_z"]
181```
182
183### Example sources
184
185The following examples provided within `util/dvsim/examples/testplanner` can be used as a starting point.
186* **`foo_testplan.hjson`**: DUT testplan
187* **`common_testplan.hjson`**: shared testplan imported within the DUT testplan
188* **`foo_dv_doc.md`**: DUT testplan imported within the DV document doc in Markdown
189
190In addition, see the [UART DV document]({{< relref "hw/ip/uart/doc/dv" >}}) for a 'production' example of inline expansion of an imported testplan as a table within the DV document.
191The [UART testplan](https://github.com/lowRISC/opentitan/blob/master/hw/ip/uart/data/uart_testplan.hjson) imports some of the shared testplans located at `hw/dv/tools/dvsim/testplans` area.
192
193### Limitations
194
195The following limitations currently hold:
196* Only the DUT testplan can import shared testplans; the imported testplans cannot further import more testplans.
197* All planned test names parsed from the DUT testplan and all of its imported testplans need to be unique.
198
199## Usage examples
200
201### Standalone tool invocations
202
203Generate the testplan table in HTML to stdout:
204```console
205$ cd $REPO_TOP
206$ ./util/dvsim/testplanner.py \
207 util/dvsim/examples/testplanner/foo_testplan.hjson
208```
209
210Generate the testplan table in HTML to a file:
211```console
212$ ./util/dvsim/testplanner.py \
213 util/dvsim/examples/testplanner/foo_testplan.hjson \
214 -o /tmp/foo_testplan_table.html
215```
216
217Generate simulation result tables in HTML to stdout:
218```console
219$ ./util/dvsim/testplanner.py \
220 util/dvsim/examples/testplanner/foo_testplan.hjson \
221 -s util/dvsim/examples/testplanner/foo_sim_results.hjson
222```
223
224Note that the simulations results HJson file used for mapping the results to the testplan is for illustration.
225`dvsim` does not generate such a file - it invokes the `Testplan` class APIs directly to map the simulation results.
226
227Generate simulation result tables in HTML to a file:
228```console
229$ ./util/dvsim/testplanner.py \
230 util/dvsim/examples/testplanner/foo_testplan.hjson \
231 -s util/dvsim/examples/testplanner/foo_sim_results.hjson \
232 -o /tmp/foo_sim_results.html
233```
234
235### APIs for external tools
236The `util/build_docs.py` script invokes the testplanner utility functions directly to parse the Hjson testplan and insert an HTML table within the DV document.
237This is done by invoking:
238```console
239$ ./util/build_docs.py --preview
240```
241The output for each testplan will be saved into `build/docs-generated`.
242For example the GPIO IP testplan is rendered into a table at `build/docs-generated/hw/ip/gpio/data/gpio_testplan.hjson.testplan`.
243The complete OpenTitan documentation is rendered locally at `https://localhost:1313`.
244
245The following snippet of code can be found in `util/build_docs.py`:
246```python
247from dvsim.Testplan import Testplan
248
249 # hjson_testplan_path: a string pointing to the path to Hjson testplan
250 testplan = Testplan(hjson_testplan_path)
251 text = testplan.get_testplan_table("html")
252```
253
254## Future work
255* Allow DUT and its imported testplans to have the same testpoint name as long as they are in separate files.
256 * The list of written tests are appended from both files.
257 * The descriptions are merged - its upto the user to ensure that it is still meaningful after the merge.
258 * Conflicting milestones are flagged as an error.