origen_testers 0.19.0 → 0.19.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|