origen_link 0.2.0.pre0 → 0.2.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.
@@ -1,25 +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
+ 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,365 +1,366 @@
1
- require 'etc'
2
- require 'origen_testers'
3
- require 'origen_link/server_com'
4
- require 'origen_link/capture_support'
5
- require 'origen_link/configuration_commands'
6
- require 'origen_link/callback_handlers'
7
- module OrigenLink
8
- # OrigenLink::VectorBased
9
- # This class is meant to be used for live silicon debug. Vector data that Origen
10
- # generates is intercepted and sent to a debug device (typically will be a Udoo
11
- # Neo - www.udoo.org). The debug device can be any device that is able to serve
12
- # a TCP socket, recieve and interpret the command set used by this class and send
13
- # the expected responses.
14
- #
15
- # Integration instructions
16
- # Set the pin map (must be done first) and pin order
17
- # if tester.link?
18
- # tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
19
- # tester.pinorder = 'tclk,tms,tdi,tdo'
20
- # end
21
- #
22
- # Set Origen to only generate vectors for pins in the pinmap (order should match)
23
- # pin_pattern_order :tclk, :tms, :tdi, :tdo, only: true if tester.link?
24
- #
25
- # At the beginning of the Startup method add this line
26
- # tester.initialize_pattern if tester.link?
27
- #
28
- # At the end of the Shutdown method add this line
29
- # tester.finalize_pattern if tester.link?
30
- #
31
- # Create a link environment with the IP address and socket number of a link server
32
- # $tester = OrigenLink::VectorBased.new('192.168.0.2', 12777)
33
- class VectorBased
34
- include OrigenTesters::VectorBasedTester
35
- include ServerCom
36
- include CaptureSupport
37
- include ConfigurationCommands
38
-
39
- # these attributes are exposed for testing purposes, a user would not need to read them
40
- attr_reader :fail_count, :vector_count, :total_comm_time, :total_connect_time, :total_xmit_time
41
- attr_reader :total_recv_time, :total_packets, :vector_repeatcount, :tsets_programmed, :captured_data
42
- attr_reader :vector_batch, :store_pins_batch, :comment_batch
43
- attr_reader :user_name, :initial_comm_sent
44
-
45
- def initialize(address, port, options = {})
46
- @address = address
47
- @port = port
48
- @fail_count = 0
49
- @vector_count = 0
50
- @previous_vectordata = ''
51
- @previous_tset = ''
52
- @vector_repeatcount = 0
53
- @total_comm_time = 0
54
- @total_connect_time = 0
55
- @total_xmit_time = 0
56
- @total_recv_time = 0
57
- @total_packets = 0
58
- @max_packet_time = 0
59
- @max_receive_time = 0
60
- @tsets_programmed = {}
61
- @tset_count = 1
62
- @store_pins = []
63
- @captured_data = []
64
- # A tester seems to be unable to register as a callback handler, so for now instantiating a
65
- # dedicated object to implement the handlers related to this tester
66
- CallbackHandlers.new
67
- @vector_batch = []
68
- @store_pins_batch = {}
69
- @comment_batch = {}
70
- @batch_vectors = true
71
- @pattern_link_messages = []
72
- @pattern_comments = {}
73
- @user_name = Etc.getlogin
74
- @initial_comm_sent = false
75
- end
76
-
77
- # push_comment
78
- # This method intercepts comments so they can be correctly placed in the output file
79
- # when vector batching is used
80
- def push_comment(msg)
81
- if @batch_vectors
82
- key = @vector_batch.length
83
- if @comment_batch.key?(key)
84
- @comment_batch[key] = @comment_batch[key] + "\n" + msg
85
- else
86
- @comment_batch[key] = msg
87
- end
88
- pattern_key = @pattern_link_messages.length + key
89
- @pattern_comments[pattern_key] = @comment_batch[key]
90
- else
91
- microcode msg
92
- end
93
- end
94
-
95
- # push_vector
96
- # This method intercepts vector data from Origen, removes white spaces and compresses repeats
97
- def push_vector(options)
98
- programmed_data = options[:pin_vals].gsub(/\s+/, '')
99
- unless options[:timeset]
100
- puts 'No timeset defined!'
101
- puts 'Add one to your top level startup method or target like this:'
102
- puts '$tester.set_timeset("nvmbist", 40) # Where 40 is the period in ns'
103
- exit 1
104
- end
105
- tset = options[:timeset].name
106
- if @vector_count > 0
107
- # compressing repeats as we go
108
- if (programmed_data == @previous_vectordata) && (@previous_tset == tset) && @store_pins.empty?
109
- @vector_repeatcount += 1
110
- else
111
- # all repeats of the previous vector have been counted
112
- # time to flush. Don't panic though! @previous_vectordata
113
- # is what gets flushed. programmed_data is passed as an
114
- # arg to be set as the new @previous_vectordata
115
- flush_vector(programmed_data, tset)
116
- end
117
- else
118
- # if this is the first vector of the pattern, insure variables are initialized
119
- @previous_vectordata = programmed_data
120
- @previous_tset = tset
121
- @vector_repeatcount = 1
122
- end # if vector_count > 0
123
- @vector_count += 1
124
- end
125
-
126
- # flush_vector
127
- # Just as the name suggests, this method "flushes" a vector. This is necessary because
128
- # of repeat compression (a vector isn't sent until different vector data is encountered)
129
- #
130
- # Don't forget to flush when you're in debug mode. Otherwise, the last vector of a
131
- # write command won't be sent to the server.
132
- def flush_vector(programmed_data = '', tset = '')
133
- # prevent server crash when vector_flush is used during debug
134
- unless @previous_vectordata == ''
135
- if @vector_repeatcount > 1
136
- repeat_prefix = "repeat#{@vector_repeatcount},"
137
- else
138
- repeat_prefix = ''
139
- end
140
- if @tsets_programmed[@previous_tset]
141
- tset_prefix = "tset#{@tsets_programmed[@previous_tset]},"
142
- else
143
- tset_prefix = ''
144
- end
145
-
146
- if @batch_vectors
147
- @vector_batch << 'pin_cycle:' + tset_prefix + repeat_prefix + @previous_vectordata
148
- # store capture pins for batch processing
149
- unless @store_pins.empty?
150
- @store_pins_batch[@vector_batch.length - 1] = @store_pins
151
- end
152
- else
153
- process_vector_response(send_cmd('pin_cycle', tset_prefix + repeat_prefix + @previous_vectordata))
154
- end
155
-
156
- # make sure that only requested vectors are stored when batching is enabled
157
- @store_pins = []
158
- end
159
-
160
- @vector_repeatcount = 1
161
- @previous_vectordata = programmed_data
162
- @previous_tset = tset
163
- end
164
-
165
- # synchronize
166
- # This method will synchronize the DUT state with Origen. All generated
167
- # vectors are sent to the DUT for execution and the responses are processed
168
- def synchronize(output_file = '')
169
- flush_vector
170
- if @batch_vectors
171
- process_response(send_batch(@vector_batch), output_file)
172
- end
173
- @vector_batch = []
174
- @store_pins_batch.clear
175
- @comment_batch.clear
176
- end
177
-
178
- # process_response
179
- # This method will process a server response. Send log info to the output,
180
- # keep track of fail count and captured data
181
- def process_response(response, output_file = '')
182
- if response.is_a?(Array)
183
- # if called from finalize_pattern -> synchronize, open the output_file and store results
184
- output_obj = nil
185
- output_obj = File.open(output_file, 'a+') unless output_file == ''
186
-
187
- # in case there were only comments and no vectors, place comments (if any)
188
- microcode @comment_batch[0] if response.size == 0
189
-
190
- response.each_index do |index|
191
- # restore store pins state for processing
192
- if @store_pins_batch.key?(index)
193
- @store_pins = @store_pins_batch[index]
194
- else
195
- @store_pins = []
196
- end
197
- process_vector_response(response[index], output_obj)
198
- if @comment_batch.key?(index)
199
- if output_file == ''
200
- microcode @comment_batch[index]
201
- else
202
- # get the header placed correctly, the below code doesn't work
203
- # if index == response.length - 1
204
- # output_obj.puts 'last comment'
205
- # output_obj.lineno = 0
206
- # end
207
- output_obj.puts(@comment_batch[index])
208
- end
209
- end
210
- end
211
- output_obj.close unless output_file == ''
212
- else
213
- process_vector_response(response)
214
- end
215
- end
216
-
217
- # process_vector_response
218
- # This method exists to prevent code duplication when handling an array of
219
- # batched responses versus a single response string.
220
- def process_vector_response(vector_response, output_obj = nil)
221
- unless @store_pins.empty?
222
- msg = " (Captured #{@store_pins.map(&:name).join(', ')})\n"
223
- capture_data(vector_response)
224
- vector_response.strip!
225
- vector_response += msg
226
- end
227
- vector_cycles = vector_response.split(/\s+/)
228
- expected_msg = ''
229
- expected_msg = ' ' + vector_cycles.pop if vector_cycles[vector_cycles.length - 1] =~ /Expected/
230
- pfstatus = vector_cycles[0].chr
231
- vector_cycles[0] = vector_cycles[0].byteslice(2, vector_cycles[0].length - 2)
232
-
233
- vector_cycles.each do |cycle|
234
- thiscyclefail = false
235
- if pfstatus == 'F'
236
- # check to see if this cycle failed
237
- 0.upto(cycle.length - 1) do |index|
238
- thiscyclefail = true if (cycle[index] == 'H') && (expected_msg[expected_msg.length - cycle.length + index] == 'L')
239
- thiscyclefail = true if (cycle[index] == 'L') && (expected_msg[expected_msg.length - cycle.length + index] == 'X')
240
- end
241
- end
242
- if thiscyclefail
243
- expected_msg_prnt = expected_msg
244
- prepend = 'F:'
245
- else
246
- expected_msg_prnt = ''
247
- prepend = 'P:'
248
- end
249
-
250
- if output_obj.nil?
251
- microcode prepend + cycle + expected_msg_prnt
252
- else
253
- output_obj.puts(prepend + cycle + expected_msg_prnt)
254
- end
255
- end
256
-
257
- unless vector_response.chr == 'P'
258
- # TODO: Put this back with an option to disable, based on a serial or parallel interface being used
259
- # microcode 'E:' + @previous_vectordata + ' //expected data for previous vector'
260
- @fail_count += 1
261
- end
262
- end
263
-
264
- # initialize_pattern
265
- # This method sets initializes variables at the start of a pattern.
266
- # it is called automatically when pattern generation starts.
267
- def initialize_pattern
268
- @fail_count = 0
269
- @vector_count = 0
270
- @vector_batch.delete_if { true }
271
- @store_pins_batch.clear
272
- @comment_batch.clear
273
- @pattern_link_messages.delete_if { true }
274
- @pattern_comments.clear
275
-
276
- @total_packets = 0
277
- @total_comm_time = 0
278
- @total_connect_time = 0
279
- @total_xmit_time = 0
280
- @total_recv_time = 0
281
-
282
- if @pinmap.nil?
283
- Origen.log.error('pinmap has not been setup, use tester.pinmap= to initialize a pinmap')
284
- else
285
- Origen.log.debug('executing pattern with pinmap:' + @pinmap.to_s)
286
- end
287
- end
288
-
289
- # finalize_pattern
290
- # This method flushes the final vector. Then, it logs success or failure of the
291
- # pattern execution along with execution time information.
292
- def finalize_pattern(output_file)
293
- Origen.log.debug('Pattern generation completed. Sending all stored vector data')
294
- synchronize(output_file)
295
- send_cmd('', 'session_end')
296
- # for debug, report communication times
297
- Origen.log.debug("total communication time: #{@total_comm_time}")
298
- Origen.log.debug("total connect time: #{@total_connect_time}")
299
- Origen.log.debug("total transmit time: #{@total_xmit_time}")
300
- Origen.log.debug("total receive time: #{@total_recv_time}")
301
- Origen.log.debug("total packets: #{@total_packets}")
302
- Origen.log.debug("total time per packet: #{@total_comm_time / @total_packets}")
303
- Origen.log.debug("connect time per packet: #{@total_connect_time / @total_packets}")
304
- Origen.log.debug("transmit time per packet: #{@total_xmit_time / @total_packets}")
305
- Origen.log.debug("receive time per packet: #{@total_recv_time / @total_packets}")
306
- Origen.log.debug("max packet time: #{@max_packet_time}")
307
- Origen.log.debug("max duration command - #{@longest_packet}")
308
- Origen.log.debug("max receive time: #{@max_receive_time}")
309
- if @fail_count == 0
310
- # Origen.log.success("PASS - pattern execution passed (#{@vector_count} vectors pass)")
311
- Origen.app.stats.report_pass
312
- else
313
- # Origen.log.error("FAIL - pattern execution failed (#{@fail_count} failures)")
314
- Origen.app.stats.report_fail
315
- end
316
- commands_file = Origen.app.current_job.output_file.split('.')[0] + '_link_cmds.txt'
317
- File.open(commands_file, 'w') do |file|
318
- file.puts("pin_assign:#{@pinmap}")
319
- file.puts("pin_patternorder:#{@pinorder}")
320
- @pattern_link_messages.each_index do |index|
321
- file.puts(@pattern_link_messages[index])
322
- file.puts(@pattern_comments[index]) if @pattern_comments.key?(index)
323
- end
324
- file.puts(':session_end')
325
- end
326
- end
327
-
328
- # to_s
329
- # returns 'Origen::VectorBased'
330
- #
331
- # This method at the moment is used for implementing code that runs only if the
332
- # environment is set to link vector based. tester.link? will be used once the testers
333
- # plug in supports the method link?.
334
- def to_s
335
- 'OrigenLink::VectorBased'
336
- end
337
-
338
- # transaction
339
- # returns true/false indicating whether the transaction passed
340
- # true = pass
341
- # false = fail
342
- #
343
- # TODO: capture transaction vector data and response for use in debug
344
- #
345
- # if !tester.transaction {dut.reg blah blah}
346
- # puts 'transaction failed'
347
- # end
348
- def transaction
349
- if block_given?
350
- synchronize
351
- transaction_fail_count = @fail_count
352
- yield
353
- synchronize
354
- transaction_fail_count = @fail_count - transaction_fail_count
355
- if transaction_fail_count == 0
356
- true
357
- else
358
- false
359
- end
360
- else
361
- true
362
- end
363
- end
364
- end
365
- end
1
+ require 'etc'
2
+ require 'origen_testers'
3
+ require 'origen_link/server_com'
4
+ require 'origen_link/capture_support'
5
+ require 'origen_link/configuration_commands'
6
+ require 'origen_link/callback_handlers'
7
+ module OrigenLink
8
+ # OrigenLink::VectorBased
9
+ # This class is meant to be used for live silicon debug. Vector data that Origen
10
+ # generates is intercepted and sent to a debug device (typically will be a Udoo
11
+ # Neo - www.udoo.org). The debug device can be any device that is able to serve
12
+ # a TCP socket, recieve and interpret the command set used by this class and send
13
+ # the expected responses.
14
+ #
15
+ # Integration instructions
16
+ # Set the pin map (must be done first) and pin order
17
+ # if tester.link?
18
+ # tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
19
+ # tester.pinorder = 'tclk,tms,tdi,tdo'
20
+ # end
21
+ #
22
+ # Set Origen to only generate vectors for pins in the pinmap (order should match)
23
+ # pin_pattern_order :tclk, :tms, :tdi, :tdo, only: true if tester.link?
24
+ #
25
+ # At the beginning of the Startup method add this line
26
+ # tester.initialize_pattern if tester.link?
27
+ #
28
+ # At the end of the Shutdown method add this line
29
+ # tester.finalize_pattern if tester.link?
30
+ #
31
+ # Create a link environment with the IP address and socket number of a link server
32
+ # $tester = OrigenLink::VectorBased.new('192.168.0.2', 12777)
33
+ class VectorBased
34
+ include OrigenTesters::VectorBasedTester
35
+ include ServerCom
36
+ include CaptureSupport
37
+ include ConfigurationCommands
38
+
39
+ # these attributes are exposed for testing purposes, a user would not need to read them
40
+ attr_reader :fail_count, :vector_count, :total_comm_time, :total_connect_time, :total_xmit_time
41
+ attr_reader :total_recv_time, :total_packets, :vector_repeatcount, :tsets_programmed, :captured_data
42
+ attr_reader :vector_batch, :store_pins_batch, :comment_batch
43
+ attr_reader :user_name, :initial_comm_sent
44
+
45
+ def initialize(address, port, options = {})
46
+ @address = address
47
+ @port = port
48
+ @fail_count = 0
49
+ @vector_count = 0
50
+ @previous_vectordata = ''
51
+ @previous_tset = ''
52
+ @vector_repeatcount = 0
53
+ @total_comm_time = 0
54
+ @total_connect_time = 0
55
+ @total_xmit_time = 0
56
+ @total_recv_time = 0
57
+ @total_packets = 0
58
+ @max_packet_time = 0
59
+ @max_receive_time = 0
60
+ @tsets_programmed = {}
61
+ @tset_count = 1
62
+ @store_pins = []
63
+ @captured_data = []
64
+ # A tester seems to be unable to register as a callback handler, so for now instantiating a
65
+ # dedicated object to implement the handlers related to this tester
66
+ CallbackHandlers.new
67
+ @vector_batch = []
68
+ @store_pins_batch = {}
69
+ @comment_batch = {}
70
+ @batch_vectors = true
71
+ @pattern_link_messages = []
72
+ @pattern_comments = {}
73
+ @user_name = Etc.getlogin
74
+ @initial_comm_sent = false
75
+ end
76
+
77
+ # push_comment
78
+ # This method intercepts comments so they can be correctly placed in the output file
79
+ # when vector batching is used
80
+ def push_comment(msg)
81
+ if @batch_vectors
82
+ key = @vector_batch.length
83
+ if @comment_batch.key?(key)
84
+ @comment_batch[key] = @comment_batch[key] + "\n" + msg
85
+ else
86
+ @comment_batch[key] = msg
87
+ end
88
+ pattern_key = @pattern_link_messages.length + key
89
+ @pattern_comments[pattern_key] = @comment_batch[key]
90
+ else
91
+ microcode msg
92
+ end
93
+ end
94
+
95
+ # push_vector
96
+ # This method intercepts vector data from Origen, removes white spaces and compresses repeats
97
+ def push_vector(options)
98
+ programmed_data = options[:pin_vals].gsub(/\s+/, '')
99
+ unless options[:timeset]
100
+ puts 'No timeset defined!'
101
+ puts 'Add one to your top level startup method or target like this:'
102
+ puts '$tester.set_timeset("nvmbist", 40) # Where 40 is the period in ns'
103
+ exit 1
104
+ end
105
+ tset = options[:timeset].name
106
+ if @vector_count > 0
107
+ # compressing repeats as we go
108
+ if (programmed_data == @previous_vectordata) && (@previous_tset == tset) && @store_pins.empty?
109
+ @vector_repeatcount += 1
110
+ else
111
+ # all repeats of the previous vector have been counted
112
+ # time to flush. Don't panic though! @previous_vectordata
113
+ # is what gets flushed. programmed_data is passed as an
114
+ # arg to be set as the new @previous_vectordata
115
+ flush_vector(programmed_data, tset)
116
+ end
117
+ else
118
+ # if this is the first vector of the pattern, insure variables are initialized
119
+ @previous_vectordata = programmed_data
120
+ @previous_tset = tset
121
+ @vector_repeatcount = 1
122
+ end # if vector_count > 0
123
+ @vector_count += 1
124
+ end
125
+
126
+ # flush_vector
127
+ # Just as the name suggests, this method "flushes" a vector. This is necessary because
128
+ # of repeat compression (a vector isn't sent until different vector data is encountered)
129
+ #
130
+ # Don't forget to flush when you're in debug mode. Otherwise, the last vector of a
131
+ # write command won't be sent to the server.
132
+ def flush_vector(programmed_data = '', tset = '')
133
+ # prevent server crash when vector_flush is used during debug
134
+ unless @previous_vectordata == ''
135
+ if @vector_repeatcount > 1
136
+ repeat_prefix = "repeat#{@vector_repeatcount},"
137
+ else
138
+ repeat_prefix = ''
139
+ end
140
+ if @tsets_programmed[@previous_tset]
141
+ tset_prefix = "tset#{@tsets_programmed[@previous_tset]},"
142
+ else
143
+ tset_prefix = ''
144
+ end
145
+
146
+ if @batch_vectors
147
+ @vector_batch << 'pin_cycle:' + tset_prefix + repeat_prefix + @previous_vectordata
148
+ # store capture pins for batch processing
149
+ unless @store_pins.empty?
150
+ @store_pins_batch[@vector_batch.length - 1] = @store_pins
151
+ end
152
+ else
153
+ process_vector_response(send_cmd('pin_cycle', tset_prefix + repeat_prefix + @previous_vectordata))
154
+ end
155
+
156
+ # make sure that only requested vectors are stored when batching is enabled
157
+ @store_pins = []
158
+ end
159
+
160
+ @vector_repeatcount = 1
161
+ @previous_vectordata = programmed_data
162
+ @previous_tset = tset
163
+ end
164
+
165
+ # synchronize
166
+ # This method will synchronize the DUT state with Origen. All generated
167
+ # vectors are sent to the DUT for execution and the responses are processed
168
+ def synchronize(output_file = '')
169
+ flush_vector
170
+ if @batch_vectors
171
+ process_response(send_batch(@vector_batch), output_file)
172
+ end
173
+ @vector_batch = []
174
+ @store_pins_batch.clear
175
+ @comment_batch.clear
176
+ end
177
+
178
+ # process_response
179
+ # This method will process a server response. Send log info to the output,
180
+ # keep track of fail count and captured data
181
+ def process_response(response, output_file = '')
182
+ if response.is_a?(Array)
183
+ # if called from finalize_pattern -> synchronize, open the output_file and store results
184
+ output_obj = nil
185
+ output_obj = File.open(output_file, 'a+') unless output_file == ''
186
+
187
+ # in case there were only comments and no vectors, place comments (if any)
188
+ microcode @comment_batch[0] if response.size == 0
189
+
190
+ response.each_index do |index|
191
+ # restore store pins state for processing
192
+ if @store_pins_batch.key?(index)
193
+ @store_pins = @store_pins_batch[index]
194
+ else
195
+ @store_pins = []
196
+ end
197
+ process_vector_response(response[index], output_obj)
198
+ if @comment_batch.key?(index)
199
+ if output_file == ''
200
+ microcode @comment_batch[index]
201
+ else
202
+ # get the header placed correctly, the below code doesn't work
203
+ # if index == response.length - 1
204
+ # output_obj.puts 'last comment'
205
+ # output_obj.lineno = 0
206
+ # end
207
+ output_obj.puts(@comment_batch[index])
208
+ end
209
+ end
210
+ end
211
+ output_obj.close unless output_file == ''
212
+ else
213
+ process_vector_response(response)
214
+ end
215
+ end
216
+
217
+ # process_vector_response
218
+ # This method exists to prevent code duplication when handling an array of
219
+ # batched responses versus a single response string.
220
+ def process_vector_response(vector_response, output_obj = nil)
221
+ msg = ''
222
+ unless @store_pins.empty?
223
+ msg = " (Captured #{@store_pins.map(&:name).join(', ')})\n"
224
+ capture_data(vector_response)
225
+ vector_response.strip!
226
+ # vector_response += msg
227
+ end
228
+ vector_cycles = vector_response.split(/\s+/)
229
+ expected_msg = ''
230
+ expected_msg = ' ' + vector_cycles.pop if vector_cycles[vector_cycles.length - 1] =~ /Expected/
231
+ pfstatus = vector_cycles[0].chr
232
+ vector_cycles[0] = vector_cycles[0].byteslice(2, vector_cycles[0].length - 2)
233
+
234
+ vector_cycles.each do |cycle|
235
+ thiscyclefail = false
236
+ if pfstatus == 'F'
237
+ # check to see if this cycle failed
238
+ 0.upto(cycle.length - 1) do |index|
239
+ thiscyclefail = true if (cycle[index] == 'H') && (expected_msg[expected_msg.length - cycle.length + index] == 'L')
240
+ thiscyclefail = true if (cycle[index] == 'L') && (expected_msg[expected_msg.length - cycle.length + index] == 'H')
241
+ end
242
+ end
243
+ if thiscyclefail
244
+ expected_msg_prnt = expected_msg
245
+ prepend = 'F:'
246
+ else
247
+ expected_msg_prnt = ''
248
+ prepend = 'P:'
249
+ end
250
+
251
+ if output_obj.nil?
252
+ microcode prepend + cycle + expected_msg_prnt + msg
253
+ else
254
+ output_obj.puts(prepend + cycle + expected_msg_prnt + msg)
255
+ end
256
+ end
257
+
258
+ unless vector_response.chr == 'P'
259
+ # TODO: Put this back with an option to disable, based on a serial or parallel interface being used
260
+ # microcode 'E:' + @previous_vectordata + ' //expected data for previous vector'
261
+ @fail_count += 1
262
+ end
263
+ end
264
+
265
+ # initialize_pattern
266
+ # This method sets initializes variables at the start of a pattern.
267
+ # it is called automatically when pattern generation starts.
268
+ def initialize_pattern
269
+ @fail_count = 0
270
+ @vector_count = 0
271
+ @vector_batch.delete_if { true }
272
+ @store_pins_batch.clear
273
+ @comment_batch.clear
274
+ @pattern_link_messages.delete_if { true }
275
+ @pattern_comments.clear
276
+
277
+ @total_packets = 0
278
+ @total_comm_time = 0
279
+ @total_connect_time = 0
280
+ @total_xmit_time = 0
281
+ @total_recv_time = 0
282
+
283
+ if @pinmap.nil?
284
+ Origen.log.error('pinmap has not been setup, use tester.pinmap= to initialize a pinmap')
285
+ else
286
+ Origen.log.debug('executing pattern with pinmap:' + @pinmap.to_s)
287
+ end
288
+ end
289
+
290
+ # finalize_pattern
291
+ # This method flushes the final vector. Then, it logs success or failure of the
292
+ # pattern execution along with execution time information.
293
+ def finalize_pattern(output_file)
294
+ Origen.log.debug('Pattern generation completed. Sending all stored vector data')
295
+ synchronize(output_file)
296
+ send_cmd('', 'session_end')
297
+ # for debug, report communication times
298
+ Origen.log.debug("total communication time: #{@total_comm_time}")
299
+ Origen.log.debug("total connect time: #{@total_connect_time}")
300
+ Origen.log.debug("total transmit time: #{@total_xmit_time}")
301
+ Origen.log.debug("total receive time: #{@total_recv_time}")
302
+ Origen.log.debug("total packets: #{@total_packets}")
303
+ Origen.log.debug("total time per packet: #{@total_comm_time / @total_packets}")
304
+ Origen.log.debug("connect time per packet: #{@total_connect_time / @total_packets}")
305
+ Origen.log.debug("transmit time per packet: #{@total_xmit_time / @total_packets}")
306
+ Origen.log.debug("receive time per packet: #{@total_recv_time / @total_packets}")
307
+ Origen.log.debug("max packet time: #{@max_packet_time}")
308
+ Origen.log.debug("max duration command - #{@longest_packet}")
309
+ Origen.log.debug("max receive time: #{@max_receive_time}")
310
+ if @fail_count == 0
311
+ # Origen.log.success("PASS - pattern execution passed (#{@vector_count} vectors pass)")
312
+ Origen.app.stats.report_pass
313
+ else
314
+ # Origen.log.error("FAIL - pattern execution failed (#{@fail_count} failures)")
315
+ Origen.app.stats.report_fail
316
+ end
317
+ commands_file = Origen.app.current_job.output_file.split('.')[0] + '_link_cmds.txt'
318
+ File.open(commands_file, 'w') do |file|
319
+ file.puts("pin_assign:#{@pinmap}")
320
+ file.puts("pin_patternorder:#{@pinorder}")
321
+ @pattern_link_messages.each_index do |index|
322
+ file.puts(@pattern_link_messages[index])
323
+ file.puts(@pattern_comments[index]) if @pattern_comments.key?(index)
324
+ end
325
+ file.puts(':session_end')
326
+ end
327
+ end
328
+
329
+ # to_s
330
+ # returns 'Origen::VectorBased'
331
+ #
332
+ # This method at the moment is used for implementing code that runs only if the
333
+ # environment is set to link vector based. tester.link? will be used once the testers
334
+ # plug in supports the method link?.
335
+ def to_s
336
+ 'OrigenLink::VectorBased'
337
+ end
338
+
339
+ # transaction
340
+ # returns true/false indicating whether the transaction passed
341
+ # true = pass
342
+ # false = fail
343
+ #
344
+ # TODO: capture transaction vector data and response for use in debug
345
+ #
346
+ # if !tester.transaction {dut.reg blah blah}
347
+ # puts 'transaction failed'
348
+ # end
349
+ def transaction
350
+ if block_given?
351
+ synchronize
352
+ transaction_fail_count = @fail_count
353
+ yield
354
+ synchronize
355
+ transaction_fail_count = @fail_count - transaction_fail_count
356
+ if transaction_fail_count == 0
357
+ true
358
+ else
359
+ false
360
+ end
361
+ else
362
+ true
363
+ end
364
+ end
365
+ end
366
+ end