Class: OrigenSim::Simulation

Inherits:
Object
  • Object
show all
Defined in:
lib/origen_sim/simulation.rb

Overview

Responsible for managing each individual simulation that is run in an Origen thread e.g. If multiple patterns are run in separate simulations, then one instance of this class will exist for each one.

It is primarily responsible for all communications with the simulation and capturing log output and errors.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, view_wave_command) ⇒ Simulation

Returns a new instance of Simulation.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/origen_sim/simulation.rb', line 20

def initialize(id, view_wave_command)
  @id = id
  @view_wave_command = view_wave_command
  @completed_cleanly = false
  @failed_to_start = false
  @logged_errors = false
  @stderr_logged_errors = false
  @error_count = 0
  @socket_ids = {}

  @server = UNIXServer.new(socket_id) # Socket used to send Origen -> Verilog commands
  @server_stdout = UNIXServer.new(socket_id(:stdout))
  @server_stderr = UNIXServer.new(socket_id(:stderr))
  @server_heartbeat = UNIXServer.new(socket_id(:heartbeat))
end

Instance Attribute Details

#completed_cleanlyObject

Returns the value of attribute completed_cleanly.



14
15
16
# File 'lib/origen_sim/simulation.rb', line 14

def completed_cleanly
  @completed_cleanly
end

#error_countObject

Returns the value of attribute error_count.



14
15
16
# File 'lib/origen_sim/simulation.rb', line 14

def error_count
  @error_count
end

#failed_to_startObject

Returns the value of attribute failed_to_start.



14
15
16
# File 'lib/origen_sim/simulation.rb', line 14

def failed_to_start
  @failed_to_start
end

#idObject (readonly)

Returns the value of attribute id.



12
13
14
# File 'lib/origen_sim/simulation.rb', line 12

def id
  @id
end

#logged_errorsObject

Returns the value of attribute logged_errors.



14
15
16
# File 'lib/origen_sim/simulation.rb', line 14

def logged_errors
  @logged_errors
end

#pidObject

Returns the value of attribute pid.



15
16
17
# File 'lib/origen_sim/simulation.rb', line 15

def pid
  @pid
end

#socketObject (readonly)

Returns the communication socket used for sending commands to the Origen VPI running in the simulation process



18
19
20
# File 'lib/origen_sim/simulation.rb', line 18

def socket
  @socket
end

#stderr_logged_errorsObject

Returns the value of attribute stderr_logged_errors.



15
16
17
# File 'lib/origen_sim/simulation.rb', line 15

def stderr_logged_errors
  @stderr_logged_errors
end

#view_wave_commandObject (readonly)

Returns the value of attribute view_wave_command.



12
13
14
# File 'lib/origen_sim/simulation.rb', line 12

def view_wave_command
  @view_wave_command
end

Instance Method Details

#closeObject

Close all communication channels with the simulator



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/origen_sim/simulation.rb', line 92

def close
  return unless @opened
  stop_heartbeat
  @heartbeat.close
  @socket.close
  @stderr.close
  @stdout.close
  File.unlink(socket_id(:heartbeat)) if File.exist?(socket_id(:heartbeat))
  File.unlink(socket_id) if File.exist?(socket_id)
  File.unlink(socket_id(:stderr)) if File.exist?(socket_id(:stderr))
  File.unlink(socket_id(:stdout)) if File.exist?(socket_id(:stdout))
end

#failed?(in_progress = false) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
39
40
41
42
43
# File 'lib/origen_sim/simulation.rb', line 36

def failed?(in_progress = false)
  failed = stderr_logged_errors || logged_errors || failed_to_start || error_count > 0
  if in_progress
    failed
  else
    failed || !completed_cleanly
  end
end

#log_results(in_progress = false) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/origen_sim/simulation.rb', line 45

def log_results(in_progress = false)
  if failed?(in_progress)
    if failed_to_start
      Origen.log.error 'The simulation failed to start!'
    else
      if in_progress
        Origen.log.error "The simulation has #{error_count} error#{error_count > 1 ? 's' : ''}!" if error_count > 0
      else
        Origen.log.error "The simulation failed with #{error_count} errors!" if error_count > 0
      end
      Origen.log.error 'The simulation log reported errors!' if logged_errors
      Origen.log.error 'The simulation stderr reported errors!' if stderr_logged_errors
      Origen.log.error 'The simulation exited early!' unless completed_cleanly || in_progress
    end
  else
    if in_progress
      Origen.log.success 'The simulation is passing!'
    else
      Origen.log.success 'The simulation passed!'
    end
  end
end

#openObject

Open the communication channels with the simulator



83
84
85
86
87
88
89
# File 'lib/origen_sim/simulation.rb', line 83

def open
  start_heartbeat
  @stdout = @server_stdout.accept
  @stderr = @server_stderr.accept
  @socket = @server.accept
  @opened = true
end

#read_sim_outputObject



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/origen_sim/simulation.rb', line 105

def read_sim_output
  while @stdout.ready?
    line = @stdout.gets.chomp
    if OrigenSim.error_strings.any? { |s| line =~ /#{s}/ } &&
       !OrigenSim.error_string_exceptions.any? { |s| line =~ /#{s}/ }
      @logged_errors = true
      Origen.log.error "(STDOUT): #{line}"
    else
      if OrigenSim.verbose? ||
         OrigenSim.log_strings.any? { |s| line =~ /#{s}/ }
        Origen.log.info line
      else
        Origen.log.debug line
      end
    end
  end
  while @stderr.ready?
    line = @stderr.gets.chomp
    if OrigenSim.fail_on_stderr && !line.empty? &&
       !OrigenSim.stderr_string_exceptions.any? { |s| line =~ /#{s}/ }
      # We're failing on stderr, so print its results and log as errors if its not an exception.
      @stderr_logged_errors = true
      Origen.log.error "(STDERR): #{line}"
    elsif OrigenSim.verbose?
      # We're not failing on stderr, or the string in stderr is an exception.
      # Print the string as regular output if verbose is set, otherwise just ignore.
      Origen.log.info line
    end
  end
end

#running?Boolean

Returns true if the simulation is running

Returns:

  • (Boolean)


137
138
139
140
141
142
143
144
145
# File 'lib/origen_sim/simulation.rb', line 137

def running?
  return false unless pid
  begin
    Process.getpgid(pid)
    true
  rescue Errno::ESRCH
    false
  end
end

#socket_id(type = nil) ⇒ Object



147
148
149
# File 'lib/origen_sim/simulation.rb', line 147

def socket_id(type = nil)
  @socket_ids[type] ||= "/tmp/#{socket_number}#{type}.sock"
end

#start_heartbeatObject

Provide a heartbeat to let the parallel Ruby process in charge of the simulator know that the master Origen process is still alive. If the Origen process crashes and leaves the simulator running, the child process will automatically reap it after a couple of missed heartbeats.



72
73
74
75
76
# File 'lib/origen_sim/simulation.rb', line 72

def start_heartbeat
  @heartbeat = @server_heartbeat.accept
  @pid = @heartbeat.gets.chomp.to_i
  @heartbeat_thread = Heartbeat.new(@heartbeat)
end

#stop_heartbeatObject



78
79
80
# File 'lib/origen_sim/simulation.rb', line 78

def stop_heartbeat
  @heartbeat_thread.stop
end