origen_testers 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed6eed4f43211577112670d75be50cd8c5af22d1
4
- data.tar.gz: 44239f70ea1b03d86784cfbaf0dffd91694b0535
3
+ metadata.gz: 112e2af4457169ff2ba79641610c0722d565f1fb
4
+ data.tar.gz: 8833d9bcc8538cb5e5a32f934222e90360957d0d
5
5
  SHA512:
6
- metadata.gz: b1dbc83b631cc269e949a36a9473cfc0935601478adacf5216293db841fc7fce6fdafe88125db77c3ba0d897237858e3aee651d9167b987f0f35f35d0c8535b3
7
- data.tar.gz: 2c2f1b09187a88366d9169d531a41465a997e09c321858babf28c5f2f20dc4eead6665fb946f6de91d630ad79693b753a189c01b89fc115b4dc57490c3ca54b8
6
+ metadata.gz: c28c0d2cba87e54110b23a77a7f4cf4eb6adc54f93daca4531a9168e98bd0915481d1bc7d4eefae082fbdfb648c7bb31f93a4e8dc7f2b12abcc164ede3b2b039
7
+ data.tar.gz: ca63134cf7ac29bb74ece0bd9487251ad16ba4b59c6901ebc34288f471591138ad72a433d84d7490586daaee38722189b9d1b088d780b611164cde7aff7758df
data/config/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module OrigenTesters
2
2
  MAJOR = 0
3
- MINOR = 12
3
+ MINOR = 13
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -130,13 +130,13 @@ module OrigenTesters
130
130
  end
131
131
 
132
132
  # @api private
133
- # This fires between target loads
133
+ # This fires between target loads (unless overridden by the ATE specific flow class)
134
134
  def at_run_start
135
135
  @@program = nil
136
136
  end
137
137
 
138
138
  # @api private
139
- # This fires between flows
139
+ # This fires between flows (unless overridden by the ATE specific flow class)
140
140
  def at_flow_start
141
141
  @labels = {}
142
142
  end
@@ -36,6 +36,7 @@ module OrigenTesters
36
36
  end
37
37
 
38
38
  def at_flow_start
39
+ model # Call to ensure the signature gets populated
39
40
  end
40
41
 
41
42
  def at_flow_end
@@ -45,7 +46,7 @@ module OrigenTesters
45
46
  h = ['{']
46
47
  if add_flow_enable
47
48
  var = filename.sub(/\..*/, '').upcase
48
- var = "#{var}_ENABLE"
49
+ var = generate_flag_name("#{var}_ENABLE")
49
50
  if add_flow_enable == :enabled
50
51
  flow_control_variables << [var, 1]
51
52
  else
@@ -84,9 +85,11 @@ module OrigenTesters
84
85
  @indent = add_flow_enable ? 2 : 1
85
86
  @lines = []
86
87
  @stack = { on_fail: [], on_pass: [] }
87
- m = Processors::IfRanCleaner.new.process(model.ast)
88
+ m = Processors::ContinueImplementer.new.process(model.ast)
89
+ m = Processors::IfRanCleaner.new.process(m)
90
+ m = Processors::FlagOptimizer.new.run(m)
91
+ m = Processors::AdjacentIfCombiner.new.process(m)
88
92
  m = Processors::EmptyBranchCleaner.new.process(m)
89
- m = Processors::FlagOptimizer.new.process(m)
90
93
  @set_runtime_variables = Processors::ExtractSetVariables.new.run(m)
91
94
  process(m)
92
95
  end
@@ -122,10 +125,8 @@ module OrigenTesters
122
125
  line '{'
123
126
  @indent += 1
124
127
  on_fail = node.children.find { |n| n.try(:type) == :on_fail }
125
- with_continue(on_fail ? on_fail.children.any? { |n| n.try(:type) == :continue } : false) do
126
- process_all(on_fail) if on_fail
127
- stack[:on_fail].each { |n| process_all(n) }
128
- end
128
+ process_all(on_fail) if on_fail
129
+ stack[:on_fail].each { |n| process_all(n) }
129
130
  @indent -= 1
130
131
  line '}'
131
132
  else
@@ -160,6 +161,8 @@ module OrigenTesters
160
161
 
161
162
  def on_condition_flag(node)
162
163
  flag, state, *nodes = *node
164
+ flag_true = node.find(:flag_true)
165
+ flag_false = node.find(:flag_false)
163
166
  if flag.is_a?(Array)
164
167
  condition = flag.map { |f| "@#{generate_flag_name(f)} == 1" }.join(' or ')
165
168
  else
@@ -168,13 +171,21 @@ module OrigenTesters
168
171
  line "if #{condition} then"
169
172
  line '{'
170
173
  @indent += 1
171
- process_all(nodes) if state
174
+ if flag_true
175
+ process_all(flag_true.children)
176
+ else
177
+ process_all(nodes) if state
178
+ end
172
179
  @indent -= 1
173
180
  line '}'
174
181
  line 'else'
175
182
  line '{'
176
183
  @indent += 1
177
- process_all(nodes) unless state
184
+ if flag_false
185
+ process_all(flag_false.children)
186
+ else
187
+ process_all(nodes) unless state
188
+ end
178
189
  @indent -= 1
179
190
  line '}'
180
191
  end
@@ -182,7 +193,7 @@ module OrigenTesters
182
193
  def on_flow_flag(node)
183
194
  flag, state, *nodes = *node
184
195
  [flag].flatten.each do |f|
185
- flow_control_variables << f
196
+ flow_control_variables << generate_flag_name(f)
186
197
  end
187
198
  on_condition_flag(node)
188
199
  end
@@ -190,7 +201,7 @@ module OrigenTesters
190
201
  def on_run_flag(node)
191
202
  flag, state, *nodes = *node
192
203
  [flag].flatten.each do |f|
193
- runtime_control_variables << f
204
+ runtime_control_variables << generate_flag_name(f)
194
205
  end
195
206
  on_condition_flag(node)
196
207
  end
@@ -208,42 +219,38 @@ module OrigenTesters
208
219
  end
209
220
 
210
221
  def on_set_run_flag(node)
211
- flag = node.value
222
+ flag = generate_flag_name(node.value)
212
223
  runtime_control_variables << flag
213
- line "@#{generate_flag_name(flag)} = 1;"
224
+ line "@#{flag} = 1;"
214
225
  end
215
226
 
216
227
  def on_group(node)
217
228
  on_fail = node.children.find { |n| n.try(:type) == :on_fail }
218
229
  on_pass = node.children.find { |n| n.try(:type) == :on_pass }
219
- with_continue(on_fail && on_fail.children.any? { |n| n.try(:type) == :continue }) do
220
- line '{'
221
- @indent += 1
222
- stack[:on_fail] << on_fail if on_fail
223
- stack[:on_pass] << on_pass if on_pass
224
- process_all(node.children - [on_fail, on_pass])
225
- stack[:on_fail].pop if on_fail
226
- stack[:on_pass].pop if on_pass
227
- @indent -= 1
228
- line "}, open,\"#{unique_group_name(node.find(:name).value)}\", \"\""
229
- end
230
+ line '{'
231
+ @indent += 1
232
+ stack[:on_fail] << on_fail if on_fail
233
+ stack[:on_pass] << on_pass if on_pass
234
+ process_all(node.children - [on_fail, on_pass])
235
+ stack[:on_fail].pop if on_fail
236
+ stack[:on_pass].pop if on_pass
237
+ @indent -= 1
238
+ line "}, open,\"#{unique_group_name(node.find(:name).value)}\", \"\""
230
239
  end
231
240
 
232
241
  def on_set_result(node)
233
- unless @continue
234
- bin = node.find(:bin).try(:value)
235
- desc = node.find(:bin).to_a[1]
236
- sbin = node.find(:softbin).try(:value)
237
- sdesc = node.find(:softbin).to_a[1] || 'fail'
238
- if bin && desc
239
- hardware_bin_descriptions[bin] ||= desc
240
- end
242
+ bin = node.find(:bin).try(:value)
243
+ desc = node.find(:bin).to_a[1]
244
+ sbin = node.find(:softbin).try(:value)
245
+ sdesc = node.find(:softbin).to_a[1] || 'fail'
246
+ if bin && desc
247
+ hardware_bin_descriptions[bin] ||= desc
248
+ end
241
249
 
242
- if node.to_a[0] == 'pass'
243
- line "stop_bin \"#{sbin}\", \"\", , good, noreprobe, green, #{bin}, over_on;"
244
- else
245
- line "stop_bin \"#{sbin}\", \"#{sdesc}\", , bad, noreprobe, red, #{bin}, over_on;"
246
- end
250
+ if node.to_a[0] == 'pass'
251
+ line "stop_bin \"#{sbin}\", \"\", , good, noreprobe, green, #{bin}, over_on;"
252
+ else
253
+ line "stop_bin \"#{sbin}\", \"#{sdesc}\", , bad, noreprobe, red, #{bin}, over_on;"
247
254
  end
248
255
  end
249
256
 
@@ -266,13 +273,6 @@ module OrigenTesters
266
273
  [job].flatten.map { |j| "@JOB == \"#{j.to_s.upcase}\"" }
267
274
  end
268
275
 
269
- def with_continue(value)
270
- orig = @continue
271
- @continue = true if value
272
- yield
273
- @continue = orig
274
- end
275
-
276
276
  private
277
277
 
278
278
  def generate_flag_name(flag)
@@ -26,7 +26,8 @@ module OrigenTesters
26
26
 
27
27
  # @api private
28
28
  def at_flow_start
29
- flow.at_flow_start
29
+ f = flow
30
+ f.at_flow_start
30
31
  # Initialize this to the value currently set on the tester, any further setting of
31
32
  # this by the interface will override
32
33
  flow.add_flow_enable = tester.add_flow_enable
@@ -7,6 +7,9 @@ module OrigenTesters
7
7
  autoload :EmptyBranchCleaner, 'origen_testers/smartest_based_tester/base/processors/empty_branch_cleaner'
8
8
  autoload :FlagOptimizer, 'origen_testers/smartest_based_tester/base/processors/flag_optimizer'
9
9
  autoload :ExtractSetVariables, 'origen_testers/smartest_based_tester/base/processors/extract_set_variables'
10
+ autoload :AdjacentIfCombiner, 'origen_testers/smartest_based_tester/base/processors/adjacent_if_combiner'
11
+ autoload :ContinueImplementer, 'origen_testers/smartest_based_tester/base/processors/continue_implementer'
12
+ autoload :ExtractRunFlagTable, 'origen_testers/smartest_based_tester/base/processors/extract_run_flag_table'
10
13
  end
11
14
  end
12
15
  end
@@ -0,0 +1,106 @@
1
+ module OrigenTesters
2
+ module SmartestBasedTester
3
+ class Base
4
+ module Processors
5
+ # This combines adjacent if flag nodes where the flag is in the opposite state
6
+ #
7
+ # s(:flow,
8
+ # s(:name, "prb1"),
9
+ # s(:run_flag, "SOME_FLAG", true,
10
+ # s(:test,
11
+ # s(:name, "test1"))),
12
+ # s(:run_flag, "SOME_FLAG", false,
13
+ # s(:test,
14
+ # s(:name, "test2"))))
15
+ #
16
+ # s(:flow,
17
+ # s(:name, "prb1"),
18
+ # s(:run_flag, "SOME_FLAG",
19
+ # s(:flag_true,
20
+ # s(:test,
21
+ # s(:name, "test1"))),
22
+ # s(:flag_false,
23
+ # s(:test,
24
+ # s(:name, "test2")))))
25
+ #
26
+ # See here for an example of the kind of flow level effect it has:
27
+ # https://github.com/Origen-SDK/origen_testers/issues/43
28
+ class AdjacentIfCombiner < ATP::Processor
29
+ class SetRunFlagFinder < ATP::Processor
30
+ def contains?(node, flag_name)
31
+ @result = false
32
+ @flag_name = flag_name
33
+ process_all(node)
34
+ @result
35
+ end
36
+
37
+ def on_set_run_flag(node)
38
+ if node.to_a[0] == @flag_name
39
+ @result = true
40
+ end
41
+ end
42
+ alias_method :on_set_flow_flag, :on_set_run_flag
43
+ end
44
+
45
+ def on_unnamed_collection(node)
46
+ node.updated(nil, optimize(process_all(node.children)))
47
+ end
48
+ alias_method :on_on_fail, :on_unnamed_collection
49
+ alias_method :on_on_pass, :on_unnamed_collection
50
+
51
+ def on_named_collection(node)
52
+ name, *nodes = *node
53
+ node.updated(nil, [name] + optimize(process_all(nodes)))
54
+ end
55
+ alias_method :on_flow, :on_named_collection
56
+ alias_method :on_group, :on_named_collection
57
+
58
+ def on_group(node)
59
+ name, *nodes = *node
60
+ node.updated(nil, [name] + optimize(process_all(nodes)))
61
+ end
62
+
63
+ def optimize(nodes)
64
+ results = []
65
+ node1 = nil
66
+ nodes.each do |node2|
67
+ if node1
68
+ if opposite_flag_states?(node1, node2) && safe_to_combine?(node1, node2)
69
+ results << combine(node1, node2)
70
+ node1 = nil
71
+ else
72
+ results << node1
73
+ node1 = node2
74
+ end
75
+ else
76
+ node1 = node2
77
+ end
78
+ end
79
+ results << node1 if node1
80
+ results
81
+ end
82
+
83
+ def combine(node1, node2)
84
+ true_node = node1.to_a[1] ? node1 : node2
85
+ false_node = node1.to_a[1] ? node2 : node1
86
+ true_node = n(:flag_true, process_all(true_node.to_a[2..-1]))
87
+ false_node = n(:flag_false, process_all(false_node.to_a[2..-1]))
88
+
89
+ n(node1.type, [node1.to_a[0], true_node, false_node])
90
+ end
91
+
92
+ def opposite_flag_states?(node1, node2)
93
+ ((node1.type == :run_flag && node2.type == :run_flag) || (node1.type == :flow_flag && node2.type == :flow_flag)) &&
94
+ node1.to_a[0] == node2.to_a[0] && node1.to_a[1] != node2.to_a[1]
95
+ end
96
+
97
+ def safe_to_combine?(node1, node2)
98
+ # Nodes won't be collapsed if node1 touches the shared run flag, i.e. if there is any chance
99
+ # that by the time it would naturally execute node2, the flag could have been changed by node1
100
+ !SetRunFlagFinder.new.contains?(node1, node1.to_a[0])
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,39 @@
1
+ module OrigenTesters
2
+ module SmartestBasedTester
3
+ class Base
4
+ module Processors
5
+ # Implements continue on a fail branch for V93K by removing any bin nodes that are
6
+ # siblings of continue nodes. The continue nodes are also removed in the process since
7
+ # they have now served their function.
8
+ class ContinueImplementer < ATP::Processor
9
+ # Delete any on-fail child if it's 'empty'
10
+ def on_on_fail(node)
11
+ if cont = node.find(:continue) || @continue
12
+ node = node.updated(nil, node.children - [cont] - node.find_all(:set_result))
13
+ end
14
+ node.updated(nil, process_all(node.children))
15
+ end
16
+
17
+ def on_group(node)
18
+ f = node.find(:on_fail)
19
+ if f && f.find(:continue)
20
+ with_continue do
21
+ node = node.updated(nil, process_all(node.children))
22
+ end
23
+ node
24
+ else
25
+ node.updated(nil, process_all(node.children))
26
+ end
27
+ end
28
+
29
+ def with_continue
30
+ orig = @continue
31
+ @continue = true
32
+ yield
33
+ @continue = orig
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,45 +2,17 @@ module OrigenTesters
2
2
  module SmartestBasedTester
3
3
  class Base
4
4
  module Processors
5
+ # Removes any empty on_pass and on_fail branches
5
6
  class EmptyBranchCleaner < ATP::Processor
6
7
  # Delete any on-fail child if it's 'empty'
7
8
  def on_test(node)
8
- on_pass = node.find(:on_pass)
9
- on_fail = node.find(:on_fail)
10
- unless on_fail.nil?
11
- n = node.remove(on_fail) if branch_is_empty?(on_fail)
12
- return n
9
+ if on_pass = node.find(:on_pass)
10
+ node = node.remove(on_pass) if on_pass.children.empty?
13
11
  end
14
- node
15
- end
16
-
17
- # Returns true if:
18
- # - node is completely empty
19
- # - only child is (continue) node
20
- # - only two children, one continue and one set-result
21
- def branch_is_empty?(node)
22
- children = node.children.dup
23
- return true if children.nil?
24
-
25
- # test for only-child situation
26
- first_born = children.shift
27
- if children.empty?
28
- if first_born == n0(:continue)
29
- return true
30
- else
31
- return false
32
- end
33
- end
34
-
35
- # if only 2 children, check qualificataions, else done and return false
36
- next_born = children.shift
37
- if children.empty?
38
- if (first_born.type == :continue && next_born.type == :set_result) ||
39
- (first_born.type == :set_result && next_born.type == :continue)
40
- return true
41
- end
12
+ if on_fail = node.find(:on_fail)
13
+ node = node.remove(on_fail) if on_fail.children.empty?
42
14
  end
43
- false
15
+ node = node.updated(nil, process_all(node.children))
44
16
  end
45
17
  end
46
18
  end
@@ -0,0 +1,33 @@
1
+ module OrigenTesters
2
+ module SmartestBasedTester
3
+ class Base
4
+ module Processors
5
+ # Processes the AST and tabulates occurrences of unique set_run_flag nodes
6
+ class ExtractRunFlagTable < ATP::Processor
7
+ # Hash table of run_flag name with number of times used
8
+ attr_reader :run_flag_table
9
+
10
+ # Reset hash table
11
+ def initialize
12
+ @run_flag_table = {}.with_indifferent_access
13
+ end
14
+
15
+ # For run_flag nodes, increment # of occurrences for specified flag
16
+ def on_run_flag(node)
17
+ children = node.children.dup
18
+ names = children.shift
19
+ state = children.shift
20
+ Array(names).each do |name|
21
+ if @run_flag_table[name.to_sym].nil?
22
+ @run_flag_table[name.to_sym] = 1
23
+ else
24
+ @run_flag_table[name.to_sym] += 1
25
+ end
26
+ end
27
+ process_all(node.children)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,139 +2,184 @@ module OrigenTesters
2
2
  module SmartestBasedTester
3
3
  class Base
4
4
  module Processors
5
+ # This processor eliminates the use of run flags between adjacent tests:
6
+ #
7
+ # s(:flow,
8
+ # s(:name, "prb1"),
9
+ # s(:test,
10
+ # s(:name, "test1"),
11
+ # s(:id, "t1"),
12
+ # s(:on_fail,
13
+ # s(:set_run_flag, "t1_FAILED", "auto_generated"),
14
+ # s(:continue))),
15
+ # s(:run_flag, "t1_FAILED", true,
16
+ # s(:test,
17
+ # s(:name, "test2"))))
18
+ #
19
+ #
20
+ # s(:flow,
21
+ # s(:name, "prb1"),
22
+ # s(:test,
23
+ # s(:name, "test1"),
24
+ # s(:id, "t1"),
25
+ # s(:on_fail,
26
+ # s(:test,
27
+ # s(:name, "test2")))))
28
+ #
5
29
  class FlagOptimizer < ATP::Processor
6
30
  attr_reader :run_flag_table
7
- # This optimizes the AST such that any adjacent flow noes that
8
- #
9
- # For example this AST:
10
- # (flow
11
- # (test
12
- # (name "test1")
13
- # (on-fail
14
- # (set-run-flag "t1_FAILED")))
15
- # (run-flag "t1_FAILED" true
16
- # (test
17
- # (name "test2"))
18
- # (test
19
- # (name "test3")))
20
- # (test
21
- # (name "test4")
22
- # (on-pass
23
- # (set-run-flag "t4_PASSED"))
24
- # (on-fail
25
- # (continue)))
26
- # (run-flag "t4_PASSED" true
27
- # (test
28
- # (name "test5"))
29
- # (test
30
- # (name "test6"))))
31
- #
32
- # Will be optimized to this:
33
- # (flow
34
- # (test
35
- # (name "test1")
36
- # (on-fail
37
- # (test
38
- # (name "test2"))
39
- # (test
40
- # (name "test3"))))
41
- # (test
42
- # (name "test4")
43
- # (on-pass
44
- # (test
45
- # (name "test5"))
46
- # (test
47
- # (name "test6")))
48
- # (on-fail
49
- # (continue))))
50
31
 
51
- # Processes the AST and tabulates occurences of unique set_run_flag nodes
52
- class ExtractRunFlagTable < ATP::Processor
53
- # Hash table of run_flag name with number of times used
54
- attr_reader :run_flag_table
32
+ def run(node)
33
+ # Pre-process the AST for # of occurrences of each run-flag used
34
+ t = ExtractRunFlagTable.new
35
+ t.process(node)
36
+ @run_flag_table = t.run_flag_table
37
+ process(node)
38
+ end
55
39
 
56
- # Reset hash table
57
- def initialize
58
- @run_flag_table = {}
40
+ def on_named_collection(node)
41
+ name, *nodes = *node
42
+ node.updated(nil, [name] + optimize(process_all(nodes)))
43
+ end
44
+ alias_method :on_flow, :on_named_collection
45
+ alias_method :on_group, :on_named_collection
46
+
47
+ def on_run_flag(node)
48
+ name, state, *nodes = *node
49
+ if run_flag_to_remove.last && run_flag_to_remove.last == node.to_a[0..1]
50
+ node.to_a.last
51
+ else
52
+ node.updated(nil, [name, state] + optimize(process_all(nodes)))
59
53
  end
54
+ end
60
55
 
61
- # For run_flag nodes, increment # of occurences for specified flag
62
- def on_run_flag(node)
63
- children = node.children.dup
64
- name = children.shift
65
- state = children.shift
66
- unless name.is_a?(Array)
67
- if @run_flag_table[name.to_sym].nil?
68
- @run_flag_table[name.to_sym] = 1
69
- else
70
- @run_flag_table[name.to_sym] += 1
56
+ def on_on_fail(node)
57
+ if to_inline = nodes_to_inline_on_pass_or_fail.last
58
+ # If this node sets the flag that gates the node to be inlined
59
+ set_run_flag = node.find(:set_run_flag)
60
+ if set_run_flag && gated_by_set?(set_run_flag.to_a[0], to_inline)
61
+ # Remove the sub-node that sets the flag if there are no further references to it
62
+
63
+ if @run_flag_table[set_run_flag.to_a[0]] == 1 || !@run_flag_table[set_run_flag.to_a[0]]
64
+ node = node.updated(nil, node.children - [set_run_flag])
71
65
  end
66
+
67
+ # And append the content of the node to be in_lined at the end of this on pass/fail node
68
+ append = reorder_nested_run_flags(set_run_flag.to_a[0], to_inline).to_a[2..-1]
69
+
70
+ # Belt and braces approach to make sure this node to be inlined does
71
+ # not get picked up anywhere else
72
+ nodes_to_inline_on_pass_or_fail.pop
73
+ nodes_to_inline_on_pass_or_fail << nil
72
74
  end
73
75
  end
76
+ node.updated(nil, optimize(process_all(node.children + Array(append))))
74
77
  end
78
+ alias_method :on_on_pass, :on_on_fail
75
79
 
76
- # Only run this on top level flow and consider adjacent nodes, no need for
77
- # looking at nested conditions.
78
- def on_flow(node)
79
- # Pre-process the AST for # of occurences of each run-flag used
80
- t = ExtractRunFlagTable.new
81
- t.process(node)
82
- @run_flag_table = t.run_flag_table
83
-
84
- name, *nodes = *node
80
+ def optimize(nodes)
85
81
  results = []
86
- node_a = nil
87
- nodes.each do |node_b|
88
- if node_a && node_a.type == :test && node_b.type == :run_flag
89
- result, node_a = remove_run_flag(node_a, node_b)
90
- results << result
82
+ node1 = nil
83
+ nodes.each do |node2|
84
+ if node1
85
+ if can_be_combined?(node1, node2)
86
+ node1 = combine(node1, node2)
87
+ else
88
+ results << node1
89
+ node1 = node2
90
+ end
91
91
  else
92
- results << node_a unless node_a.nil?
93
- node_a = node_b
92
+ node1 = node2
94
93
  end
95
94
  end
96
- results << node_a unless node_a.nil?
97
- node.updated(nil, [name] + results)
95
+ results << node1 if node1
96
+ results
98
97
  end
99
98
 
100
- # Given two adjacent nodes, where the first (a) is a test and the second (b)
101
- # is a run_flag, determine if (a) conditionally sets the same flag that (b)
102
- # uses. If it does, do a logical replacement, if not, move on quietly.
103
- def remove_run_flag(node_a, node_b)
104
- on_pass = node_a.find(:on_pass)
105
- on_fail = node_a.find(:on_fail)
106
-
107
- unless on_pass.nil? && on_fail.nil?
108
- if on_pass.nil?
109
- flag_node = on_fail.find(:set_run_flag)
110
- conditional = [flag_node, on_fail]
111
- else
112
- flag_node = on_pass.find(:set_run_flag)
113
- conditional = [flag_node, on_pass]
99
+ def can_be_combined?(node1, node2)
100
+ if node1.type == :test && node2.type == :run_flag
101
+ if node1.find_all(:on_fail, :on_pass).any? do |node|
102
+ if n = node.find(:set_run_flag)
103
+ # Inline instead of setting a flag if...
104
+ gated_by_set?(n.to_a[0], node2) && # The flag set by node1 is gating node2
105
+ n.to_a[1] == 'auto_generated' && # The flag has been generated and not specified by the user
106
+ n.to_a[0] !~ /_RAN$/ # And don't compress RAN flags because they can be set by both on_fail and on_pass
107
+ end
108
+ end
109
+ return true
114
110
  end
115
111
  end
116
- unless conditional.nil?
117
- children = node_b.children.dup
118
- name = children.shift
119
- # remove the '_RAN' here so it won't match and if_ran cases are ignored
120
- name = name.gsub(/_RAN$/, '') unless name.is_a?(Array)
121
- state = children.shift
122
- *nodes = *children
123
- flag_node_b = n2(:set_run_flag, name, 'auto_generated') if state == true
112
+ false
113
+ end
124
114
 
125
- if conditional.first == flag_node_b
126
- n = conditional.last.dup
127
- result = node_a.remove(n)
128
- n = n.remove(conditional.first) if @run_flag_table[name.to_sym] == 1
129
- n = n.remove(n0(:continue)) if n.type == :on_fail
130
- s = n.find(:set_result) if n.type == :on_fail
131
- n = n.remove(s) if s
132
- n = n.updated(nil, n.children + (nodes.is_a?(Array) ? nodes : [nodes]))
133
- result = result.updated(nil, result.children + (n.is_a?(Array) ? n : [n]))
134
- return result, nil
135
- end
115
+ def combine(node1, node2)
116
+ nodes_to_inline_on_pass_or_fail << node2
117
+ node1 = node1.updated(nil, process_all(node1.children))
118
+ nodes_to_inline_on_pass_or_fail.pop
119
+ node1
120
+ end
121
+
122
+ # node will always be a run_flag type node, guaranteed by the caller
123
+ #
124
+ # Returns true if flag matches the one supplied and it is required to be set(true), like this:
125
+ #
126
+ # s(:run_flag, flag, true,
127
+ # s(:test, ...
128
+ #
129
+ # Also returns true if flag matches the one supplied, but it is nested within other flag conditions:
130
+ #
131
+ # s(:run_flag, other_flag, false,
132
+ # s(:run_flag, other_flag2, true,
133
+ # s(:run_flag, flag, true,
134
+ # s(:test, ...
135
+ def gated_by_set?(flag, node)
136
+ (flag == node.to_a[0] && node.to_a[1]) ||
137
+ (node.to_a.size == 3 && node.to_a.last.type == :run_flag && gated_by_set?(flag, node.to_a.last))
138
+ end
139
+
140
+ # Returns the node with the run_flag clauses re-ordered to have the given flag of interest at the top.
141
+ #
142
+ # The caller guarantees the run_flag clause containing the given flag is present.
143
+ #
144
+ # For example, given this node:
145
+ #
146
+ # s(:run_flag, "flag1", false,
147
+ # s(:run_flag, "ot_BEA7F3B_FAILED", true,
148
+ # s(:test,
149
+ # s(:object, <TestSuite: inner_test1_BEA7F3B>),
150
+ # s(:name, "inner_test1_BEA7F3B"),
151
+ # s(:number, 0),
152
+ # s(:id, "it1_BEA7F3B"),
153
+ # s(:on_fail,
154
+ # s(:render, "multi_bin;")))))
155
+ #
156
+ # Then this node would be returned when the flag of interest is ot_BEA7F3B_FAILED:
157
+ #
158
+ # s(:run_flag, "ot_BEA7F3B_FAILED", true,
159
+ # s(:run_flag, "flag1", false,
160
+ # s(:test,
161
+ # s(:object, <TestSuite: inner_test1_BEA7F3B>),
162
+ # s(:name, "inner_test1_BEA7F3B"),
163
+ # s(:number, 0),
164
+ # s(:id, "it1_BEA7F3B"),
165
+ # s(:on_fail,
166
+ # s(:render, "multi_bin;")))))
167
+ def reorder_nested_run_flags(flag, node)
168
+ # If the run_flag we care about is already at the top, just return node
169
+ unless node.to_a[0] == flag && node.to_a[1]
170
+ run_flag_to_remove << [flag, true]
171
+ node = n(:run_flag, [flag, true, process(node)])
172
+ run_flag_to_remove.pop
136
173
  end
137
- [node_a, node_b]
174
+ node
175
+ end
176
+
177
+ def run_flag_to_remove
178
+ @run_flag_to_remove ||= []
179
+ end
180
+
181
+ def nodes_to_inline_on_pass_or_fail
182
+ @nodes_to_inline_on_pass_or_fail ||= []
138
183
  end
139
184
  end
140
185
  end
@@ -5,9 +5,9 @@ declarations
5
5
 
6
6
  % clean_runtime_control_variables.each do |var|
7
7
  % if var.is_a?(Array)
8
- @<%= var[0].to_s.upcase %> = <%= var[1].is_a?(String) || var[1].is_a?(Symbol) ? "\"#{var[1]}\"" : var[1] %>;
8
+ @<%= var[0].to_s %> = <%= var[1].is_a?(String) || var[1].is_a?(Symbol) ? "\"#{var[1]}\"" : var[1] %>;
9
9
  % else
10
- @<%= var.to_s.upcase %> = 0;
10
+ @<%= var.to_s %> = 0;
11
11
  % end
12
12
  % end
13
13
 
@@ -17,9 +17,9 @@ flags
17
17
 
18
18
  % clean_flow_control_variables.each do |var|
19
19
  % if var.is_a?(Array)
20
- user <%= var[0].to_s.upcase %> = <%= var[1].is_a?(String) || var[1].is_a?(Symbol) ? "\"#{var[1]}\"" : var[1] %>;
20
+ user <%= var[0].to_s %> = <%= var[1].is_a?(String) || var[1].is_a?(Symbol) ? "\"#{var[1]}\"" : var[1] %>;
21
21
  % else
22
- user <%= var.to_s.upcase %> = 0;
22
+ user <%= var.to_s %> = 0;
23
23
  % end
24
24
  % end
25
25
 
@@ -146,12 +146,18 @@ module OrigenTesters
146
146
  original = @timeset
147
147
  timeset_changed(timeset)
148
148
  @timeset = timeset
149
+ dut.timeset = timeset.name if dut.timesets[timeset.name]
150
+ dut.current_timeset_period = timeset.period_in_ns
149
151
  yield
150
152
  timeset_changed(original)
151
153
  @timeset = original
154
+ dut.timeset = original.name if dut.timesets[original.name]
155
+ dut.current_timeset_period = original.period_in_ns
152
156
  else
153
157
  timeset_changed(timeset)
154
158
  @timeset = timeset
159
+ dut.timeset = timeset.name if dut.timesets[timeset.name]
160
+ dut.current_timeset_period = timeset.period_in_ns
155
161
  end
156
162
  end
157
163
 
@@ -208,5 +208,15 @@ Flow.create do |options|
208
208
 
209
209
  pass 2, if_ran: :g100
210
210
 
211
+ log 'Test node optimization within an if_failed branch'
212
+ func :some_func_test, id: :sft1
213
+
214
+ if_failed :sft1 do
215
+ bin 10, if_flag: "Alarm"
216
+ bin 11, unless_flag: "Alarm"
217
+ bin 12, if_enable: "AlarmEnabled"
218
+ bin 13, unless_enable: "AlarmEnabled"
219
+ end
220
+
211
221
  pass 1, description: "Good die!", softbin: 1
212
222
  end
@@ -338,4 +338,85 @@ Flow.create interface: 'OrigenTesters::Test::Interface' do
338
338
 
339
339
  func :test36, on_fail: { render: 'multi_bin;' }, if_flag: :my_flag
340
340
  end
341
+
342
+ log 'An optimization test case, this should not generate a flag on V93K'
343
+ func :test1, id: :t1a
344
+
345
+ if_passed :t1a do
346
+ func :test2
347
+ end
348
+
349
+ if_failed :t1a do
350
+ func :test3
351
+ bin 10
352
+ end
353
+
354
+ log 'The reverse optimization test case, this should not generate a flag on V93K'
355
+ func :test1, id: :t1b
356
+
357
+ if_failed :t1b do
358
+ func :test3
359
+ bin 10
360
+ end
361
+
362
+ if_passed :t1b do
363
+ func :test2
364
+ end
365
+
366
+ if tester.v93k?
367
+ log 'Nested optimization test case'
368
+ func :outer_test, id: :ot
369
+ if_failed :ot do
370
+ unless_flag :flag1 do
371
+ func :inner_test1, id: :it1
372
+ render 'multi_bin;', if_failed: :it1
373
+ end
374
+ end
375
+
376
+ log 'Nested flag optimization test case'
377
+ if_flag :flag1 do
378
+ func :test4, id: :nf_t4
379
+ if_failed :nf_t4 do
380
+ render 'multi_bin;', if_flag: :flag1
381
+ end
382
+ end
383
+
384
+ log 'The setting of flags used in later OR conditions should be preserved'
385
+ func :test2, id: :of1
386
+ func :test3, if_failed: :of1
387
+ func :test2, id: :of2
388
+ func :test3, if_failed: :of2
389
+ func :test4
390
+ func :test4, if_any_failed: [:of1, :of2]
391
+
392
+ log 'The setting of flags used in later AND conditions should be preserved'
393
+ func :test2, id: :af1
394
+ func :test3, if_failed: :af1
395
+ func :test2, id: :af2
396
+ func :test3, if_failed: :af2
397
+ func :test4
398
+ func :test4, if_all_failed: [:af1, :af2]
399
+
400
+ log 'Adjacent tests that set a flag and then use it in an OR condition should be valid'
401
+ func :test2, id: :of11
402
+ func :test2, id: :of12
403
+ func :test4, if_any_failed: [:of11, :of12]
404
+
405
+ log 'Adjacent tests that set a flag and then use it in an AND condition should be valid'
406
+ func :test2, id: :af11
407
+ func :test2, id: :af12
408
+ func :test4, if_all_failed: [:af11, :af12]
409
+
410
+ log 'Adjacent if combiner test case 1'
411
+ func :test1, if_enable: :my_enable_word
412
+ func :test2, unless_enable: :my_enable_word
413
+ func :test1, if_flag: :my_flag
414
+ func :test2, unless_flag: :my_flag
415
+
416
+ log 'Adjacent if combiner test case 2'
417
+ func :test2, unless_enable: :my_enable_word
418
+ func :test1, if_enable: :my_enable_word
419
+ func :test2, unless_flag: :my_flag
420
+ func :test1, if_flag: :my_flag
421
+ end
341
422
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: origen_testers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen McGinty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-19 00:00:00.000000000 Z
11
+ date: 2017-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: origen
@@ -241,7 +241,10 @@ files:
241
241
  - lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb
242
242
  - lib/origen_testers/smartest_based_tester/base/pattern_master.rb
243
243
  - lib/origen_testers/smartest_based_tester/base/processors.rb
244
+ - lib/origen_testers/smartest_based_tester/base/processors/adjacent_if_combiner.rb
245
+ - lib/origen_testers/smartest_based_tester/base/processors/continue_implementer.rb
244
246
  - lib/origen_testers/smartest_based_tester/base/processors/empty_branch_cleaner.rb
247
+ - lib/origen_testers/smartest_based_tester/base/processors/extract_run_flag_table.rb
245
248
  - lib/origen_testers/smartest_based_tester/base/processors/extract_set_variables.rb
246
249
  - lib/origen_testers/smartest_based_tester/base/processors/flag_optimizer.rb
247
250
  - lib/origen_testers/smartest_based_tester/base/processors/if_ran_cleaner.rb