origen 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/ctags +0 -0
- data/bin/origen +165 -1
- data/bin/rgen +2 -0
- data/config/application.rb +141 -0
- data/config/commands.rb +72 -0
- data/config/development.rb +7 -0
- data/config/environment.rb +0 -0
- data/config/rgen.policy +7 -0
- data/config/rubocop/easy.yml +620 -0
- data/config/rubocop/easy_disabled.yml +271 -0
- data/config/rubocop/easy_enabled.yml +731 -0
- data/config/rubocop/strict.yml +620 -0
- data/config/rubocop/strict_disabled.yml +247 -0
- data/config/rubocop/strict_enabled.yml +755 -0
- data/config/users.rb +20 -0
- data/config/version.rb +1 -1
- data/helpers/url.rb +68 -0
- data/lib/c99/doc_interface.rb +56 -0
- data/lib/c99/j750_interface.rb +85 -0
- data/lib/c99/nvm.rb +89 -0
- data/lib/c99/target/mock2.rb +1 -0
- data/lib/c99/target/subdir/mock3.rb +1 -0
- data/lib/option_parser/optparse.rb +12 -0
- data/lib/origen/acronyms.rb +60 -0
- data/lib/origen/application/command_dispatcher.rb +12 -0
- data/lib/origen/application/configuration.rb +206 -0
- data/lib/origen/application/configuration_manager.rb +78 -0
- data/lib/origen/application/deployer.rb +367 -0
- data/lib/origen/application/environment.rb +186 -0
- data/lib/origen/application/lsf.rb +145 -0
- data/lib/origen/application/lsf_manager.rb +657 -0
- data/lib/origen/application/plugins_manager.rb +280 -0
- data/lib/origen/application/release.rb +359 -0
- data/lib/origen/application/runner.rb +246 -0
- data/lib/origen/application/statistics.rb +191 -0
- data/lib/origen/application/target.rb +374 -0
- data/lib/origen/application/version_tracker.rb +59 -0
- data/lib/origen/application/workspace_manager.rb +151 -0
- data/lib/origen/application.rb +746 -0
- data/lib/origen/bugs/bug.rb +36 -0
- data/lib/origen/bugs.rb +45 -0
- data/lib/origen/callbacks.rb +35 -0
- data/lib/origen/chip_mode.rb +118 -0
- data/lib/origen/chip_package.rb +461 -0
- data/lib/origen/client.rb +87 -0
- data/lib/origen/code_generators/actions.rb +258 -0
- data/lib/origen/code_generators/base.rb +57 -0
- data/lib/origen/code_generators/bundler.rb +17 -0
- data/lib/origen/code_generators/gem_setup.rb +49 -0
- data/lib/origen/code_generators/rake.rb +13 -0
- data/lib/origen/code_generators/rspec.rb +12 -0
- data/lib/origen/code_generators/semver.rb +39 -0
- data/lib/origen/code_generators/timever.rb +37 -0
- data/lib/origen/code_generators.rb +111 -0
- data/lib/origen/commands/add.rb +12 -0
- data/lib/origen/commands/compile.rb +62 -0
- data/lib/origen/commands/ctags.rb +9 -0
- data/lib/origen/commands/dispatch.rb +22 -0
- data/lib/origen/commands/environment.rb +11 -0
- data/lib/origen/commands/fetch.rb +63 -0
- data/lib/origen/commands/generate.rb +130 -0
- data/lib/origen/commands/interactive.rb +73 -0
- data/lib/origen/commands/lint.rb +82 -0
- data/lib/origen/commands/lsf.rb +93 -0
- data/lib/origen/commands/merge.rb +55 -0
- data/lib/origen/commands/modifications.rb +12 -0
- data/lib/origen/commands/new.rb +113 -0
- data/lib/origen/commands/plugin.rb +105 -0
- data/lib/origen/commands/program.rb +70 -0
- data/lib/origen/commands/rc.rb +442 -0
- data/lib/origen/commands/save.rb +56 -0
- data/lib/origen/commands/target.rb +27 -0
- data/lib/origen/commands/time.rb +127 -0
- data/lib/origen/commands/version.rb +17 -0
- data/lib/origen/commands/web.rb +221 -0
- data/lib/origen/commands.rb +272 -0
- data/lib/origen/commands_global.rb +76 -0
- data/lib/origen/controller.rb +94 -0
- data/lib/origen/core_ext/array.rb +23 -0
- data/lib/origen/core_ext/bignum.rb +36 -0
- data/lib/origen/core_ext/enumerable.rb +76 -0
- data/lib/origen/core_ext/fixnum.rb +46 -0
- data/lib/origen/core_ext/hash.rb +52 -0
- data/lib/origen/core_ext/module.rb +14 -0
- data/lib/origen/core_ext/numeric.rb +126 -0
- data/lib/origen/core_ext/object.rb +13 -0
- data/lib/origen/core_ext/range.rb +7 -0
- data/lib/origen/core_ext/string.rb +124 -0
- data/lib/origen/core_ext.rb +10 -0
- data/lib/origen/database/key_value_store.rb +111 -0
- data/lib/origen/database/key_value_stores.rb +108 -0
- data/lib/origen/database.rb +6 -0
- data/lib/origen/encodings.rb +102 -0
- data/lib/origen/features/feature.rb +22 -0
- data/lib/origen/features.rb +104 -0
- data/lib/origen/file_handler.rb +429 -0
- data/lib/origen/generator/comparator.rb +56 -0
- data/lib/origen/generator/compiler.rb +277 -0
- data/lib/origen/generator/flow.rb +49 -0
- data/lib/origen/generator/job.rb +131 -0
- data/lib/origen/generator/pattern.rb +356 -0
- data/lib/origen/generator/pattern_finder.rb +155 -0
- data/lib/origen/generator/pattern_iterator.rb +55 -0
- data/lib/origen/generator/renderer.rb +113 -0
- data/lib/origen/generator/resources.rb +40 -0
- data/lib/origen/generator/stage.rb +89 -0
- data/lib/origen/generator.rb +85 -0
- data/lib/origen/global_methods.rb +205 -0
- data/lib/origen/import_manager.rb +596 -0
- data/lib/origen/location/base.rb +116 -0
- data/lib/origen/location/map.rb +83 -0
- data/lib/origen/location.rb +6 -0
- data/lib/origen/log.rb +217 -0
- data/lib/origen/logger_methods.rb +56 -0
- data/lib/origen/mode.rb +61 -0
- data/lib/origen/model.rb +267 -0
- data/lib/origen/model_initializer.rb +45 -0
- data/lib/origen/nvm/block_array.rb +72 -0
- data/lib/origen/nvm.rb +6 -0
- data/lib/origen/parameters/live.rb +22 -0
- data/lib/origen/parameters/missing.rb +28 -0
- data/lib/origen/parameters/set.rb +144 -0
- data/lib/origen/parameters.rb +107 -0
- data/lib/origen/pdm.rb +218 -0
- data/lib/origen/pins/function_proxy.rb +36 -0
- data/lib/origen/pins/ground_pin.rb +6 -0
- data/lib/origen/pins/pin.rb +860 -0
- data/lib/origen/pins/pin_bank.rb +349 -0
- data/lib/origen/pins/pin_clock.rb +124 -0
- data/lib/origen/pins/pin_collection.rb +492 -0
- data/lib/origen/pins/pin_common.rb +206 -0
- data/lib/origen/pins/port.rb +268 -0
- data/lib/origen/pins/power_pin.rb +30 -0
- data/lib/origen/pins.rb +696 -0
- data/lib/origen/registers/bit.rb +562 -0
- data/lib/origen/registers/bit_collection.rb +787 -0
- data/lib/origen/registers/container.rb +288 -0
- data/lib/origen/registers/domain.rb +16 -0
- data/lib/origen/registers/reg.rb +1406 -0
- data/lib/origen/registers/reg_collection.rb +24 -0
- data/lib/origen/registers.rb +652 -0
- data/lib/origen/regression_manager.rb +251 -0
- data/lib/origen/remote_manager.rb +340 -0
- data/lib/origen/revision_control/base.rb +257 -0
- data/lib/origen/revision_control/design_sync.rb +276 -0
- data/lib/origen/revision_control/git.rb +243 -0
- data/lib/origen/revision_control/subversion.rb +6 -0
- data/lib/origen/revision_control.rb +44 -0
- data/lib/origen/ruby_version_check.rb +131 -0
- data/lib/origen/site_config.rb +61 -0
- data/lib/origen/specs/checkers.rb +103 -0
- data/lib/origen/specs/creation_info.rb +17 -0
- data/lib/origen/specs/doc_resource.rb +91 -0
- data/lib/origen/specs/exhibit.rb +17 -0
- data/lib/origen/specs/mode_select.rb +16 -0
- data/lib/origen/specs/note.rb +17 -0
- data/lib/origen/specs/override.rb +21 -0
- data/lib/origen/specs/power_supply.rb +13 -0
- data/lib/origen/specs/spec.rb +226 -0
- data/lib/origen/specs/version_history.rb +14 -0
- data/lib/origen/specs.rb +552 -0
- data/lib/origen/sub_blocks.rb +298 -0
- data/lib/origen/tester/api.rb +277 -0
- data/lib/origen/tester/bdm/bdm.rb +25 -0
- data/lib/origen/tester/command_based_tester.rb +46 -0
- data/lib/origen/tester/doc/doc.rb +226 -0
- data/lib/origen/tester/doc/generator/flow.rb +71 -0
- data/lib/origen/tester/doc/generator/flow_line.rb +203 -0
- data/lib/origen/tester/doc/generator/test.rb +68 -0
- data/lib/origen/tester/doc/generator/test_group.rb +66 -0
- data/lib/origen/tester/doc/generator/tests.rb +47 -0
- data/lib/origen/tester/doc/generator.rb +126 -0
- data/lib/origen/tester/doc/model.rb +162 -0
- data/lib/origen/tester/generator/flow_control_api.rb +606 -0
- data/lib/origen/tester/generator/identity_map.rb +25 -0
- data/lib/origen/tester/generator/placeholder.rb +13 -0
- data/lib/origen/tester/generator/test_numberer.rb +25 -0
- data/lib/origen/tester/generator.rb +271 -0
- data/lib/origen/tester/interface.rb +154 -0
- data/lib/origen/tester/j750/files.rb +45 -0
- data/lib/origen/tester/j750/generator/flow.rb +123 -0
- data/lib/origen/tester/j750/generator/flow_line.rb +288 -0
- data/lib/origen/tester/j750/generator/patgroup.rb +111 -0
- data/lib/origen/tester/j750/generator/patgroups.rb +41 -0
- data/lib/origen/tester/j750/generator/patset.rb +111 -0
- data/lib/origen/tester/j750/generator/patsets.rb +41 -0
- data/lib/origen/tester/j750/generator/templates/flow.txt.erb +9 -0
- data/lib/origen/tester/j750/generator/templates/instances.txt.erb +16 -0
- data/lib/origen/tester/j750/generator/templates/patgroups.txt.erb +8 -0
- data/lib/origen/tester/j750/generator/templates/patsets.txt.erb +10 -0
- data/lib/origen/tester/j750/generator/test_instance.rb +846 -0
- data/lib/origen/tester/j750/generator/test_instance_group.rb +60 -0
- data/lib/origen/tester/j750/generator/test_instances.rb +182 -0
- data/lib/origen/tester/j750/generator.rb +203 -0
- data/lib/origen/tester/j750/j750.rb +845 -0
- data/lib/origen/tester/j750/j750_hpt.rb +35 -0
- data/lib/origen/tester/j750/parser/ac_spec.rb +11 -0
- data/lib/origen/tester/j750/parser/ac_specs.rb +0 -0
- data/lib/origen/tester/j750/parser/dc_spec.rb +36 -0
- data/lib/origen/tester/j750/parser/dc_specs.rb +50 -0
- data/lib/origen/tester/j750/parser/descriptions.rb +340 -0
- data/lib/origen/tester/j750/parser/flow.rb +111 -0
- data/lib/origen/tester/j750/parser/flow_line.rb +207 -0
- data/lib/origen/tester/j750/parser/flows.rb +23 -0
- data/lib/origen/tester/j750/parser/pattern_set.rb +94 -0
- data/lib/origen/tester/j750/parser/pattern_sets.rb +33 -0
- data/lib/origen/tester/j750/parser/test_instance.rb +322 -0
- data/lib/origen/tester/j750/parser/test_instances.rb +26 -0
- data/lib/origen/tester/j750/parser/timeset.rb +15 -0
- data/lib/origen/tester/j750/parser/timesets.rb +0 -0
- data/lib/origen/tester/j750/parser.rb +104 -0
- data/lib/origen/tester/jlink/jlink.rb +33 -0
- data/lib/origen/tester/parser/description_lookup.rb +64 -0
- data/lib/origen/tester/parser/searchable_array.rb +32 -0
- data/lib/origen/tester/parser/searchable_hash.rb +32 -0
- data/lib/origen/tester/parser.rb +24 -0
- data/lib/origen/tester/time.rb +338 -0
- data/lib/origen/tester/timing.rb +253 -0
- data/lib/origen/tester/ultraflex/files.rb +45 -0
- data/lib/origen/tester/ultraflex/generator/flow.rb +119 -0
- data/lib/origen/tester/ultraflex/generator/flow_line.rb +269 -0
- data/lib/origen/tester/ultraflex/generator/patgroup.rb +111 -0
- data/lib/origen/tester/ultraflex/generator/patgroups.rb +41 -0
- data/lib/origen/tester/ultraflex/generator/patset.rb +111 -0
- data/lib/origen/tester/ultraflex/generator/patsets.rb +41 -0
- data/lib/origen/tester/ultraflex/generator/templates/flow.txt.erb +9 -0
- data/lib/origen/tester/ultraflex/generator/templates/instances.txt.erb +16 -0
- data/lib/origen/tester/ultraflex/generator/templates/patgroups.txt.erb +8 -0
- data/lib/origen/tester/ultraflex/generator/templates/patsets.txt.erb +10 -0
- data/lib/origen/tester/ultraflex/generator/test_instance.rb +622 -0
- data/lib/origen/tester/ultraflex/generator/test_instance_group.rb +60 -0
- data/lib/origen/tester/ultraflex/generator/test_instances.rb +174 -0
- data/lib/origen/tester/ultraflex/generator.rb +200 -0
- data/lib/origen/tester/ultraflex/parser/ac_spec.rb +11 -0
- data/lib/origen/tester/ultraflex/parser/ac_specs.rb +0 -0
- data/lib/origen/tester/ultraflex/parser/dc_spec.rb +36 -0
- data/lib/origen/tester/ultraflex/parser/dc_specs.rb +50 -0
- data/lib/origen/tester/ultraflex/parser/descriptions.rb +342 -0
- data/lib/origen/tester/ultraflex/parser/flow.rb +111 -0
- data/lib/origen/tester/ultraflex/parser/flow_line.rb +207 -0
- data/lib/origen/tester/ultraflex/parser/flows.rb +23 -0
- data/lib/origen/tester/ultraflex/parser/pattern_set.rb +94 -0
- data/lib/origen/tester/ultraflex/parser/pattern_sets.rb +33 -0
- data/lib/origen/tester/ultraflex/parser/test_instance.rb +262 -0
- data/lib/origen/tester/ultraflex/parser/test_instances.rb +26 -0
- data/lib/origen/tester/ultraflex/parser/timeset.rb +15 -0
- data/lib/origen/tester/ultraflex/parser/timesets.rb +0 -0
- data/lib/origen/tester/ultraflex/parser.rb +104 -0
- data/lib/origen/tester/ultraflex/ultraflex.rb +759 -0
- data/lib/origen/tester/v93k/generator/flow.rb +63 -0
- data/lib/origen/tester/v93k/generator/flow_node/print.rb +10 -0
- data/lib/origen/tester/v93k/generator/flow_node.rb +17 -0
- data/lib/origen/tester/v93k/generator/pattern.rb +16 -0
- data/lib/origen/tester/v93k/generator/pattern_master.rb +54 -0
- data/lib/origen/tester/v93k/generator/templates/_test_method.txt.erb +6 -0
- data/lib/origen/tester/v93k/generator/templates/_test_suite.txt.erb +11 -0
- data/lib/origen/tester/v93k/generator/templates/template.flow.erb +121 -0
- data/lib/origen/tester/v93k/generator/templates/template.pmfl.erb +9 -0
- data/lib/origen/tester/v93k/generator/test_function.rb +103 -0
- data/lib/origen/tester/v93k/generator/test_functions.rb +79 -0
- data/lib/origen/tester/v93k/generator/test_method.rb +46 -0
- data/lib/origen/tester/v93k/generator/test_methods.rb +75 -0
- data/lib/origen/tester/v93k/generator/test_suite.rb +54 -0
- data/lib/origen/tester/v93k/generator/test_suites.rb +65 -0
- data/lib/origen/tester/v93k/generator.rb +80 -0
- data/lib/origen/tester/v93k/v93k.rb +420 -0
- data/lib/origen/tester/vector.rb +86 -0
- data/lib/origen/tester/vector_generator.rb +633 -0
- data/lib/origen/tester/vector_pipeline.rb +150 -0
- data/lib/origen/tester.rb +56 -0
- data/lib/origen/top_level.rb +134 -0
- data/lib/origen/users/ldap.rb +65 -0
- data/lib/origen/users/user.rb +149 -0
- data/lib/origen/users.rb +30 -0
- data/lib/origen/utility/block_args.rb +93 -0
- data/lib/origen/utility/csv_data.rb +110 -0
- data/lib/origen/utility/design_sync.rb +494 -0
- data/lib/origen/utility/diff.rb +158 -0
- data/lib/origen/utility/input_capture.rb +121 -0
- data/lib/origen/utility/mailer.rb +143 -0
- data/lib/origen/utility/s_record.rb +205 -0
- data/lib/origen/utility/time_and_date.rb +30 -0
- data/lib/origen/utility.rb +12 -0
- data/lib/origen/version_checker.rb +117 -0
- data/lib/origen/version_string.rb +356 -0
- data/lib/origen.rb +648 -0
- data/lib/tasks/gem.rake +27 -22
- data/origen_site_config.yml +36 -0
- data/source_setup +17 -0
- data/spec/format/rgen_formatter.rb +14 -0
- data/templates/api_doc/README.txt.erb +24 -0
- data/templates/code_generators/gemfile_app.rb +4 -0
- data/templates/code_generators/gemfile_plugin.rb +6 -0
- data/templates/code_generators/gemspec.rb +33 -0
- data/templates/code_generators/rakefile.rb +10 -0
- data/templates/code_generators/spec_helper.rb +49 -0
- data/templates/code_generators/version.rb +8 -0
- data/templates/code_generators/version_time.rb +3 -0
- data/templates/git/gitignore.erb +33 -0
- data/templates/j750/_vt_flow.txt.erb +8 -0
- data/templates/j750/_vt_instances.txt.erb +4 -0
- data/templates/j750/program_sheet.txt.erb +9 -0
- data/templates/nanoc/Rules +74 -0
- data/templates/nanoc/config.yaml +77 -0
- data/templates/nanoc/content/favicon.ico +0 -0
- data/templates/nanoc/layouts/bootstrap.html.erb +63 -0
- data/templates/nanoc/layouts/bootstrap3.html.erb +71 -0
- data/templates/nanoc/layouts/freescale.html.erb +79 -0
- data/templates/nanoc/lib/bootstrap_filter.rb +49 -0
- data/templates/nanoc/lib/codeblocks_filter.rb +41 -0
- data/templates/nanoc/lib/default.rb +2 -0
- data/templates/nanoc/lib/gzip_filter.rb +16 -0
- data/templates/nanoc/lib/haml_code_filter.rb +41 -0
- data/templates/nanoc/lib/helpers.rb +1 -0
- data/templates/nanoc/lib/search_filter.rb +62 -0
- data/templates/nanoc_dynamic/content/search.js.erb +92 -0
- data/templates/shared/web/_logo.html +10 -0
- data/templates/test/_inline_sub.txt.erb +2 -0
- data/templates/test/environment.txt.erb +1 -0
- data/templates/test/inline.txt.erb +11 -0
- data/templates/test/inspections.txt.erb +19 -0
- data/templates/test/set1/_sub1.txt.erb +12 -0
- data/templates/test/set1/_sub4.txt.erb +1 -0
- data/templates/test/set1/_sub5.txt.erb +1 -0
- data/templates/test/set1/main.txt.erb +53 -0
- data/templates/test/set1/sub_dir/_sub2.txt.erb +20 -0
- data/templates/test/set1/sub_dir/_sub3.txt.erb +12 -0
- data/templates/test/set1/sub_dir/main2.txt.erb +4 -0
- data/templates/test/set2/template_with_no_erb_1.txt +9 -0
- data/templates/test/set2/template_with_no_erb_2.txt +9 -0
- data/templates/test/set3/_layout.html.erb +4 -0
- data/templates/test/set3/content.html.erb +6 -0
- data/templates/time/filter.rb.erb +15 -0
- data/templates/time/rules.rb.erb +45 -0
- metadata +639 -5
|
@@ -0,0 +1,1406 @@
|
|
|
1
|
+
module Origen
|
|
2
|
+
module Registers
|
|
3
|
+
# The register class can be used to represent not only h/ware resgisters,
|
|
4
|
+
# but really any entity which has an address and data component, such as a specific RAM location.<br>
|
|
5
|
+
# Any registers instantiated through Origen::Registers#add_reg are instances of this class.
|
|
6
|
+
#
|
|
7
|
+
# All methods in BitCollection can also be called on a Reg object.
|
|
8
|
+
class Reg
|
|
9
|
+
include Origen::SubBlocks::Path
|
|
10
|
+
include Origen::SubBlocks::Domains
|
|
11
|
+
|
|
12
|
+
# These attributes can be defined on a register at definition time and will get applied
|
|
13
|
+
# to all of its contained bits unless a specific bit has its own definition of the same
|
|
14
|
+
# attribute
|
|
15
|
+
REG_LEVEL_ATTRIBUTES = {
|
|
16
|
+
feature: {},
|
|
17
|
+
reset: { aliases: [:res] },
|
|
18
|
+
memory: {},
|
|
19
|
+
path: { aliases: [:hdl_path] },
|
|
20
|
+
abs_path: { aliases: [:absolute_path] },
|
|
21
|
+
access: {}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Returns the object that own the register.
|
|
25
|
+
# ==== Example
|
|
26
|
+
# $soc.reg(:blah).owner # Returns the $soc object
|
|
27
|
+
attr_reader :owner
|
|
28
|
+
alias_method :parent, :owner
|
|
29
|
+
# The base address of the register, this will be set dynamically
|
|
30
|
+
# by Origen based on the parent's base address
|
|
31
|
+
attr_accessor :base_address
|
|
32
|
+
attr_writer :address # :nodoc:
|
|
33
|
+
# Returns an integer representing the number of bits in the register
|
|
34
|
+
attr_reader :size
|
|
35
|
+
# The register name
|
|
36
|
+
attr_accessor :name
|
|
37
|
+
# Any feature associated with the register
|
|
38
|
+
attr_accessor :feature
|
|
39
|
+
|
|
40
|
+
attr_accessor :grows_backwards # :nodoc:
|
|
41
|
+
attr_accessor :lookup # :nodoc:
|
|
42
|
+
# Returns a full path to the file in which the register was defined
|
|
43
|
+
attr_reader :define_file
|
|
44
|
+
# Returns any application-specific meta-data attatched to the given register
|
|
45
|
+
attr_accessor :meta
|
|
46
|
+
alias_method :meta_data, :meta
|
|
47
|
+
alias_method :metadata, :meta
|
|
48
|
+
# If the given register's reset data is backed by memory, the memory address can
|
|
49
|
+
# be recorded in this attribute
|
|
50
|
+
attr_accessor :memory
|
|
51
|
+
|
|
52
|
+
# Normally shouldn't be called directly, instantiate through add_reg
|
|
53
|
+
# Upon initialization bits are stored as follows:
|
|
54
|
+
# @bits -
|
|
55
|
+
# An array of bit objects in position order, @bits[5] corresponds
|
|
56
|
+
# to the bit as position r
|
|
57
|
+
# @lookup -
|
|
58
|
+
# A Hash lookup table for quickly accessing bit objects by name
|
|
59
|
+
# @lookup = { :bit_or_bus_name => {:pos => 3, :bits => 4} }
|
|
60
|
+
def initialize(owner, address, size, name, options = {}) # :nodoc:
|
|
61
|
+
@owner = owner
|
|
62
|
+
@address = address
|
|
63
|
+
@size = size
|
|
64
|
+
@bits = []
|
|
65
|
+
@lookup = {}
|
|
66
|
+
@name = name
|
|
67
|
+
@init_as_writable = options.delete(:init_as_writable)
|
|
68
|
+
@define_file = options.delete(:define_file)
|
|
69
|
+
REG_LEVEL_ATTRIBUTES.each do |attribute, _meta|
|
|
70
|
+
instance_variable_set("@#{attribute}", options.delete(attribute))
|
|
71
|
+
end
|
|
72
|
+
@description_from_api = {}
|
|
73
|
+
description = options.delete(:description)
|
|
74
|
+
if description
|
|
75
|
+
@description_from_api[:_reg] = description.split(/\r?\n/)
|
|
76
|
+
end
|
|
77
|
+
@meta = default_reg_metadata.merge(options.delete(:meta) || {})
|
|
78
|
+
|
|
79
|
+
# Initialize with unwritable bits that read back as zero, can override this
|
|
80
|
+
# to make all writable by default by setting the :init_writable option to true
|
|
81
|
+
@size.times do |n|
|
|
82
|
+
@bits << Bit.new(self, n, writable: @init_as_writable, undefined: true)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
add_bits_from_options(options)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def freeze
|
|
89
|
+
bits.each(&:freeze)
|
|
90
|
+
# Call any methods which cache results to generate the instance variables
|
|
91
|
+
# before they are frozen
|
|
92
|
+
address
|
|
93
|
+
super
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def bind(bitname, live_parameter)
|
|
97
|
+
unless live_parameter.respond_to?(:is_a_live_parameter?) && live_parameter.is_a_live_parameter?
|
|
98
|
+
fail 'Only live updating parameters should be bound, make sure you have not missed .live in the path to the parameter!'
|
|
99
|
+
end
|
|
100
|
+
@parameter_bound_bits ||= {}
|
|
101
|
+
@parameter_bound_bits[bitname] = live_parameter
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def has_parameter_bound_bits?
|
|
105
|
+
@parameter_bound_bits && !@parameter_bound_bits.empty?
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def update_bound_bits
|
|
109
|
+
@updating_bound_bits = true
|
|
110
|
+
@parameter_bound_bits.each do |name, val|
|
|
111
|
+
bits(name).write(val)
|
|
112
|
+
end
|
|
113
|
+
@updating_bound_bits = false
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def updating_bound_bits?
|
|
117
|
+
@updating_bound_bits
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def inspect
|
|
121
|
+
bit_width = 13
|
|
122
|
+
desc = ["\n0x%X - :#{name}" % address]
|
|
123
|
+
desc << ' ' + ('=' * (bit_width + 1) * 8)
|
|
124
|
+
|
|
125
|
+
# "<#{self.class}: #{self.name}>"
|
|
126
|
+
(size / 8).times do |byte_index|
|
|
127
|
+
# Need to add support for little endian regs here?
|
|
128
|
+
byte_number = (size / 8) - byte_index
|
|
129
|
+
max_bit = size - (byte_index * 8) - 1
|
|
130
|
+
min_bit = max_bit - 8 + 1
|
|
131
|
+
|
|
132
|
+
line = ' '
|
|
133
|
+
# BIT INDEX ROW
|
|
134
|
+
8.times do |i|
|
|
135
|
+
line << '|' + "#{size - i - 1 - (byte_index * 8)}".center(bit_width)
|
|
136
|
+
end
|
|
137
|
+
line += '|'
|
|
138
|
+
desc << line
|
|
139
|
+
|
|
140
|
+
# BIT NAME ROW
|
|
141
|
+
line = ' '
|
|
142
|
+
named_bits include_spacers: true do |name, bit, bitcounter|
|
|
143
|
+
if _bit_in_range?(bit, max_bit, min_bit)
|
|
144
|
+
if bit.size > 1
|
|
145
|
+
|
|
146
|
+
if name
|
|
147
|
+
if bitcounter.nil?
|
|
148
|
+
bit_name = "#{name}[#{_max_bit_in_range(bit, max_bit, min_bit)}:#{_min_bit_in_range(bit, max_bit, min_bit)}]"
|
|
149
|
+
bit_span = _num_bits_in_range(bit, max_bit, min_bit)
|
|
150
|
+
|
|
151
|
+
else
|
|
152
|
+
upper = _max_bit_in_range(bit, max_bit, min_bit) + bitcounter - bit.size
|
|
153
|
+
lower = _min_bit_in_range(bit, max_bit, min_bit) + bitcounter - bit.size
|
|
154
|
+
bit_name = "#{name}[#{upper}:#{lower}]"
|
|
155
|
+
bit_span = upper - lower + 1
|
|
156
|
+
end
|
|
157
|
+
width = bit_width * bit_span
|
|
158
|
+
line << '|' + ":#{bit_name[0..width - 2]}".center(width + bit_span - 1)
|
|
159
|
+
|
|
160
|
+
else
|
|
161
|
+
bit.shift_out_left do |bit|
|
|
162
|
+
if _index_in_range?(bit.position, max_bit, min_bit)
|
|
163
|
+
line << '|' + ''.center(bit_width)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
else
|
|
169
|
+
bit_name = "#{name}"
|
|
170
|
+
line << '|' + ":#{bit_name[0..bit_width - 2]}".center(bit_width)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
line += '|'
|
|
175
|
+
desc << line
|
|
176
|
+
|
|
177
|
+
## BIT ACCESS ROW
|
|
178
|
+
# line = "Access "
|
|
179
|
+
# self.named_bits :include_spacers => true do |name, bit|
|
|
180
|
+
# if _bit_in_range?(bit, max_bit, min_bit)
|
|
181
|
+
# if bit.size > 1
|
|
182
|
+
# if name
|
|
183
|
+
# access = _bit_rw(bit)
|
|
184
|
+
# bit_span = _num_bits_in_range(bit, max_bit, min_bit)
|
|
185
|
+
# width = bit_width * bit_span
|
|
186
|
+
# line << "|" + access.center(width + bit_span - 1)
|
|
187
|
+
# else
|
|
188
|
+
# bit.shift_out_left do |bit|
|
|
189
|
+
# if _index_in_range?(bit.position, max_bit, min_bit)
|
|
190
|
+
# line << "|" + "".center(bit_width)
|
|
191
|
+
# end
|
|
192
|
+
# end
|
|
193
|
+
# end
|
|
194
|
+
# else
|
|
195
|
+
# access = _bit_rw(bit)
|
|
196
|
+
# line << "|" + access.center(bit_width)
|
|
197
|
+
# end
|
|
198
|
+
# end
|
|
199
|
+
# end
|
|
200
|
+
# line += "|"
|
|
201
|
+
# desc << line
|
|
202
|
+
|
|
203
|
+
## BIT RESET ROW
|
|
204
|
+
# line = "Reset "
|
|
205
|
+
# self.named_bits :include_spacers => true do |name, bit|
|
|
206
|
+
# if _bit_in_range?(bit, max_bit, min_bit)
|
|
207
|
+
# if bit.size > 1
|
|
208
|
+
# if name
|
|
209
|
+
# value = "0x%X" % bit.reset_val[_max_bit_in_range(bit, max_bit, min_bit).._min_bit_in_range(bit, max_bit, min_bit)]
|
|
210
|
+
# bit_span = _num_bits_in_range(bit, max_bit, min_bit)
|
|
211
|
+
# width = bit_width * bit_span
|
|
212
|
+
# line << "|" + value.center(width + bit_span - 1)
|
|
213
|
+
# else
|
|
214
|
+
# bit.shift_out_left do |bit|
|
|
215
|
+
# if _index_in_range?(bit.position, max_bit, min_bit)
|
|
216
|
+
# line << "|" + "".center(bit_width)
|
|
217
|
+
# end
|
|
218
|
+
# end
|
|
219
|
+
# end
|
|
220
|
+
# else
|
|
221
|
+
# line << "|" + "#{bit.reset_val}".center(bit_width)
|
|
222
|
+
# end
|
|
223
|
+
# end
|
|
224
|
+
# end
|
|
225
|
+
# line += "|"
|
|
226
|
+
# desc << line
|
|
227
|
+
|
|
228
|
+
# BIT STATE ROW
|
|
229
|
+
line = ' '
|
|
230
|
+
named_bits include_spacers: true do |name, bit, _bitcounter|
|
|
231
|
+
if _bit_in_range?(bit, max_bit, min_bit)
|
|
232
|
+
if bit.size > 1
|
|
233
|
+
if name
|
|
234
|
+
if bit.has_known_value?
|
|
235
|
+
value = '0x%X' % bit.val[_max_bit_in_range(bit, max_bit, min_bit).._min_bit_in_range(bit, max_bit, min_bit)]
|
|
236
|
+
else
|
|
237
|
+
if bit.reset_val == :undefined
|
|
238
|
+
value = 'X'
|
|
239
|
+
else
|
|
240
|
+
value = 'M'
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
value += _state_desc(bit)
|
|
244
|
+
bit_span = _num_bits_in_range(bit, max_bit, min_bit)
|
|
245
|
+
width = bit_width * bit_span
|
|
246
|
+
line << '|' + value.center(width + bit_span - 1)
|
|
247
|
+
else
|
|
248
|
+
bit.shift_out_left do |bit|
|
|
249
|
+
if _index_in_range?(bit.position, max_bit, min_bit)
|
|
250
|
+
line << '|' + ''.center(bit_width)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
else
|
|
255
|
+
if bit.has_known_value?
|
|
256
|
+
val = bit.val
|
|
257
|
+
else
|
|
258
|
+
if bit.reset_val == :undefined
|
|
259
|
+
val = 'X'
|
|
260
|
+
else
|
|
261
|
+
val = 'M'
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
value = "#{val}" + _state_desc(bit)
|
|
265
|
+
line << '|' + value.center(bit_width)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
line += '|'
|
|
270
|
+
desc << line
|
|
271
|
+
|
|
272
|
+
desc << ' ' + ('-' * (bit_width + 1) * 8)
|
|
273
|
+
end
|
|
274
|
+
desc.join("\n")
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Returns a hash containing all register descriptions that have been parsed so far.
|
|
278
|
+
#
|
|
279
|
+
# @api private
|
|
280
|
+
def description_lookup
|
|
281
|
+
@@description_lookup ||= {}
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Returns any application specific metadata that has been inherited by the
|
|
285
|
+
# given register.
|
|
286
|
+
# This does not account for any overridding that may have been applied to
|
|
287
|
+
# this register specifically however, use the meta method to get that.
|
|
288
|
+
def default_reg_metadata
|
|
289
|
+
Origen::Registers.default_reg_metadata.merge(
|
|
290
|
+
Origen::Registers.reg_metadata[owner.class] || {})
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def bit_value_descriptions(bitname, options = {})
|
|
294
|
+
options = {
|
|
295
|
+
format: :binary
|
|
296
|
+
}.merge(options)
|
|
297
|
+
base = case options[:format]
|
|
298
|
+
when :bin, :binary
|
|
299
|
+
2
|
|
300
|
+
when :hex, :hexadecimal
|
|
301
|
+
16
|
|
302
|
+
when :dec, :decimal
|
|
303
|
+
10
|
|
304
|
+
else
|
|
305
|
+
fail "Unknown integer format: #{options[:format]}"
|
|
306
|
+
end
|
|
307
|
+
desc = {}
|
|
308
|
+
description(bitname).each do |line|
|
|
309
|
+
if line =~ /^\s*(\d+)\s+\|\s+(.+)/
|
|
310
|
+
desc[Regexp.last_match[1].to_i(base)] = Regexp.last_match[2]
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
desc
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Returns the full name of the register when this has been specified in the register
|
|
317
|
+
# description like this:
|
|
318
|
+
#
|
|
319
|
+
# # ** This is the Register Full Name **
|
|
320
|
+
# # This register blah blah
|
|
321
|
+
#
|
|
322
|
+
# This method will also be called by bit collections to look up the name when
|
|
323
|
+
# defined in a similar manner in the bit description.
|
|
324
|
+
#
|
|
325
|
+
# If no name has been specified this will return nil.
|
|
326
|
+
def full_name(bitname = :_reg, _options = {})
|
|
327
|
+
bitname, options = :_reg, bitname if bitname.is_a?(Hash)
|
|
328
|
+
desc = description(bitname).first
|
|
329
|
+
# Capture something like this:
|
|
330
|
+
# ** This is the full name ** - This bit blah blah
|
|
331
|
+
if desc && desc =~ /\s*\*\*\s*([^\*.]*)\s*\*\*/
|
|
332
|
+
Regexp.last_match[1].strip
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# Escapes brackets and parenthesis. Helper for description method.
|
|
337
|
+
def escape_special_char(str)
|
|
338
|
+
str.gsub('[', '\[').gsub(']', '\]').gsub('(', '\(').gsub(')', '\)') if str
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Returns the description of this register if any, if none then an empty array
|
|
342
|
+
# will be returned
|
|
343
|
+
#
|
|
344
|
+
# **Note** Adding a description field will override any comment-driven documentation
|
|
345
|
+
# of a register (ie markdown style comments)
|
|
346
|
+
def description(bitname = :_reg, options = {})
|
|
347
|
+
bitname, options = :_reg, bitname if bitname.is_a?(Hash)
|
|
348
|
+
options = {
|
|
349
|
+
include_name: true,
|
|
350
|
+
include_bit_values: true
|
|
351
|
+
}.merge(options)
|
|
352
|
+
if @description_from_api[bitname]
|
|
353
|
+
desc = @description_from_api[bitname]
|
|
354
|
+
else
|
|
355
|
+
parse_descriptions unless description_lookup[define_file]
|
|
356
|
+
begin
|
|
357
|
+
desc = description_lookup[define_file][name][bitname] || []
|
|
358
|
+
rescue
|
|
359
|
+
desc = []
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
desc = desc.reject do |line|
|
|
363
|
+
if bitname != :_reg
|
|
364
|
+
unless options[:include_bit_values]
|
|
365
|
+
!!(line =~ /^\s*(\d+)\s+\|\s+(.+)/)
|
|
366
|
+
end
|
|
367
|
+
else
|
|
368
|
+
false
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
if desc.first
|
|
372
|
+
unless options[:include_name]
|
|
373
|
+
desc[0] = desc.first.sub(/\s*\*\*\s*#{escape_special_char(full_name(bitname))}\s*\*\*\s*-?\s*/, '')
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
desc.shift if desc.first && desc.first.strip.empty?
|
|
377
|
+
desc.pop if desc.last && desc.last.strip.empty?
|
|
378
|
+
desc
|
|
379
|
+
end
|
|
380
|
+
alias_method :descriptions, :description
|
|
381
|
+
|
|
382
|
+
# @api private
|
|
383
|
+
def parse_descriptions
|
|
384
|
+
desc = []
|
|
385
|
+
File.readlines(define_file).each do |line|
|
|
386
|
+
if line =~ /^\s*#(.*)/
|
|
387
|
+
desc << Regexp.last_match[1].strip
|
|
388
|
+
elsif line =~ /^\s*(add_reg|reg)\(?\s*:(\w+)\s*,.*do/
|
|
389
|
+
@current_reg_name = Regexp.last_match[2].to_sym
|
|
390
|
+
description_lookup[define_file] ||= {}
|
|
391
|
+
description_lookup[define_file][@current_reg_name] ||= {}
|
|
392
|
+
description_lookup[define_file][@current_reg_name][:_reg] = desc.dup
|
|
393
|
+
desc = []
|
|
394
|
+
# http://www.rubular.com/r/7FidbC1JRA
|
|
395
|
+
elsif @current_reg_name && line =~ /^\s*(add_bit|bit|reg\.bit)s?\(?\s*\d+\.?\.?\d*\s*,\s*:(\w+)/
|
|
396
|
+
description_lookup[define_file][@current_reg_name][Regexp.last_match[2].to_sym] = desc.dup
|
|
397
|
+
desc = []
|
|
398
|
+
else
|
|
399
|
+
desc = []
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def contains_bits?
|
|
405
|
+
true
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# @api private
|
|
409
|
+
def add_bits_from_options(options = {}) # :nodoc:
|
|
410
|
+
# edit Traynor
|
|
411
|
+
# options is now an array for split bit groups or a hash if single bit/range bits
|
|
412
|
+
# Now add the requested bits to the register, removing the unwritable bits as required
|
|
413
|
+
options.each do |bit_id, bit_params|
|
|
414
|
+
if bit_params.is_a? Hash
|
|
415
|
+
description = bit_params.delete(:description)
|
|
416
|
+
if description
|
|
417
|
+
@description_from_api[bit_id] = description.split(/\r?\n/)
|
|
418
|
+
end
|
|
419
|
+
bind(bit_id, bit_params.delete(:bind)) if bit_params[:bind]
|
|
420
|
+
position = bit_params[:pos] || 0
|
|
421
|
+
num_bits = bit_params[:bits] || 1
|
|
422
|
+
if @reset
|
|
423
|
+
if @reset.is_a?(Symbol)
|
|
424
|
+
bit_params[:res] = @reset
|
|
425
|
+
else
|
|
426
|
+
bit_params[:res] = @reset[(num_bits + position - 1), position]
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
bit_params[:access] = @access if bit_params[:access].nil?
|
|
430
|
+
bit_params[:res] = bit_params[:data] if bit_params[:data]
|
|
431
|
+
bit_params[:res] = bit_params[:reset] if bit_params[:reset]
|
|
432
|
+
if num_bits == 1
|
|
433
|
+
add_bit(bit_id, position, bit_params) # and add the new one
|
|
434
|
+
else
|
|
435
|
+
add_bus(bit_id, position, num_bits, bit_params)
|
|
436
|
+
end
|
|
437
|
+
elsif bit_params.is_a? Array
|
|
438
|
+
|
|
439
|
+
description = bit_params.map { |h| h.delete(:description) }.compact.join("\n")
|
|
440
|
+
unless description.empty?
|
|
441
|
+
@description_from_api[bit_id] = description.split(/\r?\n/)
|
|
442
|
+
end
|
|
443
|
+
add_bus_scramble(bit_id, bit_params)
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
self
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
# This method is called whenever reg.clone is called to make a copy of a given register.
|
|
450
|
+
# Ruby will correctly copy all instance variables but it will not drill down to copy nested
|
|
451
|
+
# attributes, like the bits contained in @bits.
|
|
452
|
+
# This function will therefore correctly clone all bits contained in the register also.
|
|
453
|
+
def initialize_copy(orig) # :nodoc:
|
|
454
|
+
@bits = []
|
|
455
|
+
orig.bits.each do |bit|
|
|
456
|
+
@bits << bit.clone
|
|
457
|
+
end
|
|
458
|
+
@lookup = orig.lookup.clone
|
|
459
|
+
self
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# Returns a dummy register object that can be used on the fly, this can sometimes
|
|
463
|
+
# be useful to configure an intricate read operation.
|
|
464
|
+
# ==== Example
|
|
465
|
+
# # Read bit 5 of RAM address 0xFFFF1280
|
|
466
|
+
# dummy = Reg.dummy # Create a dummy reg to configure the read operation
|
|
467
|
+
# dummy.address = 0xFFFF1280 # Set the address
|
|
468
|
+
# dummy.bit(5).read!(1) # Read bit 5 expecting a 1
|
|
469
|
+
def self.dummy(size = 16)
|
|
470
|
+
Reg.new(self, 0, size, :dummy, init_as_writable: true)
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
# Returns each named bit collection contained in the register,
|
|
474
|
+
def named_bits(options = {})
|
|
475
|
+
options = {
|
|
476
|
+
include_spacers: false
|
|
477
|
+
}.merge(options)
|
|
478
|
+
|
|
479
|
+
# test if @lookup has any values stored as an array
|
|
480
|
+
# if so it means there is a split group of bits
|
|
481
|
+
# process that differently to a single bit or continuous range of bits
|
|
482
|
+
# which are typically stored in a hash
|
|
483
|
+
|
|
484
|
+
split_bits = false
|
|
485
|
+
@lookup.each { |_k, v| split_bits = true if v.is_a? Array }
|
|
486
|
+
|
|
487
|
+
if split_bits == false
|
|
488
|
+
current_pos = size
|
|
489
|
+
# Sort by position descending
|
|
490
|
+
@lookup.sort_by { |_name, details| -details[:pos] }.each do |name, details|
|
|
491
|
+
pos = details[:bits] + details[:pos]
|
|
492
|
+
if options[:include_spacers] && (pos != current_pos)
|
|
493
|
+
collection = BitCollection.dummy(self, nil, size: current_pos - pos, pos: pos)
|
|
494
|
+
yield nil, collection
|
|
495
|
+
end
|
|
496
|
+
collection = BitCollection.new(self, name)
|
|
497
|
+
details[:bits].times do |i|
|
|
498
|
+
collection << @bits[details[:pos] + i]
|
|
499
|
+
end
|
|
500
|
+
yield name, collection
|
|
501
|
+
current_pos = details[:pos]
|
|
502
|
+
end
|
|
503
|
+
if options[:include_spacers] && current_pos != 0
|
|
504
|
+
collection = BitCollection.dummy(self, nil, size: current_pos, pos: 0)
|
|
505
|
+
yield nil, collection
|
|
506
|
+
end
|
|
507
|
+
elsif split_bits == true # if there are split bits, need to convert all regsiter bit values to array elements to allow sorting
|
|
508
|
+
|
|
509
|
+
# if the register has bits split up across it, then store the bits in order of decreasing reg position
|
|
510
|
+
# but first, stuff all the bits in a simple array, as single bits, or ranges of bits
|
|
511
|
+
|
|
512
|
+
@lookup_splits = []
|
|
513
|
+
@lookup.each do |k, v|
|
|
514
|
+
tempbit = {}
|
|
515
|
+
bitcounter = {}
|
|
516
|
+
if v.is_a? Hash
|
|
517
|
+
# then this is already a single bit or a continuous range so just stuff it into the array
|
|
518
|
+
tempbit[k] = v
|
|
519
|
+
@lookup_splits << tempbit.clone
|
|
520
|
+
elsif v.is_a? Array
|
|
521
|
+
# if the bitgroup is split, then decompose into single bits and continuous ranges
|
|
522
|
+
v.each_with_index do |bitdetail, _i|
|
|
523
|
+
if bitcounter.key?(k)
|
|
524
|
+
bitcounter[k] = bitcounter[k] + bitdetail[:bits]
|
|
525
|
+
else
|
|
526
|
+
bitcounter[k] = bitdetail[:bits]
|
|
527
|
+
end
|
|
528
|
+
tempbit[k] = bitdetail
|
|
529
|
+
@lookup_splits << tempbit.clone
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
if v.is_a? Array
|
|
533
|
+
@lookup_splits.each_with_index do |_e, q|
|
|
534
|
+
groupname = @lookup_splits[q].to_a[0][0]
|
|
535
|
+
if groupname == k
|
|
536
|
+
@lookup_splits[q][groupname][:bitgrouppos] = bitcounter[groupname] if groupname == k
|
|
537
|
+
bitcounter[groupname] = bitcounter[groupname] - @lookup_splits[q][groupname][:bits]
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
# Now sort the array in descending order
|
|
543
|
+
# Does adding the bitgrouppos need to happen after the sort ?
|
|
544
|
+
@lookup_splits = @lookup_splits.sort do |a, b|
|
|
545
|
+
b.to_a[0][1][:pos] <=> a.to_a[0][1][:pos]
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
current_pos = size
|
|
549
|
+
countbits = {} # if countbits.method == nil
|
|
550
|
+
|
|
551
|
+
@master = {}
|
|
552
|
+
bitgroup = {}
|
|
553
|
+
bitinfo = {}
|
|
554
|
+
info = {}
|
|
555
|
+
|
|
556
|
+
@lookup_splits.each_with_index do |hash, _i|
|
|
557
|
+
name = hash.to_a[0][0]
|
|
558
|
+
details = hash.to_a[0][1]
|
|
559
|
+
bitcounter = hash.to_a[0][1][:bitgrouppos]
|
|
560
|
+
pos = details[:bits] + details[:pos]
|
|
561
|
+
if options[:include_spacers] && (pos != current_pos)
|
|
562
|
+
collection = BitCollection.dummy(self, nil, size: current_pos - pos, pos: pos)
|
|
563
|
+
yield nil, collection, bitcounter
|
|
564
|
+
end
|
|
565
|
+
collection = BitCollection.new(self, name)
|
|
566
|
+
details[:bits].times do |i|
|
|
567
|
+
collection << @bits[details[:pos] + i]
|
|
568
|
+
end
|
|
569
|
+
yield name, collection, bitcounter
|
|
570
|
+
current_pos = details[:pos]
|
|
571
|
+
end
|
|
572
|
+
if options[:include_spacers] && current_pos != 0
|
|
573
|
+
collection = BitCollection.dummy(self, nil, size: current_pos, pos: 0)
|
|
574
|
+
yield nil, collection, bitcounter
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
# Returns each named bit collection contained in self
|
|
580
|
+
def reverse_named_bits(_options = {})
|
|
581
|
+
bits = []
|
|
582
|
+
named_bits { |name, bit| bits << [name, bit] }
|
|
583
|
+
bits.each do |bit|
|
|
584
|
+
yield bit[0], bit[1]
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
# Returns an array of occupied bit positions
|
|
589
|
+
# ==== Example
|
|
590
|
+
# reg :fstat, @base + 0x0000, :size => 8 do
|
|
591
|
+
# bit 7, :ccif
|
|
592
|
+
# bit 6, :rdcolerr
|
|
593
|
+
# bit 5, :accerr
|
|
594
|
+
# bit 4, :pviol
|
|
595
|
+
# bit 0, :mgstat0
|
|
596
|
+
# end
|
|
597
|
+
# regs(:fstat).used_bits
|
|
598
|
+
# => [0, 4, 5, 6, 7]
|
|
599
|
+
#
|
|
600
|
+
# ==== Example
|
|
601
|
+
# reg :aguahb2, @base + 0x2A, :size => 8 do
|
|
602
|
+
# bit 5..2, :m0b_hbstrb, :reset => 0x0
|
|
603
|
+
# bit 1..0, :m0b_htrans, :reset => 0x2
|
|
604
|
+
# end
|
|
605
|
+
# regs(:aguahb2).used_bits
|
|
606
|
+
# => [0, 1, 2, 3, 4, 5]
|
|
607
|
+
def used_bits(_options = {})
|
|
608
|
+
used_bits = []
|
|
609
|
+
named_bits do |_name, bit|
|
|
610
|
+
used_bits << bit.position if bit.size == 1
|
|
611
|
+
if bit.size > 1
|
|
612
|
+
used_bits << ((bit.position)..(bit.position + bit.size - 1)).to_a
|
|
613
|
+
end
|
|
614
|
+
end
|
|
615
|
+
used_bits.flatten!
|
|
616
|
+
used_bits.sort!
|
|
617
|
+
used_bits
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
# Returns true if any named_bits exist, false if used_bits is an empty array
|
|
621
|
+
def used_bits?(_options = {})
|
|
622
|
+
used_bits.size > 0
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
# Returns an array of unoccupied bit positions
|
|
626
|
+
# ==== Example
|
|
627
|
+
# reg :fstat, @base + 0x0000, :size => 8 do
|
|
628
|
+
# bit 7, :ccif
|
|
629
|
+
# bit 6, :rdcolerr
|
|
630
|
+
# bit 5, :accerr
|
|
631
|
+
# bit 4, :pviol
|
|
632
|
+
# bit 0, :mgstat0
|
|
633
|
+
# end
|
|
634
|
+
# regs(:fstat).empty_bits
|
|
635
|
+
# => [1, 2, 3]
|
|
636
|
+
#
|
|
637
|
+
# ==== Example
|
|
638
|
+
# reg :aguahb2, @base + 0x2A, :size => 8 do
|
|
639
|
+
# bit 5..2, :m0b_hbstrb, :reset => 0x0
|
|
640
|
+
# bit 1..0, :m0b_htrans, :reset => 0x2
|
|
641
|
+
# end
|
|
642
|
+
# regs(:aguahb2).empty_bits
|
|
643
|
+
# => [6, 7]
|
|
644
|
+
def empty_bits(_options = {})
|
|
645
|
+
array_span = (0..(size - 1)).to_a
|
|
646
|
+
empty_bits = array_span - used_bits
|
|
647
|
+
empty_bits
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
# Returns true if any named_bits exist, false if used_bits is an empty array
|
|
651
|
+
def empty_bits?(_options = {})
|
|
652
|
+
empty_bits.size > 0
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
# Proxies requests from bit collections to the register owner
|
|
656
|
+
def request(operation, options = {}) # :nodoc:
|
|
657
|
+
if operation == :read_register
|
|
658
|
+
object = reader
|
|
659
|
+
owner.read_register_missing!(self) unless object
|
|
660
|
+
else
|
|
661
|
+
object = writer
|
|
662
|
+
owner.write_register_missing!(self) unless object
|
|
663
|
+
end
|
|
664
|
+
object.send(operation, self, options)
|
|
665
|
+
self
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
# Returns the object that will be responsible for writing the given register
|
|
669
|
+
def writer
|
|
670
|
+
@writer ||= lookup_operation_handler(:write_register)
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
# Returns the object that will be responsible for reading the given register
|
|
674
|
+
def reader
|
|
675
|
+
@reader ||= lookup_operation_handler(:read_register)
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
# @api private
|
|
679
|
+
def lookup_operation_handler(operation)
|
|
680
|
+
# Could have made the controller be the owner when assigned above, but may have run
|
|
681
|
+
# into problems with the reg meta data stuff
|
|
682
|
+
reg_owner = owner.respond_to?(:controller) && owner.controller ? owner.controller : owner
|
|
683
|
+
if reg_owner.respond_to?(operation)
|
|
684
|
+
reg_owner
|
|
685
|
+
elsif reg_owner.respond_to?(:owner) && reg_owner.owner.respond_to?(operation)
|
|
686
|
+
reg_owner.owner
|
|
687
|
+
elsif Origen.top_level && Origen.top_level.respond_to?(operation)
|
|
688
|
+
Origen.top_level
|
|
689
|
+
end
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
# Returns the relative address of the given register, equivalent to calling
|
|
693
|
+
# reg.address(:relative => true)
|
|
694
|
+
def offset
|
|
695
|
+
address(relative: true)
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
# Returns the register address added to its current base_address value (if any).
|
|
699
|
+
#
|
|
700
|
+
# @param [Hash] options
|
|
701
|
+
# @option options [Boolean] :relative (false) Return the address without adding the base address (if present)
|
|
702
|
+
def address(options = {})
|
|
703
|
+
options = {
|
|
704
|
+
relative: false
|
|
705
|
+
}.merge(options)
|
|
706
|
+
address = @address
|
|
707
|
+
domain_option = options[:domains] || options[:domain]
|
|
708
|
+
@domain_option ||= domain_option unless frozen?
|
|
709
|
+
# Blow the cache when the domain option changes
|
|
710
|
+
@base_address_applied = nil unless @domain_option == domain_option
|
|
711
|
+
unless @base_address_applied
|
|
712
|
+
# Give highest priority to the original API which allowed the object
|
|
713
|
+
# doing register read/write to define a base_address method
|
|
714
|
+
if (writer && writer.methods.include?(:base_address) && writer.method(:base_address).arity != 0) ||
|
|
715
|
+
(reader && reader.methods.include?(:base_address) && reader.method(:base_address).arity != 0)
|
|
716
|
+
# This currently assumes that the base address is always the same
|
|
717
|
+
# for reading and writing
|
|
718
|
+
if writer && writer.respond_to?(:base_address) && writer.method(:base_address).arity != 0
|
|
719
|
+
self.base_address = writer.base_address(self)
|
|
720
|
+
elsif reader && reader.respond_to?(:base_address) && reader.method(:base_address).arity != 0
|
|
721
|
+
self.base_address = reader.base_address(self)
|
|
722
|
+
end
|
|
723
|
+
else
|
|
724
|
+
o = owner.is_a?(Container) ? owner.owner : owner
|
|
725
|
+
d = domain_option || domains
|
|
726
|
+
if o && o.reg_base_address(domain: d)
|
|
727
|
+
self.base_address = o.reg_base_address(domain: d)
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
@base_address_applied = true
|
|
731
|
+
end
|
|
732
|
+
unless options[:relative]
|
|
733
|
+
address += base_address if base_address
|
|
734
|
+
end
|
|
735
|
+
if options[:address_type]
|
|
736
|
+
Origen.deprecate 'Specifying the address_type of a register address will be removed from Origen 3'
|
|
737
|
+
case options[:address_type]
|
|
738
|
+
when :byte
|
|
739
|
+
address = address * 2
|
|
740
|
+
when :word
|
|
741
|
+
address = address
|
|
742
|
+
when :longword
|
|
743
|
+
address = address / 2
|
|
744
|
+
else
|
|
745
|
+
fail 'Unknown address type requested!'
|
|
746
|
+
end
|
|
747
|
+
end
|
|
748
|
+
address
|
|
749
|
+
end
|
|
750
|
+
alias_method :addr, :address
|
|
751
|
+
|
|
752
|
+
# Returns true if the register owner matches the given name. A match will be detected
|
|
753
|
+
# if the class names of the register's owner contains the given name.
|
|
754
|
+
#
|
|
755
|
+
# Alternatively if the register owner implements a method called reg_owner_alias
|
|
756
|
+
# then the value that this returns instead will also be considered when checking if the given
|
|
757
|
+
# name matches. This method can return an array of names if multiple aliases are required.
|
|
758
|
+
#
|
|
759
|
+
# Aliases can be useful for de-coupling the commonly used name, e.g. "NVM" from the actual
|
|
760
|
+
# class name.
|
|
761
|
+
#
|
|
762
|
+
# @example
|
|
763
|
+
# class C90NVM
|
|
764
|
+
# include Origen::Registers
|
|
765
|
+
#
|
|
766
|
+
# def initialize
|
|
767
|
+
# add_reg :clkdiv, 0x3, 16, :div => {:bits => 8}
|
|
768
|
+
# end
|
|
769
|
+
#
|
|
770
|
+
# end
|
|
771
|
+
#
|
|
772
|
+
# reg = C90NVM.new.reg(:clkdiv)
|
|
773
|
+
# reg.owned_by?(:ram) # => false
|
|
774
|
+
# reg.owned_by?(:nvm) # => true
|
|
775
|
+
# reg.owned_by?(:c90nvm) # => true
|
|
776
|
+
# reg.owned_by?(:c40nvm) # => false
|
|
777
|
+
# reg.owned_by?(:flash) # => false
|
|
778
|
+
#
|
|
779
|
+
# @example Using an alias
|
|
780
|
+
# class C90NVM
|
|
781
|
+
# include Origen::Registers
|
|
782
|
+
#
|
|
783
|
+
# def initialize
|
|
784
|
+
# add_reg :clkdiv, 0x3, 16, :div => {:bits => 8}
|
|
785
|
+
# end
|
|
786
|
+
#
|
|
787
|
+
# def reg_owner_alias
|
|
788
|
+
# "flash"
|
|
789
|
+
# end
|
|
790
|
+
#
|
|
791
|
+
# end
|
|
792
|
+
#
|
|
793
|
+
# reg = C90NVM.new.reg(:clkdiv)
|
|
794
|
+
# reg.owned_by?(:ram) # => false
|
|
795
|
+
# reg.owned_by?(:nvm) # => true
|
|
796
|
+
# reg.owned_by?(:c90nvm) # => true
|
|
797
|
+
# reg.owned_by?(:c40nvm) # => false
|
|
798
|
+
# reg.owned_by?(:flash) # => true
|
|
799
|
+
def owned_by?(name)
|
|
800
|
+
!!(owner.class.to_s =~ /#{name}/i) || begin
|
|
801
|
+
if owner.respond_to?(:reg_owner_alias)
|
|
802
|
+
[owner.reg_owner_alias].flatten.any? do |al|
|
|
803
|
+
al.to_s =~ /#{name}/i
|
|
804
|
+
end
|
|
805
|
+
else
|
|
806
|
+
false
|
|
807
|
+
end
|
|
808
|
+
end
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
# Returns true if the register contains a bit(s) matching the given name
|
|
812
|
+
# ==== Example
|
|
813
|
+
# add_reg :control, 0x55, :status => {:pos => 1}
|
|
814
|
+
#
|
|
815
|
+
# reg(:control).has_bit?(:result) # => false
|
|
816
|
+
# reg(:control).has_bit?(:status) # => true
|
|
817
|
+
def has_bit?(name)
|
|
818
|
+
@lookup.include?(name)
|
|
819
|
+
end
|
|
820
|
+
alias_method :has_bits?, :has_bit?
|
|
821
|
+
alias_method :has_bit, :has_bit?
|
|
822
|
+
alias_method :has_bits, :has_bit?
|
|
823
|
+
|
|
824
|
+
# Add a bit to the register, should only be called internally
|
|
825
|
+
def add_bit(id, position, options = {}) # :nodoc:
|
|
826
|
+
options = { data: @bits[position].data, # If undefined preserve any data/reset value that has
|
|
827
|
+
res: @bits[position].data, # already been applied at reg level
|
|
828
|
+
}.merge(options)
|
|
829
|
+
|
|
830
|
+
@lookup[id] = { pos: position, bits: 1, feature: options[:feature] }
|
|
831
|
+
@bits.delete_at(position) # Remove the initial bit from this position
|
|
832
|
+
|
|
833
|
+
@bits.insert(position, Bit.new(self, position, options))
|
|
834
|
+
self
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
# Add a bus to the register, should only be called internally
|
|
838
|
+
def add_bus(id, position, size, options = {}) # :nodoc:
|
|
839
|
+
default_data = 0
|
|
840
|
+
size.times do |n|
|
|
841
|
+
default_data |= @bits[position + n].data << n
|
|
842
|
+
end
|
|
843
|
+
options = { data: default_data, # If undefined preserve any data/reset value that has
|
|
844
|
+
res: default_data, # already been applied at reg level
|
|
845
|
+
}.merge(options)
|
|
846
|
+
|
|
847
|
+
@lookup[id] = { pos: position, bits: size }
|
|
848
|
+
size.times do |n|
|
|
849
|
+
bit_options = options.dup
|
|
850
|
+
bit_options[:data] = options[:data][n]
|
|
851
|
+
if options[:res].is_a?(Symbol)
|
|
852
|
+
bit_options[:res] = options[:res]
|
|
853
|
+
else
|
|
854
|
+
bit_options[:res] = options[:res][n]
|
|
855
|
+
end
|
|
856
|
+
@bits.delete_at(position + n)
|
|
857
|
+
@bits.insert(position + n, Bit.new(self, position + n, bit_options))
|
|
858
|
+
end
|
|
859
|
+
self
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
def add_bus_scramble(id, array_of_hashes = [])
|
|
863
|
+
array_of_hashes.each do |options|
|
|
864
|
+
bind(id, options.delete(:bind)) if options[:bind]
|
|
865
|
+
position = options[:pos] || 0
|
|
866
|
+
num_bits = options[:bits] || 1
|
|
867
|
+
size = options[:bits]
|
|
868
|
+
options[:data] = options[:data] if options[:data]
|
|
869
|
+
options[:res] = options[:reset] if options[:reset]
|
|
870
|
+
default_data = 0
|
|
871
|
+
size.times do |n|
|
|
872
|
+
default_data |= @bits[position + n].data << n
|
|
873
|
+
end
|
|
874
|
+
options = { data: default_data, # If undefined preserve any data/reset value that has
|
|
875
|
+
res: default_data, # already been applied at reg level
|
|
876
|
+
}.merge(options)
|
|
877
|
+
|
|
878
|
+
@lookup[id] = [] if @lookup[id].nil?
|
|
879
|
+
@lookup[id] = @lookup[id].push(pos: position, bits: size)
|
|
880
|
+
size.times do |n|
|
|
881
|
+
bit_options = options.dup
|
|
882
|
+
bit_options[:data] = options[:data][n]
|
|
883
|
+
bit_options[:res] = options[:res][n]
|
|
884
|
+
@bits.delete_at(position + n)
|
|
885
|
+
@bits.insert(position + n, Bit.new(self, position + n, bit_options))
|
|
886
|
+
end
|
|
887
|
+
self
|
|
888
|
+
end
|
|
889
|
+
end
|
|
890
|
+
|
|
891
|
+
# Delete the bits in the collection from the register
|
|
892
|
+
def delete_bit(collection)
|
|
893
|
+
[collection.name].flatten.each do |name|
|
|
894
|
+
@lookup.delete(name)
|
|
895
|
+
end
|
|
896
|
+
collection.each do |bit|
|
|
897
|
+
@bits.delete_at(bit.position) # Remove the bit
|
|
898
|
+
@bits.insert(bit.position, Bit.new(self, bit.position, writable: @init_as_writable))
|
|
899
|
+
end
|
|
900
|
+
self
|
|
901
|
+
end
|
|
902
|
+
alias_method :delete_bits, :delete_bit
|
|
903
|
+
|
|
904
|
+
# @api private
|
|
905
|
+
def expand_range(range)
|
|
906
|
+
if range.first > range.last
|
|
907
|
+
range = Range.new(range.last, range.first)
|
|
908
|
+
end
|
|
909
|
+
range.each do |i|
|
|
910
|
+
yield i
|
|
911
|
+
end
|
|
912
|
+
end
|
|
913
|
+
|
|
914
|
+
# Returns the bit object(s) responding to the given name, wrapped in a BitCollection.
|
|
915
|
+
# This method also accepts multiple name possibilities, if neither bit exists in
|
|
916
|
+
# the register it will raise an error, otherwise it will return the first match.
|
|
917
|
+
# If no args passed in, it will return a BitCollection containing all bits.
|
|
918
|
+
# If a number is passed in then the bits from those positions are returned.
|
|
919
|
+
# ==== Example
|
|
920
|
+
# add_reg :control, 0x55, :status => {:pos => 1, :bits => 2},
|
|
921
|
+
# :fail => {:pos => 0}
|
|
922
|
+
#
|
|
923
|
+
# reg(:control).bit(:fail) # => Returns a BitCollection containing the fail bit
|
|
924
|
+
# reg(:control).bits(:status) # => Returns a BifCollection containing the status bits
|
|
925
|
+
# reg(:control).bit(:bist_fail, :fail) # => Returns a BitCollection containing the fail bit
|
|
926
|
+
# reg(:control).bit(0) # => Returns a BitCollection containing the fail bit
|
|
927
|
+
# reg(:control).bit(1) # => Returns a BitCollection containing status bit
|
|
928
|
+
# reg(:control).bit(1,2) # => Returns a BitCollection containing both status bits
|
|
929
|
+
def bit(*args)
|
|
930
|
+
# return get_bits_with_constraint(nil,:default) if args.size == 0
|
|
931
|
+
constraint = extract_feature_params(args)
|
|
932
|
+
if constraint.nil?
|
|
933
|
+
constraint = :default
|
|
934
|
+
end
|
|
935
|
+
collection = BitCollection.new(self, :unknown)
|
|
936
|
+
if args.size == 0
|
|
937
|
+
collection.add_name(name)
|
|
938
|
+
@bits.each do |bit|
|
|
939
|
+
collection << get_bits_with_constraint(bit.position, constraint)
|
|
940
|
+
end
|
|
941
|
+
else
|
|
942
|
+
args.flatten!
|
|
943
|
+
args.sort!
|
|
944
|
+
args.each do |arg_item|
|
|
945
|
+
if arg_item.is_a?(Fixnum)
|
|
946
|
+
b = get_bits_with_constraint(arg_item, constraint)
|
|
947
|
+
collection << b if b
|
|
948
|
+
elsif arg_item.is_a?(Range)
|
|
949
|
+
expand_range(arg_item) do |bit_number|
|
|
950
|
+
collection << get_bits_with_constraint(bit_number, constraint)
|
|
951
|
+
end
|
|
952
|
+
else
|
|
953
|
+
# Reaches here if bit name is specified
|
|
954
|
+
|
|
955
|
+
if @lookup.include?(arg_item)
|
|
956
|
+
split_bits = false
|
|
957
|
+
@lookup.each { |_k, v| split_bits = true if v.is_a? Array }
|
|
958
|
+
coll = get_lookup_feature_bits(arg_item, constraint, split_bits)
|
|
959
|
+
if coll
|
|
960
|
+
coll.each do |b|
|
|
961
|
+
collection.add_name(arg_item)
|
|
962
|
+
collection << b
|
|
963
|
+
end
|
|
964
|
+
end
|
|
965
|
+
end
|
|
966
|
+
end
|
|
967
|
+
end
|
|
968
|
+
end
|
|
969
|
+
if collection.size == 0
|
|
970
|
+
# Originally Origen returned nil when asking for a bit via an index which does not
|
|
971
|
+
# exist, e.g. reg[1000] => nil
|
|
972
|
+
# The args numeric clause here is to maintain that behavior
|
|
973
|
+
if Origen.config.strict_errors && !args.all? { |arg| arg.is_a?(Numeric) }
|
|
974
|
+
puts "Register #{@name} does not have a bits(s) named :#{args.join(', :')} or it might not be enabled."
|
|
975
|
+
puts 'This could also be a typo, these are the valid bit names:'
|
|
976
|
+
puts @lookup.keys
|
|
977
|
+
fail 'Missing bits error!'
|
|
978
|
+
end
|
|
979
|
+
nil
|
|
980
|
+
else
|
|
981
|
+
collection
|
|
982
|
+
end
|
|
983
|
+
end
|
|
984
|
+
alias_method :bits, :bit
|
|
985
|
+
alias_method :[], :bit
|
|
986
|
+
|
|
987
|
+
def get_bits_with_constraint(number, params)
|
|
988
|
+
return nil unless @bits[number]
|
|
989
|
+
if (params == :default || !params) && @bits[number].enabled?
|
|
990
|
+
@bits[number]
|
|
991
|
+
elsif params == :none && !@bits[number].has_feature_constraint?
|
|
992
|
+
@bits[number]
|
|
993
|
+
elsif params == :all
|
|
994
|
+
@bits[number]
|
|
995
|
+
elsif params.class == Array
|
|
996
|
+
params.each do |param|
|
|
997
|
+
unless @bits[number].enabled_by_feature?(param)
|
|
998
|
+
return nil
|
|
999
|
+
end
|
|
1000
|
+
@bits[number]
|
|
1001
|
+
end
|
|
1002
|
+
elsif @bits[number].enabled_by_feature?(params)
|
|
1003
|
+
@bits[number]
|
|
1004
|
+
else
|
|
1005
|
+
return Bit.new(self, number, writable: false)
|
|
1006
|
+
end
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
def get_lookup_feature_bits(bit_name, params, split_group_reg)
|
|
1010
|
+
##
|
|
1011
|
+
if split_group_reg == false # if this register has single bits and continuous ranges
|
|
1012
|
+
|
|
1013
|
+
if @lookup.include?(bit_name)
|
|
1014
|
+
collection = BitCollection.new(self, bit_name)
|
|
1015
|
+
(@lookup[bit_name][:bits]).times do |i|
|
|
1016
|
+
collection << @bits[@lookup[bit_name][:pos] + i]
|
|
1017
|
+
end
|
|
1018
|
+
if !params || params == :default
|
|
1019
|
+
if collection.enabled?
|
|
1020
|
+
return collection
|
|
1021
|
+
end
|
|
1022
|
+
elsif params == :none
|
|
1023
|
+
unless collection.has_feature_constraint?
|
|
1024
|
+
return collection
|
|
1025
|
+
end
|
|
1026
|
+
elsif params == :all
|
|
1027
|
+
return collection
|
|
1028
|
+
elsif params.class == Array
|
|
1029
|
+
if params.all? { |param| collection.enabled_by_feature?(param) }
|
|
1030
|
+
return collection
|
|
1031
|
+
end
|
|
1032
|
+
else
|
|
1033
|
+
if collection.enabled_by_feature?(params)
|
|
1034
|
+
return collection
|
|
1035
|
+
end
|
|
1036
|
+
end
|
|
1037
|
+
return BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name][:pos])
|
|
1038
|
+
else
|
|
1039
|
+
return []
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
elsif split_group_reg == true # if this registers has split bits in its range
|
|
1043
|
+
if @lookup.is_a?(Hash) # && @lookup.include?(bit_name)
|
|
1044
|
+
collection = false
|
|
1045
|
+
@lookup.each do |k, v| # k is the bitname, v is the hash of bit data
|
|
1046
|
+
if k == bit_name
|
|
1047
|
+
collection ||= BitCollection.new(self, k)
|
|
1048
|
+
if v.is_a?(Array)
|
|
1049
|
+
v.reverse_each do |pb| # loop each piece of bit group data
|
|
1050
|
+
(pb[:bits]).times do |i|
|
|
1051
|
+
collection << @bits[pb[:pos] + i]
|
|
1052
|
+
end
|
|
1053
|
+
end
|
|
1054
|
+
else
|
|
1055
|
+
(v[:bits]).times do |i|
|
|
1056
|
+
collection << @bits[v[:pos] + i]
|
|
1057
|
+
end
|
|
1058
|
+
end
|
|
1059
|
+
end
|
|
1060
|
+
end
|
|
1061
|
+
if !params || params == :default
|
|
1062
|
+
if collection.enabled?
|
|
1063
|
+
return collection
|
|
1064
|
+
end
|
|
1065
|
+
elsif params == :none
|
|
1066
|
+
unless collection.has_feature_constraint?
|
|
1067
|
+
return collection
|
|
1068
|
+
end
|
|
1069
|
+
elsif params == :all
|
|
1070
|
+
return collection
|
|
1071
|
+
elsif params.class == Array
|
|
1072
|
+
if params.all? { |param| collection.enabled_by_feature?(param) }
|
|
1073
|
+
return collection
|
|
1074
|
+
end
|
|
1075
|
+
else
|
|
1076
|
+
if collection.enabled_by_feature?(params)
|
|
1077
|
+
return collection
|
|
1078
|
+
end
|
|
1079
|
+
end
|
|
1080
|
+
if @lookup.is_a?(Hash) && @lookup[bit_name].is_a?(Array)
|
|
1081
|
+
return BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name][0][:pos])
|
|
1082
|
+
else
|
|
1083
|
+
return BitCollection.dummy(self, bit_name, size: collection.size, pos: @lookup[bit_name[:pos]])
|
|
1084
|
+
end
|
|
1085
|
+
else
|
|
1086
|
+
return []
|
|
1087
|
+
end
|
|
1088
|
+
end
|
|
1089
|
+
end
|
|
1090
|
+
|
|
1091
|
+
def extract_feature_params(args)
|
|
1092
|
+
index = args.find_index { |arg| arg.class == Hash }
|
|
1093
|
+
if index
|
|
1094
|
+
params = args.delete_at(index)
|
|
1095
|
+
else
|
|
1096
|
+
params = nil
|
|
1097
|
+
end
|
|
1098
|
+
|
|
1099
|
+
if params
|
|
1100
|
+
return params[:enabled_features] || params[:enabled_feature]
|
|
1101
|
+
else
|
|
1102
|
+
return nil
|
|
1103
|
+
end
|
|
1104
|
+
end
|
|
1105
|
+
|
|
1106
|
+
# All other Reg methods are delegated to BitCollection
|
|
1107
|
+
def method_missing(method, *args, &block) # :nodoc:
|
|
1108
|
+
if method.to_sym == :to_ary || method.to_sym == :to_hash
|
|
1109
|
+
nil
|
|
1110
|
+
elsif meta_data_method?(method)
|
|
1111
|
+
extract_meta_data(method, *args)
|
|
1112
|
+
else
|
|
1113
|
+
if BitCollection.instance_methods.include?(method)
|
|
1114
|
+
BitCollection.new(self, name, @bits).send(method, *args, &block)
|
|
1115
|
+
elsif has_bits?(method)
|
|
1116
|
+
bits(method)
|
|
1117
|
+
else
|
|
1118
|
+
super
|
|
1119
|
+
end
|
|
1120
|
+
end
|
|
1121
|
+
end
|
|
1122
|
+
|
|
1123
|
+
# Recognize that Reg responds to all BitCollection methods methods based on
|
|
1124
|
+
# application-specific meta data properties
|
|
1125
|
+
def respond_to?(sym) # :nodoc:
|
|
1126
|
+
sym = sym.to_sym
|
|
1127
|
+
meta_data_method?(sym) || has_bits?(sym) || super(sym) || BitCollection.instance_methods.include?(sym)
|
|
1128
|
+
end
|
|
1129
|
+
|
|
1130
|
+
# Copy overlays from one reg object to another
|
|
1131
|
+
# ==== Example
|
|
1132
|
+
# reg(:data_copy).has_overlay? # => false
|
|
1133
|
+
# reg(:data).overlay("data_val")
|
|
1134
|
+
# reg(:data_copy).copy_overlays_from(reg(:data))
|
|
1135
|
+
# reg(:data_copy).has_overlay? # => true
|
|
1136
|
+
def copy_overlays_from(reg, options = {})
|
|
1137
|
+
size.times do |i|
|
|
1138
|
+
source_bit = reg.bit[i]
|
|
1139
|
+
if source_bit.has_overlay?
|
|
1140
|
+
ov = source_bit.overlay_str
|
|
1141
|
+
# If an id has been supplied make sure any trailing ID in the source is
|
|
1142
|
+
# changed to supplied identifier
|
|
1143
|
+
ov.gsub!(/_\d$/, "_#{options[:update_id]}") if options[:update_id]
|
|
1144
|
+
@bits[i].overlay(ov)
|
|
1145
|
+
end
|
|
1146
|
+
end
|
|
1147
|
+
self
|
|
1148
|
+
end
|
|
1149
|
+
|
|
1150
|
+
# Copies data from one reg object to another
|
|
1151
|
+
# ==== Example
|
|
1152
|
+
# reg(:data_copy).data # => 0
|
|
1153
|
+
# reg(:data).write(0x1234)
|
|
1154
|
+
# reg(:data_copy).copy_data_from(reg(:data))
|
|
1155
|
+
# reg(:data_copy).data # => 0x1234
|
|
1156
|
+
def copy_data_from(reg)
|
|
1157
|
+
size.times do |i|
|
|
1158
|
+
@bits[i].write(reg.bit[i].data)
|
|
1159
|
+
end
|
|
1160
|
+
self
|
|
1161
|
+
end
|
|
1162
|
+
|
|
1163
|
+
# Copies data and overlays from one reg object to another, it does not copy
|
|
1164
|
+
# read or store flags
|
|
1165
|
+
def copy(reg)
|
|
1166
|
+
size.times do |i|
|
|
1167
|
+
source_bit = reg.bit[i]
|
|
1168
|
+
@bits[i].overlay(source_bit.overlay_str) if source_bit.has_overlay?
|
|
1169
|
+
@bits[i].write(source_bit.data)
|
|
1170
|
+
end
|
|
1171
|
+
self
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
# Returns the BITWISE AND of reg with another reg or a number, the state of
|
|
1175
|
+
# both registers remains unchanged
|
|
1176
|
+
# ==== Example
|
|
1177
|
+
# reg(:data).write(0x5555)
|
|
1178
|
+
# reg(:data2).write(0xFFFF)
|
|
1179
|
+
# reg(:data) & 0xFF00 # => 0x5500
|
|
1180
|
+
# reg(:data) & reg(:data2) # => 0x5555
|
|
1181
|
+
def &(val)
|
|
1182
|
+
data & Reg.clean_value(val)
|
|
1183
|
+
end
|
|
1184
|
+
|
|
1185
|
+
# Returns the BITWISE OR of reg with another reg or a number, the state of
|
|
1186
|
+
# both registers remains unchanged
|
|
1187
|
+
def |(val)
|
|
1188
|
+
data | Reg.clean_value(val)
|
|
1189
|
+
end
|
|
1190
|
+
|
|
1191
|
+
# Returns the SUM of reg with another reg or a number, the state of
|
|
1192
|
+
# both registers remains unchanged
|
|
1193
|
+
def +(val)
|
|
1194
|
+
data + Reg.clean_value(val)
|
|
1195
|
+
end
|
|
1196
|
+
|
|
1197
|
+
# Returns the SUBTRACTION of reg with another reg or a number, the state of
|
|
1198
|
+
# both registers remains unchanged
|
|
1199
|
+
def -(val)
|
|
1200
|
+
data - Reg.clean_value(val)
|
|
1201
|
+
end
|
|
1202
|
+
|
|
1203
|
+
# Returns the DIVISION of reg with another reg or a number, the state of
|
|
1204
|
+
# both registers remains unchanged
|
|
1205
|
+
def /(val)
|
|
1206
|
+
data / Reg.clean_value(val)
|
|
1207
|
+
end
|
|
1208
|
+
|
|
1209
|
+
# Returns the PRODUCT of reg with another reg or a number, the state of
|
|
1210
|
+
# both registers remains unchanged
|
|
1211
|
+
def *(val)
|
|
1212
|
+
data * Reg.clean_value(val)
|
|
1213
|
+
end
|
|
1214
|
+
|
|
1215
|
+
# Cleans an input value, in some cases it could be a register object, or an explicit value.
|
|
1216
|
+
# This will return an explicit value in either case.
|
|
1217
|
+
def self.clean_value(value) # :nodoc:
|
|
1218
|
+
value = value.val if value.respond_to?('val') # Pull out the data value if a reg object has been passed in
|
|
1219
|
+
value
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1222
|
+
# @api private
|
|
1223
|
+
def meta_data_method?(method)
|
|
1224
|
+
attr_name = method.to_s.gsub(/\??=?/, '').to_sym
|
|
1225
|
+
if default_reg_metadata.key?(attr_name)
|
|
1226
|
+
if method.to_s =~ /\?/
|
|
1227
|
+
[true, false].include?(default_reg_metadata[attr_name])
|
|
1228
|
+
else
|
|
1229
|
+
true
|
|
1230
|
+
end
|
|
1231
|
+
else
|
|
1232
|
+
false
|
|
1233
|
+
end
|
|
1234
|
+
end
|
|
1235
|
+
|
|
1236
|
+
def extract_meta_data(method, *args)
|
|
1237
|
+
method = method.to_s.sub('?', '')
|
|
1238
|
+
if method =~ /=/
|
|
1239
|
+
instance_variable_set("@#{method.sub('=', '')}", args.first)
|
|
1240
|
+
else
|
|
1241
|
+
instance_variable_get("@#{method}") || meta[method.to_sym]
|
|
1242
|
+
end
|
|
1243
|
+
end
|
|
1244
|
+
|
|
1245
|
+
# Returns true if the register is constrained by the given/any feature
|
|
1246
|
+
def enabled_by_feature?(name = nil)
|
|
1247
|
+
if !name
|
|
1248
|
+
!!feature
|
|
1249
|
+
else
|
|
1250
|
+
if feature.class == Array
|
|
1251
|
+
feature.each do |f|
|
|
1252
|
+
if f == name
|
|
1253
|
+
return true
|
|
1254
|
+
end
|
|
1255
|
+
end
|
|
1256
|
+
return false
|
|
1257
|
+
else
|
|
1258
|
+
return feature == name
|
|
1259
|
+
end
|
|
1260
|
+
end
|
|
1261
|
+
end
|
|
1262
|
+
alias_method :has_feature_constraint?, :enabled_by_feature?
|
|
1263
|
+
|
|
1264
|
+
# Query the owner heirarchy to see if this register is enabled
|
|
1265
|
+
def enabled?
|
|
1266
|
+
if feature
|
|
1267
|
+
value = false
|
|
1268
|
+
current_owner = self
|
|
1269
|
+
if feature.class == Array
|
|
1270
|
+
feature.each do |f|
|
|
1271
|
+
current_owner = self
|
|
1272
|
+
loop do
|
|
1273
|
+
if current_owner.respond_to?(:owner)
|
|
1274
|
+
current_owner = current_owner.owner
|
|
1275
|
+
if current_owner.respond_to?(:has_feature?)
|
|
1276
|
+
if current_owner.has_feature?(f)
|
|
1277
|
+
value = true
|
|
1278
|
+
break
|
|
1279
|
+
end
|
|
1280
|
+
end
|
|
1281
|
+
else # if current owner does not have a owner
|
|
1282
|
+
value = false
|
|
1283
|
+
break
|
|
1284
|
+
end
|
|
1285
|
+
end # loop end
|
|
1286
|
+
unless value
|
|
1287
|
+
if Origen.top_level && \
|
|
1288
|
+
Origen.top_level.respond_to?(:has_feature?) && \
|
|
1289
|
+
Origen.top_level.has_feature?(f)
|
|
1290
|
+
value = true
|
|
1291
|
+
unless value
|
|
1292
|
+
break
|
|
1293
|
+
end
|
|
1294
|
+
end
|
|
1295
|
+
end
|
|
1296
|
+
unless value
|
|
1297
|
+
break # break if feature not found and return false
|
|
1298
|
+
end
|
|
1299
|
+
end # iterated through all features in array
|
|
1300
|
+
return value
|
|
1301
|
+
else # if feature.class != Array
|
|
1302
|
+
loop do
|
|
1303
|
+
if current_owner.respond_to?(:owner)
|
|
1304
|
+
current_owner = current_owner.owner
|
|
1305
|
+
if current_owner.respond_to?(:has_feature?)
|
|
1306
|
+
if current_owner.has_feature?(feature)
|
|
1307
|
+
value = true
|
|
1308
|
+
break
|
|
1309
|
+
end
|
|
1310
|
+
end
|
|
1311
|
+
else # if current owner does not have a owner
|
|
1312
|
+
value = false
|
|
1313
|
+
break
|
|
1314
|
+
end
|
|
1315
|
+
end # loop end
|
|
1316
|
+
unless value
|
|
1317
|
+
if Origen.top_level && \
|
|
1318
|
+
Origen.top_level.respond_to?(:has_feature?) && \
|
|
1319
|
+
Origen.top_level.has_feature?(feature)
|
|
1320
|
+
value = true
|
|
1321
|
+
end
|
|
1322
|
+
end
|
|
1323
|
+
return value
|
|
1324
|
+
end
|
|
1325
|
+
else
|
|
1326
|
+
return true
|
|
1327
|
+
end
|
|
1328
|
+
end
|
|
1329
|
+
|
|
1330
|
+
# Returns true if any of the bits within this register has feature
|
|
1331
|
+
# associated with it.
|
|
1332
|
+
def has_bits_enabled_by_feature?(name = nil)
|
|
1333
|
+
if !name
|
|
1334
|
+
bits.any?(&:has_feature_constraint?)
|
|
1335
|
+
else
|
|
1336
|
+
bits.any? { |bit| bit.enabled_by_feature?(name) }
|
|
1337
|
+
end
|
|
1338
|
+
end
|
|
1339
|
+
|
|
1340
|
+
private
|
|
1341
|
+
|
|
1342
|
+
def _state_desc(bits)
|
|
1343
|
+
state = []
|
|
1344
|
+
unless bits.readable? && bits.writable?
|
|
1345
|
+
if bits.readable?
|
|
1346
|
+
state << 'RO'
|
|
1347
|
+
else
|
|
1348
|
+
state << 'WO'
|
|
1349
|
+
end
|
|
1350
|
+
end
|
|
1351
|
+
state << 'Rd' if bits.is_to_be_read?
|
|
1352
|
+
state << 'Str' if bits.is_to_be_stored?
|
|
1353
|
+
state << 'Ov' if bits.has_overlay?
|
|
1354
|
+
if state.empty?
|
|
1355
|
+
''
|
|
1356
|
+
else
|
|
1357
|
+
"(#{state.join('|')})"
|
|
1358
|
+
end
|
|
1359
|
+
end
|
|
1360
|
+
|
|
1361
|
+
def _max_bit_in_range(bits, max, _min)
|
|
1362
|
+
upper = bits.position + bits.size - 1
|
|
1363
|
+
[upper, max].min - bits.position
|
|
1364
|
+
end
|
|
1365
|
+
|
|
1366
|
+
def _min_bit_in_range(bits, _max, min)
|
|
1367
|
+
lower = bits.position
|
|
1368
|
+
[lower, min].max - bits.position
|
|
1369
|
+
end
|
|
1370
|
+
|
|
1371
|
+
# Returns true if some portion of the given bits falls
|
|
1372
|
+
# within the given range
|
|
1373
|
+
def _bit_in_range?(bits, max, min)
|
|
1374
|
+
upper = bits.position + bits.size - 1
|
|
1375
|
+
lower = bits.position
|
|
1376
|
+
!((lower > max) || (upper < min))
|
|
1377
|
+
end
|
|
1378
|
+
|
|
1379
|
+
# Returns the number of bits from the given bits that
|
|
1380
|
+
# fall within the given range
|
|
1381
|
+
def _num_bits_in_range(bits, max, min)
|
|
1382
|
+
upper = bits.position + bits.size - 1
|
|
1383
|
+
lower = bits.position
|
|
1384
|
+
[upper, max].min - [lower, min].max + 1
|
|
1385
|
+
end
|
|
1386
|
+
|
|
1387
|
+
# Returns true if the given number is is the
|
|
1388
|
+
# given range
|
|
1389
|
+
def _index_in_range?(i, max, min)
|
|
1390
|
+
!((i > max) || (i < min))
|
|
1391
|
+
end
|
|
1392
|
+
|
|
1393
|
+
def _bit_rw(bits)
|
|
1394
|
+
if bits.readable? && bits.writable?
|
|
1395
|
+
'RW'
|
|
1396
|
+
elsif bits.readable?
|
|
1397
|
+
'RO'
|
|
1398
|
+
elsif bits.writable?
|
|
1399
|
+
'WO'
|
|
1400
|
+
else
|
|
1401
|
+
'X'
|
|
1402
|
+
end
|
|
1403
|
+
end
|
|
1404
|
+
end
|
|
1405
|
+
end
|
|
1406
|
+
end
|