origen_link 0.4.2 → 0.4.3

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,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