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,99 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
Documentation of a test program is important to allow non-test-engineering stakeholders
|
4
|
+
to understand what is in a given program, or what a given bin number refers to.
|
5
|
+
So Origen fully embraces the notion that test programs should be documented, that
|
6
|
+
this documentation should not have an opportunity to be wrong, and that no one
|
7
|
+
should have to waste their time manually trying to keep a document and the program
|
8
|
+
in sync.
|
9
|
+
|
10
|
+
However many tools in this area approach this
|
11
|
+
problem by trying to turn documentation into a test program.
|
12
|
+
Origen turns this problem on its head and unashamedly asserts that the test program
|
13
|
+
itself is the true source of authority as to what it does, and that documentation
|
14
|
+
is the follower instead of the leader.
|
15
|
+
|
16
|
+
This approach has the following advantages:
|
17
|
+
|
18
|
+
* Test programs are large and complex, who really wants to write the whole thing
|
19
|
+
out manually? It is much more efficient (and less error prone) to write it in code,
|
20
|
+
then we can use subroutines, variables, object-orientation, meta-programming (code
|
21
|
+
that generates other code) and any other programming
|
22
|
+
techniques to eliminate duplication and opportunities for error.
|
23
|
+
* Document first approaches are always constrained by the fact that some tests are
|
24
|
+
more complicated than others. In a recent industry conference a leading document-first
|
25
|
+
generator stated that typically it could handle 80% of tests, for the other 20%
|
26
|
+
you were on your own. With Origen's approach 100% of your tests will be generated.
|
27
|
+
|
28
|
+
#### The Chicken and the Egg Problem
|
29
|
+
|
30
|
+
One problem with the Origen approach is how do you bootstrap a new program, intuitively
|
31
|
+
you may want to document it first.
|
32
|
+
|
33
|
+
This problem can be solved via the following workflow:
|
34
|
+
|
35
|
+
* The Flow file syntax is designed to be as simple and human-readable as possible,
|
36
|
+
and it is self contained and can exist long before any interfaces are ever written.
|
37
|
+
Therefore it you know enough to be able to write a document of a flow, then you
|
38
|
+
know enough to be able to write an Origen flow file for that flow.
|
39
|
+
* Nonetheless some early stakeholders may want to get involved in the definition
|
40
|
+
but won't feel comfortable with the code layer. In this case it is recommended
|
41
|
+
that you immediately setup a documentation interface (these are trivially simple
|
42
|
+
and will probably eventually come from free with Origen), and begin generating
|
43
|
+
documentation of the flow from day 1.
|
44
|
+
* Definition can continue as required by iterating on the flow file, all the while
|
45
|
+
the documentation stays in sync.
|
46
|
+
* When it comes to finally implementing the flow the test engineering team will
|
47
|
+
create the interface which will turn it into a real test program.
|
48
|
+
|
49
|
+
An alternative approach is to have a short-lived hand-written document that is used
|
50
|
+
to get the team up to the first release of the test program. At that point authority
|
51
|
+
should switch to the program itself and a ticketing system should be used to iterate on
|
52
|
+
the program...
|
53
|
+
|
54
|
+
#### How Do I Specify a Program Change if I Don't Know How to Code?
|
55
|
+
|
56
|
+
The underlying program application should use a ticketing system.
|
57
|
+
Any non-test-engineering stake holders can review the documentation to see what the test program
|
58
|
+
currently does, then if they want it to do something else they will raise a ticket
|
59
|
+
requesting it.
|
60
|
+
|
61
|
+
Once the change has been implemented the ticket can be closed and the documentation
|
62
|
+
will automatically pick up the change.
|
63
|
+
|
64
|
+
This workflow is much easier to monitor and track status vs. the alternative approach where
|
65
|
+
the non-technical stakeholder release new versions of a document and the TE has the job of trying
|
66
|
+
to keep the program in sync.
|
67
|
+
|
68
|
+
#### But I already have a document containing a lot of my test details!
|
69
|
+
|
70
|
+
As the flow file is written in Ruby, it is perfectly feasible to build higher level structures
|
71
|
+
such as an importer, or even a spreadsheet-based interface on top of this.
|
72
|
+
|
73
|
+
The early users of the Origen test program generator have not had a need for such an approach,
|
74
|
+
however this is definitely an area where the [community](<%= path "community" %>) could start
|
75
|
+
to build new features.
|
76
|
+
|
77
|
+
#### Shouldn't a Program Generator build me a complete test?
|
78
|
+
|
79
|
+
It's Origen's job to provide a solid generation platform, however it deliberately does not
|
80
|
+
try to dictate how a functional/parametric/bitmap/ATD ramp/etc. test should be set up.
|
81
|
+
Firstly the scope of such an effort is too large, but secondly the Origen developers do
|
82
|
+
not necessarily have the knowledge required to dictate what is the best practice
|
83
|
+
in a lot of these areas.
|
84
|
+
|
85
|
+
However the idea of eliminating the interface layer is appealing and the good news is
|
86
|
+
that it is achievable.
|
87
|
+
|
88
|
+
The [Origen Plugins](<%= path "guides/plugins/introduction" %>) feature provides a way
|
89
|
+
for Origen code to be easily packaged into a re-usable plugin and shared between projects. So for
|
90
|
+
example, an ATD interface module could be written and then anyone wishing to create ATD
|
91
|
+
tests, could import this into their application and completely bypass the interface
|
92
|
+
creation step altogether. Just call the interface methods from the flow file and you will get a
|
93
|
+
guaranteed working (and hopefully efficient!) ATD test.
|
94
|
+
|
95
|
+
If you are a test expert in a given area, and you are using Origen to generate your program,
|
96
|
+
then we would encourage you to share your expertize by making your test setups available
|
97
|
+
as an Origen plugin.
|
98
|
+
|
99
|
+
% end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
When generating a complete test program it may be necessary to build some components
|
4
|
+
that don't naturally fall out of the regular flow generation.
|
5
|
+
Some examples of this might be:
|
6
|
+
|
7
|
+
* Creating a test which does not have a flow entry, but perhaps you want to keep it
|
8
|
+
available in your program for engineering use.
|
9
|
+
* Creating a test program sheet or file that is not supported by an Origen generator,
|
10
|
+
e.g. the IG-XL DC Specs sheet does not currently have a generator.
|
11
|
+
* Creating custom VB, C++ or similar code to support your tests.
|
12
|
+
|
13
|
+
All of these goals can be fulfilled by using a Resources file. Resources files are
|
14
|
+
very similar to the Flow files that we have already seen, the main difference is that
|
15
|
+
any flow entries generated within a Resources file will automatically be inhibited.
|
16
|
+
|
17
|
+
This makes generating tests and their resources (e.g. pattern sets, etc.) without a flow
|
18
|
+
entry extremely easy - just use the same code that you would normally use in the Flow
|
19
|
+
file and you will automatically get everything needed for the test without the flow
|
20
|
+
entry.
|
21
|
+
|
22
|
+
Resource files are syntactically equivalent to Flow files except that all references to
|
23
|
+
<code>Flow</code> are replaced by <code>Resources</code>:
|
24
|
+
|
25
|
+
~~~ruby
|
26
|
+
# program/probe_resources.rb
|
27
|
+
Resources.create do
|
28
|
+
|
29
|
+
end
|
30
|
+
~~~
|
31
|
+
|
32
|
+
So for example without changing our interface at all we can drop some of our previous
|
33
|
+
Flow code into the resources file (flow specific attributes such as bin numbers can
|
34
|
+
be removed):
|
35
|
+
|
36
|
+
~~~ruby
|
37
|
+
# program/probe_resources.rb
|
38
|
+
Resources.create do
|
39
|
+
|
40
|
+
func :vreg_functional
|
41
|
+
|
42
|
+
para :vreg_meas, lo: 1.12, hi: 1.34
|
43
|
+
|
44
|
+
end
|
45
|
+
~~~
|
46
|
+
|
47
|
+
This would generate the same program as before but with no flow entries for the generated
|
48
|
+
tests.
|
49
|
+
|
50
|
+
Parameterizable sub-resource files can be created in exactly the same way as sub-flow files.
|
51
|
+
|
52
|
+
#### Compiling Templates
|
53
|
+
|
54
|
+
Another common use case for a Resources file is to co-ordinate the compilation of template
|
55
|
+
files.
|
56
|
+
|
57
|
+
See the [Compiler section](<%= path "guides/compiler/introduction" %>) for details on
|
58
|
+
how to create templates.
|
59
|
+
|
60
|
+
A <code>compile</code> method is available with a Resources file to invoke and customize
|
61
|
+
the compilation of a specific file. Any arguments passed in will be accessible within the
|
62
|
+
template via its <code>options</code> method.
|
63
|
+
|
64
|
+
~~~ruby
|
65
|
+
# program/common_resources.rb
|
66
|
+
Resources.create do
|
67
|
+
|
68
|
+
compile "templates/j750/DCSpecs.txt", max_vdd: 5.V
|
69
|
+
|
70
|
+
compile "templates/j750/GlobalSpecs.txt", vreg_period: 40.ns
|
71
|
+
|
72
|
+
end
|
73
|
+
~~~
|
74
|
+
|
75
|
+
#### Separating Test Generation from Flow Generation
|
76
|
+
|
77
|
+
As discussed previously a conventional Origen program generation flow would be to generate
|
78
|
+
both the flow and the tests from a single flow file. However it is also possible to
|
79
|
+
generate the program in a more traditional way where the test and flow generation are
|
80
|
+
separated.
|
81
|
+
|
82
|
+
To do this use Resources files to generate the tests and all of their dependencies. This
|
83
|
+
would look very much like the flow file examples we have seen so far, the main difference
|
84
|
+
would be that each test would only ever appear once (although if you did generate duplicates
|
85
|
+
by accident Origen would still take care of it).
|
86
|
+
|
87
|
+
Then to define the flow you would have Flow files that called interface methods to insert
|
88
|
+
flow entries only.
|
89
|
+
This flow file would be a simplified version of what we have seen so far since the
|
90
|
+
attributes of the test are no longer required.
|
91
|
+
For example you might make a new interface method called 'test' which calls a test
|
92
|
+
in the flow - at flow level there is no longer any conceptual difference between
|
93
|
+
a parametric test and a functional test and so they can all use the same method.
|
94
|
+
Here is a previous example that only contains the flow concerns (includes 'cz' and
|
95
|
+
'bin_out' methods since these are also flow level concerns):
|
96
|
+
|
97
|
+
~~~ruby
|
98
|
+
Flow.create do
|
99
|
+
|
100
|
+
test :vreg_meas, softbin: 105, id: :vreg_meas_1
|
101
|
+
|
102
|
+
if_failed :vreg_meas_1 do
|
103
|
+
# Automatically characterize the vreg if the measurement fails
|
104
|
+
cz :vreg_meas, softbin: 107
|
105
|
+
# Then bin out
|
106
|
+
bin_out softbin: 105
|
107
|
+
end
|
108
|
+
|
109
|
+
# Check if the HVST has already been run on this device
|
110
|
+
test :rd_vreg_hvst_passcode, softbin: 50, id: :vreg_hvst_done
|
111
|
+
|
112
|
+
unless_passed :vreg_hvst_done do
|
113
|
+
# If not run it
|
114
|
+
test :vreg_hvst, softbin: 101
|
115
|
+
# And program the flag for next time
|
116
|
+
test :pgm_vreg_hvst_passcode, softbin: 51
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
~~~
|
121
|
+
|
122
|
+
If you want to use the same methods in the Resources and Flow files you can use the
|
123
|
+
<code>resources_mode?</code> method within your interface to control when the flow
|
124
|
+
or the tests should be generated. This method will return true if the interface method
|
125
|
+
has been called from a Resources file:
|
126
|
+
|
127
|
+
~~~ruby
|
128
|
+
# lib/vreg/interface.rb
|
129
|
+
|
130
|
+
# Create a functional test and call it from the flow
|
131
|
+
def func(name, options={})
|
132
|
+
name = namer(name, options)
|
133
|
+
if resources_mode?
|
134
|
+
# generate the test
|
135
|
+
else
|
136
|
+
# generate the flow entry
|
137
|
+
end
|
138
|
+
end
|
139
|
+
~~~
|
140
|
+
|
141
|
+
% end
|
@@ -0,0 +1,456 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
### Flow Considerations
|
4
|
+
|
5
|
+
By default, a top-level `Flow.create` call in Origen will generate a standalone V93K testflow file which is
|
6
|
+
internally wrapped by a flow group, like this:
|
7
|
+
|
8
|
+
~~~text
|
9
|
+
group <FLOW_NAME> {
|
10
|
+
// Flow content here
|
11
|
+
}
|
12
|
+
~~~
|
13
|
+
|
14
|
+
When such flows are imported into a master flow file, SmarTest does not provide a standard enable mechanism
|
15
|
+
to control which sub-flows are executed.
|
16
|
+
|
17
|
+
However, Origen provides the ability to generate V93K flow modules with an enable-word wrapper, thereby allowing
|
18
|
+
the top-level flow to easily enable/disable the execution of flow modules via flow variables.
|
19
|
+
|
20
|
+
By enabling this feature in the target like this:
|
21
|
+
|
22
|
+
~~~ruby
|
23
|
+
OrigenTesters::V93K.new(add_flow_enable: :enabled)
|
24
|
+
~~~
|
25
|
+
|
26
|
+
the flow will now generate like this:
|
27
|
+
|
28
|
+
~~~text
|
29
|
+
group <FLOW_NAME> {
|
30
|
+
if @<FLOW_NAME>_ENABLE == 1 {
|
31
|
+
// Flow content here
|
32
|
+
}
|
33
|
+
}
|
34
|
+
~~~
|
35
|
+
|
36
|
+
The `@<FLOW_NAME>_ENABLE` variable will be initialized to 1 in the generated variables file for the given flow,
|
37
|
+
meaning that the module will run by default if the top-level flow does nothing with this variable.
|
38
|
+
|
39
|
+
Alternatively, the variable can be initialized to off like this:
|
40
|
+
|
41
|
+
~~~ruby
|
42
|
+
OrigenTesters::V93K.new(add_flow_enable: :disabled)
|
43
|
+
~~~
|
44
|
+
|
45
|
+
Meaning that by default, the module will not run and the top-level flow must always enable it by including
|
46
|
+
`@<FLOW_NAME>_ENABLE = 1` before hitting the module.
|
47
|
+
|
48
|
+
Setting this attribute in the target means that it will apply to all flows. Alternatively, it can be set within
|
49
|
+
the flow itself (or the interface) if it is necessary to use this feature for only a subset of flows, or to override
|
50
|
+
the default setting for a particular flow.
|
51
|
+
|
52
|
+
Here is an example:
|
53
|
+
|
54
|
+
~~~ruby
|
55
|
+
Flow.create interface: 'MyApp::Interface' do
|
56
|
+
|
57
|
+
# Ensure that this flow is always generated with an enable word wrapper that is enabled by default
|
58
|
+
self.add_flow_enable = :enabled
|
59
|
+
|
60
|
+
# Some functional test
|
61
|
+
func :blah
|
62
|
+
end
|
63
|
+
~~~
|
64
|
+
|
65
|
+
This same API may be used to implement similar features on other platforms in future, but for now only the V93K is implemented.
|
66
|
+
|
67
|
+
|
68
|
+
### Interface Considerations
|
69
|
+
|
70
|
+
Be sure to read and understand the guide to
|
71
|
+
[Creating an Interface](<%= path "guides/program/interface" %>) before
|
72
|
+
reading this section.
|
73
|
+
This guide will describe the API to generate V93K/SmarTest test program
|
74
|
+
components from within an interface file.
|
75
|
+
|
76
|
+
To re-cap this is the shell required to implement an interface:
|
77
|
+
|
78
|
+
~~~ruby
|
79
|
+
# lib/vreg/interface.rb
|
80
|
+
module Vreg
|
81
|
+
class Interface
|
82
|
+
include OrigenTesters::ProgramGenerators
|
83
|
+
|
84
|
+
# An example method that can be called from your test flow to generate a functional test
|
85
|
+
def func(name, options={})
|
86
|
+
# If your interface supports multiple platforms, add conditional logic like this, if you
|
87
|
+
# only ever want to support one platform then you don't need this
|
88
|
+
if tester.j750?
|
89
|
+
# Functional test implementation for J750
|
90
|
+
elsif tester.v93k?
|
91
|
+
# Functional test implementation for V93K
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
~~~
|
98
|
+
|
99
|
+
The <code>OrigenTesters::ProgramGenerators</code> will provide the interface
|
100
|
+
with access to all of the platform generator APIs for the platforms that it supports.
|
101
|
+
|
102
|
+
If your interface supports multiple platforms then add conditional logic to separate
|
103
|
+
them as shown above.
|
104
|
+
|
105
|
+
#### Creating a Test Suite
|
106
|
+
|
107
|
+
Most of the effort in generating a V93K test program is in generating the test suites and their
|
108
|
+
associated test methods.
|
109
|
+
|
110
|
+
A new test suite and test method can be instantiated and linked together like this:
|
111
|
+
|
112
|
+
~~~ruby
|
113
|
+
t = test_suites.add(:vreg_func)
|
114
|
+
t.test_method = test_methods.origen.functional_test
|
115
|
+
~~~
|
116
|
+
|
117
|
+
These lines of code do the following things:
|
118
|
+
|
119
|
+
* Instantiates a new test suite object and assigns it to the local variable <code>t</code>
|
120
|
+
* Sets its name to 'vreg_func' and inserts it into the flow file (but not into the actual test flow)
|
121
|
+
* Instantiates a new functional test method object and attaches it to the test suite
|
122
|
+
* Inserts the test method into the flow file (but not into the actual test flow)
|
123
|
+
|
124
|
+
You will of course want to then decorate your new test with attributes that are specific
|
125
|
+
to your application, here for example to set the levels and timing:
|
126
|
+
|
127
|
+
~~~ruby
|
128
|
+
t.tim_equ_set = 15
|
129
|
+
t.tim_spec_set = 1
|
130
|
+
t.timset = 1
|
131
|
+
t.lev_equ_set = 20
|
132
|
+
t.lev_spec_set = 8
|
133
|
+
t.levset = 1
|
134
|
+
~~~
|
135
|
+
|
136
|
+
If the test method provides parameters, you can set them in the same way. As a convenience,
|
137
|
+
Origen will automatically work out whether the reference is to a parameter of the test suite
|
138
|
+
or of the test method, and will assign it accordingly.
|
139
|
+
For example, let's say this functional test method had a parameter named <code>checkShutdown</code>, you
|
140
|
+
could set that like this:
|
141
|
+
|
142
|
+
~~~ruby
|
143
|
+
t.check_shutdown = 1 # By Ruby convention, use the lower-cased underscored version of the C++ name
|
144
|
+
|
145
|
+
# The above is a shorthand equivalent to:
|
146
|
+
t.test_method.check_shutdown = 1
|
147
|
+
~~~
|
148
|
+
|
149
|
+
Attributes can also be passed in when instantiating the new test suite/method, this is equivalent
|
150
|
+
if you prefer:
|
151
|
+
|
152
|
+
~~~
|
153
|
+
t = test_suites.add(:vreg_func, tim_equ_set: 15, tim_spec_set: 1, timset: 1, lev_equ_set: 20)
|
154
|
+
t.test_method = test_methods.origen.functional_test(check_shutdown: 1)
|
155
|
+
~~~
|
156
|
+
|
157
|
+
#### Limits
|
158
|
+
|
159
|
+
The limits can be set for all test objects using the following API, see here for some examples
|
160
|
+
[of the available unit helpers](<%= path 'guides/misc/coreext/#Unit_Helpers' %>):
|
161
|
+
|
162
|
+
~~~ruby
|
163
|
+
t.lo_limit = 100.uA
|
164
|
+
t.hi_limit = 150.uA
|
165
|
+
~~~
|
166
|
+
|
167
|
+
#### Built-in Test Methods
|
168
|
+
|
169
|
+
SmarTest comes with a standard AC and DC test method library and Origen provides a built-in API to
|
170
|
+
generate a test flow which uses those test methods, here are some examples:
|
171
|
+
|
172
|
+
~~~ruby
|
173
|
+
# Execute a functional test
|
174
|
+
test_method = test_methods.ac_tml.ac_test.functional_test
|
175
|
+
|
176
|
+
# A basic DC voltage measurement
|
177
|
+
test_method = test_methods.dc_tml.dc_test.general_pmu force_mode: 'CURR', force_value: 100.uA
|
178
|
+
~~~
|
179
|
+
|
180
|
+
Generally the parameter naming is the lower-cased and underscored version of the name that appears
|
181
|
+
in the SMT documentation.
|
182
|
+
|
183
|
+
See the [DC library API](http://origen-sdk.org/testers/api/OrigenTesters/SmartestBasedTester/Base/TestMethods/DcTml.html)
|
184
|
+
and the [AC library API](http://origen-sdk.org/testers/api/OrigenTesters/SmartestBasedTester/Base/TestMethods/AcTml.html)
|
185
|
+
for up-to-date details of the implemented test methods and the parameter names.
|
186
|
+
|
187
|
+
However, some of these test methods are not particularly good and the recommendation from Advantest these
|
188
|
+
days is generally not to use them.
|
189
|
+
|
190
|
+
Since that means there is now a void where a universally available test method library should be, work is
|
191
|
+
underway to provide an Origen standard test method library.
|
192
|
+
The aim of this is to provide a complete generation solution from Origen so that those who have
|
193
|
+
a fairly conventional use case can rapidly build a complete test program from off-the-shelf
|
194
|
+
components, but that is still a work in progress and not yet ready for prime time use.
|
195
|
+
|
196
|
+
Many users of the V93K program generator however, are likely to want to use it in combination
|
197
|
+
with their own custom test method library...
|
198
|
+
|
199
|
+
#### Custom Test Methods
|
200
|
+
|
201
|
+
An API exists to define the naming and parameter signature of test methods provided by
|
202
|
+
a 3rd party library, enabling them to be used within an interface exactly like in the examples above.
|
203
|
+
Additionally, it is possible to define helper methods that are associated with each test method,
|
204
|
+
making them easier to use within an Origen test program interface.
|
205
|
+
|
206
|
+
This is best shown by example, here is how to define a custom test method library and a custom
|
207
|
+
test method within an Origen interface:
|
208
|
+
|
209
|
+
~~~ruby
|
210
|
+
# lib/vreg/interface.rb
|
211
|
+
module Vreg
|
212
|
+
class Interface
|
213
|
+
include OrigenTesters::ProgramGenerators
|
214
|
+
|
215
|
+
def initialize(options={})
|
216
|
+
add_my_tml if tester.v93k?
|
217
|
+
end
|
218
|
+
|
219
|
+
# Define the test methods from a custom V93K library
|
220
|
+
def add_my_tml
|
221
|
+
# The identifier you give here is what you will use to access the test methods from your interface
|
222
|
+
# code, for example: test_methods.my_tml.my_test
|
223
|
+
#
|
224
|
+
# This will also be the C++ namespace that is used within SMT to access the test method classes
|
225
|
+
# defined in this library.
|
226
|
+
add_tml :my_tml,
|
227
|
+
# [OPTIONAL] If you need the C++ namespace to be different to the above identifier then you can
|
228
|
+
# specify the C++ name like this:
|
229
|
+
class_name: 'MyTmlNamespace',
|
230
|
+
|
231
|
+
# Here is a test definition.
|
232
|
+
# The identifier should be lower-cased and underscored, in-keeping with Ruby naming conventions.
|
233
|
+
# By default the class name will be the camel-cased version of this identifier, so 'myTest' in
|
234
|
+
# this case.
|
235
|
+
my_test: {
|
236
|
+
# [OPTIONAL] The C++ test method class name can be overridden from the default like this:
|
237
|
+
class_name: 'MyTestClass',
|
238
|
+
# Parameters can be defined with an underscored symbol as the name, this can be used
|
239
|
+
# if the C++ implementation follows the standard V93K convention of calling the attribute
|
240
|
+
# the camel cased version, starting with a lower-cased letter, i.e. 'testerState' in this
|
241
|
+
# first example.
|
242
|
+
# The attribute definition has two required parameters, the type and the default value.
|
243
|
+
# The type can be :string, :current, :voltage, :time, :frequency, or :integer
|
244
|
+
pin_list: [:string, ''],
|
245
|
+
samples: [:integer, 1],
|
246
|
+
precharge_voltage: [:voltage, 0],
|
247
|
+
settling_time: [:time, 0],
|
248
|
+
# An optional parameter that sets the limits name in the 'testmethodlimits' section
|
249
|
+
# of the generated .tf file. Defaults to 'Functional' if not provided.
|
250
|
+
test_name: [:string, 'SpecSearch']
|
251
|
+
# An optional 3rd parameter can be supplied to provide an array of allowed values. If supplied,
|
252
|
+
# Origen will raise an error upon an attempt to set it to an unlisted value.
|
253
|
+
tester_state: [:string, 'CONNECTED', %w(CONNECTED UNCHANGED DISCONNECTED)],
|
254
|
+
force_mode: [:string, 'VOLT', %w(VOLT CURR)],
|
255
|
+
# The name of another parameter can be supplied as the type argument, meaning that the type
|
256
|
+
# here will be either :current or :voltage depending on the value of :force_mode
|
257
|
+
force_value: [:force_mode, 3800.mV],
|
258
|
+
# In cases where the C++ library has deviated from standard attribute naming conventions
|
259
|
+
# (camel-cased with lower cased first character), the absolute attribute name can be given
|
260
|
+
# as a string.
|
261
|
+
# The Origen accessor for these will be the underscored version, with '.' characters
|
262
|
+
# converted to underscores e.g. tm.an_unusual_name
|
263
|
+
'An.UnusualName' => [:string, 'NO', %w(NO YES)],
|
264
|
+
# Attribute aliases can be defined like this:
|
265
|
+
aliases: {
|
266
|
+
my_name: 'An.UnusualName',
|
267
|
+
precharge: :precharge_voltage,
|
268
|
+
},
|
269
|
+
# Define any methods you want the test method to have
|
270
|
+
methods: {
|
271
|
+
# If you define a method called 'finalize', it will be called automatically before the test
|
272
|
+
# method is finally rendered, making it a good place to do any last minute attribute
|
273
|
+
# manipulation based on the final values that have been set by the user.
|
274
|
+
# The test method object itself will be passed in as an argument.
|
275
|
+
#
|
276
|
+
# In this example it will set the pre-charge if it has not already been set and a voltage is
|
277
|
+
# being forced above a given threshold.
|
278
|
+
finalize: -> (tm) {
|
279
|
+
if tm.force_mode == 'VOLT' && tm.precharge_voltage == 0 && tm.force_value > 3.5.V
|
280
|
+
# Set the pre-charge level to 1V below the force value
|
281
|
+
tm.precharge_voltage = tm.force_value - 1.V
|
282
|
+
end
|
283
|
+
},
|
284
|
+
# Example of a custom helper method, here to provide a single method to force a current and
|
285
|
+
# which will configure multiple test method attributes.
|
286
|
+
force_current: -> (tm, value) {
|
287
|
+
tm.force_mode = 'CURR'
|
288
|
+
tm.force_value = value
|
289
|
+
},
|
290
|
+
}
|
291
|
+
},
|
292
|
+
|
293
|
+
my_other_test: {
|
294
|
+
# Define another test in exactly the same way...
|
295
|
+
}
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
~~~
|
300
|
+
|
301
|
+
Here is an example of how the above definition might be used with test program interface logic:
|
302
|
+
|
303
|
+
~~~ruby
|
304
|
+
# An example method that can be called from your test flow to generate a DC measurement test like this:
|
305
|
+
#
|
306
|
+
# measure :vreg, force: 10.uA, lo_limit: 1.25, hi_limit: 1.75
|
307
|
+
#
|
308
|
+
# measure :iref, force: 1.2.V, lo_limit: 20.uA, hi_limit: 30.uA, type: :current
|
309
|
+
def measure(name, options={})
|
310
|
+
t = test_suites.add(name, options)
|
311
|
+
t.test_method = test_methods.my_tml.my_test(pin_list: '@')
|
312
|
+
if options[:type] == :current
|
313
|
+
# Force mode is 'VOLT' by default per the above definition
|
314
|
+
t.force_value = options[:force]
|
315
|
+
else
|
316
|
+
# Here calling the helper method to configure the method for force current mode
|
317
|
+
t.force_current(options[:force])
|
318
|
+
end
|
319
|
+
end
|
320
|
+
~~~
|
321
|
+
|
322
|
+
#### Distribute as a Plugin
|
323
|
+
|
324
|
+
Commonly, a custom test method library will not be specific to any one test program application and
|
325
|
+
it will be used by many test programs within a group or company.
|
326
|
+
In such a case, you don't want to have the Origen definition of the given library be duplicated in all
|
327
|
+
of your applications. Rather, it is preferable to develop and maintain the definition in a central place
|
328
|
+
and then include it in all of the applications that wish to use the library.
|
329
|
+
|
330
|
+
This can be easily achieved by wrapping the Origen definition
|
331
|
+
[in an Origen plugin](<%= path 'guides/plugins/introduction' %>).
|
332
|
+
|
333
|
+
Here is an example of how to package a library definition for inclusion in a plugin:
|
334
|
+
|
335
|
+
~~~ruby
|
336
|
+
# lib/my_library.rb within the my_library plugin
|
337
|
+
module MyLibrary
|
338
|
+
# Define the test methods from a custom V93K library
|
339
|
+
def add_my_library
|
340
|
+
# The definition here is identical to the original example above
|
341
|
+
add_tml :my_tml,
|
342
|
+
# [OPTIONAL] If you need the C++ namespace to be different to the above identifier then you can
|
343
|
+
# specify the C++ name like this:
|
344
|
+
class_name: 'MyTmlNamespace',
|
345
|
+
|
346
|
+
# Here is a test definition.
|
347
|
+
# The identifier should be lower-cased and underscored, in-keeping with Ruby naming conventions.
|
348
|
+
# By default the class name will be the camel-cased version of this identifier, so 'myTest' in
|
349
|
+
# this case.
|
350
|
+
my_test: {
|
351
|
+
|
352
|
+
# ...
|
353
|
+
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# [OPTIONAL] You can also supply complete interface method definitions which use this library
|
358
|
+
# An example method that can be called from your test flow to generate a DC measurement test like this:
|
359
|
+
#
|
360
|
+
# measure :vreg, force: 10.uA, lo_limit: 1.25, hi_limit: 1.75
|
361
|
+
#
|
362
|
+
# measure :iref, force: 1.2.V, lo_limit: 20.uA, hi_limit: 30.uA, type: :current
|
363
|
+
def measure(name, options={})
|
364
|
+
t = test_suites.add(name, options)
|
365
|
+
t.test_method = test_methods.my_tml.my_test(pin_list: '@')
|
366
|
+
if options[:type] == :current
|
367
|
+
# Force mode is 'VOLT' by default per the above definition
|
368
|
+
t.force_value = options[:force]
|
369
|
+
else
|
370
|
+
# Here calling the helper method to configure the method for force current mode
|
371
|
+
t.force_current(options[:force])
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
~~~
|
376
|
+
|
377
|
+
Then simply add the plugin to a given application, and it can be used within an interface like this:
|
378
|
+
|
379
|
+
~~~ruby
|
380
|
+
module MyApp
|
381
|
+
class Interface
|
382
|
+
include OrigenTesters::ProgramGenerators
|
383
|
+
include MyLibrary
|
384
|
+
|
385
|
+
def initialize(options={})
|
386
|
+
add_my_library
|
387
|
+
end
|
388
|
+
|
389
|
+
# You don't need to do anything here, and your flow will already support the measure method!
|
390
|
+
|
391
|
+
# Some application-specific flow method that uses the library:
|
392
|
+
def some_test(name, options = {})
|
393
|
+
t = test_suites.add(name, options)
|
394
|
+
t.test_method = test_methods.my_tml.my_other_test
|
395
|
+
t.some_parameter = #...
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
~~~
|
400
|
+
|
401
|
+
For a more advanced integration which gets rid of the need to even call `add_my_library`, you
|
402
|
+
can refer to how the `origen_std_lib` interface integration works
|
403
|
+
[here](https://github.com/Origen-SDK/origen_std_lib/blob/master/plugin/lib/origen_std_lib.rb).
|
404
|
+
|
405
|
+
### Test Name Uniqueness
|
406
|
+
|
407
|
+
Test (suite) naming collisions can occur when importing multiple independent test flow modules into a
|
408
|
+
V93K master flow file.
|
409
|
+
|
410
|
+
To prevent that from ever occurring, Origen will generate and append a unique signature to the end of
|
411
|
+
all test names by default, for example:
|
412
|
+
|
413
|
+
~~~ruby
|
414
|
+
t = test_suites.add("my_test_name", options)
|
415
|
+
|
416
|
+
t.name # => "my_test_name_E32ABE8"
|
417
|
+
~~~
|
418
|
+
|
419
|
+
Applications can override this default behavior by setting the corresponding test interface attribute,
|
420
|
+
`unique_test_names`, to one of the following values:
|
421
|
+
|
422
|
+
* `:signature` - this is the default which will generate a unique signature as shown in the above example
|
423
|
+
* `nil` - no value will be appended to the test names at all
|
424
|
+
* `:flowname` - the name of the current top-level flow will be appended to all test names
|
425
|
+
* Setting this attribute to any other value will append that value directly to all test names
|
426
|
+
|
427
|
+
This attribute can be set in the [environment file](<%= path 'guides/runtime/environment' %>) when instantiating
|
428
|
+
the tester:
|
429
|
+
|
430
|
+
~~~ruby
|
431
|
+
OrigenTesters::V93K.new unique_test_names: nil
|
432
|
+
~~~
|
433
|
+
|
434
|
+
This provides a single place to control the behavior within a [monolithic application architecture](<%= path 'guides/starting/architecture/#Monolithic_Application_Architecture' %>).
|
435
|
+
|
436
|
+
However, under a [distributed application architecture](<%= path 'guides/starting/architecture/#Distributed_Application_Architecture' %>)
|
437
|
+
a given test flow module may be generated under a target/environment that is controlled by a 3rd party.
|
438
|
+
|
439
|
+
In that case, it is recommended to either set it at the flow-level, which will override any setting set at the
|
440
|
+
environment-level:
|
441
|
+
|
442
|
+
~~~ruby
|
443
|
+
# program/wt1_start.rb
|
444
|
+
Flow.create interface: 'MyApp::Interface', unique_test_names: 'wt1' do
|
445
|
+
|
446
|
+
end
|
447
|
+
~~~
|
448
|
+
|
449
|
+
Or, it can be set directly within your interface logic which will take the highest precedence:
|
450
|
+
|
451
|
+
~~~ruby
|
452
|
+
# lib/my_app/interface.rb
|
453
|
+
self.unique_test_names = :flowname
|
454
|
+
~~~
|
455
|
+
|
456
|
+
% end
|