origen_testers 0.31.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/application.rb +3 -1
- data/config/shared_commands.rb +4 -0
- data/config/version.rb +1 -1
- data/lib/origen_testers/api.rb +8 -0
- data/lib/origen_testers/atp/flow.rb +30 -9
- data/lib/origen_testers/flow.rb +36 -2
- data/lib/origen_testers/generator.rb +44 -5
- data/lib/origen_testers/interface.rb +22 -2
- data/lib/origen_testers/origen_ext/generator.rb +4 -3
- data/lib/origen_testers/origen_ext/generator/flow.rb +99 -5
- data/lib/origen_testers/program_generators.rb +5 -1
- data/lib/origen_testers/smartest_based_tester.rb +1 -0
- data/lib/origen_testers/smartest_based_tester/base.rb +177 -114
- data/lib/origen_testers/smartest_based_tester/base/flow.rb +329 -127
- data/lib/origen_testers/smartest_based_tester/base/generator.rb +25 -7
- data/lib/origen_testers/smartest_based_tester/base/limits_file.rb +186 -60
- data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +4 -0
- data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +4 -0
- data/lib/origen_testers/smartest_based_tester/base/processors/extract_bin_names.rb +5 -1
- data/lib/origen_testers/smartest_based_tester/base/processors/extract_flow_vars.rb +108 -0
- data/lib/origen_testers/smartest_based_tester/base/test_method.rb +8 -3
- data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +9 -108
- data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +17 -7
- data/lib/origen_testers/smartest_based_tester/base/variables_file.rb +29 -7
- data/lib/origen_testers/smartest_based_tester/smt7.rb +59 -0
- data/lib/origen_testers/smartest_based_tester/smt8.rb +218 -0
- data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +32 -0
- data/lib/origen_testers/smartest_based_tester/v93k/templates/vars.tf.erb +2 -2
- data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +109 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8.rb +8 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb +234 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/generator.rb +48 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/limits_file.rb +14 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/limits_workbook.rb +148 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/limits.csv.erb +3 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/template.flow.erb +41 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/test_suite.rb +66 -0
- data/lib/origen_testers/stil_based_tester/base.rb +4 -0
- data/lib/origen_testers/test/interface.rb +16 -2
- data/lib/origen_testers/vector_generator.rb +9 -4
- data/lib/origen_testers/vector_pipeline.rb +1 -1
- data/pattern/nvm/v93k/v93k_workout.rb +7 -0
- data/program/_erase_vfy.rb +2 -1
- data/program/components/_deep_nested.rb +3 -0
- data/program/components/_prb1_main.rb +1 -1
- data/program/components/_prb2_main.rb +6 -2
- data/program/flow_control.rb +3 -3
- data/program/prb1.rb +4 -0
- data/program/prb2.rb +7 -3
- data/templates/origen_guides/pattern/v93k.md.erb +24 -0
- data/templates/origen_guides/program/v93k.md.erb +6 -148
- data/templates/origen_guides/program/v93ksmt7.md.erb +165 -0
- data/templates/origen_guides/program/v93ksmt8.md.erb +112 -0
- metadata +30 -3
- data/lib/origen_testers/smartest_based_tester/base/test_methods/smart_calc_tml.rb +0 -23
@@ -4,6 +4,38 @@ module OrigenTesters
|
|
4
4
|
require 'origen_testers/smartest_based_tester/base/flow'
|
5
5
|
class Flow < Base::Flow
|
6
6
|
TEMPLATE = "#{Origen.root!}/lib/origen_testers/smartest_based_tester/v93k/templates/template.tf.erb"
|
7
|
+
|
8
|
+
def flow_header
|
9
|
+
h = [' {']
|
10
|
+
if add_flow_enable
|
11
|
+
h << " if @#{flow_enable_var_name} == 1 then"
|
12
|
+
h << ' {'
|
13
|
+
i = ' '
|
14
|
+
else
|
15
|
+
i = ''
|
16
|
+
end
|
17
|
+
if set_runtime_variables.size > 0
|
18
|
+
h << i + ' {'
|
19
|
+
set_runtime_variables.each do |var|
|
20
|
+
h << i + " @#{generate_flag_name(var.to_s)} = -1;"
|
21
|
+
end
|
22
|
+
h << i + ' }, open,"Init Flow Control Vars", ""'
|
23
|
+
end
|
24
|
+
h
|
25
|
+
end
|
26
|
+
|
27
|
+
def flow_footer
|
28
|
+
f = []
|
29
|
+
if add_flow_enable
|
30
|
+
f << ' }'
|
31
|
+
f << ' else'
|
32
|
+
f << ' {'
|
33
|
+
f << ' }'
|
34
|
+
end
|
35
|
+
f << ''
|
36
|
+
f << " }, open,\"#{flow_name}\",\"#{flow_description}\""
|
37
|
+
f
|
38
|
+
end
|
7
39
|
end
|
8
40
|
end
|
9
41
|
end
|
@@ -3,7 +3,7 @@ language_revision = 1;
|
|
3
3
|
|
4
4
|
declarations
|
5
5
|
|
6
|
-
%
|
6
|
+
% declarations.each do |var|
|
7
7
|
% if var.is_a?(Array)
|
8
8
|
@<%= var[0].to_s %> = <%= var[1].is_a?(String) || var[1].is_a?(Symbol) ? "\"#{var[1]}\"" : var[1] %>;
|
9
9
|
% else
|
@@ -15,7 +15,7 @@ end
|
|
15
15
|
-----------------------------------------------------------------
|
16
16
|
flags
|
17
17
|
|
18
|
-
%
|
18
|
+
% flags.each do |var|
|
19
19
|
% if var.is_a?(Array)
|
20
20
|
user <%= var[0].to_s %> = <%= var[1].is_a?(String) || var[1].is_a?(Symbol) ? "\"#{var[1]}\"" : var[1] %>;
|
21
21
|
% else
|
@@ -3,6 +3,115 @@ module OrigenTesters
|
|
3
3
|
class V93K
|
4
4
|
require 'origen_testers/smartest_based_tester/base/test_suite'
|
5
5
|
class TestSuite < Base::TestSuite
|
6
|
+
ATTRS =
|
7
|
+
%w(name
|
8
|
+
comment
|
9
|
+
|
10
|
+
timing_equation timing_spec timing_set
|
11
|
+
level_equation level_spec level_set
|
12
|
+
analog_set
|
13
|
+
pattern
|
14
|
+
context
|
15
|
+
test_type
|
16
|
+
test_method
|
17
|
+
|
18
|
+
test_number
|
19
|
+
test_level
|
20
|
+
|
21
|
+
bypass
|
22
|
+
set_pass
|
23
|
+
set_fail
|
24
|
+
hold
|
25
|
+
hold_on_fail
|
26
|
+
output_on_pass
|
27
|
+
output_on_fail
|
28
|
+
pass_value
|
29
|
+
fail_value
|
30
|
+
per_pin_on_pass
|
31
|
+
per_pin_on_fail
|
32
|
+
log_mixed_signal_waveform
|
33
|
+
fail_per_label
|
34
|
+
ffc_enable
|
35
|
+
log_first
|
36
|
+
ffv_enable
|
37
|
+
frg_enable
|
38
|
+
hardware_dsp_disable
|
39
|
+
)
|
40
|
+
|
41
|
+
ALIASES = {
|
42
|
+
tim_equ_set: :timing_equation,
|
43
|
+
tim_spec_set: :timing_spec,
|
44
|
+
timset: :timing_set,
|
45
|
+
timeset: :timing_set,
|
46
|
+
time_set: :timing_set,
|
47
|
+
lev_equ_set: :level_equation,
|
48
|
+
lev_spec_set: :level_spec,
|
49
|
+
levset: :level_set,
|
50
|
+
levels: :level_set,
|
51
|
+
pin_levels: :level_set,
|
52
|
+
anaset: :analog_set,
|
53
|
+
test_num: :test_number,
|
54
|
+
test_function: :test_method,
|
55
|
+
value_on_pass: :pass_value,
|
56
|
+
value_on_fail: :fail_value,
|
57
|
+
seqlbl: :pattern,
|
58
|
+
mx_waves_enable: :log_mixed_signal_waveform,
|
59
|
+
hw_dsp_disable: :hardware_dsp_disable,
|
60
|
+
ffc_on_fail: :log_first
|
61
|
+
}
|
62
|
+
|
63
|
+
DEFAULTS = {
|
64
|
+
output_on_pass: true,
|
65
|
+
output_on_fail: true,
|
66
|
+
pass_value: true,
|
67
|
+
fail_value: true,
|
68
|
+
per_pin_on_pass: true,
|
69
|
+
per_pin_on_fail: true
|
70
|
+
}
|
71
|
+
|
72
|
+
# Generate accessors for all attributes and their aliases
|
73
|
+
ATTRS.each do |attr|
|
74
|
+
if attr == 'name' || attr == 'pattern'
|
75
|
+
attr_reader attr.to_sym
|
76
|
+
else
|
77
|
+
attr_accessor attr.to_sym
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Define the aliases
|
82
|
+
ALIASES.each do |_alias, val|
|
83
|
+
define_method("#{_alias}=") do |v|
|
84
|
+
send("#{val}=", v)
|
85
|
+
end
|
86
|
+
define_method("#{_alias}") do
|
87
|
+
send(val)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def lines
|
92
|
+
if pattern
|
93
|
+
burst = $tester.multiport ? "#{$tester.multiport_name(pattern)}" : "#{pattern}"
|
94
|
+
end
|
95
|
+
l = []
|
96
|
+
l << " comment = \"#{comment}\";" if comment
|
97
|
+
l << " ffc_on_fail = #{wrap_if_string(log_first)};" if log_first
|
98
|
+
l << " local_flags = #{flags};"
|
99
|
+
l << ' override = 1;'
|
100
|
+
l << " override_anaset = #{wrap_if_string(analog_set)};" if analog_set
|
101
|
+
l << " override_lev_equ_set = #{wrap_if_string(level_equation)};" if level_equation
|
102
|
+
l << " override_lev_spec_set = #{wrap_if_string(level_spec)};" if level_spec
|
103
|
+
l << " override_levset = #{wrap_if_string(level_set)};" if level_set
|
104
|
+
l << " override_seqlbl = #{wrap_if_string(burst)};" if pattern
|
105
|
+
l << " override_test_number = #{test_number};" if test_number
|
106
|
+
l << " override_testf = #{test_method.id};" if test_method
|
107
|
+
l << " override_tim_equ_set = #{wrap_if_string(timing_equation)};" if timing_equation
|
108
|
+
l << " override_tim_spec_set = #{wrap_if_string(timing_spec)};" if timing_spec
|
109
|
+
l << " override_timset = #{wrap_if_string(timing_set)};" if timing_set
|
110
|
+
l << ' site_control = "parallel:";'
|
111
|
+
l << ' site_match = 2;'
|
112
|
+
l << " test_level = #{test_level};" if test_level
|
113
|
+
l
|
114
|
+
end
|
6
115
|
end
|
7
116
|
end
|
8
117
|
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module SmartestBasedTester
|
3
|
+
class V93K_SMT8
|
4
|
+
require 'origen_testers/smartest_based_tester/base/flow'
|
5
|
+
class Flow < Base::Flow
|
6
|
+
TEMPLATE = "#{Origen.root!}/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/template.flow.erb"
|
7
|
+
|
8
|
+
def on_test(node)
|
9
|
+
test_suite = node.find(:object).to_a[0]
|
10
|
+
if test_suite.is_a?(String)
|
11
|
+
name = test_suite
|
12
|
+
else
|
13
|
+
name = test_suite.name
|
14
|
+
test_method = test_suite.test_method
|
15
|
+
if test_method.respond_to?(:test_name) && test_method.test_name == '' &&
|
16
|
+
n = node.find(:name)
|
17
|
+
test_method.test_name = n.value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
if node.children.any? { |n| t = n.try(:type); t == :on_fail || t == :on_pass } ||
|
22
|
+
!stack[:on_pass].empty? || !stack[:on_fail].empty?
|
23
|
+
line "#{name}.execute();"
|
24
|
+
@open_test_names << name
|
25
|
+
@post_test_lines << []
|
26
|
+
process_all(node.to_a.reject { |n| t = n.try(:type); t == :on_fail || t == :on_pass })
|
27
|
+
on_pass = node.find(:on_pass)
|
28
|
+
on_fail = node.find(:on_fail)
|
29
|
+
|
30
|
+
if on_fail && on_fail.find(:continue) && tester.force_pass_on_continue
|
31
|
+
if test_method.respond_to?(:force_pass)
|
32
|
+
test_method.force_pass = 1
|
33
|
+
else
|
34
|
+
Origen.log.error 'Force pass on continue has been enabled, but the test method does not have a force_pass attribute!'
|
35
|
+
Origen.log.error " #{node.source}"
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
@open_test_methods << test_method
|
39
|
+
else
|
40
|
+
if test_method.respond_to?(:force_pass)
|
41
|
+
test_method.force_pass = 0
|
42
|
+
end
|
43
|
+
@open_test_methods << nil
|
44
|
+
end
|
45
|
+
|
46
|
+
pass_lines = capture_lines do
|
47
|
+
@indent += 1
|
48
|
+
pass_branch do
|
49
|
+
process_all(on_pass) if on_pass
|
50
|
+
stack[:on_pass].each { |n| process_all(n) }
|
51
|
+
end
|
52
|
+
@indent -= 1
|
53
|
+
end
|
54
|
+
|
55
|
+
fail_lines = capture_lines do
|
56
|
+
@indent += 1
|
57
|
+
fail_branch do
|
58
|
+
process_all(on_fail) if on_fail
|
59
|
+
stack[:on_fail].each { |n| process_all(n) }
|
60
|
+
end
|
61
|
+
@indent -= 1
|
62
|
+
end
|
63
|
+
|
64
|
+
if !pass_lines.empty? && fail_lines.empty?
|
65
|
+
line "if (#{name}.pass) {"
|
66
|
+
pass_lines.each { |l| line l, already_indented: true }
|
67
|
+
line '}'
|
68
|
+
|
69
|
+
elsif pass_lines.empty? && !fail_lines.empty?
|
70
|
+
line "if (!#{name}.pass) {"
|
71
|
+
fail_lines.each { |l| line l, already_indented: true }
|
72
|
+
line '}'
|
73
|
+
|
74
|
+
elsif !pass_lines.empty? && !fail_lines.empty?
|
75
|
+
line "if (#{name}.pass) {"
|
76
|
+
pass_lines.each { |l| line l, already_indented: true }
|
77
|
+
line '} else {'
|
78
|
+
fail_lines.each { |l| line l, already_indented: true }
|
79
|
+
line '}'
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
@open_test_methods.pop
|
84
|
+
@open_test_names.pop
|
85
|
+
@post_test_lines.pop.each { |l| line(l) }
|
86
|
+
else
|
87
|
+
line "#{name}.execute();"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def on_sub_flow(node)
|
92
|
+
sub_flow = sub_flow_from(node)
|
93
|
+
@sub_flows ||= {}
|
94
|
+
path = Pathname.new(node.find(:path).value)
|
95
|
+
name = path.basename('.*').to_s
|
96
|
+
@sub_flows[name] = "#{path.dirname}.#{name}".gsub(/(\/|\\)/, '.')
|
97
|
+
# Pass down all input variables before executing
|
98
|
+
sub_flow.input_variables.each do |var|
|
99
|
+
var = var[0] if var.is_a?(Array)
|
100
|
+
line "#{name}.#{var} = #{var};"
|
101
|
+
end
|
102
|
+
line "#{name}.execute();"
|
103
|
+
# And then retrieve all common output variables
|
104
|
+
(output_variables & sub_flow.output_variables).sort.each do |var|
|
105
|
+
var = var[0] if var.is_a?(Array)
|
106
|
+
line "#{var} = #{name}.#{var};"
|
107
|
+
end
|
108
|
+
if on_pass = node.find(:on_pass)
|
109
|
+
pass_lines = capture_lines do
|
110
|
+
@indent += 1
|
111
|
+
pass_branch do
|
112
|
+
process_all(on_pass) if on_pass
|
113
|
+
end
|
114
|
+
@indent -= 1
|
115
|
+
end
|
116
|
+
on_pass = nil if pass_lines.empty?
|
117
|
+
end
|
118
|
+
|
119
|
+
if on_fail = node.find(:on_fail)
|
120
|
+
fail_lines = capture_lines do
|
121
|
+
@indent += 1
|
122
|
+
fail_branch do
|
123
|
+
process_all(on_fail) if on_fail
|
124
|
+
end
|
125
|
+
@indent -= 1
|
126
|
+
end
|
127
|
+
on_fail = nil if fail_lines.empty?
|
128
|
+
end
|
129
|
+
|
130
|
+
if on_pass && !on_fail
|
131
|
+
line "if (#{name}.pass) {"
|
132
|
+
pass_lines.each { |l| line l, already_indented: true }
|
133
|
+
line '}'
|
134
|
+
|
135
|
+
elsif !on_pass && on_fail
|
136
|
+
line "if (!#{name}.pass) {"
|
137
|
+
fail_lines.each { |l| line l, already_indented: true }
|
138
|
+
line '}'
|
139
|
+
|
140
|
+
elsif on_pass && on_fail
|
141
|
+
line "if (#{name}.pass) {"
|
142
|
+
pass_lines.each { |l| line l, already_indented: true }
|
143
|
+
line '} else {'
|
144
|
+
fail_lines.each { |l| line l, already_indented: true }
|
145
|
+
line '}'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def sub_flows
|
150
|
+
@sub_flows || {}
|
151
|
+
end
|
152
|
+
|
153
|
+
# Variables which should be defined as an input to the current flow
|
154
|
+
def input_variables
|
155
|
+
vars = flow_variables
|
156
|
+
# Jobs and enables flow into a sub-flow
|
157
|
+
(vars[:all][:jobs] + vars[:all][:referenced_enables] + vars[:all][:set_enables] +
|
158
|
+
# As do any flags which are referenced by it but which are not set within it
|
159
|
+
(vars[:all][:referenced_flags] - vars[:all][:set_flags])).uniq.sort do |x, y|
|
160
|
+
x = x[0] if x.is_a?(Array)
|
161
|
+
y = y[0] if y.is_a?(Array)
|
162
|
+
x <=> y
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Variables which should be defined as an output of the current flow
|
167
|
+
def output_variables
|
168
|
+
vars = flow_variables
|
169
|
+
# Flags that are set by this flow flow out of it
|
170
|
+
(vars[:this_flow][:set_flags] +
|
171
|
+
# As do any flags set by its children which are marked as external
|
172
|
+
vars[:all][:set_flags_extern] +
|
173
|
+
# And any flags which are set by a child and referenced in this flow
|
174
|
+
(vars[:this_flow][:referenced_flags] & vars[:sub_flows][:set_flags]) +
|
175
|
+
# And also intermediate flags, those are flags which are set by a child and referenced
|
176
|
+
# by a parent of the current flow
|
177
|
+
intermediate_variables).uniq.sort do |x, y|
|
178
|
+
x = x[0] if x.is_a?(Array)
|
179
|
+
y = y[0] if y.is_a?(Array)
|
180
|
+
x <=> y
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Output variables which are not directly referenced by this flow, but which are referenced by a parent
|
185
|
+
# flow and set by the given child flow and therefore must pass through the current flow.
|
186
|
+
# By calling this method with no argument it will consider variables set by any child flow, alternatively
|
187
|
+
# pass in the variables for the child flow in question and only that will be considered.
|
188
|
+
def intermediate_variables(*sub_flows)
|
189
|
+
set_flags = []
|
190
|
+
all_sub_flows.each { |f| set_flags += f.flow_variables[:all][:set_flags] }
|
191
|
+
if set_flags.empty?
|
192
|
+
[]
|
193
|
+
else
|
194
|
+
upstream_referenced_flags = []
|
195
|
+
p = parent
|
196
|
+
while p
|
197
|
+
upstream_referenced_flags += p.flow_variables[:this_flow][:referenced_flags]
|
198
|
+
p = p.parent
|
199
|
+
end
|
200
|
+
upstream_referenced_flags.uniq
|
201
|
+
set_flags & upstream_referenced_flags
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def flow_header
|
206
|
+
h = []
|
207
|
+
if add_flow_enable && top_level?
|
208
|
+
h << " if (#{flow_enable_var_name} == 1) {"
|
209
|
+
i = ' '
|
210
|
+
else
|
211
|
+
i = ' '
|
212
|
+
end
|
213
|
+
flow_variables[:this_flow][:set_flags].each do |var|
|
214
|
+
if var.is_a?(Array)
|
215
|
+
h << i + "#{var[0]} = #{var[1].is_a?(String) || var[1].is_a?(Symbol) ? '"' + var[1].to_s + '"' : var[1]};"
|
216
|
+
else
|
217
|
+
h << i + "#{var} = -1;"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
h << '' unless flow_variables[:this_flow][:set_flags].empty?
|
221
|
+
h
|
222
|
+
end
|
223
|
+
|
224
|
+
def flow_footer
|
225
|
+
f = []
|
226
|
+
if add_flow_enable && top_level?
|
227
|
+
f << ' }'
|
228
|
+
end
|
229
|
+
f
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module SmartestBasedTester
|
3
|
+
class V93K_SMT8
|
4
|
+
# Include this module in an interface class to make it a V93K interface and to give
|
5
|
+
# access to the V93K SMT8 program generator API
|
6
|
+
module Generator
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
require_all "#{Origen.root!}/lib/origen_testers/smartest_based_tester/v93k_smt8"
|
10
|
+
require 'origen_testers/smartest_based_tester/base/generator'
|
11
|
+
|
12
|
+
included do
|
13
|
+
include Base::Generator
|
14
|
+
PLATFORM = V93K_SMT8
|
15
|
+
end
|
16
|
+
|
17
|
+
# Sub flows are generated in a forked process for SMT8, however any updates made to interface
|
18
|
+
# instance variables by the sub-flow will be applied to the interface of the master process.
|
19
|
+
# This is what the user would expect to happen and keeps them largely unaware of the fact that
|
20
|
+
# the sub-flow is actually being generated by a forked process.
|
21
|
+
# However, to do this it is necessary to marshal the value of the instance variables and
|
22
|
+
# some (rich) Ruby objects cannot be marshaled. This parameter allows applications to selectively
|
23
|
+
# mark such variables as not to be returned from the forked process, skipping the marshal
|
24
|
+
# operation but also meaning that any changes made to the variable by the sub-flow will not
|
25
|
+
# be visible to the top-level flow.
|
26
|
+
#
|
27
|
+
# If the application actually needs updates to that variable made during a sub-flow to
|
28
|
+
# be available to the top-level flow, then they will need to work around it in another
|
29
|
+
# way on a case by case basis.
|
30
|
+
#
|
31
|
+
# # In the application's interface
|
32
|
+
# sub_flow_no_return_vars << :@my_problem_var
|
33
|
+
def sub_flow_no_return_vars
|
34
|
+
@sub_flow_no_return_vars ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
# See sub_flow_no_return_vars
|
38
|
+
def sub_flow_no_return_vars=(val)
|
39
|
+
@sub_flow_no_return_vars = val
|
40
|
+
end
|
41
|
+
|
42
|
+
def limits_workbook
|
43
|
+
@@limits_workbook ||= LimitsWorkbook.new(manually_register: true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|