origen_testers 0.19.0 → 0.19.2
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.
- checksums.yaml +4 -4
- data/config/application.rb +34 -1
- data/config/version.rb +1 -1
- data/lib/origen_testers/flow.rb +1 -0
- data/lib/origen_testers/interface.rb +28 -0
- data/lib/origen_testers/pattern_compilers/v93k.rb +3 -1
- data/lib/origen_testers/smartest_based_tester/base.rb +14 -1
- data/lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb +10 -10
- data/lib/origen_testers/test/interface.rb +3 -0
- data/pattern/tester_overlay.rb +12 -1
- data/program/_erase.rb +1 -1
- data/program/components/_prb1_main.rb +3 -3
- data/program/test.rb +2 -2
- data/templates/origen_guides/pattern/common.md.erb +376 -0
- data/templates/origen_guides/pattern/creating.md.erb +133 -0
- data/templates/origen_guides/pattern/custom.md.erb +5 -0
- data/templates/origen_guides/pattern/documenting.md.erb +431 -0
- data/templates/origen_guides/pattern/introduction.md.erb +38 -0
- data/templates/origen_guides/pattern/j750.md.erb +10 -0
- data/templates/origen_guides/pattern/name.md.erb +511 -0
- data/templates/origen_guides/pattern/pins.md.erb +125 -0
- data/templates/origen_guides/pattern/registers.md.erb +300 -0
- data/templates/origen_guides/pattern/running.md.erb +105 -0
- data/templates/origen_guides/pattern/timing.md.erb +281 -0
- data/templates/origen_guides/pattern/ultraflex.md.erb +10 -0
- data/templates/origen_guides/pattern/v93k.md.erb +41 -0
- data/templates/origen_guides/program/code.md.erb +78 -0
- data/templates/origen_guides/program/custom.md.erb +5 -0
- data/templates/origen_guides/program/doc.md.erb +402 -0
- data/templates/origen_guides/program/flowapi.md.erb +249 -0
- data/templates/origen_guides/program/flows.md.erb +429 -0
- data/templates/origen_guides/program/generating.md.erb +97 -0
- data/templates/origen_guides/program/interface.md.erb +248 -0
- data/templates/origen_guides/program/introduction.md.erb +56 -0
- data/templates/origen_guides/program/j750.md.erb +514 -0
- data/templates/origen_guides/program/philosophy.md.erb +99 -0
- data/templates/origen_guides/program/resources.md.erb +141 -0
- data/templates/origen_guides/program/ultraflex.md.erb +5 -0
- data/templates/origen_guides/program/v93k.md.erb +456 -0
- data/templates/web/layouts/_guides.html.erb +10 -0
- data/templates/web/partials/_placeholder.md.erb +10 -0
- metadata +33 -5
@@ -0,0 +1,249 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
The runtime flow control of a test program is an area that can be particularly messy:
|
4
|
+
|
5
|
+
* Need to deal with different and often obscure vendor APIs
|
6
|
+
* It can be very hard to decipher both the intention and the actual behavior
|
7
|
+
during code reviews
|
8
|
+
* It is easy to make mistakes
|
9
|
+
* Mistakes can be costly - there have been many customer quality
|
10
|
+
incidents in the past from missed test caused by errors in flow control
|
11
|
+
|
12
|
+
To deal with these problems Origen provides a simple and intuitive API
|
13
|
+
to describe runtime flow logic:
|
14
|
+
|
15
|
+
* Generates legal and battle-tested code
|
16
|
+
* Takes care of cross-platform implementation
|
17
|
+
* Makes flow control easy to review
|
18
|
+
* Covers over gaps or weaknesses in the vendor APIs
|
19
|
+
|
20
|
+
Conditional tests fall into two categories:
|
21
|
+
|
22
|
+
* Those that will run based on the flow execution environment. For example based on
|
23
|
+
the job selected at runtime or on some enable flag that can be set by the user at
|
24
|
+
runtime.
|
25
|
+
* Those that will only run based on the outcome of another test - i.e. execute a given
|
26
|
+
test based on whether a previous test passed, failed or ran at all.
|
27
|
+
|
28
|
+
#### Execution Based on the Runtime Environment
|
29
|
+
|
30
|
+
The following methods are available to describe these cases:
|
31
|
+
|
32
|
+
* **if_enable / unless_enable** - Run the test if a flow runtime option is/is not enabled at runtime
|
33
|
+
* **if_job / unless_job** - Run based on the current job (P1, FR, QC, etc)
|
34
|
+
|
35
|
+
Here are some examples of how to apply these methods to single tests:
|
36
|
+
|
37
|
+
~~~ruby
|
38
|
+
# Run this test to characterize the vreg, only if the 'vreg_cz' flag has been enabled
|
39
|
+
para :vreg_meas, softbin: 107, cz: true, if_enable: "vreg_cz"
|
40
|
+
# Apply HVST to the vreg module, unless the 'skip_hvst' flag has been enabled
|
41
|
+
func :vreg_hvst, softbin: 101, hv: 10.V, vdd: :max, unless_enable: "skip_hvst"
|
42
|
+
# Run this test only at cold
|
43
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34V, if_job: "FC"
|
44
|
+
~~~
|
45
|
+
|
46
|
+
The use of `if/unless_enable` will make use of flow enable words on Teradyne platforms and user
|
47
|
+
flow variables on Advantest.
|
48
|
+
The `if/unless_job` control will make use of the job column on Teradyne platforms and a user
|
49
|
+
flow variable named `@JOB` on Advantest.
|
50
|
+
|
51
|
+
Both of these controls support a block form, which allows it to be applied to a group of test
|
52
|
+
and, in the case of enable words, it also provides a way to implement AND and OR logic:
|
53
|
+
|
54
|
+
~~~ruby
|
55
|
+
# OR - Run these tests if either word is set
|
56
|
+
if_enable [:word1, :word2] do
|
57
|
+
func: :test1
|
58
|
+
func: :test2
|
59
|
+
end
|
60
|
+
|
61
|
+
# AND - Run these tests if both words are set
|
62
|
+
if_enable :word1 do
|
63
|
+
if_enable :word2 do
|
64
|
+
func: :test1
|
65
|
+
func: :test2
|
66
|
+
end
|
67
|
+
end
|
68
|
+
~~~
|
69
|
+
|
70
|
+
#### Execution Based on a Previous Test
|
71
|
+
|
72
|
+
The following methods are available to describe these cases:
|
73
|
+
|
74
|
+
* **if_ran / unless_ran** - Run only if a previous test did or did not run
|
75
|
+
* **if_failed (unless_passed)** - Run only if a previous test failed
|
76
|
+
* **if_passed (unless_failed)** - Run only if a previous test passed
|
77
|
+
|
78
|
+
All of these methods require you to provide the ID of the previous test on which
|
79
|
+
the conditional execution will depend.
|
80
|
+
This ID must be assigned by you in the flow line of the previous test by adding
|
81
|
+
an `:id` key, like this:
|
82
|
+
|
83
|
+
~~~ruby
|
84
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34, id: :vreg_meas_1
|
85
|
+
~~~
|
86
|
+
|
87
|
+
The ID can be any value you like as long as it is unique, Origen will raise an error
|
88
|
+
if any duplicate IDs are encountered.
|
89
|
+
|
90
|
+
On the dependent tests the API is similar to the previous examples except the ID
|
91
|
+
of the previous test is given in place of the enable flag or job name.
|
92
|
+
Here are some examples:
|
93
|
+
|
94
|
+
~~~ruby
|
95
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34, id: :vreg_meas_1
|
96
|
+
# Automatically characterize the vreg if the measurement fails
|
97
|
+
para :vreg_meas, softbin: 107, cz: true, if_failed: :vreg_meas_1
|
98
|
+
# Then bin out
|
99
|
+
bin 3, softbin: 105, if_failed: :vreg_meas_1
|
100
|
+
# Check if the HVST has already been run on this device
|
101
|
+
func :rd_vreg_hvst_passcode, softbin: 50, vdd: :nom, id: :vreg_hvst_done
|
102
|
+
# If not run it
|
103
|
+
func :vreg_hvst, softbin: 101, hv: 10.V, vdd: :max, unless_passed: :vreg_hvst_done
|
104
|
+
# And program the flag for next time
|
105
|
+
func :pgm_vreg_hvst_passcode, softbin: 51, vdd: :nom, unless_passed: :vreg_hvst_done
|
106
|
+
~~~
|
107
|
+
|
108
|
+
Origen automatically takes care of setting up all of the tests in the relationship:
|
109
|
+
|
110
|
+
* The parent tests in the relationship are automatically set to continue on fail
|
111
|
+
* Flag(s) will be set to indicate whether the parent test passed or failed
|
112
|
+
* Conditional execution flags are set on all dependent tests
|
113
|
+
|
114
|
+
AND and OR conditions can be created by using `if_any/all_failed/passed`
|
115
|
+
variations as follows:
|
116
|
+
|
117
|
+
~~~ruby
|
118
|
+
func :test1, id: :t1
|
119
|
+
func :test2, id: :t2
|
120
|
+
|
121
|
+
# OR logic - This test will run if either of the referenced tests fail
|
122
|
+
func :test3, if_any_failed: [:t1, :t2]
|
123
|
+
|
124
|
+
# AND logic - This test will only run if both of the referenced tests fail
|
125
|
+
func :test4, if_all_passed: [:t1, :t2]
|
126
|
+
|
127
|
+
# Block forms are available as with all condition APIs
|
128
|
+
if_any_passed [:t1, :t2] do
|
129
|
+
#...
|
130
|
+
end
|
131
|
+
~~~
|
132
|
+
|
133
|
+
#### References to External Tests
|
134
|
+
|
135
|
+
It is possible to generate conditional relationships between tests that span across
|
136
|
+
different flow modules, in that case the test ID must be appended with `:extern_`.
|
137
|
+
This will indicate to Origen that the reference is external and
|
138
|
+
will prevent an error being raised for the ID not being found within the current flow.
|
139
|
+
|
140
|
+
Here is an example:
|
141
|
+
|
142
|
+
~~~ruby
|
143
|
+
# program/flow_1.rb
|
144
|
+
Flow.create do
|
145
|
+
# This ID can only be referenced within this flow
|
146
|
+
func :test1, id: :t1
|
147
|
+
# This ID can be referenced outside of this flow
|
148
|
+
func :test2 id: :extern_t2
|
149
|
+
end
|
150
|
+
|
151
|
+
# program/flow_2.rb
|
152
|
+
Flow.create do
|
153
|
+
# This will generate an undefined ID error
|
154
|
+
func :test3, if_failed: :t1
|
155
|
+
# But this will work, since the ID's name indicates that it is an intentional external reference
|
156
|
+
func :test4, if_failed: :extern_t2
|
157
|
+
end
|
158
|
+
~~~
|
159
|
+
|
160
|
+
#### Applying Conditions to Sub-Flows
|
161
|
+
|
162
|
+
All of the flow control methods have a block form which will apply the
|
163
|
+
condition to all tests within the block.
|
164
|
+
|
165
|
+
A very useful pattern is to split your code into small re-usable snippets
|
166
|
+
and then wrap the import with these flow control methods to apply conditional
|
167
|
+
execution.
|
168
|
+
For example, here the 'FH' job requirement will be applied to all tests
|
169
|
+
imported from the vreg component:
|
170
|
+
|
171
|
+
~~~ruby
|
172
|
+
# Only run the vreg tests at hot
|
173
|
+
if_job "FH" do
|
174
|
+
import "components/vreg"
|
175
|
+
end
|
176
|
+
~~~
|
177
|
+
|
178
|
+
#### Conditions Applied to Groups
|
179
|
+
|
180
|
+
Groups can also be used to implement AND/OR logic, here is an example of how you
|
181
|
+
might implement a speed binning flow:
|
182
|
+
|
183
|
+
~~~ruby
|
184
|
+
group "200Mhz", id: :spec200 do
|
185
|
+
func :test1_200
|
186
|
+
func :test2_200
|
187
|
+
end
|
188
|
+
|
189
|
+
# Bin out to bin 1 if passed at 200 Mhz, here if_passed will apply to all tests in the group
|
190
|
+
pass 1, if_passed: :spec200
|
191
|
+
|
192
|
+
group "100Mhz", id: :spec100 do
|
193
|
+
func :test1_100
|
194
|
+
func :test2_100
|
195
|
+
end
|
196
|
+
|
197
|
+
# Bin out to bin 2 if passed at 100 Mhz, here if_passed will apply to all tests in the group
|
198
|
+
pass 2, if_passed: :spec100
|
199
|
+
|
200
|
+
# Otherwise we have failed
|
201
|
+
bin 3
|
202
|
+
~~~
|
203
|
+
|
204
|
+
#### Manually Setting and Referencing Flags
|
205
|
+
|
206
|
+
It may be sometimes be necessary to react on a flag that is controlled by a 3rd party and
|
207
|
+
which will be passed into an Origen-based test block, or to set a flag which a 3rd
|
208
|
+
party test block will later reference.
|
209
|
+
|
210
|
+
An API exists to manually set and react to flags in these situations:
|
211
|
+
|
212
|
+
~~~ruby
|
213
|
+
log "Example of manual flag setting upon pass or fail"
|
214
|
+
test :test1, on_pass: { set_flag: :my_pass_flag }, on_fail: { set_flag: :my_fail_flag }, continue: true
|
215
|
+
|
216
|
+
# Execute only if the above pass flag was set
|
217
|
+
test :test2, if_flag: :my_pass_flag
|
218
|
+
|
219
|
+
# Execute only if the above pass flag was not set
|
220
|
+
unless_flag :my_pass_flag do
|
221
|
+
test :test3
|
222
|
+
end
|
223
|
+
~~~
|
224
|
+
|
225
|
+
Note that flag names will usually be forced to uppercase, this is to institute a convention that
|
226
|
+
flags/flow variables are always uppercased in order to avoid any test program bugs from
|
227
|
+
incorrectly referencing a given flag due to case sensitivity.
|
228
|
+
|
229
|
+
However, if you need to reference a flag from a 3rd party test module that does not follow this
|
230
|
+
convention, then a literal flag can be supplied by prefixing it with `$` as shown below:
|
231
|
+
|
232
|
+
~~~ruby
|
233
|
+
test :test1, on_fail: { set_flag: :$My_Mixed_Flag }, continue: true
|
234
|
+
test :test2, if_flag: "$My_Mixed_Flag"
|
235
|
+
unless_flag "$My_Mixed_Flag" do
|
236
|
+
test :test3
|
237
|
+
end
|
238
|
+
|
239
|
+
test :extra_test, if_enable: :$MCEn_extras
|
240
|
+
unless_enable "$MCEn_test" do
|
241
|
+
test :test1
|
242
|
+
test :test2
|
243
|
+
end
|
244
|
+
~~~
|
245
|
+
|
246
|
+
In all cases the `$` will be removed from the final flag name that appears in the test program.
|
247
|
+
|
248
|
+
|
249
|
+
% end
|
@@ -0,0 +1,429 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
The test flow is where you describe everything about what your test program
|
4
|
+
must do:
|
5
|
+
|
6
|
+
* The tests it must run
|
7
|
+
* The conditions applied by these tests
|
8
|
+
* Test limits
|
9
|
+
* Bin and test numbers
|
10
|
+
* Conditional test execution and other flow control
|
11
|
+
* Notes about the reason for running or the methodology behind each test
|
12
|
+
|
13
|
+
When writing your flow file you should try and distill down the amount of information
|
14
|
+
to the bare minimum, the goal here is to write as little as possible yet still
|
15
|
+
capture the details about what makes each test unique.
|
16
|
+
|
17
|
+
When describing each test the syntax and naming conventions are entirely
|
18
|
+
up to you and based on your knowledge about the application domain and the
|
19
|
+
type and variety of tests that you need to generate.
|
20
|
+
It will be the job of the interface (which you will write later) to translate
|
21
|
+
this description into method calls to the generation API for the target platform.
|
22
|
+
|
23
|
+
#### Your First Flow File
|
24
|
+
|
25
|
+
By convention all flow files should reside in the "program" directory within
|
26
|
+
the application top-level directory.
|
27
|
+
|
28
|
+
Create the file "program/probe.rb" as shown below:
|
29
|
+
|
30
|
+
~~~ruby
|
31
|
+
# program/probe.rb
|
32
|
+
Flow.create do
|
33
|
+
|
34
|
+
end
|
35
|
+
~~~
|
36
|
+
|
37
|
+
The above represents all of the officially required syntax to define a flow, what
|
38
|
+
goes inside is now completely down to the needs of the application.
|
39
|
+
|
40
|
+
When creating a flow like this it is often useful to supply some context about
|
41
|
+
the environment in which it will run. For example we have indicated via the name that this
|
42
|
+
is a flow intended to run at probe, we can also note this in the code:
|
43
|
+
|
44
|
+
~~~ruby
|
45
|
+
# program/probe.rb
|
46
|
+
Flow.create(environment: :probe) do
|
47
|
+
|
48
|
+
end
|
49
|
+
~~~
|
50
|
+
|
51
|
+
Again the naming of the terms <code>:environment</code> and <code>:probe</code> are
|
52
|
+
completely arbitrary, you may want to note some details about the temperature, parallelism
|
53
|
+
or other details which may be useful to you when it comes to actually generating
|
54
|
+
the flow for a given ATE platform.
|
55
|
+
Or not. Don't worry about this too much right now, in practice it is probably best to
|
56
|
+
just add things like this as you find that you need them. The main thing for now is just to
|
57
|
+
appreciate that you can pass some details about the execution environment of the given
|
58
|
+
flow to the interface via this mechanism.
|
59
|
+
|
60
|
+
#### Specifying Numbers
|
61
|
+
|
62
|
+
Origen extends Ruby to add the following methods which are very helpful
|
63
|
+
when specifying test conditions:
|
64
|
+
|
65
|
+
~~~ruby
|
66
|
+
3.A # => 3
|
67
|
+
3.mA # => 0.003
|
68
|
+
3.uA # => 0.000003
|
69
|
+
3.nA # => 0.000000003
|
70
|
+
3.pA # => 0.000000000003
|
71
|
+
|
72
|
+
3.V # => 3
|
73
|
+
3.mV # => 0.003
|
74
|
+
# => etc
|
75
|
+
|
76
|
+
3.Hz # => 3
|
77
|
+
3.kHz # => 3000
|
78
|
+
3.MHz # => 3000000
|
79
|
+
~~~
|
80
|
+
|
81
|
+
#### Adding Some Tests
|
82
|
+
|
83
|
+
So let's say we are writing a test for a voltage regulator module, we have a functional
|
84
|
+
test and then two parametric tests that we wish to run - one that simply tests the
|
85
|
+
output and one that tests the output under load.
|
86
|
+
Let's start with this:
|
87
|
+
|
88
|
+
~~~ruby
|
89
|
+
# program/probe.rb
|
90
|
+
Flow.create(environment: :probe) do
|
91
|
+
|
92
|
+
log "Vreg test module"
|
93
|
+
|
94
|
+
func :vreg_functional, pattern: "vreg/functional", vdd: :min, bin: 5, softbin: 101, tnum: 101000
|
95
|
+
|
96
|
+
func :vreg_functional, pattern: "vreg/functional", vdd: :max, bin: 5, softbin: 101, tnum: 101001
|
97
|
+
|
98
|
+
para :vreg_meas, pattern: "vreg/meas", vdd: :min, bin: 5, softbin: 105, tnum: 105000, lo: 1.12, hi: 1.34
|
99
|
+
|
100
|
+
para :vreg_meas, pattern: "vreg/meas", vdd: :max, bin: 5, softbin: 105, tnum: 105001, lo: 1.12, hi: 1.34
|
101
|
+
|
102
|
+
para :vreg_meas, pattern: "vreg/meas", vdd: :min, bin: 5, softbin: 105, tnum: 105002, load: 5.mA, lo: 1.10, hi: 1.34
|
103
|
+
|
104
|
+
para :vreg_meas, pattern: "vreg/meas", vdd: :max, bin: 5, softbin: 105, tnum: 105003, load: 5.mA, lo: 1.12, hi: 1.34
|
105
|
+
|
106
|
+
end
|
107
|
+
~~~
|
108
|
+
|
109
|
+
This is a good start, we have something that resembles a test flow and we have gone with the
|
110
|
+
general convention that a flow line is structured like this:
|
111
|
+
|
112
|
+
~~~text
|
113
|
+
<function> <name>, <attributes>
|
114
|
+
~~~
|
115
|
+
|
116
|
+
* **function** - The main function of a particular test, here we have gone with the categories
|
117
|
+
'log', 'func(tional)' and 'para(metric)'. You may wish to have other categories based on your domain.
|
118
|
+
For example in some NVM applications we have 'program', 'read', 'erase', 'measure', 'bitmap',
|
119
|
+
and so on. Each of these functions correspond to the methods that you will need to implement
|
120
|
+
in your interface later.
|
121
|
+
* **name** - Almost every test will need a name and so we make this a mandatory argument.
|
122
|
+
* **attributes** - There then follows a free-format list of attributes, use these to describe
|
123
|
+
the test and especially including anything that makes the test unique, such as the load
|
124
|
+
attribute which has been used above.
|
125
|
+
|
126
|
+
As mentioned previously this choice of convention is just that, a personal choice, however
|
127
|
+
this is the convention that is currently used in the flagship Origen applications that are
|
128
|
+
currently driving the development of the framework.
|
129
|
+
As the Origen program generator matures and the number of applications using it grows, it is
|
130
|
+
possible that alternative and better conventions will begin to emerge.
|
131
|
+
If you come across a better approach then please come and tell us about via the
|
132
|
+
[Origen community channels](<%= path "community" %>),
|
133
|
+
however we will stick with this one for now.
|
134
|
+
|
135
|
+
#### Eliminate Anything that can be Inferred
|
136
|
+
|
137
|
+
Remember that the goal here is to be as concise as possible, since the more concise you
|
138
|
+
are at this level then the more you can automate later. This eliminates duplication and
|
139
|
+
redundancy, reduces the amount of code you need to write to add a new test later, and the
|
140
|
+
more that can be generated the less chance there is for human error.
|
141
|
+
|
142
|
+
There are a few opportunities for simplification that we can consider at this point:
|
143
|
+
|
144
|
+
* The **pattern** field seems redundant - it very closely mirrors what has been assigned to the
|
145
|
+
test name, therefore we can infer the pattern name without explicitly declaring it. It is generally
|
146
|
+
a good approach to name the test after the pattern if you normally have one pattern per test.
|
147
|
+
* The **bin** number also looks to be redundant, it is always 5. In a case like this what
|
148
|
+
we can do is set a default of 5 within the interface, then if it is not declared for a specific
|
149
|
+
test it will be 5, but we can always override it for a specific test.
|
150
|
+
* The **tnum** attribute seems to follow the general rule that it is the softbin number * 1000
|
151
|
+
and then a counter. Anything that is the result of a function based on other
|
152
|
+
attributes is ripe for elimination.
|
153
|
+
|
154
|
+
With those optimizations applied we end up with:
|
155
|
+
|
156
|
+
~~~ruby
|
157
|
+
# program/probe.rb
|
158
|
+
Flow.create(environment: :probe) do
|
159
|
+
|
160
|
+
log "Vreg test module"
|
161
|
+
|
162
|
+
func :vreg_functional, vdd: :min, softbin: 101
|
163
|
+
|
164
|
+
func :vreg_functional, vdd: :max, softbin: 101
|
165
|
+
|
166
|
+
para :vreg_meas, vdd: :min, softbin: 105, lo: 1.12, hi: 1.34
|
167
|
+
|
168
|
+
para :vreg_meas, vdd: :max, softbin: 105, lo: 1.12, hi: 1.34
|
169
|
+
|
170
|
+
para :vreg_meas, vdd: :min, softbin: 105, load: 5.mA, lo: 1.10, hi: 1.34
|
171
|
+
|
172
|
+
para :vreg_meas, vdd: :max, softbin: 105, load: 5.mA, lo: 1.12, hi: 1.34
|
173
|
+
|
174
|
+
end
|
175
|
+
~~~
|
176
|
+
|
177
|
+
Finally we seem to always be running our tests at min vdd and then max vdd, so again
|
178
|
+
there seems to be a convention that we could choose to implement by default. One issue we
|
179
|
+
have is that the loaded test has a different limit between min and max, so this a
|
180
|
+
good example of one case where we would override the default.
|
181
|
+
|
182
|
+
So switching to the convention that each test will execute at min and max vdd unless otherwise
|
183
|
+
specified, our final flow is:
|
184
|
+
|
185
|
+
~~~ruby
|
186
|
+
# program/probe.rb
|
187
|
+
Flow.create(environment: :probe) do
|
188
|
+
|
189
|
+
log "Vreg test module"
|
190
|
+
|
191
|
+
func :vreg_functional, softbin: 101
|
192
|
+
|
193
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34V
|
194
|
+
|
195
|
+
para :vreg_meas, vdd: :min, softbin: 105, load: 5.mA, lo: 1.10, hi: 1.34
|
196
|
+
|
197
|
+
para :vreg_meas, vdd: :max, softbin: 105, load: 5.mA, lo: 1.12, hi: 1.34
|
198
|
+
|
199
|
+
end
|
200
|
+
~~~
|
201
|
+
|
202
|
+
That very clearly and concisely describes what the flow must do. Also by establishing
|
203
|
+
conventions and eliminating redundancy we have made it really easy for us to add
|
204
|
+
a new test in the future.
|
205
|
+
|
206
|
+
#### Flow Control
|
207
|
+
|
208
|
+
See the next section for details on run-time flow control.
|
209
|
+
|
210
|
+
For build-time flow control you have complete access to the current target objects if you
|
211
|
+
need to conditionally build some tests.
|
212
|
+
|
213
|
+
Lets say we have two DUT designs, and one of them has a bug which means that the
|
214
|
+
vreg load test will not work properly. Let's say its a problem with the pad connection
|
215
|
+
such that the vreg works ok but it just can't be tested via an external load.
|
216
|
+
Our models to represent this situation would look something like this:
|
217
|
+
|
218
|
+
~~~ruby
|
219
|
+
# lib/dut_1.rb
|
220
|
+
class DUT1
|
221
|
+
include Origen::Model
|
222
|
+
end
|
223
|
+
|
224
|
+
# lib/dut_2.rb
|
225
|
+
class DUT2 < DUT
|
226
|
+
include Origen::Model
|
227
|
+
|
228
|
+
bug :vreg_pad
|
229
|
+
end
|
230
|
+
|
231
|
+
DUT1.new.has_bug?(:vreg_pad) # => false
|
232
|
+
DUT2.new.has_bug?(:vreg_pad) # => true
|
233
|
+
~~~
|
234
|
+
|
235
|
+
There are two ways that we could build the flow to ensure that DUT2 can still give a bin 1 - either
|
236
|
+
skip the loaded test completely, or else don't care its result.
|
237
|
+
Here is an example of both:
|
238
|
+
|
239
|
+
~~~ruby
|
240
|
+
# program/probe.rb
|
241
|
+
Flow.create(environment: :probe) do
|
242
|
+
|
243
|
+
log "Vreg test module"
|
244
|
+
|
245
|
+
func :vreg_functional, softbin: 101
|
246
|
+
|
247
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34
|
248
|
+
|
249
|
+
# Don't build this test if the target DUT has the bug
|
250
|
+
unless $dut.has_bug?(:vreg_pad)
|
251
|
+
para :vreg_meas, vdd: :min, softbin: 105, load: 5.mA, lo: 1.10, hi: 1.34
|
252
|
+
end
|
253
|
+
|
254
|
+
# Continue on fail if the target DUT has the bug
|
255
|
+
para :vreg_meas, vdd: :max, softbin: 105, load: 5.mA, lo: 1.12, hi: 1.34, continue: $dut.has_bug?(:vreg_pad)
|
256
|
+
|
257
|
+
end
|
258
|
+
~~~
|
259
|
+
|
260
|
+
#### Re-usable Flow Snippets
|
261
|
+
|
262
|
+
It is ofter useful to extract sections of a flow into a sub-module, so that it can be re-used
|
263
|
+
and parameterized.
|
264
|
+
In our case let's say that we have a new DUT on the horizon which has two vreg instances, so
|
265
|
+
let's extract this suite of vreg tests to a module so that we can instantiate two of them in
|
266
|
+
our flow.
|
267
|
+
|
268
|
+
All sub flow file names must begin with "_", this is what tells Origen that it is a sub-flow and
|
269
|
+
not a top-level flow.
|
270
|
+
The sub-flow syntax is virtually identical to the regular flow syntax except that a hash of
|
271
|
+
options are passed in which will contain any arguments passed in by the caller when they
|
272
|
+
instantiate the sub-flow.
|
273
|
+
|
274
|
+
Let's convert our flow to a sub-flow in file "_vreg.rb":
|
275
|
+
|
276
|
+
~~~ruby
|
277
|
+
# program/_vreg.rb
|
278
|
+
Flow.create do |options|
|
279
|
+
|
280
|
+
log "Vreg test module"
|
281
|
+
|
282
|
+
func :vreg_functional, softbin: 101
|
283
|
+
|
284
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34
|
285
|
+
|
286
|
+
# Don't build this test if the target DUT has the bug
|
287
|
+
unless $dut.has_bug?(:vreg_pad)
|
288
|
+
para :vreg_meas, vdd: :min, softbin: 105, load: 5.mA, lo: 1.10, hi: 1.34
|
289
|
+
end
|
290
|
+
|
291
|
+
# Continue on fail if the target DUT has the bug
|
292
|
+
para :vreg_meas, vdd: :max, softbin: 105, load: 5.mA, lo: 1.12, hi: 1.34, continue: $dut.has_bug?(:vreg_pad)
|
293
|
+
|
294
|
+
end
|
295
|
+
~~~
|
296
|
+
|
297
|
+
Not much has changed so far - the environment option has been removed from the <code>Flow.create</code>
|
298
|
+
definition since that is more of a top-level concern, and the options have been added.
|
299
|
+
|
300
|
+
There are a couple of opportunities for improvement here:
|
301
|
+
|
302
|
+
* The flow allows the loaded tests to be skipped, however it would be better if the sub-flow
|
303
|
+
did not define the conditions under which they should be skipped - that decision should be
|
304
|
+
made by to the top-level.
|
305
|
+
* If this test is going to be instantiated multiple times it will need some kind of index
|
306
|
+
to target the test at vreg 0 or vreg 1.
|
307
|
+
|
308
|
+
Here is the flow with these modifications:
|
309
|
+
|
310
|
+
~~~ruby
|
311
|
+
# program/_vreg.rb
|
312
|
+
Flow.create do |options|
|
313
|
+
|
314
|
+
# These are the option defaults that will be used unless specified by the caller
|
315
|
+
options = {
|
316
|
+
include_loaded_output_tests: true,
|
317
|
+
index: 0,
|
318
|
+
}.merge(options)
|
319
|
+
|
320
|
+
log "Vreg test module"
|
321
|
+
|
322
|
+
func :vreg_functional, softbin: 101, index: options[:index]
|
323
|
+
|
324
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34, index: options[:index]
|
325
|
+
|
326
|
+
if options[:include_loaded_output_tests]
|
327
|
+
|
328
|
+
para :vreg_meas, vdd: :min, softbin: 105, load: 5.mA, lo: 1.10, hi: 1.34, index: options[:index]
|
329
|
+
|
330
|
+
para :vreg_meas, vdd: :max, softbin: 105, load: 5.mA, lo: 1.12, hi: 1.34, index: options[:index]
|
331
|
+
|
332
|
+
end
|
333
|
+
|
334
|
+
end
|
335
|
+
~~~
|
336
|
+
|
337
|
+
For now we have not really committed to how the indexed tests will be generated, but we have
|
338
|
+
passed the information along to the interface. Most likely when it comes to generating the
|
339
|
+
pattern name within the interface we will just append the index to the name.
|
340
|
+
|
341
|
+
So the original top-level flow is now really simple:
|
342
|
+
|
343
|
+
~~~ruby
|
344
|
+
# program/probe.rb
|
345
|
+
Flow.create(environment: :probe) do
|
346
|
+
|
347
|
+
import "vreg", include_loaded_output_tests: !$dut.has_bug?(:vreg_pad)
|
348
|
+
|
349
|
+
end
|
350
|
+
~~~
|
351
|
+
|
352
|
+
The path argument supplied to the import method can be either a relative path from the
|
353
|
+
current file (as it is above), for example <code>"../components/vreg"</code>, or an
|
354
|
+
absolute path such as <code>"#{Origen.root}/program/components/vreg"</code>. In both cases
|
355
|
+
the underscore prefix is not required.
|
356
|
+
|
357
|
+
The original reason for doing this was to add support for testing multiple
|
358
|
+
vreg instances. To support such a case let's say that our DUT model will implement a
|
359
|
+
method called <code>vregs</code> which will return one or more vreg models wrapped
|
360
|
+
in an array.
|
361
|
+
|
362
|
+
Our final flow is:
|
363
|
+
|
364
|
+
~~~ruby
|
365
|
+
# program/probe.rb
|
366
|
+
Flow.create(environment: :probe) do
|
367
|
+
|
368
|
+
$dut.vregs.each_with_index do |vreg, i|
|
369
|
+
|
370
|
+
import "vreg", include_loaded_output_tests: !$dut.has_bug?(:vreg_pad), index: i
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
375
|
+
~~~
|
376
|
+
|
377
|
+
#### Documenting Tests
|
378
|
+
|
379
|
+
All of the test attributes will be available later when it comes to generating documentation
|
380
|
+
of the test program, so there is no need to document them manually.
|
381
|
+
However in some cases it will also be useful to include some
|
382
|
+
text describing perhaps how the test works, or why it is being done.
|
383
|
+
Such information can be added via regular Ruby comments immediately before the given
|
384
|
+
test.
|
385
|
+
|
386
|
+
Origen will extract these later when it comes to generating documentation.
|
387
|
+
|
388
|
+
The comments will be parsed as [Markdown](http://kramdown.rubyforge.org/quickref.html)
|
389
|
+
so this can be used to make things like bulleted lists or tables.
|
390
|
+
|
391
|
+
Here is our vreg test suite with some example documentation added:
|
392
|
+
|
393
|
+
~~~ruby
|
394
|
+
# program/_vreg.rb
|
395
|
+
Flow.create do |options|
|
396
|
+
|
397
|
+
# These are the option defaults that will be used unless specified by the caller
|
398
|
+
options = {
|
399
|
+
include_loaded_output_tests: true,
|
400
|
+
index: 0,
|
401
|
+
}.merge(options)
|
402
|
+
|
403
|
+
log "Vreg test module"
|
404
|
+
|
405
|
+
# This test verifies that the following things work:
|
406
|
+
#
|
407
|
+
# * The vreg can be disabled
|
408
|
+
# * The trim register can be written to and read from
|
409
|
+
func :vreg_functional, softbin: 101, index: options[:index]
|
410
|
+
|
411
|
+
# Measure the output of the vreg under no load, this is a simple
|
412
|
+
# test to catch any gross defects that prevent the vreg from working
|
413
|
+
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34, index: options[:index]
|
414
|
+
|
415
|
+
if options[:include_loaded_output_tests]
|
416
|
+
|
417
|
+
# Measure the output of the vreg under the given load, this is approximately
|
418
|
+
# equivalent to 1.5x the maximum load anticipated in a customer application.
|
419
|
+
para :vreg_meas, vdd: :min, softbin: 105, load: 5.mA, lo: 1.10, hi: 1.34, index: options[:index]
|
420
|
+
|
421
|
+
# As above
|
422
|
+
para :vreg_meas, vdd: :max, softbin: 105, load: 5.mA, lo: 1.12, hi: 1.34, index: options[:index]
|
423
|
+
|
424
|
+
end
|
425
|
+
|
426
|
+
end
|
427
|
+
~~~
|
428
|
+
|
429
|
+
% end
|