• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Origen-SDK / origen_testers / 28300688211

27 Jun 2026 08:20PM UTC coverage: 87.811% (+0.05%) from 87.757%
28300688211

Pull #235

github

priyavadan
remove local path references
Pull Request #235: Feature/ruby 4 0

212 of 253 new or added lines in 65 files covered. (83.79%)

10 existing lines in 8 files now uncovered.

13335 of 15186 relevant lines covered (87.81%)

19892.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.06
/lib/origen_testers/interface.rb
1
require 'active_support/concern'
12✔
2

3
module OrigenTesters
12✔
4
  # Include this module in any class you define as a test interface
5
  module Interface
12✔
6
    extend ActiveSupport::Concern
12✔
7
    include ATP::FlowAPI
12✔
8

9
    included do
12✔
10
      Origen.add_interface(self)
108✔
11
    end
12

13
    class PatternArray < ::Array
12✔
14
      def <<(pat)
12✔
15
        push(pat)
23,184✔
16
      end
17

18
      # Override the array push method to capture the pattern under the new API, but
19
      # maintain the old one where a pattern reference was just pushed to the
20
      # referenced_patterns array
21
      def push(pat)
12✔
22
        Origen.interface.record_pattern_reference(pat)
23,184✔
23
      end
24
    end
25

26
    def self.with_resources_mode
12✔
27
      orig = @resources_mode
528✔
28
      @resources_mode = true
528✔
29
      yield
528✔
30
      @resources_mode = orig
528✔
31
    end
32

33
    def self.resources_mode?
12✔
34
      !!@resources_mode
69,336✔
35
    end
36

37
    def self.write=(val)
12✔
38
      @write = val
168✔
39
    end
40

41
    def self.write?
12✔
42
      !!@write
2,760✔
43
    end
44

45
    def test(name, options = {})
12✔
46
      flow.test(name, options)
5,172✔
47
    end
48

49
    def generating_sub_program?
12✔
50
      (defined? @@generating_sub_program) ? @@generating_sub_program : false
1,080✔
51
    end
52

53
    # Returns the abstract test program model for the current flow
54
    def atp
12✔
55
      flow.model
10,692✔
56
    end
57

58
    def write?
12✔
59
      OrigenTesters::Interface.write?
2,760✔
60
    end
61

62
    # Returns true if the test flow context (as supplied in the given options)
63
    # has changed vs. that applied to the previous test.
64
    # Flow context means enabled words, job, if_failed/passed, etc.
65
    def context_changed?(options = {})
12✔
66
      flow.context_changed?(options)
120✔
67
    end
68

69
    # Returns true if the value of the given parameter within the given options is
70
    # different vs. the last test
71
    #   if parameter_changed?(:vdd, :vddc, options)
72
    #     # execute code if the vdd level has changed
73
    #   end
74
    def parameter_changed?(*params)
12✔
75
      options = params.last.is_a?(Hash) ? params.pop : {}
96✔
76
      last = flow.instance_variable_get(:@_last_parameters_)
96✔
77
      if last
96✔
78
        params.any? { |p| options[p] != last[p] }
168✔
79
      else
80
        false
12✔
81
      end
82
    end
83

84
    # Convenience method, equivalent of calling (context_changed? || parameter_changed?)
85
    def context_or_parameter_changed?(*params)
12✔
86
      options = params.last.is_a?(Hash) ? params.pop : {}
48✔
87
      context_changed?(options) || parameter_changed?(*params, options)
48✔
88
    end
89

90
    # Returns the value defined on if/how to make test names unique within a flow
91
    def unique_test_names
12✔
92
      @unique_test_names
62,076✔
93
    end
94

95
    # Set the value of unique_test_names
96
    def unique_test_names=(val)
12✔
97
      @unique_test_names = val
1,500✔
98
    end
99

100
    # Returns whether the tester has been configured to wrap top-level flow modules with an
101
    # enable or not.
102
    #
103
    # Returns nil if not.
104
    #
105
    # Returns :enabled if the enable is configured to be on by default, or :disabled if it is
106
    # configured to be off by default.
107
    def add_flow_enable
12✔
108
      @add_flow_enable
×
109
    end
110

111
    # Set to :enabled to have the current flow wrapped by an enable flow variable
112
    # that is enabled by default (top-level flow has to disable modules it doesn't want).
113
    #
114
    # Set to :disabled to have the opposite, where the top-level flow has to enable all
115
    # modules.
116
    #
117
    # Set to nil to have no wrapping. While this is the default, setting this to nil will
118
    # override any setting of the attribute of the same name that has been set at
119
    # tester-level by the target.
120
    def add_flow_enable=(value)
12✔
121
      return unless flow.respond_to?(:add_flow_enable=)
120✔
122

123
      if value
84✔
124
        if value == :enable || value == :enabled
84✔
125
          flow.add_flow_enable = :enabled
84✔
126
        elsif value == :disable || value == :disabled
×
127
          flow.add_flow_enable = :disabled
×
128
        else
129
          fail "Unknown add_flow_enable value, #{value}, must be :enabled or :disabled"
×
130
        end
131
      else
132
        flow.add_flow_enable = nil
×
133
      end
134
    end
135

136
    # This identifier will be used to make labels and other references unique to the
137
    # current application. This will help to avoid name duplication if a program is
138
    # comprised of many modules generated by Origen.
139
    #
140
    # Override in the application interface to customize, by default the identifier
141
    # will be Origen.config.initials
142
    def app_identifier
12✔
143
      Origen.config.initials || 'Anon App'
×
144
    end
145

146
    def close(options = {})
12✔
147
      sheet_generators.each do |generator|
4,596✔
148
        generator.close(options)
38,844✔
149
      end
150
    end
151

152
    # Compile a template file
153
    def compile(file, options = {})
12✔
154
      return unless write?
24✔
155

156
      # Any options passed in from an interface will be passed to the compiler and to
157
      # the templates being compiled
158
      options[:initial_options] = options
24✔
159
      Origen.file_handler.preserve_state do
24✔
160
        file = Origen.file_handler.clean_path_to_template(file)
24✔
161
        Origen.generator.compile_file_or_directory(file, options)
24✔
162
      rescue
NEW
163
        file = Origen.file_handler.clean_path_to(file)
×
NEW
164
        Origen.generator.compile_file_or_directory(file, options)
×
165
      end
166
    end
167

168
    def import(file, options = {})
12✔
169
      # Attach the import request to the first generator, when it imports
170
      # it any generated resources will automatically find their way to the
171
      # correct generator/collection
172
      generator = flow || sheet_generators.first
2,172✔
173
      generator.import(file, options)
2,172✔
174
    end
175

176
    def render(file, options = {})
12✔
177
      flow.render(file, options)
192✔
178
    end
179

180
    def add_meta!(options)
12✔
181
      flow.send(:add_meta!, options)
10,692✔
182
    end
183

184
    def add_description!(options)
12✔
185
      flow.send(:add_description!, options)
10,692✔
186
    end
187

188
    def write_files(options = {})
12✔
189
      sheet_generators.each do |generator|
168✔
190
        generator.finalize(options)
2,472✔
191
      end
192
      sheet_generators.each do |generator| # rubocop:disable Style/CombinableLoops
168✔
193
        generator.write_to_file(options) if generator.to_be_written?
2,640✔
194
      end
195
      clean_referenced_patterns
168✔
196
      flow.save_program
168✔
197
    end
198

199
    def on_program_completion(options = {})
12✔
200
      reset_globals
168✔
201
      @@pattern_references = {}
168✔
202
      @@referenced_patterns = nil
168✔
203
    end
204

205
    # A secondary pattern is one where the pattern has been created by Origen as an output from
206
    # generating another pattern (a primary pattern). For example, on V93K anytime a tester
207
    # handshake is done, the pattern will be split into separate components, such as
208
    # meas_bgap.avc (the primary pattern) and meas_bgap_part1.avc (a secondary pattern).
209
    #
210
    # Any such secondary pattern references should be pushed to this array, rather than the
211
    # referenced_patterns array.
212
    # By using the dedicated secondary array, the pattern will not appear in the referenced.list
213
    # file so that Origen is not asked to generate it (since it will be created naturally from
214
    # the primary pattern reference).
215
    # However if the ATE requires a reference to the pattern (e.g. the V93K pattern master file),
216
    # then it will be included in the relevant ATE files.
217
    def record_pattern_reference(name, options = {})
12✔
218
      if name.is_a?(String) || name.is_a?(Symbol)
45,276✔
219
        name = name.to_s
45,276✔
220
      else
221
        fail "Pattern name must be a string or a symbol, not a #{name.class}"
×
222
      end
223
      # Help out the user and force any multi-part patterns to :ate type
224
      unless options[:type]
45,276✔
225
        if name.sub(/\..*/, '') =~ /part\d+$/
45,276✔
226
          options[:type] = :ate
×
227
        end
228
      end
229
      unless options[:type] == :origen
45,276✔
230
        # Inform the current generator that it has a new pattern reference to handle
231
        if respond_to?(:pattern_reference_recorded)
45,276✔
232
          pattern_reference_recorded(name, options)
22,092✔
233
        end
234
      end
235
      base = options[:subroutine] ? pattern_references[:subroutine] : pattern_references[:main]
45,276✔
236
      case options[:type]
45,276✔
237
      when :origen
238
        base[:origen] << name
×
239
      when :ate
240
        base[:ate] << name
×
241
      when nil
242
        base[:all] << name
45,276✔
243
      else
244
        fail "Unknown pattern reference type, #{options[:type]}, valid values are :origen or :ate"
×
245
      end
246
      nil
7,546✔
247
    end
248

249
    # @api private
250
    def clear_pattern_references
12✔
251
      @@pattern_references = nil
×
252
    end
253

254
    # @api private
255
    def merge_pattern_references(references)
12✔
256
      references.each do |name, values|
×
257
        pattern_references(name)[:main][:all].push(*values[:main][:all])
×
258
      end
259
    end
260

261
    def pattern_references(name = pattern_references_name)
12✔
262
      @@pattern_references ||= {}
47,100✔
263
      @@pattern_references[name] ||= {
47,100✔
264
        main:       {
265
          all:    [],
266
          origen: [],
267
          ate:    []
268
        },
269
        subroutine: {
270
          all:    [],
271
          origen: [],
272
          ate:    []
273
        }
274
      }
275
    end
276

277
    def all_pattern_references
12✔
278
      pattern_references
1,824✔
279
      @@pattern_references
1,824✔
280
    end
281

282
    def pattern_references_name=(name)
12✔
283
      @pattern_references_name = name
1,080✔
284
    end
285

286
    def pattern_references_name
12✔
287
      @pattern_references_name || 'global'
47,100✔
288
    end
289

290
    # @deprecated Use record_pattern_reference instead
291
    #
292
    # All generators should push to this array whenever they reference a pattern
293
    # so that it is captured in the pattern list, e.g.
294
    #   Origen.interface.referenced_patterns << pattern
295
    #
296
    # If the ATE platform also has a pattern list, e.g. the pattern master file on V93K,
297
    # then this will also be updated.
298
    # Duplicates will be automatically eliminated, so no duplicate checking should be
299
    # performed on the application side.
300
    def referenced_patterns
12✔
301
      @@referenced_patterns ||= PatternArray.new
23,352✔
302
    end
303

304
    # Remove duplicates and file extensions from the referenced pattern lists
305
    def clean_referenced_patterns
12✔
306
      refs = [:referenced_patterns]
168✔
307
      # refs << :referenced_subroutine_patterns if Origen.tester.v93k?
308
      refs.each do |ref|
168✔
309
        var = send(ref)
168✔
310
        var = var.uniq.map do |pat|
168✔
311
          pat = pat.sub(/\..*/, '')
×
312
          pat unless pat =~ /_part\d+$/
×
313
        end.uniq.compact
314
        singleton_class.class_variable_set("@@#{ref}", var)
168✔
315
      end
316
    end
317

318
    # Add a comment line into the buffer
319
    def comment(text)
12✔
320
      comments << text
×
321
    end
322

323
    def comments
12✔
324
      @@comments ||= []
13,692✔
325
    end
326

327
    def discard_comments
12✔
328
      @@comments = nil
13,692✔
329
    end
330

331
    # Returns the buffered description comments and clears the buffer
332
    def consume_comments
12✔
333
      c = comments
13,692✔
334
      discard_comments
13,692✔
335
      c
13,692✔
336
    end
337

338
    def top_level_flow
12✔
339
      @@top_level_flow ||= nil
3,096✔
340
    end
341
    alias_method :top_level_flow_filename, :top_level_flow
12✔
342

343
    def discard_top_level_flow
12✔
344
      @@top_level_flow = nil
×
345
    end
346

347
    def flow_generator
12✔
348
      flow
3,912✔
349
    end
350

351
    def set_top_level_flow
12✔
352
      @@top_level_flow = flow_generator.output_file
1,956✔
353
    end
354

355
    def clear_top_level_flow
12✔
356
      @@top_level_flow = nil
816✔
357
    end
358

359
    # A storage Hash that all generators can push comment descriptions
360
    # into when generating.
361
    # At the end of a generation run this will contain all descriptions
362
    # for all flows that were just created.
363
    #
364
    # Access via Origen.interface.descriptions
365
    def descriptions
12✔
366
      @@descriptions ||= Parser::DescriptionLookup.new
13,692✔
367
    end
368

369
    # Any tests generated within the given block will be generated in resources mode.
370
    # Generally this means that all resources for a given test will be generated but
371
    # flow entries will be inhibited.
372
    def resources_mode
12✔
373
      OrigenTesters::Interface.with_resources_mode do
264✔
374
        yield
264✔
375
      end
376
    end
377
    alias_method :with_resources_mode, :resources_mode
12✔
378

379
    def resources_mode?
12✔
380
      OrigenTesters::Interface.resources_mode?
69,336✔
381
    end
382

383
    def identity_map # :nodoc:
12✔
384
      @@identity_map ||= ::OrigenTesters::Generator::IdentityMap.new
23,160✔
385
    end
386

387
    def platform
12✔
388
      # This branch to support the ProgramGenerators module where the generator
389
      # is included into an interface instance and not the class
390
      if singleton_class.const_defined? :PLATFORM
123,300✔
391
        singleton_class::PLATFORM
123,300✔
392
      else
393
        self.class::PLATFORM
×
394
      end
395
    end
396

397
    module ClassMethods
12✔
398
      # Returns true if the interface class supports the
399
      # given tester instance
400
      def supports?(tester_instance)
12✔
401
        tester_instance.class == self::PLATFORM
×
402
      end
403
    end
404
  end
405
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc