origen 0.28.2 → 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/bin/origen +14 -2
  3. data/config/version.rb +2 -2
  4. data/lib/origen.rb +72 -45
  5. data/lib/origen/application.rb +29 -19
  6. data/lib/origen/application/deployer.rb +3 -1
  7. data/lib/origen/application/runner.rb +10 -8
  8. data/lib/origen/chip_mode.rb +1 -1
  9. data/lib/origen/commands.rb +24 -12
  10. data/lib/origen/commands/version.rb +1 -1
  11. data/lib/origen/commands_global.rb +32 -8
  12. data/lib/origen/core_ext.rb +1 -2
  13. data/lib/origen/core_ext/enumerable.rb +2 -2
  14. data/lib/origen/core_ext/integer.rb +85 -0
  15. data/lib/origen/core_ext/numeric.rb +28 -4
  16. data/lib/origen/global_app.rb +9 -0
  17. data/lib/origen/log.rb +1 -1
  18. data/lib/origen/model_initializer.rb +6 -1
  19. data/lib/origen/netlist/list.rb +2 -2
  20. data/lib/origen/org_file.rb +125 -0
  21. data/lib/origen/org_file/interceptable.rb +44 -0
  22. data/lib/origen/org_file/interceptor.rb +100 -0
  23. data/lib/origen/parameters/set.rb +1 -1
  24. data/lib/origen/pins.rb +4 -0
  25. data/lib/origen/pins/function_proxy.rb +8 -0
  26. data/lib/origen/pins/pin.rb +90 -38
  27. data/lib/origen/pins/pin_collection.rb +61 -21
  28. data/lib/origen/ports/port.rb +1 -1
  29. data/lib/origen/registers.rb +1 -1
  30. data/lib/origen/registers/reg.rb +1 -1
  31. data/lib/origen/remote_manager.rb +25 -15
  32. data/lib/origen/site_config.rb +140 -13
  33. data/lib/origen/specs/checkers.rb +2 -2
  34. data/lib/origen/sub_blocks.rb +6 -1
  35. data/lib/origen/value.rb +119 -0
  36. data/lib/origen/value/bin_str_val.rb +72 -0
  37. data/lib/origen/value/hex_str_val.rb +100 -0
  38. data/origen_site_config.yml +15 -8
  39. metadata +12 -6
  40. data/lib/origen/core_ext/bignum.rb +0 -38
  41. data/lib/origen/core_ext/fixnum.rb +0 -56
@@ -1,7 +1,6 @@
1
1
  require 'origen/core_ext/object'
2
2
  require 'origen/core_ext/string'
3
- require 'origen/core_ext/fixnum'
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, Integer, Float, String, Symbol, Regexp, Complex, Rational, Fixnum, Bignum]
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.include?(item.class)
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
- def undefined?
3
- false
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
@@ -0,0 +1,9 @@
1
+ class OrigenGlobalApplication < Origen::Application
2
+ config.output_directory do
3
+ "#{Origen.root}/origen"
4
+ end
5
+
6
+ config.reference_directory do
7
+ "#{Origen.root}/origen/.ref"
8
+ end
9
+ end
@@ -35,7 +35,7 @@ module Origen
35
35
  end
36
36
 
37
37
  def console_only?
38
- self.class.console_only? || !Origen.app
38
+ self.class.console_only? || !Origen.app || Origen.running_globally?
39
39
  end
40
40
 
41
41
  # Anything executed within the given block will log to the console only
@@ -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?(Fixnum)
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|
@@ -49,7 +49,7 @@ module Origen
49
49
  else
50
50
  from_proc = false
51
51
  end
52
- if val.is_a?(Fixnum)
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?(Fixnum)
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