Class: Origen::Generator::Pattern

Inherits:
Object
  • Object
show all
Includes:
Comparator
Defined in:
lib/origen/generator/pattern.rb

Defined Under Namespace

Classes: DummyIterator

Instance Method Summary collapse

Methods included from Comparator

#check_for_changes, #relative_path_to

Instance Method Details

#close(options = {}) ⇒ Object



58
59
60
# File 'lib/origen/generator/pattern.rb', line 58

def close(options = {})
  pattern_close(options)
end

#create(options = {}) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/origen/generator/pattern.rb', line 118

def create(options = {})
  if @pattern_sequence
    yield
  else
    @create_options = options
    unless Origen.tester
      puts 'The current target has not instantiated a tester and pattern generation cannot run.'
      puts 'Add something like this to an environment file:'
      puts
      puts '  Origen::Tester::J750.new'
      puts
      puts
      puts 'Then select it by running:  origen e <environment name>'
      exit 1
    end
    Origen.tester.generating = :pattern

    job.output_file_body = options.delete(:name).to_s if options[:name]

    # Order the iterators by the order that their enable keys appear in the options, pad
    # any missing iterators with a dummy function...
    iterators = options.map do |key, _val|
      Origen.app.pattern_iterators.find { |iterator| iterator.key == key }
    end.compact
    iterators << DummyIterator.new while iterators.size < 10

    args = []

    # Couldn't get this to work fully dynamically, so hard-coded for 10 custom
    # iterators for now, should be plenty for any application in the meantime.
    # Should revisit this when time allows and remove this limitation by changing
    # this to a recursive structure.
    iterators[0].invoke(options) do |arg0|
      args[0] = arg0
      iterators[1].invoke(options) do |arg1|
        args[1] = arg1
        iterators[2].invoke(options) do |arg2|
          args[2] = arg2
          iterators[3].invoke(options) do |arg3|
            args[3] = arg3
            iterators[4].invoke(options) do |arg4|
              args[4] = arg4
              iterators[5].invoke(options) do |arg5|
                args[5] = arg5
                iterators[6].invoke(options) do |arg6|
                  args[6] = arg6
                  iterators[7].invoke(options) do |arg7|
                    args[7] = arg7
                    iterators[8].invoke(options) do |arg8|
                      args[8] = arg8
                      iterators[9].invoke(options) do |arg9|
                        args[9] = arg9
                        # Refresh the target to start all settings from scratch each time
                        # This is an easy way to reset all registered values
                        Origen.app.reload_target!(skip_first_time: true)

                        # Final call back to the project to allow it to make any pattern name specific
                        # configuration changes
                        Origen.app.listeners_for(:before_pattern).each do |listener|
                          listener.before_pattern(job.output_pattern_filename)
                        end

                        # Work out the final pattern name based on the current iteration
                        job.reset_output_pattern_filename
                        iterators.each_with_index do |iterator, i|
                          if iterator.enabled?(options)
                            job.output_pattern_filename =
                              iterator.pattern_name.call(job.output_pattern_filename, args[i])
                          end
                        end

                        # Allow custom pattern prefix
                        unless options[:pat_prefix].to_s.empty?
                          if job.output_prefix.empty?
                            job.output_pattern_filename = "#{options[:pat_prefix]}_" + job.output_pattern_filename
                          else
                            job.output_pattern_filename = job.output_pattern_filename.sub(job.output_prefix, job.output_prefix + "#{options[:pat_prefix]}_")
                          end
                        end

                        # Allow custom pattern postfix
                        unless options[:pat_postfix].to_s.empty?
                          job.output_pattern_filename = job.output_pattern_filename.sub(job.output_postfix + job.output_extension, "_#{options[:pat_postfix]}" + job.output_postfix + job.output_extension)
                        end

                        pattern_wrapper(iterators, args, options) do
                          # Call iterator setups, whatever these return are passed to the pattern
                          yield_items = []
                          iterators.each_with_index do |iterator, i|
                            if iterator.enabled?(options)
                              yield_items << iterator.setup.call(args[i])
                            end
                          end

                          yield(*yield_items)
                        end
                      end
                    end
                  end
                end
              end
            end
          end
        end
      end
    end
  end
  @create_options = nil
end

#create_optionsObject

Returns the options passed to the current create block



21
22
23
# File 'lib/origen/generator/pattern.rb', line 21

def create_options
  @create_options || {}
end

#logObject



16
17
18
# File 'lib/origen/generator/pattern.rb', line 16

def log
  Origen.log
end

#open(options = {}) ⇒ Object

The recommended way to create a pattern is to wrap it within a Pattern.create block, however occasionally the need may arise to manually open and close a pattern, this method can be used in that case in association with the close method.

Pattern iterators are not supported when creating a pattern in this way.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/origen/generator/pattern.rb', line 31

def open(options = {})
  if block_given?
    create(options) do |*args|
      yield(*args)
    end
  else
    job.output_file_body = options.delete(:name).to_s if options[:name]

    # Refresh the target to start all settings from scratch each time
    # This is an easy way to reset all registered values
    Origen.app.reload_target!(skip_first_time: true)

    # Final call back to the project to allow it to make any pattern name specific
    # configuration changes
    Origen.app.listeners_for(:before_pattern).each do |listener|
      listener.before_pattern(job.output_pattern_filename)
    end

    # Allow custom pattern postfix
    unless options[:pat_postfix].to_s.empty?
      job.output_pattern_filename = job.output_pattern_filename.sub(job.output_postfix + job.output_extension, "_#{options[:pat_postfix]}" + job.output_postfix + job.output_extension)
    end

    pattern_open(options)
  end
end

#resetObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This is called before each new pattern source is executed



247
248
249
# File 'lib/origen/generator/pattern.rb', line 247

def reset
  $desc = nil # Clear the description
end

#sequence(options = {}, &block) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/origen/generator/pattern.rb', line 62

def sequence(options = {}, &block)
  @create_options = options
  unless Origen.tester
    puts 'The current target has not instantiated a tester and pattern generation cannot run.'
    puts 'Add something like this to an environment file:'
    puts
    puts '  Origen::Tester::J750.new'
    puts
    puts
    puts 'Then select it by running:  origen e <environment name>'
    exit 1
  end
  Origen.tester.generating = :pattern

  job.output_file_body = options.delete(:name).to_s if options[:name]

  # Refresh the target to start all settings from scratch each time
  # This is an easy way to reset all registered values
  Origen.app.reload_target!(skip_first_time: true)

  # Final call back to the project to allow it to make any pattern name specific
  # configuration changes
  Origen.app.listeners_for(:before_pattern).each do |listener|
    listener.before_pattern(job.output_pattern_filename)
  end

  ## Allow custom pattern postfix
  # unless options[:pat_postfix].to_s.empty?
  #  job.output_pattern_filename = job.output_pattern_filename.sub(job.output_postfix + job.output_extension, "_#{options[:pat_postfix]}" + job.output_postfix + job.output_extension)
  # end

  @pattern_sequence = true

  # The startup callbacks need to be skipped for now until the main thread is open for business
  pattern_wrapper([], [], options.merge(call_startup_callbacks: false)) do
    # The startup callbacks, if required, need to be wrapped up in a closure for calling
    # later by the main thread
    if (options.key?(:call_startup_callbacks) && !options[:call_startup_callbacks]) || options[:skip_startup]
      pre_block = nil
    else
      pre_block = proc do
        # Call startup callbacks
        Origen.app.listeners_for(:startup).each do |listener|
          listener.startup(options)
        end
      end
    end
    PatternSequencer.send(:active=, true)
    @pattern_sequence = PatternSequence.new(job.output_pattern_filename, block, pre_block)
    @pattern_sequence.send(:execute)
    PatternSequencer.send(:active=, false)
  end
  @pattern_sequence = false
  @create_options = nil
end

#split(options = {}) ⇒ Object

Split a running Pattern.create block into multiple patterns.

The output that has been generated up until the point where this is called will be written and a new pattern will be opened to contain the remainder of the pattern content generated by the block.

Each additional pattern section created by calling this method will have '_partN' appended to the original pattern name.



237
238
239
240
241
242
# File 'lib/origen/generator/pattern.rb', line 237

def split(options = {})
  split_name = options.delete(:name) || ''
  pattern_close(options.merge(call_shutdown_callbacks: false))
  job.inc_split_counter(split_name)
  pattern_open(options.merge(call_startup_callbacks: false))
end