origen_link 0.2.0 → 0.3.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.
@@ -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