origen 0.34.3 → 0.52.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (207) hide show
  1. checksums.yaml +5 -5
  2. data/bin/origen +1 -231
  3. data/config/application.rb +12 -3
  4. data/config/boot.rb +2 -7
  5. data/config/commands.rb +3 -74
  6. data/config/rubocop/easy_disabled.yml +4 -0
  7. data/config/rubocop/easy_enabled.yml +0 -4
  8. data/config/rubocop/strict_disabled.yml +4 -0
  9. data/config/rubocop/strict_enabled.yml +0 -4
  10. data/config/version.rb +2 -3
  11. data/lib/origen.rb +27 -14
  12. data/lib/origen/application.rb +88 -2
  13. data/lib/origen/application/deployer.rb +3 -1
  14. data/lib/origen/application/release.rb +2 -2
  15. data/lib/origen/application/runner.rb +35 -20
  16. data/lib/origen/boot.rb +302 -0
  17. data/lib/origen/boot/api.rb +13 -0
  18. data/lib/origen/boot/app.rb +284 -0
  19. data/lib/origen/code_generators.rb +30 -10
  20. data/lib/origen/code_generators/actions.rb +244 -34
  21. data/lib/origen/code_generators/base.rb +9 -2
  22. data/lib/origen/code_generators/block.rb +203 -0
  23. data/lib/origen/code_generators/block_common.rb +100 -0
  24. data/lib/origen/code_generators/dut.rb +62 -0
  25. data/lib/origen/code_generators/feature.rb +50 -0
  26. data/lib/origen/code_generators/klass.rb +41 -0
  27. data/lib/origen/code_generators/model.rb +60 -0
  28. data/lib/origen/code_generators/module.rb +92 -0
  29. data/lib/origen/commands.rb +30 -13
  30. data/lib/origen/commands/archive.rb +175 -0
  31. data/lib/origen/commands/extract.rb +43 -0
  32. data/lib/origen/commands/generate.rb +1 -0
  33. data/lib/origen/commands/lint.rb +6 -1
  34. data/lib/origen/commands/new.rb +48 -24
  35. data/lib/origen/commands/new_resource.rb +41 -0
  36. data/lib/origen/commands/site.rb +52 -0
  37. data/lib/origen/commands/web.rb +11 -6
  38. data/lib/origen/commands_global.rb +9 -7
  39. data/lib/origen/core_ext/numeric.rb +20 -0
  40. data/lib/{option_parser → origen/core_ext/option_parser}/optparse.rb +0 -0
  41. data/lib/origen/dependencies.rb +0 -0
  42. data/lib/origen/file_handler.rb +18 -6
  43. data/lib/origen/generator.rb +19 -10
  44. data/lib/origen/generator/comparator.rb +2 -1
  45. data/lib/origen/generator/flow.rb +3 -1
  46. data/lib/origen/generator/job.rb +60 -16
  47. data/lib/origen/generator/pattern.rb +132 -72
  48. data/lib/origen/generator/pattern_finder.rb +3 -3
  49. data/lib/origen/generator/pattern_sequence.rb +201 -0
  50. data/lib/origen/generator/pattern_sequencer.rb +99 -0
  51. data/lib/origen/generator/pattern_thread.rb +175 -0
  52. data/lib/origen/loader.rb +381 -0
  53. data/lib/origen/log.rb +250 -108
  54. data/lib/origen/model.rb +22 -1
  55. data/lib/origen/model/exporter.rb +50 -10
  56. data/lib/origen/model_initializer.rb +5 -1
  57. data/lib/origen/operating_systems.rb +4 -0
  58. data/lib/origen/parameters.rb +96 -4
  59. data/lib/origen/parameters/set.rb +4 -3
  60. data/lib/origen/pins.rb +10 -8
  61. data/lib/origen/pins/pin.rb +61 -46
  62. data/lib/origen/ports/port.rb +5 -0
  63. data/lib/origen/registers.rb +5 -0
  64. data/lib/origen/registers/bit.rb +57 -53
  65. data/lib/origen/registers/bit_collection.rb +100 -43
  66. data/lib/origen/registers/msb0_delegator.rb +47 -0
  67. data/lib/origen/registers/reg.rb +114 -99
  68. data/lib/origen/revision_control.rb +1 -1
  69. data/lib/origen/revision_control/git.rb +23 -3
  70. data/lib/origen/site_config.rb +251 -60
  71. data/lib/origen/site_config/config.rb +217 -0
  72. data/lib/origen/sub_blocks.rb +106 -31
  73. data/lib/origen/top_level.rb +11 -0
  74. data/lib/origen/users/user.rb +3 -2
  75. data/lib/origen/utility/mailer.rb +42 -9
  76. data/lib/origen/value/bin_str_val.rb +1 -1
  77. data/lib/origen/value/hex_str_val.rb +1 -1
  78. data/lib/origen/version_string.rb +6 -1
  79. data/lib/tasks/gem.rake +6 -1
  80. data/origen_app_generators/Gemfile +19 -0
  81. data/origen_app_generators/Gemfile.lock +152 -0
  82. data/origen_app_generators/LICENSE +21 -0
  83. data/origen_app_generators/README.md +368 -0
  84. data/{templates/code_generators/rakefile.rb → origen_app_generators/Rakefile} +0 -0
  85. data/origen_app_generators/bin/boot.rb +39 -0
  86. data/origen_app_generators/config/application.rb +153 -0
  87. data/origen_app_generators/config/boot.rb +1 -0
  88. data/origen_app_generators/config/commands.rb +63 -0
  89. data/origen_app_generators/config/shared_commands.rb +177 -0
  90. data/origen_app_generators/config/version.rb +8 -0
  91. data/origen_app_generators/doc/history +223 -0
  92. data/origen_app_generators/lbin/bundle +105 -0
  93. data/origen_app_generators/lbin/byebug +29 -0
  94. data/origen_app_generators/lbin/coderay +29 -0
  95. data/origen_app_generators/lbin/htmldiff +29 -0
  96. data/origen_app_generators/lbin/httparty +29 -0
  97. data/origen_app_generators/lbin/httpclient +29 -0
  98. data/origen_app_generators/lbin/kramdown +29 -0
  99. data/origen_app_generators/lbin/ldiff +29 -0
  100. data/origen_app_generators/lbin/nanoc +29 -0
  101. data/origen_app_generators/lbin/nokogiri +29 -0
  102. data/origen_app_generators/lbin/origen +62 -0
  103. data/origen_app_generators/lbin/pry +29 -0
  104. data/origen_app_generators/lbin/rackup +29 -0
  105. data/origen_app_generators/lbin/rake +29 -0
  106. data/origen_app_generators/lbin/rspec +29 -0
  107. data/origen_app_generators/lbin/rubocop +29 -0
  108. data/origen_app_generators/lbin/ruby-parse +29 -0
  109. data/origen_app_generators/lbin/ruby-rewrite +29 -0
  110. data/origen_app_generators/lbin/thor +29 -0
  111. data/origen_app_generators/lbin/tilt +29 -0
  112. data/origen_app_generators/lbin/yard +29 -0
  113. data/origen_app_generators/lbin/yardoc +29 -0
  114. data/origen_app_generators/lbin/yri +29 -0
  115. data/origen_app_generators/lib/origen_app_generators.rb +125 -0
  116. data/origen_app_generators/lib/origen_app_generators/application.rb +62 -0
  117. data/origen_app_generators/lib/origen_app_generators/base.rb +257 -0
  118. data/origen_app_generators/lib/origen_app_generators/empty_application.rb +15 -0
  119. data/origen_app_generators/lib/origen_app_generators/empty_plugin.rb +15 -0
  120. data/origen_app_generators/lib/origen_app_generators/new.rb +170 -0
  121. data/origen_app_generators/lib/origen_app_generators/new_app_tests.rb +4 -0
  122. data/origen_app_generators/lib/origen_app_generators/origen_infrastructure/app_generator_plugin.rb +107 -0
  123. data/origen_app_generators/lib/origen_app_generators/plugin.rb +55 -0
  124. data/origen_app_generators/lib/origen_app_generators/test_engineering/common.rb +29 -0
  125. data/origen_app_generators/lib/origen_app_generators/test_engineering/stand_alone_application.rb +64 -0
  126. data/origen_app_generators/lib/origen_app_generators/test_engineering/test_block.rb +61 -0
  127. data/origen_app_generators/origen_app_generators.gemspec +33 -0
  128. data/{templates/code_generators → origen_app_generators/spec}/spec_helper.rb +0 -0
  129. data/origen_app_generators/target/debug.rb +8 -0
  130. data/origen_app_generators/target/default.rb +8 -0
  131. data/origen_app_generators/target/production.rb +0 -0
  132. data/origen_app_generators/templates/app_generators/application/.gitignore +37 -0
  133. data/origen_app_generators/templates/app_generators/application/.irbrc +9 -0
  134. data/origen_app_generators/templates/app_generators/application/.rspec +1 -0
  135. data/origen_app_generators/templates/app_generators/application/.travis.yml +11 -0
  136. data/origen_app_generators/templates/app_generators/application/Gemfile +34 -0
  137. data/origen_app_generators/templates/app_generators/application/Rakefile +7 -0
  138. data/origen_app_generators/templates/app_generators/application/app/blocks/top_level.rb +12 -0
  139. data/origen_app_generators/templates/app_generators/application/app/lib/module.rb +6 -0
  140. data/origen_app_generators/templates/app_generators/application/app/templates/web/index.md.erb +19 -0
  141. data/origen_app_generators/templates/app_generators/application/app/templates/web/layouts/_basic.html.erb +13 -0
  142. data/origen_app_generators/templates/app_generators/application/app/templates/web/partials/_navbar.html.erb +20 -0
  143. data/origen_app_generators/templates/app_generators/application/app/templates/web/release_notes.md.erb +5 -0
  144. data/origen_app_generators/templates/app_generators/application/config/application.rb +121 -0
  145. data/origen_app_generators/templates/app_generators/application/config/boot.rb +4 -0
  146. data/origen_app_generators/templates/app_generators/application/config/commands.rb +79 -0
  147. data/origen_app_generators/templates/app_generators/application/config/maillist_dev.txt +4 -0
  148. data/origen_app_generators/templates/app_generators/application/config/maillist_prod.txt +3 -0
  149. data/origen_app_generators/templates/app_generators/application/config/version.rb +8 -0
  150. data/origen_app_generators/templates/app_generators/application/doc/history +0 -0
  151. data/origen_app_generators/templates/app_generators/application/dot_keep +0 -0
  152. data/origen_app_generators/templates/app_generators/application/origen_core_session +2 -0
  153. data/origen_app_generators/templates/app_generators/application/spec/spec_helper.rb +44 -0
  154. data/origen_app_generators/templates/app_generators/application/target/debug.rb +8 -0
  155. data/origen_app_generators/templates/app_generators/application/target/default.rb +1 -0
  156. data/origen_app_generators/templates/app_generators/application/target/production.rb +4 -0
  157. data/origen_app_generators/templates/app_generators/new/generator.rb +102 -0
  158. data/origen_app_generators/templates/app_generators/new/info.md.erb +9 -0
  159. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/application.rb +54 -0
  160. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/base.rb +55 -0
  161. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/module.rb +28 -0
  162. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/plugin.rb +64 -0
  163. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/config/load_generators.rb +6 -0
  164. data/origen_app_generators/templates/app_generators/plugin/Gemfile +32 -0
  165. data/origen_app_generators/templates/app_generators/plugin/Rakefile +10 -0
  166. data/origen_app_generators/templates/app_generators/plugin/app/templates/web/index.md.erb +37 -0
  167. data/origen_app_generators/templates/app_generators/plugin/app/templates/web/partials/_navbar_external.html.erb +20 -0
  168. data/origen_app_generators/templates/app_generators/plugin/app/templates/web/partials/_navbar_internal.html.erb +20 -0
  169. data/origen_app_generators/templates/app_generators/plugin/config/boot.rb +24 -0
  170. data/origen_app_generators/templates/app_generators/plugin/gemspec.rb +43 -0
  171. data/origen_app_generators/templates/app_generators/test_engineering/environment/j750.rb +1 -0
  172. data/origen_app_generators/templates/app_generators/test_engineering/environment/uflex.rb +1 -0
  173. data/origen_app_generators/templates/app_generators/test_engineering/environment/v93k.rb +1 -0
  174. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/.keep +0 -0
  175. data/origen_app_generators/templates/app_generators/test_engineering/test_block/.keep +0 -0
  176. data/origen_site_config.yml +55 -5
  177. data/templates/code_generators/attributes.rb +20 -0
  178. data/templates/code_generators/class.rb +9 -0
  179. data/templates/code_generators/controller.rb +87 -0
  180. data/templates/code_generators/model.rb +21 -0
  181. data/templates/code_generators/module.rb +4 -0
  182. data/templates/code_generators/parameters.rb +19 -0
  183. data/templates/code_generators/pins.rb +28 -0
  184. data/templates/code_generators/registers.rb +20 -0
  185. data/templates/code_generators/sub_blocks.rb +24 -0
  186. data/templates/code_generators/timesets.rb +24 -0
  187. data/templates/code_generators/version.rb +0 -1
  188. data/templates/git/gitignore.erb +0 -1
  189. data/vendor/lib/models/origen/export1.rb +77 -0
  190. data/vendor/lib/models/origen/export1/block1.rb +13 -0
  191. data/vendor/lib/models/origen/export1/block1/x.rb +36 -0
  192. data/vendor/lib/models/origen/non_origen_meta_data.md +1 -0
  193. metadata +149 -68
  194. data/bin/fix_my_workspace +0 -100
  195. data/lib/c99/ate_interface.rb +0 -77
  196. data/lib/c99/nvm.rb +0 -110
  197. data/lib/c99/target/mock2.rb +0 -1
  198. data/lib/c99/target/subdir/mock3.rb +0 -1
  199. data/lib/origen/code_generators/bundler.rb +0 -17
  200. data/lib/origen/code_generators/gem_setup.rb +0 -49
  201. data/lib/origen/code_generators/rake.rb +0 -13
  202. data/lib/origen/code_generators/rspec.rb +0 -12
  203. data/lib/origen/commands/add.rb +0 -12
  204. data/lib/tasks/private/build.rake +0 -8
  205. data/templates/code_generators/gemfile_app.rb +0 -4
  206. data/templates/code_generators/gemfile_plugin.rb +0 -6
  207. data/templates/code_generators/gemspec.rb +0 -33
@@ -51,7 +51,8 @@ module Origen
51
51
  end
52
52
 
53
53
  def relative_path_to(file)
54
- p = Pathname(file).relative_path_from(Pathname.pwd).to_s
54
+ file = Pathname.new(file) unless file.is_a?(Pathname)
55
+ p = file.expand_path.relative_path_from(Pathname.pwd).to_s
55
56
  p.gsub!('/', '\\') if Origen.running_on_windows?
56
57
  p
57
58
  end
@@ -31,7 +31,9 @@ module Origen
31
31
  end
32
32
  interface.close(flow: true, sub_flow: true)
33
33
  else
34
- Origen.log.info "Generating... #{Origen.file_handler.current_file.basename}"
34
+ unless tester.try(:sim?)
35
+ Origen.log.info "Generating... #{Origen.file_handler.current_file.basename}"
36
+ end
35
37
  interface = Origen.reset_interface(options)
36
38
  Origen.interface.set_top_level_flow
37
39
  Origen.interface.flow_generator.set_flow_description(Origen.interface.consume_comments)
@@ -121,18 +121,34 @@ module Origen
121
121
  end
122
122
  end
123
123
 
124
+ def strip_dir_and_ext(name)
125
+ Pathname.new(name).basename('.*').basename('.*').to_s
126
+ end
127
+
124
128
  def run
125
129
  Origen.app.current_jobs << self
126
130
  begin
127
131
  if @options[:compile]
132
+ Origen.log.start_job(strip_dir_and_ext(@requested_pattern), :compiler)
128
133
  Origen.generator.compiler.compile(@requested_pattern, @options)
129
134
  elsif @options[:job_type] == :merge
135
+ Origen.log.start_job(strip_dir_and_ext(@requested_pattern), :merger)
130
136
  Origen.generator.compiler.merge(@requested_pattern)
131
137
  elsif @options[:action] == :program
138
+ if Origen.running_simulation?
139
+ Origen.log.start_job(strip_dir_and_ext(@requested_pattern), :simulator)
140
+ else
141
+ Origen.log.start_job(strip_dir_and_ext(@requested_pattern), :program_generator)
142
+ end
132
143
  Origen.flow.reset
133
144
  Origen.resources.reset
134
145
  OrigenTesters::Generator.execute_source(@pattern)
135
146
  else
147
+ if Origen.running_simulation?
148
+ Origen.log.start_job(strip_dir_and_ext(@requested_pattern), :simulator)
149
+ else
150
+ Origen.log.start_job(strip_dir_and_ext(@requested_pattern), :pattern_generator)
151
+ end
136
152
  Origen.generator.pattern.reset # Resets the pattern controller ready for a new pattern
137
153
  # Give the app a chance to handle pattern dispatch
138
154
  skip = false
@@ -140,30 +156,58 @@ module Origen
140
156
  skip ||= !listener.before_pattern_lookup(@requested_pattern)
141
157
  end
142
158
  unless skip
143
- @pattern = Origen.generator.pattern_finder.find(@requested_pattern, @options)
144
- if @pattern.is_a?(Hash)
145
- @output_file_body = @pattern[:output]
146
- @pattern = @pattern[:pattern]
159
+ if @options[:sequence]
160
+ @pattern = @requested_pattern
161
+ Origen.pattern.sequence do |seq|
162
+ # This splits the pattern name by "_" then removes all values that are common to all patterns
163
+ # and then rejoins what is left.
164
+ # The goal is to keep the thread ID concise for the log and rather than using the whole pattern
165
+ # name only focussing on what is different.
166
+ # e.g. if you combined patterns flash_read_ckbd_ip1_max.rb and flash_read_ckbd_ip2_max.rb into
167
+ # a concurrent sequence then the two threads would be called 'ip1' and 'ip2'.
168
+ ids = @options[:patterns].map do |pat|
169
+ Pathname.new(pat).basename('.*').to_s.split('_')
170
+ end
171
+ ids = ids.map { |id| id.reject { |i| ids.all? { |id| id.include?(i) } }.join('_') }
172
+
173
+ @options[:patterns].each_with_index do |pat, i|
174
+ id = ids[i]
175
+ id = i.to_s if id.empty?
176
+ seq.in_parallel id do
177
+ seq.run pat
178
+ end
179
+ end
180
+ end
181
+ else
182
+ @pattern = Origen.generator.pattern_finder.find(@requested_pattern, @options)
183
+ if @pattern.is_a?(Hash)
184
+ @output_file_body = @pattern[:output]
185
+ @pattern = @pattern[:pattern]
186
+ end
187
+ load @pattern unless @pattern == :skip # Run the pattern
147
188
  end
148
- load @pattern unless @pattern == :skip # Run the pattern
149
189
  end
150
190
  end
151
191
  rescue Exception => e
152
- if @options[:continue] || Origen.running_remotely?
153
- Origen.log.error "FAILED - #{@requested_pattern} (for target #{Origen.target.name})"
154
- Origen.log.error e.message
155
- e.backtrace.each do |l|
156
- Origen.log.error l
157
- end
158
- if @options[:compile]
159
- Origen.app.stats.failed_files += 1
192
+ # Whoever has aborted the job is responsible for cleaning it up
193
+ unless e.is_a?(Origen::Generator::AbortError)
194
+ if @options[:continue] || Origen.running_remotely?
195
+ Origen.log.error "FAILED - #{@requested_pattern} (for target #{Origen.target.name})"
196
+ Origen.log.error e.message
197
+ e.backtrace.each do |l|
198
+ Origen.log.error l
199
+ end
200
+ if @options[:compile]
201
+ Origen.app.stats.failed_files += 1
202
+ else
203
+ Origen.app.stats.failed_patterns += 1
204
+ end
160
205
  else
161
- Origen.app.stats.failed_patterns += 1
206
+ raise
162
207
  end
163
- else
164
- raise
165
208
  end
166
209
  end
210
+ Origen.log.stop_job
167
211
  Origen.app.current_jobs.pop
168
212
  end
169
213
  end
@@ -59,87 +59,144 @@ module Origen
59
59
  pattern_close(options)
60
60
  end
61
61
 
62
- def create(options = {})
62
+ def sequence(options = {}, &block)
63
63
  @create_options = options
64
64
  unless Origen.tester
65
65
  puts 'The current target has not instantiated a tester and pattern generation cannot run.'
66
- puts 'Add something like this to your target file:'
67
- puts ''
68
- puts ' $tester = Origen::Tester::J750.new'
69
- puts ''
66
+ puts 'Add something like this to an environment file:'
67
+ puts
68
+ puts ' Origen::Tester::J750.new'
69
+ puts
70
+ puts
71
+ puts 'Then select it by running: origen e <environment name>'
70
72
  exit 1
71
73
  end
72
74
  Origen.tester.generating = :pattern
73
75
 
74
76
  job.output_file_body = options.delete(:name).to_s if options[:name]
75
77
 
76
- # Order the iterators by the order that their enable keys appear in the options, pad
77
- # any missing iterators with a dummy function...
78
- iterators = options.map do |key, _val|
79
- Origen.app.pattern_iterators.find { |iterator| iterator.key == key }
80
- end.compact
81
- iterators << DummyIterator.new while iterators.size < 10
82
-
83
- args = []
84
-
85
- # Couldn't get this to work fully dynamically, so hard-coded for 10 custom
86
- # iterators for now, should be plenty for any application in the meantime.
87
- # Should revisit this when time allows and remove this limitation by changing
88
- # this to a recursive structure.
89
- iterators[0].invoke(options) do |arg0|
90
- args[0] = arg0
91
- iterators[1].invoke(options) do |arg1|
92
- args[1] = arg1
93
- iterators[2].invoke(options) do |arg2|
94
- args[2] = arg2
95
- iterators[3].invoke(options) do |arg3|
96
- args[3] = arg3
97
- iterators[4].invoke(options) do |arg4|
98
- args[4] = arg4
99
- iterators[5].invoke(options) do |arg5|
100
- args[5] = arg5
101
- iterators[6].invoke(options) do |arg6|
102
- args[6] = arg6
103
- iterators[7].invoke(options) do |arg7|
104
- args[7] = arg7
105
- iterators[8].invoke(options) do |arg8|
106
- args[8] = arg8
107
- iterators[9].invoke(options) do |arg9|
108
- args[9] = arg9
109
- # Refresh the target to start all settings from scratch each time
110
- # This is an easy way to reset all registered values
111
- Origen.app.reload_target!(skip_first_time: true)
112
-
113
- # Final call back to the project to allow it to make any pattern name specific
114
- # configuration changes
115
- Origen.app.listeners_for(:before_pattern).each do |listener|
116
- listener.before_pattern(job.output_pattern_filename)
117
- end
78
+ # Refresh the target to start all settings from scratch each time
79
+ # This is an easy way to reset all registered values
80
+ Origen.app.reload_target!(skip_first_time: true)
118
81
 
119
- # Work out the final pattern name based on the current iteration
120
- job.reset_output_pattern_filename
121
- iterators.each_with_index do |iterator, i|
122
- if iterator.enabled?(options)
123
- job.output_pattern_filename =
124
- iterator.pattern_name.call(job.output_pattern_filename, args[i])
125
- end
126
- end
82
+ # Final call back to the project to allow it to make any pattern name specific
83
+ # configuration changes
84
+ Origen.app.listeners_for(:before_pattern).each do |listener|
85
+ listener.before_pattern(job.output_pattern_filename)
86
+ end
127
87
 
128
- # Allow custom pattern postfix
129
- unless options[:pat_postfix].to_s.empty?
130
- job.output_pattern_filename = job.output_pattern_filename.sub(job.output_postfix + job.output_extension, "_#{options[:pat_postfix]}" + job.output_postfix + job.output_extension)
131
- end
88
+ ## Allow custom pattern postfix
89
+ # unless options[:pat_postfix].to_s.empty?
90
+ # job.output_pattern_filename = job.output_pattern_filename.sub(job.output_postfix + job.output_extension, "_#{options[:pat_postfix]}" + job.output_postfix + job.output_extension)
91
+ # end
92
+
93
+ @pattern_sequence = true
94
+ pattern_wrapper([], [], options) do
95
+ PatternSequencer.send(:active=, true)
96
+ @pattern_sequence = PatternSequence.new(job.output_pattern_filename, block)
97
+ @pattern_sequence.send(:execute)
98
+ PatternSequencer.send(:active=, false)
99
+ end
100
+ @pattern_sequence = false
101
+ @create_options = nil
102
+ end
103
+
104
+ def create(options = {})
105
+ if @pattern_sequence
106
+ yield
107
+ else
108
+ @create_options = options
109
+ unless Origen.tester
110
+ puts 'The current target has not instantiated a tester and pattern generation cannot run.'
111
+ puts 'Add something like this to an environment file:'
112
+ puts
113
+ puts ' Origen::Tester::J750.new'
114
+ puts
115
+ puts
116
+ puts 'Then select it by running: origen e <environment name>'
117
+ exit 1
118
+ end
119
+ Origen.tester.generating = :pattern
120
+
121
+ job.output_file_body = options.delete(:name).to_s if options[:name]
122
+
123
+ # Order the iterators by the order that their enable keys appear in the options, pad
124
+ # any missing iterators with a dummy function...
125
+ iterators = options.map do |key, _val|
126
+ Origen.app.pattern_iterators.find { |iterator| iterator.key == key }
127
+ end.compact
128
+ iterators << DummyIterator.new while iterators.size < 10
129
+
130
+ args = []
131
+
132
+ # Couldn't get this to work fully dynamically, so hard-coded for 10 custom
133
+ # iterators for now, should be plenty for any application in the meantime.
134
+ # Should revisit this when time allows and remove this limitation by changing
135
+ # this to a recursive structure.
136
+ iterators[0].invoke(options) do |arg0|
137
+ args[0] = arg0
138
+ iterators[1].invoke(options) do |arg1|
139
+ args[1] = arg1
140
+ iterators[2].invoke(options) do |arg2|
141
+ args[2] = arg2
142
+ iterators[3].invoke(options) do |arg3|
143
+ args[3] = arg3
144
+ iterators[4].invoke(options) do |arg4|
145
+ args[4] = arg4
146
+ iterators[5].invoke(options) do |arg5|
147
+ args[5] = arg5
148
+ iterators[6].invoke(options) do |arg6|
149
+ args[6] = arg6
150
+ iterators[7].invoke(options) do |arg7|
151
+ args[7] = arg7
152
+ iterators[8].invoke(options) do |arg8|
153
+ args[8] = arg8
154
+ iterators[9].invoke(options) do |arg9|
155
+ args[9] = arg9
156
+ # Refresh the target to start all settings from scratch each time
157
+ # This is an easy way to reset all registered values
158
+ Origen.app.reload_target!(skip_first_time: true)
159
+
160
+ # Final call back to the project to allow it to make any pattern name specific
161
+ # configuration changes
162
+ Origen.app.listeners_for(:before_pattern).each do |listener|
163
+ listener.before_pattern(job.output_pattern_filename)
164
+ end
132
165
 
133
- pattern_wrapper(iterators, args, options) do
134
- # Call iterator setups, whatever these return are passed to the pattern
135
- yield_items = []
166
+ # Work out the final pattern name based on the current iteration
167
+ job.reset_output_pattern_filename
136
168
  iterators.each_with_index do |iterator, i|
137
169
  if iterator.enabled?(options)
138
- yield_items << iterator.setup.call(args[i])
170
+ job.output_pattern_filename =
171
+ iterator.pattern_name.call(job.output_pattern_filename, args[i])
172
+ end
173
+ end
174
+
175
+ # Allow custom pattern prefix
176
+ unless options[:pat_prefix].to_s.empty?
177
+ if job.output_prefix.empty?
178
+ job.output_pattern_filename = "#{options[:pat_prefix]}_" + job.output_pattern_filename
179
+ else
180
+ job.output_pattern_filename = job.output_pattern_filename.sub(job.output_prefix, job.output_prefix + "#{options[:pat_prefix]}_")
139
181
  end
140
182
  end
141
183
 
142
- yield(*yield_items)
184
+ # Allow custom pattern postfix
185
+ unless options[:pat_postfix].to_s.empty?
186
+ job.output_pattern_filename = job.output_pattern_filename.sub(job.output_postfix + job.output_extension, "_#{options[:pat_postfix]}" + job.output_postfix + job.output_extension)
187
+ end
188
+
189
+ pattern_wrapper(iterators, args, options) do
190
+ # Call iterator setups, whatever these return are passed to the pattern
191
+ yield_items = []
192
+ iterators.each_with_index do |iterator, i|
193
+ if iterator.enabled?(options)
194
+ yield_items << iterator.setup.call(args[i])
195
+ end
196
+ end
197
+
198
+ yield(*yield_items)
199
+ end
143
200
  end
144
201
  end
145
202
  end
@@ -363,9 +420,7 @@ module Origen
363
420
  unless job.test?
364
421
  File.delete(job.output_pattern) if File.exist?(job.output_pattern)
365
422
 
366
- if options[:inhibit]
367
- log.info "Generating... #{job.output_pattern_directory}/#{job.output_pattern_filename}".ljust(50)
368
- else
423
+ unless tester.try(:sim?)
369
424
  log.info "Generating... #{job.output_pattern_directory}/#{job.output_pattern_filename}".ljust(50)
370
425
  end
371
426
  end
@@ -459,11 +514,16 @@ module Origen
459
514
  end
460
515
  end
461
516
 
462
- log.info ' '
463
- log.info "Pattern vectors: #{stats.number_of_vectors_for(job.output_pattern).to_s.ljust(10)}"
464
- log.info 'Execution time'.ljust(15) + ': %.6f' % stats.execution_time_for(job.output_pattern)
465
- log.info '----------------------------------------------------------------------'
466
- check_for_changes(job.output_pattern, job.reference_pattern) unless tester.try(:disable_pattern_diffs)
517
+ unless tester.try(:sim?)
518
+ log.info ' '
519
+ log.info "Pattern vectors: #{stats.number_of_vectors_for(job.output_pattern).to_s.ljust(10)}"
520
+ log.info 'Execution time'.ljust(15) + ': %.6f' % stats.execution_time_for(job.output_pattern)
521
+ log.info '----------------------------------------------------------------------'
522
+ check_for_changes(job.output_pattern, job.reference_pattern) unless tester.try(:disable_pattern_diffs)
523
+ end
524
+ if @pattern_sequence
525
+ @pattern_sequence.send(:log_execution_profile)
526
+ end
467
527
  stats.record_pattern_completion(job.output_pattern)
468
528
  end
469
529
 
@@ -95,10 +95,10 @@ module Origen
95
95
  matches = Dir.glob("#{current_plugin_pattern_path}/**/#{name}.rb").sort
96
96
  # If the current plugin does not include the pattern then look into the current app
97
97
  if matches.size == 0
98
- matches = Dir.glob("#{pattern_directory}/**/#{name}.rb").sort # <= this does not include symlinks
98
+ matches = Dir.glob(["#{pattern_directory}/**/#{name}.rb", "#{Origen.root}/app/patterns/**/#{name}.rb"]).sort # <= this does not include symlinks
99
99
  end
100
100
  else
101
- matches = Dir.glob("#{pattern_directory}/**/#{name}.rb").sort # <= this does not include symlinks
101
+ matches = Dir.glob(["#{pattern_directory}/**/#{name}.rb", "#{Origen.root}/app/patterns/**/#{name}.rb"]).sort # <= this does not include symlinks
102
102
  end
103
103
 
104
104
  matches
@@ -114,7 +114,7 @@ module Origen
114
114
 
115
115
  def all_matches(name)
116
116
  name = name.gsub(/\..*$/, '')
117
- matches = Dir.glob("#{pattern_directory}/**{,/*/**}/#{name}.rb").sort # Takes symlinks into consideration
117
+ matches = Dir.glob(["#{pattern_directory}/**{,/*/**}/#{name}.rb", "#{Origen.root}/app/patterns/**{,/*/**}/#{name}.rb"]).sort # Takes symlinks into consideration
118
118
  matches.flatten.uniq
119
119
  end
120
120
 
@@ -0,0 +1,201 @@
1
+ require 'io/console'
2
+
3
+ module Origen
4
+ class Generator
5
+ # Manages a single pattern sequence, i.e. an instance of PatternSequence is
6
+ # created for every Pattern.sequence do ... end block
7
+ class PatternSequence
8
+ def initialize(name, block)
9
+ @number_of_threads = 1
10
+ @name = name
11
+ @running_thread_ids = { main: true }
12
+ # The contents of the main Pattern.sequence block will be executed as a thread and treated
13
+ # like any other parallel block
14
+ thread = PatternThread.new(:main, self, block, true)
15
+ threads << thread
16
+ active_threads << thread
17
+ end
18
+
19
+ # Execute the given pattern
20
+ def run(pattern_name)
21
+ pattern = Origen.generator.pattern_finder.find(pattern_name.to_s, {})
22
+ pattern = pattern[:pattern] if pattern.is_a?(Hash)
23
+ load pattern
24
+ end
25
+ alias_method :call, :run
26
+
27
+ # Execute the given block in a new concurrent thread
28
+ def thread(id = nil, &block)
29
+ @number_of_threads += 1
30
+ id ||= "thread#{@number_of_threads}".to_sym
31
+ # Just stage the request for now, it will be started at the end of the current execute loop
32
+ @parallel_blocks_waiting_to_start ||= []
33
+ @parallel_blocks_waiting_to_start << [id, block]
34
+ @running_thread_ids[id] = true
35
+ end
36
+ alias_method :in_parallel, :thread
37
+
38
+ def wait_for_threads(*ids)
39
+ completed = false
40
+ blocked = false
41
+ ids = ids.map(&:to_sym)
42
+ all = ids.empty? || ids.include?(:all)
43
+ until completed
44
+ if all
45
+ limit = current_thread.id == :main ? 1 : 2
46
+ if @running_thread_ids.size > limit
47
+ current_thread.waiting_for_thread(blocked)
48
+ blocked = true
49
+ else
50
+ current_thread.record_active if blocked
51
+ completed = true
52
+ end
53
+ else
54
+ if ids.any? { |id| @running_thread_ids[id] }
55
+ current_thread.waiting_for_thread(blocked)
56
+ blocked = true
57
+ else
58
+ current_thread.record_active if blocked
59
+ completed = true
60
+ end
61
+ end
62
+ end
63
+ end
64
+ alias_method :wait_for_thread, :wait_for_threads
65
+
66
+ private
67
+
68
+ def thread_running?(id)
69
+ @running_thread_ids[id]
70
+ end
71
+
72
+ def current_thread
73
+ PatSeq.thread
74
+ end
75
+
76
+ def log_execution_profile
77
+ if threads.size > 1
78
+ thread_id_size = threads.map { |t| t.id.to_s.size }.max
79
+ line_size = IO.console.winsize[1] - 35 - thread_id_size
80
+ line_size -= 16 if tester.try(:sim?)
81
+ cycles_per_tick = (@cycle_count_stop / (line_size * 1.0)).ceil
82
+ if tester.try(:sim?)
83
+ execution_time = tester.execution_time_in_ns / 1_000_000_000.0
84
+ else
85
+ execution_time = Origen.app.stats.execution_time_for(Origen.app.current_job.output_pattern)
86
+ end
87
+ Origen.log.info ''
88
+ tick_time = execution_time / line_size
89
+
90
+ Origen.log.info "Concurrent execution profile (#{pretty_time(tick_time)}/increment):"
91
+ Origen.log.info
92
+
93
+ number_of_ticks = @cycle_count_stop / cycles_per_tick
94
+
95
+ ticks_per_step = 0
96
+ step_size = 0.1.us
97
+
98
+ while ticks_per_step < 10
99
+ step_size = step_size * 10
100
+ ticks_per_step = step_size / tick_time
101
+ end
102
+
103
+ ticks_per_step = ticks_per_step.ceil
104
+ step_size = tick_time * ticks_per_step
105
+
106
+ if tester.try(:sim?)
107
+ padding = '.' + (' ' * (thread_id_size + 1))
108
+ else
109
+ padding = ' ' * (thread_id_size + 2)
110
+ end
111
+ scale_step = '|' + ('-' * (ticks_per_step - 1))
112
+ number_of_steps = (number_of_ticks / ticks_per_step) + 1
113
+ scale = scale_step * number_of_steps
114
+ scale = scale[0, number_of_ticks]
115
+ Origen.log.info padding + scale
116
+
117
+ scale = ''
118
+ number_of_steps.times do |i|
119
+ scale += pretty_time(i * step_size, 1).ljust(ticks_per_step)
120
+ end
121
+ scale = scale[0, number_of_ticks]
122
+ Origen.log.info padding + scale
123
+
124
+ threads.each do |thread|
125
+ line = thread.execution_profile(0, @cycle_count_stop, cycles_per_tick)
126
+ Origen.log.info ''
127
+ Origen.log.info "#{thread.id}: ".ljust(thread_id_size + 2) + line
128
+ end
129
+ Origen.log.info ''
130
+ end
131
+ end
132
+
133
+ def pretty_time(time, number_decimal_places = 0)
134
+ return '0' if time == 0
135
+ if time < 1.us
136
+ "%.#{number_decimal_places}fns" % (time * 1_000_000_000)
137
+ elsif time < 1.ms
138
+ "%.#{number_decimal_places}fus" % (time * 1_000_000)
139
+ elsif time < 1.s
140
+ "%.#{number_decimal_places}fms" % (time * 1_000)
141
+ else
142
+ "%.#{number_decimal_places}fs" % tick_time
143
+ end
144
+ end
145
+
146
+ def thread_completed(thread)
147
+ @running_thread_ids.delete(thread.id)
148
+ active_threads.delete(thread)
149
+ end
150
+
151
+ def threads
152
+ @threads ||= []
153
+ end
154
+
155
+ def active_threads
156
+ @active_threads ||= []
157
+ end
158
+
159
+ def threads_waiting_to_start?
160
+ @parallel_blocks_waiting_to_start
161
+ end
162
+
163
+ def execute
164
+ active_threads.first.start
165
+ until active_threads.empty?
166
+ # Advance all threads to their next cycle point in sequential order. Keeping tight control of
167
+ # when threads are running in this way ensures that the output is deterministic no matter what
168
+ # computer it is running on, and ensures that the application code does not have to worry about
169
+ # race conditions.
170
+ cycs = active_threads.map do |t|
171
+ t.advance
172
+ t.pending_cycles
173
+ end.compact.min
174
+
175
+ if cycs
176
+ # Now generate the required number of cycles which is defined by the thread that has the least
177
+ # amount of cycles ready to go.
178
+ # Since tester.cycle is being called by the master process here it will generate as normal (as
179
+ # opposed to when called from a thread in which case it causes the thread to wait).
180
+ cycs.cycles
181
+
182
+ # Now let each thread know how many cycles we just generated, so they can decide whether they
183
+ # need to wait for more cycles or if they can start preparing the next one
184
+ active_threads.each { |t| t.executed_cycles(cycs) }
185
+ end
186
+
187
+ if @parallel_blocks_waiting_to_start
188
+ @parallel_blocks_waiting_to_start.each do |id, block|
189
+ thread = PatternThread.new(id, self, block)
190
+ threads << thread
191
+ active_threads << thread
192
+ thread.start
193
+ end
194
+ @parallel_blocks_waiting_to_start = nil
195
+ end
196
+ end
197
+ @cycle_count_stop = threads.first.current_cycle_count
198
+ end
199
+ end
200
+ end
201
+ end