origen_link 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -34,6 +34,11 @@ require 'origen_link/server/pin'
34
34
  # timing is stored in a timeset hash
35
35
  # first argument is the timeset key
36
36
  # ex: "pin_timing:1,tdi,0,tdo,1,tms,0
37
+ #
38
+ # version (check version of app server is
39
+ # running)
40
+ # ex: "version:"
41
+ # response ex: "P:0.2.0.pre0"
37
42
  ##################################################
38
43
  module OrigenLink
39
44
  module Server
@@ -45,10 +50,50 @@ module OrigenLink
45
50
  @gpio_dir || '/sys/class/gpio'
46
51
  end
47
52
 
53
+ ##################################################
54
+ # OrigenLink::Server::Sequencer Class
55
+ #
56
+ # This class processes messages targeted for
57
+ # pin sequencer interface (vector pattern
58
+ # execution).
59
+ #
60
+ # Supported messages:
61
+ # pin_assign (create pin mapping)
62
+ # ex: "pin_assign:tck,3,extal,23,tdo,5"
63
+ #
64
+ # pin_patternorder (define vector pin order)
65
+ # ex: "pin_patternorder:tdo,extal,tck"
66
+ #
67
+ # pin_cycle (execute vector data)
68
+ # ex: "pin_cycle:H11"
69
+ #
70
+ # pin_clear (clear all setup information)
71
+ # ex: "pin_clear:"
72
+ #
73
+ # pin_format (setup a pin with return format)
74
+ # first argument is the timeset
75
+ # ex: "pin_format:1,tck,rl"
76
+ #
77
+ # pin_timing (define when pin events happen)
78
+ # timing is stored in a timeset hash
79
+ # first argument is the timeset key
80
+ # ex: "pin_timing:1,tdi,0,tdo,1,tms,0
81
+ #
82
+ # version (check version of app server is
83
+ # running)
84
+ # ex: "version:"
85
+ # response ex: "P:0.2.0.pre0"
86
+ ##################################################
48
87
  class Sequencer
88
+ # code version of the server (populated by start_link_server)
89
+ attr_accessor :version
90
+ # hash holding the pinmap ('name' => pin object)
49
91
  attr_reader :pinmap
92
+ # array of pin names in pattern order
50
93
  attr_reader :patternorder
94
+ # hash holding programmed time set information
51
95
  attr_reader :cycletiming
96
+ # hash holding pin pattern order ('name' => index)
52
97
  attr_reader :patternpinindex
53
98
 
54
99
  ##################################################
@@ -61,6 +106,7 @@ module OrigenLink
61
106
  @patternpinindex = Hash.new(-1)
62
107
  @patternorder = []
63
108
  @cycletiming = Hash.new(-1)
109
+ @version = ''
64
110
  end
65
111
 
66
112
  ##################################################
@@ -90,6 +136,10 @@ module OrigenLink
90
136
  pin_format(command[1])
91
137
  when 'pin_timing'
92
138
  pin_timing(command[1])
139
+ when 'pin_timingv2'
140
+ pin_timingv2(command[1])
141
+ when 'version'
142
+ "P:#{@version}"
93
143
  else
94
144
  'Error Invalid command: ' + command[0].to_s
95
145
  end
@@ -126,13 +176,89 @@ module OrigenLink
126
176
  end
127
177
  end
128
178
 
179
+ ########################################################
180
+ # pin_timingv2 method
181
+ # arguments: <args> from the message request
182
+ # Should be '1,drive,5,pin,10,pin2,|compare,0,pin3'
183
+ # First integer is timeset number
184
+ #
185
+ # returns "P:" or error message
186
+ #
187
+ # This method sets up a time set. Any arbitrary
188
+ # waveform can be generated
189
+ #
190
+ ########################################################
191
+ def pin_timingv2(args)
192
+ # get the tset number
193
+ argarr = args.split(',')
194
+ tset_key = argarr.delete_at(0).to_i
195
+ new_timeset(tset_key)
196
+ args = argarr.join(',')
197
+
198
+ invalid_pins = []
199
+
200
+ # process and load the timeset
201
+ waves = args.split('|')
202
+ waves.each do |w|
203
+ argarr = w.split(',')
204
+ wave_type = argarr.delete_at(0)
205
+ event_data_key = wave_type + '_event_data'
206
+ event_pins_key = wave_type + '_event_pins'
207
+ w = argarr.join(',')
208
+ events = w.split(';')
209
+ events.each do |e|
210
+ argarr = e.split(',')
211
+ event_key = argarr.delete_at(0).to_f
212
+ @cycletiming[tset_key]['events'] << event_key
213
+ @cycletiming[tset_key][event_data_key][event_key] = [] unless @cycletiming[tset_key][event_data_key].key?(event_key)
214
+ @cycletiming[tset_key][event_data_key][event_key] << argarr.delete_at(0)
215
+ # now load the pins for this event
216
+ @cycletiming[tset_key][event_pins_key][event_key] = [] unless @cycletiming[tset_key][event_pins_key].key?(event_key)
217
+ @cycletiming[tset_key][event_pins_key][event_key] << []
218
+ argarr.each do |pin|
219
+ if @pinmap.key?(pin)
220
+ @cycletiming[tset_key][event_pins_key][event_key].last << @pinmap[pin]
221
+ else
222
+ invalid_pins << pin
223
+ end
224
+ end # of argarr.each
225
+ end # of events.each
226
+ end # of waves.each
227
+ @cycletiming[tset_key]['events'].uniq!
228
+ @cycletiming[tset_key]['events'].sort!
229
+
230
+ # return result
231
+ if invalid_pins.size > 0
232
+ 'F:Invalid pins (not in pinmap): ' + invalid_pins.join(', ')
233
+ else
234
+ 'P:'
235
+ end
236
+ end # of def pin_timingv2
237
+
129
238
  ##################################################
130
239
  # new_timeset(tset)
131
240
  # creates a new empty timeset hash
241
+ #
242
+ # timing format:
243
+ # ['events'] = [0, 5, 10, 35]
244
+ # ['drive_event_data'] = {
245
+ # 0: ['data']
246
+ # 10: ['data','0']
247
+ # 35: ['0']
248
+ # }
249
+ # ['drive_event_pins'] = {
250
+ # 0: [[pin_obj1, pin_obj2]]
251
+ # 10: [[pin1,pin2], [pin3]]
252
+ # etc.
253
+ # }
132
254
  ##################################################
133
255
  def new_timeset(tset)
134
256
  @cycletiming[tset] = {}
135
- @cycletiming[tset]['timing'] = [[], [], []]
257
+ @cycletiming[tset]['events'] = []
258
+ @cycletiming[tset]['drive_event_data'] = {}
259
+ @cycletiming[tset]['drive_event_pins'] = {}
260
+ @cycletiming[tset]['compare_event_data'] = {}
261
+ @cycletiming[tset]['compare_event_pins'] = {}
136
262
  end
137
263
 
138
264
  ##################################################
@@ -146,11 +272,24 @@ module OrigenLink
146
272
  argarr = args.split(',')
147
273
  tset_key = argarr.delete_at(0).to_i
148
274
  new_timeset(tset_key) unless @cycletiming.key?(tset_key)
149
- @cycletiming[tset_key].delete('rl')
150
- @cycletiming[tset_key].delete('rh')
275
+ @cycletiming[tset_key]['events'] += [1, 3]
276
+ @cycletiming[tset_key]['events'].sort!
277
+ [1, 3].each do |event|
278
+ @cycletiming[tset_key]['drive_event_pins'][event] = [[]]
279
+ end
280
+ @cycletiming[tset_key]['compare_event_data'][1] = ['data']
151
281
  0.step(argarr.length - 2, 2) do |index|
152
- @cycletiming[tset_key][argarr[index + 1]] = [] unless @cycletiming[tset_key].key?(argarr[index + 1])
153
- @cycletiming[tset_key][argarr[index + 1]] << argarr[index]
282
+ drive_type = argarr[index + 1]
283
+ pin_name = argarr[index]
284
+ @cycletiming[tset_key]['drive_event_data'][1] = ['data']
285
+ @cycletiming[tset_key]['drive_event_pins'][1][0] << @pinmap[pin_name]
286
+ @cycletiming[tset_key]['drive_event_pins'][3][0] << @pinmap[pin_name]
287
+ @cycletiming[tset_key]['compare_event_pins'][1] = [[@pinmap[pin_name]]]
288
+ if drive_type == 'rl'
289
+ @cycletiming[tset_key]['drive_event_data'][3] = ['0']
290
+ else
291
+ @cycletiming[tset_key]['drive_event_data'][3] = ['1']
292
+ end
154
293
  end
155
294
  'P:'
156
295
  end
@@ -173,16 +312,41 @@ module OrigenLink
173
312
  # format pins are driven between 0 and 1 and
174
313
  # return between 1 and 2. Non-return pins are
175
314
  # acted upon during the 0, 1 or 2 time period.
315
+ #
176
316
  ##################################################
177
317
  def pin_timing(args)
178
318
  argarr = args.split(',')
179
319
  tset_key = argarr.delete_at(0).to_i
180
320
  new_timeset(tset_key) unless @cycletiming.key?(tset_key)
181
- @cycletiming[tset_key]['timing'].each do |index|
182
- index.delete_if { true }
321
+ [0, 2, 4].each do |event|
322
+ @cycletiming[tset_key]['drive_event_pins'][event] = [[]]
323
+ @cycletiming[tset_key]['compare_event_pins'][event] = [[]]
183
324
  end
325
+
326
+ # process the information received
184
327
  0.step(argarr.length - 2, 2) do |index|
185
- @cycletiming[tset_key]['timing'][argarr[index + 1].to_i] << argarr[index]
328
+ event = argarr[index + 1].to_i
329
+ # reorder event number to allow rising/falling edges
330
+ event *= 2
331
+ pin_name = argarr[index]
332
+ @cycletiming[tset_key]['events'] << event
333
+ @cycletiming[tset_key]['drive_event_data'][event] = ['data']
334
+ @cycletiming[tset_key]['drive_event_pins'][event][0] << @pinmap[pin_name]
335
+ @cycletiming[tset_key]['compare_event_data'][event] = ['data']
336
+ @cycletiming[tset_key]['compare_event_pins'][event][0] << @pinmap[pin_name]
337
+ end
338
+
339
+ # remove events with no associated pins
340
+ @cycletiming[tset_key]['events'].uniq!
341
+ @cycletiming[tset_key]['events'].sort!
342
+ [0, 2, 4].each do |event|
343
+ if @cycletiming[tset_key]['drive_event_pins'][event][0].size == 0
344
+ @cycletiming[tset_key]['events'] -= [event]
345
+ @cycletiming[tset_key]['drive_event_data'].delete(event)
346
+ @cycletiming[tset_key]['drive_event_pins'].delete(event)
347
+ @cycletiming[tset_key]['compare_event_data'].delete(event)
348
+ @cycletiming[tset_key]['compare_event_pins'].delete(event)
349
+ end
186
350
  end
187
351
  'P:'
188
352
  end
@@ -198,15 +362,18 @@ module OrigenLink
198
362
  def pin_patternorder(args)
199
363
  argarr = args.split(',')
200
364
  index = 0
201
- if @cycletiming.key?(0)
202
- @cycletiming[0]['timing'][0].delete_if { true }
203
- else
204
- new_timeset(0)
205
- end
365
+ new_timeset(0)
206
366
  argarr.each do |pin|
207
367
  @patternorder << pin
208
- @patternpinindex[pin] = index
209
- @cycletiming[0]['timing'][0] << pin
368
+ @pinmap[pin].pattern_index = index # pattern index stored in pin object now
369
+ @patternpinindex[pin] = index # to be removed
370
+
371
+ # define default timing
372
+ @cycletiming[0]['events'] << index
373
+ @cycletiming[0]['drive_event_data'][index] = ['data']
374
+ @cycletiming[0]['drive_event_pins'][index] = [[@pinmap[pin]]]
375
+ @cycletiming[0]['compare_event_data'][index] = ['data']
376
+ @cycletiming[0]['compare_event_pins'][index] = [[@pinmap[pin]]]
210
377
  index += 1
211
378
  end
212
379
  'P:'
@@ -222,6 +389,7 @@ module OrigenLink
222
389
  # sequenced. Each pin object and pin data
223
390
  # is passed to the "process_pindata" method
224
391
  # for decoding and execution
392
+ #
225
393
  ##################################################
226
394
  def pin_cycle(args)
227
395
  # set default repeats and timeset
@@ -240,108 +408,48 @@ module OrigenLink
240
408
  end
241
409
 
242
410
  message = ''
243
- pindata = args.split('')
244
- @cycle_failure = false
411
+ # load pattern cycle data into pin objects
412
+ @pinmap.each_value { |p| p.load_pattern_data(args) }
413
+ cycle_failure = false
414
+
245
415
  0.upto(repeat_count - 1) do |count|
246
- response = {}
247
- # process time 0 events
248
- response = process_events(@cycletiming[tset]['timing'][0], pindata)
249
- # send drive data for return format pins
250
- response = (process_events(@cycletiming[tset]['rl'], pindata)).merge(response)
251
- response = (process_events(@cycletiming[tset]['rh'], pindata)).merge(response)
252
- # process time 1 events
253
- response = process_events(@cycletiming[tset]['timing'][1], pindata).merge(response)
254
- # send return data
255
- unless @cycletiming[tset]['rl'].nil?
256
- @cycletiming[tset]['rl'].each do |pin|
257
- process_pindata(@pinmap[pin], '0')
416
+ # process timing events
417
+ @cycletiming[tset]['events'].each do |event|
418
+ # process drive events
419
+ if @cycletiming[tset]['drive_event_pins'].key?(event)
420
+ @cycletiming[tset]['drive_event_pins'][event].each_index do |i|
421
+ @cycletiming[tset]['drive_event_pins'][event][i].each do |p|
422
+ p.process_event(:drive, @cycletiming[tset]['drive_event_data'][event][i])
423
+ end
424
+ end
258
425
  end
259
- end
260
- unless @cycletiming[tset]['rh'].nil?
261
- @cycletiming[tset]['rh'].each do |pin|
262
- process_pindata(@pinmap[pin], '1')
426
+
427
+ # process compare events
428
+ if @cycletiming[tset]['compare_event_pins'].key?(event)
429
+ @cycletiming[tset]['compare_event_pins'][event].each_index do |i|
430
+ @cycletiming[tset]['compare_event_pins'][event][i].each do |p|
431
+ p.process_event(:compare, @cycletiming[tset]['compare_event_data'][event][i])
432
+ end
433
+ end
263
434
  end
435
+ end # event
436
+
437
+ # build response message
438
+ message += ' ' unless count == 0
439
+
440
+ @patternorder.each do |p|
441
+ message += @pinmap[p].response
442
+ cycle_failure = true if @pinmap[p].cycle_failure
264
443
  end
265
- # process time 2 events
266
- response = process_events(@cycletiming[tset]['timing'][2], pindata).merge(response)
267
- # changing response format to return all data for easier debug, below is original method
268
- # TODO: remove the commented code once return format and delay handling is finalized
269
- # if (count == 0) || (@cycle_failure)
270
- # message = ''
271
- # @patternorder.each do |pin|
272
- # message += response[pin]
273
- # end
274
- # end
275
- message = message + ' ' unless count == 0
276
- @patternorder.each do |pin|
277
- message += response[pin]
278
- end
279
- end # end cycle through repeats
280
- if @cycle_failure
444
+ end # count
445
+ if cycle_failure
281
446
  rtnmsg = 'F:' + message + ' Expected:' + args
282
447
  else
283
448
  rtnmsg = 'P:' + message
284
449
  end
285
- # no need to return repeat count since all data is returned
286
- # TODO: remove the commented code once return format and delay handling is finalized
287
- # rtnmsg += ' Repeat ' + repeat_count.to_s if repeat_count > 1
288
450
  rtnmsg
289
451
  end
290
452
 
291
- ##################################################
292
- # process_events
293
- # used by pin_cycle to avoid duplicating code
294
- ##################################################
295
- def process_events(events, pindata)
296
- response = {}
297
- unless events.nil?
298
- events.each do |pin|
299
- response[pin] = process_pindata(@pinmap[pin], pindata[@patternpinindex[pin]])
300
- end
301
- end
302
- response
303
- end
304
-
305
- ##################################################
306
- # process_pindata method
307
- # arguments:
308
- # pin: the pin object to be operated on
309
- # data: the pin data to be executed
310
- # returns: the drive data or read data
311
- #
312
- # This method translates pin data into one
313
- # of three possible events. Drive 0, drive 1
314
- # or read. Supported character decode:
315
- # drive 0: '0'
316
- # drive 1: '1'
317
- # read: anything else
318
- ##################################################
319
- def process_pindata(pin, data)
320
- if data == '0' || data == '1'
321
- pin.out(data)
322
- data
323
- else
324
- case pin.in
325
- when '0'
326
- @cycle_failure = true if data == 'H'
327
- if data == 'X'
328
- '.'
329
- else
330
- 'L'
331
- end
332
- when '1'
333
- @cycle_failure = true if data == 'L'
334
- if data == 'X'
335
- '`'
336
- else
337
- 'H'
338
- end
339
- else
340
- 'W'
341
- end
342
- end
343
- end
344
-
345
453
  ##################################################
346
454
  # pin_clear method
347
455
  #
@@ -1,5 +1,7 @@
1
1
  module OrigenLink
2
2
  module ServerCom
3
+ # send a single command to the server
4
+ #
3
5
  # send_cmd(cmdstr, argstr)
4
6
  # cmdstr is a valid command. <category>_<command>
5
7
  # Ex: 'pin_assign'
@@ -72,6 +74,7 @@ module OrigenLink
72
74
  response # ensure the response is passed along
73
75
  end
74
76
 
77
+ # Send the stored batch of vectors to the server
75
78
  def send_batch(vector_batch)
76
79
  vector_batch_str = @user_name + "\n" + vector_batch.join("\n") + "\n\n"
77
80
  user_status = ''
@@ -124,7 +127,8 @@ module OrigenLink
124
127
  response
125
128
  end
126
129
 
127
- # setup_cmd_response_logger
130
+ # Handle a server response (inform of Failures)
131
+ #
128
132
  # There are several setup commands that initialize the debugger device with
129
133
  # information about how to interact with the dut. All of the setup commands
130
134
  # return pass or fail. This method exists so that the code doesn't have to
@@ -15,10 +15,10 @@ module OrigenLink
15
15
  invalid_pin_number_test: false,
16
16
  missing_pinmap_test: false
17
17
  }.merge(options)
18
- add_pin :tclk
19
- add_pin :tdi
20
- add_pin :tdo
21
- add_pin :tms
18
+ add_pin :tclk, meta: { link_io: 119 }
19
+ add_pin :tdi, meta: { link_io: 116 }
20
+ add_pin :tdo, meta: { link_io: 124 }
21
+ add_pin :tms, meta: { link_io: 6 }
22
22
  add_pin :resetb
23
23
  add_pins :port_a, size: 8
24
24
 
@@ -31,7 +31,7 @@ module OrigenLink
31
31
  else
32
32
  tester.pinmap = 'tclk,119,tms,6,tdi,116,tdo,124' unless options[:missing_pinmap_test]
33
33
  end
34
- tester.pinorder = 'tclk,tms,tdi,tdo'
34
+ # tester.pinorder = 'tclk,tms,tdi,tdo'
35
35
  end
36
36
  end
37
37