ruby-vpi 18.0.2 → 19.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +15 -19
- data/bin/generate/proto.rb +15 -10
- data/bin/ruby-vpi +2 -0
- data/doc/README +3 -5
- data/doc/Rakefile +3 -3
- data/doc/common.css +24 -136
- data/doc/common.tpl +48 -37
- data/doc/figures/figures.dia +19 -19
- data/doc/figures/ruby_relay.png +0 -0
- data/doc/history.html +252 -67
- data/doc/history.inc +98 -1
- data/doc/history.yaml +105 -0
- data/doc/intro.inc +43 -32
- data/doc/lib/doc_format.rb +19 -13
- data/doc/lib/doc_proxy.rb +7 -7
- data/doc/manual.doc +156 -117
- data/doc/manual.html +601 -560
- data/doc/memo.html +29 -25
- data/doc/print.css +63 -4
- data/doc/readme.doc +4 -6
- data/doc/readme.html +129 -111
- data/doc/rss.xml +168 -7
- data/doc/screen.css +146 -0
- data/doc/spacing.css +57 -0
- data/{samp → examples}/counter/RSpec/Rakefile +0 -0
- data/{samp → examples}/counter/RSpec/counter_design.rb +0 -0
- data/examples/counter/RSpec/counter_proto.rb +9 -0
- data/{samp → examples}/counter/RSpec/counter_runner.rake +0 -0
- data/{samp → examples}/counter/RSpec/counter_spec.rb +0 -0
- data/{samp → examples}/counter/Rakefile +0 -0
- data/{samp → examples}/counter/counter.v +0 -0
- data/{samp → examples}/counter/xUnit/Rakefile +0 -0
- data/{samp → examples}/counter/xUnit/counter_bench.rb +0 -0
- data/{samp → examples}/counter/xUnit/counter_bench.v +0 -0
- data/{samp → examples}/counter/xUnit/counter_design.rb +0 -0
- data/examples/counter/xUnit/counter_proto.rb +9 -0
- data/{samp → examples}/counter/xUnit/counter_runner.rake +0 -0
- data/{samp → examples}/counter/xUnit/counter_spec.rb +0 -0
- data/{samp → examples}/pipelined_alu/Hw5UnitModel.rb +0 -0
- data/{samp → examples}/pipelined_alu/README +0 -0
- data/{samp → examples}/pipelined_alu/Rakefile +0 -0
- data/{samp → examples}/pipelined_alu/TestHw5UnitModel.rb +0 -0
- data/{samp → examples}/pipelined_alu/hw5_unit.v +0 -0
- data/{samp → examples}/pipelined_alu/hw5_unit_design.rb +0 -7
- data/examples/pipelined_alu/hw5_unit_proto.rb +2 -0
- data/{samp → examples}/pipelined_alu/hw5_unit_runner.rake +0 -0
- data/{samp → examples}/pipelined_alu/hw5_unit_spec.rb +0 -0
- data/{samp → examples}/pipelined_alu/int_gen.rb +0 -0
- data/{samp → examples}/register_file/LICENSE +0 -0
- data/{samp → examples}/register_file/README +0 -0
- data/{samp → examples}/register_file/Rakefile +0 -0
- data/{samp → examples}/register_file/register_file.v +0 -0
- data/{samp → examples}/register_file/register_file_design.rb +0 -0
- data/examples/register_file/register_file_proto.rb +11 -0
- data/{samp → examples}/register_file/register_file_runner.rake +0 -0
- data/{samp → examples}/register_file/register_file_spec.rb +0 -0
- data/ext/main.c +5 -5
- data/ext/swig_vpi.i +6 -2
- data/lib/ruby-vpi/core/callback.rb +142 -0
- data/lib/ruby-vpi/core/edge.rb +128 -0
- data/lib/ruby-vpi/core/handle.rb +421 -0
- data/lib/ruby-vpi/core/scheduler.rb +244 -0
- data/lib/ruby-vpi/core/struct.rb +123 -0
- data/lib/ruby-vpi/core.rb +41 -0
- data/lib/ruby-vpi/rcov.rb +25 -12
- data/lib/ruby-vpi/runner.rb +30 -26
- data/lib/ruby-vpi/runner_boot_loader.rb +67 -37
- data/lib/ruby-vpi.rb +2 -2
- 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/ERB.html +7 -5
- data/ref/ruby/classes/ERB.src/{M000026.html → M000024.html} +0 -0
- data/ref/ruby/classes/FileUtils.html +11 -11
- data/ref/ruby/classes/FileUtils.src/{M000027.html → M000025.html} +0 -0
- data/ref/ruby/classes/FileUtils.src/{M000028.html → M000026.html} +0 -0
- data/ref/ruby/classes/Float.html +8 -6
- data/ref/ruby/classes/Float.src/{M000021.html → M000019.html} +0 -0
- data/ref/ruby/classes/Integer.html +67 -65
- data/ref/ruby/classes/Integer.src/M000007.html +25 -0
- data/ref/ruby/classes/Integer.src/{M000014.html → M000008.html} +5 -5
- data/ref/ruby/classes/Integer.src/M000009.html +5 -12
- data/ref/ruby/classes/Integer.src/M000010.html +5 -5
- data/ref/ruby/classes/Integer.src/M000011.html +5 -5
- data/ref/ruby/classes/Integer.src/M000012.html +5 -5
- data/ref/ruby/classes/Integer.src/M000015.html +25 -0
- data/ref/ruby/classes/Integer.src/M000016.html +31 -0
- data/ref/ruby/classes/Integer.src/M000017.html +12 -12
- data/ref/ruby/classes/Integer.src/M000018.html +17 -18
- data/ref/ruby/classes/Object.html +126 -0
- data/ref/ruby/classes/RDoc.html +5 -5
- data/ref/ruby/classes/RDoc.src/{M000061.html → M000081.html} +0 -0
- data/ref/ruby/classes/RubyVPI.html +50 -9
- data/ref/ruby/classes/String.html +22 -20
- data/ref/ruby/classes/String.src/M000020.html +36 -0
- data/ref/ruby/classes/String.src/M000021.html +41 -0
- data/ref/ruby/classes/String.src/M000022.html +5 -23
- data/ref/ruby/classes/String.src/M000023.html +5 -28
- data/ref/ruby/classes/{Vpi → VPI}/Handle.html +442 -140
- data/ref/ruby/classes/{Vpi/Handle.src/M000042.html → VPI/Handle.src/M000037.html} +4 -4
- data/ref/ruby/classes/VPI/Handle.src/M000038.html +21 -0
- data/ref/ruby/classes/VPI/Handle.src/M000039.html +18 -0
- data/ref/ruby/classes/{Vpi/Handle.src/M000036.html → VPI/Handle.src/M000040.html} +5 -5
- data/ref/ruby/classes/VPI/Handle.src/M000045.html +18 -0
- data/ref/ruby/classes/{Vpi/Handle.src/M000038.html → VPI/Handle.src/M000046.html} +5 -5
- data/ref/ruby/classes/VPI/Handle.src/M000057.html +18 -0
- data/ref/ruby/classes/{Vpi/Handle.src/M000040.html → VPI/Handle.src/M000058.html} +5 -5
- data/ref/ruby/classes/VPI/Handle.src/M000061.html +18 -0
- data/ref/ruby/classes/VPI/Handle.src/M000062.html +18 -0
- data/ref/ruby/classes/{Vpi/Handle.src/M000054.html → VPI/Handle.src/M000065.html} +11 -11
- data/ref/ruby/classes/VPI/Handle.src/M000067.html +21 -0
- data/ref/ruby/classes/VPI/Handle.src/M000068.html +28 -0
- data/ref/ruby/classes/VPI/Handle.src/M000069.html +50 -0
- data/ref/ruby/classes/{Vpi/Handle.src/M000048.html → VPI/Handle.src/M000070.html} +6 -6
- data/ref/ruby/classes/{Vpi/Handle.src/M000049.html → VPI/Handle.src/M000071.html} +6 -6
- data/ref/ruby/classes/{Vpi/Handle.src/M000050.html → VPI/Handle.src/M000072.html} +5 -5
- data/ref/ruby/classes/{Vpi/Handle.src/M000051.html → VPI/Handle.src/M000073.html} +17 -17
- data/ref/ruby/classes/VPI/Handle.src/M000075.html +18 -0
- data/ref/ruby/classes/VPI/Handle.src/M000076.html +40 -0
- data/ref/ruby/classes/{Vpi/Handle.src/M000056.html → VPI/Handle.src/M000077.html} +18 -18
- data/ref/ruby/classes/{Vpi → VPI}/S_vpi_time.html +22 -20
- data/ref/ruby/classes/VPI/S_vpi_time.src/M000078.html +18 -0
- data/ref/ruby/classes/VPI/S_vpi_time.src/M000079.html +19 -0
- data/ref/ruby/classes/{Vpi → VPI}/S_vpi_value.html +37 -23
- data/ref/ruby/classes/VPI/S_vpi_value.src/M000034.html +35 -0
- data/ref/ruby/classes/VPI/S_vpi_value.src/M000035.html +42 -0
- data/ref/ruby/classes/VPI/S_vpi_value.src/M000036.html +42 -0
- data/ref/ruby/classes/{Vpi.html → VPI.html} +129 -34
- data/ref/ruby/classes/VPI.src/M000027.html +19 -0
- data/ref/ruby/classes/VPI.src/M000028.html +18 -0
- data/ref/ruby/classes/VPI.src/M000029.html +19 -0
- data/ref/ruby/classes/VPI.src/M000031.html +25 -0
- data/ref/ruby/classes/VPI.src/M000032.html +26 -0
- data/ref/ruby/classes/VerilogParser/Module/Port.html +17 -15
- data/ref/ruby/classes/VerilogParser/Module/Port.src/M000004.html +23 -0
- data/ref/ruby/classes/VerilogParser/Module/Port.src/{M000007.html → M000005.html} +0 -0
- data/ref/ruby/classes/VerilogParser/Module/Port.src/M000006.html +5 -10
- data/ref/ruby/classes/VerilogParser/Module.html +7 -5
- data/ref/ruby/classes/VerilogParser/Module.src/{M000005.html → M000003.html} +0 -0
- data/ref/ruby/classes/VerilogParser.html +7 -5
- data/ref/ruby/classes/VerilogParser.src/{M000004.html → M000002.html} +0 -0
- data/ref/ruby/created.rid +1 -1
- data/ref/ruby/files/bin/generate_rb.html +2 -2
- data/ref/ruby/files/lib/ruby-vpi/{vpi_rb.html → core/callback_rb.html} +7 -8
- data/ref/ruby/files/lib/ruby-vpi/core/edge_rb.html +114 -0
- data/ref/ruby/files/lib/ruby-vpi/core/handle_rb.html +107 -0
- data/ref/ruby/files/lib/ruby-vpi/core/scheduler_rb.html +114 -0
- data/ref/ruby/files/lib/ruby-vpi/core/struct_rb.html +108 -0
- data/ref/ruby/files/lib/ruby-vpi/core_rb.html +121 -0
- data/ref/ruby/files/lib/ruby-vpi/rcov_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.html +5 -41
- data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.src/M000001.html +3 -3
- data/ref/ruby/files/lib/ruby-vpi/runner_rb.html +1 -1
- data/ref/ruby/files/lib/ruby-vpi_rb.html +1 -1
- data/ref/ruby/fr_class_index.html +5 -4
- data/ref/ruby/fr_file_index.html +6 -1
- data/ref/ruby/fr_method_index.html +80 -60
- metadata +126 -103
- data/ext/swig_vpi.h +0 -924
- data/ext/swig_wrap.cin +0 -7083
- data/lib/ruby-vpi/vpi.rb +0 -651
- data/ref/ruby/classes/Integer.src/M000013.html +0 -18
- data/ref/ruby/classes/Integer.src/M000019.html +0 -25
- data/ref/ruby/classes/Integer.src/M000020.html +0 -30
- data/ref/ruby/classes/String.src/M000024.html +0 -18
- data/ref/ruby/classes/String.src/M000025.html +0 -18
- data/ref/ruby/classes/VerilogParser/Module/Port.src/M000008.html +0 -18
- data/ref/ruby/classes/Vpi/Handle.src/M000035.html +0 -18
- data/ref/ruby/classes/Vpi/Handle.src/M000037.html +0 -18
- data/ref/ruby/classes/Vpi/Handle.src/M000039.html +0 -18
- data/ref/ruby/classes/Vpi/Handle.src/M000041.html +0 -18
- data/ref/ruby/classes/Vpi/Handle.src/M000043.html +0 -21
- data/ref/ruby/classes/Vpi/Handle.src/M000044.html +0 -21
- data/ref/ruby/classes/Vpi/Handle.src/M000045.html +0 -22
- data/ref/ruby/classes/Vpi/Handle.src/M000046.html +0 -50
- data/ref/ruby/classes/Vpi/Handle.src/M000047.html +0 -91
- data/ref/ruby/classes/Vpi/Handle.src/M000053.html +0 -18
- data/ref/ruby/classes/Vpi/Handle.src/M000057.html +0 -40
- data/ref/ruby/classes/Vpi/S_vpi_time.src/M000058.html +0 -18
- data/ref/ruby/classes/Vpi/S_vpi_time.src/M000059.html +0 -19
- data/ref/ruby/classes/Vpi/S_vpi_value.src/M000032.html +0 -18
- data/ref/ruby/classes/Vpi/S_vpi_value.src/M000033.html +0 -18
- data/ref/ruby/classes/Vpi/S_vpi_value.src/M000034.html +0 -18
- data/ref/ruby/classes/Vpi.src/M000029.html +0 -28
- data/ref/ruby/classes/Vpi.src/M000030.html +0 -39
- data/ref/ruby/classes/Vpi.src/M000031.html +0 -20
- data/ref/ruby/files/lib/ruby-vpi/runner_boot_loader_rb.src/M000002.html +0 -18
- data/samp/counter/RSpec/counter_proto.rb +0 -10
- data/samp/counter/xUnit/counter_proto.rb +0 -10
- data/samp/pipelined_alu/hw5_unit_proto.rb +0 -4
- data/samp/register_file/register_file_proto.rb +0 -11
@@ -0,0 +1,244 @@
|
|
1
|
+
# Concurrent processes.
|
2
|
+
#--
|
3
|
+
# Copyright 2007 Suraj N. Kurapati
|
4
|
+
# See the file named LICENSE for details.
|
5
|
+
|
6
|
+
Thread.abort_on_exception = true
|
7
|
+
|
8
|
+
require 'singleton'
|
9
|
+
|
10
|
+
module RubyVPI
|
11
|
+
class SchedulerClass #:nodoc:
|
12
|
+
include Singleton
|
13
|
+
|
14
|
+
|
15
|
+
Task = Struct.new(:thread, :state)
|
16
|
+
|
17
|
+
class Task #:nodoc:
|
18
|
+
def run
|
19
|
+
self.state = :run
|
20
|
+
self.thread.wakeup
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop
|
24
|
+
self.state = :wait
|
25
|
+
Thread.stop
|
26
|
+
end
|
27
|
+
|
28
|
+
def stop?
|
29
|
+
self.thread.stop? and self.state == :wait
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@thread2task = { Thread.main => Task.new(Thread.main, :run) }
|
36
|
+
@thread2task_sw = @thread2task.dup # software threads
|
37
|
+
@thread2task_hw = {} # hardware threads (Ruby prototype of DUT)
|
38
|
+
@thread2task_lock = Mutex.new
|
39
|
+
|
40
|
+
|
41
|
+
# base case: hardware runs first before any software does at startup
|
42
|
+
@time = 0
|
43
|
+
|
44
|
+
unless RubyVPI::USE_PROTOTYPE
|
45
|
+
Callback.relay_verilog(VPI::CbReadOnlySynch, 0)
|
46
|
+
end
|
47
|
+
|
48
|
+
@scheduler = Thread.new do
|
49
|
+
# pause because boot loader is not fully init yet
|
50
|
+
Thread.stop
|
51
|
+
|
52
|
+
loop do
|
53
|
+
# run software in current time step
|
54
|
+
run_tasks @thread2task_sw, true
|
55
|
+
Edge.refresh_cache
|
56
|
+
|
57
|
+
# go to time slot where writing is permitted before flushing writes
|
58
|
+
unless RubyVPI::USE_PROTOTYPE
|
59
|
+
Callback.relay_verilog(VPI::CbAfterDelay, 1)
|
60
|
+
end
|
61
|
+
|
62
|
+
flush_writes
|
63
|
+
|
64
|
+
# run hardware in next time step
|
65
|
+
@time += 1
|
66
|
+
|
67
|
+
if RubyVPI::USE_PROTOTYPE
|
68
|
+
run_tasks @thread2task_hw, false
|
69
|
+
flush_writes
|
70
|
+
else
|
71
|
+
Callback.relay_verilog(VPI::CbReadOnlySynch, 0)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
@handle2write = Hash.new {|h,k| h[k] = []}
|
78
|
+
@handle2write_lock = Mutex.new
|
79
|
+
end
|
80
|
+
|
81
|
+
def current_time
|
82
|
+
@time
|
83
|
+
end
|
84
|
+
|
85
|
+
def start
|
86
|
+
@scheduler.wakeup
|
87
|
+
end
|
88
|
+
|
89
|
+
# Registers the calling thread with the scheduler.
|
90
|
+
def attach
|
91
|
+
key = Thread.current
|
92
|
+
|
93
|
+
hash =
|
94
|
+
if caller.grep(/_proto\.rb/).empty?
|
95
|
+
@thread2task_sw
|
96
|
+
else
|
97
|
+
@thread2task_hw
|
98
|
+
end
|
99
|
+
|
100
|
+
@thread2task_lock.synchronize do
|
101
|
+
task = Task.new(key, :run)
|
102
|
+
hash[key] = task
|
103
|
+
@thread2task[key] = task
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Unregisters the calling thread from the scheduler.
|
108
|
+
def detach
|
109
|
+
key = Thread.current
|
110
|
+
|
111
|
+
@thread2task_lock.synchronize do
|
112
|
+
@thread2task.delete key
|
113
|
+
@thread2task_hw.delete key
|
114
|
+
@thread2task_sw.delete key
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Waits for the scheduler to arrive in the next time step.
|
119
|
+
def await
|
120
|
+
key = Thread.current
|
121
|
+
|
122
|
+
task = @thread2task_lock.synchronize do
|
123
|
+
@thread2task[key]
|
124
|
+
end
|
125
|
+
|
126
|
+
task.stop
|
127
|
+
end
|
128
|
+
|
129
|
+
def ensure_caller_is_registered
|
130
|
+
unless @thread2task_lock.synchronize {@thread2task.key? Thread.current}
|
131
|
+
raise SecurityError, 'This method may only be invoked from within a process (see the VPI::process() method).'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
Write = Struct.new :thread, :trace, :args
|
136
|
+
|
137
|
+
# Captures the given write operation so it
|
138
|
+
# can be flushed later, at the correct time.
|
139
|
+
def capture_write aHandle, *aArgs
|
140
|
+
@handle2write_lock.synchronize do
|
141
|
+
@handle2write[aHandle] << Write.new(Thread.current, caller, aArgs)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
# Flushes all captured writes.
|
148
|
+
def flush_writes
|
149
|
+
@handle2write_lock.synchronize do
|
150
|
+
@handle2write.each_pair do |handle, writes|
|
151
|
+
if writes.map {|w| w.thread}.uniq.length > 1
|
152
|
+
culprits = writes.map {|w| "\n\n#{w.thread}" << w.trace.map {|x| "\n\t#{x}"}.join}.join
|
153
|
+
STDERR.puts "Race condition detected at time step #{current_time}: the logic value of handle #{handle} is being modified by more than one concurrent process: #{culprits}"
|
154
|
+
exit 1
|
155
|
+
end
|
156
|
+
|
157
|
+
writes.each do |w|
|
158
|
+
VPI::__scheduler__vpi_put_value(handle, *w.args)
|
159
|
+
end
|
160
|
+
|
161
|
+
writes.clear
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def run_tasks aHash, aExitWhenEmpty
|
167
|
+
@thread2task_lock.synchronize do
|
168
|
+
tasks = aHash.values
|
169
|
+
tasks.each {|t| t.run}
|
170
|
+
|
171
|
+
if aExitWhenEmpty and tasks.empty?
|
172
|
+
Thread.exit
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
loop do
|
177
|
+
ready = @thread2task_lock.synchronize do
|
178
|
+
aHash.values.all? {|t| t.stop?}
|
179
|
+
end
|
180
|
+
|
181
|
+
if ready
|
182
|
+
break
|
183
|
+
else
|
184
|
+
Thread.pass
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
Scheduler = SchedulerClass.instance
|
191
|
+
end
|
192
|
+
|
193
|
+
module VPI
|
194
|
+
alias_method :__scheduler__vpi_put_value, :vpi_put_value
|
195
|
+
module_function :__scheduler__vpi_put_value
|
196
|
+
|
197
|
+
def vpi_put_value *args #:nodoc:
|
198
|
+
RubyVPI::Scheduler.capture_write(*args)
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
# Returns the current simulation time.
|
203
|
+
def current_time
|
204
|
+
RubyVPI::Scheduler.current_time
|
205
|
+
end
|
206
|
+
|
207
|
+
# Wait until the simulation advances by the given number of time steps.
|
208
|
+
def advance_time aNumTimeSteps = 1
|
209
|
+
RubyVPI::Scheduler.ensure_caller_is_registered
|
210
|
+
aNumTimeSteps.times { RubyVPI::Scheduler.await }
|
211
|
+
end
|
212
|
+
|
213
|
+
alias wait advance_time
|
214
|
+
|
215
|
+
|
216
|
+
# Creates a new concurrent process, which will execute the
|
217
|
+
# given block with the given arguments, and returns it.
|
218
|
+
def process *aBlockArgs
|
219
|
+
RubyVPI::Scheduler.ensure_caller_is_registered
|
220
|
+
raise ArgumentError, "block must be given" unless block_given?
|
221
|
+
|
222
|
+
Thread.new do
|
223
|
+
RubyVPI::Scheduler.attach
|
224
|
+
yield(*aBlockArgs)
|
225
|
+
RubyVPI::Scheduler.detach
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Wraps the given block inside an infinite loop and executes it
|
230
|
+
# inside a new concurrent process (see the VPI::process method).
|
231
|
+
def always *aBlockArgs, &aBlock
|
232
|
+
process do
|
233
|
+
loop do
|
234
|
+
startTime = VPI.current_time
|
235
|
+
aBlock.call(*aBlockArgs)
|
236
|
+
finishTime = VPI.current_time
|
237
|
+
|
238
|
+
VPI.advance_time unless finishTime > startTime
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
alias forever always
|
244
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# VPI structures (S_vpi_* and S_cb_*) stuff
|
2
|
+
#--
|
3
|
+
# Copyright 2006 Suraj N. Kurapati
|
4
|
+
# See the file named LICENSE for details.
|
5
|
+
|
6
|
+
module VPI
|
7
|
+
class S_vpi_time
|
8
|
+
# Returns the high and low portions of
|
9
|
+
# this time as a single 64-bit integer.
|
10
|
+
def integer
|
11
|
+
(self.high << INTEGER_BITS) | self.low
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sets the high and low portions of this
|
15
|
+
# time from the given 64-bit integer.
|
16
|
+
def integer= aValue
|
17
|
+
self.low = aValue & INTEGER_MASK
|
18
|
+
self.high = (aValue >> INTEGER_BITS) & INTEGER_MASK
|
19
|
+
end
|
20
|
+
|
21
|
+
alias to_i integer
|
22
|
+
alias to_f real
|
23
|
+
end
|
24
|
+
|
25
|
+
class S_vpi_value
|
26
|
+
# Attempts to detect the format of the given value.
|
27
|
+
# Returns +nil+ if detection is not possible.
|
28
|
+
def S_vpi_value.detect_format aValue
|
29
|
+
if aValue.respond_to? :to_int
|
30
|
+
VpiIntVal
|
31
|
+
|
32
|
+
elsif aValue.respond_to? :to_float
|
33
|
+
VpiRealVal
|
34
|
+
|
35
|
+
elsif aValue.respond_to? :to_str
|
36
|
+
VpiStringVal
|
37
|
+
|
38
|
+
elsif aValue.is_a? S_vpi_time
|
39
|
+
VpiTimeVal
|
40
|
+
|
41
|
+
elsif aValue.is_a? S_vpi_vecval
|
42
|
+
VpiVectorVal
|
43
|
+
|
44
|
+
elsif aValue.is_a? S_vpi_strengthval
|
45
|
+
VpiStrengthVal
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Writes the given value, which has the given format.
|
50
|
+
def write aValue, aFormat
|
51
|
+
case aFormat
|
52
|
+
when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
|
53
|
+
value.str = aValue.to_s
|
54
|
+
|
55
|
+
when VpiScalarVal
|
56
|
+
value.scalar = aValue.to_i
|
57
|
+
|
58
|
+
when VpiIntVal
|
59
|
+
value.integer = aValue.to_i
|
60
|
+
|
61
|
+
when VpiRealVal
|
62
|
+
value.real = aValue.to_f
|
63
|
+
|
64
|
+
when VpiTimeVal
|
65
|
+
value.time = aValue
|
66
|
+
|
67
|
+
when VpiVectorVal
|
68
|
+
value.vector = aValue
|
69
|
+
|
70
|
+
when VpiStrengthVal
|
71
|
+
value.strength = aValue
|
72
|
+
|
73
|
+
else
|
74
|
+
raise "unknown format: #{aFormat.inspect}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the value in the given format.
|
79
|
+
def read aFormat = self.format
|
80
|
+
case aFormat
|
81
|
+
when VpiBinStrVal, VpiOctStrVal, VpiDecStrVal, VpiHexStrVal, VpiStringVal
|
82
|
+
value.str.to_s
|
83
|
+
|
84
|
+
when VpiScalarVal
|
85
|
+
value.scalar.to_i
|
86
|
+
|
87
|
+
when VpiIntVal
|
88
|
+
value.integer.to_i
|
89
|
+
|
90
|
+
when VpiRealVal
|
91
|
+
value.real.to_f
|
92
|
+
|
93
|
+
when VpiTimeVal
|
94
|
+
value.time
|
95
|
+
|
96
|
+
when VpiVectorVal
|
97
|
+
value.vector
|
98
|
+
|
99
|
+
when VpiStrengthVal
|
100
|
+
value.strength
|
101
|
+
|
102
|
+
else
|
103
|
+
raise "unknown format: #{aFormat.inspect}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# make VPI structs more accessible by allowing their
|
109
|
+
# members to be initialized through the constructor
|
110
|
+
constants.grep(/^S_/).each do |s|
|
111
|
+
const_get(s).class_eval do
|
112
|
+
alias __struct__initialize initialize
|
113
|
+
|
114
|
+
def initialize aMembers = {} #:nodoc:
|
115
|
+
__struct__initialize
|
116
|
+
|
117
|
+
aMembers.each_pair do |k, v|
|
118
|
+
__send__("#{k}=", v)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# A utility layer which transforms the VPI interface
|
2
|
+
# into one that is more suitable for Ruby.
|
3
|
+
#--
|
4
|
+
# Copyright 2006 Suraj N. Kurapati
|
5
|
+
# See the file named LICENSE for details.
|
6
|
+
|
7
|
+
module VPI
|
8
|
+
# restore compatibility with the C language version of VPI: in Ruby,
|
9
|
+
# constants are capitalized, whereas in C, they do not have to be.
|
10
|
+
constants.grep(/^(S_|Cb|Vpi)/).each do |name|
|
11
|
+
meth = name[0,1].downcase << name[1..-1]
|
12
|
+
value = const_get(name)
|
13
|
+
|
14
|
+
define_method meth do value end
|
15
|
+
module_function meth
|
16
|
+
end
|
17
|
+
|
18
|
+
# Number of bits in PLI_INT32.
|
19
|
+
INTEGER_BITS = 32
|
20
|
+
|
21
|
+
# Lowest upper bound of PLI_INT32.
|
22
|
+
INTEGER_LIMIT = 2 ** INTEGER_BITS
|
23
|
+
|
24
|
+
# Bit-mask capable of capturing PLI_INT32.
|
25
|
+
INTEGER_MASK = INTEGER_LIMIT - 1
|
26
|
+
end
|
27
|
+
|
28
|
+
module RubyVPI
|
29
|
+
SIMULATOR = ENV['RUBYVPI_SIMULATOR'].to_sym
|
30
|
+
USE_DEBUGGER = ENV['DEBUGGER'].to_i == 1
|
31
|
+
USE_COVERAGE = ENV['COVERAGE'].to_i == 1
|
32
|
+
USE_PROTOTYPE = ENV['PROTOTYPE'].to_i == 1
|
33
|
+
USE_PROFILER = ENV['PROFILER'].to_i == 1
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'thread'
|
37
|
+
require 'ruby-vpi/core/struct'
|
38
|
+
require 'ruby-vpi/core/handle'
|
39
|
+
require 'ruby-vpi/core/edge'
|
40
|
+
require 'ruby-vpi/core/callback'
|
41
|
+
require 'ruby-vpi/core/scheduler'
|
data/lib/ruby-vpi/rcov.rb
CHANGED
@@ -23,23 +23,36 @@ require 'rcov'
|
|
23
23
|
require 'rcov/report'
|
24
24
|
|
25
25
|
|
26
|
+
module RubyVPI::Coverage #:nodoc:
|
27
|
+
end
|
28
|
+
|
26
29
|
module RubyVPI
|
27
|
-
|
28
|
-
|
30
|
+
module Coverage
|
31
|
+
@@analyzer = Rcov::CodeCoverageAnalyzer.new
|
32
|
+
|
33
|
+
def Coverage.start
|
34
|
+
@@analyzer.install_hook
|
35
|
+
end
|
36
|
+
|
37
|
+
def Coverage.stop
|
38
|
+
@@analyzer.remove_hook
|
39
|
+
end
|
29
40
|
|
30
|
-
COVERAGE_ANALYSIS_HANDLERS = []
|
31
41
|
|
32
|
-
|
33
|
-
COVERAGE_ANALYSIS.remove_hook
|
42
|
+
@@handlers = []
|
34
43
|
|
35
|
-
|
36
|
-
|
44
|
+
# Invokes the given block after code coverage analysis has completed.
|
45
|
+
def Coverage.attach &aBlock # :yield: Rcov::CodeCoverageAnalyzer
|
46
|
+
raise ArgumentError unless block_given?
|
47
|
+
@@handlers << aBlock if aBlock
|
37
48
|
end
|
38
|
-
end
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
at_exit do
|
51
|
+
Coverage.stop
|
52
|
+
|
53
|
+
@@handlers.each do |h|
|
54
|
+
h.call @@analyzer
|
55
|
+
end
|
56
|
+
end
|
44
57
|
end
|
45
58
|
end
|
data/lib/ruby-vpi/runner.rb
CHANGED
@@ -26,7 +26,7 @@ require 'ruby-vpi/util'
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# auto-detect and set default parameters
|
29
|
-
runnerPath = caller.grep(/runner
|
29
|
+
runnerPath = caller.grep(/runner\.rake/).first.rstrip_from(':')
|
30
30
|
@target = File.basename(runnerPath).rstrip_from('_')
|
31
31
|
|
32
32
|
task :setup
|
@@ -84,6 +84,15 @@ def expand_incdir_options aSimId # :nodoc:
|
|
84
84
|
@incdirs.map {|i| prefix + i}
|
85
85
|
end
|
86
86
|
|
87
|
+
# Creates a new task for running the given simulator.
|
88
|
+
def sim_task aSimId #:nodoc:
|
89
|
+
desc "Simulate with #{RubyVPI::SIMULATORS[aSimId].name}."
|
90
|
+
task aSimId => :setup do
|
91
|
+
ENV['RUBYVPI_SIMULATOR'] = aSimId.to_s
|
92
|
+
yield aSimId
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
87
96
|
|
88
97
|
desc "Show a list of available tasks."
|
89
98
|
task :default do
|
@@ -92,24 +101,22 @@ task :default do
|
|
92
101
|
end
|
93
102
|
|
94
103
|
|
95
|
-
|
96
|
-
task :cver => :setup do
|
104
|
+
sim_task :cver do |id|
|
97
105
|
sh 'cver',
|
98
|
-
"+loadvpi=#{object_file_path(
|
99
|
-
SIMULATOR_ARGUMENTS[
|
100
|
-
expand_incdir_options(
|
106
|
+
"+loadvpi=#{object_file_path(id)}:#{LOADER_FUNC}",
|
107
|
+
SIMULATOR_ARGUMENTS[id],
|
108
|
+
expand_incdir_options(id),
|
101
109
|
@sources
|
102
110
|
end
|
103
111
|
|
104
112
|
CLOBBER.include 'verilog.log'
|
105
113
|
|
106
114
|
|
107
|
-
|
108
|
-
|
109
|
-
cp object_file_path(:ivl), 'ruby-vpi.vpi'
|
115
|
+
sim_task :ivl do |id|
|
116
|
+
cp object_file_path(id), 'ruby-vpi.vpi'
|
110
117
|
sh %w[iverilog -mruby-vpi],
|
111
|
-
SIMULATOR_ARGUMENTS[
|
112
|
-
expand_incdir_options(
|
118
|
+
SIMULATOR_ARGUMENTS[id],
|
119
|
+
expand_incdir_options(id),
|
113
120
|
@sources
|
114
121
|
sh 'vvp -M. a.out'
|
115
122
|
end
|
@@ -117,28 +124,26 @@ end
|
|
117
124
|
CLEAN.include 'ruby-vpi.vpi', 'a.out'
|
118
125
|
|
119
126
|
|
120
|
-
|
121
|
-
task :vcs => :setup do
|
127
|
+
sim_task :vcs do |id|
|
122
128
|
sh %w[vcs -R +v2k +vpi +cli],
|
123
129
|
'-P', File.join(File.dirname(__FILE__), 'pli.tab'),
|
124
|
-
'-load', "#{object_file_path(
|
130
|
+
'-load', "#{object_file_path(id)}:#{LOADER_FUNC}",
|
125
131
|
('-full64' if @archIs64),
|
126
|
-
SIMULATOR_ARGUMENTS[
|
127
|
-
expand_incdir_options(
|
132
|
+
SIMULATOR_ARGUMENTS[id],
|
133
|
+
expand_incdir_options(id),
|
128
134
|
@sources
|
129
135
|
end
|
130
136
|
|
131
137
|
CLEAN.include 'csrc', 'simv*'
|
132
138
|
|
133
139
|
|
134
|
-
|
135
|
-
task :vsim => :setup do
|
140
|
+
sim_task :vsim do |id|
|
136
141
|
sh 'vlib work'
|
137
|
-
sh 'vlog', expand_incdir_options(
|
142
|
+
sh 'vlog', expand_incdir_options(id), @sources
|
138
143
|
sh %w[vsim -c],
|
139
144
|
'-do', 'run -all; exit',
|
140
|
-
'-pli', object_file_path(
|
141
|
-
SIMULATOR_ARGUMENTS[
|
145
|
+
'-pli', object_file_path(id),
|
146
|
+
SIMULATOR_ARGUMENTS[id],
|
142
147
|
@target
|
143
148
|
end
|
144
149
|
|
@@ -146,13 +151,12 @@ CLEAN.include 'work', 'vsim.wlf'
|
|
146
151
|
CLOBBER.include 'transcript'
|
147
152
|
|
148
153
|
|
149
|
-
|
150
|
-
task :ncsim => :setup do
|
154
|
+
sim_task :ncsim do |id|
|
151
155
|
sh %w[ncverilog +access+rwc +plinowarn],
|
152
|
-
"+loadvpi=#{object_file_path(
|
156
|
+
"+loadvpi=#{object_file_path(id)}:#{LOADER_FUNC}",
|
153
157
|
('+nc64bit' if @archIs64),
|
154
|
-
SIMULATOR_ARGUMENTS[
|
155
|
-
expand_incdir_options(
|
158
|
+
SIMULATOR_ARGUMENTS[id],
|
159
|
+
expand_incdir_options(id),
|
156
160
|
@sources
|
157
161
|
end
|
158
162
|
|