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, callstack, comment_stack, #context_changed?, flow_comments, flow_comments=, #generate_unique_label, #is_the_flow?, #lines, #model, #nop, #orig_render, #program, #render, #save_program, #sig, unique_ids, unique_ids=

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.



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



323
324
325
326
327
328
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 323

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



376
377
378
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 376

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



364
365
366
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 364

def completed_lines
  lines
end

#current_lineObject



372
373
374
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 372

def current_line
  open_lines.last
end

#flag_to_s(flag, state) ⇒ Object



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

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)


346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 346

def new_line(type, attrs = {})
  attrs = {
    job:    stack[:jobs].last,
    enable: current_enable
  }.merge(attrs)
  line = platform::FlowLine.new(type, attrs)
  if current_flag
    line.device_sense = 'not' unless current_flag[1]
    line.device_name = clean_flag(current_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



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



334
335
336
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 334

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

#on_enable(node) ⇒ Object



330
331
332
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 330

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_enabled(node) ⇒ Object Also known as: on_unless_enabled



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

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



338
339
340
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 338

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



342
343
344
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 342

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



368
369
370
# File 'lib/origen_testers/igxl_based_tester/base/flow.rb', line 368

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