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,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