Class: RubyVPI::SchedulerClass

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/ruby-vpi/core/scheduler.rb

Overview

:nodoc:

Defined Under Namespace

Classes: Routine, Write

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSchedulerClass

Returns a new instance of SchedulerClass.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ruby-vpi/core/scheduler.rb', line 15

def initialize
  @writes = Hash.new {|h,k| h[k] = []}
  @writes_lock = Mutex.new

  # for coroutines in Ruby-based prototypes of Verilog hardware
  @routines = []
  @routines_lock = Mutex.new
  @current_routine = nil

  @current_time = 0

  # allow "initial" blocks in Verilog code of DUT to take effect
  if @current_time.zero?
    unless RubyVPI::USE_PROTOTYPE
      advance_to_read_only_slot
    end
  end
end

Instance Attribute Details

#current_timeObject (readonly)

Returns the current simulation time, as tracked by the scheduler.



35
36
37
# File 'lib/ruby-vpi/core/scheduler.rb', line 35

def current_time
  @current_time
end

Instance Method Details

#capture_write(aHandle, *aArgs) ⇒ Object

Captures the given write operation so it can be flushed later, at the correct time.



94
95
96
97
98
# File 'lib/ruby-vpi/core/scheduler.rb', line 94

def capture_write aHandle, *aArgs
  @writes_lock.synchronize do
    @writes[aHandle] << Write.new(Thread.current, caller, aArgs)
  end
end

#pause_current_routineObject

Makes the current routine wait for the scheduler to arrive in the next time step.



47
48
49
# File 'lib/ruby-vpi/core/scheduler.rb', line 47

def pause_current_routine
  @current_routine.pause
end

#register_routine(*aRoutineArgs, &aRoutineBody) ⇒ Object

Registers a new routine with the scheduler. The given block is the body of the routine and the given arguments are passed directly to the block.



39
40
41
42
43
# File 'lib/ruby-vpi/core/scheduler.rb', line 39

def register_routine *aRoutineArgs, &aRoutineBody
  @routines_lock.synchronize do
    @routines << Routine.new(*aRoutineArgs, &aRoutineBody)
  end
end

#run(&aRoutineBody) ⇒ Object

Runs the scheduler until there are no more routines to be scheduled.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/ruby-vpi/core/scheduler.rb', line 52

def run &aRoutineBody
  main = Routine.new(&aRoutineBody)

  until main.done?
    # run software in current time step
    resume_routine main

    Edge.refresh_cache

    # go to time slot where writing is permitted
    # before applying captured write operations
    unless RubyVPI::USE_PROTOTYPE
      if RubyVPI::USE_SIMULATOR == :vsim
        Callback.relay_verilog(VPI::CbAfterDelay, 0)
      else
        Callback.relay_verilog(VPI::CbAfterDelay, 1)
      end
    end

    apply_writes

    # run hardware in next time step
    @current_time += 1

    if RubyVPI::USE_PROTOTYPE
      @routines_lock.synchronize do
        @routines.reject! {|r| r.done? }

        @routines.each do |r|
          resume_routine r
        end
      end

      apply_writes
    else
      advance_to_read_only_slot
    end
  end
end