Class: OrigenTesters::IGXLBasedTester::Base::Flow

Inherits:
ATP::Formatter
  • Object
show all
Includes:
Flow
Defined in:
lib/origen_testers/igxl_based_tester/base/flow.rb

Direct Known Subclasses

J750::Flow, UltraFLEX::Flow

Defined Under Namespace

Classes: FlowLineAPI, TestCounter

Constant Summary collapse

OUTPUT_POSTFIX =
'flow'

Constants included from Flow

Flow::PROGRAM_MODELS_DIR

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Flow

#at_flow_start, #at_run_start, #bin, callstack, comment_stack, #context_changed?, #cz, #disable, #enable, flow_comments, flow_comments=, #generate_unique_label, #group, #if_all_failed, #if_all_passed, #if_any_failed, #if_any_passed, #if_enable, #if_failed, #if_flag, #if_job, #if_passed, #if_ran, #is_the_flow?, #lines, #log, #model, #nop, #pass, #program, #render, #save_program, #sig, #test, unique_ids, unique_ids=, #unless_enable, #unless_flag, #unless_job, #unless_ran

Methods included from Generator

#close, #collection, #collection=, #compiler, #current_dir, #dont_diff=, execute_source, #file_extension, #file_pipeline, #filename, #filename=, #finalize, #identity_map, #import, #inhibit_output, #name, #on_close, #output_file, #output_inhibited?, #platform, #reference_file, #render, #set_flow_description, #stats, #to_be_written?, #write_from_template, #write_to_file

Instance Attribute Details

#branchObject (readonly)

Returns the value of attribute branch.



9
10
11
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 9

def branch
  @branch
end

#contextObject (readonly)

Returns the value of attribute context.



12
13
14
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 12

def context
  @context
end

#current_groupObject (readonly)

Returns the value of attribute current_group.



11
12
13
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 11

def current_group
  @current_group
end

#flow_flagObject

Returns the value of attribute flow_flag.



15
16
17
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 15

def flow_flag
  @flow_flag
end

#run_flagObject

Returns the value of attribute run_flag.



14
15
16
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 14

def run_flag
  @run_flag
end

#set_run_flagsObject (readonly)

Returns the value of attribute set_run_flags.



13
14
15
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 13

def set_run_flags
  @set_run_flags
end

#stackObject (readonly)

Returns the value of attribute stack.



10
11
12
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 10

def stack
  @stack
end

Instance Method Details

#branch_if_enable(word) ⇒ Object



379
380
381
382
383
384
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 379

def branch_if_enable(word)
  label = generate_unique_label
  completed_lines << new_line(:goto, parameter: label, enable: word)
  yield
  completed_lines << new_line(:nop, label: label, enable: nil)
end

#clean_job(job) ⇒ Object



432
433
434
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 432

def clean_job(job)
  [job].flatten.map { |j| j.to_s.upcase }
end

#completed_linesObject

Any completed lines should be pushed to the array that this returns



420
421
422
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 420

def completed_lines
  stack[:groups].last || lines
end

#current_lineObject



428
429
430
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 428

def current_line
  open_lines.last
end

#flag_to_s(flag, state) ⇒ Object



436
437
438
439
440
441
442
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 436

def flag_to_s(flag, state)
  if state
    flag
  else
    "NOT_#{flag}"
  end
end

#formatObject

Will be called at the end to transform the final flow model into an array of lines to be rendered to the IG-XL flow sheet



63
64
65
66
67
68
69
70
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 63

def format
  @lines = []
  @stack = { jobs: [], groups: [] }
  @set_run_flags = {}
  @context = []
  process(model.ast)
  lines
end

#new_line(type, attrs = {}) {|line| ... } ⇒ Object

Yields:

  • (line)


402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 402

def new_line(type, attrs = {})
  attrs = {
    job:    stack[:jobs].last,
    enable: flow_flag
  }.merge(attrs)
  line = platform::FlowLine.new(type, attrs)
  if run_flag
    line.device_sense = 'not' unless run_flag[1]
    line.device_name = run_flag[0]
    line.device_condition = 'flag-true'
  end
  open_lines << line
  yield line if block_given?
  open_lines.pop
  line
end

#number_of_tests_in(node) ⇒ Object



56
57
58
59
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 56

def number_of_tests_in(node)
  @test_counter ||= TestCounter.new
  @test_counter.run(node)
end

#on_continue(node) ⇒ Object



168
169
170
171
172
173
174
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 168

def on_continue(node)
  if current_group
    current_group.each { |line| line.result = 'None' }
  else
    current_line.result = 'None'
  end
end

#on_cz(node) ⇒ Object



105
106
107
108
109
110
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 105

def on_cz(node)
  setup, test = *node
  completed_lines << new_line(:cz, cz_setup: setup) do |line|
    process_all(test)
  end
end

#on_disable_flow_flag(node) ⇒ Object



390
391
392
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 390

def on_disable_flow_flag(node)
  completed_lines << new_line(:disable_flow_word, parameter: node.value)
end

#on_enable_flow_flag(node) ⇒ Object



386
387
388
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 386

def on_enable_flow_flag(node)
  completed_lines << new_line(:enable_flow_word, parameter: node.value)
end

#on_flow(node) ⇒ Object



72
73
74
75
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 72

def on_flow(node)
  name, *nodes = *node
  process_all(nodes)
end

#on_flow_flag(node) ⇒ Object



320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 320

def on_flow_flag(node)
  flag, value = *node.to_a.take(2)
  orig = flow_flag
  if flag.is_a?(Array)
    if flag.size > 1
      or_flag = flag.join('_OR_')
      flag.each do |f|
        completed_lines << new_line(:enable_flow_word, parameter: or_flag, enable: f)
      end
      flag = or_flag
    else
      flag = flag.first
    end
  end
  if value
    # IG-XL docs say that enable words are not optimized for test time, so branch around
    # large blocks to minimize enable word evaluation
    if number_of_tests_in(node) > 5
      label = generate_unique_label
      branch_if_enable(flag) do
        completed_lines << new_line(:goto, parameter: label, enable: nil)
      end
      context << flag
      process_all(node)
      context.pop
      completed_lines << new_line(:nop, label: label, enable: nil)
    else
      if flow_flag
        and_flag = "#{flow_flag}_AND_#{flag}"
        label = generate_unique_label
        branch_if_enable(flow_flag) do
          completed_lines << new_line(:goto, parameter: label, enable: nil)
        end
        completed_lines << new_line(:enable_flow_word, parameter: and_flag, enable: flag)
        completed_lines << new_line(:nop, label: label, enable: nil)
        self.flow_flag = and_flag
        context << and_flag
        process_all(node)
        context.pop
        self.flow_flag = orig
      else
        self.flow_flag = flag
        context << flag
        process_all(node)
        context.pop
        self.flow_flag = orig
      end
    end
  else
    # IG-XL does not have a !enable option, so generate a branch around the tests
    # to be skipped unless the required flag is enabled
    context << "!#{flag}"
    branch_if_enable(flag) do
      process_all(node)
    end
    context.pop
  end
end

#on_group(node) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 112

def on_group(node)
  stack[:groups] << []
  post_group = node.children.select { |n| [:on_fail, :on_pass, :name].include?(n.try(:type)) }
  process_all(node.children - post_group)
  # Now process any on_fail and similar conditional logic attached to the group
  @current_group = stack[:groups].last
  process_all(post_group)
  @current_group = nil
  flags = { on_pass: [], on_fail: [] }
  stack[:groups].pop.each do |test|
    flags[:on_pass] << test.flag_pass
    flags[:on_fail] << test.flag_fail
    completed_lines << test
  end
  if @group_on_fail_flag
    flags[:on_fail].each do |flag|
      self.run_flag = [flag, true]
      completed_lines << new_line(:flag_true, parameter: @group_on_fail_flag)
    end
    self.run_flag = nil
    @group_on_fail_flag = nil
  end
  if @group_on_pass_flag
    flags[:on_pass].each do |flag|
      self.run_flag = [flag, true]
      completed_lines << new_line(:flag_true, parameter: @group_on_pass_flag)
    end
    self.run_flag = nil
    @group_on_pass_flag = nil
  end
end

#on_job(node) ⇒ Object



244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 244

def on_job(node)
  jobs, state, *nodes = *node
  jobs = clean_job(jobs)
  unless state
    jobs = jobs.map { |j| "!#{j}" }
  end
  stack[:jobs] << [stack[:jobs].last, jobs].compact.join(',')
  context << stack[:jobs].last
  process_all(node)
  stack[:jobs].pop
  context.pop
end

#on_log(node) ⇒ Object



394
395
396
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 394

def on_log(node)
  completed_lines << new_line(:logprint, parameter: node.to_a[0].gsub(' ', '_'))
end

#on_name(node) ⇒ Object



144
145
146
147
148
149
150
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 144

def on_name(node)
  if current_group
    # No action, groups will not actually appear in the flow sheet
  else
    current_line.tname = node.to_a[0]
  end
end

#on_number(node) ⇒ Object



152
153
154
155
156
157
158
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 152

def on_number(node)
  if Origen.tester.diff_friendly_output?
    current_line.tnum = 0
  else
    current_line.tnum = node.to_a[0]
  end
end

#on_object(node) ⇒ Object



160
161
162
163
164
165
166
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 160

def on_object(node)
  instance = node.to_a[0]
  if instance.is_a?(String)
    current_line.instance_variable_set('@ignore_missing_instance', true)
  end
  current_line.parameter = instance
end

#on_on_fail(node) ⇒ Object



232
233
234
235
236
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 232

def on_on_fail(node)
  @branch = :on_fail
  process_all(node)
  @branch = nil
end

#on_on_pass(node) ⇒ Object



238
239
240
241
242
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 238

def on_on_pass(node)
  @branch = :on_pass
  process_all(node)
  @branch = nil
end

#on_render(node) ⇒ Object



398
399
400
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 398

def on_render(node)
  completed_lines << node.to_a[0]
end

#on_run_flag(node) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 257

def on_run_flag(node)
  flag, state, *nodes = *node
  orig = run_flag
  if flag.is_a?(Array)
    or_flag = flag.join('_OR_')
    or_flag = "NOT_#{flag}" unless state
    flag.each do |f|
      if run_flag
        fail 'Not implemented yet!'
      else
        self.run_flag = [f, state]
        completed_lines << new_line(:flag_true, parameter: or_flag)
        self.run_flag = nil
      end
    end
    # Don't need to create an AND flag if the flag on which this test is dependent was also
    # set under the same context.
    if run_flag && set_run_flags[flag] && set_run_flags[flag].hash != context.hash
      and_flag = flag_to_s(or_flag, state) + '_AND_' + flag_to_s(*run_flag)
      # If the AND flag has already been created and set in this context (for a previous test),
      # no need to re-create it
      if !set_run_flags[and_flag] || (set_run_flags[and_flag].hash != context.hash)
        set_run_flags[and_flag] = context
        existing_flag = run_flag
        self.run_flag = nil
        completed_lines << new_line(:flag_true, parameter: and_flag)
        self.run_flag = [existing_flag[0], !existing_flag[1]]
        completed_lines << new_line(:flag_false, parameter: and_flag)
        self.run_flag = [flag, !state]
        completed_lines << new_line(:flag_false, parameter: and_flag)
      end
      self.run_flag = [and_flag, true]
    else
      self.run_flag = [or_flag, true]
    end
  else
    # Don't need to create an AND flag if the flag on which this test is dependent was also
    # set under the same context.
    if run_flag && set_run_flags[flag] && set_run_flags[flag].hash != context.hash
      and_flag = flag_to_s(flag, state) + '_AND_' + flag_to_s(*run_flag)
      # If the AND flag has already been created and set in this context (for a previous test),
      # no need to re-create it
      if !set_run_flags[and_flag] || (set_run_flags[and_flag].hash != context.hash)
        set_run_flags[and_flag] = context
        existing_flag = run_flag
        self.run_flag = nil
        completed_lines << new_line(:flag_true, parameter: and_flag)
        self.run_flag = [existing_flag[0], !existing_flag[1]]
        completed_lines << new_line(:flag_false, parameter: and_flag)
        self.run_flag = [flag, !state]
        completed_lines << new_line(:flag_false, parameter: and_flag)
      end
      self.run_flag = [and_flag, true]
    else
      self.run_flag = [flag, state]
    end
  end
  context << run_flag
  process_all(node)
  context.pop
  self.run_flag = orig
end

#on_set_result(node) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 200

def on_set_result(node)
  bin = node.find(:bin).try(:value)
  sbin = node.find(:softbin).try(:value)
  desc = node.find(:bin_description).try(:value)
  if current_line
    if branch == :on_fail
      current_line.bin_fail = bin
      current_line.sort_fail = sbin
      current_line.comment = desc
      current_line.result = 'Fail'
    else
      current_line.bin_pass = bin
      current_line.sort_pass = sbin
      current_line.comment = desc
      current_line.result = 'Pass'
    end
  else
    line = new_line(:set_device)
    if node.to_a[0] == 'pass'
      line.bin_pass = bin
      line.sort_pass = sbin
      line.result = 'Pass'
    else
      line.bin_fail = bin
      line.sort_fail = sbin
      line.result = 'Fail'
    end
    line.comment = desc
    completed_lines << line
  end
end

#on_set_run_flag(node) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 176

def on_set_run_flag(node)
  flag = node.to_a[0]
  set_run_flags[flag] = context.dup
  if current_group
    if branch == :on_fail
      @group_on_fail_flag = flag
      current_group.each_with_index do |line, i|
        line.flag_fail = "#{flag}_#{i}" unless line.flag_fail
      end
    else
      @group_on_pass_flag = flag
      current_group.each_with_index do |line, i|
        line.flag_pass = "#{flag}_#{i}" unless line.flag_pass
      end
    end
  else
    if branch == :on_fail
      current_line.flag_fail = flag
    else
      current_line.flag_pass = flag
    end
  end
end

#on_test(node) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 77

def on_test(node)
  line = new_line(:test) { |l| process_all(node) }

  # In IG-XL you can't set the same flag in case of pass or fail, if that situation has
  # occurred then rectify it now
  if line.flag_fail && line.flag_fail == line.flag_pass
    # If the test will bin, don't need to resolve the situation, the flag only matters
    # in the pass case
    if line.result = 'Fail'
      line.flag_fail = nil
      completed_lines << line
    else
      flag = line.flag_fail
      line.flag_fail = "#{flag}_FAILED"
      line.flag_pass = "#{flag}_PASSED"
      completed_lines << line
      existing_flag = run_flag
      self.run_flag = [line.flag_fail, true]
      completed_lines << new_line(:flag_true, parameter: flag)
      self.run_flag = [line.flag_pass, true]
      completed_lines << new_line(:flag_true, parameter: flag)
      self.run_flag = existing_flag
    end
  else
    completed_lines << line
  end
end

#open_linesObject



424
425
426
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 424

def open_lines
  @open_lines ||= []
end

#ultraflexObject Also known as: uflex, j750

Returns the API to manually generate an IG-XL flow line



50
51
52
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 50

def ultraflex
  @flow_line_api ||= FlowLineAPI.new(self)
end