ruby-vpi 17.0.0 → 18.0.0

Sign up to get free protection for your applications and to get access to all the features.
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