origen_testers 0.45.3 → 0.48.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +5 -5
  2. data/config/application.rb +1 -0
  3. data/config/version.rb +2 -2
  4. data/lib/origen_testers.rb +1 -0
  5. data/lib/origen_testers/atp/flow.rb +4 -0
  6. data/lib/origen_testers/charz.rb +421 -0
  7. data/lib/origen_testers/charz/profile.rb +120 -0
  8. data/lib/origen_testers/charz/routine.rb +38 -0
  9. data/lib/origen_testers/charz/routines/search_routine.rb +42 -0
  10. data/lib/origen_testers/charz/routines/shmoo_routine.rb +62 -0
  11. data/lib/origen_testers/charz/session.rb +100 -0
  12. data/lib/origen_testers/igxl_based_tester/base.rb +14 -0
  13. data/lib/origen_testers/origen_ext/generator/flow.rb +1 -0
  14. data/lib/origen_testers/smartest_based_tester/base/flow.rb +1 -1
  15. data/lib/origen_testers/smartest_based_tester/base/limits_file.rb +7 -3
  16. data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +2 -2
  17. data/lib/origen_testers/smartest_based_tester/base/test_method.rb +7 -1
  18. data/lib/origen_testers/smartest_based_tester/base/test_methods/base_tml.rb +18 -7
  19. data/lib/origen_testers/smartest_based_tester/base/test_methods/dc_tml.rb +1 -1
  20. data/lib/origen_testers/smartest_based_tester/base/variables_file.rb +16 -12
  21. data/lib/origen_testers/smartest_based_tester/v93k/templates/vars.tf.erb +10 -6
  22. data/lib/origen_testers/test/interface.rb +80 -0
  23. data/pattern/tester_overlay_no_start.rb +41 -0
  24. data/program/charz.rb +48 -0
  25. data/program/prb1.rb +1 -1
  26. data/templates/origen_guides/pattern/ultraflex.md.erb +20 -0
  27. data/templates/origen_guides/program/charz.md.erb +221 -0
  28. metadata +43 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 6faf36c86859e96420d8f5a3ca695f7667ba11325a420229b7b450be5b1dad04
4
- data.tar.gz: 4629dce6b089f5d9cfc1a63d780b987f80d13fcf09487a0c2c0254d09571fc93
2
+ SHA1:
3
+ metadata.gz: aab714d801c978890bf63dcf475ccf275b87b54e
4
+ data.tar.gz: 37d3ef0d30281f9e467ba8475957aacebdb2959a
5
5
  SHA512:
6
- metadata.gz: 1be29af63ad12f1d87e5b3c39d14d4c1a561002d5c728520378c29737674dbddb821aae8e7a4ab1209fc9db56798b51c4b7802a99e8de279385c10e1201bb5a2
7
- data.tar.gz: 2fd59d9187b6d731388689bd885ccfed6e9af1e1b7c3bf97e6bbcf3992fec4fb339c6818224c3d0f9e4a5fab54c31c08f53115d2ff37f9395b2ea4c6abd1767a
6
+ metadata.gz: b2abd50fe57675fa06d61afe99ca4930a36bdfeaf172b8f166c40e0af190cf57b90a5e01ce366471a5aec5dd3a9be7957c09bb089c9922bdf07891f12226a9d6
7
+ data.tar.gz: b53c79a3dbc31a29fd74a984b4dc5111c245032d093d099a66195c08404f7d12980dd1f33d2f454ec4df1759a72c775aeb612c578dcfe4155af12f3cbe9d8b54
@@ -31,6 +31,7 @@ class OrigenTestersApplication < Origen::Application
31
31
  section.page :interface, heading: "Creating an Interface"
32
32
  section.page :resources, heading: "Additional Resources"
33
33
  section.page :code, heading: "Dynamic Custom Code"
34
+ section.page :charz, heading: "Characterization API"
34
35
  section.page :j750, heading: "J750 API"
35
36
  section.page :v93k, heading: "V93K Common API"
36
37
  section.page :v93ksmt7, heading: "V93K SMT7 API"
@@ -1,7 +1,7 @@
1
1
  module OrigenTesters
2
2
  MAJOR = 0
3
- MINOR = 45
4
- BUGFIX = 3
3
+ MINOR = 48
4
+ BUGFIX = 0
5
5
  DEV = nil
6
6
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
7
7
  end
@@ -24,6 +24,7 @@ module OrigenTesters
24
24
  autoload :NoInterface, 'origen_testers/no_interface'
25
25
  autoload :MemoryStyle, 'origen_testers/memory_style'
26
26
  autoload :ATP, 'origen_testers/atp'
27
+ autoload :Charz, 'origen_testers/charz'
27
28
 
28
29
  # not yet autoload :Time, 'origen_testers/time'
29
30
 
@@ -408,6 +408,10 @@ module OrigenTesters::ATP
408
408
  children << n(:meta, attrs)
409
409
  end
410
410
 
411
+ if options[:test_text]
412
+ children << n(:test_text, [options[:test_text]])
413
+ end
414
+
411
415
  if subs = options[:sub_test] || options[:sub_tests]
412
416
  subs = [subs] unless subs.is_a?(Array)
413
417
  subs.each do |s|
@@ -0,0 +1,421 @@
1
+ Dir.glob("#{File.dirname(__FILE__)}/charz/**/*.rb").sort.each do |file|
2
+ require file
3
+ end
4
+ module OrigenTesters
5
+ module Charz
6
+ # @!attribute charz_stack
7
+ # @return [Array] FILO queue of charz session defining data
8
+ # @!attribute charz_routines
9
+ # @return [Hash] user defined charz routines
10
+ # @!attribute charz_profiles
11
+ # @return [Hash] user defined charz profiles
12
+ # @!attribute charz_session
13
+ # @return [Session] current charz session, based on data in the top of the charz_stack
14
+ # @!attribute eof_charz_tests
15
+ # @return [Array] charz tests to be added at the end of the flow
16
+ # @!attribute skip_group_eof_charz_tests
17
+ # @return [Boolean] whether or not to wrap eof charz tests in a group
18
+ # @!attribute eof_charz_tests_group_name
19
+ # @return [String, Symbol] group name to be used to for eof charz tests
20
+ attr_accessor :charz_stack, :charz_routines, :charz_profiles, :charz_session, :eof_charz_tests, :skip_group_eof_charz_tests, :eof_charz_tests_group_name
21
+
22
+ def charz_stack
23
+ @charz_stack ||= []
24
+ end
25
+
26
+ def charz_profiles
27
+ @charz_profiles ||= {}
28
+ end
29
+
30
+ def charz_routines
31
+ @charz_routines ||= {}
32
+ end
33
+
34
+ def charz_session
35
+ @charz_session ||= Session.new
36
+ end
37
+
38
+ def eof_charz_tests
39
+ @eof_charz_tests ||= []
40
+ end
41
+
42
+ # Add a new charz routine to @charz_routines
43
+ # A charz routine is a object that contains all the necessary info specific to a characterization test
44
+ # Its intended to be used in combination with an existing point test (regular non charz test) to create
45
+ # a characterization version of the point test
46
+ #
47
+ # @example create a 1d search routine that searches vdd, from 900mv to 300mv, resolution of 5mv
48
+ # add_charz_routine :my_routine, type: search do |rt|
49
+ # rt.start = 900.mv
50
+ # rt.stop = 300.mv
51
+ # rt.res = 5.mv
52
+ # rt.spec = 'vdd'
53
+ # end
54
+ #
55
+ # @param [Symbol] id charz_routine id, will be the key value in the @charz_routines hash. Must not have been previously used
56
+ # @param [Hash] options charz_routine options
57
+ # @option options [Symbol] :type :search or :'1d' will create a SearchRoutine, :shmoo or :'2d' will create a ShmooRoutine, nil will create a Routine
58
+ def add_charz_routine(id, options = {}, &block)
59
+ if charz_routines.ids.include?(id)
60
+ Origen.log.error("Cannot create charz routine '#{id}', it already exists!")
61
+ fail
62
+ end
63
+ case options[:type]
64
+ when :search, :'1d'
65
+ charz_routines[id] = SearchRoutine.new(id, options, &block)
66
+ when :shmoo, :'2d'
67
+ charz_routines[id] = ShmooRoutine.new(id, options, &block)
68
+ else
69
+ charz_routines[id] = Routine.new(id, options, &block)
70
+ end
71
+ end
72
+
73
+ # Add a new charz profile to @charz_profiles
74
+ # A charz profile is a collection of one or more charz routines, as well as flow control and placement data for
75
+ # the charz tests generated by those routines
76
+ #
77
+ # @example create a profile containing 2 routines, end of flow placement, whose tests are only ran if the parent fails
78
+ # add_charz_profile :my_profile do |prof|
79
+ # prof.routines = [:my_routine1, :my_routine2]
80
+ # prof.placement = :eof
81
+ # prof.on_result = :on_fail
82
+ # end
83
+ #
84
+ # @param [Symbol] id charz_profile id, will be the key value in the @charz_profiles hash. Must not have been previously used
85
+ # @param [Hash] options charz_profile options
86
+ def add_charz_profile(id, options = {}, &block)
87
+ if charz_profiles.ids.include?(id)
88
+ Origen.log.error("Cannot create charz profile '#{id}', it already exists!")
89
+ fail
90
+ end
91
+ charz_profiles[id] = Profile.new(id, options.merge(defined_routines: charz_routines.ids), &block)
92
+ end
93
+
94
+ # Queries the current charz session to see if its active, indicating point tests should be generating charz tests
95
+ def charz_active?
96
+ charz_session.active
97
+ end
98
+
99
+ # Queries the current charz session to see if point tests should skip generation, only adding the resulting charz test
100
+ def charz_only?
101
+ charz_active? && charz_session.charz_only
102
+ end
103
+
104
+ # Pauses the current charz session, preventing point tests from generating charz tests even if the session is valid
105
+ def charz_pause
106
+ charz_session.pause
107
+ end
108
+
109
+ # Resumes the current charz session. If the session isn't valid (ie charz_resume before setting up the session) then nothing will happen
110
+ def charz_resume
111
+ charz_session.resume
112
+ end
113
+
114
+ # Removes the current session generating data off the charz stack
115
+ # If charz data is still on the stack afterward, the session will update to reflect the new data
116
+ # if not, the session will become inactive
117
+ def charz_off
118
+ charz_stack.pop
119
+ if charz_stack.empty?
120
+ update_charz_session(nil)
121
+ else
122
+ update_charz_session(*charz_stack.last)
123
+ end
124
+ end
125
+
126
+ # Pushes a charz object (either a profile or a routine) onto the stack, along with any optional updates to modify the current session
127
+ # Once pushed, the charz_session will attempt to update itself with the new data, failing if the resulting session is invalid
128
+ #
129
+ # If a block is passed, yield the block of tests to enable charz for those tests, then disable charz with a charz_off call
130
+ #
131
+ # @param [Symbol] charz_id either a routine or profile id. Method fails if the id can't be found in @charz_routines or @charz_profiles
132
+ # @param [Hash] options charz_on options
133
+ # @option options [Symbol] :type (:profile) whether the charz_id refers to a charz profile or routine
134
+ def charz_on(charz_id, options = {})
135
+ options = {
136
+ type: :profile
137
+ }.merge(options)
138
+ case options[:type]
139
+ when :profile
140
+ charz_obj = charz_profiles[charz_id]
141
+ when :routine
142
+ if charz_id.is_a?(Array)
143
+ charz_obj = charz_routines[charz_id.first]
144
+ options[:routines] = charz_id
145
+ else
146
+ charz_obj = charz_routines[charz_id]
147
+ options[:routines] = [charz_id]
148
+ end
149
+ else
150
+ Origen.log.error "Unknown charz object type #{options[:type]}, valid types: :profile, :routine"
151
+ fail
152
+ end
153
+ if charz_obj.nil?
154
+ Origen.log.error "No #{options[:type]} found for charz_id: #{charz_id}"
155
+ fail
156
+ end
157
+ charz_stack.push([charz_obj, options])
158
+ unless update_charz_session(*charz_stack.last)
159
+ Origen.log.error 'charz_on failed to create a valid charz session'
160
+ fail
161
+ end
162
+ if block_given?
163
+ yield
164
+ charz_off
165
+ end
166
+ end
167
+
168
+ # An optional helper method to automatically assign an id to tests that will be generating charz tests that depend on the result of the parent test
169
+ # @param [Hash] options the options for a test before its created and added to the flow
170
+ # @param [TestInstance, #name] instance <Optional> the test instance whose name is stored in .name, alternatively pass the name in the options hash under :parent_test_name
171
+ def set_conditional_charz_id(*args)
172
+ case args.size
173
+ when 1
174
+ options = args[0]
175
+ parent_test_name = options[:parent_test_name]
176
+ when 2
177
+ instance = args[0]
178
+ options = args[1]
179
+ parent_test_name = instance.name
180
+ else
181
+ Origen.log.error 'Too many arguments passed to set_conditional_charz_id. Pass either (test_instance, options), or just (options)'
182
+ fail
183
+ end
184
+ unless options[:id]
185
+ if charz_active?
186
+ if charz_session.on_result
187
+ options[:id] = "#{parent_test_name}_charz_#{charz_session.name}".to_sym
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ # Called after the relevant point test has been inserted into the flow
194
+ # Takes the options used to build the previous point test as well as insert_charz_test specific options to then
195
+ # drill down to the point of the flow where the charz test would go, at which point control is handed back to the user's
196
+ # interface to handle creating and inserting the test
197
+ #
198
+ # By default, this method will handle:
199
+ # - the placement of the test (inline aka right after the point test, end of flow, or other)
200
+ # - wrapping the created charz tests in a group (skippable, group name defaults to <point test name> charz <session name>)
201
+ # - conditionally executing the charz tests based on if the point test passed or failed (see set_conditional_charz_id)
202
+ # - conditionally executing some/all charz tests based on a mix of enables and flags
203
+ #
204
+ # After the above is determined, the user regains control on a per-routine (if multiple routines) basis to then process generating the charz test
205
+ def insert_charz_tests(options, &block)
206
+ if charz_active?
207
+ if options[:id]
208
+ # two purposes:
209
+ # 1) prevent all charz tests inadverntently using the same ID as their parent
210
+ # 2) used in on_result behavior
211
+ current_id = options.delete(:id)
212
+ options[:last_test_id] ||= current_id
213
+ end
214
+ case charz_session.placement
215
+ when :inline
216
+ create_charz_group(options, &block)
217
+ when :eof
218
+ # collect the current session and options into a proc, stored in eof_charz_tests to be called later
219
+ current_session = charz_session.clone
220
+ eof_charz_tests << proc do
221
+ @charz_session = current_session
222
+ create_charz_group(options, &block)
223
+ end
224
+ else
225
+ # inline is the default behavior, and eof (end of flow) has built in support.
226
+ if respond_to?(:"create_#{charz_session.placement}_charz_tests")
227
+ send(:"create_#{charz_session.placement}_charz_tests", options, &block)
228
+ elsif respond_to?(:"insert_#{charz_session.placement}_charz_tests")
229
+ send(:"insert_#{charz_session.placement}_charz_tests", options, &block)
230
+ else
231
+ Origen.log.error "No handling specified for #{charz_session.placement} placement charz tests"
232
+ fail
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ # called automatically right after a top_level shutdown, generates end of flow charz tests
239
+ # user should not have to reference this call explicitly
240
+ def generate_eof_charz_tests
241
+ unless eof_charz_tests.empty?
242
+ if skip_group_eof_charz_tests
243
+ eof_charz_tests.map(&:call)
244
+ else
245
+ group_name = eof_charz_tests_group_name || 'End of Flow Charz Tests'
246
+ group group_name do
247
+ eof_charz_tests.map(&:call)
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ private
254
+
255
+ # called by charz_on, updates the current session, and passes the available routines in for validity checks
256
+ def update_charz_session(charz_obj, options = {})
257
+ charz_session.update(charz_obj, options.merge(defined_routines: charz_routines.ids))
258
+ end
259
+
260
+ # called by insert_charz_tests
261
+ #
262
+ # if insert_charz_tests was called with the skip group option, then skip to processing the sessions on_result functionality
263
+ # otherwise, on_result processing occurs within the created group
264
+ #
265
+ # group name defaults to <point test name> charz <session name>, but can be set by the user by passing :group_name in the options
266
+ def create_charz_group(options, &block)
267
+ if options[:skip_group]
268
+ process_on_result(options, &block)
269
+ else
270
+ group_name = options[:group_name] || "#{options[:parent_test_name]} charz #{charz_session.name}"
271
+ group group_name.to_sym do
272
+ process_on_result(options, &block)
273
+ end
274
+ end
275
+ end
276
+
277
+ # called by create_charz_group
278
+ #
279
+ # Handles the case where the session indicates these charz tests' execution depend on the point test's result
280
+ # Requires that the id of the point test has been passed to use this functionality. Otherwise, make sure that
281
+ # charz_session.on_result == nil
282
+ #
283
+ # on_fail and on_pass results are built-in, but if the user has a different check to make, it can be handled
284
+ # by defining the method process_<custom result>_charz_tests
285
+ #
286
+ # @see set_conditional_charz_id
287
+ def process_on_result(options, &block)
288
+ if charz_session.on_result
289
+ case charz_session.on_result
290
+ when :on_fail, :fail, :failed
291
+ last_test_id = options[:last_test_id] || @last_test_id
292
+ if_failed last_test_id do
293
+ process_gates(options, &block)
294
+ end
295
+ when :on_pass, :pass, :passed
296
+ last_test_id = options[:last_test_id] || @last_test_id
297
+ if_passed last_test_id do
298
+ process_gates(options, &block)
299
+ end
300
+ else
301
+ if respond_to?(:"process_#{charz_session.placement}_charz_tests")
302
+ send(:"process_#{charz_session.on_result}_charz_tests", options, &block)
303
+ else
304
+ Origen.log.error "No handling specified for result #{charz_session.on_result} charz tests"
305
+ fail
306
+ end
307
+ end
308
+ else
309
+ process_gates(options, &block)
310
+ end
311
+ end
312
+
313
+ # called by process_on_result
314
+ #
315
+ # Handles the case where charz_session.enables or charz_session.flags have been set
316
+ # referring to enables and flags both as gates, gates can wrap all routines in a session if they're in the form of an
317
+ # array, symbol, or a string (think of the normal use case of if_enable or if_flag)
318
+ #
319
+ # If the gate is a Hash, then that means different routines are getting different gate wrappers.
320
+ # Also if a routine is not indicated in the values of the gate, then that means that routine should not be gated at all
321
+ #
322
+ # This is the final method of handling the insert_charz_test usecases, where the block thats been passed around is finally called
323
+ # the user's provided block is passed the current routine (one at a time) to then take its info to generate a charz test
324
+ def process_gates(options, &block)
325
+ if options[:skip_gates] || !(charz_session.enables || charz_session.flags)
326
+ charz_session.routines.each do |routine|
327
+ block.call(options.merge(current_routine: routine))
328
+ end
329
+ else
330
+ if charz_session.enables && charz_session.flags
331
+ if charz_session.enables.is_a?(Hash) && !charz_session.flags.is_a?(Hash)
332
+ # wrap all tests in flags, wrap specific tests in enables
333
+ if_flag charz_session.flags do
334
+ insert_hash_gates(options, charz_session.enables, :if_enable, &block)
335
+ end
336
+ elsif !charz_session.enables.is_a?(Hash) && charz_session.flags.is_a?(Hash)
337
+ # wrap all tests in enables, wrap specific tests in flags
338
+ if_enable charz_session.enables do
339
+ insert_hash_gates(options, charz_session.flags, :if_flag, &block)
340
+ end
341
+ elsif charz_session.enables.is_a?(Hash) && charz_session.flags.is_a?(Hash)
342
+ # first insert the tests that are not tied to an enable or flag gate
343
+ ungated_routines = charz_session.routines - (charz_session.enables.values.flatten | charz_session.flags.values.flatten)
344
+ ungated_routines.each do |routine|
345
+ block.call(options.merge(current_routine: routine))
346
+ end
347
+ # wrap tests in an enable gate, flag gate, or both
348
+ gated_routines = charz_session.routines - ungated_routines
349
+ gated_routines.each do |routine|
350
+ enable = charz_session.enables.find { |gates, routines| routines.include?(routine) }&.first
351
+ flag = charz_session.flags.find { |gates, routines| routines.include?(routine) }&.first
352
+ if enable && flag
353
+ if_enable enable do
354
+ if_flag flag do
355
+ # wrap test in both enable and flag gate
356
+ block.call(options.merge(current_routine: routine))
357
+ end
358
+ end
359
+ elsif enable
360
+ if_enable enable do
361
+ # enable only
362
+ block.call(options.merge(current_routine: routine))
363
+ end
364
+ elsif flag
365
+ if_flag flag do
366
+ # flag only
367
+ block.call(options.merge(current_routine: routine))
368
+ end
369
+ end
370
+ end
371
+ else
372
+ # both enable and flag is set, and both apply to all routines in session
373
+ if_enable charz_session.enables do
374
+ if_flag charz_session.flags do
375
+ charz_session.routines.each do |routine|
376
+ block.call(options.merge(current_routine: routine))
377
+ end
378
+ end
379
+ end
380
+ end
381
+ else
382
+ # only enables or flags is set, not both
383
+ if charz_session.enables
384
+ gates = charz_session.enables
385
+ gate_method = :if_enable
386
+ elsif charz_session.flags
387
+ gates = charz_session.flags
388
+ gate_method = :if_flag
389
+ end
390
+ if gates.is_a?(Hash)
391
+ # wrap some tests in specific gates
392
+ insert_hash_gates(options, gates, gate_method, &block)
393
+ else
394
+ # wrap all tests in the indicated gates
395
+ send(gate_method, gates) do
396
+ charz_session.routines.each do |routine|
397
+ block.call(options.merge(current_routine: routine))
398
+ end
399
+ end
400
+ end
401
+ end
402
+ end
403
+ end
404
+
405
+ # helper method for the process gates method above
406
+ # handles wrapping routines in specific gates, and passing ungated routines back to the user
407
+ def insert_hash_gates(options, gate_hash, gate_method, &block)
408
+ ungated_routines = charz_session.routines - gate_hash.values.flatten
409
+ ungated_routines.each do |routine|
410
+ block.call(options.merge(current_routine: routine))
411
+ end
412
+ gate_hash.each do |gate, gated_routines|
413
+ send(gate_method, gate) do
414
+ gated_routines.each do |routine|
415
+ block.call(options.merge(current_routine: routine))
416
+ end
417
+ end
418
+ end
419
+ end
420
+ end
421
+ end