origen_link 0.1.0.pre0 → 0.1.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.
- checksums.yaml +4 -4
- data/bin/start_link_server +20 -0
- data/config/application.rb +0 -0
- data/config/boot.rb +3 -2
- data/config/commands.rb +0 -0
- data/config/version.rb +1 -1
- data/lib/origen_link.rb +1 -15
- data/lib/origen_link/callback_handlers.rb +13 -0
- data/lib/origen_link/server/jtag.rb +180 -0
- data/lib/origen_link/server/pin.rb +125 -0
- data/lib/origen_link/server/sequencer.rb +353 -0
- data/lib/origen_link/{includes_vector_based.rb → server_com.rb} +32 -7
- data/lib/origen_link/test/top_level.rb +48 -0
- data/lib/origen_link/test/top_level_controller.rb +44 -0
- data/lib/origen_link/test/vector_based.rb +25 -0
- data/lib/origen_link/vector_based.rb +254 -53
- data/lib/tasks/origen_link.rake +0 -0
- data/pattern/example.rb +0 -0
- data/pattern/jtag_100_operations.rb +0 -0
- data/pattern/jtag_comm_fail_test.rb +0 -0
- data/pattern/jtag_comm_test.rb +0 -0
- data/templates/web/index.md.erb +0 -0
- data/templates/web/layouts/_basic.html.erb +0 -0
- data/templates/web/partials/_navbar.html.erb +0 -0
- data/templates/web/release_notes.md.erb +0 -0
- metadata +32 -18
- data/lib/origen_link/test/regression_tests.rb +0 -68
- data/lib/origen_link/test/test_dut.rb +0 -46
- data/lib/origen_link/test/test_dut_controller.rb +0 -42
- data/lib/origen_link/test/vector_based_redefs.rb +0 -17
- data/lib/origen_link_server/LinkSequencer.rb +0 -333
- data/lib/origen_link_server/LinkTCPServer.rb +0 -45
- data/lib/origen_link_server/jtag_interface.rb +0 -177
- data/lib/origen_link_server/pin_interface.rb +0 -134
- data/lib/origen_link_server/test/test_Sequencer.rb +0 -51
@@ -1,7 +1,5 @@
|
|
1
1
|
module OrigenLink
|
2
|
-
|
3
|
-
include OrigenTesters::VectorBasedTester
|
4
|
-
|
2
|
+
module ServerCom
|
5
3
|
# send_cmd(cmdstr, argstr)
|
6
4
|
# cmdstr is a valid command. <category>_<command>
|
7
5
|
# Ex: 'pin_assign'
|
@@ -29,7 +27,7 @@ module OrigenLink
|
|
29
27
|
# open a connection to the server, send the command and wait for a response
|
30
28
|
TCPSocket.open(@address, @port) do |link|
|
31
29
|
t2 = Time.now
|
32
|
-
link.
|
30
|
+
link.write(cmdstr + ':' + argstr + "\n\n")
|
33
31
|
t3 = Time.now
|
34
32
|
response = link.gets
|
35
33
|
t4 = Time.now
|
@@ -46,8 +44,35 @@ module OrigenLink
|
|
46
44
|
@total_recv_time += (t4 - t3)
|
47
45
|
@max_receive_time = (t4 - t3) if @max_receive_time < (t4 - t3)
|
48
46
|
@total_packets += 1
|
49
|
-
Origen.log.error 'nil
|
50
|
-
response
|
47
|
+
Origen.log.error 'nil response from server (likely died) for command(' + cmdstr + ':' + argstr + ')' if response.nil?
|
48
|
+
response # ensure the response is passed along
|
49
|
+
end
|
50
|
+
|
51
|
+
def send_batch(vector_batch)
|
52
|
+
t2 = 0
|
53
|
+
t3 = 0
|
54
|
+
t4 = 0
|
55
|
+
t5 = 0
|
56
|
+
response = []
|
57
|
+
t1 = Time.now
|
58
|
+
TCPSocket.open(@address, @port) do |link|
|
59
|
+
t2 = Time.now
|
60
|
+
vector_batch_str = vector_batch.join("\n") + "\n\n"
|
61
|
+
link.write(vector_batch_str)
|
62
|
+
t3 = Time.now
|
63
|
+
while line = link.gets
|
64
|
+
response << line.chomp
|
65
|
+
end
|
66
|
+
t4 = Time.now
|
67
|
+
end
|
68
|
+
t5 = Time.now
|
69
|
+
@total_comm_time += (t5 - t1)
|
70
|
+
@total_connect_time += (t2 - t1)
|
71
|
+
@total_xmit_time += (t3 - t2)
|
72
|
+
@total_recv_time += (t4 - t3)
|
73
|
+
@max_receive_time = (t4 - t3) if @max_receive_time < (t4 - t3)
|
74
|
+
@total_packets += 1
|
75
|
+
response
|
51
76
|
end
|
52
77
|
|
53
78
|
# setup_cmd_response_logger
|
@@ -60,7 +85,7 @@ module OrigenLink
|
|
60
85
|
# if the server died (which hopefully it never will) response is nil
|
61
86
|
case response.chr
|
62
87
|
when 'P'
|
63
|
-
Origen.log.
|
88
|
+
Origen.log.debug command + ' setup was successful'
|
64
89
|
when 'F'
|
65
90
|
Origen.log.error command + ' setup FAILED with the following message:'
|
66
91
|
Origen.log.error response.chomp
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module OrigenLink
|
2
|
+
module Test
|
3
|
+
class TopLevel
|
4
|
+
include Origen::TopLevel
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
instantiate_pins(options)
|
8
|
+
instantiate_registers(options)
|
9
|
+
instantiate_sub_blocks(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def instantiate_pins(options = {})
|
13
|
+
options = {
|
14
|
+
jtag_comm_config: false,
|
15
|
+
invalid_pin_number_test: false,
|
16
|
+
missing_pinmap_test: false
|
17
|
+
}.merge(options)
|
18
|
+
add_pin :tclk
|
19
|
+
add_pin :tdi
|
20
|
+
add_pin :tdo
|
21
|
+
add_pin :tms
|
22
|
+
add_pin :resetb
|
23
|
+
add_pins :port_a, size: 8
|
24
|
+
|
25
|
+
pin_pattern_order :tclk, :tms, :tdi, :tdo, only: true if options[:jtag_comm_config]
|
26
|
+
|
27
|
+
# if tester.link? #.to_s == 'OrigenLink::VectorBased'
|
28
|
+
if tester.to_s == 'OrigenLink::VectorBased'
|
29
|
+
if options[:invalid_pin_number_test]
|
30
|
+
tester.pinmap = 'tclk,119,tms,1900,tdi,116,tdo,124'
|
31
|
+
else
|
32
|
+
tester.pinmap = 'tclk,119,tms,6,tdi,116,tdo,124' unless options[:missing_pinmap_test]
|
33
|
+
end
|
34
|
+
tester.pinorder = 'tclk,tms,tdi,tdo'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def instantiate_registers(options = {})
|
39
|
+
reg :testreg, 0 do |reg|
|
40
|
+
reg.bits 31..0, :value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def instantiate_sub_blocks(options = {})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module OrigenLink
|
2
|
+
module Test
|
3
|
+
class TopLevelController
|
4
|
+
include Origen::Controller
|
5
|
+
|
6
|
+
include OrigenJTAG
|
7
|
+
|
8
|
+
JTAG_CONFIG = {
|
9
|
+
#:tclk_format => :rl,
|
10
|
+
tclk_format: :rh,
|
11
|
+
#:tclk_multiple => 1,
|
12
|
+
tclk_multiple: 4,
|
13
|
+
tdo_strobe: :tclk_high,
|
14
|
+
tdo_store_cycle: 3,
|
15
|
+
init_state: :idle
|
16
|
+
}
|
17
|
+
|
18
|
+
def startup(options)
|
19
|
+
pp 'Enter test mode' do
|
20
|
+
# if tester.link?
|
21
|
+
if tester.to_s == 'OrigenLink::VectorBased'
|
22
|
+
tester.initialize_pattern
|
23
|
+
# below is for testing return format timing, requires tclk to be rl and multiple of 1
|
24
|
+
# tester.pinformat = 'func_25mhz,tclk,rl'
|
25
|
+
# tester.pintiming = 'func_25mhz,tdi,0,tms,0,tdo,1'
|
26
|
+
end
|
27
|
+
tester.set_timeset('func_25mhz', 40) # Where 40 is the period in ns
|
28
|
+
tester.wait time_in_us: 100
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def shutdown(options)
|
33
|
+
pp 'Reset the device' do
|
34
|
+
pin(:resetb).drive!(0)
|
35
|
+
pin(:tclk).drive!(0)
|
36
|
+
end
|
37
|
+
# if tester.link?
|
38
|
+
if tester.to_s == 'OrigenLink::VectorBased'
|
39
|
+
tester.finalize_pattern
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'origen_link/vector_based'
|
2
|
+
|
3
|
+
module OrigenLink
|
4
|
+
module Test
|
5
|
+
class VectorBased < ::OrigenLink::VectorBased
|
6
|
+
attr_accessor :message, :microcodestr, :test_response
|
7
|
+
|
8
|
+
def send_cmd(cmdstr, argstr)
|
9
|
+
@message = cmdstr + ':' + argstr
|
10
|
+
@test_response
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_batch(vector_batch)
|
14
|
+
@test_response
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_cmd_response_logger(command, response)
|
18
|
+
end
|
19
|
+
|
20
|
+
def microcode(msg)
|
21
|
+
@microcodestr = @microcodestr + msg
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'origen_testers'
|
2
|
+
require 'origen_link/server_com'
|
3
|
+
require 'origen_link/callback_handlers'
|
1
4
|
module OrigenLink
|
2
5
|
# OrigenLink::VectorBased
|
3
6
|
# This class is meant to be used for live silicon debug. Vector data that Origen
|
@@ -9,15 +12,15 @@ module OrigenLink
|
|
9
12
|
# Integration instructions
|
10
13
|
# Set the pin map (must be done first) and pin order
|
11
14
|
# if tester.link?
|
12
|
-
#
|
13
|
-
#
|
15
|
+
# tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
|
16
|
+
# tester.pinorder = 'tclk,tms,tdi,tdo'
|
14
17
|
# end
|
15
18
|
#
|
16
19
|
# Set Origen to only generate vectors for pins in the pinmap (order should match)
|
17
|
-
#
|
20
|
+
# pin_pattern_order :tclk, :tms, :tdi, :tdo, only: true if tester.link?
|
18
21
|
#
|
19
22
|
# At the beginning of the Startup method add this line
|
20
|
-
#
|
23
|
+
# tester.initialize_pattern if tester.link?
|
21
24
|
#
|
22
25
|
# At the end of the Shutdown method add this line
|
23
26
|
# tester.finalize_pattern if tester.link?
|
@@ -25,12 +28,15 @@ module OrigenLink
|
|
25
28
|
# Create a link environment with the IP address and socket number of a link server
|
26
29
|
# $tester = OrigenLink::VectorBased.new('192.168.0.2', 12777)
|
27
30
|
class VectorBased
|
28
|
-
|
31
|
+
include OrigenTesters::VectorBasedTester
|
32
|
+
include ServerCom
|
29
33
|
|
30
34
|
# these attributes are exposed for testing purposes, a user would not need to read them
|
31
|
-
attr_reader :fail_count, :vector_count, :total_comm_time, :total_connect_time, :total_xmit_time
|
35
|
+
attr_reader :fail_count, :vector_count, :total_comm_time, :total_connect_time, :total_xmit_time
|
36
|
+
attr_reader :total_recv_time, :total_packets, :vector_repeatcount, :tsets_programmed, :captured_data
|
37
|
+
attr_reader :vector_batch, :store_pins_batch, :comment_batch
|
32
38
|
|
33
|
-
def initialize(address, port)
|
39
|
+
def initialize(address, port, options = {})
|
34
40
|
@address = address
|
35
41
|
@port = port
|
36
42
|
@fail_count = 0
|
@@ -47,16 +53,47 @@ module OrigenLink
|
|
47
53
|
@max_receive_time = 0
|
48
54
|
@tsets_programmed = {}
|
49
55
|
@tset_count = 1
|
56
|
+
@store_pins = []
|
57
|
+
@captured_data = []
|
58
|
+
# A tester seems to be unable to register as a callback handler, so for now instantiating a
|
59
|
+
# dedicated object to implement the handlers related to this tester
|
60
|
+
CallbackHandlers.new
|
61
|
+
@vector_batch = []
|
62
|
+
@store_pins_batch = {}
|
63
|
+
@comment_batch = {}
|
64
|
+
@batch_vectors = true
|
65
|
+
end
|
66
|
+
|
67
|
+
# push_comment
|
68
|
+
# This method intercepts comments so they can be correctly placed in the output file
|
69
|
+
# when vector batching is used
|
70
|
+
def push_comment(msg)
|
71
|
+
if @batch_vectors
|
72
|
+
key = @vector_batch.length
|
73
|
+
if @comment_batch.key?(key)
|
74
|
+
@comment_batch[key] = @comment_batch[key] + "\n" + msg
|
75
|
+
else
|
76
|
+
@comment_batch[key] = msg
|
77
|
+
end
|
78
|
+
else
|
79
|
+
microcode msg
|
80
|
+
end
|
50
81
|
end
|
51
82
|
|
52
83
|
# push_vector
|
53
84
|
# This method intercepts vector data from Origen, removes white spaces and compresses repeats
|
54
85
|
def push_vector(options)
|
55
86
|
programmed_data = options[:pin_vals].gsub(/\s+/, '')
|
87
|
+
unless options[:timeset]
|
88
|
+
puts 'No timeset defined!'
|
89
|
+
puts 'Add one to your top level startup method or target like this:'
|
90
|
+
puts '$tester.set_timeset("nvmbist", 40) # Where 40 is the period in ns'
|
91
|
+
exit 1
|
92
|
+
end
|
56
93
|
tset = options[:timeset].name
|
57
94
|
if @vector_count > 0
|
58
95
|
# compressing repeats as we go
|
59
|
-
if (programmed_data == @previous_vectordata) && (@previous_tset == tset)
|
96
|
+
if (programmed_data == @previous_vectordata) && (@previous_tset == tset) && @store_pins.empty?
|
60
97
|
@vector_repeatcount += 1
|
61
98
|
else
|
62
99
|
# all repeats of the previous vector have been counted
|
@@ -74,6 +111,65 @@ module OrigenLink
|
|
74
111
|
@vector_count += 1
|
75
112
|
end
|
76
113
|
|
114
|
+
# Capture a vector
|
115
|
+
#
|
116
|
+
# This method applies a store vector request to the previous vector, note that is does
|
117
|
+
# not actually generate a new vector.
|
118
|
+
#
|
119
|
+
# The captured data is added to the captured_data array.
|
120
|
+
#
|
121
|
+
# This method is indended to be used by pin drivers, see the #capture method for the application
|
122
|
+
# level API.
|
123
|
+
#
|
124
|
+
# @example
|
125
|
+
# $tester.cycle # This is the vector you want to capture
|
126
|
+
# $tester.store # This applies the store request
|
127
|
+
def store(*pins)
|
128
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
129
|
+
fail 'The store is not implemented yet on Link'
|
130
|
+
end
|
131
|
+
|
132
|
+
# Capture the next vector generated
|
133
|
+
#
|
134
|
+
# This method applies a store request to the next vector to be generated,
|
135
|
+
# note that is does not actually generate a new vector.
|
136
|
+
#
|
137
|
+
# The captured data is added to the captured_data array.
|
138
|
+
#
|
139
|
+
# This method is indended to be used by pin drivers, see the #capture method for the application
|
140
|
+
# level API.
|
141
|
+
#
|
142
|
+
# @example
|
143
|
+
# tester.store_next_cycle
|
144
|
+
# tester.cycle # This is the vector that will be captured
|
145
|
+
def store_next_cycle(*pins)
|
146
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
147
|
+
flush_vector
|
148
|
+
@store_pins = pins
|
149
|
+
end
|
150
|
+
|
151
|
+
# Capture any store data within the given block, return it and then internally clear the tester's
|
152
|
+
# capture memory.
|
153
|
+
#
|
154
|
+
# @example
|
155
|
+
#
|
156
|
+
# v = tester.capture do
|
157
|
+
# my_reg.store!
|
158
|
+
# end
|
159
|
+
# v # => Data value read from my_reg on the DUT
|
160
|
+
def capture(*args)
|
161
|
+
if block_given?
|
162
|
+
yield
|
163
|
+
synchronize
|
164
|
+
d = @captured_data
|
165
|
+
@captured_data = []
|
166
|
+
d
|
167
|
+
else
|
168
|
+
# On other testers capture is an alias of store
|
169
|
+
store(*args)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
77
173
|
# flush_vector
|
78
174
|
# Just as the name suggests, this method "flushes" a vector. This is necessary because
|
79
175
|
# of repeat compression (a vector isn't sent until different vector data is encountered)
|
@@ -81,36 +177,116 @@ module OrigenLink
|
|
81
177
|
# Don't forget to flush when you're in debug mode. Otherwise, the last vector of a
|
82
178
|
# write command won't be sent to the server.
|
83
179
|
def flush_vector(programmed_data = '', tset = '')
|
84
|
-
|
85
|
-
|
180
|
+
# prevent server crash when vector_flush is used during debug
|
181
|
+
unless @previous_vectordata == ''
|
182
|
+
if @vector_repeatcount > 1
|
183
|
+
repeat_prefix = "repeat#{@vector_repeatcount},"
|
184
|
+
else
|
185
|
+
repeat_prefix = ''
|
186
|
+
end
|
187
|
+
if @tsets_programmed[@previous_tset]
|
188
|
+
tset_prefix = "tset#{@tsets_programmed[@previous_tset]},"
|
189
|
+
else
|
190
|
+
tset_prefix = ''
|
191
|
+
end
|
192
|
+
|
193
|
+
if @batch_vectors
|
194
|
+
@vector_batch << 'pin_cycle:' + tset_prefix + repeat_prefix + @previous_vectordata
|
195
|
+
# store capture pins for batch processing
|
196
|
+
unless @store_pins.empty?
|
197
|
+
@store_pins_batch[@vector_batch.length - 1] = @store_pins
|
198
|
+
end
|
199
|
+
else
|
200
|
+
process_vector_response(send_cmd('pin_cycle', tset_prefix + repeat_prefix + @previous_vectordata))
|
201
|
+
end
|
202
|
+
|
203
|
+
# make sure that only requested vectors are stored when batching is enabled
|
204
|
+
@store_pins = []
|
205
|
+
end
|
206
|
+
|
207
|
+
@vector_repeatcount = 1
|
208
|
+
@previous_vectordata = programmed_data
|
209
|
+
@previous_tset = tset
|
210
|
+
end
|
211
|
+
|
212
|
+
# synchronize
|
213
|
+
# This method will synchronize the DUT state with Origen. All generated
|
214
|
+
# vectors are sent to the DUT for execution and the responses are processed
|
215
|
+
def synchronize(output_file = '')
|
216
|
+
flush_vector
|
217
|
+
if @batch_vectors
|
218
|
+
process_response(send_batch(@vector_batch), output_file)
|
219
|
+
end
|
220
|
+
@vector_batch = []
|
221
|
+
@store_pins_batch.clear
|
222
|
+
@comment_batch.clear
|
223
|
+
end
|
224
|
+
|
225
|
+
# process_response
|
226
|
+
# This method will process a server response. Send log info to the output,
|
227
|
+
# keep track of fail count and captured data
|
228
|
+
def process_response(response, output_file = '')
|
229
|
+
if response.is_a?(Array)
|
230
|
+
# if called from finalize_pattern -> synchronize, open the output_file and store results
|
231
|
+
output_obj = nil
|
232
|
+
output_obj = File.open(output_file, 'a+') unless output_file == ''
|
233
|
+
response.each_index do |index|
|
234
|
+
# restore store pins state for processing
|
235
|
+
if @store_pins_batch.key?(index)
|
236
|
+
@store_pins = @store_pins_batch[index]
|
237
|
+
else
|
238
|
+
@store_pins = []
|
239
|
+
end
|
240
|
+
if @comment_batch.key?(index)
|
241
|
+
unless output_file == ''
|
242
|
+
# get the header placed correctly
|
243
|
+
if index == response.length - 1
|
244
|
+
output_obj.puts 'last comment'
|
245
|
+
output_obj.lineno = 0
|
246
|
+
end
|
247
|
+
output_obj.puts(@comment_batch[index])
|
248
|
+
end
|
249
|
+
end
|
250
|
+
process_vector_response(response[index], output_obj)
|
251
|
+
end
|
252
|
+
output_obj.close unless output_file == ''
|
86
253
|
else
|
87
|
-
|
254
|
+
process_vector_response(response)
|
88
255
|
end
|
89
|
-
|
90
|
-
|
256
|
+
end
|
257
|
+
|
258
|
+
# process_vector_response
|
259
|
+
# This method exists to prevent code duplication when handling an array of
|
260
|
+
# batched responses versus a single response string.
|
261
|
+
def process_vector_response(vector_response, output_obj = nil)
|
262
|
+
unless @store_pins.empty?
|
263
|
+
msg = " (Captured #{@store_pins.map(&:name).join(', ')})\n"
|
264
|
+
capture_data(vector_response)
|
265
|
+
vector_response.strip!
|
266
|
+
vector_response += msg
|
267
|
+
end
|
268
|
+
if output_obj.nil?
|
269
|
+
microcode vector_response
|
91
270
|
else
|
92
|
-
|
271
|
+
output_obj.puts(vector_response)
|
93
272
|
end
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
microcode 'E:' + @previous_vectordata + ' //expected data for previous vector'
|
273
|
+
|
274
|
+
unless vector_response.chr == 'P'
|
275
|
+
# TODO: Put this back with an option to disable, based on a serial or parallel interface being used
|
276
|
+
# microcode 'E:' + @previous_vectordata + ' //expected data for previous vector'
|
98
277
|
@fail_count += 1
|
99
278
|
end
|
100
|
-
@vector_repeatcount = 1
|
101
|
-
@previous_vectordata = programmed_data
|
102
|
-
@previous_tset = tset
|
103
279
|
end
|
104
280
|
|
105
281
|
# initialize_pattern
|
106
|
-
# At some point in the future this intialization should be done behind the
|
107
|
-
# scenes without requiring the user to add code to the controller.
|
108
|
-
#
|
109
282
|
# This method sets initializes variables at the start of a pattern.
|
110
|
-
# it
|
283
|
+
# it is called automatically when pattern generation starts.
|
111
284
|
def initialize_pattern
|
112
285
|
@fail_count = 0
|
113
286
|
@vector_count = 0
|
287
|
+
@vector_batch.delete_if { true }
|
288
|
+
@store_pins_batch.clear
|
289
|
+
@comment_batch.clear
|
114
290
|
|
115
291
|
@total_packets = 0
|
116
292
|
@total_comm_time = 0
|
@@ -121,35 +297,36 @@ module OrigenLink
|
|
121
297
|
if @pinmap.nil?
|
122
298
|
Origen.log.error('pinmap has not been setup, use tester.pinmap= to initialize a pinmap')
|
123
299
|
else
|
124
|
-
Origen.log.
|
300
|
+
Origen.log.debug('executing pattern with pinmap:' + @pinmap.to_s)
|
125
301
|
end
|
126
302
|
end
|
127
303
|
|
128
304
|
# finalize_pattern
|
129
|
-
# At some point in the future this finalization should be done behind the scenes.
|
130
|
-
#
|
131
305
|
# This method flushes the final vector. Then, it logs success or failure of the
|
132
306
|
# pattern execution along with execution time information.
|
133
|
-
def finalize_pattern(
|
134
|
-
|
307
|
+
def finalize_pattern(output_file)
|
308
|
+
Origen.log.debug('Pattern generation completed. Sending all stored vector data')
|
309
|
+
synchronize(output_file)
|
310
|
+
# for debug, report communication times
|
311
|
+
Origen.log.debug("total communication time: #{@total_comm_time}")
|
312
|
+
Origen.log.debug("total connect time: #{@total_connect_time}")
|
313
|
+
Origen.log.debug("total transmit time: #{@total_xmit_time}")
|
314
|
+
Origen.log.debug("total receive time: #{@total_recv_time}")
|
315
|
+
Origen.log.debug("total packets: #{@total_packets}")
|
316
|
+
Origen.log.debug("total time per packet: #{@total_comm_time / @total_packets}")
|
317
|
+
Origen.log.debug("connect time per packet: #{@total_connect_time / @total_packets}")
|
318
|
+
Origen.log.debug("transmit time per packet: #{@total_xmit_time / @total_packets}")
|
319
|
+
Origen.log.debug("receive time per packet: #{@total_recv_time / @total_packets}")
|
320
|
+
Origen.log.debug("max packet time: #{@max_packet_time}")
|
321
|
+
Origen.log.debug("max duration command - #{@longest_packet}")
|
322
|
+
Origen.log.debug("max receive time: #{@max_receive_time}")
|
135
323
|
if @fail_count == 0
|
136
|
-
Origen.log.success("PASS - pattern execution passed (#{@vector_count} vectors pass)")
|
324
|
+
# Origen.log.success("PASS - pattern execution passed (#{@vector_count} vectors pass)")
|
325
|
+
Origen.app.stats.report_pass
|
137
326
|
else
|
138
|
-
Origen.log.error("FAIL - pattern execution failed (#{@fail_count} failures)")
|
327
|
+
# Origen.log.error("FAIL - pattern execution failed (#{@fail_count} failures)")
|
328
|
+
Origen.app.stats.report_fail
|
139
329
|
end
|
140
|
-
# for debug, report communication times
|
141
|
-
Origen.log.info("total communication time: #{@total_comm_time}")
|
142
|
-
Origen.log.info("total connect time: #{@total_connect_time}")
|
143
|
-
Origen.log.info("total transmit time: #{@total_xmit_time}")
|
144
|
-
Origen.log.info("total receive time: #{@total_recv_time}")
|
145
|
-
Origen.log.info("total packets: #{@total_packets}")
|
146
|
-
Origen.log.info("total time per packet: #{@total_comm_time / @total_packets}")
|
147
|
-
Origen.log.info("connect time per packet: #{@total_connect_time / @total_packets}")
|
148
|
-
Origen.log.info("transmit time per packet: #{@total_xmit_time / @total_packets}")
|
149
|
-
Origen.log.info("receive time per packet: #{@total_recv_time / @total_packets}")
|
150
|
-
Origen.log.info("max packet time: #{@max_packet_time}")
|
151
|
-
Origen.log.info('max duration command - ' + @longest_packet)
|
152
|
-
Origen.log.info("max receive time: #{@max_receive_time}")
|
153
330
|
end
|
154
331
|
|
155
332
|
# to_s
|
@@ -162,14 +339,6 @@ module OrigenLink
|
|
162
339
|
'OrigenLink::VectorBased'
|
163
340
|
end
|
164
341
|
|
165
|
-
# link?
|
166
|
-
# returns true.
|
167
|
-
#
|
168
|
-
# This method indicates to user code that link is the tester environment.
|
169
|
-
def link?
|
170
|
-
true
|
171
|
-
end
|
172
|
-
|
173
342
|
# pinmap=
|
174
343
|
# This method is used to setup the pin map on the debugger device.
|
175
344
|
# The argument should be a string with <pin name>, <gpio #>, <pin name>
|
@@ -250,5 +419,37 @@ module OrigenLink
|
|
250
419
|
end
|
251
420
|
@tsets_programmed[name]
|
252
421
|
end
|
422
|
+
|
423
|
+
private
|
424
|
+
|
425
|
+
def capture_data(response)
|
426
|
+
if @store_pins.size > 1
|
427
|
+
fail 'Data capture on multiple pins is not implemented yet'
|
428
|
+
else
|
429
|
+
captured_data[0] ||= 0
|
430
|
+
captured_data[0] = (captured_data[0] << 1) | extract_value(response, @store_pins[0])
|
431
|
+
@store_pins = []
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def extract_value(response, pin)
|
436
|
+
v = response[index_of(pin) + 2]
|
437
|
+
if v == '`'
|
438
|
+
1
|
439
|
+
elsif v == '.'
|
440
|
+
0
|
441
|
+
else
|
442
|
+
fail "Failed to extract value for pin #{pin.name}, character in response is: #{v}"
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
# Returns the vector index (position) of the given pin
|
447
|
+
def index_of(pin)
|
448
|
+
i = @pinorder.split(',').index(pin.name.to_s)
|
449
|
+
unless i
|
450
|
+
fail "Data capture of pin #{pin.name} has been requested, but it has not been included in the Link pinmap!"
|
451
|
+
end
|
452
|
+
i
|
453
|
+
end
|
253
454
|
end
|
254
455
|
end
|