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

Inherits:
ATP::Formatter 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

#active_description, #at_flow_start, #at_run_start, callstack, cc_comments, cc_comments=, #children, comment_stack, #context_changed?, flow_comments, flow_comments=, #generate_unique_label, ht_comments, ht_comments=, #is_the_flow?, #lines, #model, name_stack, #nop, #orig_render, #parent, #path, #program, #render, #save_program, #sig, #test, #top_level, #top_level?, unique_ids, unique_ids=

Methods included from ATP::FlowAPI

#atp, #atp=, #hi_limit, #limit, #lo_limit

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, original_reference_file, original_reference_file=, #output_file, #output_inhibited?, #platform, #reference_file, #render, #set_flow_description, #stats, #to_be_written?, #write_from_template, #write_to_file

Methods inherited from ATP::Formatter

format, run, run_and_format, #run_and_format

Methods inherited from ATP::Processor

#extract_volatiles, #handler_missing, #process, #process_all, #run, #volatile?, #volatile_flags

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.


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

def context
  @context
end

#current_enableObject

Returns the value of attribute current_enable.


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

def current_enable
  @current_enable
end

#current_flagObject

Returns the value of attribute current_flag.


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

def current_flag
  @current_flag
end

#set_flagsObject (readonly)

Keeps a note of the context under which flags where set


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

def set_flags
  @set_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


347
348
349
350
351
352
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 347

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


408
409
410
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 408

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


396
397
398
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 396

def completed_lines
  lines
end

#current_lineObject


404
405
406
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 404

def current_line
  open_lines.last
end

#flag_to_s(flag, state) ⇒ Object


412
413
414
415
416
417
418
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 412

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
71
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 63

def format
  @lines = []
  @stack = { jobs: [] }
  @context = []
  @set_flags = {}
  ast = atp.ast(unique_id: sig, optimization: :igxl)
  process(ast)
  lines
end

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

Yields:

  • (line)

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 370

def new_line(type, attrs = {})
  attrs = {
    job:    stack[:jobs].last,
    enable: current_enable
  }.merge(attrs)
  line = platform::FlowLine.new(type, attrs)
  if current_flag
    # If any/all sites condition
    if current_flag[2]
      line.group_sense = 'not' unless current_flag[1]
      line.group_specifier = "#{current_flag[2]}-active"
      line.group_name = clean_flag(current_flag[0])
      line.group_condition = 'flag-true'
    else
      line.device_sense = 'not' unless current_flag[1]
      line.device_name = clean_flag(current_flag[0])
      line.device_condition = 'flag-true'
    end
  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


117
118
119
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 117

def on_continue(node)
  current_line.result = 'None' if current_line
end

#on_cz(node) ⇒ Object


90
91
92
93
94
95
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 90

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

#on_disable(node) ⇒ Object


358
359
360
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 358

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

#on_enable(node) ⇒ Object


354
355
356
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 354

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

#on_flow(node) ⇒ Object


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

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

#on_if_any_sites_flag(node) ⇒ Object Also known as: on_if_all_sites_flag


259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 259

def on_if_any_sites_flag(node)
  flag, *nodes = *node
  state = [:if_any_sites_flag, :if_all_sites_flag].include?(node.type)
  flag = clean_flag(flag)

  # If a flag condition is currently active
  if current_flag
    fail 'Nesting of if_any_sites/if_all_sites conditions with other flag conditions is not supported yet, please create a ticket here if you need this functionality: https://github.com/Origen-SDK/origen_testers/issues'
  end

  # Update the currently active flag condition, this will be added as a condition to all
  # lines created from children of this node
  if node.type.to_s =~ /any/
    self.current_flag = [flag, state, :any]
  else
    self.current_flag = [flag, state, :all]
  end
  context << current_flag
  process_all(node)
  context.pop
  self.current_flag = nil
end

#on_if_enabled(node) ⇒ Object Also known as: on_unless_enabled


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
319
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
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 283

def on_if_enabled(node)
  flag, *nodes = *node
  orig = current_enable
  value = node.type == :if_enabled
  if flag.is_a?(Array)
    flag.map! { |a_flag| clean_enable(a_flag) }
    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
  else
    flag = clean_enable(flag)
  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 current_enable
        and_flag = "#{current_enable}_AND_#{flag}"
        label = generate_unique_label
        branch_if_enable(current_enable) 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.current_enable = and_flag
        context << and_flag
        process_all(node)
        context.pop
        self.current_enable = orig
      else
        self.current_enable = flag
        context << flag
        process_all(node)
        context.pop
        self.current_enable = 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_if_flag(node) ⇒ Object Also known as: on_unless_flag


198
199
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 198

def on_if_flag(node)
  flag, *nodes = *node
  orig = current_flag
  state = node.type == :if_flag
  if flag.is_a?(Array)
    or_flag = flag.join('_OR_')
    or_flag = "NOT_#{flag}" unless state
    flag.each do |f|
      if current_flag
        fail 'Not implemented yet!'
      else
        set_previously = !!set_flags[or_flag]
        set_flags[or_flag] = context
        self.current_flag = [f, state]
        unless set_previously
          completed_lines << platform::FlowLine.new(:defaults, flag_fail: or_flag)
        end
        completed_lines << new_line(:flag_true, parameter: or_flag)
        self.current_flag = nil
      end
    end
    flag = or_flag
  end
  flag = clean_flag(flag)

  # If a flag condition is currently active
  if current_flag
    # If the current flag condition also gated the setting of this node's flag, then we
    # don't need to create an AND flag
    if !set_flags[flag] || (set_flags[flag] && set_flags[flag].hash != context.hash)
      and_flag = clean_flag(flag_to_s(*current_flag) + '_AND_' + flag_to_s(flag, state))
      # 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_flags[and_flag] || (set_flags[and_flag].hash != context.hash)
        set_previously = !!set_flags[and_flag]
        set_flags[and_flag] = context
        existing_flag = current_flag
        self.current_flag = nil
        unless set_previously
          completed_lines << platform::FlowLine.new(:defaults, flag_fail: and_flag)
        end
        completed_lines << new_line(:flag_true, parameter: and_flag)
        self.current_flag = [flag, !state]
        completed_lines << new_line(:flag_false, parameter: and_flag)
        self.current_flag = [existing_flag[0], !existing_flag[1]]
        completed_lines << new_line(:flag_false, parameter: and_flag)
      end
      flag = and_flag
    end
  end

  # Update the currently active flag condition, this will be added as a condition to all
  # lines created from children of this node
  self.current_flag = [flag, state]
  context << current_flag
  process_all(node)
  context.pop
  self.current_flag = orig
end

#on_if_job(node) ⇒ Object Also known as: on_unless_job


183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 183

def on_if_job(node)
  jobs, *nodes = *node
  jobs = clean_job(jobs)
  state = node.type == :if_job
  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


362
363
364
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 362

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

#on_name(node) ⇒ Object


97
98
99
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 97

def on_name(node)
  current_line.tname = node.to_a[0] if current_line
end

#on_number(node) ⇒ Object


101
102
103
104
105
106
107
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 101

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


109
110
111
112
113
114
115
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 109

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


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

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

#on_on_pass(node) ⇒ Object


177
178
179
180
181
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 177

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

#on_render(node) ⇒ Object


366
367
368
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 366

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

#on_set_flag(node) ⇒ Object


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 121

def on_set_flag(node)
  flag = clean_flag(node.to_a[0])
  set_previously = !!set_flags[flag]
  set_flags[flag] = context.dup
  if current_line
    if branch == :on_fail
      current_line.flag_fail = flag
    else
      current_line.flag_pass = flag
    end
  else
    unless set_previously
      completed_lines << platform::FlowLine.new(:defaults, flag_fail: flag)
    end
    completed_lines << new_line(:flag_true, parameter: flag)
  end
end

#on_set_result(node) ⇒ Object


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 139

def on_set_result(node)
  bin = node.find(:bin).try(:value)
  desc = node.find(:bin).to_a[1]
  sbin = node.find(:softbin).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_test(node) ⇒ Object


78
79
80
81
82
83
84
85
86
87
88
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 78

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, that situation should
  # never occur unless the user has manually set up that condition
  if line.flag_fail && line.flag_fail == line.flag_pass
    fail "You can't set the same flag on test pass and fail in IG-XL!"
  else
    completed_lines << line
  end
end

#open_linesObject


400
401
402
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 400

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