cross_origen 0.5.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 20fb4952ec7d0da9dcad3673c0442cbc1b79afc3
4
+ data.tar.gz: 8b55d120f0783322f057ba2db4fc638d063f1443
5
+ SHA512:
6
+ metadata.gz: 513b242817d94cd5b7f7614ca14087150e9e5cbcad31995e9eea344493d35bf525a6b9d52a268702b0d3ec73b44f31338d0d755e80b30fbcfec1d6a4183fe038
7
+ data.tar.gz: 9b767385a47a1f14319b4c22e4feb4c575f4aef07f615a70f376f12998623921642eff97e9b8dc9940b4248a7074b78923c81ebf76fc64dde058bc5c3cd1cc7e
@@ -0,0 +1,78 @@
1
+ class CrossOrigenApplication < Origen::Application
2
+
3
+ # See http://origen.freescale.net/origen/latest/api/Origen/Application/Configuration.html
4
+ # for a full list of the configuration options available
5
+
6
+ config.lint_test = {
7
+ # Require the lint tests to pass before allowing a release to proceed
8
+ :run_on_tag => true,
9
+ # Auto correct violations where possible whenever 'origen lint' is run
10
+ :auto_correct => true,
11
+ # Limit the testing for large legacy applications
12
+ #:level => :easy,
13
+ # Run on these directories/files by default
14
+ #:files => ["lib", "config/application.rb"],
15
+ }
16
+
17
+ # Prevent these from showing up in 'origen rc unman'
18
+ config.unmanaged_dirs = %w()
19
+ config.unmanaged_files = %w()
20
+
21
+ # This information is used in headers and email templates, set it specific
22
+ # to your application
23
+ config.name = "Cross Origen"
24
+ config.initials = "CrossOrigen"
25
+ config.rc_url = "git@github.com:Origen-SDK/cross_origen.git"
26
+ config.release_externally = true
27
+
28
+ config.web_directory = "git@github.com:Origen-SDK/Origen-SDK.github.io.git/cross_origen"
29
+ config.web_domain = "http://origen-sdk.org/cross_origen"
30
+
31
+ # When false Origen will be less strict about checking for some common coding errors,
32
+ # it is recommended that you leave this to true for better feedback and easier debug.
33
+ # This will be the default setting in Origen v3.
34
+ config.strict_errors = true
35
+
36
+ config.semantically_version = true
37
+
38
+ # By default all generated output will end up in ./output.
39
+ # Here you can specify an alternative directory entirely, or make it dynamic such that
40
+ # the output ends up in a setup specific directory.
41
+ #config.output_directory do
42
+ # "#{Origen.root}/output/#{$dut.class}"
43
+ #end
44
+
45
+ # Similary for the reference files, generally you want to setup the reference directory
46
+ # structure to mirror that of your output directory structure.
47
+ #config.reference_directory do
48
+ # "#{Origen.root}/.ref/#{$dut.class}"
49
+ #end
50
+
51
+ # Ensure that all tests pass before allowing a release to continue
52
+ def validate_release
53
+ if !system("origen test")
54
+ puts "Sorry but you can't release with failing tests, please fix them and try again."
55
+ exit 1
56
+ else
57
+ puts "All tests passing, proceeding with the release process!"
58
+ end
59
+ end
60
+
61
+ # Run the tests before deploying to generate test coverage numbers
62
+ def before_deploy_site
63
+ Dir.chdir Origen.root do
64
+ system "origen test -c"
65
+ dir = "#{Origen.root}/web/output/coverage"
66
+ FileUtils.remove_dir(dir, true) if File.exists?(dir)
67
+ system "mv #{Origen.root}/coverage #{dir}"
68
+ end
69
+ end
70
+
71
+ # This will automatically deploy your documentation after every tag
72
+ def after_release_email(tag, note, type, selector, options)
73
+ command = "origen web compile --remote --api"
74
+ Dir.chdir Origen.root do
75
+ system command
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,47 @@
1
+ # This file should be used to extend origen with application specific tasks
2
+
3
+ aliases ={
4
+
5
+ }
6
+
7
+ @command = aliases[@command] || @command
8
+
9
+ case @command
10
+
11
+ when "specs"
12
+ require "rspec"
13
+ exit RSpec::Core::Runner.run(['spec'])
14
+
15
+ when "examples", "test"
16
+ status = 0
17
+
18
+ ARGV = %w(templates/test -t debug -r approved)
19
+ load "origen/commands/compile.rb"
20
+
21
+ if Origen.app.stats.changed_files == 0 &&
22
+ Origen.app.stats.new_files == 0 &&
23
+ Origen.app.stats.changed_patterns == 0 &&
24
+ Origen.app.stats.new_patterns == 0
25
+
26
+ Origen.app.stats.report_pass
27
+ else
28
+ Origen.app.stats.report_fail
29
+ status = 1
30
+ end
31
+ puts
32
+ if @command == "test"
33
+ Origen.app.unload_target!
34
+ require "rspec"
35
+ result = RSpec::Core::Runner.run(['spec'])
36
+ status = status == 1 ? 1 : result
37
+ end
38
+ exit status
39
+
40
+ else
41
+ @application_commands = <<-EOT
42
+ specs Run the specs (unit tests), -c will enable coverage
43
+ examples Run the examples (acceptance tests), -c will enable coverage
44
+ test Run both specs and examples, -c will enable coverage
45
+ EOT
46
+
47
+ end
@@ -0,0 +1,17 @@
1
+ # This file is similar to environment.rb and will be loaded
2
+ # automatically at the start of each invocation of Origen.
3
+ #
4
+ # However the major difference is that it will not be loaded
5
+ # if the application is imported by a 3rd party app - in that
6
+ # case only environment.rb is loaded.
7
+ #
8
+ # Therefore this file should be used to load anything you need
9
+ # to setup a development environment for this app, normally
10
+ # this would be used to load some dummy classes to instantiate
11
+ # your objects so that they can be tested and/or interacted with
12
+ # in the console.
13
+ module CrossOrigen
14
+ module Test
15
+ autoload :DUT, "cross_origen/test/dut"
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ # This file will be required by Origen before your target is loaded, you
2
+ # can use this to require all of your files, which is the easiest way
3
+ # to get started. As your experience grows you may wish to require only the
4
+ # minimum files required to allow the target to be initialized and let
5
+ # each class require its own dependencies.
6
+ #
7
+ # It is recommended that you keep all of your application logic in lib/
8
+ # The lib directory has already been added to the search path and so any files
9
+ # in there can be referenced from here with a relative path.
10
+ #
11
+ # Note that pattern files do not need to be referenced from here and these
12
+ # will be located automatically by origen.
13
+
14
+ # This says load the file "lib/pioneer.rb" the first time anyone makes a
15
+ # reference to the class name 'Pioneer'.
16
+ #autoload :Pioneer, "pioneer"
17
+ # This is generally preferable to using require which will load the file
18
+ # regardless of whether it is needed by the current target or not:
19
+ #require "pioneer"
20
+ # Sometimes you have to use require however:-
21
+ # 1. When defining a test program interface:
22
+ #require "interfaces/j750"
23
+ # 2. If you want to extend a class defined by an imported application, in
24
+ # this case your must use required and supply a full path (to distinguish
25
+ # it from the one in the parent application):
26
+ #require "#{Origen.root}/c90_top_level/p2"
27
+ module CrossOrigen
28
+ autoload :XMLDoc, "cross_origen/xml_doc"
29
+ autoload :Headers, "cross_origen/headers"
30
+ autoload :Ralf, "cross_origen/ralf"
31
+ autoload :IpXact, "cross_origen/ip_xact"
32
+ autoload :DesignSync, "cross_origen/design_sync"
33
+ autoload :OrigenFormat, "cross_origen/origen_format"
34
+ end
35
+ require "cross_origen"
data/config/users.rb ADDED
@@ -0,0 +1,18 @@
1
+ # This file defines the users associated with your project, it is basically the
2
+ # mailing list for release notes.
3
+ #
4
+ # You can split your users into "admin" and "user" groups, the main difference
5
+ # between the two is that admin users will get all tag emails, users will get
6
+ # emails on external/official releases only.
7
+ #
8
+ # Users are also prohibited from running the "origen tag" task, but this is
9
+ # really just to prevent a casual user from executing it inadvertently and is
10
+ # not intended to be a serious security gate.
11
+ module Origen
12
+ module Users
13
+ def users
14
+ @users ||= [
15
+ ]
16
+ end
17
+ end
18
+ end
data/config/version.rb ADDED
@@ -0,0 +1,8 @@
1
+ module CrossOrigen
2
+ MAJOR = 0
3
+ MINOR = 5
4
+ BUGFIX = 0
5
+ DEV = nil
6
+
7
+ VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
8
+ end
@@ -0,0 +1,54 @@
1
+ module CrossOrigen
2
+ # Driver for talking to DesignSync
3
+ class DesignSync
4
+ require 'digest/sha1'
5
+
6
+ # Returns the object that included the CrossOrigen module
7
+ attr_reader :owner
8
+
9
+ def initialize(owner)
10
+ @owner = owner
11
+ end
12
+
13
+ def driver
14
+ @driver ||= Origen::Utility::DesignSync.new
15
+ end
16
+
17
+ # Returns a full path to the Design Sync import (cache) directory
18
+ def import_dir
19
+ return @import_dir if @import_dir
20
+ @import_dir = "#{Origen.app.workspace_manager.imports_directory}/design_sync"
21
+ FileUtils.mkdir_p(@import_dir) unless File.exist?(@import_dir)
22
+ @import_dir
23
+ end
24
+
25
+ # This will be called if the user has supplied a :vault in the rs_import options. The corresponding
26
+ # version of the file will be returned from the cache if it already exists locally, otherwise it
27
+ # will be imported.
28
+ #
29
+ # This method returns a full path to the local cache copy of the file.
30
+ def fetch(options = {})
31
+ unless options[:version]
32
+ puts 'You must supply a :version number (or tag) when importing data from Design Sync'
33
+ exit 1
34
+ end
35
+ v = options[:vault]
36
+ f = v.split('/').last
37
+ vault = v.sub(/\/#{f}$/, '')
38
+ # Consider that similarly named files could exist in different vaults, so attach
39
+ # a representation of the vault to the filename
40
+ vault_hash = Digest::SHA1.hexdigest(vault)
41
+ dir = "#{import_dir}/#{vault_hash}-#{f}"
42
+ file = "#{dir}/#{options[:version]}"
43
+ if f =~ /.*\.(.*)/
44
+ file += ".#{Regexp.last_match[1]}"
45
+ end
46
+ if !File.exist?(file) || options[:force]
47
+ FileUtils.mkdir_p(dir) unless File.exist?(dir)
48
+ driver.import(f, vault, options[:version], dir)
49
+ FileUtils.mv("#{dir}/#{f}", file)
50
+ end
51
+ file
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,21 @@
1
+ module CrossOrigen
2
+ class Headers
3
+ # Returns the object that included the CrossOrigen module
4
+ attr_reader :owner
5
+
6
+ def initialize(owner)
7
+ @owner = owner
8
+ end
9
+
10
+ # Returns a string representing the owner as a C header
11
+ def owner_to_header(_options = {})
12
+ Origen.compile("#{path_to_templates}/headers/default.h.erb", scope: owner)
13
+ end
14
+
15
+ private
16
+
17
+ def path_to_templates
18
+ "#{File.expand_path(File.dirname(__FILE__))}/../../templates"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,243 @@
1
+ module CrossOrigen
2
+ class IpXact < XMLDoc
3
+ AddressSpace = Struct.new(:name, :range, :width)
4
+
5
+ MemoryMaps = Struct.new(:name, :address_blocks)
6
+
7
+ AddressBlock = Struct.new(:name, :base_address, :range, :width)
8
+
9
+ # Import/reader that currently only supports creating registers and bit fields
10
+ def import(file, options = {}) # rubocop:disable CyclomaticComplexity
11
+ require 'kramdown'
12
+
13
+ address_spaces = {}
14
+
15
+ doc(file, options) do |doc|
16
+ doc.xpath('//spirit:addressSpaces/spirit:addressSpace').each do |addr_space|
17
+ name = fetch addr_space.at_xpath('spirit:name'), downcase: true, to_sym: true, get_text: true
18
+ range = fetch addr_space.at_xpath('spirit:range'), get_text: true, to_dec: true
19
+ width = fetch addr_space.at_xpath('spirit:width'), get_text: true, to_i: true
20
+ address_spaces[name] = AddressSpace.new(name, range, width)
21
+ end
22
+ doc.xpath('//spirit:memoryMaps/spirit:memoryMap').each do |mem_map|
23
+ mem_map_name = fetch mem_map.at_xpath('spirit:name'), downcase: true, to_sym: true, get_text: true
24
+ owner.sub_block mem_map_name
25
+ mem_map_obj = owner.send(mem_map_name)
26
+ mem_map.xpath('spirit:addressBlock').each do |addr_block|
27
+ name = fetch addr_block.at_xpath('spirit:name'), downcase: true, to_sym: true, get_text: true
28
+ base_address = fetch addr_block.at_xpath('spirit:baseAddress'), get_text: true, to_dec: true
29
+ range = fetch addr_block.at_xpath('spirit:range'), get_text: true, to_dec: true
30
+ width = fetch addr_block.at_xpath('spirit:width'), get_text: true, to_i: true
31
+ mem_map_obj.sub_block name, base_address: base_address, range: range, lau: width
32
+ addr_block_obj = mem_map_obj.send(name)
33
+ addr_block.xpath('spirit:register').each do |register|
34
+ name = fetch register.at_xpath('spirit:name'), downcase: true, to_sym: true, get_text: true
35
+ size = fetch register.at_xpath('spirit:size'), get_text: true, to_i: true
36
+ addr_offset = fetch register.at_xpath('spirit:addressOffset'), get_text: true, to_dec: true
37
+ access = fetch register.at_xpath('spirit:access'), get_text: true
38
+ reset_value = fetch register.at_xpath('spirit:reset/spirit:value'), get_text: true, to_dec: true
39
+ reset_mask = fetch register.at_xpath('spirit:reset/spirit:mask'), get_text: true, to_dec: true
40
+ if [reset_value, reset_mask].include? nil
41
+ # Set default values for some register attributes
42
+ reset_value, reset_mask = 0, 0
43
+ else
44
+ # Do a logical bitwise AND with the reset value and mask
45
+ reset_value = reset_value & reset_mask
46
+ end
47
+ addr_block_obj.reg name, addr_offset, size: size, access: access do |reg|
48
+ register.xpath('spirit:field').each do |field|
49
+ name = fetch field.at_xpath('spirit:name'), downcase: true, to_sym: true, get_text: true
50
+ bit_offset = fetch field.at_xpath('spirit:bitOffset'), get_text: true, to_i: true
51
+ bit_width = fetch field.at_xpath('spirit:bitWidth'), get_text: true, to_i: true
52
+ access = fetch field.at_xpath('spirit:access'), get_text: true
53
+ if access =~ /\S+\-\S+/
54
+ access = access[/^(\S)/, 1] + access[/\-(\S)\S+$/, 1]
55
+ access = access.downcase.to_sym
56
+ else
57
+ # default to read-write if access is not specified
58
+ access = :rw
59
+ end
60
+ range = nil
61
+ if bit_width == 1
62
+ range = bit_offset
63
+ else
64
+ range = (bit_offset + bit_width - 1)..bit_offset
65
+ end
66
+ reg.bit range, name, reset: reset_value[range], access: access
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ # Returns a string representing the owner object in IP-XACT XML
76
+ def owner_to_xml(options = {})
77
+ require 'builder'
78
+
79
+ options = {
80
+ include_bit_field_values: true
81
+ }.merge(options)
82
+
83
+ @format = options[:format]
84
+
85
+ xml = Builder::XmlMarkup.new(indent: 2, margin: 0)
86
+
87
+ xml.instruct!
88
+
89
+ schemas = [
90
+ 'http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.4',
91
+ 'http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.4/index.xsd'
92
+ ]
93
+ if uvm?
94
+ schemas << '$IREG_GEN/XMLSchema/SPIRIT/VendorExtensions.xsd'
95
+ end
96
+
97
+ headers = {
98
+ 'xmlns:spirit' => 'http://www.spiritconsortium.org/XMLSchema/SPIRIT/1.4',
99
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
100
+ 'xsi:schemaLocation' => schemas.join(' ')
101
+ }
102
+ if uvm?
103
+ headers['xmlns:vendorExtensions'] = '$IREG_GEN/XMLSchema/SPIRIT'
104
+ end
105
+
106
+ xml.tag!('spirit:component', headers) do
107
+ xml.spirit :vendor, options[:vendor] || 'Freescale'
108
+ xml.spirit :library, options[:library] || 'Freescale'
109
+ # I guess this should really be the register owner's owner's name?
110
+ xml.spirit :name, try(:ip_name, :pdm_part_name) || owner.class.to_s.split('::').last
111
+ xml.spirit :version, try(:ip_version, :pdm_version, :pdm_cm_version, :version, :revision)
112
+ xml.spirit :memoryMaps do
113
+ memory_maps.each do |map_name, _map|
114
+ xml.spirit :memoryMap do
115
+ xml.spirit :name, map_name
116
+ address_blocks do |domain_name, _domain, sub_block|
117
+ xml.spirit :addressBlock do
118
+ xml.spirit :name, address_block_name(domain_name, sub_block)
119
+ xml.spirit :baseAddress, sub_block.base_address.to_hex
120
+ xml.spirit :range, range(sub_block)
121
+ xml.spirit :width, width(sub_block)
122
+ sub_block.regs.each do |name, reg|
123
+ # Required for now to ensure that the current value is the reset value
124
+ reg.reset
125
+ xml.spirit :register do
126
+ xml.spirit :name, name
127
+ xml.spirit :description, try(reg, :name_full, :full_name)
128
+ xml.spirit :addressOffset, reg.offset.to_hex
129
+ xml.spirit :size, reg.size
130
+ if reg.bits.any?(&:writable?)
131
+ xml.spirit :access, 'read-write'
132
+ else
133
+ xml.spirit :access, 'read-only'
134
+ end
135
+ xml.spirit :reset do
136
+ xml.spirit :value, reg.data.to_hex
137
+ xml.spirit :mask, mask(reg).to_hex
138
+ end
139
+ reg.named_bits do |name, bits|
140
+ xml.spirit :field do
141
+ xml.spirit :name, name
142
+ xml.spirit :description, try(bits, :brief_description, :name_full, :full_name)
143
+ xml.spirit :bitOffset, bits.position
144
+ xml.spirit :bitWidth, bits.size
145
+ xml.spirit :access, bits.access
146
+ if options[:include_bit_field_values]
147
+ if bits.bit_value_descriptions[0]
148
+ bits.bit_value_descriptions.each do |val, desc|
149
+ xml.spirit :values do
150
+ xml.spirit :value, val.to_hex
151
+ xml.spirit :name, "val_#{val.to_hex}"
152
+ xml.spirit :description, desc
153
+ end
154
+ end
155
+ end
156
+ end
157
+ if uvm?
158
+ xml.spirit :vendorExtensions do
159
+ xml.vendorExtensions :hdl_path, bits.path(relative_to: sub_block)
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ if uvm?
167
+ xml.spirit :vendorExtensions do
168
+ xml.vendorExtensions :hdl_path, sub_block.path(relative_to: owner)
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ private
180
+
181
+ def mask(reg)
182
+ m = 0
183
+ reg.size.times do |i|
184
+ unless reg[i].reset_val == :undefined
185
+ m |= (1 << i)
186
+ end
187
+ end
188
+ m
189
+ end
190
+
191
+ def uvm?
192
+ @format == :uvm
193
+ end
194
+
195
+ def memory_maps
196
+ { owner.name => {} }
197
+ end
198
+
199
+ def sub_blocks(domain_name)
200
+ owner.all_sub_blocks.select do |sub_block|
201
+ sub_block.owns_registers? &&
202
+ (sub_block.domains[domain_name] || domain_name == :default)
203
+ end
204
+ end
205
+
206
+ def address_blocks
207
+ domains = owner.register_domains
208
+ domains = { default: {} } if domains.empty?
209
+ domains.each do |domain_name, domain|
210
+ sub_blocks(domain_name).each do |sub_block|
211
+ yield domain_name, domain, sub_block
212
+ end
213
+ end
214
+ end
215
+
216
+ def address_block_name(domain_name, sub_block)
217
+ if domain_name == :default
218
+ sub_block.name.to_s
219
+ else
220
+ "#{domain_name}_#{sub_block.name}"
221
+ end
222
+ end
223
+
224
+ def width(sub_block)
225
+ sub_block.try(:width) || 32
226
+ end
227
+
228
+ def range(sub_block)
229
+ range = sub_block.try(:range) || begin
230
+ # This is to work around an Origen bug where max_address_reg_size is not updated in the case of
231
+ # only one register being present
232
+ # TODO: Fix in Origen
233
+ max_address_reg_size = sub_block.max_address_reg_size || sub_block.regs.first[1].size
234
+ (sub_block.max_reg_address + (max_address_reg_size / 8))
235
+ end
236
+ width_in_bytes = width(sub_block) / 8
237
+ if range % width_in_bytes != 0
238
+ range += (width_in_bytes - (range % width_in_bytes))
239
+ end
240
+ range
241
+ end
242
+ end
243
+ end