Class: VPI::Handle

Inherits:
Object
  • Object
show all
Includes:
VPI
Defined in:
lib/ruby-vpi/core/handle.rb,
lib/ruby-vpi/core/edge.rb,
lib/ruby-vpi/core/callback.rb

Overview

A handle is an object inside a Verilog simulation (see vpiHandle in IEEE Std. 1364-2005 for details).

Nearly all methods of this class, such as put_value() and get_value(), you allow you to specify VPI types and properties (which are listed in ext/vpi_user.h) by their names (strings or symbols) or integer constants.

For example, the vpiIntVal property can be specified as a string ("vpiIntVal"), a symbol (:vpiIntVal), or as an integer (VpiIntVal or VPI::vpiIntVal).

Defined Under Namespace

Classes: Property

Constant Summary collapse

@@propCache =
Hash.new {|h,k| h[k] = Property.new(k)}

Constants included from VPI

INTEGER_BITS, INTEGER_LIMIT, INTEGER_MASK

Instance Method Summary collapse

Methods included from VPI

__callback__vpi_register_cb, __callback__vpi_remove_cb, __scheduler__vpi_put_value, #advance_time, #always, #current_time, #process, #vpi_put_value, #vpi_register_cb, #vpi_remove_cb

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(aMeth, *aArgs, &aBlock) ⇒ Object

Provides access to this handle’s (1) child handles and (2) VPI properties through method calls. In the case that a child handle has the same name as a VPI property, the child handle will be accessed instead of the VPI property. However, you can still access the VPI property using the square brackets #[] method.



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/ruby-vpi/core/handle.rb', line 298

def method_missing aMeth, *aArgs, &aBlock
  # cache the result for future accesses, in order
  # to cut down number of calls to method_missing()
  eigen_class = (class << self; self; end)

  if child = vpi_handle_by_name(aMeth.to_s, self)
    eigen_class.class_eval do
      define_method aMeth do
        child
      end
    end

    child
  else
    # XXX: using a string because define_method() does
    #      not support a block argument until Ruby 1.9
    eigen_class.class_eval %{
      def #{aMeth}(*a, &b)
        access_prop(#{aMeth.inspect}, *a, &b)
      end
    }, __FILE__, __LINE__

    __send__(aMeth, *aArgs, &aBlock)
  end
end

Instance Method Details

#/(aRelativePath) ⇒ Object

Returns the child handle at the given relative VPI path.



223
224
225
# File 'lib/ruby-vpi/core/handle.rb', line 223

def / aRelativePath
  access_child(aRelativePath)
end

#<=>(other) ⇒ Object

Sort by absolute VPI path.



273
274
275
# File 'lib/ruby-vpi/core/handle.rb', line 273

def <=> other
  get_value(VpiFullName) <=> other.get_value(VpiFullName)
end

#[](aProp) ⇒ Object

Returns the value of the given VPI property (name or integer constant) of this handle.



284
285
286
# File 'lib/ruby-vpi/core/handle.rb', line 284

def [] aProp
  access_prop(aProp)
end

#cbValueChange(aOptions = {}, &aHandler) ⇒ Object

Registers a callback that is invoked whenever the value of this object changes.

Raises:



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ruby-vpi/core/callback.rb', line 92

def cbValueChange aOptions = {}, &aHandler
  raise ArgumentError unless block_given?

  aOptions[:time]  ||= S_vpi_time.new(:type => VpiSuppressTime)
  aOptions[:value] ||= S_vpi_value.new(:format => VpiSuppressVal)

  alarm = S_cb_data.new(
    :reason => CbValueChange,
    :obj    => self,
    :time   => aOptions[:time],
    :value  => aOptions[:value],
    :index  => 0
  )

  vpi_register_cb alarm, &aHandler
end

#change?Boolean

Tests if the logic value of this handle has changed since the last simulation time step.

Returns:



68
69
70
71
72
73
# File 'lib/ruby-vpi/core/edge.rb', line 68

def change?
  old = @__edge__prev_val
  new = get_value(VpiScalarVal)

  old != new
end

#edge?Boolean

Tests if either a positive or negative edge has occurred.

Returns:



62
63
64
# File 'lib/ruby-vpi/core/edge.rb', line 62

def edge?
  posedge? or negedge?
end

#force?Boolean

Tests if there is currently a value forced onto this handle.

Returns:



213
214
215
# File 'lib/ruby-vpi/core/handle.rb', line 213

def force?
  self.to_a(VpiDriver).any? {|d| vpi_get(VpiType, d) == VpiForce}
end

#force_value(*args) ⇒ Object

Forces the given value (see arguments for #put_value) onto this handle.



201
202
203
204
# File 'lib/ruby-vpi/core/handle.rb', line 201

def force_value *args
  args[3] = VpiForceFlag
  put_value(*args)
end

#get_value(aFormat = VpiIntVal) ⇒ Object

Reads the value using the given format (name or integer constant) and returns it. If a format is not given, then it is assumed to be VpiIntVal.



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ruby-vpi/core/handle.rb', line 144

def get_value aFormat = VpiIntVal
  fmt = resolve_prop_type(aFormat)
  @size ||= vpi_get(VpiSize, self)

  if fmt == VpiIntVal and @size > INTEGER_BITS
    fmt = VpiBinStrVal
    val = get_value_wrapper(fmt)
    val.read(fmt).gsub(/[^01]/, '0').to_i(2)
  else
    val = get_value_wrapper(fmt)
    val.read(fmt)
  end
end

#get_value_wrapper(aFormat) ⇒ Object

Reads the value using the given format (name or integer constant) and returns a S_vpi_value object.



135
136
137
138
139
140
# File 'lib/ruby-vpi/core/handle.rb', line 135

def get_value_wrapper aFormat
  fmt = resolve_prop_type(aFormat)
  val = S_vpi_value.new(:format => fmt)
  vpi_get_value(self, val)
  val
end

#inspect(*aPropNames) ⇒ Object Also known as: to_s

Inspects the given VPI property names, in addition to those common to all handles.



116
117
118
119
120
121
122
123
124
# File 'lib/ruby-vpi/core/handle.rb', line 116

def inspect *aPropNames
  aPropNames.unshift :name, :fullName, :size, :file, :lineNo, :hexStrVal

  aPropNames.map! do |name|
    "#{name}=#{__send__(name).inspect}"
  end

  "#<VPI::Handle #{vpi_get_str(VpiType, self)} #{aPropNames.join(', ')}>"
end

#put_value(aValue, aFormat = nil, aTime = nil, aDelay = VpiNoDelay) ⇒ Object

Writes the given value using the given format (name or integer constant), time, and delay, and then returns the written value.

  • If you do not specify the format, then the Verilog simulator will attempt to determine the correct format.



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/ruby-vpi/core/handle.rb', line 164

def put_value aValue, aFormat = nil, aTime = nil, aDelay = VpiNoDelay
  if vpi_get(VpiType, self) == VpiNet
    aDelay = VpiForceFlag

    if driver = self.to_a(VpiDriver).find {|d| vpi_get(VpiType, d) != VpiForce}
      warn "forcing value #{aValue.inspect} onto wire #{self} that is already driven by #{driver.inspect}"
    end
  end

  aFormat =
    if aFormat
      resolve_prop_type(aFormat)
    else
      S_vpi_value.detect_format(aValue) ||
      get_value_wrapper(VpiObjTypeVal).format # let the simulator detect
    end

  if aFormat == VpiIntVal
    @size ||= vpi_get(VpiSize, self)

    unless @size < INTEGER_BITS
      aFormat = VpiHexStrVal
      aValue  = aValue.to_i.to_s(16)
    end
  end

  aTime ||= S_vpi_time.new(:type => VpiSimTime, :integer => 0)

  wrapper = S_vpi_value.new(:format => aFormat)
  result  = wrapper.write(aValue, aFormat)

  vpi_put_value(self, wrapper, aTime, aDelay)

  result
end

#release_valueObject

Releases all forced values on this handle (if any).



207
208
209
210
# File 'lib/ruby-vpi/core/handle.rb', line 207

def release_value
  # this doesn't really change the value, it only removes the force flag
  put_value(0, VpiIntVal, nil, VpiReleaseFlag)
end

#to_a(*aChildTypes) ⇒ Object

Returns an array of child handles which have the given types (names or integer constants).



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/ruby-vpi/core/handle.rb', line 229

def to_a *aChildTypes
  handles = []

  aChildTypes.each do |arg|
    t = resolve_prop_type(arg)

    if itr = vpi_iterate(t, self)
      while h = vpi_scan(itr)
        handles << h
      end
    end
  end

  handles
end

#vpi0!Object Also known as: f!

Sets the integer value of this handle to 0.



50
51
52
# File 'lib/ruby-vpi/core/handle.rb', line 50

def vpi0!
  put_value(Vpi0, VpiScalarVal)
end

#vpi0?Boolean Also known as: f?

Tests if the integer value of this handle is 0.

Returns:



45
46
47
# File 'lib/ruby-vpi/core/handle.rb', line 45

def vpi0?
  get_value(VpiScalarVal) == Vpi0
end

#vpi1!Object Also known as: t!

Sets the integer value of this handle to 1.



36
37
38
# File 'lib/ruby-vpi/core/handle.rb', line 36

def vpi1!
  put_value(Vpi1, VpiScalarVal)
end

#vpi1?Boolean Also known as: t?

Tests if the integer value of this handle is 1.

Returns:



31
32
33
# File 'lib/ruby-vpi/core/handle.rb', line 31

def vpi1?
  get_value(VpiScalarVal) == Vpi1
end

#vpiH!Object Also known as: h!

Sets the strength value of this handle to high.



92
93
94
# File 'lib/ruby-vpi/core/handle.rb', line 92

def vpiH!
  put_value(VpiH, VpiScalarVal)
end

#vpiH?Boolean Also known as: h?

Tests if the strength value of this handle is high.

Returns:



87
88
89
# File 'lib/ruby-vpi/core/handle.rb', line 87

def vpiH?
  get_value(VpiScalarVal) == VpiH
end

#vpiL!Object Also known as: l!

Sets the strength value of this handle to low.



106
107
108
# File 'lib/ruby-vpi/core/handle.rb', line 106

def vpiL!
  put_value(VpiL, VpiScalarVal)
end

#vpiL?Boolean Also known as: l?

Tests if the strength value of this handle is low.

Returns:



101
102
103
# File 'lib/ruby-vpi/core/handle.rb', line 101

def vpiL?
  get_value(VpiScalarVal) == VpiL
end

#vpiX!Object Also known as: x!

Sets the logic value of this handle to unknown (x).



64
65
66
# File 'lib/ruby-vpi/core/handle.rb', line 64

def vpiX!
  put_value(VpiX, VpiScalarVal)
end

#vpiX?Boolean Also known as: x?

Tests if the logic value of this handle is unknown (x).

Returns:



59
60
61
# File 'lib/ruby-vpi/core/handle.rb', line 59

def vpiX?
  get_value(VpiScalarVal) == VpiX
end

#vpiZ!Object Also known as: z!

Sets the logic value of this handle to high impedance (z).



78
79
80
# File 'lib/ruby-vpi/core/handle.rb', line 78

def vpiZ!
  put_value(VpiZ, VpiScalarVal)
end

#vpiZ?Boolean Also known as: z?

Tests if the logic value of this handle is high impedance (z).

Returns:



73
74
75
# File 'lib/ruby-vpi/core/handle.rb', line 73

def vpiZ?
  get_value(VpiScalarVal) == VpiZ
end