origen_link 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,236 +1,236 @@
1
- module OrigenLink
2
- module ConfigurationCommands
3
- # pinmap=
4
- # This method is used to setup the pin map on the debugger device.
5
- # The argument should be a string with <pin name>, <gpio #>, <pin name>
6
- # <gpio #>, etc
7
- #
8
- # example:
9
- # tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
10
- def pinmap=(pinmap)
11
- @pinmap = pinmap.gsub(/\s+/, '')
12
- response = send_cmd('pin_assign', @pinmap)
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 }
18
- end
19
-
20
- # pinorder=
21
- # This method is used to setup the pin order on the debugger device.
22
- # The pin order will indicate the order that pin data appears in vector
23
- # data.
24
- #
25
- # This is a duplicate of pattern_pin_order and can be handled behind the
26
- # scenes in the future.
27
- #
28
- # example:
29
- # tester.pinorder = 'tclk,tms,tdi,tdo'
30
- def pinorder=(pinorder)
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
65
- end
66
-
67
- # pinformat=
68
- # This method is used to setup the pin clock format on the debugger device.
69
- # The supported formats are rl and rh
70
- #
71
- # example:
72
- # tester.pinformat = 'func_25mhz,tclk,rl'
73
- def pinformat=(pinformat)
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
84
- end
85
-
86
- # pintiming=
87
- # This method is used to setup the pin timing on the debugger device.
88
- # Timing is relative to the rise and fall of a clock
89
- #
90
- # timing value: 0 1 2
91
- # clock waveform: ___/***\___
92
- #
93
- # example:
94
- # tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'
95
- def pintiming=(pintiming)
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
209
- end
210
-
211
- # replace_tset_name_w_number(csl)
212
- # This method is used by pinformat= and pintiming=
213
- # This method receives a comma separated list of arguments
214
- # the first of which is a timeset name. A comma
215
- # separated list is returned with the timeset name replaced
216
- # by it's lookup number. If it is a new timset, a lookup
217
- # number is associated with the name.
218
- def replace_tset_name_w_number(csl)
219
- args = csl.split(',')
220
- args[0] = get_tset_number(args[0])
221
- args.join(',')
222
- end
223
-
224
- # get_tset_number(name)
225
- # This method returns the test number associated with the
226
- # passed in tset name. If the name is unknown a new lookup
227
- # number is returned.
228
- def get_tset_number(name)
229
- unless @tsets_programmed.key?(name)
230
- @tsets_programmed[name] = @tset_count
231
- @tset_count += 1
232
- end
233
- @tsets_programmed[name]
234
- end
235
- end
236
- end
1
+ module OrigenLink
2
+ module ConfigurationCommands
3
+ # pinmap=
4
+ # This method is used to setup the pin map on the debugger device.
5
+ # The argument should be a string with <pin name>, <gpio #>, <pin name>
6
+ # <gpio #>, etc
7
+ #
8
+ # example:
9
+ # tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
10
+ def pinmap=(pinmap)
11
+ @pinmap = pinmap.gsub(/\s+/, '')
12
+ response = send_cmd('pin_assign', @pinmap)
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 }
18
+ end
19
+
20
+ # pinorder=
21
+ # This method is used to setup the pin order on the debugger device.
22
+ # The pin order will indicate the order that pin data appears in vector
23
+ # data.
24
+ #
25
+ # This is a duplicate of pattern_pin_order and can be handled behind the
26
+ # scenes in the future.
27
+ #
28
+ # example:
29
+ # tester.pinorder = 'tclk,tms,tdi,tdo'
30
+ def pinorder=(pinorder)
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
65
+ end
66
+
67
+ # pinformat=
68
+ # This method is used to setup the pin clock format on the debugger device.
69
+ # The supported formats are rl and rh
70
+ #
71
+ # example:
72
+ # tester.pinformat = 'func_25mhz,tclk,rl'
73
+ def pinformat=(pinformat)
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
84
+ end
85
+
86
+ # pintiming=
87
+ # This method is used to setup the pin timing on the debugger device.
88
+ # Timing is relative to the rise and fall of a clock
89
+ #
90
+ # timing value: 0 1 2
91
+ # clock waveform: ___/***\___
92
+ #
93
+ # example:
94
+ # tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'
95
+ def pintiming=(pintiming)
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
209
+ end
210
+
211
+ # replace_tset_name_w_number(csl)
212
+ # This method is used by pinformat= and pintiming=
213
+ # This method receives a comma separated list of arguments
214
+ # the first of which is a timeset name. A comma
215
+ # separated list is returned with the timeset name replaced
216
+ # by it's lookup number. If it is a new timset, a lookup
217
+ # number is associated with the name.
218
+ def replace_tset_name_w_number(csl)
219
+ args = csl.split(',')
220
+ args[0] = get_tset_number(args[0])
221
+ args.join(',')
222
+ end
223
+
224
+ # get_tset_number(name)
225
+ # This method returns the test number associated with the
226
+ # passed in tset name. If the name is unknown a new lookup
227
+ # number is returned.
228
+ def get_tset_number(name)
229
+ unless @tsets_programmed.key?(name)
230
+ @tsets_programmed[name] = @tset_count
231
+ @tset_count += 1
232
+ end
233
+ @tsets_programmed[name]
234
+ end
235
+ end
236
+ end