ruby-vpi 18.0.2 → 19.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,142 @@
1
+ # Simulation callbacks.
2
+ #--
3
+ # Copyright 2006 Suraj N. Kurapati
4
+ # See the file named LICENSE for details.
5
+
6
+ require 'singleton'
7
+
8
+ module RubyVPI
9
+ class CallbackClass #:nodoc:
10
+ include Singleton
11
+
12
+ def initialize
13
+ @id2handler = {}
14
+ @id2receipt = {}
15
+ @lock = Mutex.new
16
+ end
17
+
18
+ def attach aData, &aHandler
19
+ raise ArgumentError, "block must be given" unless block_given?
20
+ id = aHandler.object_id.to_s
21
+
22
+ # register the callback with Verilog
23
+ aData.user_data = id
24
+ aData.cb_rtn = VPI::Vlog_relay_ruby
25
+ receipt = VPI::__callback__vpi_register_cb(aData)
26
+
27
+ @lock.synchronize do
28
+ @id2handler[id] = aHandler
29
+ @id2receipt[id] = receipt
30
+ end
31
+
32
+ receipt
33
+ end
34
+
35
+ def detach aData
36
+ id = aData.user_data.to_s
37
+ receipt = @lock.synchronize{ @id2receipt[id] }
38
+
39
+ if receipt
40
+ VPI::__callback__vpi_remove_cb(receipt)
41
+
42
+ @lock.synchronize do
43
+ @id2handler.delete id
44
+ @id2receipt.delete id
45
+ end
46
+ end
47
+ end
48
+
49
+ # Transfers control to the simulator, which will return control
50
+ # during the given time slot after the given number of time steps.
51
+ def relay_verilog aTimeSlot, aNumSteps
52
+ # schedule wake-up callback from verilog
53
+ time = VPI::S_vpi_time.new
54
+ time.integer = aNumSteps
55
+ time.type = VPI::VpiSimTime
56
+
57
+ value = VPI::S_vpi_value.new
58
+ value.format = VPI::VpiSuppressVal
59
+
60
+ alarm = VPI::S_cb_data.new
61
+ alarm.reason = aTimeSlot
62
+ alarm.cb_rtn = VPI::Vlog_relay_ruby
63
+ alarm.obj = nil
64
+ alarm.time = time
65
+ alarm.value = value
66
+ alarm.index = 0
67
+ alarm.user_data = nil
68
+
69
+ VPI.vpi_free_object(VPI::__callback__vpi_register_cb(alarm))
70
+
71
+ # transfer control to verilog
72
+ loop do
73
+ VPI::__extension__relay_verilog
74
+
75
+ if reason = VPI::__extension__relay_ruby_reason # might be nil
76
+ id = reason.user_data.to_s
77
+
78
+ handler = @lock.synchronize do
79
+ @id2handler[id]
80
+ end
81
+
82
+ if handler
83
+ handler.call reason
84
+ else
85
+ break
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ Callback = CallbackClass.instance
93
+ end
94
+
95
+ module VPI
96
+ class Handle
97
+ # Registers a callback that is invoked
98
+ # whenever the value of this object changes.
99
+ def cbValueChange aOptions = {}, &aHandler
100
+ raise ArgumentError unless block_given?
101
+
102
+ aOptions[:time] ||= S_vpi_time.new(:type => VpiSuppressTime)
103
+ aOptions[:value] ||= S_vpi_value.new(:format => VpiSuppressVal)
104
+
105
+ alarm = S_cb_data.new(
106
+ :reason => CbValueChange,
107
+ :obj => self,
108
+ :time => aOptions[:time],
109
+ :value => aOptions[:value],
110
+ :index => 0
111
+ )
112
+
113
+ vpi_register_cb alarm, &aHandler
114
+ end
115
+ end
116
+
117
+
118
+ alias_method :__callback__vpi_register_cb, :vpi_register_cb
119
+ module_function :__callback__vpi_register_cb
120
+
121
+ # This is a Ruby version of the vpi_register_cb C function. It is
122
+ # identical to the C function, except for the following differences:
123
+ #
124
+ # * This method accepts a block (callback handler)
125
+ # which is executed whenever the callback occurs.
126
+ #
127
+ # * This method overwrites the +cb_rtn+ and +user_data+
128
+ # fields of the given +S_cb_data+ object.
129
+ #
130
+ def vpi_register_cb aData, &aHandler # :yields: VPI::S_cb_data
131
+ raise ArgumentError, "block must be given" unless block_given?
132
+ RubyVPI::Callback.attach(aData, &aHandler)
133
+ end
134
+
135
+
136
+ alias_method :__callback__vpi_remove_cb, :vpi_remove_cb
137
+ module_function :__callback__vpi_remove_cb
138
+
139
+ def vpi_remove_cb aData # :nodoc:
140
+ RubyVPI::Callback.detach(aData)
141
+ end
142
+ end
@@ -0,0 +1,128 @@
1
+ # Value change / edge detection for handles.
2
+ #--
3
+ # Copyright 2007 Suraj N. Kurapati
4
+ # See the file named LICENSE for details.
5
+
6
+ require 'singleton'
7
+
8
+ module RubyVPI
9
+ class EdgeClass #:nodoc:
10
+ include Singleton
11
+
12
+ def initialize
13
+ @handles = []
14
+ @lock = Mutex.new
15
+ end
16
+
17
+ # Begins monitoring the given handle for value change.
18
+ def monitor aHandle
19
+ # ignore handles that cannot hold a meaningful value
20
+ type = VPI::vpi_get_str(VpiType, aHandle)
21
+ return if type =~ /Bit|Array|Module|Parameter/
22
+
23
+ @lock.synchronize do
24
+ unless @handles.include? aHandle
25
+ @handles << aHandle
26
+ refresh_handle aHandle
27
+ end
28
+ end
29
+ end
30
+
31
+ # Refreshes the cached value of all monitored handles.
32
+ def refresh_cache
33
+ @lock.synchronize do
34
+ @handles.each do |h|
35
+ refresh_handle h
36
+ end
37
+ end
38
+ end
39
+
40
+ # Remember the current value as the "previous" value.
41
+ def refresh_handle aHandle
42
+ aHandle.instance_eval do
43
+ @__edge__prev_val = get_value(VpiHexStrVal)
44
+ end
45
+ end
46
+ end
47
+
48
+ Edge = EdgeClass.instance
49
+ end
50
+
51
+ module VPI
52
+ class Handle
53
+ # create methods for detecting all possible value changes
54
+ vals = %w[0 1 x z]
55
+ edges = vals.map {|a| vals.map {|b| a + b}}.flatten
56
+
57
+ edges.each do |edge|
58
+ meth = "change_#{edge}?"
59
+ old, new = edge.split(//)
60
+
61
+ old_int = old =~ /[01]/
62
+ new_int = new =~ /[01]/
63
+
64
+ old_read = old_int ? 'int' : 'hex'
65
+ new_read = new_int ? 'VpiIntVal' : 'VpiHexStrVal'
66
+
67
+ old_test = old_int ? "== #{old}" : "=~ /#{old}/i"
68
+ new_test = new_int ? "== #{new}" : "=~ /#{new}/i"
69
+
70
+ class_eval %{
71
+ def #{meth}
72
+ old = __edge__prev_val_#{old_read}
73
+ new = get_value(#{new_read})
74
+
75
+ old #{old_test} and new #{new_test}
76
+ end
77
+ }
78
+ end
79
+
80
+ alias posedge? change_01?
81
+ alias negedge? change_10?
82
+
83
+ # Tests if either a positive or negative edge has occurred.
84
+ def edge?
85
+ posedge? or negedge?
86
+ end
87
+
88
+ # Tests if the logic value of this handle has
89
+ # changed since the last simulation time step.
90
+ def change?
91
+ old = __edge__prev_val_hex
92
+ new = get_value(VpiHexStrVal)
93
+
94
+ old != new
95
+ end
96
+
97
+
98
+ private
99
+
100
+ # Returns the previous value as a hex string.
101
+ def __edge__prev_val_hex #:nodoc:
102
+ @__edge__prev_val.to_s
103
+ end
104
+
105
+ # Returns the previous value as an integer.
106
+ def __edge__prev_val_int #:nodoc:
107
+ __edge__prev_val_hex.to_i(16)
108
+ end
109
+ end
110
+
111
+ %w[
112
+ vpi_handle_by_name
113
+ vpi_handle_by_index
114
+ vpi_handle
115
+ vpi_scan
116
+ ].each do |src|
117
+ dst = "__value_change__#{src}"
118
+ alias_method dst, src
119
+
120
+ define_method src do |*args|
121
+ if result = __send__(dst, *args)
122
+ RubyVPI::Edge.monitor(result)
123
+ end
124
+
125
+ result
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,421 @@
1
+ # Interface to VPI handles.
2
+ #--
3
+ # Copyright 2006 Suraj N. Kurapati
4
+ # See the file named LICENSE for details.
5
+
6
+ module VPI
7
+ Handle = SWIG::TYPE_p_unsigned_int
8
+
9
+ # A handle is an object inside a Verilog simulation (see
10
+ # *vpiHandle* in IEEE Std. 1364-2005). VPI types and
11
+ # properties listed in ext/vpi_user.h can be specified by
12
+ # their names (strings or symbols) or integer constants.
13
+ #
14
+ # = Example names
15
+ # * "intVal"
16
+ # * :intVal
17
+ # * "vpiIntVal"
18
+ # * :vpiIntVal
19
+ # * "VpiIntVal"
20
+ # * :VpiIntVal
21
+ #
22
+ # = Example constants
23
+ # * VpiIntVal
24
+ # * VpiModule
25
+ # * VpiReg
26
+ #
27
+ class Handle
28
+ include VPI
29
+
30
+ # Tests if the logic value of this handle is unknown (x).
31
+ def x?
32
+ get_value(VpiHexStrVal) =~ /x/i
33
+ end
34
+
35
+ # Sets the logic value of this handle to unknown (x).
36
+ def x!
37
+ put_value('x', VpiHexStrVal)
38
+ end
39
+
40
+ alias unknown? x?
41
+ alias unknown! x!
42
+
43
+ alias dont_care? x?
44
+ alias dont_care! x!
45
+
46
+ # Tests if the logic value of this handle is high impedance (z).
47
+ def z?
48
+ get_value(VpiHexStrVal) =~ /z/i
49
+ end
50
+
51
+ # Sets the logic value of this handle to high impedance (z).
52
+ def z!
53
+ put_value('z', VpiHexStrVal)
54
+ end
55
+
56
+ alias hi_z? z?
57
+ alias hi_z! z!
58
+
59
+ alias high_z? z?
60
+ alias high_z! z!
61
+
62
+ alias high_impedance? z?
63
+ alias high_impedance! z!
64
+
65
+ alias tri_state? z?
66
+ alias tri_state! z!
67
+
68
+ alias floating? z?
69
+ alias floating! z!
70
+
71
+ # Tests if the logic value of this handle is at "logic high" level.
72
+ def high?
73
+ get_value(VpiIntVal) != 0
74
+ end
75
+
76
+ # Sets the logic value of this handle to "logic high" level.
77
+ def high!
78
+ put_value(1, VpiIntVal)
79
+ end
80
+
81
+ alias one? high?
82
+ alias one! high!
83
+
84
+ # Tests if the logic value of this handle is at "logic low" level.
85
+ def low?
86
+ get_value(VpiHexStrVal) =~ /^0+$/
87
+ end
88
+
89
+ # Sets the logic value of this handle to "logic low" level.
90
+ def low!
91
+ put_value(0, VpiIntVal)
92
+ end
93
+
94
+ alias zero? low?
95
+ alias zero! low!
96
+
97
+
98
+ # Inspects the given VPI property names, in
99
+ # addition to those common to all handles.
100
+ def inspect *aPropNames
101
+ aPropNames.unshift :name, :fullName, :size, :file, :lineNo, :hexStrVal
102
+
103
+ aPropNames.map! do |name|
104
+ "#{name}=#{__send__(name).inspect}"
105
+ end
106
+
107
+ "#<VPI::Handle #{vpi_get_str(VpiType, self)} #{aPropNames.join(', ')}>"
108
+ end
109
+
110
+ alias to_s inspect
111
+
112
+
113
+ #---------------------------------------------------------------------------
114
+ # reading & writing values
115
+ #---------------------------------------------------------------------------
116
+
117
+ # Reads the value using the given format (name or
118
+ # integer constant) and returns a +S_vpi_value+ object.
119
+ def get_value_wrapper aFormat
120
+ fmt = resolve_prop_type(aFormat)
121
+ val = S_vpi_value.new(:format => fmt)
122
+ vpi_get_value(self, val)
123
+ val
124
+ end
125
+
126
+ # Reads the value using the given format (name or integer constant) and
127
+ # returns it. If a format is not given, then it is assumed to be VpiIntVal.
128
+ def get_value aFormat = VpiIntVal
129
+ fmt = resolve_prop_type(aFormat)
130
+ @size ||= vpi_get(VpiSize, self)
131
+
132
+ if fmt == VpiIntVal and @size > INTEGER_BITS
133
+ fmt = VpiHexStrVal
134
+ val = get_value_wrapper(fmt)
135
+ val.read(fmt).to_i(16)
136
+ else
137
+ val = get_value_wrapper(fmt)
138
+ val.read(fmt)
139
+ end
140
+ end
141
+
142
+ # Writes the given value using the given format (name or integer
143
+ # constant), time, and delay, and then returns the written value.
144
+ #
145
+ # * If a format is not given, then the Verilog simulator
146
+ # will attempt to determine the correct format.
147
+ #
148
+ def put_value aValue, aFormat = nil, aTime = nil, aDelay = VpiNoDelay
149
+ if vpi_get(VpiType, self) == VpiNet
150
+ aDelay = VpiForceFlag
151
+
152
+ if driver = self[VpiDriver].find {|d| vpi_get(VpiType, d) != VpiForce}
153
+ warn "forcing value #{aValue.inspect} onto wire #{self} that is already driven by #{driver.inspect}"
154
+ end
155
+ end
156
+
157
+ aFormat =
158
+ if aFormat
159
+ resolve_prop_type(aFormat)
160
+ else
161
+ S_vpi_value.detect_format(aValue) ||
162
+ get_value_wrapper(VpiObjTypeVal).format # let the simulator detect
163
+ end
164
+
165
+ if aFormat == VpiIntVal
166
+ @size ||= vpi_get(VpiSize, self)
167
+
168
+ unless @size < INTEGER_BITS
169
+ aFormat = VpiHexStrVal
170
+ aValue = aValue.to_i.to_s(16)
171
+ end
172
+ end
173
+
174
+ aTime ||= S_vpi_time.new(:type => VpiSimTime, :integer => 0)
175
+
176
+ wrapper = S_vpi_value.new(:format => aFormat)
177
+ result = wrapper.write(aValue, aFormat)
178
+
179
+ vpi_put_value(self, wrapper, aTime, aDelay)
180
+
181
+ result
182
+ end
183
+
184
+ # Forces the given value (see arguments for #put_value) onto this handle.
185
+ def force_value *args
186
+ args[3] = VpiForceFlag
187
+ put_value(*args)
188
+ end
189
+
190
+ # Releases a previously forced value on this handle.
191
+ def release_value
192
+ # this doesn't really change the value, it only removes the force flag
193
+ put_value(0, VpiIntVal, nil, VpiReleaseFlag)
194
+ end
195
+
196
+ # Tests if there is currently a value forced onto this handle.
197
+ def force?
198
+ self[VpiDriver].any? {|d| vpi_get(VpiType, d) == VpiForce}
199
+ end
200
+
201
+
202
+ #---------------------------------------------------------------------------
203
+ # accessing related handles / traversing the hierarchy
204
+ #---------------------------------------------------------------------------
205
+
206
+ # Returns an array of child handles of the
207
+ # given types (name or integer constant).
208
+ def [] *aTypes
209
+ handles = []
210
+
211
+ aTypes.each do |arg|
212
+ t = resolve_prop_type(arg)
213
+
214
+ if itr = vpi_iterate(t, self)
215
+ while h = vpi_scan(itr)
216
+ handles << h
217
+ end
218
+ end
219
+ end
220
+
221
+ handles
222
+ end
223
+
224
+ # inherit Enumerable methods, such as #each, #map, #select, etc.
225
+ Enumerable.instance_methods.push('each').each do |meth|
226
+ # using a string because define_method
227
+ # does not accept a block until Ruby 1.9
228
+ class_eval %{
229
+ def #{meth}(*args, &block)
230
+ if ary = self[*args]
231
+ ary.#{meth}(&block)
232
+ end
233
+ end
234
+ }, __FILE__, __LINE__
235
+ end
236
+
237
+ # bypass Enumerable's #to_a method, which relies on #each
238
+ alias to_a []
239
+
240
+ # Sort by absolute VPI path.
241
+ def <=> other
242
+ get_value(VpiFullName) <=> other.get_value(VpiFullName)
243
+ end
244
+
245
+
246
+ #---------------------------------------------------------------------------
247
+ # accessing VPI properties
248
+ #---------------------------------------------------------------------------
249
+
250
+ @@propCache = Hash.new {|h, k| h[k] = Property.new(k)}
251
+
252
+ undef type # used to access VpiType
253
+
254
+ # Provides access to this handle's (1) child handles
255
+ # and (2) VPI properties through method calls. In the
256
+ # case that a child handle has the same name as a VPI
257
+ # property, the child handle will be accessed instead
258
+ # of the VPI property. However, you can still access
259
+ # the VPI property via #get_value and #put_value.
260
+ def method_missing aMeth, *aArgs, &aBlockArg
261
+ # cache the result for future accesses, in order
262
+ # to cut down number of calls to method_missing()
263
+ eigen_class = (class << self; self; end)
264
+
265
+ if child = vpi_handle_by_name(aMeth.to_s, self)
266
+ eigen_class.class_eval do
267
+ define_method aMeth do
268
+ child
269
+ end
270
+ end
271
+
272
+ child
273
+ else
274
+ # XXX: using a string because define_method() does
275
+ # not support a block argument until Ruby 1.9
276
+ eigen_class.class_eval %{
277
+ def #{aMeth}(*a, &b)
278
+ @@propCache[#{aMeth.inspect}].execute(self, *a, &b)
279
+ end
280
+ }, __FILE__, __LINE__
281
+
282
+ __send__(aMeth, *aArgs, &aBlockArg)
283
+ end
284
+ end
285
+
286
+ private
287
+
288
+ class Property # :nodoc:
289
+ attr_reader :name, :type, :accessor, :operation
290
+
291
+ def initialize aMethName
292
+ @methName = aMethName.to_s
293
+
294
+ # parse property information from the given method name
295
+ tokens = @methName.split('_')
296
+
297
+ tokens.last.sub!(/[\?!=]$/, '')
298
+ addendum = $&
299
+ @isAssign = $& == '='
300
+ isQuery = $& == '?'
301
+
302
+ tokens.last =~ /^[a-z]$/ && tokens.pop
303
+ @accessor = $&
304
+
305
+ @name = tokens.pop
306
+
307
+ @operation = unless tokens.empty?
308
+ tokens.join('_') << (addendum || '')
309
+ end
310
+
311
+ # determine the VPI integer type for the property
312
+ @name = @name.to_ruby_const_name
313
+ @name.insert 0, 'Vpi' unless @name =~ /^[Vv]pi/
314
+
315
+ begin
316
+ @type = VPI.const_get(@name)
317
+ rescue NameError
318
+ raise ArgumentError, "#{@name.inspect} is not a valid VPI property"
319
+ end
320
+
321
+ @accessor = if @accessor
322
+ @accessor.to_sym
323
+ else
324
+ # infer accessor from VPI property @name
325
+ if isQuery
326
+ :b
327
+ else
328
+ case @name
329
+ when /Time$/
330
+ :d
331
+
332
+ when /Val$/
333
+ :l
334
+
335
+ when /Type$/, /Direction$/, /Index$/, /Size$/, /Strength\d?$/, /Polarity$/, /Edge$/, /Offset$/, /Mode$/, /LineNo$/
336
+ :i
337
+
338
+ when /Is[A-Z]/, /ed$/
339
+ :b
340
+
341
+ when /Name$/, /File$/, /Decompile$/
342
+ :s
343
+
344
+ when /Parent$/, /Inst$/, /Range$/, /Driver$/, /Net$/, /Load$/, /Conn$/, /Bit$/, /Word$/, /[LR]hs$/, /(In|Out)$/, /Term$/, /Argument$/, /Condition$/, /Use$/, /Operand$/, /Stmt$/, /Expr$/, /Scope$/, /Memory$/, /Delay$/
345
+ :h
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ def execute aHandle, *aArgs, &aBlockArg
352
+ if @operation
353
+ aHandle.__send__(@operation, @type, *aArgs, &aBlockArg)
354
+ else
355
+ case @accessor
356
+ when :d # delay values
357
+ raise NotImplementedError, 'processing of delay values is not yet implemented.'
358
+ # TODO: vpi_put_delays
359
+ # TODO: vpi_get_delays
360
+
361
+ when :l # logic values
362
+ if @isAssign
363
+ value = aArgs.shift
364
+ aHandle.put_value(value, @type, *aArgs)
365
+ else
366
+ aHandle.get_value(@type)
367
+ end
368
+
369
+ when :i # integer values
370
+ if @isAssign
371
+ raise NotImplementedError
372
+ else
373
+ vpi_get(@type, aHandle)
374
+ end
375
+
376
+ when :b # boolean values
377
+ if @isAssign
378
+ raise NotImplementedError
379
+ else
380
+ value = vpi_get(@type, aHandle)
381
+ value && (value != 0) # zero is false in C
382
+ end
383
+
384
+ when :s # string values
385
+ if @isAssign
386
+ raise NotImplementedError
387
+ else
388
+ vpi_get_str(@type, aHandle)
389
+ end
390
+
391
+ when :h # handle values
392
+ if @isAssign
393
+ raise NotImplementedError
394
+ else
395
+ vpi_handle(@type, aHandle)
396
+ end
397
+
398
+ when :a # array of child handles
399
+ if @isAssign
400
+ raise NotImplementedError
401
+ else
402
+ aHandle[@type]
403
+ end
404
+
405
+ else
406
+ raise NoMethodError, "cannot access VPI property #{@name.inspect} for handle #{aHandle.inspect} through method #{@methName.inspect} with arguments #{aArgs.inspect}"
407
+ end
408
+ end
409
+ end
410
+ end
411
+
412
+ # resolve type names into type constants
413
+ def resolve_prop_type aNameOrType
414
+ if aNameOrType.respond_to? :to_int and not aNameOrType.is_a? Symbol
415
+ aNameOrType.to_int
416
+ else
417
+ @@propCache[aNameOrType.to_sym].type
418
+ end
419
+ end
420
+ end
421
+ end