origen_testers 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/application.rb +9 -7
- data/config/global_commands.rb +12 -0
- data/config/version.rb +1 -1
- data/lib/commands/convert.rb +105 -0
- data/lib/origen_testers.rb +2 -0
- data/lib/origen_testers/api.rb +34 -26
- data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +39 -0
- data/lib/origen_testers/labview_based_tester/pxie6570.rb +1 -0
- data/lib/origen_testers/origen_ext/generator/pattern.rb +137 -0
- data/lib/origen_testers/stil_based_tester.rb +10 -0
- data/lib/origen_testers/stil_based_tester/base.rb +377 -0
- data/lib/origen_testers/stil_based_tester/d10.rb +18 -0
- data/lib/origen_testers/stil_based_tester/stil.rb +8 -0
- data/lib/origen_testers/test/dut.rb +2 -0
- data/lib/origen_testers/timing.rb +4 -0
- data/lib/origen_testers/vector_generator.rb +10 -0
- data/pattern/freq_counter.rb +1 -1
- data/pattern/mem_test.rb +1 -1
- data/program/basic_interface.rb +9 -0
- data/program/prb1.rb +3 -1
- data/program/prb2.rb +3 -1
- data/templates/origen_guides/pattern/stil.md.erb +35 -0
- data/templates/origen_guides/program/j750.md.erb +53 -0
- data/templates/origen_guides/program/ultraflex.md.erb +34 -1
- metadata +26 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe9e0d79136d4c5a7a16b3e73e098ac9069c0aa0d4efb70e4e9c93bb1b1d01d7
|
4
|
+
data.tar.gz: 115289be29ed7e600ee5e331a61649e05f649131956214bebd81a6afb963a0d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13b81ab2f3f0c642ba283399fbc39df7f1fcf7f982995f53ae75ef4acef6b060ca196bec8ea9571b65a548831a712eba6653b6eadcd52b5672fd84cad91ff051
|
7
|
+
data.tar.gz: 1ee85240a3d5c559dff37c61f12110f02a1a8228fc36f828911fe7d13c79cfc12fff72d49ead48f7b0ca33ee24fc3263f2f4f357abfd014aad3bb418bb12b0be
|
data/config/application.rb
CHANGED
@@ -4,6 +4,7 @@ class OrigenTestersApplication < Origen::Application
|
|
4
4
|
|
5
5
|
config.shared = {
|
6
6
|
command_launcher: "config/shared_commands.rb",
|
7
|
+
global_launcher: "config/global_commands.rb",
|
7
8
|
origen_guides: "templates/origen_guides",
|
8
9
|
origen_guides_index: -> (index) do
|
9
10
|
index.section :pattern, heading: "Pattern Generator", after: :controllers do |section|
|
@@ -18,6 +19,7 @@ class OrigenTestersApplication < Origen::Application
|
|
18
19
|
section.page :j750, heading: "J750 API"
|
19
20
|
section.page :v93k, heading: "V93K API"
|
20
21
|
section.page :ultraflex, heading: "UltraFlex API"
|
22
|
+
section.page :stil, heading: "STIL & Other Formats"
|
21
23
|
section.page :custom, heading: "Custom Testers"
|
22
24
|
section.page :running, heading: "Running The PatGen"
|
23
25
|
end
|
@@ -84,13 +86,13 @@ class OrigenTestersApplication < Origen::Application
|
|
84
86
|
dir
|
85
87
|
end
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
dir = "#{Origen.root}/spec/patterns/atp"
|
90
|
-
# Check if running on windows, if so, substitute :: with _
|
91
|
-
dir.gsub!("::","_") if Origen.os.windows?
|
92
|
-
dir
|
93
|
-
end
|
89
|
+
# config.pattern_output_directory do
|
90
|
+
# # Setting this to the spec area for testing of compiler
|
91
|
+
# dir = "#{Origen.root}/spec/patterns/atp"
|
92
|
+
# # Check if running on windows, if so, substitute :: with _
|
93
|
+
# dir.gsub!("::","_") if Origen.os.windows?
|
94
|
+
# dir
|
95
|
+
# end
|
94
96
|
|
95
97
|
# Run the tests before deploying to generate test coverage numbers
|
96
98
|
def before_deploy_site
|
data/config/version.rb
CHANGED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'pathname'
|
3
|
+
require 'origen_testers'
|
4
|
+
require 'origen_stil'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
ENVIRONMENTS = {
|
9
|
+
j750: OrigenTesters::J750,
|
10
|
+
uflex: OrigenTesters::UltraFLEX,
|
11
|
+
v93k_smt7: OrigenTesters::V93K
|
12
|
+
}.with_indifferent_access
|
13
|
+
|
14
|
+
opt_parser = OptionParser.new do |opts|
|
15
|
+
if Origen.running_globally?
|
16
|
+
opts.banner = <<-EOT
|
17
|
+
Convert the given pattern file to another environment (tester) format.
|
18
|
+
|
19
|
+
Usage: origen convert FILE -e v93k_smt7 [options]
|
20
|
+
EOT
|
21
|
+
else
|
22
|
+
opts.banner = <<-EOT
|
23
|
+
Convert the given pattern file to another environment (tester) format.
|
24
|
+
|
25
|
+
Usage: origen convert FILE [options]
|
26
|
+
EOT
|
27
|
+
end
|
28
|
+
opts.on('-o', '--output DIR', String, 'Override the default output directory') { |t| options[:output] = t }
|
29
|
+
if Origen.running_globally?
|
30
|
+
opts.on('-e', '--environment NAME', ENVIRONMENTS, 'Specify the target environment:', ' ' + ENVIRONMENTS.keys.join(', ')) { |e| options[:environment] = e }
|
31
|
+
else
|
32
|
+
opts.on('-e', '--environment NAME', String, 'Override the default environment, NAME can be a full path or a fragment of an environment file name') { |e| options[:environment] = e }
|
33
|
+
opts.on('-t', '--target NAME', String, 'Override the default target, NAME can be a full path or a fragment of a target file name') { |t| options[:target] = t }
|
34
|
+
end
|
35
|
+
opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
|
36
|
+
opts.on('-m', '--mode MODE', Origen::Mode::MODES, 'Force the Origen operating mode:', ' ' + Origen::Mode::MODES.join(', ')) { |_m| }
|
37
|
+
opts.separator ''
|
38
|
+
opts.on('-h', '--help', 'Show this message') { puts opts; exit 0 }
|
39
|
+
end
|
40
|
+
|
41
|
+
opt_parser.parse! ARGV
|
42
|
+
|
43
|
+
if Origen.running_globally?
|
44
|
+
|
45
|
+
module OrigenTesters
|
46
|
+
class AnonymousDUT
|
47
|
+
include Origen::TopLevel
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
unless options[:environment]
|
52
|
+
puts 'You must specify the target environment (tester) via the -e switch with one of the following values:'
|
53
|
+
puts ' ' + ENVIRONMENTS.keys.join(', ')
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
|
57
|
+
Origen.target.temporary = lambda do
|
58
|
+
OrigenTesters::AnonymousDUT.new
|
59
|
+
options[:environment].new
|
60
|
+
# Stops the generated pattern being compared to a reference
|
61
|
+
tester.define_singleton_method(:disable_pattern_diffs) { true }
|
62
|
+
end
|
63
|
+
else
|
64
|
+
|
65
|
+
Origen.environment.temporary = options[:environment] if options[:environment]
|
66
|
+
Origen.target.temporary = options[:target] if options[:target]
|
67
|
+
end
|
68
|
+
|
69
|
+
def converter(file, options = {})
|
70
|
+
snippet = IO.read(file, 2000) # Read first 2000 characters
|
71
|
+
case snippet
|
72
|
+
when /STIL \d+\.\d+/
|
73
|
+
lambda do
|
74
|
+
STIL.add_pins(file)
|
75
|
+
# Use raw pin names in the output pattern and not the ALL pin group or similar, maybe
|
76
|
+
# make this an option in future though
|
77
|
+
dut.pin_pattern_order(*dut.pins.map { |id, pin| id })
|
78
|
+
STIL.execute(file, set_timesets: true)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
Origen.log.error "Unknown input format for file: #{file}"
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
ARGV.each do |input|
|
87
|
+
if c = converter(input)
|
88
|
+
name = Pathname.new(input).basename('.*').to_s
|
89
|
+
|
90
|
+
job = Origen::Generator::Job.new('anonymous', {})
|
91
|
+
Origen.app.current_jobs << job
|
92
|
+
if options[:output]
|
93
|
+
FileUtils.mkdir_p(options[:output]) unless File.exist?(options[:output])
|
94
|
+
job.instance_variable_set(:@output_pattern_directory, options[:output])
|
95
|
+
end
|
96
|
+
|
97
|
+
Origen.load_target
|
98
|
+
|
99
|
+
Origen::Generator::Pattern.convert(input) do
|
100
|
+
Pattern.create name: name do
|
101
|
+
c.call
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/origen_testers.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_support/concern'
|
|
5
5
|
require 'require_all'
|
6
6
|
require 'atp'
|
7
7
|
require 'pathname'
|
8
|
+
require 'origen_testers/origen_ext/generator/pattern'
|
8
9
|
require 'origen_testers/origen_ext/generator/flow'
|
9
10
|
require 'origen_testers/origen_ext/generator/resources'
|
10
11
|
require 'origen_testers/origen_ext/application/runner'
|
@@ -41,6 +42,7 @@ end
|
|
41
42
|
|
42
43
|
require 'origen_testers/igxl_based_tester'
|
43
44
|
require 'origen_testers/smartest_based_tester'
|
45
|
+
require 'origen_testers/stil_based_tester'
|
44
46
|
require 'origen_testers/labview_based_tester'
|
45
47
|
require 'origen_testers/pattern_compilers'
|
46
48
|
require 'origen_testers/pattern_compilers/runner'
|
data/lib/origen_testers/api.rb
CHANGED
@@ -76,11 +76,6 @@ module OrigenTesters
|
|
76
76
|
!is_vector_based?
|
77
77
|
end
|
78
78
|
|
79
|
-
def stil?
|
80
|
-
defined?(OrigenTesters::StilBasedTester::Base) &&
|
81
|
-
is_a?(OrigenTesters::StilBasedTester::Base)
|
82
|
-
end
|
83
|
-
|
84
79
|
def j750?
|
85
80
|
is_a?(OrigenTesters::IGXLBasedTester::J750)
|
86
81
|
end
|
@@ -98,6 +93,14 @@ module OrigenTesters
|
|
98
93
|
end
|
99
94
|
alias_method :uflex?, :ultraflex?
|
100
95
|
|
96
|
+
def stil?
|
97
|
+
is_a?(OrigenTesters::StilBasedTester::Base)
|
98
|
+
end
|
99
|
+
|
100
|
+
def d10?
|
101
|
+
is_a?(OrigenTesters::StilBasedTester::D10)
|
102
|
+
end
|
103
|
+
|
101
104
|
def link?
|
102
105
|
!!(self.class.to_s =~ /^OrigenLink::/)
|
103
106
|
end
|
@@ -140,6 +143,7 @@ module OrigenTesters
|
|
140
143
|
# cc "step comment"
|
141
144
|
# end
|
142
145
|
def c1(msg, options = {})
|
146
|
+
PatSeq.add_thread(msg) unless options[:no_thread_id]
|
143
147
|
prefix = comment_char + ' '
|
144
148
|
prefix += step_comment_prefix + ' ' if @step_comment_on
|
145
149
|
if Origen.tester.generating == :program
|
@@ -171,7 +175,7 @@ module OrigenTesters
|
|
171
175
|
def ss(msg = nil)
|
172
176
|
div = step_comment_prefix.length
|
173
177
|
div = 1 if div == 0
|
174
|
-
c1(step_comment_prefix * (70 / div))
|
178
|
+
c1(step_comment_prefix * (70 / div), no_thread_id: true)
|
175
179
|
@step_comment_on = true
|
176
180
|
if block_given?
|
177
181
|
yield
|
@@ -182,9 +186,9 @@ module OrigenTesters
|
|
182
186
|
if $_testers_enable_vector_comments
|
183
187
|
timestamp = " #{execution_time_in_ns}ns #{step_comment_prefix}"
|
184
188
|
str = step_comment_prefix * (70 / div)
|
185
|
-
c1
|
189
|
+
c1(str.sub(/#{step_comment_prefix}{#{timestamp.length - 1}}$/, timestamp), no_thread_id: true)
|
186
190
|
else
|
187
|
-
c1(step_comment_prefix * (70 / div))
|
191
|
+
c1(step_comment_prefix * (70 / div), no_thread_id: true)
|
188
192
|
end
|
189
193
|
end
|
190
194
|
|
@@ -223,29 +227,33 @@ module OrigenTesters
|
|
223
227
|
repeat: nil
|
224
228
|
}.merge(options)
|
225
229
|
|
226
|
-
if
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
230
|
+
if PatSeq.thread
|
231
|
+
PatSeq.thread.cycle(options)
|
232
|
+
else
|
233
|
+
if any_clocks_running?
|
234
|
+
update_running_clocks
|
235
|
+
if options[:repeat]
|
236
|
+
slice_repeats(options).each do |slice|
|
237
|
+
options[:repeat] = slice[0]
|
238
|
+
delay(options.delete(:repeat), options) do |options|
|
239
|
+
push_vector(options)
|
240
|
+
end
|
241
|
+
slice[1].each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
242
|
+
options[:pin_vals] = current_pin_vals
|
233
243
|
end
|
234
|
-
|
235
|
-
|
244
|
+
pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
245
|
+
else
|
246
|
+
push_vector(options)
|
247
|
+
pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
236
248
|
end
|
237
|
-
pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
238
249
|
else
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
delay(options.delete(:repeat), options) do |options|
|
250
|
+
if options[:repeat]
|
251
|
+
delay(options.delete(:repeat), options) do |options|
|
252
|
+
push_vector(options)
|
253
|
+
end
|
254
|
+
else
|
245
255
|
push_vector(options)
|
246
256
|
end
|
247
|
-
else
|
248
|
-
push_vector(options)
|
249
257
|
end
|
250
258
|
end
|
251
259
|
end
|
@@ -31,6 +31,7 @@ module OrigenTesters
|
|
31
31
|
lo = ins.lo
|
32
32
|
hi = ins.hi
|
33
33
|
end
|
34
|
+
|
34
35
|
size = 1
|
35
36
|
if lo.is_a?(Array)
|
36
37
|
size = lo.size if lo.size > size
|
@@ -80,6 +81,44 @@ module OrigenTesters
|
|
80
81
|
completed_lines << line
|
81
82
|
end
|
82
83
|
end
|
84
|
+
# finish off any limit lines from sub tests
|
85
|
+
unless @limit_lines.nil?
|
86
|
+
tl = completed_lines.last
|
87
|
+
tnum = tl.tnum
|
88
|
+
@limit_lines.each do |line|
|
89
|
+
line.parameter = tl.parameter
|
90
|
+
line.sbin = tl.sbin
|
91
|
+
line.bin = tl.bin
|
92
|
+
line.tnum = tnum += 1 if tnum.is_a?(Numeric) && !line.tnum
|
93
|
+
completed_lines << line
|
94
|
+
end
|
95
|
+
@limit_lines = nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def on_sub_test(node)
|
100
|
+
# for now assuming sub tests will be limits
|
101
|
+
tname = node.find(:object).value
|
102
|
+
# for some reason new_line :use_limit does not provide hbin, sbin etc accessors, duplicating behavior in on_test above
|
103
|
+
line = open_lines.last.dup
|
104
|
+
line.type = :use_limit
|
105
|
+
line.opcode = 'Use-Limit'
|
106
|
+
line.tname = tname
|
107
|
+
line.tnum = nil
|
108
|
+
open_lines << line
|
109
|
+
process_all(node.children)
|
110
|
+
@limit_lines = [] if @limit_lines.nil?
|
111
|
+
@limit_lines << open_lines.pop
|
112
|
+
end
|
113
|
+
|
114
|
+
def on_limit(node)
|
115
|
+
value, rule, unit, selector = *node
|
116
|
+
case rule
|
117
|
+
when 'gte'
|
118
|
+
current_line.lolim = value
|
119
|
+
when 'lte'
|
120
|
+
current_line.hilim = value
|
121
|
+
end
|
83
122
|
end
|
84
123
|
|
85
124
|
# Returns the scale that should be best used to represent the given number, returns
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# This responsibility should be with OrigenTesters, starting to override the methods here
|
2
|
+
# within OrigenTesters over time and it will be removed from Origen in future once fully
|
3
|
+
# transferred
|
4
|
+
require 'origen/generator/pattern'
|
5
|
+
module Origen
|
6
|
+
class Generator
|
7
|
+
class Pattern
|
8
|
+
# @api private
|
9
|
+
def self.convert(file)
|
10
|
+
@converting = file
|
11
|
+
yield
|
12
|
+
@converting = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
def self.converting
|
17
|
+
@converting
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def converting
|
23
|
+
self.class.converting
|
24
|
+
end
|
25
|
+
|
26
|
+
def header
|
27
|
+
Origen.tester.pre_header if Origen.tester.doc?
|
28
|
+
inject_separator
|
29
|
+
if $desc
|
30
|
+
c2 'DESCRIPTION:'
|
31
|
+
$desc.split(/\n/).each { |line| cc line }
|
32
|
+
inject_separator
|
33
|
+
end
|
34
|
+
c2 'GENERATED:'
|
35
|
+
c2 " Time: #{Origen.launch_time}"
|
36
|
+
c2 " By: #{Origen.current_user.name}"
|
37
|
+
c2 " Mode: #{Origen.mode}"
|
38
|
+
if converting
|
39
|
+
c2 " Source: #{converting}"
|
40
|
+
|
41
|
+
else
|
42
|
+
l = " Command: origen g #{job.requested_pattern} -t #{Origen.target.file.basename}"
|
43
|
+
if Origen.environment && Origen.environment.file
|
44
|
+
l += " -e #{Origen.environment.file.basename}"
|
45
|
+
end
|
46
|
+
c2(l)
|
47
|
+
end
|
48
|
+
inject_separator
|
49
|
+
c2 'ENVIRONMENT:'
|
50
|
+
unless converting
|
51
|
+
c2 ' Application'
|
52
|
+
if Origen.app.rc
|
53
|
+
if Origen.app.rc.git?
|
54
|
+
c2 " Source: #{Origen.config.rc_url}"
|
55
|
+
else
|
56
|
+
c2 " Vault: #{Origen.config.vault}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
c2 " Version: #{Origen.app.version}"
|
60
|
+
unless Origen.app.config.release_externally
|
61
|
+
c2 " Workspace: #{Origen.root}"
|
62
|
+
end
|
63
|
+
if Origen.app.rc && Origen.app.rc.git?
|
64
|
+
begin
|
65
|
+
@branch ||= Origen.app.rc.current_branch
|
66
|
+
@commit ||= Origen.app.rc.current_commit
|
67
|
+
status = "#{@branch}(#{@commit})"
|
68
|
+
@pattern_local_mods = !Origen.app.rc.local_modifications.empty? unless @pattern_local_mods_fetched
|
69
|
+
@pattern_local_mods_fetched = true
|
70
|
+
status += ' (+local edits)' if @pattern_local_mods
|
71
|
+
c2 " Branch: #{status}"
|
72
|
+
rescue
|
73
|
+
# No problem, we did our best
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
c2 ' Origen'
|
78
|
+
c2 ' Source: https://github.com/Origen-SDK/origen'
|
79
|
+
c2 " Version: #{Origen.version}"
|
80
|
+
unless Origen.app.plugins.empty?
|
81
|
+
c2 ' Plugins'
|
82
|
+
Origen.app.plugins.sort_by { |p| p.name.to_s }.each do |plugin|
|
83
|
+
c2 " #{plugin.name}:".ljust(30) + plugin.version
|
84
|
+
end
|
85
|
+
end
|
86
|
+
inject_separator
|
87
|
+
|
88
|
+
unless Origen.app.plugins.empty?
|
89
|
+
# Plugins can use config.shared_pattern_header to inject plugin-specific comments into the patterns header
|
90
|
+
header_printed = false
|
91
|
+
Origen.app.plugins.sort_by { |p| p.name.to_s }.each do |plugin|
|
92
|
+
unless plugin.config.shared_pattern_header.nil?
|
93
|
+
unless header_printed
|
94
|
+
c2 'Header Comments From Shared Plugins:'
|
95
|
+
header_printed = true
|
96
|
+
end
|
97
|
+
inject_pattern_header(
|
98
|
+
config_loc: plugin,
|
99
|
+
scope: :shared_pattern_header,
|
100
|
+
message: "Header Comments From Shared Plugin: #{plugin.name}:",
|
101
|
+
message_spacing: 2,
|
102
|
+
line_spacing: 4,
|
103
|
+
no_separator: true
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
inject_separator if header_printed
|
108
|
+
end
|
109
|
+
|
110
|
+
if Origen.app.plugins.current && !Origen.app.plugins.current.config.send(:current_plugin_pattern_header).nil?
|
111
|
+
# The top level plugin (if one is set) can further inject plugin-specific comment into the header.
|
112
|
+
# These will only appear if the plugin is the top-level plugin though.
|
113
|
+
inject_pattern_header(
|
114
|
+
config_loc: Origen.app.plugins.current,
|
115
|
+
scope: :current_plugin_pattern_header,
|
116
|
+
message: "Header Comments From The Current Plugin: #{Origen.app.plugins.current.name}:"
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
unless Origen.app.config.send(:application_pattern_header).nil?
|
121
|
+
inject_pattern_header(
|
122
|
+
config_loc: Origen.app,
|
123
|
+
scope: :application_pattern_header,
|
124
|
+
message: "Header Comments From Application: #{Origen.app.name}:"
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
if Origen.config.pattern_header
|
129
|
+
Origen.log.deprecated 'Origen.config.pattern_header is deprecated.'
|
130
|
+
Origen.log.deprecated 'Please use config.shared_pattern_header, config.application_pattern_header, or config.current_plugin_pattern_header instead.'
|
131
|
+
inject_separator
|
132
|
+
end
|
133
|
+
Origen.tester.close_text_block if Origen.tester.doc?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module StilBasedTester
|
3
|
+
autoload :Base, 'origen_testers/stil_based_tester/base.rb'
|
4
|
+
autoload :D10, 'origen_testers/stil_based_tester/d10.rb'
|
5
|
+
autoload :STIL, 'origen_testers/stil_based_tester/stil.rb'
|
6
|
+
end
|
7
|
+
# Convenience/Legacy names without the IGXLBasedTester namespace
|
8
|
+
autoload :D10, 'origen_testers/stil_based_tester/d10.rb'
|
9
|
+
autoload :STIL, 'origen_testers/stil_based_tester/stil.rb'
|
10
|
+
end
|
@@ -0,0 +1,377 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module StilBasedTester
|
3
|
+
class Base
|
4
|
+
include VectorBasedTester
|
5
|
+
|
6
|
+
# When set to true generated patterns will only contain Pattern blocks, i.e. only vectors
|
7
|
+
attr_accessor :pattern_only
|
8
|
+
|
9
|
+
# Returns a new J750 instance, normally there would only ever be one of these
|
10
|
+
# assigned to the global variable such as $tester by your target:
|
11
|
+
# $tester = J750.new
|
12
|
+
def initialize(options = {})
|
13
|
+
self.pattern_only = options.delete(:pattern_only)
|
14
|
+
@max_repeat_loop = 65_535
|
15
|
+
@min_repeat_loop = 2
|
16
|
+
@pat_extension = 'stil'
|
17
|
+
@compress = true
|
18
|
+
|
19
|
+
# @support_repeat_previous = true
|
20
|
+
@match_entries = 10
|
21
|
+
@name = 'stil'
|
22
|
+
@comment_char = '//'
|
23
|
+
@level_period = true
|
24
|
+
@inline_comments = true
|
25
|
+
@header_done = false
|
26
|
+
@footer_done = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def stil_based?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# An internal method called by Origen to create the pattern header
|
34
|
+
def pattern_header(options = {})
|
35
|
+
options = {
|
36
|
+
}.merge(options)
|
37
|
+
|
38
|
+
@pattern_name = options[:pattern]
|
39
|
+
|
40
|
+
unless pattern_only
|
41
|
+
microcode 'STIL 1.0;'
|
42
|
+
|
43
|
+
microcode ''
|
44
|
+
microcode 'Signals {'
|
45
|
+
ordered_pins.each do |pin|
|
46
|
+
line = ''
|
47
|
+
line << "#{pin.name} "
|
48
|
+
if pin.direction == :input
|
49
|
+
line << 'In;'
|
50
|
+
elsif pin.direction == :output
|
51
|
+
line << 'Out;'
|
52
|
+
else
|
53
|
+
line << 'InOut;'
|
54
|
+
end
|
55
|
+
microcode " #{line}"
|
56
|
+
end
|
57
|
+
microcode '}'
|
58
|
+
|
59
|
+
microcode ''
|
60
|
+
microcode 'SignalGroups {'
|
61
|
+
line = "\"#{ordered_pins_name || 'ALL'}\" = '"
|
62
|
+
ordered_pins.each_with_index do |pin, i|
|
63
|
+
unless i == 0
|
64
|
+
line << '+'
|
65
|
+
end
|
66
|
+
line << pin.name.to_s
|
67
|
+
end
|
68
|
+
microcode " #{line}';"
|
69
|
+
microcode '}'
|
70
|
+
|
71
|
+
microcode ''
|
72
|
+
microcode "Timing t_#{@pattern_name} {"
|
73
|
+
(@wavesets || []).each_with_index do |w, i|
|
74
|
+
microcode '' if i != 0
|
75
|
+
microcode " WaveformTable Waveset#{i + 1} {"
|
76
|
+
microcode " Period '#{w[:period]}ns';"
|
77
|
+
microcode ' Waveforms {'
|
78
|
+
w[:lines].each do |line|
|
79
|
+
microcode " #{line}"
|
80
|
+
end
|
81
|
+
microcode ' }'
|
82
|
+
microcode ' }'
|
83
|
+
end
|
84
|
+
microcode '}'
|
85
|
+
|
86
|
+
microcode ''
|
87
|
+
microcode "PatternBurst b_#{@pattern_name} {"
|
88
|
+
microcode " PatList { #{@pattern_name}; }"
|
89
|
+
microcode '}'
|
90
|
+
|
91
|
+
microcode ''
|
92
|
+
microcode "PatternExec e_#{@pattern_name} {"
|
93
|
+
microcode " Timing t_#{@pattern_name};"
|
94
|
+
microcode " PatternBurst b_#{@pattern_name};"
|
95
|
+
microcode '}'
|
96
|
+
microcode ''
|
97
|
+
end
|
98
|
+
|
99
|
+
microcode "Pattern \"#{@pattern_name}\" {"
|
100
|
+
microcode "#{@pattern_name}:"
|
101
|
+
@header_done = true
|
102
|
+
|
103
|
+
if tester.ordered_pins_name.nil? && pattern_only
|
104
|
+
Origen.log.warn "WARN: SigName must be defined for STIL format. Use pin_pattern_order(*pins, name: <sigName>). Defaulting to use 'ALL'"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def set_timeset(timeset, period_in_ns = nil)
|
109
|
+
super
|
110
|
+
if pattern_only
|
111
|
+
# Why does D10 not include this?
|
112
|
+
# microcode "W #{timeset};"
|
113
|
+
else
|
114
|
+
@wavesets ||= []
|
115
|
+
wave_number = nil
|
116
|
+
@wavesets.each_with_index do |w, i|
|
117
|
+
if w[:name] == @timeset.name && w[:period] = @timeset.period_in_ns
|
118
|
+
wave_number = i
|
119
|
+
end
|
120
|
+
end
|
121
|
+
unless wave_number
|
122
|
+
lines = []
|
123
|
+
ordered_pins.each do |pin|
|
124
|
+
if pin.direction == :input || pin.direction == :io
|
125
|
+
line = "#{pin.name} { 01 { "
|
126
|
+
wave = pin.drive_wave
|
127
|
+
(wave ? wave.evaluated_events : []).each do |t, v|
|
128
|
+
line << "'#{t}ns' "
|
129
|
+
if v == 0
|
130
|
+
line << 'D'
|
131
|
+
elsif v == 0
|
132
|
+
line << 'U'
|
133
|
+
else
|
134
|
+
line << 'D/U'
|
135
|
+
end
|
136
|
+
line << '; '
|
137
|
+
end
|
138
|
+
line << '}}'
|
139
|
+
lines << line
|
140
|
+
end
|
141
|
+
if pin.direction == :output || pin.direction == :io
|
142
|
+
line = "#{pin.name} { LHX { "
|
143
|
+
wave = pin.compare_wave
|
144
|
+
(wave ? wave.evaluated_events : []).each_with_index do |tv, i|
|
145
|
+
t, v = *tv
|
146
|
+
if i == 0 && t != 0
|
147
|
+
line << "'0ns' X; "
|
148
|
+
end
|
149
|
+
line << "'#{t}ns' "
|
150
|
+
if v == 0
|
151
|
+
line << 'L'
|
152
|
+
elsif v == 0
|
153
|
+
line << 'H'
|
154
|
+
else
|
155
|
+
line << 'L/H/X'
|
156
|
+
end
|
157
|
+
line << '; '
|
158
|
+
end
|
159
|
+
line << '}}'
|
160
|
+
lines << line
|
161
|
+
end
|
162
|
+
end
|
163
|
+
@wavesets << { name: @timeset.name, period: @timeset.period_in_ns, lines: lines }
|
164
|
+
wave_number = @wavesets.size
|
165
|
+
end
|
166
|
+
microcode "W Waveset#{wave_number};"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Capture the pin data from a vector to the tester.
|
171
|
+
#
|
172
|
+
# This method uses the Digital Capture feature (Selective mode) of the V93000 to capture
|
173
|
+
# the data from the given pins on the previous vector.
|
174
|
+
# Note that is does not actually generate a new vector.
|
175
|
+
#
|
176
|
+
# Note also that any drive cycles on the target pins can also be captured, to avoid this
|
177
|
+
# the wavetable should be set up like this to infer a 'D' (Don't Capture) on vectors where
|
178
|
+
# the target pin is being used to drive data:
|
179
|
+
#
|
180
|
+
# PINS nvm_fail
|
181
|
+
# 0 d1:0 r1:D 0
|
182
|
+
# 1 d1:1 r1:D 1
|
183
|
+
# 2 r1:C Capt
|
184
|
+
# 3 r1:D NoCapt
|
185
|
+
#
|
186
|
+
# Sometimes when generating vectors within a loop you may want to apply a capture
|
187
|
+
# retrospectively to a previous vector, passing in an offset option will allow you
|
188
|
+
# to do this.
|
189
|
+
#
|
190
|
+
# ==== Examples
|
191
|
+
# $tester.cycle # This is the vector you want to capture
|
192
|
+
# $tester.store :pin => pin(:fail) # This applys the required opcode to the given pins
|
193
|
+
#
|
194
|
+
# $tester.cycle # This one gets captured
|
195
|
+
# $tester.cycle
|
196
|
+
# $tester.cycle
|
197
|
+
# $tester.store(:pin => pin(:fail), :offset => -2) # Just realized I need to capture that earlier vector
|
198
|
+
#
|
199
|
+
# # Capturing multiple pins:
|
200
|
+
# $tester.cycle
|
201
|
+
# $tester.store :pins => [pin(:fail), pin(:done)]
|
202
|
+
#
|
203
|
+
# Since the STIL store operates on a pin level (rather than vector level as on the J750)
|
204
|
+
# equivalent functionality can also be achieved by setting the store attribute of the pin
|
205
|
+
# itself prior to calling $tester.cycle.
|
206
|
+
# However it is recommended to use the tester API to do the store if cross-compatibility with
|
207
|
+
# other platforms, such as the J750, is required.
|
208
|
+
def store(*pins)
|
209
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
210
|
+
options = { offset: 0
|
211
|
+
}.merge(options)
|
212
|
+
pins = pins.flatten.compact
|
213
|
+
if pins.empty?
|
214
|
+
fail 'For the STIL generation you must supply the pins to store/capture'
|
215
|
+
end
|
216
|
+
pins.each do |pin|
|
217
|
+
pin.restore_state do
|
218
|
+
pin.capture
|
219
|
+
update_vector_pin_val pin, offset: options[:offset]
|
220
|
+
last_vector(options[:offset]).dont_compress = true
|
221
|
+
last_vector(options[:offset]).contains_capture = true
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
alias_method :capture, :store
|
226
|
+
|
227
|
+
# Same as the store method, except that the capture will be applied to the next
|
228
|
+
# vector to be generated.
|
229
|
+
#
|
230
|
+
# @example
|
231
|
+
# $tester.store_next_cycle
|
232
|
+
# $tester.cycle # This is the vector that will be captured
|
233
|
+
def store_next_cycle(*pins)
|
234
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
235
|
+
options = {
|
236
|
+
}.merge(options)
|
237
|
+
pins = pins.flatten.compact
|
238
|
+
if pins.empty?
|
239
|
+
fail 'For STIL generation you must supply the pins to store/capture'
|
240
|
+
end
|
241
|
+
pins.each { |pin| pin.save; pin.capture }
|
242
|
+
# Register this clean up function to be run after the next vector
|
243
|
+
# is generated, cool or what!
|
244
|
+
preset_next_vector do |vector|
|
245
|
+
vector.contains_capture = true
|
246
|
+
pins.each(&:restore)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
alias_method :store!, :store_next_cycle
|
250
|
+
|
251
|
+
def match(pin, state, timeout_in_cycles, options = {})
|
252
|
+
Origen.log.warning "Call to match loop on pin #{pin.id} is not supported by the STIL generator and has been ignored"
|
253
|
+
end
|
254
|
+
|
255
|
+
# Add a loop to the pattern.
|
256
|
+
#
|
257
|
+
# Pass in the number of times to execute it, all vectors
|
258
|
+
# generated by the given block will be captured in the loop.
|
259
|
+
#
|
260
|
+
# ==== Examples
|
261
|
+
# $tester.loop_vectors 3 do # Do this 3 times...
|
262
|
+
# $tester.cycle
|
263
|
+
# some_other_method_to_generate_vectors
|
264
|
+
# end
|
265
|
+
#
|
266
|
+
# For compatibility with the J750 you can supply a name as the first argument
|
267
|
+
# and that will simply be ignored when generated for the V93K tester...
|
268
|
+
#
|
269
|
+
# $tester.loop_vectors "my_loop", 3 do # Do this 3 times...
|
270
|
+
# $tester.cycle
|
271
|
+
# some_other_method_to_generate_vectors
|
272
|
+
# end
|
273
|
+
def loop_vectors(name = nil, number_of_loops = 1, _global = false)
|
274
|
+
# The name argument is present to maych J750 API, sort out the
|
275
|
+
unless name.is_a?(String) || name.is_a?(Symbol)
|
276
|
+
name, number_of_loops, global = 'loop', name, number_of_loops
|
277
|
+
end
|
278
|
+
if number_of_loops > 1
|
279
|
+
@loop_counters ||= {}
|
280
|
+
if @loop_counters[name]
|
281
|
+
@loop_counters[name] += 1
|
282
|
+
else
|
283
|
+
@loop_counters[name] = 0
|
284
|
+
end
|
285
|
+
loop_name = @loop_counters[name] == 0 ? name : "#{name}_#{@loop_counters[name]}"
|
286
|
+
loop_name = loop_name.symbolize
|
287
|
+
microcode "#{loop_name}: Loop #{number_of_loops} {"
|
288
|
+
yield
|
289
|
+
microcode '}'
|
290
|
+
else
|
291
|
+
yield
|
292
|
+
end
|
293
|
+
end
|
294
|
+
alias_method :loop_vector, :loop_vectors
|
295
|
+
|
296
|
+
# An internal method called by Origen to generate the pattern footer
|
297
|
+
def pattern_footer(options = {})
|
298
|
+
cycle dont_compress: true # one extra single vector before stop microcode
|
299
|
+
microcode 'Stop;' unless options[:subroutine]
|
300
|
+
microcode '}'
|
301
|
+
@footer_done = true
|
302
|
+
end
|
303
|
+
|
304
|
+
# Returns an array of subroutines called while generating the current pattern
|
305
|
+
def called_subroutines
|
306
|
+
@called_subroutines ||= []
|
307
|
+
end
|
308
|
+
|
309
|
+
# Call a subroutine.
|
310
|
+
#
|
311
|
+
# This calls a subroutine immediately following previous vector, it does not
|
312
|
+
# generate a new vector.
|
313
|
+
#
|
314
|
+
# Subroutines should always be called through this method as it ensures a running
|
315
|
+
# log of called subroutines is maintained and which then gets output in the pattern
|
316
|
+
# header to import the right dependencies.
|
317
|
+
#
|
318
|
+
# An offset option is available to make the call on earlier vectors.
|
319
|
+
#
|
320
|
+
# Repeated calls to the same subroutine will automatically be compressed unless
|
321
|
+
# option :suppress_repeated_calls is supplied and set to false. This means that for
|
322
|
+
# the common use case of calling a subroutine to implement an overlay the subroutine
|
323
|
+
# can be called for every bit that has the overlay and the pattern will automatically
|
324
|
+
# generate correctly.
|
325
|
+
#
|
326
|
+
# ==== Examples
|
327
|
+
# $tester.call_subroutine("mysub")
|
328
|
+
# $tester.call_subroutine("my_other_sub", :offset => -1)
|
329
|
+
def call_subroutine(name, options = {})
|
330
|
+
options = {
|
331
|
+
offset: 0,
|
332
|
+
suppress_repeated_calls: true
|
333
|
+
}.merge(options)
|
334
|
+
called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
335
|
+
|
336
|
+
code = "Call #{name};"
|
337
|
+
if !options[:suppress_repeated_calls] ||
|
338
|
+
last_object != code
|
339
|
+
microcode code, offset: (options[:offset] * -1)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def push_comment(msg)
|
344
|
+
if @footer_done
|
345
|
+
stage.store msg unless @inhibit_comments
|
346
|
+
else
|
347
|
+
stage.store "Ann {*#{msg}*}" unless @inhibit_comments
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
# This is an internal method use by Origen which returns a fully formatted vector
|
352
|
+
# You can override this if you wish to change the output formatting at vector level
|
353
|
+
def format_vector(vec)
|
354
|
+
timeset = vec.timeset ? "#{vec.timeset.name}" : ''
|
355
|
+
pin_vals = vec.pin_vals ? "#{vec.pin_vals};".gsub(' ', '') : ''
|
356
|
+
sig_name = tester.ordered_pins_name || 'ALL'
|
357
|
+
if sig_name.nil?
|
358
|
+
Origen.log.warn "WARN: SigName must be defined for STIL format. Use pin_pattern_order(*pins, name: <sigName>). Default to 'ALL'"
|
359
|
+
sig_name = 'ALL'
|
360
|
+
end
|
361
|
+
if vec.repeat > 1
|
362
|
+
microcode = "Loop #{vec.repeat} {\n"
|
363
|
+
else
|
364
|
+
microcode = vec.microcode ? vec.microcode : ''
|
365
|
+
end
|
366
|
+
if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
|
367
|
+
comment = "// V:#{vec.number} C:#{vec.cycle} #{vec.inline_comment}"
|
368
|
+
else
|
369
|
+
comment = vec.inline_comment.empty? ? '' : "Ann {*// #{vec.inline_comment}*}"
|
370
|
+
end
|
371
|
+
|
372
|
+
microcode_post = vec.repeat > 1 ? "\n}" : ''
|
373
|
+
"#{microcode} V { \"#{sig_name}\" = #{pin_vals} }#{comment}#{microcode_post}"
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module StilBasedTester
|
3
|
+
class D10 < Base
|
4
|
+
def initialize(options = {})
|
5
|
+
options = {
|
6
|
+
pattern_only: true
|
7
|
+
}.merge(options)
|
8
|
+
super(options)
|
9
|
+
@name = 'd10'
|
10
|
+
end
|
11
|
+
|
12
|
+
def d10?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
D10 = StilBasedTester::D10
|
18
|
+
end
|
@@ -196,6 +196,10 @@ module OrigenTesters
|
|
196
196
|
end
|
197
197
|
@_last_timeset_change = change
|
198
198
|
end
|
199
|
+
if dut.timesets[timeset.name]
|
200
|
+
dut.timeset = timeset.name
|
201
|
+
dut.current_timeset_period = timeset.period_in_ns
|
202
|
+
end
|
199
203
|
end
|
200
204
|
|
201
205
|
def before_timeset_change(options = {})
|
@@ -389,6 +389,16 @@ module OrigenTesters
|
|
389
389
|
@ordered_pins_cache ||= ordered_pins(options)
|
390
390
|
end
|
391
391
|
|
392
|
+
# Retrieve optional 'name' meta passed in with the pin_pattern_order call
|
393
|
+
def ordered_pins_name
|
394
|
+
pinorder = Origen.app.pin_pattern_order.dup
|
395
|
+
if Origen.app.pin_pattern_order.last.is_a?(Hash)
|
396
|
+
options = pinorder.pop
|
397
|
+
name = options[:name]
|
398
|
+
end
|
399
|
+
name
|
400
|
+
end
|
401
|
+
|
392
402
|
def ordered_pins(options = {})
|
393
403
|
options = {
|
394
404
|
include_inhibited_pins: false,
|
data/pattern/freq_counter.rb
CHANGED
data/pattern/mem_test.rb
CHANGED
data/program/basic_interface.rb
CHANGED
@@ -2,4 +2,13 @@ Flow.create interface: 'OrigenTesters::Test::BasicInterface' do
|
|
2
2
|
|
3
3
|
functional :test1, sbin: 100, number: 20000
|
4
4
|
|
5
|
+
# test multi limit support if uflex, not sure what platforms support this or the syntax
|
6
|
+
if tester.uflex?
|
7
|
+
functional :test2, sbin: 101, number: 20020,
|
8
|
+
sub_tests: [
|
9
|
+
sub_test(:lim1, lo: -2, hi: 2),
|
10
|
+
sub_test(:lim2, lo: -1, hi: 1)
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
5
14
|
end
|
data/program/prb1.rb
CHANGED
@@ -4,7 +4,9 @@
|
|
4
4
|
# similar to Pattern.create.
|
5
5
|
Flow.create interface: 'OrigenTesters::Test::Interface', flow_description: 'Probe1 Main' do
|
6
6
|
|
7
|
-
|
7
|
+
unless Origen.app.environment.name == 'v93k_global'
|
8
|
+
self.resources_filename = 'prb1'
|
9
|
+
end
|
8
10
|
|
9
11
|
import 'components/prb1_main'
|
10
12
|
|
data/program/prb2.rb
CHANGED
@@ -5,7 +5,9 @@ Flow.create interface: 'OrigenTesters::Test::Interface' do
|
|
5
5
|
# Test that this can be overridden from the target at flow-level
|
6
6
|
self.add_flow_enable = :enabled
|
7
7
|
|
8
|
-
|
8
|
+
unless Origen.app.environment.name == 'v93k_global'
|
9
|
+
self.resources_filename = 'prb2'
|
10
|
+
end
|
9
11
|
|
10
12
|
func :erase_all, duration: :dynamic, number: 10000
|
11
13
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
#### STIL
|
4
|
+
|
5
|
+
Patterns can be generated into STIL cyclized vector format by creating an environment like this:
|
6
|
+
|
7
|
+
~~~ruby
|
8
|
+
# environment/stil.rb
|
9
|
+
OrigenTesters::STIL.new
|
10
|
+
~~~
|
11
|
+
|
12
|
+
All of the
|
13
|
+
[Common Pattern API](<%= path "guides/pattern/common" %>) should be supported in addition to
|
14
|
+
[custom waveform codes](<%= path "guides/pattern/v93k" %>) like the V93K.
|
15
|
+
|
16
|
+
If the timeset waveforms used by the pattern are
|
17
|
+
[fully defined within your Origen application](<%= path "guides/pattern/timing/#Defining_Timesets" %>)
|
18
|
+
then that information will also be represented within the generated STIL pattern.
|
19
|
+
|
20
|
+
A pattern containing a `Pattern { }` block only - i.e. only vectors and without the `Signals { }`,
|
21
|
+
`Timing { }` and other frontmatter blocks - can be generated by setting up your environment as follows:
|
22
|
+
|
23
|
+
~~~ruby
|
24
|
+
OrigenTesters::STIL.new pattern_only: true
|
25
|
+
~~~
|
26
|
+
|
27
|
+
An alias for this configuration is the `D10` tester environment setup:
|
28
|
+
|
29
|
+
~~~ruby
|
30
|
+
# environment/d10.rb
|
31
|
+
OrigenTesters::D10.new
|
32
|
+
~~~
|
33
|
+
|
34
|
+
|
35
|
+
% end
|
@@ -136,6 +136,59 @@ information):
|
|
136
136
|
* other
|
137
137
|
* empty
|
138
138
|
|
139
|
+
#### Custom Test Instance Types
|
140
|
+
|
141
|
+
The <code>add_til</code> method is available to describe a custom instance. An example is below.
|
142
|
+
|
143
|
+
~~~ruby
|
144
|
+
# app_interface
|
145
|
+
|
146
|
+
def initialize(options = {})
|
147
|
+
add_til :my_lib,
|
148
|
+
test_a: {
|
149
|
+
# Basic arg
|
150
|
+
input1: :arg0,
|
151
|
+
# Arg with default value
|
152
|
+
input2: [:arg1, 'default'],
|
153
|
+
# Arg with default and list of predefined allowed values
|
154
|
+
input3: [:arg2, 'volt', %w(volt curr)],
|
155
|
+
# Attribute aliases can be defined like this:
|
156
|
+
aliases: {
|
157
|
+
some_alias_name: :input1,
|
158
|
+
another_alias: :input2
|
159
|
+
},
|
160
|
+
# Define any methods you want for the instance like this
|
161
|
+
methods: {
|
162
|
+
# An optional finalize method can be supplied, this method will be called
|
163
|
+
# immediately before the test instance is rendered. The test object itself
|
164
|
+
# will be passed as an argument.
|
165
|
+
finalize: lambda do |ti|
|
166
|
+
ti.proc_name = 'blah_blah'
|
167
|
+
ti.proc_called_as = ''
|
168
|
+
end,
|
169
|
+
set_some_arg: lambda do |ti, val|
|
170
|
+
ti.input1 = val
|
171
|
+
end
|
172
|
+
}
|
173
|
+
},
|
174
|
+
|
175
|
+
test_b: {
|
176
|
+
# ...
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
180
|
+
# Here's how to use the custom library
|
181
|
+
def do_test_a(name, options = {})
|
182
|
+
ti = test_instances.my_lib.test_a name
|
183
|
+
ti.input1 = 50.0
|
184
|
+
ti.input3 = 'curr'
|
185
|
+
|
186
|
+
# ...
|
187
|
+
end
|
188
|
+
~~~
|
189
|
+
|
190
|
+
#### Legacy Custom Test Instance Types (prefered method is above)
|
191
|
+
|
139
192
|
If you need a different type you can still call the add method, the difference in the
|
140
193
|
returned instance for an unrecognized type is:
|
141
194
|
|
@@ -1,5 +1,38 @@
|
|
1
1
|
% render "layouts/guides.html" do
|
2
2
|
|
3
|
-
|
3
|
+
Be sure to read and understand the guide to
|
4
|
+
[Creating an Interface](<%= path "guides/program/interface" %>)
|
5
|
+
and
|
6
|
+
[J750 API](<%= path "guides/program/j750" %>)
|
7
|
+
before reading this section.
|
8
|
+
This guide will describe the API differences between UFlex/IG-XL and J750/IG-XL test program
|
9
|
+
generation.
|
10
|
+
|
11
|
+
### Creating a flow entry with multiple Use-Limit lines
|
12
|
+
|
13
|
+
~~~ruby
|
14
|
+
functional :test2, sbin: 101, number: 20020,
|
15
|
+
sub_tests: [
|
16
|
+
sub_test(:limit_name1, lo: -2, hi: 2),
|
17
|
+
sub_test(:limit_name2, lo: -1, hi: 1)
|
18
|
+
]
|
19
|
+
~~~
|
20
|
+
|
21
|
+
~~~ruby
|
22
|
+
# Another example using a custom instance
|
23
|
+
def sar_cal_test(name, options = {})
|
24
|
+
ti = test_instances.sar_tests.sar_cal name
|
25
|
+
# ...
|
26
|
+
|
27
|
+
# Assign fixed limits
|
28
|
+
options[:sub_tests] = [
|
29
|
+
sub_test(:source_gain, lo: 0.99, hi: 1.01),
|
30
|
+
sub_test(:source_offset, lo: -0.001, hi: 0.001)
|
31
|
+
]
|
32
|
+
|
33
|
+
# add the test to the flow
|
34
|
+
flow.test ti, options
|
35
|
+
end
|
36
|
+
~~~
|
4
37
|
|
5
38
|
% 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.
|
4
|
+
version: 0.21.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: 2019-
|
11
|
+
date: 2019-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.44.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.44.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: require_all
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 1.1.3
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: origen_stil
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.2.1
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.2.1
|
61
75
|
description:
|
62
76
|
email:
|
63
77
|
- stephen.f.mcginty@gmail.com
|
@@ -68,10 +82,12 @@ files:
|
|
68
82
|
- config/application.rb
|
69
83
|
- config/boot.rb
|
70
84
|
- config/commands.rb
|
85
|
+
- config/global_commands.rb
|
71
86
|
- config/shared_commands.rb
|
72
87
|
- config/users.rb
|
73
88
|
- config/version.rb
|
74
89
|
- lib/commands/build.rb
|
90
|
+
- lib/commands/convert.rb
|
75
91
|
- lib/commands/run.rb
|
76
92
|
- lib/origen_testers.rb
|
77
93
|
- lib/origen_testers/api.rb
|
@@ -230,6 +246,7 @@ files:
|
|
230
246
|
- lib/origen_testers/origen_ext/application/runner.rb
|
231
247
|
- lib/origen_testers/origen_ext/generator.rb
|
232
248
|
- lib/origen_testers/origen_ext/generator/flow.rb
|
249
|
+
- lib/origen_testers/origen_ext/generator/pattern.rb
|
233
250
|
- lib/origen_testers/origen_ext/generator/resources.rb
|
234
251
|
- lib/origen_testers/origen_ext/pins/pin.rb
|
235
252
|
- lib/origen_testers/origen_ext/pins/pin_collection.rb
|
@@ -287,6 +304,10 @@ files:
|
|
287
304
|
- lib/origen_testers/smartest_based_tester/v93k/test_suite.rb
|
288
305
|
- lib/origen_testers/smartest_based_tester/v93k/test_suites.rb
|
289
306
|
- lib/origen_testers/smartest_based_tester/v93k/variables_file.rb
|
307
|
+
- lib/origen_testers/stil_based_tester.rb
|
308
|
+
- lib/origen_testers/stil_based_tester/base.rb
|
309
|
+
- lib/origen_testers/stil_based_tester/d10.rb
|
310
|
+
- lib/origen_testers/stil_based_tester/stil.rb
|
290
311
|
- lib/origen_testers/test/basic_interface.rb
|
291
312
|
- lib/origen_testers/test/block.rb
|
292
313
|
- lib/origen_testers/test/custom_test_interface.rb
|
@@ -351,6 +372,7 @@ files:
|
|
351
372
|
- templates/origen_guides/pattern/pins.md.erb
|
352
373
|
- templates/origen_guides/pattern/registers.md.erb
|
353
374
|
- templates/origen_guides/pattern/running.md.erb
|
375
|
+
- templates/origen_guides/pattern/stil.md.erb
|
354
376
|
- templates/origen_guides/pattern/timing.md.erb
|
355
377
|
- templates/origen_guides/pattern/ultraflex.md.erb
|
356
378
|
- templates/origen_guides/pattern/v93k.md.erb
|