origen_testers 0.45.3 → 0.48.0

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.
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