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.
- data/LICENSE +8 -6
- data/Rakefile +4 -4
- data/doc/common.css +6 -9
- data/doc/common.inc +3 -3
- data/doc/common.tpl +14 -6
- data/doc/history.html +152 -44
- data/doc/history.inc +55 -3
- data/doc/history.yaml +62 -2
- data/doc/intro.inc +20 -16
- data/doc/manual.doc +23 -9
- data/doc/manual.html +232 -200
- data/doc/memo.doc +7 -6
- data/doc/memo.html +28 -17
- data/doc/readme.doc +1 -1
- data/doc/readme.html +51 -35
- data/doc/rss.xml +96 -70
- data/ext/Rakefile +24 -11
- data/ext/swig_vpi.h +1 -1
- data/ext/swig_wrap.cin +17 -42
- data/lib/ruby-vpi/pli.tab +1 -0
- data/lib/ruby-vpi/runner.rb +34 -10
- data/lib/ruby-vpi/vpi.rb +483 -438
- data/ref/c/annotated.html +1 -1
- data/ref/c/common_8h.html +1 -1
- data/ref/c/files.html +1 -1
- data/ref/c/functions.html +1 -1
- data/ref/c/functions_vars.html +1 -1
- data/ref/c/globals.html +1 -1
- data/ref/c/globals_0x63.html +1 -1
- data/ref/c/globals_0x65.html +1 -1
- data/ref/c/globals_0x66.html +1 -1
- data/ref/c/globals_0x6d.html +1 -1
- data/ref/c/globals_0x70.html +1 -1
- data/ref/c/globals_0x72.html +1 -1
- data/ref/c/globals_0x73.html +1 -1
- data/ref/c/globals_0x74.html +1 -1
- data/ref/c/globals_0x76.html +1 -1
- data/ref/c/globals_0x78.html +1 -1
- data/ref/c/globals_defs.html +1 -1
- data/ref/c/globals_defs_0x65.html +1 -1
- data/ref/c/globals_defs_0x70.html +1 -1
- data/ref/c/globals_defs_0x76.html +1 -1
- data/ref/c/globals_defs_0x78.html +1 -1
- data/ref/c/globals_enum.html +1 -1
- data/ref/c/globals_eval.html +1 -1
- data/ref/c/globals_func.html +1 -1
- data/ref/c/globals_type.html +1 -1
- data/ref/c/globals_vars.html +1 -1
- data/ref/c/index.html +1 -1
- data/ref/c/main_8c.html +1 -1
- data/ref/c/main_8h.html +1 -1
- data/ref/c/relay_8c.html +1 -1
- data/ref/c/relay_8h.html +1 -1
- data/ref/c/structt__cb__data.html +1 -1
- data/ref/c/structt__vpi__delay.html +1 -1
- data/ref/c/structt__vpi__error__info.html +1 -1
- data/ref/c/structt__vpi__strengthval.html +1 -1
- data/ref/c/structt__vpi__systf__data.html +1 -1
- data/ref/c/structt__vpi__time.html +1 -1
- data/ref/c/structt__vpi__value.html +1 -1
- data/ref/c/structt__vpi__vecval.html +1 -1
- data/ref/c/structt__vpi__vlog__info.html +1 -1
- data/ref/c/verilog_8h.html +1 -1
- data/ref/c/vlog_8c.html +1 -1
- data/ref/c/vlog_8h.html +1 -1
- data/ref/c/vpi__user_8h.html +1 -1
- data/ref/ruby/classes/RDoc.html +5 -5
- data/ref/ruby/classes/RDoc.src/{M000058.html → M000061.html} +0 -0
- data/ref/ruby/classes/String.html +24 -24
- data/ref/ruby/classes/String.src/M000022.html +23 -5
- data/ref/ruby/classes/String.src/M000023.html +28 -5
- data/ref/ruby/classes/String.src/M000024.html +5 -23
- data/ref/ruby/classes/String.src/M000025.html +5 -28
- data/ref/ruby/classes/Vpi/Handle.html +94 -49
- data/ref/ruby/classes/Vpi/Handle.src/M000035.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000036.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000037.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000038.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000039.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000040.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000041.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000042.html +4 -4
- data/ref/ruby/classes/Vpi/Handle.src/M000043.html +7 -7
- data/ref/ruby/classes/Vpi/Handle.src/M000044.html +7 -7
- data/ref/ruby/classes/Vpi/Handle.src/M000045.html +8 -8
- data/ref/ruby/classes/Vpi/Handle.src/M000046.html +36 -30
- data/ref/ruby/classes/Vpi/Handle.src/M000047.html +72 -67
- data/ref/ruby/classes/Vpi/Handle.src/M000048.html +6 -17
- data/ref/ruby/classes/Vpi/Handle.src/M000049.html +19 -0
- data/ref/ruby/classes/Vpi/Handle.src/M000050.html +5 -5
- data/ref/ruby/classes/Vpi/Handle.src/M000051.html +16 -10
- data/ref/ruby/classes/Vpi/Handle.src/M000053.html +5 -18
- data/ref/ruby/classes/Vpi/Handle.src/M000054.html +11 -76
- data/ref/ruby/classes/Vpi/Handle.src/M000056.html +31 -0
- data/ref/ruby/classes/Vpi/Handle.src/M000057.html +40 -0
- data/ref/ruby/classes/Vpi/S_vpi_time.html +16 -16
- data/ref/ruby/classes/Vpi/S_vpi_time.src/{M000055.html → M000058.html} +4 -4
- data/ref/ruby/classes/Vpi/S_vpi_time.src/M000059.html +19 -0
- data/ref/ruby/classes/Vpi/S_vpi_value.src/M000032.html +4 -4
- data/ref/ruby/classes/Vpi/S_vpi_value.src/M000033.html +4 -4
- data/ref/ruby/classes/Vpi/S_vpi_value.src/M000034.html +4 -4
- data/ref/ruby/classes/Vpi.html +0 -7
- data/ref/ruby/classes/Vpi.src/M000029.html +14 -14
- data/ref/ruby/classes/Vpi.src/M000030.html +25 -24
- data/ref/ruby/classes/Vpi.src/M000031.html +6 -6
- data/ref/ruby/created.rid +1 -1
- data/ref/ruby/files/bin/convert_rb.html +1 -1
- data/ref/ruby/files/bin/generate_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/erb_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/float_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/integer_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/rake_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/rcov_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/rdoc_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/runner_proxy_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/runner_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/util_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/verilog_parser_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/vpi_rb.html +8 -1
- data/ref/ruby/files/lib/ruby-vpi_rb.html +1 -1
- data/ref/ruby/fr_method_index.html +19 -16
- data/samp/register_file/register_file.v +1 -1
- data/samp/register_file/register_file_spec.rb +9 -5
- metadata +42 -38
- 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
|
-
|
|
53
|
+
# Sets the logic value of this handle to unknown (x).
|
|
54
|
+
def x!
|
|
55
|
+
self.hexStrVal = 'x'
|
|
56
|
+
end
|
|
20
57
|
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
63
|
+
# Sets the logic value of this handle to high impedance (z).
|
|
64
|
+
def z!
|
|
65
|
+
self.hexStrVal = 'z'
|
|
66
|
+
end
|
|
46
67
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
73
|
+
# Sets the logic value of this handle to "logic high" level.
|
|
74
|
+
def high!
|
|
75
|
+
self.intVal = 1
|
|
76
|
+
end
|
|
56
77
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
83
|
+
# Sets the logic value of this handle to "logic low" level.
|
|
84
|
+
def low!
|
|
85
|
+
self.intVal = 0
|
|
86
|
+
end
|
|
66
87
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
self.hexStrVal =~ /^0+$/
|
|
75
|
-
end
|
|
93
|
+
old == 0 && new == 1
|
|
94
|
+
end
|
|
76
95
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
old = @lastVal
|
|
85
|
-
new = @lastVal = self.intVal
|
|
101
|
+
old == 1 && new == 0
|
|
102
|
+
end
|
|
86
103
|
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
new = @lastVal = self.intVal
|
|
111
|
+
vpi_get_value self, val
|
|
112
|
+
val
|
|
113
|
+
end
|
|
94
114
|
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
106
|
-
val
|
|
107
|
-
end
|
|
125
|
+
when VpiScalarVal
|
|
126
|
+
val.value.scalar.to_i
|
|
108
127
|
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
121
|
-
|
|
137
|
+
when VpiRealVal
|
|
138
|
+
val.value.real.to_f
|
|
122
139
|
|
|
123
|
-
|
|
124
|
-
|
|
140
|
+
when VpiTimeVal
|
|
141
|
+
val.value.time
|
|
125
142
|
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
when VpiVectorVal
|
|
144
|
+
val.value.vector
|
|
128
145
|
|
|
129
|
-
|
|
130
|
-
|
|
146
|
+
when VpiStrengthVal
|
|
147
|
+
val.value.strength
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
|
|
149
|
+
else
|
|
150
|
+
raise "unknown S_vpi_value.format: #{val.format.inspect}"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
134
153
|
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
139
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
173
|
+
elsif aValue.respond_to? :to_int
|
|
174
|
+
VpiIntVal
|
|
156
175
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
newVal.value.str = aValue.to_s
|
|
176
|
+
elsif aValue.respond_to? :to_float
|
|
177
|
+
VpiRealVal
|
|
160
178
|
|
|
161
|
-
|
|
162
|
-
|
|
179
|
+
elsif aValue.respond_to? :to_str
|
|
180
|
+
VpiStringVal
|
|
163
181
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
newVal.value.str = aValue.to_i.to_s(16)
|
|
182
|
+
elsif aValue.is_a? S_vpi_time
|
|
183
|
+
VpiTimeVal
|
|
167
184
|
|
|
168
|
-
|
|
169
|
-
|
|
185
|
+
elsif aValue.is_a? S_vpi_vecval
|
|
186
|
+
VpiVectorVal
|
|
170
187
|
|
|
171
|
-
|
|
172
|
-
|
|
188
|
+
elsif aValue.is_a? S_vpi_strengthval
|
|
189
|
+
VpiStrengthVal
|
|
173
190
|
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
178
|
-
|
|
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
|
-
|
|
182
|
-
|
|
212
|
+
newVal.format = VpiHexStrVal
|
|
213
|
+
newVal.value.str = aValue.to_i.to_s(16)
|
|
214
|
+
end
|
|
183
215
|
|
|
184
|
-
|
|
216
|
+
when VpiRealVal
|
|
217
|
+
newVal.value.real = aValue.to_f
|
|
185
218
|
|
|
186
|
-
|
|
187
|
-
|
|
219
|
+
when VpiTimeVal
|
|
220
|
+
newVal.value.time = aValue
|
|
188
221
|
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
199
|
-
|
|
225
|
+
when VpiStrengthVal
|
|
226
|
+
newVal.value.strength = aValue
|
|
200
227
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
228
|
+
else
|
|
229
|
+
raise "unknown S_vpi_value.format: #{newVal.format.inspect}"
|
|
230
|
+
end
|
|
204
231
|
|
|
205
|
-
|
|
206
|
-
readenVal == aValue.to_f
|
|
232
|
+
vpi_put_value(self, newVal, aTime, aDelay)
|
|
207
233
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
end
|
|
234
|
+
writtenVal
|
|
235
|
+
end
|
|
211
236
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
217
|
-
|
|
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
|
-
|
|
225
|
-
|
|
255
|
+
# Returns an array of child handles of the
|
|
256
|
+
# given types (name or integer constant).
|
|
257
|
+
def [] *aTypes
|
|
258
|
+
handles = []
|
|
226
259
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
252
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
|
|
300
|
+
aPropNames.map! do |name|
|
|
301
|
+
"#{name}=#{self.send(name.to_sym).inspect}"
|
|
270
302
|
end
|
|
271
303
|
|
|
272
|
-
|
|
304
|
+
"#<Vpi::Handle #{vpiType_s} #{aPropNames.join(', ')}>"
|
|
305
|
+
end
|
|
273
306
|
|
|
274
|
-
|
|
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
|
-
|
|
280
|
-
|
|
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
|
-
|
|
283
|
-
|
|
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
|
-
|
|
291
|
-
|
|
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
|
-
|
|
329
|
+
@@propCache = Hash.new {|h, k| h[k] = Property.new(k)}
|
|
313
330
|
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
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
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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
|
-
|
|
365
|
+
class Property # :nodoc:
|
|
366
|
+
def initialize aMethName
|
|
367
|
+
@methName = aMethName.to_s
|
|
389
368
|
|
|
390
|
-
|
|
391
|
-
|
|
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
|
-
|
|
402
|
-
|
|
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
|
|
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
|
-
|
|
417
|
-
|
|
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
|
-
|
|
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
|
-
|
|
425
|
-
|
|
426
|
-
:d
|
|
441
|
+
aHandle.get_value(@type)
|
|
442
|
+
end
|
|
427
443
|
|
|
428
|
-
|
|
429
|
-
|
|
444
|
+
when :i # integer values
|
|
445
|
+
if @isAssign
|
|
446
|
+
raise NotImplementedError
|
|
447
|
+
else
|
|
448
|
+
vpi_get(@type, aHandle)
|
|
449
|
+
end
|
|
430
450
|
|
|
431
|
-
|
|
432
|
-
|
|
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
|
-
|
|
435
|
-
|
|
459
|
+
when :s # string values
|
|
460
|
+
if @isAssign
|
|
461
|
+
raise NotImplementedError
|
|
462
|
+
else
|
|
463
|
+
vpi_get_str(@type, aHandle)
|
|
464
|
+
end
|
|
436
465
|
|
|
437
|
-
|
|
438
|
-
|
|
466
|
+
when :h # handle values
|
|
467
|
+
if @isAssign
|
|
468
|
+
raise NotImplementedError
|
|
469
|
+
else
|
|
470
|
+
vpi_handle(@type, aHandle)
|
|
471
|
+
end
|
|
439
472
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
-
|
|
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
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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
|
-
|
|
463
|
-
|
|
502
|
+
Callback = Struct.new :handler, :token #:nodoc:
|
|
503
|
+
@@callbacks = {}
|
|
464
504
|
|
|
465
|
-
|
|
505
|
+
alias vpi_register_cb_old vpi_register_cb
|
|
466
506
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
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
|
-
|
|
519
|
+
key = aHandler.object_id.to_s
|
|
480
520
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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
|
-
|
|
487
|
-
|
|
488
|
-
|
|
526
|
+
@@callbacks[key] = Callback.new(aHandler, token)
|
|
527
|
+
token
|
|
528
|
+
end
|
|
489
529
|
|
|
490
|
-
|
|
530
|
+
alias vpi_remove_cb_old vpi_remove_cb
|
|
491
531
|
|
|
492
|
-
|
|
493
|
-
|
|
532
|
+
def vpi_remove_cb aData # :nodoc:
|
|
533
|
+
key = aData.user_data
|
|
494
534
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
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
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
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
|
-
|
|
510
|
-
|
|
549
|
+
if reason = relay_ruby_reason # might be nil
|
|
550
|
+
dst = reason.user_data
|
|
511
551
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
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
|
-
|
|
532
|
-
|
|
573
|
+
value = S_vpi_value.new
|
|
574
|
+
value.format = VpiSuppressVal
|
|
533
575
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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
|
-
|
|
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
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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
|
-
|
|
574
|
-
|
|
622
|
+
class S_vpi_value
|
|
623
|
+
def to_i
|
|
624
|
+
value.integer
|
|
575
625
|
end
|
|
576
626
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
end
|
|
581
|
-
|
|
582
|
-
def to_f
|
|
583
|
-
value.real
|
|
584
|
-
end
|
|
627
|
+
def to_f
|
|
628
|
+
value.real
|
|
629
|
+
end
|
|
585
630
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
end
|
|
631
|
+
def to_s
|
|
632
|
+
value.str
|
|
589
633
|
end
|
|
634
|
+
end
|
|
590
635
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
-
|
|
598
|
-
|
|
642
|
+
def initialize aMembers = {} #:nodoc:
|
|
643
|
+
old_initialize
|
|
599
644
|
|
|
600
|
-
|
|
601
|
-
|
|
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
|