Class: OrigenTesters::ATP::Processors::FlagOptimizer
- Inherits:
-
OrigenTesters::ATP::Processor
- Object
- OrigenTesters::ATP::Processor
- OrigenTesters::ATP::Processors::FlagOptimizer
- Defined in:
- lib/origen_testers/atp/processors/flag_optimizer.rb
Overview
This processor eliminates the use of run flags between adjacent tests:
s(:flow,
s(:name, "prb1"),
s(:test,
s(:name, "test1"),
s(:id, "t1"),
s(:on_fail,
s(:set_flag, "t1_FAILED", "auto_generated"),
s(:continue))),
s(:if_flag, "t1_FAILED",
s(:test,
s(:name, "test2"))))
s(:flow,
s(:name, "prb1"),
s(:test,
s(:name, "test1"),
s(:id, "t1"),
s(:on_fail,
s(:test,
s(:name, "test2")))))
Defined Under Namespace
Classes: ExtractRunFlagTable
Instance Attribute Summary collapse
-
#optimize_when_continue ⇒ Object
readonly
Returns the value of attribute optimize_when_continue.
-
#run_flag_table ⇒ Object
readonly
Returns the value of attribute run_flag_table.
Instance Method Summary collapse
- #can_be_combined?(node1, node2) ⇒ Boolean
- #combine(node1, node2) ⇒ Object
-
#gated_by_set?(flag, node) ⇒ Boolean
node will always be an if_flag or unless_flag type node, guaranteed by the caller.
- #if_run_flag_to_remove ⇒ Object
- #nodes_to_inline_on_pass_or_fail ⇒ Object
- #on_if_flag(node) ⇒ Object
- #on_named_collection(node) ⇒ Object (also: #on_flow, #on_group, #on_unless_flag, #on_sub_flow)
- #on_on_fail(node) ⇒ Object (also: #on_on_pass)
- #on_unnamed_collection(node) ⇒ Object (also: #on_else)
- #on_whenever(node) ⇒ Object (also: #on_whenever_all, #on_whenever_any)
- #optimize(nodes) ⇒ Object
-
#reorder_nested_run_flags(flag, node) ⇒ Object
Returns the node with the run_flag clauses re-ordered to have the given flag of interest at the top.
- #run(node, options = {}) ⇒ Object
Methods inherited from OrigenTesters::ATP::Processor
#add_global_flag, #clean_flag, #extract_globals, #extract_volatiles, #global_flag?, #global_flags, #handler_missing, #process, #process_all, #volatile?, #volatile_flags
Instance Attribute Details
#optimize_when_continue ⇒ Object (readonly)
Returns the value of attribute optimize_when_continue.
28 29 30 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 28 def optimize_when_continue @optimize_when_continue end |
#run_flag_table ⇒ Object (readonly)
Returns the value of attribute run_flag_table.
28 29 30 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 28 def run_flag_table @run_flag_table end |
Instance Method Details
#can_be_combined?(node1, node2) ⇒ Boolean
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 143 def can_be_combined?(node1, node2) if (node1.type == :test || node1.type == :sub_flow) && (node2.type == :if_flag || node2.type == :unless_flag) && # Don't optimize tests which are marked as continue if told not to !(node1.find(:on_fail) && node1.find(:on_fail).find(:continue) && !optimize_when_continue) if node1.find_all(:on_fail, :on_pass).any? do |node| if n = node.find(:set_flag) # Inline instead of setting a flag if... gated_by_set?(n.to_a[0], node2) && # The flag set by node1 is gating node2 n.to_a[1] == 'auto_generated' && # The flag has been generated and not specified by the user n.to_a[0] !~ /_RAN$/ && # And don't compress RAN flags because they can be set by both on_fail and on_pass !volatile?(n.to_a[0]) # And make sure the flag has not been marked as volatile end end return true end end false end |
#combine(node1, node2) ⇒ Object
163 164 165 166 167 168 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 163 def combine(node1, node2) nodes_to_inline_on_pass_or_fail << node2 # .updated(nil, process_all(node2.children)) node1 = node1.updated(nil, process_all(node1.children)) nodes_to_inline_on_pass_or_fail.pop node1 end |
#gated_by_set?(flag, node) ⇒ Boolean
node will always be an if_flag or unless_flag type node, guaranteed by the caller
Returns true if flag matches the one supplied
s(:if_flag, flag,
s(:test, ...
Also returns true if flag matches the one supplied, but it is nested within other flag conditions:
s(:unless_flag, other_flag,
s(:if_flag, other_flag2,
s(:if_flag, flag,
s(:test, ...
183 184 185 186 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 183 def gated_by_set?(flag, node) (flag == node.to_a[0] && node.type == :if_flag) || (node.to_a.size == 2 && (node.to_a.last.type == :if_flag || node.to_a.last.type == :unless_flag) && gated_by_set?(flag, node.to_a.last)) end |
#if_run_flag_to_remove ⇒ Object
225 226 227 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 225 def if_run_flag_to_remove @if_run_flag_to_remove ||= [] end |
#nodes_to_inline_on_pass_or_fail ⇒ Object
229 230 231 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 229 def nodes_to_inline_on_pass_or_fail @nodes_to_inline_on_pass_or_fail ||= [] end |
#on_if_flag(node) ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 90 def on_if_flag(node) name, *nodes = *node # Remove this node and return its children if required if if_run_flag_to_remove.last == node.to_a[0] node.updated(:inline, optimize(process_all(node.to_a[1..-1]))) else node.updated(nil, [name] + optimize(process_all(nodes))) end end |
#on_named_collection(node) ⇒ Object Also known as: on_flow, on_group, on_unless_flag, on_sub_flow
69 70 71 72 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 69 def on_named_collection(node) name, *nodes = *node node.updated(nil, [name] + optimize(process_all(nodes))) end |
#on_on_fail(node) ⇒ Object Also known as: on_on_pass
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 100 def on_on_fail(node) if to_inline = nodes_to_inline_on_pass_or_fail.last # If this node sets the flag that gates the node to be inlined set_flag = node.find(:set_flag) if set_flag && gated_by_set?(set_flag.to_a[0], to_inline) # Remove the sub-node that sets the flag if there are no further references to it if @run_flag_table[set_flag.to_a[0]] == 1 || !@run_flag_table[set_flag.to_a[0]] node = node.updated(nil, node.children - [set_flag]) end # And append the content of the node to be in_lined at the end of this on pass/fail node append = reorder_nested_run_flags(set_flag.to_a[0], to_inline).to_a[1..-1] # Belt and braces approach to make sure this node to be inlined does # not get picked up anywhere else nodes_to_inline_on_pass_or_fail.pop nodes_to_inline_on_pass_or_fail << nil end end node.updated(nil, optimize(process_all(node.children + Array(append)))) end |
#on_unnamed_collection(node) ⇒ Object Also known as: on_else
78 79 80 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 78 def on_unnamed_collection(node) node.updated(nil, optimize(process_all(node.children))) end |
#on_whenever(node) ⇒ Object Also known as: on_whenever_all, on_whenever_any
83 84 85 86 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 83 def on_whenever(node) name, *nodes = *node node.updated(nil, [name] + optimize(process_all(nodes))) end |
#optimize(nodes) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 124 def optimize(nodes) results = [] node1 = nil nodes.each do |node2| if node1 if can_be_combined?(node1, node2) node1 = combine(node1, node2) else results << node1 node1 = node2 end else node1 = node2 end end results << node1 if node1 results end |
#reorder_nested_run_flags(flag, node) ⇒ Object
Returns the node with the run_flag clauses re-ordered to have the given flag of interest at the top.
The caller guarantees the run_flag clause containing the given flag is present.
For example, given this node:
s(:unless_flag, "flag1",
s(:if_flag, "ot_BEA7F3B_FAILED",
s(:test,
s(:object, <TestSuite: inner_test1_BEA7F3B>),
s(:name, "inner_test1_BEA7F3B"),
s(:number, 0),
s(:id, "it1_BEA7F3B"),
s(:on_fail,
s(:render, "multi_bin;")))))
Then this node would be returned when the flag of interest is ot_BEA7F3B_FAILED:
s(:if_flag, "ot_BEA7F3B_FAILED",
s(:unless_flag, "flag1",
s(:test,
s(:object, <TestSuite: inner_test1_BEA7F3B>),
s(:name, "inner_test1_BEA7F3B"),
s(:number, 0),
s(:id, "it1_BEA7F3B"),
s(:on_fail,
s(:render, "multi_bin;")))))
215 216 217 218 219 220 221 222 223 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 215 def reorder_nested_run_flags(flag, node) # If the run_flag we care about is already at the top, just return node unless node.to_a[0] == flag && node.type == :if_flag if_run_flag_to_remove << flag node = node.updated(:if_flag, [flag] + [process(node)]) if_run_flag_to_remove.pop end node end |
#run(node, options = {}) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/origen_testers/atp/processors/flag_optimizer.rb', line 56 def run(node, = {}) = { optimize_when_continue: true }.merge() @optimize_when_continue = [:optimize_when_continue] # Pre-process the AST for # of occurrences of each run-flag used t = ExtractRunFlagTable.new t.process(node) @run_flag_table = t.run_flag_table extract_volatiles(node) process(node) end |