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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d1466528f6de1eb1b70731626991a685065ad6e0
4
- data.tar.gz: 06d3028a38164e75078b9865ec5a2ff63fb0b422
3
+ metadata.gz: 14d0facfcb04447ab5238b62f38ee31b4332e212
4
+ data.tar.gz: f68f21592acc3eb1dd48301cac3e220a742b789a
5
5
  SHA512:
6
- metadata.gz: 30db744c9d97bd49fe11988415c69b39ef9a71f14d54fb485209df8ca89247b7a2f52b1a917c93d74da167426d11dcb7a2a1d2da419e544e9bf1b40c94d6bcc2
7
- data.tar.gz: cb73f596dc2fdfd691b31722a232e67c9969b0346520e142aaf511cf289eabad94a65e3e029324d5cfad6ac510bdd8ce7c86ca09e1ff4013e7c09799583b5023
6
+ metadata.gz: e162fafd6a68753e03afb20a20cd6f779b7a25a5d50473711f83a9769955453c3e1259adfedd02a9b3c36f8077fc4d9823c68ed5f802b9a8ae8c049265070010
7
+ data.tar.gz: 8fd17ea6f4eb541a880e9c526d36d265ba3fdfc075e276bfd65b6f535f785a854b615b576df5f2467df791a23d57c27535eb912758bfec2c4e48ecf3930071ee
@@ -1,15 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
  $LOAD_PATH.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
3
+ $LOAD_PATH.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'config'))
3
4
  require 'socket'
4
5
  require 'origen_link/server/sequencer'
6
+ require 'version'
5
7
 
6
8
  server = TCPServer.open('', 12_777)
7
- puts 'server started'
8
9
  pinsequencer = OrigenLink::Server::Sequencer.new
10
+ pinsequencer.version = OrigenLink::VERSION
9
11
  remoteuser = ''
10
12
  remotehost = ''
11
13
  sessionactivity = Time.now
12
14
  sessionactive = false
15
+ puts "server version #{pinsequencer.version} started"
13
16
 
14
17
  loop do
15
18
  client = server.accept
data/config/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module OrigenLink
2
2
  MAJOR = 0
3
- MINOR = 2
3
+ MINOR = 3
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -11,6 +11,10 @@ module OrigenLink
11
11
  @pinmap = pinmap.gsub(/\s+/, '')
12
12
  response = send_cmd('pin_assign', @pinmap)
13
13
  setup_cmd_response_logger('pin_assign', response)
14
+ # store pins to the pinmap hash, this is used to remove non-link pins
15
+ # from the pattern in cases where the app includes too many pins
16
+ pinmap_arr = @pinmap.split(',')
17
+ 0.step(pinmap_arr.size - 1, 2) { |p| @pinmap_hash[pinmap_arr[p]] = true }
14
18
  end
15
19
 
16
20
  # pinorder=
@@ -24,9 +28,40 @@ module OrigenLink
24
28
  # example:
25
29
  # tester.pinorder = 'tclk,tms,tdi,tdo'
26
30
  def pinorder=(pinorder)
27
- @pinorder = pinorder.gsub(/\s+/, '')
28
- response = send_cmd('pin_patternorder', @pinorder)
29
- setup_cmd_response_logger('pin_patternorder', response)
31
+ cmd = []
32
+ cmd << 'pin_patternorder'
33
+ cmd << pinorder.gsub(/\s+/, '')
34
+ @pinorder = cmd[1]
35
+ if @pinmap.nil?
36
+ @batched_setup_cmds << cmd
37
+ else
38
+ response = send_cmd(cmd[0], @pinorder)
39
+ setup_cmd_response_logger(cmd[0], response)
40
+ end
41
+ end
42
+
43
+ # set_pinorder
44
+ # This method is called if the app has not explicitly set the pin order
45
+ # for the Link server using pinorder= (above)
46
+ #
47
+ # Origen.app.pin_pattern_order is read to get the pin pattern order
48
+ # and pass it to pinorder=
49
+ def set_pinorder
50
+ pinlist = ''
51
+ ordered_pins_cache.each do |pin|
52
+ unless pin.is_a?(Hash)
53
+ if pin.size == 1
54
+ pinlist = pinlist + ',' unless pinlist.length == 0
55
+ pinlist = pinlist + pin.name.to_s
56
+ else
57
+ dut.pins(pin.id).map.each do |sub_pin|
58
+ pinlist = pinlist + ',' unless pinlist.length == 0
59
+ pinlist = pinlist + sub_pin.name.to_s
60
+ end
61
+ end
62
+ end
63
+ end
64
+ self.pinorder = pinlist
30
65
  end
31
66
 
32
67
  # pinformat=
@@ -36,9 +71,16 @@ module OrigenLink
36
71
  # example:
37
72
  # tester.pinformat = 'func_25mhz,tclk,rl'
38
73
  def pinformat=(pinformat)
39
- @pinformat = replace_tset_name_w_number(pinformat.gsub(/\s+/, ''))
40
- response = send_cmd('pin_format', @pinformat)
41
- setup_cmd_response_logger('pin_format', response)
74
+ cmd = []
75
+ cmd << 'pin_format'
76
+ cmd << replace_tset_name_w_number(pinformat.gsub(/\s+/, ''))
77
+ @pinformat = cmd[1]
78
+ if @pinmap.nil?
79
+ @batched_setup_cmds << cmd
80
+ else
81
+ response = send_cmd(cmd[0], @pinformat)
82
+ setup_cmd_response_logger(cmd[0], response)
83
+ end
42
84
  end
43
85
 
44
86
  # pintiming=
@@ -51,9 +93,119 @@ module OrigenLink
51
93
  # example:
52
94
  # tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'
53
95
  def pintiming=(pintiming)
54
- @pintiming = replace_tset_name_w_number(pintiming.gsub(/\s+/, ''))
55
- response = send_cmd('pin_timing', @pintiming)
56
- setup_cmd_response_logger('pin_timing', response)
96
+ cmd = []
97
+ cmd << 'pin_timing'
98
+ cmd << replace_tset_name_w_number(pintiming.gsub(/\s+/, ''))
99
+ @pintiming = cmd[1]
100
+ if @pinmap.nil?
101
+ @batched_setup_cmds << cmd
102
+ else
103
+ response = send_cmd(cmd[0], @pintiming)
104
+ setup_cmd_response_logger(cmd[0], response)
105
+ end
106
+ end
107
+
108
+ # process_timeset(tset)
109
+ # This method will check the pin timing api for the current timeset.
110
+ # If the timset is programmed, it will be processed into the Link
111
+ # timing format, registered, and sent to the server.
112
+ # Else, a warning message will be displayed
113
+ #
114
+ # example generated command:
115
+ # send_cmd('pin_timingv2', '2,drive,5,data,tck;10,data,tdi|compare,35,data,tck,tdo;5,data,tdi')
116
+ def process_timeset(tset)
117
+ # Check to see if this timeset has been programmed
118
+ if dut.timesets(tset.to_sym).nil?
119
+ # Timset has not been programmed through the pin timing api
120
+ tset_warning(tset)
121
+ '' # return empty string on failure
122
+ else
123
+ # Timeset has been programmed
124
+ # accumulate and sort drive events
125
+ drive_str = tset_argstr_from_events(dut.timesets(tset.to_sym).drive_waves)
126
+
127
+ # accumulate and sort compare events
128
+ compare_str = tset_argstr_from_events(dut.timesets(tset.to_sym).compare_waves)
129
+
130
+ # construct the command argument string
131
+ argstr = get_tset_number(tset).to_s
132
+ if drive_str.length > 0
133
+ argstr = argstr + ',drive,' + drive_str
134
+ argstr = argstr + '|compare,' + compare_str if compare_str.length > 0
135
+ elsif compare_str.length > 0
136
+ argstr = argstr + ',compare,' + compare_str
137
+ else
138
+ fail "#{tset} timeset is programmed with no drive or compare edges"
139
+ end
140
+
141
+ # send the timeset information to the server
142
+ cmd = []
143
+ cmd << 'pin_timingv2'
144
+ cmd << argstr
145
+ if @pinmap.nil?
146
+ @batched_setup_cmds << cmd
147
+ else
148
+ response = send_cmd('pin_timingv2', argstr)
149
+ setup_cmd_response_logger('pin_timingv2', response)
150
+ end
151
+
152
+ # return the tset number from the tset hash
153
+ "tset#{@tsets_programmed[tset]},"
154
+ end
155
+ end
156
+
157
+ # tset_argstr_from_events(timing_waves)
158
+ # consume timing wave info and return command argstr format
159
+ # output: 10,data,tdi,tms;15,data,tck;25,0,tck;35,data,tms
160
+ def tset_argstr_from_events(waves)
161
+ event_time = []
162
+ event_setting = {}
163
+ event_pins = {}
164
+ waves.each do |w|
165
+ # skip any events wave that does not have any associated pins
166
+ unless w.pins.size == 0
167
+ w.evaluated_events.each do |e|
168
+ event_key = e[0].to_f # time stamp for the event
169
+ event_time << event_key
170
+ event_setting[event_key] = [] unless event_setting.key?(event_key)
171
+ event_setting[event_key] << e[1].to_s
172
+
173
+ event_pins[event_key] = [] unless event_pins.key?(event_key)
174
+ event_pins[event_key] << []
175
+ w.pins.each do |p|
176
+ event_pins[event_key].last << p.id.to_s if @pinmap_hash[p.id.to_s]
177
+ end
178
+ end
179
+ end
180
+ end
181
+ # now sort the events into time order and build the tset argstr
182
+ event_time.uniq!
183
+ event_time.sort!
184
+ rtnstr = ''
185
+ event_time.each do |event_key|
186
+ rtnstr = rtnstr + ';' unless rtnstr.length == 0
187
+ event_setting[event_key].each_index do |i|
188
+ pins = event_pins[event_key][i].uniq.join(',')
189
+ rtnstr = rtnstr + ';' if i > 0
190
+ rtnstr = rtnstr + event_key.to_s + ',' + event_setting[event_key][i] + ',' + pins if pins.length > 0
191
+ end
192
+ end
193
+ rtnstr.gsub(/;+/, ';')
194
+ end
195
+
196
+ # tset_warning(tset)
197
+ # This method is used to display a no timing info warning.
198
+ # The warning is displayed only once per tset that is
199
+ # encountered
200
+ def tset_warning(tset)
201
+ unless @tsets_warned.key?(tset)
202
+ Origen.log.warn("No timing information provided for timeset :#{tset}")
203
+ Origen.log.warn('Default timing will be used (pin operations are in pattern order)')
204
+ Origen.log.warn('Specify timing through the timing api or by using:')
205
+ Origen.log.warn(" tester.pinformat = 'func_25mhz,tclk,rl'")
206
+ Origen.log.warn(" tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'")
207
+ @tsets_warned[tset] = true
208
+ end
57
209
  end
58
210
 
59
211
  # replace_tset_name_w_number(csl)
@@ -2,11 +2,17 @@ require 'origen_link/server/pin'
2
2
 
3
3
  module OrigenLink
4
4
  module Server
5
+ # The Jtag class is not part of the OrigenLink plug-in/server ecosystem.
6
+ # It implements standard jtag protocol. It can be used to implement a
7
+ # Jtag protocol server (not included in this repository presently).
5
8
  class Jtag
9
+ # The value read from TDO during the shift
6
10
  attr_reader :tdoval
11
+ # Enable extra output
7
12
  attr_accessor :verbose_enable
8
13
  attr_accessor :anytdofail
9
14
 
15
+ # Create the jtag pin objects
10
16
  def initialize(tdiio = 16, tdoio = 23, tmsio = 19, tckio = 26, tck_period = 0.000001)
11
17
  @tdipin = Pin.new(tdiio, :out)
12
18
  @tdopin = Pin.new(tdoio, :in)
@@ -19,10 +25,12 @@ module OrigenLink
19
25
  @anytdofail = false
20
26
  end
21
27
 
28
+ # not needed, no need for wait states between operations
22
29
  def tck_period=(value)
23
30
  @tck_half_period = value / 2
24
31
  end
25
32
 
33
+ # close out file IO objects for the pins
26
34
  def destroy
27
35
  @tdipin.destroy
28
36
  @tdopin.destroy
@@ -34,6 +42,7 @@ module OrigenLink
34
42
  @tckpin = nil
35
43
  end
36
44
 
45
+ # perform 1 jtag cycle
37
46
  def do_cycle(tdival, tmsval, capturetdo = false)
38
47
  @tdipin.out(tdival)
39
48
  @tmspin.out(tmsval)
@@ -47,11 +56,13 @@ module OrigenLink
47
56
  @tckpin.out(0)
48
57
  end
49
58
 
59
+ # advance state machine to test logic reset, then return to run/test idle
50
60
  def do_tlr
51
61
  8.times { do_cycle(0, 1) }
52
62
  do_cycle(0, 0)
53
63
  end
54
64
 
65
+ # shift a value in on tdi, optionall capture tdo
55
66
  def do_shift(numbits, value, capturetdo = false, suppresscomments = false, tdocompare = '')
56
67
  @tdoval = 0
57
68
  @tdostr = ''
@@ -98,6 +109,7 @@ module OrigenLink
98
109
  end
99
110
  end
100
111
 
112
+ # perform an ir-update
101
113
  def do_ir(numbits, value, options = {})
102
114
  defaults = {
103
115
  capturetdo: false,
@@ -130,6 +142,7 @@ module OrigenLink
130
142
  do_cycle(0, 0)
131
143
  end
132
144
 
145
+ # perform a dr update
133
146
  def do_dr(numbits, value, options = {})
134
147
  defaults = {
135
148
  capturetdo: true,
@@ -160,6 +173,7 @@ module OrigenLink
160
173
  do_cycle(0, 0)
161
174
  end
162
175
 
176
+ # traverse the pause dr state
163
177
  def pause_dr
164
178
  do_cycle(0, 1)
165
179
  do_cycle(0, 0)
@@ -171,6 +185,7 @@ module OrigenLink
171
185
  do_cycle(0, 0)
172
186
  end
173
187
 
188
+ # traverse the pause ir state
174
189
  def pause_ir
175
190
  do_cycle(0, 1)
176
191
  pause_dr
@@ -5,20 +5,31 @@
5
5
 
6
6
  module OrigenLink
7
7
  module Server
8
+ # The server pin class is used to perform IO using the UDOO pins
8
9
  class Pin
9
10
  @@pin_setup = {
10
11
  in: 'in',
11
12
  out: 'out'
12
13
  }
13
14
 
15
+ # True if this pin exists in /sys/class/gpio after export. False otherwise.
14
16
  attr_reader :gpio_valid
17
+ # This pin's vector data for the pattern cycle being executed
18
+ attr_accessor :pattern_data
19
+ # This pin's index in the vector data received from the plug-in app
20
+ attr_accessor :pattern_index
21
+ # This pin's response for the executing vector
22
+ attr_accessor :response
15
23
 
16
- # initialize:
17
- # description - This method will execute system command
18
- # "sudo echo ionumber > /sys/class/gpio/export"
19
- # to create the IO file interface. It will
20
- # set the direction, initial pin state and initialize
21
- # instance variables
24
+ # Export the pin io files through the system and take control of the IO
25
+ #
26
+ # This method will execute system command
27
+ # "echo #{ionumber} > /sys/class/gpio/export"
28
+ # to create the IO file interface. It will
29
+ # set the direction, initial pin state and initialize
30
+ # instance variables
31
+ #
32
+ # Receives
22
33
  # ionumber - required, value indicating the pin number (BCM IO number,
23
34
  # not the header pin number)
24
35
  # direction - optional, specifies the pin direction. A pin is
@@ -49,8 +60,94 @@ module OrigenLink
49
60
  end
50
61
  @pin_val_obj = File.open(@pin_val_name, 'r+') if @gpio_valid
51
62
  end
63
+ @pattern_data = ''
64
+ @pattern_index = -1
65
+ @response = 'W'
66
+ @cycle_failure = false
67
+ @data_is_drive = false
68
+ end
69
+
70
+ # data_is_drive?
71
+ # returns whether the current pattern data is drive
72
+ def data_is_drive?
73
+ @data_is_drive
74
+ end
75
+
76
+ # data_is_compare?
77
+ # returns whether the current pattern data is compare
78
+ def data_is_compare?
79
+ !@data_is_drive
52
80
  end
53
81
 
82
+ # cycle_failure
83
+ # returns a boolean indicating pass/fail status of this pin
84
+ def cycle_failure
85
+ if @response == 'W'
86
+ true # force failure if no operation performed
87
+ else
88
+ @cycle_failure
89
+ end
90
+ end
91
+
92
+ # load_pattern_data
93
+ # Grab this pin's data character from the pattern data
94
+ def load_pattern_data(cycle)
95
+ if @pattern_index > -1
96
+ @pattern_data = cycle[@pattern_index]
97
+ @response = 'W'
98
+ @cycle_failure = false
99
+ if @pattern_data == '1' || @pattern_data == '0'
100
+ @data_is_drive = true
101
+ else
102
+ @data_is_drive = false
103
+ end
104
+ else
105
+ @gpio_valid = false
106
+ end
107
+ end
108
+
109
+ # process_event(event)
110
+ # perform the requested pin operation and update the response (if required)
111
+ def process_event(operation, requested_action)
112
+ if operation == :drive
113
+ if data_is_drive?
114
+ if requested_action == 'data'
115
+ out(@pattern_data)
116
+ @response = @pattern_data
117
+ else
118
+ out(requested_action)
119
+ end # requested_action == 'data'
120
+ end # data_is_drive?
121
+ end # operation == :drive
122
+ if operation == :compare
123
+ if data_is_compare?
124
+ if requested_action == 'data'
125
+ case self.in
126
+ when '0'
127
+ @cycle_failure = true if @pattern_data == 'H'
128
+ if @pattern_data == 'X'
129
+ @response = '.'
130
+ else
131
+ @response = 'L'
132
+ end
133
+ # end of when '0'
134
+ when '1'
135
+ @cycle_failure = true if @pattern_data == 'L'
136
+ if @pattern_data == 'X'
137
+ @response = '`'
138
+ else
139
+ @response = 'H'
140
+ end
141
+ # end of when '1'
142
+ else
143
+ @response = 'W'
144
+ end # case
145
+ end # requested_action == 'data'
146
+ end # data_is_compare?
147
+ end # operation == :compare
148
+ end
149
+
150
+ # Close the file IO objects associated with this pin
54
151
  def destroy
55
152
  if @gpio_valid
56
153
  @pin_dir_obj.close
@@ -60,10 +157,10 @@ module OrigenLink
60
157
  end
61
158
  end
62
159
 
63
- # out:
64
- # description - Sets the output state of the pin. If the pin
65
- # is setup as an input, the direction will first
66
- # be changed to output.
160
+ # Sets the output state of the pin.
161
+ #
162
+ # If the pin is setup as an input,
163
+ # the direction will first be changed to output.
67
164
  #
68
165
  def out(value)
69
166
  if @gpio_valid
@@ -75,10 +172,10 @@ module OrigenLink
75
172
  end
76
173
  end
77
174
 
78
- # in:
79
- # description - Reads and returns state of the pin. If the pin
80
- # is setup as an output, the direction will first
81
- # be changed to input.
175
+ # Reads and returns state of the pin.
176
+ #
177
+ # If the pin is setup as an output, the direction will first
178
+ # be changed to input.
82
179
  #
83
180
  def in
84
181
  if @gpio_valid
@@ -95,11 +192,10 @@ module OrigenLink
95
192
  end
96
193
  end
97
194
 
98
- # update_direction:
99
- # description - Sets the pin direction
195
+ # Sets the pin direction
100
196
  #
101
- # direction - specifies the pin direction. A pin is
102
- # initialized as an input if a direction isn't specified.
197
+ # Receives:
198
+ # direction - specifies the pin direction. Input is default.
103
199
  #
104
200
  # Valid direction values:
105
201
  # :in - input
@@ -113,6 +209,7 @@ module OrigenLink
113
209
  end
114
210
  end
115
211
 
212
+ # Returns 'OrigenLinPin' + io number
116
213
  def to_s
117
214
  'OrigenLinkPin' + @ionumber.to_s
118
215
  end