origen 0.44.0 → 0.50.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/config/application.rb +2 -2
  3. data/config/boot.rb +0 -7
  4. data/config/commands.rb +3 -74
  5. data/config/rubocop/easy_disabled.yml +4 -0
  6. data/config/rubocop/easy_enabled.yml +0 -4
  7. data/config/rubocop/strict_disabled.yml +4 -0
  8. data/config/rubocop/strict_enabled.yml +0 -4
  9. data/config/version.rb +1 -2
  10. data/lib/origen/application/deployer.rb +3 -1
  11. data/lib/origen/application/release.rb +2 -2
  12. data/lib/origen/application/runner.rb +9 -2
  13. data/lib/origen/application.rb +91 -2
  14. data/lib/origen/boot/app.rb +0 -4
  15. data/lib/origen/boot.rb +2 -1
  16. data/lib/origen/code_generators/actions.rb +244 -34
  17. data/lib/origen/code_generators/base.rb +9 -2
  18. data/lib/origen/code_generators/block.rb +203 -0
  19. data/lib/origen/code_generators/block_common.rb +100 -0
  20. data/lib/origen/code_generators/dut.rb +62 -0
  21. data/lib/origen/code_generators/feature.rb +50 -0
  22. data/lib/origen/code_generators/klass.rb +41 -0
  23. data/lib/origen/code_generators/model.rb +60 -0
  24. data/lib/origen/code_generators/module.rb +92 -0
  25. data/lib/origen/code_generators.rb +30 -10
  26. data/lib/origen/commands/lint.rb +6 -1
  27. data/lib/origen/commands/new.rb +1 -1
  28. data/lib/origen/commands/new_resource.rb +41 -0
  29. data/lib/origen/commands/web.rb +11 -6
  30. data/lib/origen/commands.rb +18 -0
  31. data/lib/{option_parser → origen/core_ext/option_parser}/optparse.rb +0 -0
  32. data/lib/origen/dependencies.rb +0 -0
  33. data/lib/origen/file_handler.rb +8 -4
  34. data/lib/origen/generator/pattern_finder.rb +3 -3
  35. data/lib/origen/loader.rb +377 -0
  36. data/lib/origen/model.rb +22 -1
  37. data/lib/origen/model_initializer.rb +5 -1
  38. data/lib/origen/parameters/set.rb +2 -1
  39. data/lib/origen/parameters.rb +95 -3
  40. data/lib/origen/sub_blocks.rb +21 -7
  41. data/lib/origen/top_level.rb +11 -0
  42. data/lib/origen.rb +3 -1
  43. data/origen_app_generators/Gemfile +6 -2
  44. data/origen_app_generators/Gemfile.lock +83 -72
  45. data/origen_app_generators/bin/boot.rb +4 -2
  46. data/origen_app_generators/config/commands.rb +3 -3
  47. data/origen_app_generators/config/shared_commands.rb +11 -6
  48. data/origen_app_generators/lbin/bundle +105 -0
  49. data/origen_app_generators/lbin/byebug +29 -0
  50. data/origen_app_generators/lbin/coderay +29 -0
  51. data/origen_app_generators/lbin/htmldiff +29 -0
  52. data/origen_app_generators/lbin/httparty +29 -0
  53. data/origen_app_generators/lbin/httpclient +29 -0
  54. data/origen_app_generators/lbin/kramdown +29 -0
  55. data/origen_app_generators/lbin/ldiff +29 -0
  56. data/origen_app_generators/lbin/nanoc +29 -0
  57. data/origen_app_generators/lbin/nokogiri +29 -0
  58. data/origen_app_generators/lbin/origen +62 -0
  59. data/origen_app_generators/lbin/pry +29 -0
  60. data/origen_app_generators/lbin/rackup +29 -0
  61. data/origen_app_generators/lbin/rake +29 -0
  62. data/origen_app_generators/lbin/rspec +29 -0
  63. data/origen_app_generators/lbin/rubocop +29 -0
  64. data/origen_app_generators/lbin/ruby-parse +29 -0
  65. data/origen_app_generators/lbin/ruby-rewrite +29 -0
  66. data/origen_app_generators/lbin/thor +29 -0
  67. data/origen_app_generators/lbin/tilt +29 -0
  68. data/origen_app_generators/lbin/yard +29 -0
  69. data/origen_app_generators/lbin/yardoc +29 -0
  70. data/origen_app_generators/lbin/yri +29 -0
  71. data/origen_app_generators/lib/origen_app_generators/application.rb +12 -12
  72. data/origen_app_generators/lib/origen_app_generators/base.rb +34 -8
  73. data/origen_app_generators/lib/origen_app_generators/new.rb +17 -9
  74. data/origen_app_generators/lib/{tasks/new_app_tests.rake → origen_app_generators/new_app_tests.rb} +1 -5
  75. data/origen_app_generators/lib/origen_app_generators/origen_infrastructure/app_generator_plugin.rb +6 -8
  76. data/origen_app_generators/lib/origen_app_generators/plugin.rb +4 -7
  77. data/origen_app_generators/lib/origen_app_generators/test_engineering/common.rb +29 -0
  78. data/origen_app_generators/lib/origen_app_generators/test_engineering/stand_alone_application.rb +9 -181
  79. data/origen_app_generators/lib/origen_app_generators/test_engineering/test_block.rb +4 -105
  80. data/origen_app_generators/lib/origen_app_generators.rb +6 -4
  81. data/origen_app_generators/origen_app_generators.gemspec +7 -7
  82. data/origen_app_generators/templates/app_generators/application/Gemfile +14 -3
  83. data/origen_app_generators/templates/app_generators/application/{lib → app/blocks}/top_level.rb +1 -1
  84. data/origen_app_generators/templates/app_generators/application/app/lib/module.rb +6 -0
  85. data/origen_app_generators/templates/app_generators/application/{templates → app/templates}/web/index.md.erb +0 -0
  86. data/origen_app_generators/templates/app_generators/application/{templates → app/templates}/web/layouts/_basic.html.erb +0 -0
  87. data/origen_app_generators/templates/app_generators/application/{templates → app/templates}/web/partials/_navbar.html.erb +0 -0
  88. data/origen_app_generators/templates/app_generators/application/{templates → app/templates}/web/release_notes.md.erb +0 -0
  89. data/origen_app_generators/templates/app_generators/application/config/application.rb +51 -55
  90. data/origen_app_generators/templates/app_generators/application/{spec → test/spec}/spec_helper.rb +0 -0
  91. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/{lib → app/lib}/application.rb +0 -0
  92. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/{lib → app/lib}/base.rb +0 -0
  93. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/{lib → app/lib}/module.rb +0 -0
  94. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/{lib → app/lib}/plugin.rb +0 -0
  95. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/config/load_generators.rb +1 -1
  96. data/origen_app_generators/templates/app_generators/plugin/Gemfile +5 -2
  97. data/origen_app_generators/templates/app_generators/plugin/{templates → app/templates}/web/index.md.erb +0 -0
  98. data/origen_app_generators/templates/app_generators/plugin/{templates → app/templates}/web/partials/_navbar_external.html.erb +0 -0
  99. data/origen_app_generators/templates/app_generators/plugin/{templates → app/templates}/web/partials/_navbar_internal.html.erb +0 -0
  100. data/origen_app_generators/templates/app_generators/plugin/gemspec.rb +4 -3
  101. data/origen_app_generators/templates/app_generators/test_engineering/{stand_alone_application/environment → environment}/j750.rb +0 -0
  102. data/origen_app_generators/templates/app_generators/test_engineering/{stand_alone_application/environment → environment}/uflex.rb +0 -0
  103. data/origen_app_generators/templates/app_generators/test_engineering/{stand_alone_application/environment → environment}/v93k.rb +0 -0
  104. data/origen_site_config.yml +0 -7
  105. data/templates/code_generators/attributes.rb +20 -0
  106. data/templates/code_generators/class.rb +9 -0
  107. data/templates/code_generators/controller.rb +87 -0
  108. data/templates/code_generators/model.rb +21 -0
  109. data/templates/code_generators/module.rb +4 -0
  110. data/templates/code_generators/parameters.rb +19 -0
  111. data/templates/code_generators/pins.rb +28 -0
  112. data/templates/code_generators/registers.rb +20 -0
  113. data/templates/code_generators/sub_blocks.rb +24 -0
  114. data/templates/code_generators/timesets.rb +24 -0
  115. data/templates/code_generators/version.rb +0 -1
  116. metadata +66 -77
  117. data/lib/c99/ate_interface.rb +0 -77
  118. data/lib/c99/nvm.rb +0 -110
  119. data/lib/c99/target/mock2.rb +0 -1
  120. data/lib/c99/target/subdir/mock3.rb +0 -1
  121. data/lib/origen/code_generators/bundler.rb +0 -17
  122. data/lib/origen/code_generators/gem_setup.rb +0 -49
  123. data/lib/origen/code_generators/rake.rb +0 -13
  124. data/lib/origen/code_generators/rspec.rb +0 -12
  125. data/lib/origen/commands/add.rb +0 -12
  126. data/lib/tasks/private/build.rake +0 -8
  127. data/origen_app_generators/bin/fix_my_workspace +0 -100
  128. data/origen_app_generators/lib/origen_app_generators/sub_block_parser.rb +0 -81
  129. data/origen_app_generators/lib/tasks/app_generators.rake +0 -6
  130. data/origen_app_generators/spec/sub_block_spec.rb +0 -36
  131. data/origen_app_generators/templates/app_generators/application/lib/app.rake +0 -6
  132. data/origen_app_generators/templates/app_generators/application/lib/module.rb +0 -22
  133. data/origen_app_generators/templates/app_generators/plugin/lib/README +0 -4
  134. data/origen_app_generators/templates/app_generators/plugin/lib_dev/README +0 -5
  135. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/Gemfile +0 -23
  136. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/jlink.rb +0 -1
  137. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/ip_block.rb +0 -23
  138. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/ip_block_controller.rb +0 -5
  139. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/top_level.rb +0 -33
  140. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/top_level_controller.rb +0 -21
  141. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/pattern/example.rb +0 -4
  142. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/target/top_level.rb +0 -4
  143. data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/j750.rb +0 -2
  144. data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/ultraflex.rb +0 -2
  145. data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/v93k.rb +0 -2
  146. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/controller.rb +0 -12
  147. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/interface.rb +0 -21
  148. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/model.rb +0 -18
  149. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib_dev/dut.rb +0 -27
  150. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib_dev/dut_controller.rb +0 -26
  151. data/origen_app_generators/templates/app_generators/test_engineering/test_block/pattern/example.rb +0 -5
  152. data/origen_app_generators/templates/app_generators/test_engineering/test_block/program/prb1.rb +0 -11
  153. data/origen_app_generators/templates/app_generators/test_engineering/test_block/target/default.rb +0 -2
  154. data/templates/code_generators/gemfile_app.rb +0 -4
  155. data/templates/code_generators/gemfile_plugin.rb +0 -6
  156. data/templates/code_generators/gemspec.rb +0 -33
  157. data/templates/code_generators/rakefile.rb +0 -10
  158. data/templates/code_generators/spec_helper.rb +0 -49
@@ -0,0 +1,377 @@
1
+ module Origen
2
+ # This module is responsible for enhancing how Ruby requires and loads files to support loading of
3
+ # classes and modules from an application's app dir without having to require them.
4
+ #
5
+ # It also implements the <model>.load_block method that loads files from app/blocks.
6
+ module Loader
7
+ # @api private
8
+ #
9
+ # Unload all constants (classes and modules) that have been auto-loaded since this was last called
10
+ def self.unload
11
+ # puts "******** LOADED CONSTS@ #{@loaded_consts}"
12
+ path = []
13
+ (@consts_hierarchy || {}).each do |name, children|
14
+ _unload(path, name, children)
15
+ end
16
+ @consts_hierarchy = {}
17
+ @loaded_consts = {}
18
+ (Origen.app.plugins + [Origen.app]).each do |app|
19
+ app.instance_variable_set(:@blocks_files, nil)
20
+ end
21
+ nil
22
+ end
23
+
24
+ # @api private
25
+ def self._unload(path, name, children)
26
+ path << name
27
+ children.each do |name, children|
28
+ _unload(path, name, children)
29
+ end
30
+ const = path.join('::')
31
+ if @loaded_consts[const]
32
+ path[0...-1].join('::').constantize.send :remove_const, path.last
33
+ # puts "******** Unloading: #{const}"
34
+ end
35
+ path.pop
36
+ end
37
+
38
+ # @api private
39
+ def self.record_const(name)
40
+ @consts_hierarchy ||= {}
41
+ @loaded_consts ||= {}
42
+ @loaded_consts[name] = true
43
+ pointer = nil
44
+ name.split('::').each do |name|
45
+ if pointer
46
+ pointer[name] ||= {}
47
+ pointer = pointer[name]
48
+ else
49
+ @consts_hierarchy[name] ||= {}
50
+ pointer = @consts_hierarchy[name]
51
+ end
52
+ end
53
+ end
54
+
55
+ # @api private
56
+ def self.load_attributes(file, model)
57
+ if model.respond_to?(:is_an_origen_model?)
58
+ attributes = model.attributes.dup
59
+ else
60
+ attributes = {}
61
+ end
62
+ vars = model.instance_variables
63
+ if load_block_file(file, model)
64
+ # Update the value of any pre-existing attribute that could have just changed
65
+ attributes.each do |a, v|
66
+ attributes[a] = model.instance_variable_get("@#{a}")
67
+ end
68
+ # And add any new ones that were encountered for the first time
69
+ (model.instance_variables - vars).each do |var|
70
+ val = model.instance_variable_get(var)
71
+ attribute = var.to_s.sub('@', '')
72
+ attributes[attribute.to_sym] = val
73
+ unless model.respond_to?(attribute)
74
+ model.define_singleton_method(attribute) do
75
+ instance_variable_get(var)
76
+ end
77
+ end
78
+ if val == true || val == false
79
+ attribute += '?'
80
+ unless model.respond_to?(attribute)
81
+ model.define_singleton_method(attribute) do
82
+ instance_variable_get(var)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ if model.respond_to?(:is_an_origen_model?)
88
+ attributes.freeze
89
+ model.instance_variable_set(:@attributes, attributes)
90
+ end
91
+ true
92
+ end
93
+ end
94
+
95
+ # @api private
96
+ def self.load_block_file(file, model)
97
+ e = File.exist?(file.to_s)
98
+ model.instance_eval(file.read, file.to_s) if e
99
+ true
100
+ end
101
+
102
+ # @api private
103
+ def self.with_parameters_transaction(type)
104
+ if type == :parameters
105
+ Origen::Parameters.transaction do
106
+ yield
107
+ end
108
+ else
109
+ yield
110
+ end
111
+ end
112
+
113
+ # If a block definition exists for the given model, then this will load it and apply it to
114
+ # the model.
115
+ # Returns true if a model is found and loaded, otherwise nil.
116
+ def self.load_block(model, options = {})
117
+ model = model.model # Ensure we have a handle on the model and not its controller
118
+ loaded = nil
119
+ if app = options[:app] || model.app
120
+ if options[:path]
121
+ full_paths = Array(options[:path])
122
+ else
123
+ full_paths = model.class.to_s.split('::')
124
+ full_paths.shift # Throw away the app namespace
125
+ full_paths = [full_paths.join('/')]
126
+ end
127
+ full_paths.each do |full_path|
128
+ paths = full_path.to_s.split('/')
129
+ key = ''
130
+ only = Array(options[:only]) if options[:only]
131
+ except = Array(options[:except]) if options[:except]
132
+ path = paths.map(&:underscore).join('/')
133
+ # If the path refers to a nested sub-block then don't load the full hierarchy since they
134
+ # don't support inheritance or derivatives, modify the paths array so that only the sub-block
135
+ # level will be loaded and nothing else.
136
+ paths = [path] if app.blocks_files[path] && app.blocks_files[path][:_sub_block]
137
+ # These will be loaded first, followed by the rest in an undefined order.
138
+ # Attributes and parameters are first so that they may be referenced in the other files.
139
+ # Sub-blocks was added early due to a corner case issue that could be encountered if the pins or
140
+ # regs imported an Origen exported file that defined a module with the same name as a sub-block
141
+ # class, in that case the sub-block class would not be auto-loaded.
142
+ load_first = [:attributes, :parameters, :sub_blocks]
143
+
144
+ load_first.each do |type|
145
+ unless (only && !only.include?(type)) || (except && except.include?(type))
146
+ with_parameters_transaction(type) do
147
+ paths.each_with_index do |path, i|
148
+ key = i == 0 ? path.underscore : "#{key}/#{path.underscore}"
149
+ if app.blocks_files[key] && app.blocks_files[key][type]
150
+ app.blocks_files[key][type].each do |f|
151
+ if type == :attributes
152
+ success = load_attributes(f, model)
153
+ else
154
+ success = load_block_file(f, model)
155
+ end
156
+ loaded ||= success
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ # Now load the rest
165
+ paths.each_with_index do |path, i|
166
+ key = i == 0 ? path.underscore : "#{key}/#{path.underscore}"
167
+ if app.blocks_files[key]
168
+ app.blocks_files[key].each do |type, files|
169
+ unless type == :_sub_block || load_first.include?(type) || (only && !only.include?(type)) || (except && except.include?(type))
170
+ files.each { |f| success = load_block_file(f, model); loaded ||= success }
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ loaded
178
+ end
179
+
180
+ # This is inspired by Rails' ActiveSupport::Dependencies module.
181
+ module ModuleConstMissing
182
+ def self.append_features(base)
183
+ base.class_eval do
184
+ # Emulate #exclude via an ivar
185
+ return if defined?(@_const_missing) && @_const_missing
186
+ @_const_missing = instance_method(:const_missing)
187
+ remove_method(:const_missing)
188
+ end
189
+ super
190
+ end
191
+
192
+ def self.exclude_from(base)
193
+ base.class_eval do
194
+ define_method :const_missing, @_const_missing
195
+ @_const_missing = nil
196
+ end
197
+ end
198
+
199
+ # @api private
200
+ # Substitutes a single occurrence of 'derivatives' in the given dirs array, starting
201
+ # from the end of it and replacing it with the given new value.
202
+ # Returns true if a substitution is made, else false.
203
+ def _sub_derivatives_from_end(new_val, dirs)
204
+ subbed = false
205
+ size = dirs.size - 1
206
+ dirs.reverse_each.with_index do |val, i|
207
+ if val == 'derivatives'
208
+ dirs[size - i] = new_val
209
+ subbed = true
210
+ break
211
+ end
212
+ end
213
+ dirs if subbed
214
+ end
215
+
216
+ # Allows classes and modules to be defined in app/blocks and app/lib without needing to
217
+ # require them and in the case of app/blocks to use a custom directory structure.
218
+ #
219
+ # The first time a reference is made to a class or module name it will trigger this hook,
220
+ # and we then work out what the file name should be and require it.
221
+ def const_missing(name)
222
+ if Origen.in_app_workspace?
223
+ if self == Object
224
+ name = name.to_s
225
+ else
226
+ name = "#{self}::#{name}"
227
+ end
228
+ return nil if @_checking_name == name
229
+ names = name.split('::')
230
+ namespace = names.shift
231
+ if app = Origen::Application.from_namespace(namespace)
232
+ # First we are going to check for a match in the app/blocks directory, this needs to be handled
233
+ # specially since it follows a non-std structure, e.g. use of derivatives/ and sub_blocks/ folders
234
+ # for organization without having them as part of the class name-spacing
235
+ altname = nil
236
+ dirs = [app.root, 'app', 'blocks']
237
+ names.each_with_index do |name, i|
238
+ dirs << 'derivatives' unless i == 0
239
+ dirs << name.underscore
240
+ end
241
+
242
+ # Is this a reference to a model?
243
+ if File.exist?(f = File.join(*dirs, 'model.rb'))
244
+ model = _load_const(f, name)
245
+ # Also load the model's controller if it exists
246
+ if File.exist?(f = File.join(*dirs, 'controller.rb'))
247
+ controller = _load_const(f, name + 'Controller')
248
+ end
249
+ return model
250
+ end
251
+
252
+ # Is this a reference to a controller?
253
+ if dirs.last.to_s =~ /_controller$/
254
+ controller_reference = true
255
+ dirs << dirs.pop.sub(/_controller$/, '')
256
+ if File.exist?(f = File.join(*dirs, 'controller.rb'))
257
+ return _load_const(f, name)
258
+ end
259
+ end
260
+
261
+ # Is this a reference to a sub-block model or controller that is nested within a block?
262
+ dirs_ = dirs.dup
263
+ while dirs_ = _sub_derivatives_from_end('sub_blocks', dirs_)
264
+ if controller_reference
265
+ if File.exist?(f = File.join(*dirs_, 'controller.rb'))
266
+ return _load_const(f, name)
267
+ end
268
+ elsif File.exist?(f = File.join(*dirs_, 'model.rb'))
269
+ model = _load_const(f, name)
270
+ # Also load the model's controller if it exists
271
+ if File.exist?(f = File.join(*dirs_, 'controller.rb'))
272
+ controller = _load_const(f, name + 'Controller')
273
+ end
274
+ return model
275
+ end
276
+ end
277
+
278
+ # Is this a reference to a module that has been added to a model or controller?
279
+ # In this case dirs contains something like:
280
+ # [..., "my_model", "derivatives", "my_module"]
281
+ # [..., "my_model_controller", "derivatives", "my_module"]
282
+ # So let's try by transforming these into:
283
+ # [..., "my_model", "model"] + "my_module.rb"
284
+ # [..., "my_model", "controller"] + "my_module.rb"
285
+ filename = dirs.pop + '.rb'
286
+ dirs.pop # Lose 'derivatives'
287
+ if dirs.last.to_s =~ /_controller$/
288
+ dirs << dirs.pop.sub(/_controller$/, '')
289
+ dirs << 'controller'
290
+ else
291
+ dirs << 'model'
292
+ end
293
+ if File.exist?(f = File.join(*dirs, filename))
294
+ return _load_const(f, name)
295
+ end
296
+
297
+ # Now that we have established that it is not a reference to a block (which has a non-std code
298
+ # organization structure), we can now check for a match in the app/lib directory following std
299
+ # Ruby code organization conventions
300
+ until names.empty?
301
+ path = File.join(*names.map(&:underscore)) + '.rb'
302
+
303
+ f = File.join(app.root, 'app', 'lib', namespace.underscore, path)
304
+ if File.exist?(f)
305
+ model = _load_const(f, name, altname)
306
+ # Try and reference the controller to load it too, though don't raise an error if it
307
+ # doesn't exist
308
+ @@pre_loading_controller = true
309
+ eval "#{altname || name}Controller"
310
+ return model
311
+ # If a folder exists that is named after this constant, then assume it is an otherwise
312
+ # undeclared namespace module and declare it now
313
+ elsif File.exist?(f.sub('.rb', ''))
314
+ return const_set path.sub('.rb', '').camelcase, Module.new
315
+ end
316
+
317
+ # Don't waste time looking up the namespace hierarchy for the controller, if it exists it
318
+ # should be within the exact same namespace as the model
319
+ return nil if defined?(@@pre_loading_controller) && @@pre_loading_controller
320
+
321
+ # Remove the highest level namespace and then search again in the parent namespace
322
+ if discarded_namespace = names.delete_at(-2)
323
+ altname ||= name
324
+ altname = altname.sub("#{discarded_namespace}::", '')
325
+ else
326
+ names.pop
327
+ end
328
+ end
329
+
330
+ _raise_uninitialized_constant_error(name)
331
+ else
332
+ _raise_uninitialized_constant_error(name)
333
+ end
334
+ else
335
+ _raise_uninitialized_constant_error(name)
336
+ end
337
+ ensure
338
+ @@pre_loading_controller = false
339
+ end
340
+
341
+ # @api_private
342
+ def _load_const(file, name, altname = nil)
343
+ load file
344
+ if defined?(@@pre_loading_controller)
345
+ return if @@pre_loading_controller
346
+ end
347
+ @_checking_name = altname || name
348
+ const = eval(altname || name)
349
+ @_checking_name = nil
350
+ if const
351
+ Origen::Loader.record_const(altname || name)
352
+ return const
353
+ end
354
+ msg ||= "uninitialized constant #{name} (expected it to be defined in: #{file})"
355
+ _raise_uninitialized_constant_error(name, msg)
356
+ end
357
+
358
+ # @api private
359
+ def _raise_uninitialized_constant_error(name, msg = nil)
360
+ msg ||= "uninitialized constant #{name}"
361
+ name_error = NameError.new(msg, name)
362
+ name_error.set_backtrace(caller.reject { |l| l =~ /^#{__FILE__}/ })
363
+ fail name_error
364
+ end
365
+ end
366
+
367
+ def self.enable_origen_load_extensions!
368
+ Module.class_eval { include ModuleConstMissing }
369
+ end
370
+
371
+ def self.disable_origen_load_extensions!
372
+ ModuleConstMissing.exclude_from(Module)
373
+ end
374
+ end
375
+ end
376
+
377
+ Origen::Loader.enable_origen_load_extensions!
data/lib/origen/model.rb CHANGED
@@ -43,6 +43,12 @@ module Origen
43
43
  end
44
44
  end
45
45
 
46
+ # Returns a frozen hash containing any attributes that were
47
+ # derived from a block definition
48
+ def attributes
49
+ @attributes ||= {}.freeze
50
+ end
51
+
46
52
  def inspect
47
53
  if controller
48
54
  "<Model/Controller: #{self.class}:#{object_id}/#{controller.class}:#{controller.object_id}>"
@@ -63,7 +69,7 @@ module Origen
63
69
 
64
70
  # Returns true if the model is the current DUT/top-level model
65
71
  def is_top_level?
66
- Origen.top_level == self
72
+ respond_to?(:includes_origen_top_level?)
67
73
  end
68
74
  alias_method :is_dut?, :is_top_level?
69
75
  alias_method :top_level?, :is_top_level?
@@ -75,6 +81,21 @@ module Origen
75
81
  self
76
82
  end
77
83
 
84
+ # Returns the application instance that defines the model, often the current app but it could
85
+ # also be one of the plugins.
86
+ # Returns nil if the application cannot be resolved, usually because the model's class has
87
+ # not been correctly namespaced.
88
+ def app
89
+ @app ||= Origen::Application.from_namespace(self.class.to_s)
90
+ end
91
+
92
+ # Load the block definitions from the given path to the model.
93
+ # Returns true if a block is found and loaded, otherwise nil.
94
+ def load_block(path, options = {})
95
+ options[:path] = path
96
+ Origen::Loader.load_block(self, options)
97
+ end
98
+
78
99
  def ==(obj)
79
100
  if obj.is_a?(Origen::SubBlocks::Placeholder)
80
101
  obj = obj.materialize
@@ -46,7 +46,10 @@ module Origen
46
46
  else
47
47
  x.send(:initialize, *args, &block)
48
48
  end
49
- x.send(:_initialized) if x.respond_to?(:is_an_origen_model?)
49
+ if x.respond_to?(:is_an_origen_model?)
50
+ x.send(:_initialized)
51
+ Origen::Loader.load_block(x)
52
+ end
50
53
  if x.respond_to?(:register_callback_listener)
51
54
  Origen.after_app_loaded do |app|
52
55
  x.register_callback_listener
@@ -55,6 +58,7 @@ module Origen
55
58
  # Do this before wrapping, otherwise the respond to method in the controller will
56
59
  # be looking for the model to be instantiated when it is not fully done yet
57
60
  is_top_level = x.respond_to?(:includes_origen_top_level?)
61
+
58
62
  if x.respond_to?(:wrap_in_controller)
59
63
  x = x.wrap_in_controller
60
64
  end
@@ -21,7 +21,7 @@ module Origen
21
21
  @defining = true
22
22
  yield self, parent
23
23
  @defining = false
24
- finalize
24
+ finalize unless Origen::Parameters.transaction_open
25
25
  end
26
26
 
27
27
  # Returns the current parameter context
@@ -114,6 +114,7 @@ module Origen
114
114
  end
115
115
 
116
116
  def defining?
117
+ return true if Origen::Parameters.transaction_open
117
118
  if top_level?
118
119
  @defining
119
120
  else
@@ -1,4 +1,5 @@
1
1
  require 'active_support/concern'
2
+ require 'set'
2
3
  module Origen
3
4
  module Parameters
4
5
  extend ActiveSupport::Concern
@@ -8,6 +9,75 @@ module Origen
8
9
 
9
10
  attr_accessor :current
10
11
 
12
+ # @api private
13
+ #
14
+ # Any define_params blocks contained within the given block will be allowed to be re-opened later
15
+ # in the block to override existing parameter settings or to add new ones.
16
+ #
17
+ # This is not allowed normally since already-defined child parameter sets could have referenced the
18
+ # original parameter and they would not reflect the final value after re-opening the parent parameter
19
+ # set.
20
+ #
21
+ # By defining the parameters within this block, Origen will keep track of relationships between parameter
22
+ # sets and any time a parent is changed the definitions of existing children will be re-executed to ensure
23
+ # that they reflect the new values.
24
+ #
25
+ # This is initially intended to support the concept of a app/parameters/application.rb being
26
+ # used to define baseline parameter sets, and then target-specific files can then override them.
27
+ def self.transaction
28
+ start_transaction
29
+ yield
30
+ stop_transaction
31
+ end
32
+
33
+ # @api private
34
+ def self.start_transaction
35
+ @transaction_data = {}
36
+ @transaction_open = true
37
+ @transaction_counter ||= 0
38
+ @transaction_counter += 1
39
+ end
40
+
41
+ # @api private
42
+ def self.stop_transaction
43
+ @transaction_counter -= 1
44
+ if @transaction_counter == 0
45
+ # Now finalize (freeze) all parameter sets we have just defined, this was deferred at define time due
46
+ # to running within a transaction
47
+ @transaction_data.each do |model, parameter_sets|
48
+ parameter_sets.keys.each do |name|
49
+ model._parameter_sets[name].finalize
50
+ end
51
+ end
52
+ @transaction_data = nil
53
+ @transaction_open = false
54
+ end
55
+ end
56
+
57
+ # @api private
58
+ def self.transaction_data
59
+ @transaction_data
60
+ end
61
+
62
+ # @api private
63
+ def self.transaction_open
64
+ @transaction_open
65
+ end
66
+
67
+ # @api private
68
+ def self.transaction_redefine
69
+ @transaction_redefine
70
+ end
71
+
72
+ # @api private
73
+ def self.redefine(model, name)
74
+ @transaction_redefine = true
75
+ model._parameter_sets.delete(name)
76
+ @transaction_data[model][name][:definitions].each { |options, block| model.define_params(name, options, &block) }
77
+ @transaction_data[model][name][:children].each { |model, name| redefine(model, name) }
78
+ @transaction_redefine = false
79
+ end
80
+
11
81
  module ClassMethods
12
82
  def parameters_context(obj = nil)
13
83
  if obj
@@ -25,19 +95,41 @@ module Origen
25
95
  end
26
96
  end
27
97
 
98
+ # @api private
99
+ def define_params_transaction
100
+ Origen::Parameters.transaction_data
101
+ end
102
+
28
103
  def define_params(name, options = {}, &block)
29
- if _parameter_sets[name]
104
+ name = name.to_sym
105
+ if _parameter_sets[name] && !Origen::Parameters.transaction_open
30
106
  fail "Parameter set '#{name}' cannot be re-opened once originally defined!"
31
107
  else
32
- _parameter_sets[name] = Set.new(top_level: true, owner: self)
108
+ if Origen::Parameters.transaction_open && !Origen::Parameters.transaction_redefine
109
+ define_params_transaction[self] ||= {}
110
+ define_params_transaction[self][name] ||= { children: ::Set[], definitions: [] }
111
+ define_params_transaction[self][name][:definitions] << [options.dup, block]
112
+ redefine_children = define_params_transaction[self][name][:children] if _parameter_sets[name]
113
+ end
114
+ if _parameter_sets[name]
115
+ defaults_already_set = true
116
+ else
117
+ _parameter_sets[name] = Origen::Parameters::Set.new(top_level: true, owner: self)
118
+ end
33
119
  if options[:inherit]
34
120
  kontext = _validate_parameter_set_name(options[:inherit])
35
121
  parent = kontext[:obj]._parameter_sets[kontext[:context]]
36
- _parameter_sets[name].copy_defaults_from(parent)
122
+ if Origen::Parameters.transaction_open && !Origen::Parameters.transaction_redefine
123
+ define_params_transaction[kontext[:obj]][kontext[:context]][:children] << [self, name]
124
+ end
125
+ _parameter_sets[name].copy_defaults_from(parent) unless defaults_already_set
37
126
  _parameter_sets[name].define(parent, &block)
38
127
  else
39
128
  _parameter_sets[name].define(&block)
40
129
  end
130
+ if redefine_children
131
+ redefine_children.each { |model, set_name| Origen::Parameters.redefine(model, set_name) }
132
+ end
41
133
  end
42
134
  end
43
135
  alias_method :define_parameters, :define_params
@@ -407,6 +407,11 @@ module Origen
407
407
 
408
408
  # Make this appear like a sub-block to any application code
409
409
  def is_a?(klass)
410
+ # Because sub_blocks are stored in a hash.with_indifferent_access, the value is tested
411
+ # against being a Hash or Array when it is added to the hash. This prevents the class being
412
+ # looking up and loaded by the autoload system straight away, especially if the sub-block
413
+ # has been specified to lazy load
414
+ return false if klass == Hash || klass == Array
410
415
  klass == self.klass || klass == Placeholder
411
416
  end
412
417
 
@@ -424,13 +429,16 @@ module Origen
424
429
  end
425
430
 
426
431
  def materialize
432
+ block = nil
427
433
  file = attributes.delete(:file)
434
+ load_block = attributes.delete(:load_block)
428
435
  dir = attributes.delete(:dir) || owner.send(:export_dir)
429
436
  block = owner.send(:instantiate_sub_block, name, klass, attributes)
430
437
  if file
431
438
  require File.join(dir, file)
432
439
  block.extend owner.send(:export_module_names_from_path, file).join('::').constantize
433
440
  end
441
+ block.load_block(load_block) if load_block
434
442
  block.owner = owner
435
443
  block
436
444
  end
@@ -464,17 +472,17 @@ module Origen
464
472
  @klass ||= begin
465
473
  class_name = attributes.delete(:class_name)
466
474
  if class_name
467
- if eval("defined? ::#{owner.namespace}::#{class_name}")
475
+ begin
468
476
  klass = eval("::#{owner.namespace}::#{class_name}")
469
- else
470
- if eval("defined? #{class_name}")
477
+ rescue NameError
478
+ begin
471
479
  klass = eval(class_name)
472
- else
473
- if eval("defined? #{owner.class}::#{class_name}")
480
+ rescue NameError
481
+ begin
474
482
  klass = eval("#{owner.class}::#{class_name}")
475
- else
483
+ rescue NameError
476
484
  puts "Could not find class: #{class_name}"
477
- fail 'Unknown sub block class!'
485
+ raise 'Unknown sub block class!'
478
486
  end
479
487
  end
480
488
  end
@@ -502,6 +510,12 @@ module Origen
502
510
  class SubBlock
503
511
  include Origen::Model
504
512
 
513
+ # Since no application defined this sub-block class, consider its parent's app to be
514
+ # the owning application
515
+ def app
516
+ parent.app
517
+ end
518
+
505
519
  # Used to create attribute accessors on the fly.
506
520
  #
507
521
  # On first call of a missing method a method is generated to avoid the missing lookup
@@ -24,6 +24,17 @@ module Origen
24
24
  include Origen::Model
25
25
  end
26
26
 
27
+ # Unloads all modules class defined by the application and reloads the target, use
28
+ # this in the console to pick up changes made to files since you opened it.
29
+ # It will only work if your application uses Origen auto-loading from the app/dir,
30
+ # any files that you have manually required will not be re-loaded and may generally
31
+ # cause problems with the use of this method.
32
+ def reload!
33
+ Loader.unload
34
+ Origen.app.reload_target!
35
+ true
36
+ end
37
+
27
38
  # Top-level timing manager/API, returns an instance of Origen::Pins::Timing
28
39
  def timing
29
40
  @timing ||= Pins::Timing.new
data/lib/origen.rb CHANGED
@@ -13,6 +13,7 @@ unless defined? RGen::ORIGENTRANSITION
13
13
  $_origen_invocation_pwd ||= Pathname.pwd
14
14
  require 'fileutils'
15
15
  # Force these to re-load since they could have been loaded from an earlier version of Origen during boot
16
+ load 'origen/loader.rb'
16
17
  load 'origen/site_config.rb'
17
18
  load 'origen/operating_systems.rb'
18
19
  require 'origen/core_ext'
@@ -25,7 +26,7 @@ unless defined? RGen::ORIGENTRANSITION
25
26
  require 'origen/remote_manager'
26
27
  require 'origen/utility'
27
28
  require 'origen/logger_methods'
28
- require 'option_parser/optparse'
29
+ require 'origen/core_ext/option_parser/optparse'
29
30
  require 'bundler'
30
31
  require 'origen/undefined'
31
32
  require 'origen/componentable'
@@ -290,6 +291,7 @@ unless defined? RGen::ORIGENTRANSITION
290
291
 
291
292
  # Returns true if Origen is running in an application workspace
292
293
  def in_app_workspace?
294
+ return @in_app_workspace if defined? @in_app_workspace
293
295
  @in_app_workspace ||= begin
294
296
  path = Pathname.new(Dir.pwd)
295
297
  until path.root? || File.exist?(File.join(path, APP_CONFIG))