# Value change / edge detection for handles. #-- # Copyright 2007 Suraj N. Kurapati # See the file named LICENSE for details. require File.join(File.dirname(__FILE__), 'edge-methods.rb') module RubyVPI class EdgeClass #:nodoc: require 'singleton' include Singleton def initialize @handles = [] @lock = Mutex.new end # Begins monitoring the given handle for value change. def monitor aHandle # ignore handles that cannot hold a meaningful value type = VPI::vpi_get_str(VpiType, aHandle) return if type =~ /Bit|Array|Module|Parameter/ @lock.synchronize do unless @handles.include? aHandle @handles << aHandle refresh_handle aHandle end end end # Refreshes the cached value of all monitored handles. def refresh_cache @lock.synchronize do @handles.each do |h| refresh_handle h end end end # Remember the current value as the "previous" value. def refresh_handle aHandle aHandle.instance_eval do @__edge__prev_val = get_value(VpiScalarVal) end end end Edge = EdgeClass.instance end module VPI class Handle RubyVPI::EdgeClass::DETECTION_METHODS.each {|m| class_eval m.body} alias posedge? change_01? alias negedge? change_10? # Tests if either a positive or negative edge has occurred. def edge? posedge? or negedge? end # Tests if the logic value of this handle has # changed since the last simulation time step. def change? old = @__edge__prev_val new = get_value(VpiScalarVal) old != new end end %w[ vpi_handle_by_name vpi_handle_by_index vpi_handle vpi_scan ].each do |src| dst = "__value_change__#{src}" alias_method dst, src define_method src do |*args| if result = __send__(dst, *args) RubyVPI::Edge.monitor(result) end result end end end