origen_testers 0.20.0 → 0.21.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bb719c179345dee09336e7c9ef743de9383d0bc32602c58226a682607c93016
4
- data.tar.gz: 7f98c2c6a7d9639bf70c42d4264ba3294b72b814b3c455e9983d4342c3ade773
3
+ metadata.gz: fe9e0d79136d4c5a7a16b3e73e098ac9069c0aa0d4efb70e4e9c93bb1b1d01d7
4
+ data.tar.gz: 115289be29ed7e600ee5e331a61649e05f649131956214bebd81a6afb963a0d7
5
5
  SHA512:
6
- metadata.gz: 5530008ddd55eb90eb4d6502dc8a61633eb28a88d1eed1baa8e9b51ed52bbd3b274c8fb7bd680318716b6c70d910a40c27c2515134b1ce067e69d6e2fde2fce6
7
- data.tar.gz: d599275895db3b446e5f8c3ebe9da2101aa759e8ba622ca5c9a94c14fb12159409f35a1b423df2f6383c70c19136a638c2383a3ce6ac62a2ddb2f48c4f37ca7f
6
+ metadata.gz: 13b81ab2f3f0c642ba283399fbc39df7f1fcf7f982995f53ae75ef4acef6b060ca196bec8ea9571b65a548831a712eba6653b6eadcd52b5672fd84cad91ff051
7
+ data.tar.gz: 1ee85240a3d5c559dff37c61f12110f02a1a8228fc36f828911fe7d13c79cfc12fff72d49ead48f7b0ca33ee24fc3263f2f4f357abfd014aad3bb418bb12b0be
@@ -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
- # Setting this to the spec area for testing of compiler
88
- config.pattern_output_directory do
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
@@ -0,0 +1,12 @@
1
+ case @command
2
+
3
+ when "convert"
4
+ require "#{Origen.root!}/lib/commands/convert"
5
+ exit 0
6
+
7
+ else
8
+ @global_commands << <<-EOT
9
+ convert Convert a tester pattern from one format to another
10
+ EOT
11
+
12
+ end
@@ -1,6 +1,6 @@
1
1
  module OrigenTesters
2
2
  MAJOR = 0
3
- MINOR = 20
3
+ MINOR = 21
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -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
@@ -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'
@@ -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 str.sub(/#{step_comment_prefix}{#{timestamp.length - 1}}$/, timestamp)
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 any_clocks_running?
227
- update_running_clocks
228
- if options[:repeat]
229
- slice_repeats(options).each do |slice|
230
- options[:repeat] = slice[0]
231
- delay(options.delete(:repeat), options) do |options|
232
- push_vector(options)
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
- slice[1].each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
235
- options[:pin_vals] = current_pin_vals
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
- push_vector(options)
240
- pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
241
- end
242
- else
243
- if options[:repeat]
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
@@ -6,6 +6,7 @@ module OrigenTesters
6
6
  attr_accessor :default_source_wave_name, :default_capture_wave_name
7
7
 
8
8
  def initialize
9
+ @name = 'pxie'
9
10
  @pat_extension = 'digipatsrc'
10
11
  @capture_history = {}
11
12
  @source_history = {}
@@ -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
@@ -0,0 +1,8 @@
1
+ module OrigenTesters
2
+ module StilBasedTester
3
+ class STIL < Base
4
+ end
5
+ end
6
+ # Support OrigenTesters::STIL.new
7
+ STIL = StilBasedTester::STIL
8
+ end
@@ -58,6 +58,8 @@ module OrigenTesters
58
58
  @digcap_settings = { digcap_format: :twos_complement }
59
59
  end
60
60
  @blocks = [Block.new(0, self), Block.new(1, self), Block.new(2, self)]
61
+
62
+ add_timeset 'tp0'
61
63
  end
62
64
 
63
65
  def on_create
@@ -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,
@@ -1,5 +1,5 @@
1
1
  # Pattern to exercise the Freq Counter feature
2
- unless $tester.v93k? || $tester.pxie6570?
2
+ unless $tester.v93k? || $tester.pxie6570? || $tester.stil?
3
3
  Pattern.create do
4
4
  $dut.freq_count
5
5
  end
@@ -1,4 +1,4 @@
1
- unless $tester.v93k? || $tester.pxie6570?
1
+ unless $tester.v93k? || $tester.pxie6570? || $tester.stil?
2
2
  # Pattern to exercise the memory test feature of tester
3
3
  Pattern.create(:memory_test => true) do
4
4
 
@@ -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
@@ -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
- self.resources_filename = 'prb1'
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
 
@@ -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
- self.resources_filename = 'prb2'
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
- <%= render "partials/placeholder.md" %>
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.20.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-02-06 00:00:00.000000000 Z
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.26.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.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