origen 0.34.3 → 0.52.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/bin/origen +1 -231
- data/config/application.rb +12 -3
- data/config/boot.rb +2 -7
- data/config/commands.rb +3 -74
- data/config/rubocop/easy_disabled.yml +4 -0
- data/config/rubocop/easy_enabled.yml +0 -4
- data/config/rubocop/strict_disabled.yml +4 -0
- data/config/rubocop/strict_enabled.yml +0 -4
- data/config/version.rb +2 -3
- data/lib/origen.rb +27 -14
- data/lib/origen/application.rb +88 -2
- data/lib/origen/application/deployer.rb +3 -1
- data/lib/origen/application/release.rb +2 -2
- data/lib/origen/application/runner.rb +35 -20
- data/lib/origen/boot.rb +302 -0
- data/lib/origen/boot/api.rb +13 -0
- data/lib/origen/boot/app.rb +284 -0
- data/lib/origen/code_generators.rb +30 -10
- data/lib/origen/code_generators/actions.rb +244 -34
- data/lib/origen/code_generators/base.rb +9 -2
- data/lib/origen/code_generators/block.rb +203 -0
- data/lib/origen/code_generators/block_common.rb +100 -0
- data/lib/origen/code_generators/dut.rb +62 -0
- data/lib/origen/code_generators/feature.rb +50 -0
- data/lib/origen/code_generators/klass.rb +41 -0
- data/lib/origen/code_generators/model.rb +60 -0
- data/lib/origen/code_generators/module.rb +92 -0
- data/lib/origen/commands.rb +30 -13
- data/lib/origen/commands/archive.rb +175 -0
- data/lib/origen/commands/extract.rb +43 -0
- data/lib/origen/commands/generate.rb +1 -0
- data/lib/origen/commands/lint.rb +6 -1
- data/lib/origen/commands/new.rb +48 -24
- data/lib/origen/commands/new_resource.rb +41 -0
- data/lib/origen/commands/site.rb +52 -0
- data/lib/origen/commands/web.rb +11 -6
- data/lib/origen/commands_global.rb +9 -7
- data/lib/origen/core_ext/numeric.rb +20 -0
- data/lib/{option_parser → origen/core_ext/option_parser}/optparse.rb +0 -0
- data/lib/origen/dependencies.rb +0 -0
- data/lib/origen/file_handler.rb +18 -6
- data/lib/origen/generator.rb +19 -10
- data/lib/origen/generator/comparator.rb +2 -1
- data/lib/origen/generator/flow.rb +3 -1
- data/lib/origen/generator/job.rb +60 -16
- data/lib/origen/generator/pattern.rb +132 -72
- data/lib/origen/generator/pattern_finder.rb +3 -3
- data/lib/origen/generator/pattern_sequence.rb +201 -0
- data/lib/origen/generator/pattern_sequencer.rb +99 -0
- data/lib/origen/generator/pattern_thread.rb +175 -0
- data/lib/origen/loader.rb +381 -0
- data/lib/origen/log.rb +250 -108
- data/lib/origen/model.rb +22 -1
- data/lib/origen/model/exporter.rb +50 -10
- data/lib/origen/model_initializer.rb +5 -1
- data/lib/origen/operating_systems.rb +4 -0
- data/lib/origen/parameters.rb +96 -4
- data/lib/origen/parameters/set.rb +4 -3
- data/lib/origen/pins.rb +10 -8
- data/lib/origen/pins/pin.rb +61 -46
- data/lib/origen/ports/port.rb +5 -0
- data/lib/origen/registers.rb +5 -0
- data/lib/origen/registers/bit.rb +57 -53
- data/lib/origen/registers/bit_collection.rb +100 -43
- data/lib/origen/registers/msb0_delegator.rb +47 -0
- data/lib/origen/registers/reg.rb +114 -99
- data/lib/origen/revision_control.rb +1 -1
- data/lib/origen/revision_control/git.rb +23 -3
- data/lib/origen/site_config.rb +251 -60
- data/lib/origen/site_config/config.rb +217 -0
- data/lib/origen/sub_blocks.rb +106 -31
- data/lib/origen/top_level.rb +11 -0
- data/lib/origen/users/user.rb +3 -2
- data/lib/origen/utility/mailer.rb +42 -9
- data/lib/origen/value/bin_str_val.rb +1 -1
- data/lib/origen/value/hex_str_val.rb +1 -1
- data/lib/origen/version_string.rb +6 -1
- data/lib/tasks/gem.rake +6 -1
- data/origen_app_generators/Gemfile +19 -0
- data/origen_app_generators/Gemfile.lock +152 -0
- data/origen_app_generators/LICENSE +21 -0
- data/origen_app_generators/README.md +368 -0
- data/{templates/code_generators/rakefile.rb → origen_app_generators/Rakefile} +0 -0
- data/origen_app_generators/bin/boot.rb +39 -0
- data/origen_app_generators/config/application.rb +153 -0
- data/origen_app_generators/config/boot.rb +1 -0
- data/origen_app_generators/config/commands.rb +63 -0
- data/origen_app_generators/config/shared_commands.rb +177 -0
- data/origen_app_generators/config/version.rb +8 -0
- data/origen_app_generators/doc/history +223 -0
- data/origen_app_generators/lbin/bundle +105 -0
- data/origen_app_generators/lbin/byebug +29 -0
- data/origen_app_generators/lbin/coderay +29 -0
- data/origen_app_generators/lbin/htmldiff +29 -0
- data/origen_app_generators/lbin/httparty +29 -0
- data/origen_app_generators/lbin/httpclient +29 -0
- data/origen_app_generators/lbin/kramdown +29 -0
- data/origen_app_generators/lbin/ldiff +29 -0
- data/origen_app_generators/lbin/nanoc +29 -0
- data/origen_app_generators/lbin/nokogiri +29 -0
- data/origen_app_generators/lbin/origen +62 -0
- data/origen_app_generators/lbin/pry +29 -0
- data/origen_app_generators/lbin/rackup +29 -0
- data/origen_app_generators/lbin/rake +29 -0
- data/origen_app_generators/lbin/rspec +29 -0
- data/origen_app_generators/lbin/rubocop +29 -0
- data/origen_app_generators/lbin/ruby-parse +29 -0
- data/origen_app_generators/lbin/ruby-rewrite +29 -0
- data/origen_app_generators/lbin/thor +29 -0
- data/origen_app_generators/lbin/tilt +29 -0
- data/origen_app_generators/lbin/yard +29 -0
- data/origen_app_generators/lbin/yardoc +29 -0
- data/origen_app_generators/lbin/yri +29 -0
- data/origen_app_generators/lib/origen_app_generators.rb +125 -0
- data/origen_app_generators/lib/origen_app_generators/application.rb +62 -0
- data/origen_app_generators/lib/origen_app_generators/base.rb +257 -0
- data/origen_app_generators/lib/origen_app_generators/empty_application.rb +15 -0
- data/origen_app_generators/lib/origen_app_generators/empty_plugin.rb +15 -0
- data/origen_app_generators/lib/origen_app_generators/new.rb +170 -0
- data/origen_app_generators/lib/origen_app_generators/new_app_tests.rb +4 -0
- data/origen_app_generators/lib/origen_app_generators/origen_infrastructure/app_generator_plugin.rb +107 -0
- data/origen_app_generators/lib/origen_app_generators/plugin.rb +55 -0
- data/origen_app_generators/lib/origen_app_generators/test_engineering/common.rb +29 -0
- data/origen_app_generators/lib/origen_app_generators/test_engineering/stand_alone_application.rb +64 -0
- data/origen_app_generators/lib/origen_app_generators/test_engineering/test_block.rb +61 -0
- data/origen_app_generators/origen_app_generators.gemspec +33 -0
- data/{templates/code_generators → origen_app_generators/spec}/spec_helper.rb +0 -0
- data/origen_app_generators/target/debug.rb +8 -0
- data/origen_app_generators/target/default.rb +8 -0
- data/origen_app_generators/target/production.rb +0 -0
- data/origen_app_generators/templates/app_generators/application/.gitignore +37 -0
- data/origen_app_generators/templates/app_generators/application/.irbrc +9 -0
- data/origen_app_generators/templates/app_generators/application/.rspec +1 -0
- data/origen_app_generators/templates/app_generators/application/.travis.yml +11 -0
- data/origen_app_generators/templates/app_generators/application/Gemfile +34 -0
- data/origen_app_generators/templates/app_generators/application/Rakefile +7 -0
- data/origen_app_generators/templates/app_generators/application/app/blocks/top_level.rb +12 -0
- data/origen_app_generators/templates/app_generators/application/app/lib/module.rb +6 -0
- data/origen_app_generators/templates/app_generators/application/app/templates/web/index.md.erb +19 -0
- data/origen_app_generators/templates/app_generators/application/app/templates/web/layouts/_basic.html.erb +13 -0
- data/origen_app_generators/templates/app_generators/application/app/templates/web/partials/_navbar.html.erb +20 -0
- data/origen_app_generators/templates/app_generators/application/app/templates/web/release_notes.md.erb +5 -0
- data/origen_app_generators/templates/app_generators/application/config/application.rb +121 -0
- data/origen_app_generators/templates/app_generators/application/config/boot.rb +4 -0
- data/origen_app_generators/templates/app_generators/application/config/commands.rb +79 -0
- data/origen_app_generators/templates/app_generators/application/config/maillist_dev.txt +4 -0
- data/origen_app_generators/templates/app_generators/application/config/maillist_prod.txt +3 -0
- data/origen_app_generators/templates/app_generators/application/config/version.rb +8 -0
- data/origen_app_generators/templates/app_generators/application/doc/history +0 -0
- data/origen_app_generators/templates/app_generators/application/dot_keep +0 -0
- data/origen_app_generators/templates/app_generators/application/origen_core_session +2 -0
- data/origen_app_generators/templates/app_generators/application/spec/spec_helper.rb +44 -0
- data/origen_app_generators/templates/app_generators/application/target/debug.rb +8 -0
- data/origen_app_generators/templates/app_generators/application/target/default.rb +1 -0
- data/origen_app_generators/templates/app_generators/application/target/production.rb +4 -0
- data/origen_app_generators/templates/app_generators/new/generator.rb +102 -0
- data/origen_app_generators/templates/app_generators/new/info.md.erb +9 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/application.rb +54 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/base.rb +55 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/module.rb +28 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/app/lib/plugin.rb +64 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/config/load_generators.rb +6 -0
- data/origen_app_generators/templates/app_generators/plugin/Gemfile +32 -0
- data/origen_app_generators/templates/app_generators/plugin/Rakefile +10 -0
- data/origen_app_generators/templates/app_generators/plugin/app/templates/web/index.md.erb +37 -0
- data/origen_app_generators/templates/app_generators/plugin/app/templates/web/partials/_navbar_external.html.erb +20 -0
- data/origen_app_generators/templates/app_generators/plugin/app/templates/web/partials/_navbar_internal.html.erb +20 -0
- data/origen_app_generators/templates/app_generators/plugin/config/boot.rb +24 -0
- data/origen_app_generators/templates/app_generators/plugin/gemspec.rb +43 -0
- data/origen_app_generators/templates/app_generators/test_engineering/environment/j750.rb +1 -0
- data/origen_app_generators/templates/app_generators/test_engineering/environment/uflex.rb +1 -0
- data/origen_app_generators/templates/app_generators/test_engineering/environment/v93k.rb +1 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/.keep +0 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/.keep +0 -0
- data/origen_site_config.yml +55 -5
- data/templates/code_generators/attributes.rb +20 -0
- data/templates/code_generators/class.rb +9 -0
- data/templates/code_generators/controller.rb +87 -0
- data/templates/code_generators/model.rb +21 -0
- data/templates/code_generators/module.rb +4 -0
- data/templates/code_generators/parameters.rb +19 -0
- data/templates/code_generators/pins.rb +28 -0
- data/templates/code_generators/registers.rb +20 -0
- data/templates/code_generators/sub_blocks.rb +24 -0
- data/templates/code_generators/timesets.rb +24 -0
- data/templates/code_generators/version.rb +0 -1
- data/templates/git/gitignore.erb +0 -1
- data/vendor/lib/models/origen/export1.rb +77 -0
- data/vendor/lib/models/origen/export1/block1.rb +13 -0
- data/vendor/lib/models/origen/export1/block1/x.rb +36 -0
- data/vendor/lib/models/origen/non_origen_meta_data.md +1 -0
- metadata +149 -68
- data/bin/fix_my_workspace +0 -100
- data/lib/c99/ate_interface.rb +0 -77
- data/lib/c99/nvm.rb +0 -110
- data/lib/c99/target/mock2.rb +0 -1
- data/lib/c99/target/subdir/mock3.rb +0 -1
- data/lib/origen/code_generators/bundler.rb +0 -17
- data/lib/origen/code_generators/gem_setup.rb +0 -49
- data/lib/origen/code_generators/rake.rb +0 -13
- data/lib/origen/code_generators/rspec.rb +0 -12
- data/lib/origen/commands/add.rb +0 -12
- data/lib/tasks/private/build.rake +0 -8
- data/templates/code_generators/gemfile_app.rb +0 -4
- data/templates/code_generators/gemfile_plugin.rb +0 -6
- data/templates/code_generators/gemspec.rb +0 -33
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
module Origen
|
3
|
+
class Generator
|
4
|
+
# Provides APIs to enable applications to support concurrency
|
5
|
+
class PatternSequencer
|
6
|
+
class << self
|
7
|
+
def serialize(id = nil)
|
8
|
+
if active?
|
9
|
+
s = nil
|
10
|
+
id ||= caller[0]
|
11
|
+
@semaphores ||= {}
|
12
|
+
@semaphores[id] ||= Concurrent::Semaphore.new(1)
|
13
|
+
s = @semaphores[id]
|
14
|
+
completed = false
|
15
|
+
blocked = false
|
16
|
+
until completed
|
17
|
+
# If already acquired or available
|
18
|
+
if (thread.reservations[id] && thread.reservations[id][:semaphore]) || s.try_acquire
|
19
|
+
thread.record_active if blocked
|
20
|
+
yield
|
21
|
+
completed = true
|
22
|
+
else
|
23
|
+
thread.waiting_for_serialize(id, blocked)
|
24
|
+
blocked = true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
# If the thread has reserved access to this serialized resource then don't release it now, but
|
28
|
+
# store a reference to the semaphore and it will be released at the end of the reserve block
|
29
|
+
if thread.reservations[id]
|
30
|
+
thread.reservations[id][:semaphore] = s
|
31
|
+
else
|
32
|
+
s.release
|
33
|
+
end
|
34
|
+
else
|
35
|
+
yield
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Once a lock is acquired on a serialize block with the given ID, it won't be released to
|
40
|
+
# other parallel threads until the end of this block
|
41
|
+
def reserve(id)
|
42
|
+
if active?
|
43
|
+
if thread.reservations[id]
|
44
|
+
thread.reservations[id][:count] += 1
|
45
|
+
else
|
46
|
+
thread.reservations[id] = { count: 1, semaphore: nil }
|
47
|
+
end
|
48
|
+
yield
|
49
|
+
if thread.reservations[id][:count] == 1
|
50
|
+
# May not be set if the application reserved the resource but never hit it
|
51
|
+
if s = thread.reservations[id][:semaphore]
|
52
|
+
s.release
|
53
|
+
end
|
54
|
+
thread.reservations[id] = nil
|
55
|
+
else
|
56
|
+
thread.reservations[id][:count] -= 1
|
57
|
+
end
|
58
|
+
else
|
59
|
+
yield
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns true if a pattern sequence is currently open/active
|
64
|
+
def active?
|
65
|
+
!!@active
|
66
|
+
end
|
67
|
+
alias_method :open?, :active?
|
68
|
+
alias_method :runnng?, :active?
|
69
|
+
|
70
|
+
# Returns the PatternThread object for the current thread
|
71
|
+
def thread
|
72
|
+
@thread.value
|
73
|
+
end
|
74
|
+
|
75
|
+
# Prepends the given string with "[<current thread ID>] " unless it already contains it
|
76
|
+
def add_thread(str)
|
77
|
+
if active? && thread
|
78
|
+
id = "[#{thread.id}] "
|
79
|
+
str.prepend(id) unless str =~ /#{id}/
|
80
|
+
end
|
81
|
+
str
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def active=(val)
|
87
|
+
@active = val
|
88
|
+
end
|
89
|
+
|
90
|
+
def thread=(t)
|
91
|
+
@thread ||= Concurrent::ThreadLocalVar.new(nil)
|
92
|
+
@thread.value = t
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
PatSeq = Origen::Generator::PatternSequencer
|
99
|
+
PatSeq.send(:thread=, nil)
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Origen
|
2
|
+
class Generator
|
3
|
+
# An instance of PatternThread is created for each parallel thread of execution
|
4
|
+
# in a pattern sequence. One instance of this class is also created to represent
|
5
|
+
# the original main thread in addition to those created by calling seq.in_parallel
|
6
|
+
class PatternThread
|
7
|
+
# Returns the parent pattern sequence object
|
8
|
+
attr_reader :sequence
|
9
|
+
attr_reader :pending_cycles
|
10
|
+
attr_reader :id
|
11
|
+
attr_reader :reservations
|
12
|
+
attr_reader :cycle_count_start
|
13
|
+
attr_reader :cycle_count_stop
|
14
|
+
# A record of when the thread is active to construct the execution profile
|
15
|
+
attr_reader :events
|
16
|
+
|
17
|
+
def initialize(id, sequence, block, primary = false)
|
18
|
+
if primary
|
19
|
+
@cycle_count_start = 0
|
20
|
+
else
|
21
|
+
@cycle_count_start = current_cycle_count
|
22
|
+
end
|
23
|
+
@events = [[:active, cycle_count_start]]
|
24
|
+
@id = id.to_sym
|
25
|
+
@sequence = sequence
|
26
|
+
@block = block
|
27
|
+
@primary = primary
|
28
|
+
@running = Concurrent::Event.new
|
29
|
+
@waiting = Concurrent::Event.new
|
30
|
+
@pending_cycles = nil
|
31
|
+
@completed = false
|
32
|
+
@reservations = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns true if this is main thread (the one from which all in_parallel threads
|
36
|
+
# have been branched from)
|
37
|
+
def primary?
|
38
|
+
@primary
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
#
|
43
|
+
# This method is called once by the pattern sequence to start a new thread. It will block until
|
44
|
+
# the thread is in the waiting state.
|
45
|
+
def start
|
46
|
+
@thread = Thread.new do
|
47
|
+
PatSeq.send(:thread=, self)
|
48
|
+
wait
|
49
|
+
@block.call(sequence)
|
50
|
+
sequence.send(:thread_completed, self)
|
51
|
+
record_cycle_count_stop
|
52
|
+
@completed = true
|
53
|
+
wait
|
54
|
+
end
|
55
|
+
@waiting.wait
|
56
|
+
end
|
57
|
+
|
58
|
+
def record_cycle_count_stop
|
59
|
+
@cycle_count_stop = current_cycle_count
|
60
|
+
events << [:stopped, cycle_count_stop]
|
61
|
+
events.freeze
|
62
|
+
end
|
63
|
+
|
64
|
+
def record_active
|
65
|
+
events << [:active, current_cycle_count]
|
66
|
+
end
|
67
|
+
|
68
|
+
def current_cycle_count
|
69
|
+
tester.try(:cycle_count) || 0
|
70
|
+
end
|
71
|
+
|
72
|
+
def execution_profile(start, stop, step)
|
73
|
+
events = @events.dup
|
74
|
+
cycles = start
|
75
|
+
state = :inactive
|
76
|
+
line = ''
|
77
|
+
((stop - start) / step).times do |i|
|
78
|
+
active_cycles = 0
|
79
|
+
while events.first && events.first[1] >= cycles && events.first[1] < cycles + step
|
80
|
+
event = events.shift
|
81
|
+
# Bring the current cycles up to this event point applying the current state
|
82
|
+
if state == :active
|
83
|
+
active_cycles += event[1] - cycles
|
84
|
+
end
|
85
|
+
state = event[0] == :active ? :active : :inactive
|
86
|
+
cycles = event[1]
|
87
|
+
end
|
88
|
+
|
89
|
+
# Bring the current cycles up to the end of this profile tick
|
90
|
+
if state == :active
|
91
|
+
active_cycles += ((i + 1) * step) - cycles
|
92
|
+
end
|
93
|
+
cycles = ((i + 1) * step)
|
94
|
+
|
95
|
+
if active_cycles == 0
|
96
|
+
line += '_'
|
97
|
+
elsif active_cycles > (step * 0.5)
|
98
|
+
line += '█'
|
99
|
+
else
|
100
|
+
line += '▄'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
line
|
104
|
+
end
|
105
|
+
|
106
|
+
# Will be called when the thread can't execute its next cycle because it is waiting to obtain a
|
107
|
+
# lock on a serialized block
|
108
|
+
def waiting_for_serialize(serialize_id, skip_event = false)
|
109
|
+
# puts "Thread #{id} is blocked waiting for #{serialize_id}"
|
110
|
+
events << [:waiting, current_cycle_count] unless skip_event
|
111
|
+
wait
|
112
|
+
end
|
113
|
+
|
114
|
+
# Will be called when the thread can't execute its next cycle because it is waiting for another
|
115
|
+
# thread to complete
|
116
|
+
def waiting_for_thread(skip_event = false)
|
117
|
+
events << [:waiting, current_cycle_count] unless skip_event
|
118
|
+
wait
|
119
|
+
end
|
120
|
+
|
121
|
+
# Will be called when the thread is ready for the next cycle
|
122
|
+
def cycle(options)
|
123
|
+
@pending_cycles = options[:repeat] || 1
|
124
|
+
# If there are threads pending start and we are about to enter a long delay, block for only
|
125
|
+
# one cycle to give them a change to get underway and make use of this delay
|
126
|
+
if @pending_cycles > 1 && sequence.send(:threads_waiting_to_start?)
|
127
|
+
remainder = @pending_cycles - 1
|
128
|
+
@pending_cycles = 1
|
129
|
+
end
|
130
|
+
wait
|
131
|
+
@pending_cycles = remainder if remainder
|
132
|
+
# If the sequence did not do enough cycles in that round to satisfy this thread, then go back
|
133
|
+
# around to complete the remainder before continuing with the rest of the pattern
|
134
|
+
if @pending_cycles == 0
|
135
|
+
@pending_cycles = nil
|
136
|
+
elsif @pending_cycles > 0
|
137
|
+
@pending_cycles.cycles
|
138
|
+
else
|
139
|
+
fail "Something has gone wrong @pending_cycles is #{@pending_cycles}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# @api private
|
144
|
+
def executed_cycles(cycles)
|
145
|
+
@pending_cycles -= cycles if @pending_cycles
|
146
|
+
end
|
147
|
+
|
148
|
+
def completed?
|
149
|
+
@completed
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns true if the thread is currently waiting for the pattern sequence to advance it
|
153
|
+
def waiting?
|
154
|
+
@waiting.set?
|
155
|
+
end
|
156
|
+
|
157
|
+
# This should be called only by the pattern thread itself, and will block it until it is told to
|
158
|
+
# advance by the pattern sequence running in the main thread
|
159
|
+
def wait
|
160
|
+
@running.reset
|
161
|
+
@waiting.set
|
162
|
+
@running.wait
|
163
|
+
end
|
164
|
+
|
165
|
+
# This should be called only by the pattern sequence running in the main thread, it will un-block the
|
166
|
+
# pattern thread which is currently waiting, and it will block the main thread until the pattern thread
|
167
|
+
# reaches the next wait point (or completes)
|
168
|
+
def advance(completed_cycles = nil)
|
169
|
+
@waiting.reset
|
170
|
+
@running.set # Release the pattern thread
|
171
|
+
@waiting.wait # And wait for it to reach the next wait point
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,381 @@
|
|
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
|
+
file = file.to_s
|
98
|
+
if File.exist?(file)
|
99
|
+
File.open(file, 'r') do |f|
|
100
|
+
model.instance_eval(f.read, file)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
# @api private
|
107
|
+
def self.with_parameters_transaction(type)
|
108
|
+
if type == :parameters
|
109
|
+
Origen::Parameters.transaction do
|
110
|
+
yield
|
111
|
+
end
|
112
|
+
else
|
113
|
+
yield
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# If a block definition exists for the given model, then this will load it and apply it to
|
118
|
+
# the model.
|
119
|
+
# Returns true if a model is found and loaded, otherwise nil.
|
120
|
+
def self.load_block(model, options = {})
|
121
|
+
model = model.model # Ensure we have a handle on the model and not its controller
|
122
|
+
loaded = nil
|
123
|
+
if app = options[:app] || model.app
|
124
|
+
if options[:path]
|
125
|
+
full_paths = Array(options[:path])
|
126
|
+
else
|
127
|
+
full_paths = model.class.to_s.split('::')
|
128
|
+
full_paths.shift # Throw away the app namespace
|
129
|
+
full_paths = [full_paths.join('/')]
|
130
|
+
end
|
131
|
+
full_paths.each do |full_path|
|
132
|
+
paths = full_path.to_s.split('/')
|
133
|
+
key = ''
|
134
|
+
only = Array(options[:only]) if options[:only]
|
135
|
+
except = Array(options[:except]) if options[:except]
|
136
|
+
path = paths.map(&:underscore).join('/')
|
137
|
+
# If the path refers to a nested sub-block then don't load the full hierarchy since they
|
138
|
+
# don't support inheritance or derivatives, modify the paths array so that only the sub-block
|
139
|
+
# level will be loaded and nothing else.
|
140
|
+
paths = [path] if app.blocks_files[path] && app.blocks_files[path][:_sub_block]
|
141
|
+
# These will be loaded first, followed by the rest in an undefined order.
|
142
|
+
# Attributes and parameters are first so that they may be referenced in the other files.
|
143
|
+
# Sub-blocks was added early due to a corner case issue that could be encountered if the pins or
|
144
|
+
# regs imported an Origen exported file that defined a module with the same name as a sub-block
|
145
|
+
# class, in that case the sub-block class would not be auto-loaded.
|
146
|
+
load_first = [:attributes, :parameters, :sub_blocks]
|
147
|
+
|
148
|
+
load_first.each do |type|
|
149
|
+
unless (only && !only.include?(type)) || (except && except.include?(type))
|
150
|
+
with_parameters_transaction(type) do
|
151
|
+
paths.each_with_index do |path, i|
|
152
|
+
key = i == 0 ? path.underscore : "#{key}/#{path.underscore}"
|
153
|
+
if app.blocks_files[key] && app.blocks_files[key][type]
|
154
|
+
app.blocks_files[key][type].each do |f|
|
155
|
+
if type == :attributes
|
156
|
+
success = load_attributes(f, model)
|
157
|
+
else
|
158
|
+
success = load_block_file(f, model)
|
159
|
+
end
|
160
|
+
loaded ||= success
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Now load the rest
|
169
|
+
paths.each_with_index do |path, i|
|
170
|
+
key = i == 0 ? path.underscore : "#{key}/#{path.underscore}"
|
171
|
+
if app.blocks_files[key]
|
172
|
+
app.blocks_files[key].each do |type, files|
|
173
|
+
unless type == :_sub_block || load_first.include?(type) || (only && !only.include?(type)) || (except && except.include?(type))
|
174
|
+
files.each { |f| success = load_block_file(f, model); loaded ||= success }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
loaded
|
182
|
+
end
|
183
|
+
|
184
|
+
# This is inspired by Rails' ActiveSupport::Dependencies module.
|
185
|
+
module ModuleConstMissing
|
186
|
+
def self.append_features(base)
|
187
|
+
base.class_eval do
|
188
|
+
# Emulate #exclude via an ivar
|
189
|
+
return if defined?(@_const_missing) && @_const_missing
|
190
|
+
@_const_missing = instance_method(:const_missing)
|
191
|
+
remove_method(:const_missing)
|
192
|
+
end
|
193
|
+
super
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.exclude_from(base)
|
197
|
+
base.class_eval do
|
198
|
+
define_method :const_missing, @_const_missing
|
199
|
+
@_const_missing = nil
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# @api private
|
204
|
+
# Substitutes a single occurrence of 'derivatives' in the given dirs array, starting
|
205
|
+
# from the end of it and replacing it with the given new value.
|
206
|
+
# Returns true if a substitution is made, else false.
|
207
|
+
def _sub_derivatives_from_end(new_val, dirs)
|
208
|
+
subbed = false
|
209
|
+
size = dirs.size - 1
|
210
|
+
dirs.reverse_each.with_index do |val, i|
|
211
|
+
if val == 'derivatives'
|
212
|
+
dirs[size - i] = new_val
|
213
|
+
subbed = true
|
214
|
+
break
|
215
|
+
end
|
216
|
+
end
|
217
|
+
dirs if subbed
|
218
|
+
end
|
219
|
+
|
220
|
+
# Allows classes and modules to be defined in app/blocks and app/lib without needing to
|
221
|
+
# require them and in the case of app/blocks to use a custom directory structure.
|
222
|
+
#
|
223
|
+
# The first time a reference is made to a class or module name it will trigger this hook,
|
224
|
+
# and we then work out what the file name should be and require it.
|
225
|
+
def const_missing(name)
|
226
|
+
if Origen.in_app_workspace?
|
227
|
+
if self == Object
|
228
|
+
name = name.to_s
|
229
|
+
else
|
230
|
+
name = "#{self}::#{name}"
|
231
|
+
end
|
232
|
+
return nil if @_checking_name == name
|
233
|
+
names = name.split('::')
|
234
|
+
namespace = names.shift
|
235
|
+
if app = Origen::Application.from_namespace(namespace)
|
236
|
+
# First we are going to check for a match in the app/blocks directory, this needs to be handled
|
237
|
+
# specially since it follows a non-std structure, e.g. use of derivatives/ and sub_blocks/ folders
|
238
|
+
# for organization without having them as part of the class name-spacing
|
239
|
+
altname = nil
|
240
|
+
dirs = [app.root, 'app', 'blocks']
|
241
|
+
names.each_with_index do |name, i|
|
242
|
+
dirs << 'derivatives' unless i == 0
|
243
|
+
dirs << name.underscore
|
244
|
+
end
|
245
|
+
|
246
|
+
# Is this a reference to a model?
|
247
|
+
if File.exist?(f = File.join(*dirs, 'model.rb'))
|
248
|
+
model = _load_const(f, name)
|
249
|
+
# Also load the model's controller if it exists
|
250
|
+
if File.exist?(f = File.join(*dirs, 'controller.rb'))
|
251
|
+
controller = _load_const(f, name + 'Controller')
|
252
|
+
end
|
253
|
+
return model
|
254
|
+
end
|
255
|
+
|
256
|
+
# Is this a reference to a controller?
|
257
|
+
if dirs.last.to_s =~ /_controller$/
|
258
|
+
controller_reference = true
|
259
|
+
dirs << dirs.pop.sub(/_controller$/, '')
|
260
|
+
if File.exist?(f = File.join(*dirs, 'controller.rb'))
|
261
|
+
return _load_const(f, name)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# Is this a reference to a sub-block model or controller that is nested within a block?
|
266
|
+
dirs_ = dirs.dup
|
267
|
+
while dirs_ = _sub_derivatives_from_end('sub_blocks', dirs_)
|
268
|
+
if controller_reference
|
269
|
+
if File.exist?(f = File.join(*dirs_, 'controller.rb'))
|
270
|
+
return _load_const(f, name)
|
271
|
+
end
|
272
|
+
elsif File.exist?(f = File.join(*dirs_, 'model.rb'))
|
273
|
+
model = _load_const(f, name)
|
274
|
+
# Also load the model's controller if it exists
|
275
|
+
if File.exist?(f = File.join(*dirs_, 'controller.rb'))
|
276
|
+
controller = _load_const(f, name + 'Controller')
|
277
|
+
end
|
278
|
+
return model
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
# Is this a reference to a module that has been added to a model or controller?
|
283
|
+
# In this case dirs contains something like:
|
284
|
+
# [..., "my_model", "derivatives", "my_module"]
|
285
|
+
# [..., "my_model_controller", "derivatives", "my_module"]
|
286
|
+
# So let's try by transforming these into:
|
287
|
+
# [..., "my_model", "model"] + "my_module.rb"
|
288
|
+
# [..., "my_model", "controller"] + "my_module.rb"
|
289
|
+
filename = dirs.pop + '.rb'
|
290
|
+
dirs.pop # Lose 'derivatives'
|
291
|
+
if dirs.last.to_s =~ /_controller$/
|
292
|
+
dirs << dirs.pop.sub(/_controller$/, '')
|
293
|
+
dirs << 'controller'
|
294
|
+
else
|
295
|
+
dirs << 'model'
|
296
|
+
end
|
297
|
+
if File.exist?(f = File.join(*dirs, filename))
|
298
|
+
return _load_const(f, name)
|
299
|
+
end
|
300
|
+
|
301
|
+
# Now that we have established that it is not a reference to a block (which has a non-std code
|
302
|
+
# organization structure), we can now check for a match in the app/lib directory following std
|
303
|
+
# Ruby code organization conventions
|
304
|
+
until names.empty?
|
305
|
+
path = File.join(*names.map(&:underscore)) + '.rb'
|
306
|
+
|
307
|
+
f = File.join(app.root, 'app', 'lib', namespace.underscore, path)
|
308
|
+
if File.exist?(f)
|
309
|
+
model = _load_const(f, name, altname)
|
310
|
+
# Try and reference the controller to load it too, though don't raise an error if it
|
311
|
+
# doesn't exist
|
312
|
+
@@pre_loading_controller = true
|
313
|
+
eval "#{altname || name}Controller"
|
314
|
+
return model
|
315
|
+
# If a folder exists that is named after this constant, then assume it is an otherwise
|
316
|
+
# undeclared namespace module and declare it now
|
317
|
+
elsif File.exist?(f.sub('.rb', ''))
|
318
|
+
return const_set path.sub('.rb', '').camelcase, Module.new
|
319
|
+
end
|
320
|
+
|
321
|
+
# Don't waste time looking up the namespace hierarchy for the controller, if it exists it
|
322
|
+
# should be within the exact same namespace as the model
|
323
|
+
return nil if defined?(@@pre_loading_controller) && @@pre_loading_controller
|
324
|
+
|
325
|
+
# Remove the highest level namespace and then search again in the parent namespace
|
326
|
+
if discarded_namespace = names.delete_at(-2)
|
327
|
+
altname ||= name
|
328
|
+
altname = altname.sub("#{discarded_namespace}::", '')
|
329
|
+
else
|
330
|
+
names.pop
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
_raise_uninitialized_constant_error(name)
|
335
|
+
else
|
336
|
+
_raise_uninitialized_constant_error(name)
|
337
|
+
end
|
338
|
+
else
|
339
|
+
_raise_uninitialized_constant_error(name)
|
340
|
+
end
|
341
|
+
ensure
|
342
|
+
@@pre_loading_controller = false
|
343
|
+
end
|
344
|
+
|
345
|
+
# @api_private
|
346
|
+
def _load_const(file, name, altname = nil)
|
347
|
+
load file
|
348
|
+
if defined?(@@pre_loading_controller)
|
349
|
+
return if @@pre_loading_controller
|
350
|
+
end
|
351
|
+
@_checking_name = altname || name
|
352
|
+
const = eval(altname || name)
|
353
|
+
@_checking_name = nil
|
354
|
+
if const
|
355
|
+
Origen::Loader.record_const(altname || name)
|
356
|
+
return const
|
357
|
+
end
|
358
|
+
msg ||= "uninitialized constant #{name} (expected it to be defined in: #{file})"
|
359
|
+
_raise_uninitialized_constant_error(name, msg)
|
360
|
+
end
|
361
|
+
|
362
|
+
# @api private
|
363
|
+
def _raise_uninitialized_constant_error(name, msg = nil)
|
364
|
+
msg ||= "uninitialized constant #{name}"
|
365
|
+
name_error = NameError.new(msg, name)
|
366
|
+
name_error.set_backtrace(caller.reject { |l| l =~ /^#{__FILE__}/ })
|
367
|
+
fail name_error
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
def self.enable_origen_load_extensions!
|
372
|
+
Module.class_eval { include ModuleConstMissing }
|
373
|
+
end
|
374
|
+
|
375
|
+
def self.disable_origen_load_extensions!
|
376
|
+
ModuleConstMissing.exclude_from(Module)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
Origen::Loader.enable_origen_load_extensions!
|