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,97 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
The program generator is launched via the Origen generate command, see the command line
|
4
|
+
help to get details of the most up to date options:
|
5
|
+
|
6
|
+
~~~text
|
7
|
+
origen program -h
|
8
|
+
~~~
|
9
|
+
|
10
|
+
As this is such a commonly used command it has a short cut alias:
|
11
|
+
|
12
|
+
~~~text
|
13
|
+
origen p -h
|
14
|
+
~~~
|
15
|
+
|
16
|
+
The generator can be run on a single file:
|
17
|
+
|
18
|
+
~~~text
|
19
|
+
origen p program/probe/sort1.rb
|
20
|
+
~~~
|
21
|
+
|
22
|
+
or it can be run on a whole directory:
|
23
|
+
|
24
|
+
~~~text
|
25
|
+
origen p program/probe
|
26
|
+
~~~
|
27
|
+
|
28
|
+
Program list files can also be used, by convention these should be kept in the list directory
|
29
|
+
and should have the extension <code>.list</code>:
|
30
|
+
|
31
|
+
~~~text
|
32
|
+
origen p list/program/production.list
|
33
|
+
~~~
|
34
|
+
|
35
|
+
Here is an example of a list file:
|
36
|
+
|
37
|
+
~~~text
|
38
|
+
# List files can be commented like this
|
39
|
+
# Simply list the name of the files that you would use on the command line
|
40
|
+
program/probe/sort1.rb
|
41
|
+
program/probe/sort2.rb
|
42
|
+
# List files can also call other lists
|
43
|
+
ft.list
|
44
|
+
~~~
|
45
|
+
|
46
|
+
The generated files will be put in whatever directory
|
47
|
+
is returned by the <code>config.test_program_output_directory</code> attribute in <code>application.rb</code>.
|
48
|
+
|
49
|
+
Submit to the LSF by appending <code>-l</code> and optionally interactively
|
50
|
+
wait for completion:
|
51
|
+
|
52
|
+
~~~text
|
53
|
+
origen p list/program/production.list -l -w
|
54
|
+
~~~
|
55
|
+
|
56
|
+
#### Regression Testing
|
57
|
+
|
58
|
+
Everytime Origen generates a file it will check to see if it has generated it before, and
|
59
|
+
if so it will compare the current version to the previous version and alert if there is a
|
60
|
+
difference. This can be used to check for regressions when making changes that you don't want
|
61
|
+
to affect the output, or to verify that the change is what you intended in cases where you
|
62
|
+
are intentionally modifying the output.
|
63
|
+
|
64
|
+
The diff is a smart diff and will not care about any changes to comments, only about changes
|
65
|
+
that will affect the file's operation.
|
66
|
+
|
67
|
+
In the case of a difference being found Origen will automatically present you with the diff command
|
68
|
+
to run if you want to view the change.
|
69
|
+
|
70
|
+
To accept changes or to start tracking the differences in a file (or files) run the following command
|
71
|
+
after generating:
|
72
|
+
|
73
|
+
~~~text
|
74
|
+
origen save all
|
75
|
+
~~~
|
76
|
+
|
77
|
+
#### Programatically Launching the Generator
|
78
|
+
|
79
|
+
If you start writing your own [commands](<%= path "guides/misc/commands" %>) you may want
|
80
|
+
to launch the generator from Ruby, do that as follows:
|
81
|
+
|
82
|
+
~~~ruby
|
83
|
+
Origen.app.runner.launch action: :program,
|
84
|
+
files: "list/program/production.list"
|
85
|
+
~~~
|
86
|
+
|
87
|
+
This can be combined with [Target Loops](<%= path "guides/targets/programming" %>) to run the
|
88
|
+
generator for multiple targets.
|
89
|
+
|
90
|
+
A generate job can also be posted to the LSF by supplying the same options that you would use
|
91
|
+
on the command line like this:
|
92
|
+
|
93
|
+
~~~ruby
|
94
|
+
Origen.lsf.submit_origen_job("p program/probe/sort1.rb")
|
95
|
+
~~~
|
96
|
+
|
97
|
+
% end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
To re-cap the purpose of an interface is to translate your behavioral
|
4
|
+
description of the test flow into a test program for a specific ATE
|
5
|
+
platform.
|
6
|
+
This step is where most of the work comes in and interfaces can grow to
|
7
|
+
be quite large pieces of code depending on the complexity of your flow.
|
8
|
+
|
9
|
+
An interface is a regular Ruby class which would be created in your lib
|
10
|
+
directory.
|
11
|
+
Continuing with the vreg example and assuming that all of our code was
|
12
|
+
[namespaced](<%= path "guides/models/naming" %>) in the Vreg module,
|
13
|
+
we could create an initial interface like this:
|
14
|
+
|
15
|
+
~~~ruby
|
16
|
+
# lib/vreg/interface.rb
|
17
|
+
module Vreg
|
18
|
+
class Interface
|
19
|
+
include OrigenTesters::ProgramGenerators
|
20
|
+
|
21
|
+
# The methods called by the flow files will be implemented here
|
22
|
+
end
|
23
|
+
end
|
24
|
+
~~~
|
25
|
+
|
26
|
+
#### Required Methods
|
27
|
+
|
28
|
+
For an interface to run it must implement all of the methods that will be called
|
29
|
+
by your flow.
|
30
|
+
It is also customary to create an initialize method that will capture any options
|
31
|
+
that are passed in to <code>Flow.create</code> (such as declaring the environment
|
32
|
+
as probe in our flow example).
|
33
|
+
|
34
|
+
Here is an interface shell to handle the test flow that we created in the previous
|
35
|
+
section:
|
36
|
+
|
37
|
+
~~~ruby
|
38
|
+
# lib/vreg/interface.rb
|
39
|
+
module Vreg
|
40
|
+
class Interface
|
41
|
+
include OrigenTesters::ProgramGenerators
|
42
|
+
|
43
|
+
# Add a regular attribute to our interface to allow us to query the
|
44
|
+
# execution environment
|
45
|
+
attr_reader :environment
|
46
|
+
|
47
|
+
# Any options passed to Flow.create can be captured here and assigned
|
48
|
+
# to instance variables which can be used later to modify the output from
|
49
|
+
# your other interface methods.
|
50
|
+
def initialize(options={})
|
51
|
+
options = {
|
52
|
+
environment: :ft, # Set the environment to FT unless otherwise specified
|
53
|
+
}.merge(options)
|
54
|
+
@environment = options[:environment]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Record the given message to the datalog
|
58
|
+
def log(msg, options={})
|
59
|
+
end
|
60
|
+
|
61
|
+
# Create a functional test and call it from the flow
|
62
|
+
def func(name, options={})
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create a parametric test and call it from the flow
|
66
|
+
def para(name, options={})
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
~~~
|
72
|
+
|
73
|
+
Note that you do not need to define methods to handle the
|
74
|
+
[Flow Control API](<%= path "guides/program/flowapi" %>), the included generator
|
75
|
+
module will already take care of those.
|
76
|
+
|
77
|
+
At this point you can now generate your flow for the first time to make sure
|
78
|
+
that there are no methods missing:
|
79
|
+
|
80
|
+
~~~text
|
81
|
+
origen p path/to/your/flow.rb
|
82
|
+
~~~
|
83
|
+
|
84
|
+
All being well this should run cleanly without actually generating any of your tests,
|
85
|
+
if you get some errors your should be able to work out what methods need to be added to
|
86
|
+
your interface from the error messages.
|
87
|
+
|
88
|
+
The contents of these methods will be discussed in the following platform-specific
|
89
|
+
section of the test program guide.
|
90
|
+
|
91
|
+
#### Avoiding Duplicate Tests
|
92
|
+
|
93
|
+
The astute reader may at this point note that the intention of the above methods
|
94
|
+
is to both generate a test and to add it to the flow. Well how do we avoid duplicate
|
95
|
+
tests from being generated if the same method is called multiple times within the same flow?
|
96
|
+
|
97
|
+
The answer is that you don't need to worry about this, Origen will take care of suppressing
|
98
|
+
duplicate entries in things like a test instance or a test pattern file, depending on the
|
99
|
+
needs of the target platform.
|
100
|
+
So your interface does not need to keep track of details like whether a test has previously
|
101
|
+
been generated or not. Just generate all the resources required to run a particular test
|
102
|
+
every time that your method is called and Origen will take care of optimizing it.
|
103
|
+
|
104
|
+
When assessing whether or not a test already exists Origen does not simply just look at the
|
105
|
+
name, all of the attributes of a particular test are considered as well. If a test of the
|
106
|
+
same name already exists but with different attributes then Origen will create a new test
|
107
|
+
and apply a version of '_v1' to the original test and '_v2' to the new one. The flow will
|
108
|
+
call the correct version at the correct place as you would expect.
|
109
|
+
|
110
|
+
Generally you should keep an eye on what is being generated and if you start to see
|
111
|
+
'v1' or 'v2' tests being generated then it is a sign that your test naming
|
112
|
+
convention is not including some detail that is required to uniquely identify each test.
|
113
|
+
So while the program generated will be functionally correct, it will not be obvious to
|
114
|
+
a user of the test program what the difference is between 'test_v1' and 'test_v2'.
|
115
|
+
For example say that your test name does not include the vdd, yet your flow generates the same
|
116
|
+
test to run at min, nom and max vdd. In that case Origen will generate these as versions
|
117
|
+
1, 2 and 3.
|
118
|
+
Adding the vdd to you test names would resolve this problem and the program would now
|
119
|
+
include tests called 'test_min', 'test_nom' and 'test_max' which is much more
|
120
|
+
descriptive.
|
121
|
+
|
122
|
+
If you are not comfortable with this approach for some reason and would prefer separate
|
123
|
+
control over test generation and flow insertion then Origen also supports a
|
124
|
+
a more traditional workflow where you can generate a library of tests and then call them
|
125
|
+
from a separate flow definition.
|
126
|
+
How to do that is discussed in the [Resources](<%= path "guides/program/resources" %>)
|
127
|
+
section.
|
128
|
+
However the combined test generation and flow insertion is the recommended way and
|
129
|
+
fully leverages Origen's unique ability to completely generate a new test from adding a single
|
130
|
+
line to the test flow (once you have an interface already setup).
|
131
|
+
|
132
|
+
#### Additional Methods
|
133
|
+
|
134
|
+
The interface can also define whatever additional methods it needs to help implement
|
135
|
+
the main flow API.
|
136
|
+
In this example, let's just add the following method to help us generate the full
|
137
|
+
test names:
|
138
|
+
|
139
|
+
~~~ruby
|
140
|
+
# lib/vreg/interface.rb
|
141
|
+
|
142
|
+
def namer(basename, options={})
|
143
|
+
name = basename
|
144
|
+
if options[:vdd]
|
145
|
+
# In our world let's have the convention that if the vdd is not included in
|
146
|
+
# the name then it is nominal, otherwise it will be in the name
|
147
|
+
unless options[:vdd] == :nom
|
148
|
+
name = "#{name}_#{options[:vdd]}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
name
|
152
|
+
end
|
153
|
+
~~~
|
154
|
+
|
155
|
+
In reality some interfaces can get quite complex, and breaking the code down to additional
|
156
|
+
Ruby class or modules is common.
|
157
|
+
|
158
|
+
#### Re-using Interface Methods
|
159
|
+
|
160
|
+
The interface, or portions of it, can be easily extracted to a plugin
|
161
|
+
for future use in another application.
|
162
|
+
|
163
|
+
See the [Origen Plugins](<%= path "guides/plugins/introduction" %>)
|
164
|
+
section for details on how to do this.
|
165
|
+
|
166
|
+
#### Detecting Changes in the Execution Context
|
167
|
+
|
168
|
+
The execution context of a test is the name given to the rules that decide whether it will
|
169
|
+
be executed or not, and these are generally the attributes exposed by the
|
170
|
+
[Flow Control API](<%= path "guides/program/flowapi" %>). i.e. enable flag, job, failed flag,
|
171
|
+
etc.
|
172
|
+
|
173
|
+
If the context applied to two adjacent tests is different, then it means that the second test
|
174
|
+
cannot be guaranteed that the first test will always run before it. This could be a concern if the
|
175
|
+
second test is expecting to inherit some state from the previous test, such as the vdd/levels
|
176
|
+
selection for example.
|
177
|
+
|
178
|
+
Therefore, an interface helper exists to help you identify when such context switches occur.
|
179
|
+
|
180
|
+
The next pages will cover the creation of an interface in more detail, but generally it is
|
181
|
+
recommended to have a single method responsible for actually adding the generated tests into
|
182
|
+
the flow, like this:
|
183
|
+
|
184
|
+
~~~ruby
|
185
|
+
# my_interface.rb
|
186
|
+
|
187
|
+
# Add the given test into the flow
|
188
|
+
def add_to_flow(test_object, options = {})
|
189
|
+
flow.test test_object, options
|
190
|
+
end
|
191
|
+
~~~
|
192
|
+
|
193
|
+
By funneling all tests through a single point like this, it naturally gives you a place to look
|
194
|
+
for context changes and take corrective action.
|
195
|
+
Use the `context_changed?` helper as shown in this example:
|
196
|
+
|
197
|
+
~~~ruby
|
198
|
+
def add_to_flow(test_object, options = {})
|
199
|
+
# Give this all options that you are about to send to the flow.test method
|
200
|
+
if context_changed?(options)
|
201
|
+
# Can't rely on inheriting from the previous test, configure this test to re-apply the levels
|
202
|
+
# (where add_levels_configuration is a fictional method within your interface)
|
203
|
+
add_levels_configuration(test_object)
|
204
|
+
end
|
205
|
+
flow.test test_object, options
|
206
|
+
end
|
207
|
+
~~~
|
208
|
+
|
209
|
+
A similar helper method called `parameter_changed?` exists to detect changes in your application-specific test attributes. For
|
210
|
+
example, let's say that your test flow always defines the vdd settings via two parameters called
|
211
|
+
`:vdde` and `:vddc`:
|
212
|
+
|
213
|
+
~~~ruby
|
214
|
+
# my_flow.rb
|
215
|
+
|
216
|
+
func :march_a, vdde: :nom, :vddc: :nom
|
217
|
+
|
218
|
+
func :march_b, vdde: :nom, :vddc: :nom
|
219
|
+
|
220
|
+
func :march_b, vdde: :nom, :vddc: :max
|
221
|
+
~~~
|
222
|
+
|
223
|
+
Then if your level switching had to be implemented by the injection of a dedicated test instance,
|
224
|
+
it could be easily handled like this:
|
225
|
+
|
226
|
+
~~~ruby
|
227
|
+
def add_to_flow(test_object, options = {})
|
228
|
+
# Give this all options that you are about to send to the flow.test method, supply as many parameter
|
229
|
+
# names as you want up front
|
230
|
+
if parameter_changed?(:vdde, :vddc, options)
|
231
|
+
# The upcoming test requires a vdd change, inject this into the flow before inserting it, again
|
232
|
+
# using a fictional switch_levels method
|
233
|
+
switch_levels(options)
|
234
|
+
end
|
235
|
+
flow.test test_object, options
|
236
|
+
end
|
237
|
+
~~~
|
238
|
+
|
239
|
+
Finally, a convenience method exists that will trigger if either the context or one of your
|
240
|
+
specified parameters changes:
|
241
|
+
|
242
|
+
~~~ruby
|
243
|
+
if context_or_parameter_changed?(:vdde, :vddc, options)
|
244
|
+
# ...
|
245
|
+
~~~
|
246
|
+
|
247
|
+
|
248
|
+
% end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
Origen provides a powerful object-oriented test program generator which has a
|
4
|
+
unique architecture which fully separates an application's test flow logic
|
5
|
+
from its implementation on a given test platform.
|
6
|
+
|
7
|
+
This architecture offers many advantages but most notably:
|
8
|
+
|
9
|
+
* It is extremely efficient. Adding additional tests is very quick after you have
|
10
|
+
initially bootstrapped your program generator, in many cases only requiring
|
11
|
+
one line to be added to your source code.
|
12
|
+
* It keeps you sane. As test flows and programs get larger and larger it really
|
13
|
+
helps to be able to use object-oriented programming techniques to keep
|
14
|
+
everything organized.
|
15
|
+
* It eliminates bugs. The architecture encourages you to write the least amount of
|
16
|
+
code possible to create a new test, this maximizes the re-use of working code
|
17
|
+
and reduces the number of moving parts and opportunities for bugs to occur.
|
18
|
+
* It supports multi-platform and documentation. The same test flow source file
|
19
|
+
can be used to generate the program on different platforms, including
|
20
|
+
creating documentation of the test program.
|
21
|
+
* Dynamic custom code is supported. Custom VB/C++ code can be compiled through
|
22
|
+
Origen, this eliminates the need to keep DUT configuration information in your
|
23
|
+
test program code - write it to support a single device, then modify it later
|
24
|
+
to work with another configuration with Origen.
|
25
|
+
|
26
|
+
#### Architecture
|
27
|
+
|
28
|
+
An overview of the program generator architecture is shown below:
|
29
|
+
|
30
|
+
<p style="text-align: center">
|
31
|
+
<img src="http://origen-sdk.org/img/prog_gen.png" width="700" height="410">
|
32
|
+
</p>
|
33
|
+
|
34
|
+
Origen provides a rich generator for each supported platform, this takes care of
|
35
|
+
all formatting concerns and tries to automate some details of the platform API which
|
36
|
+
can be particularly error prone - for example flow control logic.
|
37
|
+
|
38
|
+
The application then provides a Flow file which contains a behavioural description
|
39
|
+
of each test and the order that they should be executed in.
|
40
|
+
<strong>Note that there should be no consideration given to the underlying platform implementation
|
41
|
+
of the test at this level</strong>, the job of the flow is to describe the electrical
|
42
|
+
properties of each test and pattern dependencies, but should not worry about things
|
43
|
+
like test instances, interpose functions, test methods, etc.
|
44
|
+
|
45
|
+
The application must then provide an interface which has
|
46
|
+
the job of translating the flow definition to the one or more of the target test platform APIs.
|
47
|
+
For example the interface may say "ok when the flow asks
|
48
|
+
for a functional test then create a new patset, create a new functional test instance
|
49
|
+
which will reference that patset, setup the instance based on the electrical
|
50
|
+
properties of the test, and then finally add an entry in the flow sheet".
|
51
|
+
|
52
|
+
In this way the tedium of having to create a test instance, then a pattern set, then
|
53
|
+
a flow entry, then go back to the test instance because you named the pattern set
|
54
|
+
wrong, etc, etc...is eliminated along with many opportunities for errors.
|
55
|
+
|
56
|
+
% end
|
@@ -0,0 +1,514 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
Be sure to read and understand the guide to
|
4
|
+
[Creating an Interface](<%= path "guides/program/interface" %>) before
|
5
|
+
reading this section.
|
6
|
+
This guide will describe the API to generate J750/IG-XL test program
|
7
|
+
components from within an interface file.
|
8
|
+
|
9
|
+
To re-cap this is the shell required to implement an interface:
|
10
|
+
|
11
|
+
~~~ruby
|
12
|
+
# lib/vreg/interface.rb
|
13
|
+
module Vreg
|
14
|
+
class Interface
|
15
|
+
include OrigenTesters::ProgramGenerators
|
16
|
+
|
17
|
+
# An example method that can be called from your test flow to generate a functional test
|
18
|
+
def func(name, options={})
|
19
|
+
# If your interface supports multiple platforms, add conditional logic like this, if you
|
20
|
+
# only ever want to support one platform then you don't need this
|
21
|
+
if tester.j750?
|
22
|
+
# Functional test implementation for J750
|
23
|
+
elsif tester.v93k?
|
24
|
+
# Functional test implementation for V93K
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
~~~
|
31
|
+
|
32
|
+
The <code>OrigenTesters::ProgramGenerators</code> will provide the interface
|
33
|
+
with access to all of the platform generator APIs for the platforms that it supports.
|
34
|
+
|
35
|
+
If your interface supports multiple platforms then add conditional logic to separate
|
36
|
+
them as shown above.
|
37
|
+
|
38
|
+
### Creating a Test Instance
|
39
|
+
|
40
|
+
When generating a J750 program most of the effort is in generating the test
|
41
|
+
instances. To start with the basic method of creating and decorating test instance
|
42
|
+
objects will be discussed and then at the end of this section some recommendations
|
43
|
+
will be given on how to structure your test instance generation methods.
|
44
|
+
|
45
|
+
The method <code>test_instances</code> returns an instance of
|
46
|
+
<code>OrigenTesters::IGXLBasedTester::J750::TestInstances</code> which provides additional
|
47
|
+
methods to generate new test instances.
|
48
|
+
The [API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/TestInstances.html)
|
49
|
+
should be consulted for the most up to date information on the methods available.
|
50
|
+
|
51
|
+
A new test instance can be instantiated like this:
|
52
|
+
|
53
|
+
~~~ruby
|
54
|
+
test_instances.add(:vreg_func, :functional)
|
55
|
+
~~~
|
56
|
+
|
57
|
+
This one line of code does a lot of things:
|
58
|
+
|
59
|
+
* Creates a new test instance sheet if one doesn't exist already
|
60
|
+
* Instantiates a new test instance object
|
61
|
+
* Sets its name to 'vreg_func'
|
62
|
+
* Applies the default attributes for a J750 functional test instance
|
63
|
+
(basically the same attributes that would be present when you added a new functional
|
64
|
+
test instance within IG-XL)
|
65
|
+
* Adds the new test instance to the test instance sheet
|
66
|
+
|
67
|
+
If you were to add that line and generate your program you would now get
|
68
|
+
a test instance sheet generated with a single functional test instance in it
|
69
|
+
called 'vreg_func'. Not bad.
|
70
|
+
|
71
|
+
Convenience methods exist where you can call a method named after the type of the test instance,
|
72
|
+
this is equivalent:
|
73
|
+
|
74
|
+
~~~ruby
|
75
|
+
test_instances.functional(:vreg_func)
|
76
|
+
~~~
|
77
|
+
|
78
|
+
You will of course want to decorate your new test instance with attributes that are specific
|
79
|
+
to your application, to do that you simply assign the returned instance to a variable and
|
80
|
+
then you can programmatically set the attributes that you want.
|
81
|
+
For example:
|
82
|
+
|
83
|
+
~~~ruby
|
84
|
+
ins = test_instances.functional(:vreg_func)
|
85
|
+
ins.ac_category = "Spec"
|
86
|
+
ins.ac_selector = "Default"
|
87
|
+
ins.time_sets = "Tim"
|
88
|
+
ins.pin_levels = "Lvl"
|
89
|
+
~~~
|
90
|
+
|
91
|
+
The name of these methods is the underscored (to align with general Ruby conventions)
|
92
|
+
version of the name in the IG-XL columns headers and they should hopefully be very
|
93
|
+
intuitive.
|
94
|
+
|
95
|
+
Note that you don't need to do anything here to save or push the instance into the sheet,
|
96
|
+
this will all be done automatically.
|
97
|
+
|
98
|
+
Attributes can also be passed in when instantiating the new instance, this is equivalent
|
99
|
+
if you prefer:
|
100
|
+
|
101
|
+
~~~ruby
|
102
|
+
ins = test_instances.functional :vreg_func, ac_category: "Spec",
|
103
|
+
ac_selector: "Default",
|
104
|
+
time_sets: "Tim",
|
105
|
+
pin_levels: "Lvl"
|
106
|
+
~~~
|
107
|
+
|
108
|
+
#### Instance Type Specific Attributes
|
109
|
+
|
110
|
+
Additional methods will be available depending on the instance type that you
|
111
|
+
specified.
|
112
|
+
For example in our functional instance we can set the pattern and call a pre-test
|
113
|
+
interpose function like this:
|
114
|
+
|
115
|
+
~~~ruby
|
116
|
+
ins.pattern = "vreg_functional"
|
117
|
+
ins.pre_test_func = "someInterposeFunc"
|
118
|
+
~~~
|
119
|
+
|
120
|
+
Again the method names should hopefully be intuitive and should correspond to
|
121
|
+
the IG-XL names.
|
122
|
+
|
123
|
+
To see what the method names are called refer to the <code>TEST_INSTANCE_ALIASES</code> constant
|
124
|
+
definition at the top of the
|
125
|
+
[J750 TestInstance API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/TestInstance.html).
|
126
|
+
|
127
|
+
#### Supported Test Instance Types
|
128
|
+
|
129
|
+
Currently supported test instance types are (although check the
|
130
|
+
[API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/TestInstances.html) for the latest
|
131
|
+
information):
|
132
|
+
|
133
|
+
* functional
|
134
|
+
* board_pmu (bpmu)
|
135
|
+
* pin_pmu (ppmu)
|
136
|
+
* other
|
137
|
+
* empty
|
138
|
+
|
139
|
+
If you need a different type you can still call the add method, the difference in the
|
140
|
+
returned instance for an unrecognized type is:
|
141
|
+
|
142
|
+
* The instance will be completely empty and all attributes will need to be
|
143
|
+
added by your application code.
|
144
|
+
* The named attribute methods will not be available.
|
145
|
+
|
146
|
+
The latter means that instead of using convenience methods to set the attributes you
|
147
|
+
will need to use argX format instead, where argX corresponds to the column name
|
148
|
+
in IG-XL.
|
149
|
+
|
150
|
+
So the previous example of adding a pattern and interpose function call to our functional
|
151
|
+
instance could be re-written as shown below:
|
152
|
+
|
153
|
+
~~~ruby
|
154
|
+
ins.arg0 = "vreg_functional"
|
155
|
+
ins.arg3 = "someInterposeFunc"
|
156
|
+
~~~
|
157
|
+
|
158
|
+
You would also need to configure the basic attributes such as the template type and name.
|
159
|
+
To get an idea of what is required refer to the <code>TEST_INSTANCE_DEFAULTS</code> constant
|
160
|
+
definition near the top of the
|
161
|
+
[J750 TestInstance API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/TestInstance.html).
|
162
|
+
|
163
|
+
If you do find yourself in this situation please get in touch via
|
164
|
+
[the community channels](<%= path "community" %>) and
|
165
|
+
we can quickly work with you to add the new instance type to Origen, then the names attribute
|
166
|
+
methods will be available for everyone.
|
167
|
+
|
168
|
+
#### What Are the Defaults?
|
169
|
+
|
170
|
+
Generally the test instance defaults should match exactly what you get from IG-XL (that is
|
171
|
+
the intention at least).
|
172
|
+
|
173
|
+
To see what the defaults are for a given test instance type refer to the <code>TEST_INSTANCE_DEFAULTS</code> constant
|
174
|
+
definition near the top of the
|
175
|
+
[J750 TestInstance API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/TestInstance.html).
|
176
|
+
|
177
|
+
#### Helper Methods
|
178
|
+
|
179
|
+
A number of helper methods are available to make test instance generation easier.
|
180
|
+
|
181
|
+
A good example is setting the current range of a parametric test instance where the value
|
182
|
+
stored in the IG-XL workbook is not at all intuitive and bears little resemblance to the numeric
|
183
|
+
range value that it represents.
|
184
|
+
A [set_irange](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/Base/TestInstance.html#set_irange-instance_method)
|
185
|
+
method is available to help, here are some examples:
|
186
|
+
|
187
|
+
~~~ruby
|
188
|
+
ins.set_irange(:smart)
|
189
|
+
ins.set_irange(ua: 2)
|
190
|
+
ins.set_irange(2.uA) # Same as above
|
191
|
+
ins.set_irange(ma: 200)
|
192
|
+
ins.set_irange(0.2) # Same as above
|
193
|
+
ins.set_irange(a: 0.2) # Same as above
|
194
|
+
~~~
|
195
|
+
|
196
|
+
A useful pattern when using this method is just to set the range to the test upper
|
197
|
+
spec limit, Origen will then take care of rounding this to the correct range.
|
198
|
+
|
199
|
+
See the
|
200
|
+
[J750 TestInstance API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/TestInstance.html)
|
201
|
+
for details on the currently available helper methods.
|
202
|
+
|
203
|
+
If you have a good helper method in your application that you think would be a
|
204
|
+
useful addition to Origen please do create a pull request with the additions to the
|
205
|
+
[Origen Testers plugin](https://github.com/Origen-SDK/origen_testers).
|
206
|
+
|
207
|
+
#### Avoiding Duplicate Test Instances
|
208
|
+
|
209
|
+
Your interface does not need to keep track of duplicate instances, Origen will automatically
|
210
|
+
get rid of them.
|
211
|
+
See the discussion "Avoiding Duplicate Tests" in the
|
212
|
+
[Creating an Interface](<%= path "guides/program/interface" %>) guide.
|
213
|
+
|
214
|
+
#### A Note on Test Instance Groups
|
215
|
+
|
216
|
+
IG-XL has the concept of a test instance group, that is a group of test instances that
|
217
|
+
you can call from a single line in the test flow. However the syntax for this in the test instance
|
218
|
+
sheet does not lend itself to easy generation -
|
219
|
+
that is a test instance with the same name as an existing one will be treated as a group if
|
220
|
+
they occur next to each other, whereas it will be a validation error if they are apart.
|
221
|
+
This poses some problems for Origen when it comes to test instance generation - how does it
|
222
|
+
know when the instance your application has requested is a duplicate that should be screened
|
223
|
+
vs. an intentional generation of a group?
|
224
|
+
|
225
|
+
To avoid pushing responsibility of duplicate tracking to the application there is a dedicated
|
226
|
+
method for generating groups. Any instances generated within the given block of code will
|
227
|
+
be treated as a group:
|
228
|
+
|
229
|
+
~~~ruby
|
230
|
+
test_instances.group("vreg_func_all") do |group|
|
231
|
+
$dut.vregs.each_with_index do |vreg, i|
|
232
|
+
test_instances.functional("vreg_func")
|
233
|
+
end
|
234
|
+
end
|
235
|
+
~~~
|
236
|
+
|
237
|
+
See the [group method API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/Base/TestInstances.html#group-instance_method)
|
238
|
+
for more details and examples.
|
239
|
+
|
240
|
+
#### Structuring Your Instance Methods
|
241
|
+
|
242
|
+
As mentioned at the start the vast majority of your J750 interface code will be concerned
|
243
|
+
with generating test instances, so it pays to spend a bit of time up front thinking about
|
244
|
+
how to organize this code into a maintainable architecture.
|
245
|
+
|
246
|
+
The following techniques have proved to be useful in organizing the test instance generation
|
247
|
+
for some very large and complex test flows.
|
248
|
+
|
249
|
+
##### Create Base Instances
|
250
|
+
|
251
|
+
Add methods to create base test instances, that is
|
252
|
+
test instances which contains all of the attributes that every instance in your
|
253
|
+
application will have.
|
254
|
+
|
255
|
+
~~~ruby
|
256
|
+
def base_instance(name, type, options={})
|
257
|
+
ins = test_instances.add(name, type)
|
258
|
+
ins.dc_category = "VREG"
|
259
|
+
if options[:vdd]
|
260
|
+
ins.dc_selector = options[:vdd].to_s.capitalize # If :min, :max for example
|
261
|
+
else
|
262
|
+
ins.dc_selector = "Typ"
|
263
|
+
end
|
264
|
+
ins.ac_category = "Spec"
|
265
|
+
ins.ac_selector = "Default"
|
266
|
+
ins.time_sets = "Tim"
|
267
|
+
ins.pin_levels = "Lvl"
|
268
|
+
ins # Remember to return the newly created instance object to the caller
|
269
|
+
end
|
270
|
+
|
271
|
+
def func(name, options={})
|
272
|
+
ins = base_instance(name, :functional, options)
|
273
|
+
# Additional functional specific configuration here
|
274
|
+
end
|
275
|
+
~~~
|
276
|
+
|
277
|
+
This pattern can be extended to provide additional methods like "base_functional_instance",
|
278
|
+
"base_bpmu_instance" and so on.
|
279
|
+
|
280
|
+
##### Use Decorator Methods
|
281
|
+
|
282
|
+
A decorator method is a method that decorates (or adds to) a test instance with specific
|
283
|
+
functionality.
|
284
|
+
For example in the flagship Origen application, some of our functional test instances required match
|
285
|
+
loop support while others did not, so we created a decorator that we could call to add
|
286
|
+
this feature:
|
287
|
+
|
288
|
+
~~~ruby
|
289
|
+
def add_match(ins)
|
290
|
+
ins.post_test_f = "MatchBinFails"
|
291
|
+
ins.pat_flag_f = "MatchLoopPatFlagFunc"
|
292
|
+
ins.set_wait_flags :a
|
293
|
+
end
|
294
|
+
|
295
|
+
def func(name, options={})
|
296
|
+
ins = base_instance(name, :functional, options)
|
297
|
+
ins.add_match(ins) if some_logic_to_gate_this
|
298
|
+
end
|
299
|
+
~~~
|
300
|
+
|
301
|
+
##### Split Your Application Instances into Logical Groups
|
302
|
+
|
303
|
+
In the flagship application we found it best to conceptually split our test instance
|
304
|
+
generators by application-specific types rather than by sticking to the IG-XL types
|
305
|
+
like functional, BPMU, PPMU, etc.
|
306
|
+
|
307
|
+
It is hard to give a universal example here since this area is so application specific,
|
308
|
+
but to hopefully give you some food for thought...
|
309
|
+
|
310
|
+
In the flagship application we had a lot of parametric tests and initially we went down the
|
311
|
+
path of having an instance generation method for all BPMU tests and one for all PPMU tests.
|
312
|
+
However within those groups some of the tests were very different and it led to a
|
313
|
+
lot of complexity within those methods.
|
314
|
+
|
315
|
+
When we took a step back and looked at our application our tests were not really split into
|
316
|
+
2 types, rather they were comprised of 4 types - a high-voltage measurement, a high-voltage
|
317
|
+
calibration, a low-voltage measurement and a low-voltage calibration.
|
318
|
+
When we continued this process through our test flow as a whole we ended up with 14 different
|
319
|
+
test classifications and we then added a method dedicated to generating the test instance
|
320
|
+
for each one.
|
321
|
+
|
322
|
+
You should probably not go down this path initially, but once you get a feel for the
|
323
|
+
generation process and if your interface is starting to get complex, then this is a step
|
324
|
+
to consider.
|
325
|
+
|
326
|
+
### Creating a Pattern Entry
|
327
|
+
|
328
|
+
The hard part is over, creating pattern sets and groups is trivial by comparison to
|
329
|
+
creating test instances.
|
330
|
+
A similar API is provided to generate pattern resources in your test program and a nice
|
331
|
+
by product is that Origen will keep track of the referenced patterns and will produce a required
|
332
|
+
list of patterns at the end (which you can then pass to the pattern generator).
|
333
|
+
|
334
|
+
As with test instance generation Origen will deal with the suppression of duplicates in all
|
335
|
+
cases.
|
336
|
+
|
337
|
+
To add a pattern set call as follows:
|
338
|
+
|
339
|
+
~~~ruby
|
340
|
+
patsets.add("vreg_func_pset", pattern: "patterns/VREG/vreg_func.PAT")
|
341
|
+
~~~
|
342
|
+
|
343
|
+
Multiple patterns can be specified by passing an array as the 2nd argument:
|
344
|
+
|
345
|
+
~~~ruby
|
346
|
+
patsets.add("vreg_func_pset", [{pattern: "patterns/VREG/vreg_func.PAT"},
|
347
|
+
{pattern: "patterns/VREG/vreg_global_subs.PAT", start_label: "subr"}
|
348
|
+
])
|
349
|
+
~~~
|
350
|
+
|
351
|
+
Creating pattern groups is identical, just substitute <code>patsets</code> with
|
352
|
+
<code>patgroups</code>.
|
353
|
+
|
354
|
+
Normally you would create a dedicated method for creating pattern sets to avoid
|
355
|
+
duplication, something like this:
|
356
|
+
|
357
|
+
~~~ruby
|
358
|
+
def add_patset(name)
|
359
|
+
patsets.add("#{name}_pset", pattern: "patterns/VREG/#{name}.PAT")
|
360
|
+
end
|
361
|
+
~~~
|
362
|
+
|
363
|
+
The pattern set or group object can be assigned to the pattern attribute of a test
|
364
|
+
instance directly:
|
365
|
+
|
366
|
+
~~~ruby
|
367
|
+
def func(name, options={})
|
368
|
+
ins = test_instances.functional(name)
|
369
|
+
ins.pattern = add_patset(name)
|
370
|
+
end
|
371
|
+
~~~
|
372
|
+
|
373
|
+
If you just want to add a pattern reference outside of a pattern set or group then
|
374
|
+
add it to the <code>referenced_patterns</code> array to ensure that it gets added
|
375
|
+
to the list of required patterns that is output from the program generation process:
|
376
|
+
|
377
|
+
~~~ruby
|
378
|
+
referenced_patterns << "some_vreg_pattern"
|
379
|
+
~~~
|
380
|
+
|
381
|
+
### Creating a Flow Entry
|
382
|
+
|
383
|
+
Within your interface the <code>flow</code> method will return an instance of
|
384
|
+
the J750 flow generator which provides methods for adding tests and other entries
|
385
|
+
to your test flow. See the [API](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/Flow.html)
|
386
|
+
for full details.
|
387
|
+
|
388
|
+
So for example to enter a log print statement in the flow you can call:
|
389
|
+
|
390
|
+
~~~ruby
|
391
|
+
flow.logprint "Start of the vreg test section"
|
392
|
+
~~~
|
393
|
+
|
394
|
+
Going back to the earlier example from the [Creating Flows](<%= path "guides/program/flows" %>)
|
395
|
+
guide we had this in our flow:
|
396
|
+
|
397
|
+
~~~ruby
|
398
|
+
log "Vreg test module"
|
399
|
+
~~~
|
400
|
+
|
401
|
+
This is probably the simplest method to implement in our interface:
|
402
|
+
|
403
|
+
~~~ruby
|
404
|
+
def log(msg)
|
405
|
+
flow.logprint(msg)
|
406
|
+
end
|
407
|
+
~~~
|
408
|
+
|
409
|
+
The most common call will be to the <code>test</code> method which will insert a call
|
410
|
+
to a test instance in the flow.
|
411
|
+
**Note that it is recommended that you pass all options from the test flow into any flow methods,
|
412
|
+
this ensures that any [flow control](<%= path "guides/program/flowapi" %>)
|
413
|
+
logic will get implemented**.
|
414
|
+
|
415
|
+
Here is a complete interface method for the first time that will generate a test instance,
|
416
|
+
add a pattern set reference to it, and now finally call the instance from the
|
417
|
+
test flow:
|
418
|
+
|
419
|
+
~~~ruby
|
420
|
+
def func(name, options={})
|
421
|
+
ins = test_instances.functional(name)
|
422
|
+
ins.pattern = add_patset(name)
|
423
|
+
flow.test(ins, options)
|
424
|
+
end
|
425
|
+
~~~
|
426
|
+
|
427
|
+
The object returned from <code>flow.test</code> is an instance of
|
428
|
+
[OrigenTesters::IGXLBasedTester::J750::FlowLine](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/FlowLine.html)
|
429
|
+
and this does provide a few methods that may be of use. However in general most of the
|
430
|
+
methods are there to support flow control and it is not recommended that you use these
|
431
|
+
directly, rather use the [flow control API](<%= path "guides/program/flowapi" %>) to
|
432
|
+
do this.
|
433
|
+
|
434
|
+
However it is recommended that you look at the
|
435
|
+
[TESTER_FLOWLINE_ATTRS](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/J750/FlowLine.html),
|
436
|
+
[ALIASES](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/Base/FlowLine.html),
|
437
|
+
and [DEFAULTS](http://origen-sdk.org/testers/api/OrigenTesters/IGXLBasedTester/Base/FlowLine.html)
|
438
|
+
definitions as this will tell you what the generator calls the IG-XL attributes. For example you can
|
439
|
+
see that the test number attribute is called <code>tnum</code> and that this is also aliased
|
440
|
+
to <code>'number'</code>.
|
441
|
+
|
442
|
+
This means that you can set this attribute via this style (which is most useful
|
443
|
+
for passing attributes through directly from the flow file):
|
444
|
+
|
445
|
+
~~~ruby
|
446
|
+
flow.test(ins, tnum: 10000)
|
447
|
+
~~~
|
448
|
+
|
449
|
+
Or it can also be set via a method call:
|
450
|
+
|
451
|
+
~~~ruby
|
452
|
+
flow_line = flow.test(ins)
|
453
|
+
flow_line.tnum = 10000
|
454
|
+
~~~
|
455
|
+
|
456
|
+
It is recommended that you create a dedicated method for flow insertion as this gives you
|
457
|
+
a single place to implement defaults and to perform any translation between what the flow has
|
458
|
+
called an attribute and what the J750 generator would call it:
|
459
|
+
|
460
|
+
~~~ruby
|
461
|
+
def add_flow_entry(ins, options)
|
462
|
+
# Defaults
|
463
|
+
options = {
|
464
|
+
bin: 5,
|
465
|
+
tname: options[:tname] || options[:name] || ins.name,
|
466
|
+
}.merge(options)
|
467
|
+
|
468
|
+
# Some translations
|
469
|
+
options[:softbin] = options[:sbin] if options[:sbin]
|
470
|
+
|
471
|
+
# Add the flow entry
|
472
|
+
flow_line = flow.test(ins, options)
|
473
|
+
|
474
|
+
# Some final decoration
|
475
|
+
flow_line.continue_on_fail if options[:continue]
|
476
|
+
|
477
|
+
flow_line
|
478
|
+
end
|
479
|
+
~~~
|
480
|
+
|
481
|
+
Here is an example interface method using this add to flow method:
|
482
|
+
|
483
|
+
~~~ruby
|
484
|
+
def func(name, options={})
|
485
|
+
ins = test_instances.functional(name, options)
|
486
|
+
ins.pattern = add_patset(name)
|
487
|
+
add_flow_entry(ins, options)
|
488
|
+
end
|
489
|
+
~~~
|
490
|
+
|
491
|
+
Finally you may on occasion wish to call a test from your flow where the instance
|
492
|
+
is not available - maybe the instance is generated by another test module for example.
|
493
|
+
In this case the <code>:instance_not_available</code> option can be set to <code>true</code>
|
494
|
+
to prevent Origen from trying to match up the flow with an instance object.
|
495
|
+
|
496
|
+
~~~ruby
|
497
|
+
flow.test("POR_INSTANCE", instance_not_available: true)
|
498
|
+
~~~
|
499
|
+
|
500
|
+
### What About My DC Specs?
|
501
|
+
|
502
|
+
Other IG-XL sheets do not currently have generators available, although that is likely
|
503
|
+
to change in the future.
|
504
|
+
|
505
|
+
For now though the existing Origen-based applications have found that the other sheets tend
|
506
|
+
to be simple enough that they can be easily handled via a template-based approach.
|
507
|
+
|
508
|
+
To create a template simply build the sheet in IG-XL, export it to ASCII and this becomes
|
509
|
+
your initial template, then add Ruby snippets as required to make parts of it dynamic.
|
510
|
+
|
511
|
+
See the [Dynamic Custom Code](<%= path "guides/program/code" %>) guide for more details
|
512
|
+
on how to compile a template automatically during a program generation process.
|
513
|
+
|
514
|
+
% end
|