ruby-vpi 18.0.2 → 19.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. data/Rakefile +15 -19
  2. data/bin/generate/proto.rb +15 -10
  3. data/bin/ruby-vpi +2 -0
  4. data/doc/README +3 -5
  5. data/doc/Rakefile +3 -3
  6. data/doc/common.css +24 -136
  7. data/doc/common.tpl +48 -37
  8. data/doc/figures/figures.dia +19 -19
  9. data/doc/figures/ruby_relay.png +0 -0
  10. data/doc/history.html +252 -67
  11. data/doc/history.inc +98 -1
  12. data/doc/history.yaml +105 -0
  13. data/doc/intro.inc +43 -32
  14. data/doc/lib/doc_format.rb +19 -13
  15. data/doc/lib/doc_proxy.rb +7 -7
  16. data/doc/manual.doc +156 -117
  17. data/doc/manual.html +601 -560
  18. data/doc/memo.html +29 -25
  19. data/doc/print.css +63 -4
  20. data/doc/readme.doc +4 -6
  21. data/doc/readme.html +129 -111
  22. data/doc/rss.xml +168 -7
  23. data/doc/screen.css +146 -0
  24. data/doc/spacing.css +57 -0
  25. data/{samp → examples}/counter/RSpec/Rakefile +0 -0
  26. data/{samp → examples}/counter/RSpec/counter_design.rb +0 -0
  27. data/examples/counter/RSpec/counter_proto.rb +9 -0
  28. data/{samp → examples}/counter/RSpec/counter_runner.rake +0 -0
  29. data/{samp → examples}/counter/RSpec/counter_spec.rb +0 -0
  30. data/{samp → examples}/counter/Rakefile +0 -0
  31. data/{samp → examples}/counter/counter.v +0 -0
  32. data/{samp → examples}/counter/xUnit/Rakefile +0 -0
  33. data/{samp → examples}/counter/xUnit/counter_bench.rb +0 -0
  34. data/{samp → examples}/counter/xUnit/counter_bench.v +0 -0
  35. data/{samp → examples}/counter/xUnit/counter_design.rb +0 -0
  36. data/examples/counter/xUnit/counter_proto.rb +9 -0
  37. data/{samp → examples}/counter/xUnit/counter_runner.rake +0 -0
  38. data/{samp → examples}/counter/xUnit/counter_spec.rb +0 -0
  39. data/{samp → examples}/pipelined_alu/Hw5UnitModel.rb +0 -0
  40. data/{samp → examples}/pipelined_alu/README +0 -0
  41. data/{samp → examples}/pipelined_alu/Rakefile +0 -0
  42. data/{samp → examples}/pipelined_alu/TestHw5UnitModel.rb +0 -0
  43. data/{samp → examples}/pipelined_alu/hw5_unit.v +0 -0
  44. data/{samp → examples}/pipelined_alu/hw5_unit_design.rb +0 -7
  45. data/examples/pipelined_alu/hw5_unit_proto.rb +2 -0
  46. data/{samp → examples}/pipelined_alu/hw5_unit_runner.rake +0 -0
  47. data/{samp → examples}/pipelined_alu/hw5_unit_spec.rb +0 -0
  48. data/{samp → examples}/pipelined_alu/int_gen.rb +0 -0
  49. data/{samp → examples}/register_file/LICENSE +0 -0
  50. data/{samp → examples}/register_file/README +0 -0
  51. data/{samp → examples}/register_file/Rakefile +0 -0
  52. data/{samp → examples}/register_file/register_file.v +0 -0
  53. data/{samp → examples}/register_file/register_file_design.rb +0 -0
  54. data/examples/register_file/register_file_proto.rb +11 -0
  55. data/{samp → examples}/register_file/register_file_runner.rake +0 -0
  56. data/{samp → examples}/register_file/register_file_spec.rb +0 -0
  57. data/ext/main.c +5 -5
  58. data/ext/swig_vpi.i +6 -2
  59. data/lib/ruby-vpi/core/callback.rb +142 -0
  60. data/lib/ruby-vpi/core/edge.rb +128 -0
  61. data/lib/ruby-vpi/core/handle.rb +421 -0
  62. data/lib/ruby-vpi/core/scheduler.rb +244 -0
  63. data/lib/ruby-vpi/core/struct.rb +123 -0
  64. data/lib/ruby-vpi/core.rb +41 -0
  65. data/lib/ruby-vpi/rcov.rb +25 -12
  66. data/lib/ruby-vpi/runner.rb +30 -26
  67. data/lib/ruby-vpi/runner_boot_loader.rb +67 -37
  68. data/lib/ruby-vpi.rb +2 -2
  69. data/ref/c/annotated.html +1 -1
  70. data/ref/c/common_8h.html +1 -1
  71. data/ref/c/files.html +1 -1
  72. data/ref/c/functions.html +1 -1
  73. data/ref/c/functions_vars.html +1 -1
  74. data/ref/c/globals.html +1 -1
  75. data/ref/c/globals_0x63.html +1 -1
  76. data/ref/c/globals_0x65.html +1 -1
  77. data/ref/c/globals_0x66.html +1 -1
  78. data/ref/c/globals_0x6d.html +1 -1
  79. data/ref/c/globals_0x70.html +1 -1
  80. data/ref/c/globals_0x72.html +1 -1
  81. data/ref/c/globals_0x73.html +1 -1
  82. data/ref/c/globals_0x74.html +1 -1
  83. data/ref/c/globals_0x76.html +1 -1
  84. data/ref/c/globals_0x78.html +1 -1
  85. data/ref/c/globals_defs.html +1 -1
  86. data/ref/c/globals_defs_0x65.html +1 -1
  87. data/ref/c/globals_defs_0x70.html +1 -1
  88. data/ref/c/globals_defs_0x76.html +1 -1
  89. data/ref/c/globals_defs_0x78.html +1 -1
  90. data/ref/c/globals_enum.html +1 -1
  91. data/ref/c/globals_eval.html +1 -1
  92. data/ref/c/globals_func.html +1 -1
  93. data/ref/c/globals_type.html +1 -1
  94. data/ref/c/globals_vars.html +1 -1
  95. data/ref/c/index.html +1 -1
  96. data/ref/c/main_8c.html +1 -1
  97. data/ref/c/main_8h.html +1 -1
  98. data/ref/c/relay_8c.html +1 -1
  99. data/ref/c/relay_8h.html +1 -1
  100. data/ref/c/structt__cb__data.html +1 -1
  101. data/ref/c/structt__vpi__delay.html +1 -1
  102. data/ref/c/structt__vpi__error__info.html +1 -1
  103. data/ref/c/structt__vpi__strengthval.html +1 -1
  104. data/ref/c/structt__vpi__systf__data.html +1 -1
  105. data/ref/c/structt__vpi__time.html +1 -1
  106. data/ref/c/structt__vpi__value.html +1 -1
  107. data/ref/c/structt__vpi__vecval.html +1 -1
  108. data/ref/c/structt__vpi__vlog__info.html +1 -1
  109. data/ref/c/verilog_8h.html +1 -1
  110. data/ref/c/vlog_8c.html +1 -1
  111. data/ref/c/vlog_8h.html +1 -1
  112. data/ref/c/vpi__user_8h.html +1 -1
  113. data/ref/ruby/classes/ERB.html +7 -5
  114. data/ref/ruby/classes/ERB.src/{M000026.html → M000024.html} +0 -0
  115. data/ref/ruby/classes/FileUtils.html +11 -11
  116. data/ref/ruby/classes/FileUtils.src/{M000027.html → M000025.html} +0 -0
  117. data/ref/ruby/classes/FileUtils.src/{M000028.html → M000026.html} +0 -0
  118. data/ref/ruby/classes/Float.html +8 -6
  119. data/ref/ruby/classes/Float.src/{M000021.html → M000019.html} +0 -0
  120. data/ref/ruby/classes/Integer.html +67 -65
  121. data/ref/ruby/classes/Integer.src/M000007.html +25 -0
  122. data/ref/ruby/classes/Integer.src/{M000014.html → M000008.html} +5 -5
  123. data/ref/ruby/classes/Integer.src/M000009.html +5 -12
  124. data/ref/ruby/classes/Integer.src/M000010.html +5 -5
  125. data/ref/ruby/classes/Integer.src/M000011.html +5 -5
  126. data/ref/ruby/classes/Integer.src/M000012.html +5 -5
  127. data/ref/ruby/classes/Integer.src/M000015.html +25 -0
  128. data/ref/ruby/classes/Integer.src/M000016.html +31 -0
  129. data/ref/ruby/classes/Integer.src/M000017.html +12 -12
  130. data/ref/ruby/classes/Integer.src/M000018.html +17 -18
  131. data/ref/ruby/classes/Object.html +126 -0
  132. data/ref/ruby/classes/RDoc.html +5 -5
  133. data/ref/ruby/classes/RDoc.src/{M000061.html → M000081.html} +0 -0
  134. data/ref/ruby/classes/RubyVPI.html +50 -9
  135. data/ref/ruby/classes/String.html +22 -20
  136. data/ref/ruby/classes/String.src/M000020.html +36 -0
  137. data/ref/ruby/classes/String.src/M000021.html +41 -0
  138. data/ref/ruby/classes/String.src/M000022.html +5 -23
  139. data/ref/ruby/classes/String.src/M000023.html +5 -28
  140. data/ref/ruby/classes/{Vpi → VPI}/Handle.html +442 -140
  141. data/ref/ruby/classes/{Vpi/Handle.src/M000042.html → VPI/Handle.src/M000037.html} +4 -4
  142. data/ref/ruby/classes/VPI/Handle.src/M000038.html +21 -0
  143. data/ref/ruby/classes/VPI/Handle.src/M000039.html +18 -0
  144. data/ref/ruby/classes/{Vpi/Handle.src/M000036.html → VPI/Handle.src/M000040.html} +5 -5
  145. data/ref/ruby/classes/VPI/Handle.src/M000045.html +18 -0
  146. data/ref/ruby/classes/{Vpi/Handle.src/M000038.html → VPI/Handle.src/M000046.html} +5 -5
  147. data/ref/ruby/classes/VPI/Handle.src/M000057.html +18 -0
  148. data/ref/ruby/classes/{Vpi/Handle.src/M000040.html → VPI/Handle.src/M000058.html} +5 -5
  149. data/ref/ruby/classes/VPI/Handle.src/M000061.html +18 -0
  150. data/ref/ruby/classes/VPI/Handle.src/M000062.html +18 -0
  151. data/ref/ruby/classes/{Vpi/Handle.src/M000054.html → VPI/Handle.src/M000065.html} +11 -11
  152. data/ref/ruby/classes/VPI/Handle.src/M000067.html +21 -0
  153. data/ref/ruby/classes/VPI/Handle.src/M000068.html +28 -0
  154. data/ref/ruby/classes/VPI/Handle.src/M000069.html +50 -0
  155. data/ref/ruby/classes/{Vpi/Handle.src/M000048.html → VPI/Handle.src/M000070.html} +6 -6
  156. data/ref/ruby/classes/{Vpi/Handle.src/M000049.html → VPI/Handle.src/M000071.html} +6 -6
  157. data/ref/ruby/classes/{Vpi/Handle.src/M000050.html → VPI/Handle.src/M000072.html} +5 -5
  158. data/ref/ruby/classes/{Vpi/Handle.src/M000051.html → VPI/Handle.src/M000073.html} +17 -17
  159. data/ref/ruby/classes/VPI/Handle.src/M000075.html +18 -0
  160. data/ref/ruby/classes/VPI/Handle.src/M000076.html +40 -0
  161. data/ref/ruby/classes/{Vpi/Handle.src/M000056.html → VPI/Handle.src/M000077.html} +18 -18
  162. data/ref/ruby/classes/{Vpi → VPI}/S_vpi_time.html +22 -20
  163. data/ref/ruby/classes/VPI/S_vpi_time.src/M000078.html +18 -0
  164. data/ref/ruby/classes/VPI/S_vpi_time.src/M000079.html +19 -0
  165. data/ref/ruby/classes/{Vpi → VPI}/S_vpi_value.html +37 -23
  166. data/ref/ruby/classes/VPI/S_vpi_value.src/M000034.html +35 -0
  167. data/ref/ruby/classes/VPI/S_vpi_value.src/M000035.html +42 -0
  168. data/ref/ruby/classes/VPI/S_vpi_value.src/M000036.html +42 -0
  169. data/ref/ruby/classes/{Vpi.html → VPI.html} +129 -34
  170. data/ref/ruby/classes/VPI.src/M000027.html +19 -0
  171. data/ref/ruby/classes/VPI.src/M000028.html +18 -0
  172. data/ref/ruby/classes/VPI.src/M000029.html +19 -0
  173. data/ref/ruby/classes/VPI.src/M000031.html +25 -0
  174. data/ref/ruby/classes/VPI.src/M000032.html +26 -0
  175. data/ref/ruby/classes/VerilogParser/Module/Port.html +17 -15
  176. data/ref/ruby/classes/VerilogParser/Module/Port.src/M000004.html +23 -0
  177. data/ref/ruby/classes/VerilogParser/Module/Port.src/{M000007.html → M000005.html} +0 -0
  178. data/ref/ruby/classes/VerilogParser/Module/Port.src/M000006.html +5 -10
  179. data/ref/ruby/classes/VerilogParser/Module.html +7 -5
  180. data/ref/ruby/classes/VerilogParser/Module.src/{M000005.html → M000003.html} +0 -0
  181. data/ref/ruby/classes/VerilogParser.html +7 -5
  182. data/ref/ruby/classes/VerilogParser.src/{M000004.html → M000002.html} +0 -0
  183. data/ref/ruby/created.rid +1 -1
  184. data/ref/ruby/files/bin/generate_rb.html +2 -2
  185. data/ref/ruby/files/lib/ruby-vpi/{vpi_rb.html → core/callback_rb.html} +7 -8
  186. data/ref/ruby/files/lib/ruby-vpi/core/edge_rb.html +114 -0
  187. data/ref/ruby/files/lib/ruby-vpi/core/handle_rb.html +107 -0
  188. data/ref/ruby/files/lib/ruby-vpi/core/scheduler_rb.html +114 -0
  189. data/ref/ruby/files/lib/ruby-vpi/core/struct_rb.html +108 -0
  190. data/ref/ruby/files/lib/ruby-vpi/core_rb.html +121 -0
  191. data/ref/ruby/files/lib/ruby-vpi/rcov_rb.html +1 -1
  192. data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.html +5 -41
  193. data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.src/M000001.html +3 -3
  194. data/ref/ruby/files/lib/ruby-vpi/runner_rb.html +1 -1
  195. data/ref/ruby/files/lib/ruby-vpi_rb.html +1 -1
  196. data/ref/ruby/fr_class_index.html +5 -4
  197. data/ref/ruby/fr_file_index.html +6 -1
  198. data/ref/ruby/fr_method_index.html +80 -60
  199. metadata +126 -103
  200. data/ext/swig_vpi.h +0 -924
  201. data/ext/swig_wrap.cin +0 -7083
  202. data/lib/ruby-vpi/vpi.rb +0 -651
  203. data/ref/ruby/classes/Integer.src/M000013.html +0 -18
  204. data/ref/ruby/classes/Integer.src/M000019.html +0 -25
  205. data/ref/ruby/classes/Integer.src/M000020.html +0 -30
  206. data/ref/ruby/classes/String.src/M000024.html +0 -18
  207. data/ref/ruby/classes/String.src/M000025.html +0 -18
  208. data/ref/ruby/classes/VerilogParser/Module/Port.src/M000008.html +0 -18
  209. data/ref/ruby/classes/Vpi/Handle.src/M000035.html +0 -18
  210. data/ref/ruby/classes/Vpi/Handle.src/M000037.html +0 -18
  211. data/ref/ruby/classes/Vpi/Handle.src/M000039.html +0 -18
  212. data/ref/ruby/classes/Vpi/Handle.src/M000041.html +0 -18
  213. data/ref/ruby/classes/Vpi/Handle.src/M000043.html +0 -21
  214. data/ref/ruby/classes/Vpi/Handle.src/M000044.html +0 -21
  215. data/ref/ruby/classes/Vpi/Handle.src/M000045.html +0 -22
  216. data/ref/ruby/classes/Vpi/Handle.src/M000046.html +0 -50
  217. data/ref/ruby/classes/Vpi/Handle.src/M000047.html +0 -91
  218. data/ref/ruby/classes/Vpi/Handle.src/M000053.html +0 -18
  219. data/ref/ruby/classes/Vpi/Handle.src/M000057.html +0 -40
  220. data/ref/ruby/classes/Vpi/S_vpi_time.src/M000058.html +0 -18
  221. data/ref/ruby/classes/Vpi/S_vpi_time.src/M000059.html +0 -19
  222. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000032.html +0 -18
  223. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000033.html +0 -18
  224. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000034.html +0 -18
  225. data/ref/ruby/classes/Vpi.src/M000029.html +0 -28
  226. data/ref/ruby/classes/Vpi.src/M000030.html +0 -39
  227. data/ref/ruby/classes/Vpi.src/M000031.html +0 -20
  228. data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.src/M000002.html +0 -18
  229. data/samp/counter/RSpec/counter_proto.rb +0 -10
  230. data/samp/counter/xUnit/counter_proto.rb +0 -10
  231. data/samp/pipelined_alu/hw5_unit_proto.rb +0 -4
  232. data/samp/register_file/register_file_proto.rb +0 -11
@@ -0,0 +1,244 @@
1
+ # Concurrent processes.
2
+ #--
3
+ # Copyright 2007 Suraj N. Kurapati
4
+ # See the file named LICENSE for details.
5
+
6
+ Thread.abort_on_exception = true
7
+
8
+ require 'singleton'
9
+
10
+ module RubyVPI
11
+ class SchedulerClass #:nodoc:
12
+ include Singleton
13
+
14
+
15
+ Task = Struct.new(:thread, :state)
16
+
17
+ class Task #:nodoc:
18
+ def run
19
+ self.state = :run
20
+ self.thread.wakeup
21
+ end
22
+
23
+ def stop
24
+ self.state = :wait
25
+ Thread.stop
26
+ end
27
+
28
+ def stop?
29
+ self.thread.stop? and self.state == :wait
30
+ end
31
+ end
32
+
33
+
34
+ def initialize
35
+ @thread2task = { Thread.main => Task.new(Thread.main, :run) }
36
+ @thread2task_sw = @thread2task.dup # software threads
37
+ @thread2task_hw = {} # hardware threads (Ruby prototype of DUT)
38
+ @thread2task_lock = Mutex.new
39
+
40
+
41
+ # base case: hardware runs first before any software does at startup
42
+ @time = 0
43
+
44
+ unless RubyVPI::USE_PROTOTYPE
45
+ Callback.relay_verilog(VPI::CbReadOnlySynch, 0)
46
+ end
47
+
48
+ @scheduler = Thread.new do
49
+ # pause because boot loader is not fully init yet
50
+ Thread.stop
51
+
52
+ loop do
53
+ # run software in current time step
54
+ run_tasks @thread2task_sw, true
55
+ Edge.refresh_cache
56
+
57
+ # go to time slot where writing is permitted before flushing writes
58
+ unless RubyVPI::USE_PROTOTYPE
59
+ Callback.relay_verilog(VPI::CbAfterDelay, 1)
60
+ end
61
+
62
+ flush_writes
63
+
64
+ # run hardware in next time step
65
+ @time += 1
66
+
67
+ if RubyVPI::USE_PROTOTYPE
68
+ run_tasks @thread2task_hw, false
69
+ flush_writes
70
+ else
71
+ Callback.relay_verilog(VPI::CbReadOnlySynch, 0)
72
+ end
73
+ end
74
+ end
75
+
76
+
77
+ @handle2write = Hash.new {|h,k| h[k] = []}
78
+ @handle2write_lock = Mutex.new
79
+ end
80
+
81
+ def current_time
82
+ @time
83
+ end
84
+
85
+ def start
86
+ @scheduler.wakeup
87
+ end
88
+
89
+ # Registers the calling thread with the scheduler.
90
+ def attach
91
+ key = Thread.current
92
+
93
+ hash =
94
+ if caller.grep(/_proto\.rb/).empty?
95
+ @thread2task_sw
96
+ else
97
+ @thread2task_hw
98
+ end
99
+
100
+ @thread2task_lock.synchronize do
101
+ task = Task.new(key, :run)
102
+ hash[key] = task
103
+ @thread2task[key] = task
104
+ end
105
+ end
106
+
107
+ # Unregisters the calling thread from the scheduler.
108
+ def detach
109
+ key = Thread.current
110
+
111
+ @thread2task_lock.synchronize do
112
+ @thread2task.delete key
113
+ @thread2task_hw.delete key
114
+ @thread2task_sw.delete key
115
+ end
116
+ end
117
+
118
+ # Waits for the scheduler to arrive in the next time step.
119
+ def await
120
+ key = Thread.current
121
+
122
+ task = @thread2task_lock.synchronize do
123
+ @thread2task[key]
124
+ end
125
+
126
+ task.stop
127
+ end
128
+
129
+ def ensure_caller_is_registered
130
+ unless @thread2task_lock.synchronize {@thread2task.key? Thread.current}
131
+ raise SecurityError, 'This method may only be invoked from within a process (see the VPI::process() method).'
132
+ end
133
+ end
134
+
135
+ Write = Struct.new :thread, :trace, :args
136
+
137
+ # Captures the given write operation so it
138
+ # can be flushed later, at the correct time.
139
+ def capture_write aHandle, *aArgs
140
+ @handle2write_lock.synchronize do
141
+ @handle2write[aHandle] << Write.new(Thread.current, caller, aArgs)
142
+ end
143
+ end
144
+
145
+ private
146
+
147
+ # Flushes all captured writes.
148
+ def flush_writes
149
+ @handle2write_lock.synchronize do
150
+ @handle2write.each_pair do |handle, writes|
151
+ if writes.map {|w| w.thread}.uniq.length > 1
152
+ culprits = writes.map {|w| "\n\n#{w.thread}" << w.trace.map {|x| "\n\t#{x}"}.join}.join
153
+ STDERR.puts "Race condition detected at time step #{current_time}: the logic value of handle #{handle} is being modified by more than one concurrent process: #{culprits}"
154
+ exit 1
155
+ end
156
+
157
+ writes.each do |w|
158
+ VPI::__scheduler__vpi_put_value(handle, *w.args)
159
+ end
160
+
161
+ writes.clear
162
+ end
163
+ end
164
+ end
165
+
166
+ def run_tasks aHash, aExitWhenEmpty
167
+ @thread2task_lock.synchronize do
168
+ tasks = aHash.values
169
+ tasks.each {|t| t.run}
170
+
171
+ if aExitWhenEmpty and tasks.empty?
172
+ Thread.exit
173
+ end
174
+ end
175
+
176
+ loop do
177
+ ready = @thread2task_lock.synchronize do
178
+ aHash.values.all? {|t| t.stop?}
179
+ end
180
+
181
+ if ready
182
+ break
183
+ else
184
+ Thread.pass
185
+ end
186
+ end
187
+ end
188
+ end
189
+
190
+ Scheduler = SchedulerClass.instance
191
+ end
192
+
193
+ module VPI
194
+ alias_method :__scheduler__vpi_put_value, :vpi_put_value
195
+ module_function :__scheduler__vpi_put_value
196
+
197
+ def vpi_put_value *args #:nodoc:
198
+ RubyVPI::Scheduler.capture_write(*args)
199
+ end
200
+
201
+
202
+ # Returns the current simulation time.
203
+ def current_time
204
+ RubyVPI::Scheduler.current_time
205
+ end
206
+
207
+ # Wait until the simulation advances by the given number of time steps.
208
+ def advance_time aNumTimeSteps = 1
209
+ RubyVPI::Scheduler.ensure_caller_is_registered
210
+ aNumTimeSteps.times { RubyVPI::Scheduler.await }
211
+ end
212
+
213
+ alias wait advance_time
214
+
215
+
216
+ # Creates a new concurrent process, which will execute the
217
+ # given block with the given arguments, and returns it.
218
+ def process *aBlockArgs
219
+ RubyVPI::Scheduler.ensure_caller_is_registered
220
+ raise ArgumentError, "block must be given" unless block_given?
221
+
222
+ Thread.new do
223
+ RubyVPI::Scheduler.attach
224
+ yield(*aBlockArgs)
225
+ RubyVPI::Scheduler.detach
226
+ end
227
+ end
228
+
229
+ # Wraps the given block inside an infinite loop and executes it
230
+ # inside a new concurrent process (see the VPI::process method).
231
+ def always *aBlockArgs, &aBlock
232
+ process do
233
+ loop do
234
+ startTime = VPI.current_time
235
+ aBlock.call(*aBlockArgs)
236
+ finishTime = VPI.current_time
237
+
238
+ VPI.advance_time unless finishTime > startTime
239
+ end
240
+ end
241
+ end
242
+
243
+ alias forever always
244
+ end
@@ -0,0 +1,123 @@
1
+ # VPI structures (S_vpi_* and S_cb_*) stuff
2
+ #--
3
+ # Copyright 2006 Suraj N. Kurapati
4
+ # See the file named LICENSE for details.
5
+
6
+ module VPI
7
+ class S_vpi_time
8
+ # Returns the high and low portions of
9
+ # this time as a single 64-bit integer.
10
+ def integer
11
+ (self.high << INTEGER_BITS) | self.low
12
+ end
13
+
14
+ # Sets the high and low portions of this
15
+ # time from the given 64-bit integer.
16
+ def integer= aValue
17
+ self.low = aValue & INTEGER_MASK
18
+ self.high = (aValue >> INTEGER_BITS) & INTEGER_MASK
19
+ end
20
+
21
+ alias to_i integer
22
+ alias to_f real
23
+ end
24
+
25
+ class S_vpi_value
26
+ # Attempts to detect the format of the given value.
27
+ # Returns +nil+ if detection is not possible.
28
+ def S_vpi_value.detect_format aValue
29
+ if aValue.respond_to? :to_int
30
+ VpiIntVal
31
+
32
+ elsif aValue.respond_to? :to_float
33
+ VpiRealVal
34
+
35
+ elsif aValue.respond_to? :to_str
36
+ VpiStringVal
37
+
38
+ elsif aValue.is_a? S_vpi_time
39
+ VpiTimeVal
40
+
41
+ elsif aValue.is_a? S_vpi_vecval
42
+ VpiVectorVal
43
+
44
+ elsif aValue.is_a? S_vpi_strengthval
45
+ VpiStrengthVal
46
+ end
47
+ end
48
+
49
+ # Writes the given value, which has the given format.
50
+ def write aValue, aFormat
51
+ case aFormat
52
+ when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
53
+ value.str = aValue.to_s
54
+
55
+ when VpiScalarVal
56
+ value.scalar = aValue.to_i
57
+
58
+ when VpiIntVal
59
+ value.integer = aValue.to_i
60
+
61
+ when VpiRealVal
62
+ value.real = aValue.to_f
63
+
64
+ when VpiTimeVal
65
+ value.time = aValue
66
+
67
+ when VpiVectorVal
68
+ value.vector = aValue
69
+
70
+ when VpiStrengthVal
71
+ value.strength = aValue
72
+
73
+ else
74
+ raise "unknown format: #{aFormat.inspect}"
75
+ end
76
+ end
77
+
78
+ # Returns the value in the given format.
79
+ def read aFormat = self.format
80
+ case aFormat
81
+ when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
82
+ value.str.to_s
83
+
84
+ when VpiScalarVal
85
+ value.scalar.to_i
86
+
87
+ when VpiIntVal
88
+ value.integer.to_i
89
+
90
+ when VpiRealVal
91
+ value.real.to_f
92
+
93
+ when VpiTimeVal
94
+ value.time
95
+
96
+ when VpiVectorVal
97
+ value.vector
98
+
99
+ when VpiStrengthVal
100
+ value.strength
101
+
102
+ else
103
+ raise "unknown format: #{aFormat.inspect}"
104
+ end
105
+ end
106
+ end
107
+
108
+ # make VPI structs more accessible by allowing their
109
+ # members to be initialized through the constructor
110
+ constants.grep(/^S_/).each do |s|
111
+ const_get(s).class_eval do
112
+ alias __struct__initialize initialize
113
+
114
+ def initialize aMembers = {} #:nodoc:
115
+ __struct__initialize
116
+
117
+ aMembers.each_pair do |k, v|
118
+ __send__("#{k}=", v)
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,41 @@
1
+ # A utility layer which transforms the VPI interface
2
+ # into one that is more suitable for Ruby.
3
+ #--
4
+ # Copyright 2006 Suraj N. Kurapati
5
+ # See the file named LICENSE for details.
6
+
7
+ module VPI
8
+ # restore compatibility with the C language version of VPI: in Ruby,
9
+ # constants are capitalized, whereas in C, they do not have to be.
10
+ constants.grep(/^(S_|Cb|Vpi)/).each do |name|
11
+ meth = name[0,1].downcase << name[1..-1]
12
+ value = const_get(name)
13
+
14
+ define_method meth do value end
15
+ module_function meth
16
+ end
17
+
18
+ # Number of bits in PLI_INT32.
19
+ INTEGER_BITS = 32
20
+
21
+ # Lowest upper bound of PLI_INT32.
22
+ INTEGER_LIMIT = 2 ** INTEGER_BITS
23
+
24
+ # Bit-mask capable of capturing PLI_INT32.
25
+ INTEGER_MASK = INTEGER_LIMIT - 1
26
+ end
27
+
28
+ module RubyVPI
29
+ SIMULATOR = ENV['RUBYVPI_SIMULATOR'].to_sym
30
+ USE_DEBUGGER = ENV['DEBUGGER'].to_i == 1
31
+ USE_COVERAGE = ENV['COVERAGE'].to_i == 1
32
+ USE_PROTOTYPE = ENV['PROTOTYPE'].to_i == 1
33
+ USE_PROFILER = ENV['PROFILER'].to_i == 1
34
+ end
35
+
36
+ require 'thread'
37
+ require 'ruby-vpi/core/struct'
38
+ require 'ruby-vpi/core/handle'
39
+ require 'ruby-vpi/core/edge'
40
+ require 'ruby-vpi/core/callback'
41
+ require 'ruby-vpi/core/scheduler'
data/lib/ruby-vpi/rcov.rb CHANGED
@@ -23,23 +23,36 @@ require 'rcov'
23
23
  require 'rcov/report'
24
24
 
25
25
 
26
+ module RubyVPI::Coverage #:nodoc:
27
+ end
28
+
26
29
  module RubyVPI
27
- COVERAGE_ANALYSIS = Rcov::CodeCoverageAnalyzer.new
28
- COVERAGE_ANALYSIS.install_hook
30
+ module Coverage
31
+ @@analyzer = Rcov::CodeCoverageAnalyzer.new
32
+
33
+ def Coverage.start
34
+ @@analyzer.install_hook
35
+ end
36
+
37
+ def Coverage.stop
38
+ @@analyzer.remove_hook
39
+ end
29
40
 
30
- COVERAGE_ANALYSIS_HANDLERS = []
31
41
 
32
- at_exit do
33
- COVERAGE_ANALYSIS.remove_hook
42
+ @@handlers = []
34
43
 
35
- COVERAGE_ANALYSIS_HANDLERS.each do |a|
36
- a.call COVERAGE_ANALYSIS
44
+ # Invokes the given block after code coverage analysis has completed.
45
+ def Coverage.attach &aBlock # :yield: Rcov::CodeCoverageAnalyzer
46
+ raise ArgumentError unless block_given?
47
+ @@handlers << aBlock if aBlock
37
48
  end
38
- end
39
49
 
40
- # Invokes the given block, which yields COVERAGE_ANALYSIS,
41
- # after code coverage analysis has completed.
42
- def RubyVPI.with_coverage_analysis &aBlock # :nodoc:
43
- COVERAGE_ANALYSIS_HANDLERS << aBlock if aBlock
50
+ at_exit do
51
+ Coverage.stop
52
+
53
+ @@handlers.each do |h|
54
+ h.call @@analyzer
55
+ end
56
+ end
44
57
  end
45
58
  end
@@ -26,7 +26,7 @@ require 'ruby-vpi/util'
26
26
  end
27
27
 
28
28
  # auto-detect and set default parameters
29
- runnerPath = caller.grep(/runner.rake/).first.rstrip_from(':')
29
+ runnerPath = caller.grep(/runner\.rake/).first.rstrip_from(':')
30
30
  @target = File.basename(runnerPath).rstrip_from('_')
31
31
 
32
32
  task :setup
@@ -84,6 +84,15 @@ def expand_incdir_options aSimId # :nodoc:
84
84
  @incdirs.map {|i| prefix + i}
85
85
  end
86
86
 
87
+ # Creates a new task for running the given simulator.
88
+ def sim_task aSimId #:nodoc:
89
+ desc "Simulate with #{RubyVPI::SIMULATORS[aSimId].name}."
90
+ task aSimId => :setup do
91
+ ENV['RUBYVPI_SIMULATOR'] = aSimId.to_s
92
+ yield aSimId
93
+ end
94
+ end
95
+
87
96
 
88
97
  desc "Show a list of available tasks."
89
98
  task :default do
@@ -92,24 +101,22 @@ task :default do
92
101
  end
93
102
 
94
103
 
95
- desc "Simulate with #{RubyVPI::SIMULATORS[:cver].name}."
96
- task :cver => :setup do
104
+ sim_task :cver do |id|
97
105
  sh 'cver',
98
- "+loadvpi=#{object_file_path(:cver)}:#{LOADER_FUNC}",
99
- SIMULATOR_ARGUMENTS[:cver],
100
- expand_incdir_options(:cver),
106
+ "+loadvpi=#{object_file_path(id)}:#{LOADER_FUNC}",
107
+ SIMULATOR_ARGUMENTS[id],
108
+ expand_incdir_options(id),
101
109
  @sources
102
110
  end
103
111
 
104
112
  CLOBBER.include 'verilog.log'
105
113
 
106
114
 
107
- desc "Simulate with #{RubyVPI::SIMULATORS[:ivl].name}."
108
- task :ivl => :setup do
109
- cp object_file_path(:ivl), 'ruby-vpi.vpi'
115
+ sim_task :ivl do |id|
116
+ cp object_file_path(id), 'ruby-vpi.vpi'
110
117
  sh %w[iverilog -mruby-vpi],
111
- SIMULATOR_ARGUMENTS[:ivl],
112
- expand_incdir_options(:ivl),
118
+ SIMULATOR_ARGUMENTS[id],
119
+ expand_incdir_options(id),
113
120
  @sources
114
121
  sh 'vvp -M. a.out'
115
122
  end
@@ -117,28 +124,26 @@ end
117
124
  CLEAN.include 'ruby-vpi.vpi', 'a.out'
118
125
 
119
126
 
120
- desc "Simulate with #{RubyVPI::SIMULATORS[:vcs].name}."
121
- task :vcs => :setup do
127
+ sim_task :vcs do |id|
122
128
  sh %w[vcs -R +v2k +vpi +cli],
123
129
  '-P', File.join(File.dirname(__FILE__), 'pli.tab'),
124
- '-load', "#{object_file_path(:vcs)}:#{LOADER_FUNC}",
130
+ '-load', "#{object_file_path(id)}:#{LOADER_FUNC}",
125
131
  ('-full64' if @archIs64),
126
- SIMULATOR_ARGUMENTS[:vcs],
127
- expand_incdir_options(:vcs),
132
+ SIMULATOR_ARGUMENTS[id],
133
+ expand_incdir_options(id),
128
134
  @sources
129
135
  end
130
136
 
131
137
  CLEAN.include 'csrc', 'simv*'
132
138
 
133
139
 
134
- desc "Simulate with #{RubyVPI::SIMULATORS[:vsim].name}."
135
- task :vsim => :setup do
140
+ sim_task :vsim do |id|
136
141
  sh 'vlib work'
137
- sh 'vlog', expand_incdir_options(:vsim), @sources
142
+ sh 'vlog', expand_incdir_options(id), @sources
138
143
  sh %w[vsim -c],
139
144
  '-do', 'run -all; exit',
140
- '-pli', object_file_path(:vsim),
141
- SIMULATOR_ARGUMENTS[:vsim],
145
+ '-pli', object_file_path(id),
146
+ SIMULATOR_ARGUMENTS[id],
142
147
  @target
143
148
  end
144
149
 
@@ -146,13 +151,12 @@ CLEAN.include 'work', 'vsim.wlf'
146
151
  CLOBBER.include 'transcript'
147
152
 
148
153
 
149
- desc "Simulate with #{RubyVPI::SIMULATORS[:ncsim].name}."
150
- task :ncsim => :setup do
154
+ sim_task :ncsim do |id|
151
155
  sh %w[ncverilog +access+rwc +plinowarn],
152
- "+loadvpi=#{object_file_path(:ncsim)}:#{LOADER_FUNC}",
156
+ "+loadvpi=#{object_file_path(id)}:#{LOADER_FUNC}",
153
157
  ('+nc64bit' if @archIs64),
154
- SIMULATOR_ARGUMENTS[:ncsim],
155
- expand_incdir_options(:ncsim),
158
+ SIMULATOR_ARGUMENTS[id],
159
+ expand_incdir_options(id),
156
160
  @sources
157
161
  end
158
162