ruby-vpi 17.0.0 → 18.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 (126) hide show
  1. data/LICENSE +8 -6
  2. data/Rakefile +4 -4
  3. data/doc/common.css +6 -9
  4. data/doc/common.inc +3 -3
  5. data/doc/common.tpl +14 -6
  6. data/doc/history.html +152 -44
  7. data/doc/history.inc +55 -3
  8. data/doc/history.yaml +62 -2
  9. data/doc/intro.inc +20 -16
  10. data/doc/manual.doc +23 -9
  11. data/doc/manual.html +232 -200
  12. data/doc/memo.doc +7 -6
  13. data/doc/memo.html +28 -17
  14. data/doc/readme.doc +1 -1
  15. data/doc/readme.html +51 -35
  16. data/doc/rss.xml +96 -70
  17. data/ext/Rakefile +24 -11
  18. data/ext/swig_vpi.h +1 -1
  19. data/ext/swig_wrap.cin +17 -42
  20. data/lib/ruby-vpi/pli.tab +1 -0
  21. data/lib/ruby-vpi/runner.rb +34 -10
  22. data/lib/ruby-vpi/vpi.rb +483 -438
  23. data/ref/c/annotated.html +1 -1
  24. data/ref/c/common_8h.html +1 -1
  25. data/ref/c/files.html +1 -1
  26. data/ref/c/functions.html +1 -1
  27. data/ref/c/functions_vars.html +1 -1
  28. data/ref/c/globals.html +1 -1
  29. data/ref/c/globals_0x63.html +1 -1
  30. data/ref/c/globals_0x65.html +1 -1
  31. data/ref/c/globals_0x66.html +1 -1
  32. data/ref/c/globals_0x6d.html +1 -1
  33. data/ref/c/globals_0x70.html +1 -1
  34. data/ref/c/globals_0x72.html +1 -1
  35. data/ref/c/globals_0x73.html +1 -1
  36. data/ref/c/globals_0x74.html +1 -1
  37. data/ref/c/globals_0x76.html +1 -1
  38. data/ref/c/globals_0x78.html +1 -1
  39. data/ref/c/globals_defs.html +1 -1
  40. data/ref/c/globals_defs_0x65.html +1 -1
  41. data/ref/c/globals_defs_0x70.html +1 -1
  42. data/ref/c/globals_defs_0x76.html +1 -1
  43. data/ref/c/globals_defs_0x78.html +1 -1
  44. data/ref/c/globals_enum.html +1 -1
  45. data/ref/c/globals_eval.html +1 -1
  46. data/ref/c/globals_func.html +1 -1
  47. data/ref/c/globals_type.html +1 -1
  48. data/ref/c/globals_vars.html +1 -1
  49. data/ref/c/index.html +1 -1
  50. data/ref/c/main_8c.html +1 -1
  51. data/ref/c/main_8h.html +1 -1
  52. data/ref/c/relay_8c.html +1 -1
  53. data/ref/c/relay_8h.html +1 -1
  54. data/ref/c/structt__cb__data.html +1 -1
  55. data/ref/c/structt__vpi__delay.html +1 -1
  56. data/ref/c/structt__vpi__error__info.html +1 -1
  57. data/ref/c/structt__vpi__strengthval.html +1 -1
  58. data/ref/c/structt__vpi__systf__data.html +1 -1
  59. data/ref/c/structt__vpi__time.html +1 -1
  60. data/ref/c/structt__vpi__value.html +1 -1
  61. data/ref/c/structt__vpi__vecval.html +1 -1
  62. data/ref/c/structt__vpi__vlog__info.html +1 -1
  63. data/ref/c/verilog_8h.html +1 -1
  64. data/ref/c/vlog_8c.html +1 -1
  65. data/ref/c/vlog_8h.html +1 -1
  66. data/ref/c/vpi__user_8h.html +1 -1
  67. data/ref/ruby/classes/RDoc.html +5 -5
  68. data/ref/ruby/classes/RDoc.src/{M000058.html → M000061.html} +0 -0
  69. data/ref/ruby/classes/String.html +24 -24
  70. data/ref/ruby/classes/String.src/M000022.html +23 -5
  71. data/ref/ruby/classes/String.src/M000023.html +28 -5
  72. data/ref/ruby/classes/String.src/M000024.html +5 -23
  73. data/ref/ruby/classes/String.src/M000025.html +5 -28
  74. data/ref/ruby/classes/Vpi/Handle.html +94 -49
  75. data/ref/ruby/classes/Vpi/Handle.src/M000035.html +4 -4
  76. data/ref/ruby/classes/Vpi/Handle.src/M000036.html +4 -4
  77. data/ref/ruby/classes/Vpi/Handle.src/M000037.html +4 -4
  78. data/ref/ruby/classes/Vpi/Handle.src/M000038.html +4 -4
  79. data/ref/ruby/classes/Vpi/Handle.src/M000039.html +4 -4
  80. data/ref/ruby/classes/Vpi/Handle.src/M000040.html +4 -4
  81. data/ref/ruby/classes/Vpi/Handle.src/M000041.html +4 -4
  82. data/ref/ruby/classes/Vpi/Handle.src/M000042.html +4 -4
  83. data/ref/ruby/classes/Vpi/Handle.src/M000043.html +7 -7
  84. data/ref/ruby/classes/Vpi/Handle.src/M000044.html +7 -7
  85. data/ref/ruby/classes/Vpi/Handle.src/M000045.html +8 -8
  86. data/ref/ruby/classes/Vpi/Handle.src/M000046.html +36 -30
  87. data/ref/ruby/classes/Vpi/Handle.src/M000047.html +72 -67
  88. data/ref/ruby/classes/Vpi/Handle.src/M000048.html +6 -17
  89. data/ref/ruby/classes/Vpi/Handle.src/M000049.html +19 -0
  90. data/ref/ruby/classes/Vpi/Handle.src/M000050.html +5 -5
  91. data/ref/ruby/classes/Vpi/Handle.src/M000051.html +16 -10
  92. data/ref/ruby/classes/Vpi/Handle.src/M000053.html +5 -18
  93. data/ref/ruby/classes/Vpi/Handle.src/M000054.html +11 -76
  94. data/ref/ruby/classes/Vpi/Handle.src/M000056.html +31 -0
  95. data/ref/ruby/classes/Vpi/Handle.src/M000057.html +40 -0
  96. data/ref/ruby/classes/Vpi/S_vpi_time.html +16 -16
  97. data/ref/ruby/classes/Vpi/S_vpi_time.src/{M000055.html → M000058.html} +4 -4
  98. data/ref/ruby/classes/Vpi/S_vpi_time.src/M000059.html +19 -0
  99. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000032.html +4 -4
  100. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000033.html +4 -4
  101. data/ref/ruby/classes/Vpi/S_vpi_value.src/M000034.html +4 -4
  102. data/ref/ruby/classes/Vpi.html +0 -7
  103. data/ref/ruby/classes/Vpi.src/M000029.html +14 -14
  104. data/ref/ruby/classes/Vpi.src/M000030.html +25 -24
  105. data/ref/ruby/classes/Vpi.src/M000031.html +6 -6
  106. data/ref/ruby/created.rid +1 -1
  107. data/ref/ruby/files/bin/convert_rb.html +1 -1
  108. data/ref/ruby/files/bin/generate_rb.html +1 -1
  109. data/ref/ruby/files/lib/ruby-vpi/erb_rb.html +1 -1
  110. data/ref/ruby/files/lib/ruby-vpi/float_rb.html +1 -1
  111. data/ref/ruby/files/lib/ruby-vpi/integer_rb.html +1 -1
  112. data/ref/ruby/files/lib/ruby-vpi/rake_rb.html +1 -1
  113. data/ref/ruby/files/lib/ruby-vpi/rcov_rb.html +1 -1
  114. data/ref/ruby/files/lib/ruby-vpi/rdoc_rb.html +1 -1
  115. data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.html +1 -1
  116. data/ref/ruby/files/lib/ruby-vpi/runner_proxy_rb.html +1 -1
  117. data/ref/ruby/files/lib/ruby-vpi/runner_rb.html +1 -1
  118. data/ref/ruby/files/lib/ruby-vpi/util_rb.html +1 -1
  119. data/ref/ruby/files/lib/ruby-vpi/verilog_parser_rb.html +1 -1
  120. data/ref/ruby/files/lib/ruby-vpi/vpi_rb.html +8 -1
  121. data/ref/ruby/files/lib/ruby-vpi_rb.html +1 -1
  122. data/ref/ruby/fr_method_index.html +19 -16
  123. data/samp/register_file/register_file.v +1 -1
  124. data/samp/register_file/register_file_spec.rb +9 -5
  125. metadata +42 -38
  126. data/ref/ruby/classes/Vpi/S_vpi_time.src/M000056.html +0 -19
data/lib/ruby-vpi/vpi.rb CHANGED
@@ -4,6 +4,8 @@
4
4
  # Copyright 2006-2007 Suraj N. Kurapati
5
5
  # See the file named LICENSE for details.
6
6
 
7
+ require 'ruby-vpi/util'
8
+
7
9
  module Vpi
8
10
  # Number of bits in PLI_INT32.
9
11
  INTEGER_BITS = 32
@@ -14,593 +16,636 @@ module Vpi
14
16
  # Bit-mask capable of capturing PLI_INT32.
15
17
  INTEGER_MASK = INTEGER_LIMIT - 1
16
18
 
19
+
20
+ ##############################################################################
17
21
  # handles
22
+ ##############################################################################
23
+
24
+ Handle = SWIG::TYPE_p_unsigned_int
25
+
26
+ # A handle is an object inside a Verilog simulation (see
27
+ # *vpiHandle* in IEEE Std. 1364-2005). VPI types and
28
+ # properties listed in ext/vpi_user.h can be specified by
29
+ # their names (strings or symbols) or integer constants.
30
+ #
31
+ # = Example names
32
+ # * "intVal"
33
+ # * :intVal
34
+ # * "vpiIntVal"
35
+ # * :vpiIntVal
36
+ # * "VpiIntVal"
37
+ # * :VpiIntVal
38
+ #
39
+ # = Example constants
40
+ # * VpiIntVal
41
+ # * VpiModule
42
+ # * VpiReg
43
+ #
44
+ class Handle
45
+ undef type # used to access vpiType
46
+ include Vpi
47
+
48
+ # Tests if the logic value of this handle is unknown (x).
49
+ def x?
50
+ self.hexStrVal =~ /x/i
51
+ end
18
52
 
19
- Handle = SWIG::TYPE_p_unsigned_int
53
+ # Sets the logic value of this handle to unknown (x).
54
+ def x!
55
+ self.hexStrVal = 'x'
56
+ end
20
57
 
21
- # A handle is an object inside a Verilog simulation (see
22
- # *vpiHandle* in IEEE Std. 1364-2005). VPI types and
23
- # properties listed in ext/vpi_user.h can be specified by
24
- # their names (strings or symbols) or integer constants.
25
- #
26
- # = Example names
27
- # * "intVal"
28
- # * :intVal
29
- # * "vpiIntVal"
30
- # * :vpiIntVal
31
- # * "VpiIntVal"
32
- # * :VpiIntVal
33
- #
34
- # = Example constants
35
- # * VpiIntVal
36
- # * VpiModule
37
- # * VpiReg
38
- #
39
- class Handle
40
- include Vpi
58
+ # Tests if the logic value of this handle is high impedance (z).
59
+ def z?
60
+ self.hexStrVal =~ /z/i
61
+ end
41
62
 
42
- # Tests if the logic value of this handle is unknown (x).
43
- def x?
44
- self.hexStrVal =~ /x/i
45
- end
63
+ # Sets the logic value of this handle to high impedance (z).
64
+ def z!
65
+ self.hexStrVal = 'z'
66
+ end
46
67
 
47
- # Sets the logic value of this handle to unknown (x).
48
- def x!
49
- self.hexStrVal = 'x'
50
- end
68
+ # Tests if the logic value of this handle is at "logic high" level.
69
+ def high?
70
+ self.intVal != 0
71
+ end
51
72
 
52
- # Tests if the logic value of this handle is high impedance (z).
53
- def z?
54
- self.hexStrVal =~ /z/i
55
- end
73
+ # Sets the logic value of this handle to "logic high" level.
74
+ def high!
75
+ self.intVal = 1
76
+ end
56
77
 
57
- # Sets the logic value of this handle to high impedance (z).
58
- def z!
59
- self.hexStrVal = 'z'
60
- end
78
+ # Tests if the logic value of this handle is at "logic low" level.
79
+ def low?
80
+ self.hexStrVal =~ /^0+$/
81
+ end
61
82
 
62
- # Tests if the logic value of this handle is at "logic high" level.
63
- def high?
64
- self.intVal != 0
65
- end
83
+ # Sets the logic value of this handle to "logic low" level.
84
+ def low!
85
+ self.intVal = 0
86
+ end
66
87
 
67
- # Sets the logic value of this handle to "logic high" level.
68
- def high!
69
- self.intVal = 1
70
- end
88
+ # Tests if the logic value of this handle is currently at a positive edge.
89
+ def posedge?
90
+ old = @lastVal
91
+ new = @lastVal = self.intVal
71
92
 
72
- # Tests if the logic value of this handle is at "logic low" level.
73
- def low?
74
- self.hexStrVal =~ /^0+$/
75
- end
93
+ old == 0 && new == 1
94
+ end
76
95
 
77
- # Sets the logic value of this handle to "logic low" level.
78
- def low!
79
- self.intVal = 0
80
- end
96
+ # Tests if the logic value of this handle is currently at a negative edge.
97
+ def negedge?
98
+ old = @lastVal
99
+ new = @lastVal = self.intVal
81
100
 
82
- # Tests if the logic value of this handle is currently at a positive edge.
83
- def posedge?
84
- old = @lastVal
85
- new = @lastVal = self.intVal
101
+ old == 1 && new == 0
102
+ end
86
103
 
87
- old == 0 && new == 1
88
- end
104
+ # Reads the value using the given
105
+ # format (integer constant) and
106
+ # returns a +S_vpi_value+ object.
107
+ def get_value_wrapper aFormat
108
+ val = S_vpi_value.new
109
+ val.format = aFormat
89
110
 
90
- # Tests if the logic value of this handle is currently at a negative edge.
91
- def negedge?
92
- old = @lastVal
93
- new = @lastVal = self.intVal
111
+ vpi_get_value self, val
112
+ val
113
+ end
94
114
 
95
- old == 1 && new == 0
96
- end
115
+ # Reads the value using the given format (name or
116
+ # integer constant) and returns it. If a format is
117
+ # not given, then it is assumed to be VpiIntVal.
118
+ def get_value aFormat = VpiIntVal
119
+ val = get_value_wrapper(resolve_prop_type(aFormat))
97
120
 
98
- # Reads the value using the given
99
- # format (integer constant) and
100
- # returns a +S_vpi_value+ object.
101
- def get_value_wrapper aFormat
102
- val = S_vpi_value.new
103
- val.format = aFormat
121
+ case val.format
122
+ when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
123
+ val.value.str.to_s
104
124
 
105
- vpi_get_value self, val
106
- val
107
- end
125
+ when VpiScalarVal
126
+ val.value.scalar.to_i
108
127
 
109
- # Reads the value using the given format (name or
110
- # integer constant) and returns it. If a format
111
- # is not given, then the Verilog simulator will
112
- # attempt to determine the correct format.
113
- def get_value aFormat = VpiObjTypeVal
114
- val = get_value_wrapper(resolve_prop_type(aFormat))
128
+ when VpiIntVal
129
+ @size ||= vpi_get(VpiSize, self)
115
130
 
116
- case val.format
117
- when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
118
- val.value.str
131
+ if @size < INTEGER_BITS
132
+ val.value.integer.to_i
133
+ else
134
+ get_value_wrapper(VpiHexStrVal).value.str.to_s.to_i(16)
135
+ end
119
136
 
120
- when VpiScalarVal
121
- val.value.scalar
137
+ when VpiRealVal
138
+ val.value.real.to_f
122
139
 
123
- when VpiIntVal
124
- get_value_wrapper(VpiBinStrVal).value.str.gsub(/[^01]/, '0').to_i(2)
140
+ when VpiTimeVal
141
+ val.value.time
125
142
 
126
- when VpiRealVal
127
- val.value.real
143
+ when VpiVectorVal
144
+ val.value.vector
128
145
 
129
- when VpiTimeVal
130
- val.value.time
146
+ when VpiStrengthVal
147
+ val.value.strength
131
148
 
132
- when VpiVectorVal
133
- val.value.vector
149
+ else
150
+ raise "unknown S_vpi_value.format: #{val.format.inspect}"
151
+ end
152
+ end
134
153
 
135
- when VpiStrengthVal
136
- val.value.strength
154
+ # Writes the given value using the given format (name or integer
155
+ # constant), time, and delay, and then returns the written value.
156
+ #
157
+ # * If a format is not given, then the Verilog simulator
158
+ # will attempt to determine the correct format.
159
+ #
160
+ def put_value aValue, aFormat = nil, aTime = nil, aDelay = VpiNoDelay
161
+ if vpi_get(VpiType, self) == VpiNet
162
+ aDelay = VpiForceFlag
137
163
 
138
- else
139
- raise "unknown S_vpi_value.format: #{val.format}"
164
+ if driver = self[VpiDriver].find {|d| d.vpiType != VpiForce}
165
+ warn "forcing value #{aValue.inspect} onto wire #{self} that is already driven by #{driver.inspect}"
140
166
  end
141
167
  end
142
168
 
143
- # Writes the given value using the given format (name or
144
- # integer constant), time, and delay, and then returns the
145
- # given value. If a format is not given, then the Verilog
146
- # simulator will attempt to determine the correct format.
147
- def put_value aValue, aFormat = nil, aTime = nil, aDelay = VpiNoDelay
148
- aFormat =
149
- if aFormat
150
- resolve_prop_type(aFormat)
151
- else
152
- get_value_wrapper(VpiObjTypeVal).format
153
- end
169
+ aFormat =
170
+ if aFormat
171
+ resolve_prop_type(aFormat)
154
172
 
155
- newVal = S_vpi_value.new(:format => aFormat)
173
+ elsif aValue.respond_to? :to_int
174
+ VpiIntVal
156
175
 
157
- case aFormat
158
- when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
159
- newVal.value.str = aValue.to_s
176
+ elsif aValue.respond_to? :to_float
177
+ VpiRealVal
160
178
 
161
- when VpiScalarVal
162
- newVal.value.scalar = aValue
179
+ elsif aValue.respond_to? :to_str
180
+ VpiStringVal
163
181
 
164
- when VpiIntVal
165
- newVal.format = VpiHexStrVal
166
- newVal.value.str = aValue.to_i.to_s(16)
182
+ elsif aValue.is_a? S_vpi_time
183
+ VpiTimeVal
167
184
 
168
- when VpiRealVal
169
- newVal.value.real = aValue.to_f
185
+ elsif aValue.is_a? S_vpi_vecval
186
+ VpiVectorVal
170
187
 
171
- when VpiTimeVal
172
- newVal.value.time = aValue
188
+ elsif aValue.is_a? S_vpi_strengthval
189
+ VpiStrengthVal
173
190
 
174
- when VpiVectorVal
175
- newVal.value.vector = aValue
191
+ else
192
+ get_value_wrapper(VpiObjTypeVal).format
193
+ end
194
+
195
+ newVal = S_vpi_value.new(:format => aFormat)
196
+
197
+ writtenVal =
198
+ case aFormat
199
+ when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
200
+ newVal.value.str = aValue.to_s
176
201
 
177
- when VpiStrengthVal
178
- newVal.value.strength = aValue
202
+ when VpiScalarVal
203
+ newVal.value.scalar = aValue.to_i
179
204
 
205
+ when VpiIntVal
206
+ @size ||= vpi_get(VpiSize, self)
207
+
208
+ if @size < INTEGER_BITS
209
+ newVal.format = VpiIntVal
210
+ newVal.value.integer = aValue.to_i
180
211
  else
181
- raise "unknown S_vpi_value.format: #{newVal.format}"
182
- end
212
+ newVal.format = VpiHexStrVal
213
+ newVal.value.str = aValue.to_i.to_s(16)
214
+ end
183
215
 
184
- vpi_put_value(self, newVal, aTime, aDelay)
216
+ when VpiRealVal
217
+ newVal.value.real = aValue.to_f
185
218
 
186
- # ensure that value was written correctly
187
- readenVal = get_value(aFormat)
219
+ when VpiTimeVal
220
+ newVal.value.time = aValue
188
221
 
189
- writtenCorrectly =
190
- case aFormat
191
- when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal
192
- if aValue =~ /[xz]/i # TODO: verify 'z' behavior
193
- readenVal =~ /[xz]/i
194
- else
195
- readenVal == aValue.to_s
196
- end
222
+ when VpiVectorVal
223
+ newVal.value.vector = aValue
197
224
 
198
- when VpiStringVal
199
- readenVal == aValue.to_s
225
+ when VpiStrengthVal
226
+ newVal.value.strength = aValue
200
227
 
201
- when VpiIntVal
202
- # allow for register overflow when limit reached
203
- readenVal == (aValue.to_i % (2 ** vpi_get(VpiSize, self)))
228
+ else
229
+ raise "unknown S_vpi_value.format: #{newVal.format.inspect}"
230
+ end
204
231
 
205
- when VpiRealVal
206
- readenVal == aValue.to_f
232
+ vpi_put_value(self, newVal, aTime, aDelay)
207
233
 
208
- else
209
- true
210
- end
234
+ writtenVal
235
+ end
211
236
 
212
- unless writtenCorrectly
213
- raise "value written (#{aValue.inspect}) does not match value read (#{readenVal.inspect}) on handle #{self}"
214
- end
237
+ # Forces the given value (see arguments for #put_value) onto this handle.
238
+ def force_value *args
239
+ args[3] = VpiForceFlag
240
+ put_value(*args)
241
+ end
215
242
 
216
- aValue
217
- end
243
+ # Releases a previously forced value on this handle.
244
+ def release_value
245
+ # this doesn't really change the value, it only removes the force flag
246
+ put_value(0, VpiIntVal, nil, VpiReleaseFlag)
247
+ end
248
+
249
+ # Tests if there is currently a value forced onto this handle.
250
+ def value_forced?
251
+ self[VpiDriver].any? {|d| d.vpiType == VpiForce}
252
+ end
218
253
 
219
- # Returns an array of child handles of the
220
- # given types (name or integer constant).
221
- def [] *aTypes
222
- handles = []
223
254
 
224
- aTypes.each do |arg|
225
- t = resolve_prop_type(arg)
255
+ # Returns an array of child handles of the
256
+ # given types (name or integer constant).
257
+ def [] *aTypes
258
+ handles = []
226
259
 
227
- if itr = vpi_iterate(t, self)
228
- while h = vpi_scan(itr)
229
- handles << h
230
- end
260
+ aTypes.each do |arg|
261
+ t = resolve_prop_type(arg)
262
+
263
+ if itr = vpi_iterate(t, self)
264
+ while h = vpi_scan(itr)
265
+ handles << h
231
266
  end
232
267
  end
233
-
234
- handles
235
268
  end
236
269
 
270
+ handles
271
+ end
237
272
 
238
- # inherit Enumerable methods, such as #each, #map, #select, etc.
239
- Enumerable.instance_methods.push('each').each do |meth|
240
- # using a string because define_method
241
- # does not accept a block until Ruby 1.9
242
- class_eval %{
243
- def #{meth}(*args, &block)
244
- if ary = self[*args]
245
- ary.#{meth}(&block)
246
- end
247
- end
248
- }, __FILE__, __LINE__
273
+ # inherit Enumerable methods, such as #each, #map, #select, etc.
274
+ Enumerable.instance_methods.push('each').each do |meth|
275
+ # using a string because define_method
276
+ # does not accept a block until Ruby 1.9
277
+ class_eval %{
278
+ def #{meth}(*args, &block)
279
+ if ary = self[*args]
280
+ ary.#{meth}(&block)
281
+ end
249
282
  end
283
+ }, __FILE__, __LINE__
284
+ end
250
285
 
251
- # bypass Enumerable's #to_a method, which relies on #each
252
- alias to_a []
253
-
254
- # Sort by absolute VPI path.
255
- def <=> other
256
- self.fullName <=> other.fullName
257
- end
286
+ # bypass Enumerable's #to_a method, which relies on #each
287
+ alias to_a []
258
288
 
289
+ # Sort by absolute VPI path.
290
+ def <=> other
291
+ self.fullName <=> other.fullName
292
+ end
259
293
 
260
- # Inspects the given VPI property names, in
261
- # addition to those common to all handles.
262
- def inspect *aPropNames
263
- aPropNames.unshift :fullName, :size, :file, :lineNo
264
294
 
265
- aPropNames.map! do |name|
266
- "#{name}=#{self.send(name.to_sym)}"
267
- end
295
+ # Inspects the given VPI property names, in
296
+ # addition to those common to all handles.
297
+ def inspect *aPropNames
298
+ aPropNames.unshift :name, :fullName, :size, :file, :lineNo, :hexStrVal
268
299
 
269
- "#<Vpi::Handle #{vpiType_s} #{aPropNames.join(', ')}>"
300
+ aPropNames.map! do |name|
301
+ "#{name}=#{self.send(name.to_sym).inspect}"
270
302
  end
271
303
 
272
- alias to_s inspect
304
+ "#<Vpi::Handle #{vpiType_s} #{aPropNames.join(', ')}>"
305
+ end
273
306
 
274
- # Registers a callback that is invoked
275
- # whenever the value of this object changes.
276
- def cbValueChange aOptions = {}, &aHandler
277
- raise ArgumentError unless block_given?
307
+ alias to_s inspect
278
308
 
279
- aOptions[:time] ||= S_vpi_time.new(:type => VpiSuppressTime)
280
- aOptions[:value] ||= S_vpi_value.new(:format => VpiSuppressVal)
309
+ # Registers a callback that is invoked
310
+ # whenever the value of this object changes.
311
+ def cbValueChange aOptions = {}, &aHandler
312
+ raise ArgumentError unless block_given?
281
313
 
282
- alarm = S_cb_data.new(
283
- :reason => CbValueChange,
284
- :obj => self,
285
- :time => aOptions[:time],
286
- :value => aOptions[:value],
287
- :index => 0
288
- )
314
+ aOptions[:time] ||= S_vpi_time.new(:type => VpiSuppressTime)
315
+ aOptions[:value] ||= S_vpi_value.new(:format => VpiSuppressVal)
289
316
 
290
- vpi_register_cb alarm, &aHandler
291
- end
317
+ alarm = S_cb_data.new(
318
+ :reason => CbValueChange,
319
+ :obj => self,
320
+ :time => aOptions[:time],
321
+ :value => aOptions[:value],
322
+ :index => 0
323
+ )
292
324
 
325
+ vpi_register_cb alarm, &aHandler
326
+ end
293
327
 
294
- @@propCache = Hash.new {|h, k| h[k] = Property.resolve(k)}
295
-
296
- # Provides access to this handle's (1) child handles
297
- # and (2) VPI properties through method calls. In the
298
- # case that a child handle has the same name as a VPI
299
- # property, the child handle will be accessed instead
300
- # of the VPI property. However, you can still access
301
- # the VPI property via #get_value and #put_value.
302
- def method_missing aMeth, *aArgs, &aBlockArg
303
- if child = vpi_handle_by_name(aMeth.to_s, self)
304
- # cache the child for future accesses, in order
305
- # to cut down number of calls to method_missing
306
- (class << self; self; end).class_eval do
307
- define_method aMeth do
308
- child
309
- end
310
- end
311
328
 
312
- child
329
+ @@propCache = Hash.new {|h, k| h[k] = Property.new(k)}
313
330
 
314
- else
315
- prop = @@propCache[aMeth]
331
+ # Provides access to this handle's (1) child handles
332
+ # and (2) VPI properties through method calls. In the
333
+ # case that a child handle has the same name as a VPI
334
+ # property, the child handle will be accessed instead
335
+ # of the VPI property. However, you can still access
336
+ # the VPI property via #get_value and #put_value.
337
+ def method_missing aMeth, *aArgs, &aBlockArg
338
+ # cache the result for future accesses, in order
339
+ # to cut down number of calls to method_missing()
340
+ eigen_class = (class << self; self; end)
316
341
 
317
- if prop.operation
318
- self.__send__(prop.operation, prop.type, *aArgs, &aBlockArg)
319
- else
320
- case prop.accessor
321
- when :d # delay values
322
- raise NotImplementedError, 'processing of delay values is not yet implemented.'
323
- # TODO: vpi_put_delays
324
- # TODO: vpi_get_delays
325
-
326
- when :l # logic values
327
- if prop.assignment
328
- value = aArgs.shift
329
- put_value(value, prop.type, *aArgs)
330
- else
331
- get_value(prop.type)
332
- end
333
-
334
- when :i # integer values
335
- unless prop.assignment
336
- vpi_get(prop.type, self)
337
- else
338
- raise NotImplementedError
339
- end
340
-
341
- when :b # boolean values
342
- unless prop.assignment
343
- value = vpi_get(prop, self)
344
- value && (value != 0) # zero is false in C
345
- else
346
- raise NotImplementedError
347
- end
348
-
349
- when :s # string values
350
- unless prop.assignment
351
- vpi_get_str(prop.type, self)
352
- else
353
- raise NotImplementedError
354
- end
355
-
356
- when :h # handle values
357
- unless prop.assignment
358
- vpi_handle(prop.type, self)
359
- else
360
- raise NotImplementedError
361
- end
362
-
363
- when :a # array of child handles
364
- unless prop.assignment
365
- self[prop.type]
366
- else
367
- raise NotImplementedError
368
- end
369
-
370
- else
371
- raise NoMethodError, "unable to access VPI property #{prop.name.inspect} through method #{aMeth.inspect} with arguments #{aArgs.inspect} for handle #{self}"
372
- end
342
+ if child = vpi_handle_by_name(aMeth.to_s, self)
343
+ eigen_class.class_eval do
344
+ define_method aMeth do
345
+ child
373
346
  end
374
347
  end
375
- end
376
348
 
377
- private
378
-
379
- Property = Struct.new(:type, :name, :operation, :accessor, :assignment)
349
+ child
350
+ else
351
+ # XXX: using a string because define_method() does
352
+ # not support a block argument until Ruby 1.9
353
+ eigen_class.class_eval %{
354
+ def #{aMeth}(*a, &b)
355
+ @@propCache[#{aMeth.inspect}].execute(self, *a, &b)
356
+ end
357
+ }, __FILE__, __LINE__
380
358
 
381
- # Resolves the given shorthand name into
382
- # a description of its VPI property.
383
- def Property.resolve aName # :nodoc:
384
- # parse the given property name
385
- tokens = aName.to_s.split(/_/)
359
+ self.__send__(aMeth, *aArgs, &aBlockArg)
360
+ end
361
+ end
386
362
 
363
+ private
387
364
 
388
- tokens.last.sub!(/[\?!=]$/, '')
365
+ class Property # :nodoc:
366
+ def initialize aMethName
367
+ @methName = aMethName.to_s
389
368
 
390
- addendum = $&
391
- isAssign = $& == '='
392
- isQuery = $& == '?'
369
+ # parse property information from the given method name
370
+ tokens = @methName.split('_')
393
371
 
372
+ tokens.last.sub!(/[\?!=]$/, '')
373
+ addendum = $&
374
+ @isAssign = $& == '='
375
+ isQuery = $& == '?'
394
376
 
395
377
  tokens.last =~ /^[a-z]$/ && tokens.pop
396
- accessor = $&
378
+ @accessor = $&
397
379
 
398
- name = tokens.pop
380
+ @name = tokens.pop
399
381
 
400
- operation =
401
- unless tokens.empty?
402
- tokens.join('_') << (addendum || '')
403
- end
382
+ @operation = unless tokens.empty?
383
+ tokens.join('_') << (addendum || '')
384
+ end
404
385
 
405
386
  # determine the VPI integer type for the property
406
- name = name[0, 1].upcase << name[1..-1]
407
- name.insert 0, 'Vpi' unless name =~ /^[Vv]pi/
387
+ @name = @name.to_ruby_const_name
388
+ @name.insert 0, 'Vpi' unless @name =~ /^[Vv]pi/
408
389
 
409
390
  begin
410
- type = Vpi.const_get(name)
391
+ @type = Vpi.const_get(@name)
411
392
  rescue NameError
412
- raise ArgumentError, "#{name.inspect} is not a valid VPI property"
393
+ raise ArgumentError, "#{@name.inspect} is not a valid VPI property"
413
394
  end
414
395
 
415
- accessor =
416
- if accessor
417
- accessor.to_sym
396
+ @accessor = if @accessor
397
+ @accessor.to_sym
398
+ else
399
+ # infer accessor from VPI property @name
400
+ if isQuery
401
+ :b
402
+ else
403
+ case @name
404
+ when /Time$/
405
+ :d
406
+
407
+ when /Val$/
408
+ :l
409
+
410
+ when /Type$/, /Direction$/, /Index$/, /Size$/, /Strength\d?$/, /Polarity$/, /Edge$/, /Offset$/, /Mode$/, /LineNo$/
411
+ :i
418
412
 
419
- else # infer accessor from VPI property name
420
- if isQuery
413
+ when /Is[A-Z]/, /ed$/
421
414
  :b
422
415
 
416
+ when /Name$/, /File$/, /Decompile$/
417
+ :s
418
+
419
+ when /Parent$/, /Inst$/, /Range$/, /Driver$/, /Net$/, /Load$/, /Conn$/, /Bit$/, /Word$/, /[LR]hs$/, /(In|Out)$/, /Term$/, /Argument$/, /Condition$/, /Use$/, /Operand$/, /Stmt$/, /Expr$/, /Scope$/, /Memory$/, /Delay$/
420
+ :h
421
+ end
422
+ end
423
+ end
424
+ end
425
+
426
+ def execute aHandle, *aArgs, &aBlockArg
427
+ if @operation
428
+ aHandle.__send__(@operation, @type, *aArgs, &aBlockArg)
429
+ else
430
+ case @accessor
431
+ when :d # delay values
432
+ raise NotImplementedError, 'processing of delay values is not yet implemented.'
433
+ # TODO: vpi_put_delays
434
+ # TODO: vpi_get_delays
435
+
436
+ when :l # logic values
437
+ if @isAssign
438
+ value = aArgs.shift
439
+ aHandle.put_value(value, @type, *aArgs)
423
440
  else
424
- case name
425
- when /Time$/
426
- :d
441
+ aHandle.get_value(@type)
442
+ end
427
443
 
428
- when /Val$/
429
- :l
444
+ when :i # integer values
445
+ if @isAssign
446
+ raise NotImplementedError
447
+ else
448
+ vpi_get(@type, aHandle)
449
+ end
430
450
 
431
- when /Type$/, /Direction$/, /Index$/, /Size$/, /Strength\d?$/, /Polarity$/, /Edge$/, /Offset$/, /Mode$/, /LineNo$/
432
- :i
451
+ when :b # boolean values
452
+ if @isAssign
453
+ raise NotImplementedError
454
+ else
455
+ value = vpi_get(@type, aHandle)
456
+ value && (value != 0) # zero is false in C
457
+ end
433
458
 
434
- when /Is[A-Z]/, /ed$/
435
- :b
459
+ when :s # string values
460
+ if @isAssign
461
+ raise NotImplementedError
462
+ else
463
+ vpi_get_str(@type, aHandle)
464
+ end
436
465
 
437
- when /Name$/, /File$/, /Decompile$/
438
- :s
466
+ when :h # handle values
467
+ if @isAssign
468
+ raise NotImplementedError
469
+ else
470
+ vpi_handle(@type, aHandle)
471
+ end
439
472
 
440
- when /Parent$/, /Inst$/, /Range$/, /Driver$/, /Net$/, /Load$/, /Conn$/, /Bit$/, /Word$/, /[LR]hs$/, /(In|Out)$/, /Term$/, /Argument$/, /Condition$/, /Use$/, /Operand$/, /Stmt$/, /Expr$/, /Scope$/, /Memory$/, /Delay$/
441
- :h
442
- end
473
+ when :a # array of child handles
474
+ if @isAssign
475
+ raise NotImplementedError
476
+ else
477
+ aHandle[@type]
443
478
  end
444
- end
445
479
 
446
- Property.new(type, name, operation, accessor, isAssign)
480
+ else
481
+ raise NoMethodError, "cannot access VPI property #{@name.inspect} for handle #{aHandle.inspect} through method #{@methName.inspect} with arguments #{aArgs.inspect}"
482
+ end
483
+ end
447
484
  end
485
+ end
448
486
 
449
- # resolve type names into type constants
450
- def resolve_prop_type aNameOrType
451
- if aNameOrType.is_a? Integer
452
- aNameOrType
453
- else
454
- @@propCache[aNameOrType.to_sym].type
455
- end
487
+ # resolve type names into type constants
488
+ def resolve_prop_type aNameOrType
489
+ if aNameOrType.respond_to? :to_int
490
+ aNameOrType.to_int
491
+ else
492
+ @@propCache[aNameOrType.to_sym].type
456
493
  end
457
494
  end
495
+ end
458
496
 
459
497
 
498
+ ##############################################################################
460
499
  # callbacks
500
+ ##############################################################################
461
501
 
462
- Callback = Struct.new :handler, :token #:nodoc:
463
- @@callbacks = {}
502
+ Callback = Struct.new :handler, :token #:nodoc:
503
+ @@callbacks = {}
464
504
 
465
- alias vpi_register_cb_old vpi_register_cb
505
+ alias vpi_register_cb_old vpi_register_cb
466
506
 
467
- # This is a Ruby version of the vpi_register_cb C function. It is
468
- # identical to the C function, except for the following differences:
469
- #
470
- # * This method accepts a block (callback handler)
471
- # which is executed whenever the callback occurs.
472
- #
473
- # * This method overwrites the +cb_rtn+ and +user_data+
474
- # fields of the given +S_cb_data+ object.
475
- #
476
- def vpi_register_cb aData, &aHandler # :yields: Vpi::S_cb_data
477
- raise ArgumentError, "block must be given" unless block_given?
507
+ # This is a Ruby version of the vpi_register_cb C function. It is
508
+ # identical to the C function, except for the following differences:
509
+ #
510
+ # * This method accepts a block (callback handler)
511
+ # which is executed whenever the callback occurs.
512
+ #
513
+ # * This method overwrites the +cb_rtn+ and +user_data+
514
+ # fields of the given +S_cb_data+ object.
515
+ #
516
+ def vpi_register_cb aData, &aHandler # :yields: Vpi::S_cb_data
517
+ raise ArgumentError, "block must be given" unless block_given?
478
518
 
479
- key = aHandler.object_id.to_s
519
+ key = aHandler.object_id.to_s
480
520
 
481
- # register the callback with Verilog
482
- aData.user_data = key
483
- aData.cb_rtn = Vlog_relay_ruby
484
- token = vpi_register_cb_old(aData)
521
+ # register the callback with Verilog
522
+ aData.user_data = key
523
+ aData.cb_rtn = Vlog_relay_ruby
524
+ token = vpi_register_cb_old(aData)
485
525
 
486
- @@callbacks[key] = Callback.new(aHandler, token)
487
- token
488
- end
526
+ @@callbacks[key] = Callback.new(aHandler, token)
527
+ token
528
+ end
489
529
 
490
- alias vpi_remove_cb_old vpi_remove_cb
530
+ alias vpi_remove_cb_old vpi_remove_cb
491
531
 
492
- def vpi_remove_cb aData # :nodoc:
493
- key = aData.user_data
532
+ def vpi_remove_cb aData # :nodoc:
533
+ key = aData.user_data
494
534
 
495
- if c = @@callbacks[key]
496
- vpi_remove_cb_old c.token
497
- @@callbacks.delete key
498
- end
535
+ if c = @@callbacks[key]
536
+ vpi_remove_cb_old c.token
537
+ @@callbacks.delete key
499
538
  end
539
+ end
500
540
 
501
- # Proxy for relay_verilog which supports callbacks. This method
502
- # should NOT be invoked from callback handlers (see vpi_register_cb)
503
- # and threads -- otherwise the situation will be like seven remote
504
- # controls changing the channel on a single television set!
505
- def relay_verilog_proxy # :nodoc:
506
- loop do
507
- relay_verilog
541
+ # Proxy for relay_verilog which supports callbacks. This method
542
+ # should NOT be invoked from callback handlers (see vpi_register_cb)
543
+ # and threads -- otherwise the situation will be like seven remote
544
+ # controls changing the channel on a single television set!
545
+ def relay_verilog_proxy # :nodoc:
546
+ loop do
547
+ relay_verilog
508
548
 
509
- if reason = relay_ruby_reason # might be nil
510
- dst = reason.user_data
549
+ if reason = relay_ruby_reason # might be nil
550
+ dst = reason.user_data
511
551
 
512
- if c = @@callbacks[dst]
513
- c.handler.call reason
514
- else
515
- break # main thread is receiver
516
- end
552
+ if c = @@callbacks[dst]
553
+ c.handler.call reason
554
+ else
555
+ break # main thread is receiver
517
556
  end
518
557
  end
519
558
  end
559
+ end
520
560
 
521
561
 
562
+ ##############################################################################
522
563
  # simulation control
564
+ ##############################################################################
523
565
 
524
- # Advances the simulation by the given number of steps.
525
- def advance_time aNumSteps = 1
526
- # schedule wake-up callback from verilog
527
- time = S_vpi_time.new
528
- time.integer = aNumSteps
529
- time.type = VpiSimTime
566
+ # Advances the simulation by the given number of steps.
567
+ def advance_time aNumSteps = 1
568
+ # schedule wake-up callback from verilog
569
+ time = S_vpi_time.new
570
+ time.integer = aNumSteps
571
+ time.type = VpiSimTime
530
572
 
531
- value = S_vpi_value.new
532
- value.format = VpiSuppressVal
573
+ value = S_vpi_value.new
574
+ value.format = VpiSuppressVal
533
575
 
534
- alarm = S_cb_data.new
535
- alarm.reason = CbAfterDelay
536
- alarm.cb_rtn = Vlog_relay_ruby
537
- alarm.obj = nil
538
- alarm.time = time
539
- alarm.value = value
540
- alarm.index = 0
541
- alarm.user_data = nil
576
+ alarm = S_cb_data.new
577
+ alarm.reason = CbReadWriteSynch
578
+ alarm.cb_rtn = Vlog_relay_ruby
579
+ alarm.obj = nil
580
+ alarm.time = time
581
+ alarm.value = value
582
+ alarm.index = 0
583
+ alarm.user_data = nil
542
584
 
543
- vpi_free_object(vpi_register_cb_old(alarm))
585
+ vpi_free_object(vpi_register_cb_old(alarm))
544
586
 
545
- # relay to verilog
546
- relay_verilog_proxy
547
- end
548
587
 
588
+ # transfer control to verilog
589
+ relay_verilog_proxy
590
+ end
549
591
 
550
- # utility
551
592
 
552
- # Returns the current simulation time as an integer.
553
- def simulation_time
554
- t = S_vpi_time.new :type => VpiSimTime
555
- vpi_get_time nil, t
556
- t.to_i
593
+ ##############################################################################
594
+ # utility
595
+ ##############################################################################
596
+
597
+ # Returns the current simulation time as an integer.
598
+ def simulation_time
599
+ t = S_vpi_time.new :type => VpiSimTime
600
+ vpi_get_time nil, t
601
+ t.to_i
602
+ end
603
+
604
+ class S_vpi_time
605
+ # Returns the high and low portions of
606
+ # this time as a single 64-bit integer.
607
+ def integer
608
+ (self.high << INTEGER_BITS) | self.low
557
609
  end
558
610
 
559
- class S_vpi_time
560
- # Returns the high and low portions of
561
- # this time as a single 64-bit integer.
562
- def integer
563
- (self.high << INTEGER_BITS) | self.low
564
- end
611
+ # Sets the high and low portions of this
612
+ # time from the given 64-bit integer.
613
+ def integer= aValue
614
+ self.low = aValue & INTEGER_MASK
615
+ self.high = (aValue >> INTEGER_BITS) & INTEGER_MASK
616
+ end
565
617
 
566
- # Sets the high and low portions of this
567
- # time from the given 64-bit integer.
568
- def integer= aValue
569
- self.low = aValue & INTEGER_MASK
570
- self.high = (aValue >> INTEGER_BITS) & INTEGER_MASK
571
- end
618
+ alias to_i integer
619
+ alias to_f real
620
+ end
572
621
 
573
- alias to_i integer
574
- alias to_f real
622
+ class S_vpi_value
623
+ def to_i
624
+ value.integer
575
625
  end
576
626
 
577
- class S_vpi_value
578
- def to_i
579
- value.integer
580
- end
581
-
582
- def to_f
583
- value.real
584
- end
627
+ def to_f
628
+ value.real
629
+ end
585
630
 
586
- def to_s
587
- value.str
588
- end
631
+ def to_s
632
+ value.str
589
633
  end
634
+ end
590
635
 
591
- # make VPI structs more accessible by allowing their
592
- # members to be initialized through the constructor
593
- constants.grep(/^S_/).each do |s|
594
- const_get(s).class_eval do
595
- alias old_initialize initialize
636
+ # make VPI structs more accessible by allowing their
637
+ # members to be initialized through the constructor
638
+ constants.grep(/^S_/).each do |s|
639
+ const_get(s).class_eval do
640
+ alias old_initialize initialize
596
641
 
597
- def initialize aMembers = {} #:nodoc:
598
- old_initialize
642
+ def initialize aMembers = {} #:nodoc:
643
+ old_initialize
599
644
 
600
- aMembers.each_pair do |k, v|
601
- __send__ "#{k}=", v
602
- end
645
+ aMembers.each_pair do |k, v|
646
+ __send__ "#{k}=", v
603
647
  end
604
648
  end
605
649
  end
650
+ end
606
651
  end