Class: OrigenTesters::SmartestBasedTester::V93K_SMT8::Flow

Inherits:
Base::Flow show all
Defined in:
lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb

Constant Summary collapse

TEMPLATE =
"#{Origen.root!}/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/template.flow.erb"
IN_IDENTIFIER =
'_AUTOIN'

Constants inherited from Base::Flow

Base::Flow::RELATIONAL_OPERATOR_STRINGS

Constants included from Flow

Flow::PROGRAM_MODELS_DIR

Instance Attribute Summary

Attributes inherited from Base::Flow

#add_flow_enable, #flow_bypass, #flow_description, #flow_name, #lines, #set_runtime_variables, #stack, #subdirectory, #test_methods, #test_suites, #var_filename

Attributes included from Generator

#output_directory

Instance Method Summary collapse

Methods inherited from Base::Flow

#all_sub_flows, #ast, #at_flow_end, #at_flow_start, #capture_lines, #clean_job, #extract_sub_flows, #filename, #finalize, #flow_enable_var_name, #flow_variables, #generate_expr_string, #generate_expr_term, generate_flag_name, #hardware_bin_descriptions, #limits_file, #line, #on_condition_flag, #on_disable, #on_enable, #on_group, #on_if_enabled, #on_if_flag, #on_if_job, #on_log, #on_loop, #on_render, #on_set, #on_set_flag, #on_set_result, #on_top_level_set, #on_unset_flag, #on_whenever, #render_limits_file, #set_var_filename, #smt8?, #sub_flow_from, #unique_group_name

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, format, run, #run_and_format, run_and_format

Methods inherited from ATP::Processor

#add_global_flag, #clean_flag, #extract_globals, #extract_volatiles, #global_flag?, #global_flags, #handler_missing, #process, #process_all, #run, #volatile?, #volatile_flags

Instance Method Details

#auxiliary_flowsObject



188
189
190
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 188

def auxiliary_flows
  @auxiliary_flows || {}
end


288
289
290
291
292
293
294
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 288

def flow_footer
  f = []
  if add_flow_enable && top_level?
    f << '        }'
  end
  f
end

#flow_headerObject



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 264

def flow_header
  h = []
  if add_flow_enable && top_level?
    h << "        if (#{flow_enable_var_name} == 1) {"
    i = '            '
  else
    i = '        '
  end
  flow_variables[:this_flow][:set_flags].each do |var|
    if var.is_a?(Array)
      h << i + "#{var[0]} = #{var[1].is_a?(String) || var[1].is_a?(Symbol) ? '"' + var[1].to_s + '"' : var[1]};"
    else
      h << i + "#{var} = -1;"
    end
  end
  # Handle the inout variables
  # Use the original variable name and get the value out of the temporary input variable
  inout_variables.each do |inout_var, orig_var|
    h << i + "#{orig_var} = #{inout_var};"
  end
  h << '' unless flow_variables[:this_flow][:set_flags].empty?
  h
end

#inout_variablesObject



192
193
194
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 192

def inout_variables
  @inout_variables || {}
end

#input_variablesObject

Variables which should be defined as an input to the current flow



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 197

def input_variables
  vars = flow_variables
  # Jobs and enables flow into a sub-flow
  in_var_array = (vars[:all][:jobs] + vars[:all][:referenced_enables] + vars[:all][:set_enables] +
    # As do any flags which are referenced by it but which are not set within it
    (vars[:all][:referenced_flags] - vars[:all][:set_flags] - vars[:all][:unset_flags])).uniq
  identified_inout_variables = in_var_array.select { |e| output_variables.include?(e) }
  result = in_var_array.reject { |e| output_variables.include?(e) }
  @inout_variables = {}
  # create inout variables with unique ids to reduce user conflicts
  identified_inout_variables.each do |var|
    unique_id = 0
    var.each_byte { |n| unique_id += n }
    identifier = IN_IDENTIFIER + "_#{unique_id.to_s[0..4]}"
    @inout_variables[:"#{var}#{identifier}"] = var
  end
  result += @inout_variables.keys
  result.uniq.sort do |x, y|
    x = x[0] if x.is_a?(Array)
    y = y[0] if y.is_a?(Array)
    x.to_s <=> y.to_s
  end
end

#intermediate_variables(*sub_flows) ⇒ Object

Output variables which are not directly referenced by this flow, but which are referenced by a parent flow and set by the given child flow and therefore must pass through the current flow. By calling this method with no argument it will consider variables set by any child flow, alternatively pass in the variables for the child flow in question and only that will be considered.



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 247

def intermediate_variables(*sub_flows)
  set_flags = []
  all_sub_flows.each { |f| set_flags += f.flow_variables[:all][:set_flags] }
  if set_flags.empty?
    []
  else
    upstream_referenced_flags = []
    p = parent
    while p
      upstream_referenced_flags += p.flow_variables[:this_flow][:referenced_flags]
      p = p.parent
    end
    upstream_referenced_flags.uniq
    set_flags & upstream_referenced_flags
  end
end

#on_auxiliary_flow(node) ⇒ Object



176
177
178
179
180
181
182
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 176

def on_auxiliary_flow(node)
  @auxiliary_flows ||= {}
  path = node.find(:path).value
  name = node.find(:name).value
  @auxiliary_flows[name] = "#{path}"
  line "#{name}.execute();"
end

#on_sub_flow(node) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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
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
170
171
172
173
174
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 92

def on_sub_flow(node)
  sub_flow = sub_flow_from(node)
  @sub_flows ||= {}
  path = Pathname.new(node.find(:path).value)
  name = path.basename('.*').to_s
  path = Origen.interface.sub_flow_path_overwrite(path) if Origen.interface.respond_to? :sub_flow_path_overwrite
  @sub_flows[name] = "#{path.dirname}.#{name}".gsub(/(\/|\\)/, '.')
  # Pass down all input variables before executing
  if sub_flow.input_variables.size > 0 && tester.flow_variable_grouping
    line "// #{name} sub-flow input variables"
    line '{'
    @indent += 1
  end
  sub_flow.input_variables.each do |var|
    # Handle the inout variables
    # Get the main value into the temporary input variable
    if sub_flow.inout_variables.keys.include?(var)
      var = var[0] if var.is_a?(Array)
      line "#{name}.#{var} = #{sub_flow.inout_variables[var]};"
    else
      var = var[0] if var.is_a?(Array)
      line "#{name}.#{var} = #{var};"
    end
  end
  if sub_flow.input_variables.size > 0 && tester.flow_variable_grouping
    @indent -= 1
    line '}'
  end
  line "#{name}.execute();"
  # And then retrieve all common output variables
  if (output_variables & sub_flow.output_variables).size > 0 && tester.flow_variable_grouping
    line "// #{name} sub-flow output variables"
    line '{'
    @indent += 1
  end
  (output_variables & sub_flow.output_variables).sort.each do |var|
    var = var[0] if var.is_a?(Array)
    line "#{var} = #{name}.#{var};"
  end
  if (output_variables & sub_flow.output_variables).size > 0 && tester.flow_variable_grouping
    @indent -= 1
    line '}'
  end
  if on_pass = node.find(:on_pass)
    pass_lines = capture_lines do
      @indent += 1
      pass_branch do
        process_all(on_pass) if on_pass
      end
      @indent -= 1
    end
    on_pass = nil if pass_lines.empty?
  end

  if on_fail = node.find(:on_fail)
    fail_lines = capture_lines do
      @indent += 1
      fail_branch do
        process_all(on_fail) if on_fail
      end
      @indent -= 1
    end
    on_fail = nil if fail_lines.empty?
  end

  if on_pass && !on_fail
    line "if (#{name}.pass) {"
    pass_lines.each { |l| line l, already_indented: true }
    line '}'

  elsif !on_pass && on_fail
    line "if (!#{name}.pass) {"
    fail_lines.each { |l| line l, already_indented: true }
    line '}'

  elsif on_pass && on_fail
    line "if (#{name}.pass) {"
    pass_lines.each { |l| line l, already_indented: true }
    line '} else {'
    fail_lines.each { |l| line l, already_indented: true }
    line '}'
  end
end

#on_test(node) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 9

def on_test(node)
  test_suite = node.find(:object).to_a[0]
  if test_suite.is_a?(String)
    name = test_suite
  else
    name = test_suite.name
    test_method = test_suite.test_method
    if test_method.respond_to?(:test_name) && test_method.test_name == '' &&
       n = node.find(:name)
      test_method.test_name = n.value
    end
  end

  if node.children.any? { |n| t = n.try(:type); t == :on_fail || t == :on_pass } ||
     !stack[:on_pass].empty? || !stack[:on_fail].empty?
    line "#{name}.execute();"
    @open_test_names << name
    @post_test_lines << []
    process_all(node.to_a.reject { |n| t = n.try(:type); t == :on_fail || t == :on_pass })
    on_pass = node.find(:on_pass)
    on_fail = node.find(:on_fail)

    if on_fail && on_fail.find(:continue) && tester.force_pass_on_continue
      if test_method.respond_to?(:force_pass)
        test_method.force_pass = 1
      else
        Origen.log.error 'Force pass on continue has been enabled, but the test method does not have a force_pass attribute!'
        Origen.log.error "  #{node.source}"
        exit 1
      end
      @open_test_methods << test_method
    else
      if test_method.respond_to?(:force_pass)
        test_method.force_pass = 0
      end
      @open_test_methods << nil
    end

    pass_lines = capture_lines do
      @indent += 1
      pass_branch do
        process_all(on_pass) if on_pass
        stack[:on_pass].each { |n| process_all(n) }
      end
      @indent -= 1
    end

    fail_lines = capture_lines do
      @indent += 1
      fail_branch do
        process_all(on_fail) if on_fail
        stack[:on_fail].each { |n| process_all(n) }
      end
      @indent -= 1
    end

    if !pass_lines.empty? && fail_lines.empty?
      line "if (#{name}.pass) {"
      pass_lines.each { |l| line l, already_indented: true }
      line '}'

    elsif pass_lines.empty? && !fail_lines.empty?
      line "if (!#{name}.pass) {"
      fail_lines.each { |l| line l, already_indented: true }
      line '}'

    elsif !pass_lines.empty? && !fail_lines.empty?
      line "if (#{name}.pass) {"
      pass_lines.each { |l| line l, already_indented: true }
      line '} else {'
      fail_lines.each { |l| line l, already_indented: true }
      line '}'

    end

    @open_test_methods.pop
    @open_test_names.pop
    @post_test_lines.pop.each { |l| line(l) }
  else
    line "#{name}.execute();"
  end
end

#output_variablesObject

Variables which should be defined as an output of the current flow



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 222

def output_variables
  vars = flow_variables
  # Flags that are set by this flow flow out of it
  (vars[:this_flow][:set_flags] +
   # As do any flags set by its children which are marked as external
   vars[:all][:set_flags_extern] +
   # Other test methods are setting the flags
   vars[:this_flow][:add_flags] +
   # Other test methods are set in the children
   vars[:all][:add_flags_extern] +
   # And any flags which are set by a child and referenced in this flow
   (vars[:this_flow][:referenced_flags] & vars[:sub_flows][:set_flags]) +
   # And also intermediate flags, those are flags which are set by a child and referenced
   # by a parent of the current flow
   intermediate_variables).uniq.sort do |x, y|
    x = x[0] if x.is_a?(Array)
    y = y[0] if y.is_a?(Array)
    x <=> y
  end
end

#sub_flowsObject



184
185
186
# File 'lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb', line 184

def sub_flows
  @sub_flows || {}
end