cross_origen 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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