origen 0.28.2 → 0.29.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/origen +14 -2
- data/config/version.rb +2 -2
- data/lib/origen.rb +72 -45
- data/lib/origen/application.rb +29 -19
- data/lib/origen/application/deployer.rb +3 -1
- data/lib/origen/application/runner.rb +10 -8
- data/lib/origen/chip_mode.rb +1 -1
- data/lib/origen/commands.rb +24 -12
- data/lib/origen/commands/version.rb +1 -1
- data/lib/origen/commands_global.rb +32 -8
- data/lib/origen/core_ext.rb +1 -2
- data/lib/origen/core_ext/enumerable.rb +2 -2
- data/lib/origen/core_ext/integer.rb +85 -0
- data/lib/origen/core_ext/numeric.rb +28 -4
- data/lib/origen/global_app.rb +9 -0
- data/lib/origen/log.rb +1 -1
- data/lib/origen/model_initializer.rb +6 -1
- data/lib/origen/netlist/list.rb +2 -2
- data/lib/origen/org_file.rb +125 -0
- data/lib/origen/org_file/interceptable.rb +44 -0
- data/lib/origen/org_file/interceptor.rb +100 -0
- data/lib/origen/parameters/set.rb +1 -1
- data/lib/origen/pins.rb +4 -0
- data/lib/origen/pins/function_proxy.rb +8 -0
- data/lib/origen/pins/pin.rb +90 -38
- data/lib/origen/pins/pin_collection.rb +61 -21
- data/lib/origen/ports/port.rb +1 -1
- data/lib/origen/registers.rb +1 -1
- data/lib/origen/registers/reg.rb +1 -1
- data/lib/origen/remote_manager.rb +25 -15
- data/lib/origen/site_config.rb +140 -13
- data/lib/origen/specs/checkers.rb +2 -2
- data/lib/origen/sub_blocks.rb +6 -1
- data/lib/origen/value.rb +119 -0
- data/lib/origen/value/bin_str_val.rb +72 -0
- data/lib/origen/value/hex_str_val.rb +100 -0
- data/origen_site_config.yml +15 -8
- metadata +12 -6
- data/lib/origen/core_ext/bignum.rb +0 -38
- data/lib/origen/core_ext/fixnum.rb +0 -56
data/lib/origen/core_ext.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'origen/core_ext/object'
|
2
2
|
require 'origen/core_ext/string'
|
3
|
-
require 'origen/core_ext/
|
4
|
-
require 'origen/core_ext/bignum'
|
3
|
+
require 'origen/core_ext/integer'
|
5
4
|
require 'origen/core_ext/numeric'
|
6
5
|
require 'origen/core_ext/module'
|
7
6
|
require 'origen/core_ext/hash'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Enumerable
|
2
|
-
PRIMATIVES = [TrueClass, FalseClass, NilClass,
|
2
|
+
PRIMATIVES = [TrueClass, FalseClass, NilClass, String, Symbol, Regexp, Numeric]
|
3
3
|
|
4
4
|
def debug(msg)
|
5
5
|
Origen.log.debug(msg)
|
@@ -48,7 +48,7 @@ module Enumerable
|
|
48
48
|
end
|
49
49
|
next
|
50
50
|
else
|
51
|
-
next unless options[:select].empty? || options[:select].include?(item.class) || PRIMATIVES.
|
51
|
+
next unless options[:select].empty? || options[:select].include?(item.class) || PRIMATIVES.any? { |klass| item.is_a?(klass) }
|
52
52
|
next if options[:ignore].include?(item.class)
|
53
53
|
case item
|
54
54
|
when NilClass
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# The base class of ALL integers, i.e. including Fixum and Bignum
|
2
|
+
|
3
|
+
# Shim to handle Ruby < 2.4.0, where [] is implemented in Fixnum/Bignum instead
|
4
|
+
# of Integer
|
5
|
+
module Origen
|
6
|
+
module IntegerExtension
|
7
|
+
def [](*args)
|
8
|
+
if args.length == 1 && !args.first.is_a?(Range)
|
9
|
+
super
|
10
|
+
else
|
11
|
+
if args.first.is_a?(Range)
|
12
|
+
msb = args.first.first
|
13
|
+
lsb = args.first.last
|
14
|
+
else
|
15
|
+
msb = args.first
|
16
|
+
lsb = args.last
|
17
|
+
end
|
18
|
+
(self >> lsb) & 0.ones_comp(msb - lsb + 1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Integer
|
25
|
+
if RUBY_VERSION >= '2.4.0'
|
26
|
+
prepend Origen::IntegerExtension
|
27
|
+
end
|
28
|
+
|
29
|
+
# Implements 10.cycles
|
30
|
+
def cycles
|
31
|
+
if block_given?
|
32
|
+
times do
|
33
|
+
yield
|
34
|
+
Origen.app.tester.cycle
|
35
|
+
end
|
36
|
+
else
|
37
|
+
Origen.app.tester.cycle(repeat: self)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
alias_method :cycle, :cycles
|
41
|
+
|
42
|
+
def ones_comp(num_bits)
|
43
|
+
self ^ ((1 << num_bits) - 1)
|
44
|
+
end
|
45
|
+
alias_method :ones_complement, :ones_comp
|
46
|
+
alias_method :ones_compliment, :ones_comp
|
47
|
+
|
48
|
+
# Returns a bit mask for the given number of bits:
|
49
|
+
#
|
50
|
+
# 4.to_bit_mask # => 0x1111
|
51
|
+
def to_bit_mask
|
52
|
+
(1 << self) - 1
|
53
|
+
end
|
54
|
+
alias_method :bit_mask, :to_bit_mask
|
55
|
+
|
56
|
+
def to_bool
|
57
|
+
if self == 1
|
58
|
+
return true
|
59
|
+
elsif self == 0
|
60
|
+
return false
|
61
|
+
else
|
62
|
+
return nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_spreadsheet_column
|
67
|
+
index_hash = Hash.new { |hash, key| hash[key] = hash[key - 1].next }.merge(0 => 'A')
|
68
|
+
index_hash[self]
|
69
|
+
end
|
70
|
+
alias_method :to_xls_column, :to_spreadsheet_column
|
71
|
+
alias_method :to_xlsx_column, :to_spreadsheet_column
|
72
|
+
alias_method :to_xls_col, :to_spreadsheet_column
|
73
|
+
alias_method :to_xlsx_col, :to_spreadsheet_column
|
74
|
+
alias_method :to_spreadsheet_col, :to_spreadsheet_column
|
75
|
+
end
|
76
|
+
|
77
|
+
if RUBY_VERSION <= '2.4.0'
|
78
|
+
class Fixnum
|
79
|
+
prepend Origen::IntegerExtension
|
80
|
+
end
|
81
|
+
|
82
|
+
class Bignum
|
83
|
+
prepend Origen::IntegerExtension
|
84
|
+
end
|
85
|
+
end
|
@@ -1,6 +1,30 @@
|
|
1
|
+
# The base class of all numbers, i.e. integers and floats
|
1
2
|
class Numeric
|
2
|
-
|
3
|
-
|
3
|
+
# Helpers for cases where a method may return a 0, 1 or an instance
|
4
|
+
# of Origen::Value::X or Origen::Value::Z
|
5
|
+
|
6
|
+
def z?;
|
7
|
+
false;
|
8
|
+
end
|
9
|
+
|
10
|
+
def hi_z?;
|
11
|
+
false;
|
12
|
+
end
|
13
|
+
|
14
|
+
def x?;
|
15
|
+
false;
|
16
|
+
end
|
17
|
+
|
18
|
+
def undefined?;
|
19
|
+
false;
|
20
|
+
end
|
21
|
+
|
22
|
+
def x_or_z?;
|
23
|
+
false;
|
24
|
+
end
|
25
|
+
|
26
|
+
def z_or_x?;
|
27
|
+
false;
|
4
28
|
end
|
5
29
|
|
6
30
|
def to_hex
|
@@ -65,13 +89,13 @@ class Numeric
|
|
65
89
|
|
66
90
|
# Msps ==> Mega samples per second
|
67
91
|
|
68
|
-
%w(GHz Ghz GTs Gts Gsps).each do |m|
|
92
|
+
%w(GHz Ghz GTs Gts Gsps Gbps).each do |m|
|
69
93
|
define_method m do
|
70
94
|
self * 1_000_000_000
|
71
95
|
end
|
72
96
|
end
|
73
97
|
|
74
|
-
%w(MHz Mhz MTs Mts Msps).each do |m|
|
98
|
+
%w(MHz Mhz MTs Mts Msps Mbps).each do |m|
|
75
99
|
define_method m do
|
76
100
|
self * 1_000_000
|
77
101
|
end
|
data/lib/origen/log.rb
CHANGED
@@ -14,7 +14,7 @@ module Origen
|
|
14
14
|
x.send(:init_sub_blocks, *args) if x.respond_to?(:init_sub_blocks)
|
15
15
|
if x.respond_to?(:version=)
|
16
16
|
version = options[:version]
|
17
|
-
version ||= args.first if args.first.is_a?(
|
17
|
+
version ||= args.first if args.first.is_a?(Integer)
|
18
18
|
x.version = version
|
19
19
|
end
|
20
20
|
if x.respond_to?(:parent=)
|
@@ -47,6 +47,11 @@ module Origen
|
|
47
47
|
is_top_level = x.respond_to?(:includes_origen_top_level?)
|
48
48
|
if x.respond_to?(:wrap_in_controller)
|
49
49
|
x = x.wrap_in_controller
|
50
|
+
# If this object has been instantiated after on_create has already been called,
|
51
|
+
# then invoke it now
|
52
|
+
if Origen.application_loaded? && Origen.app.on_create_called?
|
53
|
+
x.controller.on_create if x.controller.respond_to?(:on_create)
|
54
|
+
end
|
50
55
|
end
|
51
56
|
if is_top_level
|
52
57
|
Origen.app.listeners_for(:on_top_level_instantiated, top_level: false).each do |listener|
|
data/lib/origen/netlist/list.rb
CHANGED
@@ -49,7 +49,7 @@ module Origen
|
|
49
49
|
else
|
50
50
|
from_proc = false
|
51
51
|
end
|
52
|
-
if val.is_a?(
|
52
|
+
if val.is_a?(Integer)
|
53
53
|
bits << Registers::Bit.new(nil, index, access: :ro, data: (i == '*' && !from_proc) ? val[index] : val)
|
54
54
|
elsif val
|
55
55
|
vp, vi = *to_v(val)
|
@@ -122,7 +122,7 @@ module Origen
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def clean(path)
|
125
|
-
if path.is_a?(
|
125
|
+
if path.is_a?(Integer)
|
126
126
|
{ path: path, numeric: true }
|
127
127
|
elsif path.is_a?(Proc)
|
128
128
|
{ path: path, proc: true }
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Origen
|
2
|
+
class OrgFile
|
3
|
+
autoload :Interceptor, 'origen/org_file/interceptor'
|
4
|
+
autoload :Interceptable, 'origen/org_file/interceptable'
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def new(*args, &block)
|
8
|
+
if @internal_new
|
9
|
+
super
|
10
|
+
else
|
11
|
+
open(*args, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def open(id, options = {})
|
16
|
+
fail "An org_file is already open with id: #{id}" if open_files[id]
|
17
|
+
@internal_new = true
|
18
|
+
f = OrgFile.new(id, options)
|
19
|
+
@internal_new = nil
|
20
|
+
open_files[id] = f
|
21
|
+
if block_given?
|
22
|
+
yield f
|
23
|
+
close(id, options)
|
24
|
+
else
|
25
|
+
f
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def close(id, options = {})
|
30
|
+
fail "An org_file with this ID has not been opened id: #{id}" unless open_files[id]
|
31
|
+
open_files[id].close unless options[:_internal_org_file_call_]
|
32
|
+
open_files[id] = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def org_file(id = nil)
|
36
|
+
id ? open_files[id] : open_files.to_a.last[1]
|
37
|
+
end
|
38
|
+
|
39
|
+
def cycle(number = 1)
|
40
|
+
open_files.each { |id, f| f.cycle(number) }
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def open_files
|
46
|
+
@open_files ||= {}.with_indifferent_access
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
attr_accessor :path, :filename
|
51
|
+
attr_reader :id, :operation
|
52
|
+
|
53
|
+
def initialize(id, options = {})
|
54
|
+
@id = id
|
55
|
+
@path = options[:path] || default_filepath
|
56
|
+
@filename = options[:filename] || "#{id}.org"
|
57
|
+
FileUtils.mkdir_p(path)
|
58
|
+
@path_to_file = File.join(path, filename)
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_filepath
|
62
|
+
"#{Origen.root}/pattern/org/#{Origen.target.name}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def file
|
66
|
+
@file ||= begin
|
67
|
+
if operation == 'r'
|
68
|
+
fail "No org file found at: #{@path_to_file}" unless exist?
|
69
|
+
end
|
70
|
+
File.open(@path_to_file, operation)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def exist?
|
75
|
+
File.exist?(@path_to_file)
|
76
|
+
end
|
77
|
+
|
78
|
+
def close
|
79
|
+
# Corner case, if no call to read_line or record was made then no file was created and there
|
80
|
+
# is no file to close
|
81
|
+
if @file
|
82
|
+
file.puts "#{@buffer}#{@buffer_cycles}" if @buffer
|
83
|
+
file.close
|
84
|
+
end
|
85
|
+
self.class.close(id, _internal_org_file_call_: true)
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
|
89
|
+
def read_line
|
90
|
+
@operation ||= 'r'
|
91
|
+
operations = file.readline.strip.split(';')
|
92
|
+
cycles = operations.pop.to_i
|
93
|
+
operations = operations.map { |op| op.split(',') }.map { |op| op[0] = eval(op[0]); op }
|
94
|
+
if block_given?
|
95
|
+
yield operations, cycles
|
96
|
+
else
|
97
|
+
[operations, cycles]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def record(path_to_object, method, *args)
|
102
|
+
@operation ||= 'w'
|
103
|
+
@line ||= ''
|
104
|
+
@line += "#{path_to_object},#{method}"
|
105
|
+
@line += ",#{args.join(',')}" unless args.empty?
|
106
|
+
@line += ';'
|
107
|
+
end
|
108
|
+
|
109
|
+
def cycle(number)
|
110
|
+
if @buffer
|
111
|
+
if @line == @buffer
|
112
|
+
@buffer_cycles += 1
|
113
|
+
else
|
114
|
+
file.puts "#{@buffer}#{@buffer_cycles}"
|
115
|
+
@buffer = @line
|
116
|
+
@buffer_cycles = 1
|
117
|
+
end
|
118
|
+
else
|
119
|
+
@buffer = @line
|
120
|
+
@buffer_cycles = 1
|
121
|
+
end
|
122
|
+
@line = nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Origen
|
2
|
+
class OrgFile
|
3
|
+
module Interceptable
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
|
7
|
+
# Defers this executing until the whole class has loaded
|
8
|
+
Origen.after_app_loaded do
|
9
|
+
unless (base.instance_methods - Object.methods).include?(:global_path_to)
|
10
|
+
puts 'When adding the OrgFile::Interceptable module to a class, the class must define an instance method called "global_path_to", like this:'
|
11
|
+
puts
|
12
|
+
puts ' # Must return a string that contains a global path to access the given object,'
|
13
|
+
puts ' # here for example if the object was a pin'
|
14
|
+
puts ' def global_path_to'
|
15
|
+
puts ' "dut.pins(:#{id})"'
|
16
|
+
puts ' end'
|
17
|
+
fail "Incomplete integration of OrgFile::Interceptable in #{base}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
def new(*args, &block)
|
24
|
+
o = allocate
|
25
|
+
i = OrgFile::Interceptor.new(o)
|
26
|
+
o.__interceptor__ = i
|
27
|
+
i.send(:initialize, *args, &block)
|
28
|
+
i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Class which include OrgFile::Interceptor should use 'myself' anytime then want to reference 'self',
|
33
|
+
# this ensures that there are never any references to the unwrapped object
|
34
|
+
def myself
|
35
|
+
@__interceptor__
|
36
|
+
end
|
37
|
+
|
38
|
+
# @api private
|
39
|
+
def __interceptor__=(obj)
|
40
|
+
@__interceptor__ = obj
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'set'
|
2
|
+
module Origen
|
3
|
+
class OrgFile
|
4
|
+
# @api private
|
5
|
+
#
|
6
|
+
# Helper for the Interceptor where block_given? doesn't work internally
|
7
|
+
def self._block_given_?(&block)
|
8
|
+
block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
class Interceptor < ::BasicObject
|
12
|
+
def initialize(object, options = {})
|
13
|
+
@object = object
|
14
|
+
@@locked = false unless defined? @@locked
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect(*args)
|
18
|
+
@object.inspect(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(obj)
|
22
|
+
if obj.respond_to?(:__org_file_interceptor__)
|
23
|
+
@object == obj.__object__
|
24
|
+
else
|
25
|
+
@object == obj
|
26
|
+
end
|
27
|
+
end
|
28
|
+
alias_method :equal?, :==
|
29
|
+
|
30
|
+
def record_to_org_file(id = nil, options = {})
|
31
|
+
id, options = nil, id if id.is_a?(::Hash)
|
32
|
+
if options[:only]
|
33
|
+
@org_file_methods_to_intercept = Array(options[:only]).to_set
|
34
|
+
else
|
35
|
+
@org_file_methods_to_intercept = default_org_file_captures
|
36
|
+
if options[:also]
|
37
|
+
@org_file_methods_to_intercept += Array(options[:also]).to_set
|
38
|
+
end
|
39
|
+
end
|
40
|
+
@org_file ||= @old_org_file || OrgFile.org_file(id)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Temporarily stop recording operations within the given block, or stop recording
|
44
|
+
# completely if no block given
|
45
|
+
def stop_recording_to_org_file(&block)
|
46
|
+
@old_org_file = @org_file
|
47
|
+
if OrgFile._block_given_?(&block)
|
48
|
+
@org_file = nil
|
49
|
+
yield
|
50
|
+
@org_file = @old_org_file
|
51
|
+
else
|
52
|
+
@org_file = nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(method, *args, &block)
|
57
|
+
if !@@locked && @org_file && @org_file_methods_to_intercept.include?(method)
|
58
|
+
@org_file.record(@object.global_path_to, method, *args)
|
59
|
+
# Locking prevents an operation on an intercepted container object trigger from generating multiple
|
60
|
+
# org file entries if its contained objects are also intercepted. e.g. Imagine this is a pin group, we
|
61
|
+
# want the org file to reflect the operation called on the pin group, but not the many subsequent internal
|
62
|
+
# operations as the group proxies the operation to its contained pins
|
63
|
+
@@locked = true
|
64
|
+
@object.send(method, *args, &block)
|
65
|
+
@@locked = false
|
66
|
+
else
|
67
|
+
@object.send(method, *args, &block)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def respond_to?(method, include_private = false)
|
72
|
+
method == :__org_file_interceptor__ ||
|
73
|
+
@object.respond_to?(method, include_private)
|
74
|
+
end
|
75
|
+
|
76
|
+
def __org_file_interceptor__
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
# @api private
|
81
|
+
#
|
82
|
+
# Don't ever use this! An un-wrapped reference to an object must never make it into
|
83
|
+
# application code or else any operations called on the un-wrapped reference will not
|
84
|
+
# be captured.
|
85
|
+
def __object__
|
86
|
+
@object
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def debugger
|
92
|
+
::Kernel.debugger
|
93
|
+
end
|
94
|
+
|
95
|
+
def default_org_file_captures
|
96
|
+
@default_captures ||= Array(@object.try(:org_file_intercepted_methods)).to_set
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|