origen_link 0.1.0.pre0

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.
@@ -0,0 +1,254 @@
1
+ module OrigenLink
2
+ # OrigenLink::VectorBased
3
+ # This class is meant to be used for live silicon debug. Vector data that Origen
4
+ # generates is intercepted and sent to a debug device (typically will be a Udoo
5
+ # Neo - www.udoo.org). The debug device can be any device that is able to serve
6
+ # a TCP socket, recieve and interpret the command set used by this class and send
7
+ # the expected responses.
8
+ #
9
+ # Integration instructions
10
+ # Set the pin map (must be done first) and pin order
11
+ # if tester.link?
12
+ # tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
13
+ # tester.pinorder = 'tclk,tms,tdi,tdo'
14
+ # end
15
+ #
16
+ # Set Origen to only generate vectors for pins in the pinmap (order should match)
17
+ # pin_pattern_order :tclk, :tms, :tdi, :tdo, only: true if tester.link?
18
+ #
19
+ # At the beginning of the Startup method add this line
20
+ # tester.initialize_pattern if tester.link?
21
+ #
22
+ # At the end of the Shutdown method add this line
23
+ # tester.finalize_pattern if tester.link?
24
+ #
25
+ # Create a link environment with the IP address and socket number of a link server
26
+ # $tester = OrigenLink::VectorBased.new('192.168.0.2', 12777)
27
+ class VectorBased
28
+ # include OrigenTesters::VectorBasedTester
29
+
30
+ # these attributes are exposed for testing purposes, a user would not need to read them
31
+ attr_reader :fail_count, :vector_count, :total_comm_time, :total_connect_time, :total_xmit_time, :total_recv_time, :total_packets, :vector_repeatcount, :tsets_programmed
32
+
33
+ def initialize(address, port)
34
+ @address = address
35
+ @port = port
36
+ @fail_count = 0
37
+ @vector_count = 0
38
+ @previous_vectordata = ''
39
+ @previous_tset = ''
40
+ @vector_repeatcount = 0
41
+ @total_comm_time = 0
42
+ @total_connect_time = 0
43
+ @total_xmit_time = 0
44
+ @total_recv_time = 0
45
+ @total_packets = 0
46
+ @max_packet_time = 0
47
+ @max_receive_time = 0
48
+ @tsets_programmed = {}
49
+ @tset_count = 1
50
+ end
51
+
52
+ # push_vector
53
+ # This method intercepts vector data from Origen, removes white spaces and compresses repeats
54
+ def push_vector(options)
55
+ programmed_data = options[:pin_vals].gsub(/\s+/, '')
56
+ tset = options[:timeset].name
57
+ if @vector_count > 0
58
+ # compressing repeats as we go
59
+ if (programmed_data == @previous_vectordata) && (@previous_tset == tset)
60
+ @vector_repeatcount += 1
61
+ else
62
+ # all repeats of the previous vector have been counted
63
+ # time to flush. Don't panic though! @previous_vectordata
64
+ # is what gets flushed. programmed_data is passed as an
65
+ # arg to be set as the new @previous_vectordata
66
+ flush_vector(programmed_data, tset)
67
+ end
68
+ else
69
+ # if this is the first vector of the pattern, insure variables are initialized
70
+ @previous_vectordata = programmed_data
71
+ @previous_tset = tset
72
+ @vector_repeatcount = 1
73
+ end # if vector_count > 0
74
+ @vector_count += 1
75
+ end
76
+
77
+ # flush_vector
78
+ # Just as the name suggests, this method "flushes" a vector. This is necessary because
79
+ # of repeat compression (a vector isn't sent until different vector data is encountered)
80
+ #
81
+ # Don't forget to flush when you're in debug mode. Otherwise, the last vector of a
82
+ # write command won't be sent to the server.
83
+ def flush_vector(programmed_data = '', tset = '')
84
+ if @vector_repeatcount > 1
85
+ repeat_prefix = "repeat#{@vector_repeatcount},"
86
+ else
87
+ repeat_prefix = ''
88
+ end
89
+ if @tsets_programmed[@previous_tset]
90
+ tset_prefix = "tset#{@tsets_programmed[@previous_tset]},"
91
+ else
92
+ tset_prefix = ''
93
+ end
94
+ response = send_cmd('pin_cycle', tset_prefix + repeat_prefix + @previous_vectordata)
95
+ microcode response
96
+ unless response.chr == 'P'
97
+ microcode 'E:' + @previous_vectordata + ' //expected data for previous vector'
98
+ @fail_count += 1
99
+ end
100
+ @vector_repeatcount = 1
101
+ @previous_vectordata = programmed_data
102
+ @previous_tset = tset
103
+ end
104
+
105
+ # initialize_pattern
106
+ # At some point in the future this intialization should be done behind the
107
+ # scenes without requiring the user to add code to the controller.
108
+ #
109
+ # This method sets initializes variables at the start of a pattern.
110
+ # it should be called from the Startup method of the dut controller.
111
+ def initialize_pattern
112
+ @fail_count = 0
113
+ @vector_count = 0
114
+
115
+ @total_packets = 0
116
+ @total_comm_time = 0
117
+ @total_connect_time = 0
118
+ @total_xmit_time = 0
119
+ @total_recv_time = 0
120
+
121
+ if @pinmap.nil?
122
+ Origen.log.error('pinmap has not been setup, use tester.pinmap= to initialize a pinmap')
123
+ else
124
+ Origen.log.info('executing pattern with pinmap:' + @pinmap.to_s)
125
+ end
126
+ end
127
+
128
+ # finalize_pattern
129
+ # At some point in the future this finalization should be done behind the scenes.
130
+ #
131
+ # This method flushes the final vector. Then, it logs success or failure of the
132
+ # pattern execution along with execution time information.
133
+ def finalize_pattern(programmed_data = '')
134
+ flush_vector(programmed_data)
135
+ if @fail_count == 0
136
+ Origen.log.success("PASS - pattern execution passed (#{@vector_count} vectors pass)")
137
+ else
138
+ Origen.log.error("FAIL - pattern execution failed (#{@fail_count} failures)")
139
+ end
140
+ # for debug, report communication times
141
+ Origen.log.info("total communication time: #{@total_comm_time}")
142
+ Origen.log.info("total connect time: #{@total_connect_time}")
143
+ Origen.log.info("total transmit time: #{@total_xmit_time}")
144
+ Origen.log.info("total receive time: #{@total_recv_time}")
145
+ Origen.log.info("total packets: #{@total_packets}")
146
+ Origen.log.info("total time per packet: #{@total_comm_time / @total_packets}")
147
+ Origen.log.info("connect time per packet: #{@total_connect_time / @total_packets}")
148
+ Origen.log.info("transmit time per packet: #{@total_xmit_time / @total_packets}")
149
+ Origen.log.info("receive time per packet: #{@total_recv_time / @total_packets}")
150
+ Origen.log.info("max packet time: #{@max_packet_time}")
151
+ Origen.log.info('max duration command - ' + @longest_packet)
152
+ Origen.log.info("max receive time: #{@max_receive_time}")
153
+ end
154
+
155
+ # to_s
156
+ # returns 'Origen::VectorBased'
157
+ #
158
+ # This method at the moment is used for implementing code that runs only if the
159
+ # environment is set to link vector based. tester.link? will be used once the testers
160
+ # plug in supports the method link?.
161
+ def to_s
162
+ 'OrigenLink::VectorBased'
163
+ end
164
+
165
+ # link?
166
+ # returns true.
167
+ #
168
+ # This method indicates to user code that link is the tester environment.
169
+ def link?
170
+ true
171
+ end
172
+
173
+ # pinmap=
174
+ # This method is used to setup the pin map on the debugger device.
175
+ # The argument should be a string with <pin name>, <gpio #>, <pin name>
176
+ # <gpio #>, etc
177
+ #
178
+ # example:
179
+ # tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
180
+ def pinmap=(pinmap)
181
+ @pinmap = pinmap.gsub(/\s+/, '')
182
+ response = send_cmd('pin_assign', @pinmap)
183
+ setup_cmd_response_logger('pin_assign', response)
184
+ end
185
+
186
+ # pinorder=
187
+ # This method is used to setup the pin order on the debugger device.
188
+ # The pin order will indicate the order that pin data appears in vector
189
+ # data.
190
+ #
191
+ # This is a duplicate of pattern_pin_order and can be handled behind the
192
+ # scenes in the future.
193
+ #
194
+ # example:
195
+ # tester.pinorder = 'tclk,tms,tdi,tdo'
196
+ def pinorder=(pinorder)
197
+ @pinorder = pinorder.gsub(/\s+/, '')
198
+ response = send_cmd('pin_patternorder', @pinorder)
199
+ setup_cmd_response_logger('pin_patternorder', response)
200
+ end
201
+
202
+ # pinformat=
203
+ # This method is used to setup the pin clock format on the debugger device.
204
+ # The supported formats are rl and rh
205
+ #
206
+ # example:
207
+ # tester.pinformat = 'func_25mhz,tclk,rl'
208
+ def pinformat=(pinformat)
209
+ @pinformat = replace_tset_name_w_number(pinformat.gsub(/\s+/, ''))
210
+ response = send_cmd('pin_format', @pinformat)
211
+ setup_cmd_response_logger('pin_format', response)
212
+ end
213
+
214
+ # pintiming=
215
+ # This method is used to setup the pin timing on the debugger device.
216
+ # Timing is relative to the rise and fall of a clock
217
+ #
218
+ # timing value: 0 1 2
219
+ # clock waveform: ___/***\___
220
+ #
221
+ # example:
222
+ # tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'
223
+ def pintiming=(pintiming)
224
+ @pintiming = replace_tset_name_w_number(pintiming.gsub(/\s+/, ''))
225
+ response = send_cmd('pin_timing', @pintiming)
226
+ setup_cmd_response_logger('pin_timing', response)
227
+ end
228
+
229
+ # replace_tset_name_w_number(csl)
230
+ # This method is used by pinformat= and pintiming=
231
+ # This method receives a comma separated list of arguments
232
+ # the first of which is a timeset name. A comma
233
+ # separated list is returned with the timeset name replaced
234
+ # by it's lookup number. If it is a new timset, a lookup
235
+ # number is associated with the name.
236
+ def replace_tset_name_w_number(csl)
237
+ args = csl.split(',')
238
+ args[0] = get_tset_number(args[0])
239
+ args.join(',')
240
+ end
241
+
242
+ # get_tset_number(name)
243
+ # This method returns the test number associated with the
244
+ # passed in tset name. If the name is unknown a new lookup
245
+ # number is returned.
246
+ def get_tset_number(name)
247
+ unless @tsets_programmed.key?(name)
248
+ @tsets_programmed[name] = @tset_count
249
+ @tset_count += 1
250
+ end
251
+ @tsets_programmed[name]
252
+ end
253
+ end
254
+ end
@@ -0,0 +1,18 @@
1
+ require 'origen'
2
+ require 'origen_testers'
3
+ require 'socket'
4
+
5
+ module OrigenLink
6
+ # Load all files in the lib directory via a wildcard, if your project becomes
7
+ # large or load order dependencies start to creep in then you may need to
8
+ # start taking control of this manually as described above.
9
+ # Note that there is no problem from requiring a file twice (Ruby will ignore
10
+ # the second require), so if you have a file that must be required up front
11
+ # you can do that one manually and the let the wildcard take care of the rest.
12
+ # Dir.glob("#{File.dirname(__FILE__)}/**/*.rb").sort.each do |file|
13
+ # require file
14
+ # end
15
+ Dir.glob("#{File.dirname(__FILE__)}/origen_link/*.rb").sort.each do |file|
16
+ require file
17
+ end
18
+ end
@@ -0,0 +1,333 @@
1
+ # rubocop:disable Style/FileName: Use snake_case for source file names
2
+ require_relative 'pin_interface'
3
+
4
+ ##################################################
5
+ # OrigenLinkSequencer Class
6
+ # Instance variables:
7
+ # pinmap: hash with ["pin name"] = pin object
8
+ # patternpinindex: hash with ["pin name"] =
9
+ # integer index into vector data
10
+ # patternpinorder: Array with pin names in
11
+ # the vector order
12
+ #
13
+ # This class processes messages targeted for
14
+ # pin sequencer interface (vector pattern
15
+ # execution).
16
+ #
17
+ # Supported messages:
18
+ # pin_assign (create pin mapping)
19
+ # ex: "pin_assign:tck,3,extal,23,tdo,5"
20
+ #
21
+ # pin_patternorder (define vector pin order)
22
+ # ex: "pin_patternorder:tdo,extal,tck"
23
+ #
24
+ # pin_cycle (execute vector data)
25
+ # ex: "pin_cycle:H11"
26
+ #
27
+ # pin_clear (clear all setup information)
28
+ # ex: "pin_clear:"
29
+ #
30
+ # pin_format (setup a pin with return format)
31
+ # first argument is the timeset
32
+ # ex: "pin_format:1,tck,rl"
33
+ #
34
+ # pin_timing (define when pin events happen)
35
+ # timing is stored in a timeset hash
36
+ # first argument is the timeset key
37
+ # ex: "pin_timing:1,tdi,0,tdo,1,tms,0
38
+ ##################################################
39
+ class OrigenLinkSequencer
40
+ attr_reader :pinmap
41
+ attr_reader :patternorder
42
+ attr_reader :cycletiming
43
+ attr_reader :patternpinindex
44
+
45
+ ##################################################
46
+ # initialize method
47
+ # Create empty pinmap, pattern pin index
48
+ # and pattern order instance variables
49
+ ##################################################
50
+ def initialize
51
+ @pinmap = Hash.new(-1)
52
+ @patternpinindex = Hash.new(-1)
53
+ @patternorder = []
54
+ @cycletiming = Hash.new(-1)
55
+ end
56
+
57
+ ##################################################
58
+ # processmessage method
59
+ # arguments: message
60
+ # message format is <group>_<command>:<args>
61
+ # returns: message response
62
+ #
63
+ # This method splits a message into it's
64
+ # command and arguments and passes this
65
+ # information to the method that performs
66
+ # the requested command
67
+ ##################################################
68
+ def processmessage(message)
69
+ command = message.split(':')
70
+
71
+ case command[0]
72
+ when 'pin_assign'
73
+ pin_assign(command[1])
74
+ when 'pin_patternorder'
75
+ pin_patternorder(command[1])
76
+ when 'pin_cycle'
77
+ pin_cycle(command[1])
78
+ when 'pin_clear'
79
+ pin_clear
80
+ when 'pin_format'
81
+ pin_format(command[1])
82
+ when 'pin_timing'
83
+ pin_timing(command[1])
84
+ else
85
+ 'Error Invalid command: ' + command[0].to_s
86
+ end
87
+ end
88
+
89
+ ##################################################
90
+ # pin_assign method
91
+ # arguments: <args> from the message request
92
+ # see "processmessage" method
93
+ # returns: "P:" or error message
94
+ #
95
+ # This method creates a pin instance for each
96
+ # pin in the pin map and builds the pinmap
97
+ # hash. Before the pinmap is created, any
98
+ # information from a previous pattern run is
99
+ # cleared.
100
+ ##################################################
101
+ def pin_assign(args)
102
+ pin_clear
103
+ success = true
104
+ fail_message = ''
105
+ argarr = args.split(',')
106
+ 0.step(argarr.length - 2, 2) do |index|
107
+ @pinmap[argarr[index]] = OrigenLinkPin.new(argarr[index + 1])
108
+ unless @pinmap[argarr[index]].gpio_valid
109
+ success = false
110
+ fail_message = fail_message + 'pin ' + argarr[index] + ' gpio' + argarr[index + 1] + ' is invalid'
111
+ end
112
+ end
113
+ if success
114
+ 'P:'
115
+ else
116
+ 'F:' + fail_message
117
+ end
118
+ end
119
+
120
+ ##################################################
121
+ # new_timeset(tset)
122
+ # creates a new empty timeset hash
123
+ ##################################################
124
+ def new_timeset(tset)
125
+ @cycletiming[tset] = {}
126
+ @cycletiming[tset]['timing'] = [[], [], []]
127
+ end
128
+
129
+ ##################################################
130
+ # pin_format method
131
+ # arguments: <args> from the message request
132
+ # Should be <timeset>,<pin>,rl or rh
133
+ # multi-clock not currently supported
134
+ #
135
+ ##################################################
136
+ def pin_format(args)
137
+ argarr = args.split(',')
138
+ tset_key = argarr.delete_at(0).to_i
139
+ new_timeset(tset_key) unless @cycletiming.key?(tset_key)
140
+ @cycletiming[tset_key].delete('rl')
141
+ @cycletiming[tset_key].delete('rh')
142
+ 0.step(argarr.length - 2, 2) do |index|
143
+ @cycletiming[tset_key][argarr[index + 1]] = [] unless @cycletiming[tset_key].key?(argarr[index + 1])
144
+ @cycletiming[tset_key][argarr[index + 1]] << argarr[index]
145
+ end
146
+ 'P:'
147
+ end
148
+
149
+ ##################################################
150
+ # pin_timing method
151
+ # arguments: <args> from the message request
152
+ # Should be '1,pin,-1,pin2,0,pin3,1'
153
+ # First integer is timeset number
154
+ # If argument is '', default timing is created
155
+ # Default timeset number is 0, this is used
156
+ # if no timeset is explicitly defined
157
+ #
158
+ # cycle arg: 0 1 2
159
+ # waveform : ___/***\___
160
+ #
161
+ # returns "P:" or error message
162
+ #
163
+ # This method sets up a time set. All retrun
164
+ # format pins are driven between 0 and 1 and
165
+ # return between 1 and 2. Non-return pins are
166
+ # acted upon during the 0, 1 or 2 time period.
167
+ ##################################################
168
+ def pin_timing(args)
169
+ argarr = args.split(',')
170
+ tset_key = argarr.delete_at(0).to_i
171
+ new_timeset(tset_key) unless @cycletiming.key?(tset_key)
172
+ @cycletiming[tset_key]['timing'].each do |index|
173
+ index.delete_if { true }
174
+ end
175
+ 0.step(argarr.length - 2, 2) do |index|
176
+ @cycletiming[tset_key]['timing'][argarr[index + 1].to_i] << argarr[index]
177
+ end
178
+ 'P:'
179
+ end
180
+
181
+ ##################################################
182
+ # pin_patternorder method
183
+ # arguments: <args> from the message request
184
+ # returns: "P:" or error message
185
+ #
186
+ # This method is used to define the order
187
+ # for pin vector data.
188
+ ##################################################
189
+ def pin_patternorder(args)
190
+ argarr = args.split(',')
191
+ index = 0
192
+ if @cycletiming.key?(0)
193
+ @cycletiming[0]['timing'][0].delete_if { true }
194
+ else
195
+ new_timeset(0)
196
+ end
197
+ argarr.each do |pin|
198
+ @patternorder << pin
199
+ @patternpinindex[pin] = index
200
+ @cycletiming[0]['timing'][0] << pin
201
+ index += 1
202
+ end
203
+ 'P:'
204
+ end
205
+
206
+ ##################################################
207
+ # pin_cycle method
208
+ # arguments: <args> from the message request
209
+ # returns: "P:" or "F:" followed by results
210
+ #
211
+ # This method executes one cycle of pin vector
212
+ # data. The vector data is decomposed and
213
+ # sequenced. Each pin object and pin data
214
+ # is passed to the "process_pindata" method
215
+ # for decoding and execution
216
+ ##################################################
217
+ def pin_cycle(args)
218
+ # set default repeats and timeset
219
+ repeat_count = 1
220
+ tset = 0
221
+ if args =~ /,/
222
+ parsedargs = args.split(',')
223
+ args = parsedargs.pop
224
+ parsedargs.each do |arg|
225
+ if arg =~ /repeat/
226
+ repeat_count = arg.sub(/repeat/, '').to_i
227
+ elsif arg =~ /tset/
228
+ tset = arg.sub(/tset/, '').to_i
229
+ end
230
+ end
231
+ end
232
+
233
+ message = ''
234
+ pindata = args.split('')
235
+ @cycle_failure = false
236
+ 0.upto(repeat_count - 1) do |count|
237
+ response = {}
238
+ # process time 0 events
239
+ response = process_events(@cycletiming[tset]['timing'][0], pindata)
240
+ # send drive data for return format pins
241
+ response = (process_events(@cycletiming[tset]['rl'], pindata)).merge(response)
242
+ response = (process_events(@cycletiming[tset]['rh'], pindata)).merge(response)
243
+ # process time 1 events
244
+ response = process_events(@cycletiming[tset]['timing'][1], pindata).merge(response)
245
+ # send return data
246
+ unless @cycletiming[tset]['rl'].nil?
247
+ @cycletiming[tset]['rl'].each do |pin|
248
+ process_pindata(@pinmap[pin], '0')
249
+ end
250
+ end
251
+ unless @cycletiming[tset]['rh'].nil?
252
+ @cycletiming[tset]['rh'].each do |pin|
253
+ process_pindata(@pinmap[pin], '1')
254
+ end
255
+ end
256
+ # process time 2 events
257
+ response = process_events(@cycletiming[tset]['timing'][2], pindata).merge(response)
258
+ if (count == 0) || (@cycle_failure)
259
+ message = ''
260
+ @patternorder.each do |pin|
261
+ message += response[pin]
262
+ end
263
+ end
264
+ end # end cycle through repeats
265
+ if @cycle_failure
266
+ rtnmsg = 'F:' + message + ' Expected:' + args
267
+ else
268
+ rtnmsg = 'P:' + message
269
+ end
270
+ rtnmsg += ' Repeat ' + repeat_count.to_s if repeat_count > 1
271
+ rtnmsg
272
+ end
273
+
274
+ ##################################################
275
+ # process_events
276
+ # used by pin_cycle to avoid duplicating code
277
+ ##################################################
278
+ def process_events(events, pindata)
279
+ response = {}
280
+ unless events.nil?
281
+ events.each do |pin|
282
+ response[pin] = process_pindata(@pinmap[pin], pindata[@patternpinindex[pin]])
283
+ end
284
+ end
285
+ response
286
+ end
287
+
288
+ ##################################################
289
+ # process_pindata method
290
+ # arguments:
291
+ # pin: the pin object to be operated on
292
+ # data: the pin data to be executed
293
+ # returns: the drive data or read data
294
+ #
295
+ # This method translates pin data into one
296
+ # of three possible events. Drive 0, drive 1
297
+ # or read. Supported character decode:
298
+ # drive 0: '0'
299
+ # drive 1: '1'
300
+ # read: anything else
301
+ ##################################################
302
+ def process_pindata(pin, data)
303
+ if data == '0' || data == '1'
304
+ pin.out(data)
305
+ data
306
+ else
307
+ case pin.in
308
+ when '0'
309
+ @cycle_failure = true if data == 'H'
310
+ 'L'
311
+ when '1'
312
+ @cycle_failure = true if data == 'L'
313
+ 'H'
314
+ else
315
+ 'W'
316
+ end
317
+ end
318
+ end
319
+
320
+ ##################################################
321
+ # pin_clear method
322
+ #
323
+ # This method clears all storage objects. It
324
+ # is called by the "pin_assign" method
325
+ ##################################################
326
+ def pin_clear
327
+ @pinmap.clear
328
+ @patternpinindex.clear
329
+ @patternorder.delete_if { true }
330
+ @cycletiming.clear
331
+ 'P:'
332
+ end
333
+ end
@@ -0,0 +1,45 @@
1
+ # rubocop:disable Style/FileName: Use snake_case for source file names.
2
+ require 'socket'
3
+ require_relative 'LinkSequencer'
4
+
5
+ server = TCPServer.open('192.168.0.2', 12_777)
6
+ puts 'server started'
7
+ pinsequencer = OrigenLinkSequencer.new
8
+
9
+ # time measurements for debug only
10
+ # total_receive_time=0
11
+ # total_process_time=0
12
+ # total_xmit_time=0
13
+ # total_close_time=0
14
+ # total_packets=0
15
+ loop do
16
+ client = server.accept
17
+ # time measurements for debug only
18
+ # t1 = Time.now
19
+ message = client.gets
20
+ # t2 = Time.now
21
+ # process the message
22
+ # for now only pin_ messages are accepted
23
+ response = pinsequencer.processmessage(message.chomp)
24
+ # t3 = Time.now
25
+ client.puts(response)
26
+ # t4 = Time.now
27
+ client.close
28
+ # t5 = Time.now
29
+
30
+ # puts "packet process time: #{t3-t2}"
31
+ # total_receive_time += (t2-t1)
32
+ # total_process_time += (t3-t2)
33
+ # total_xmit_time += (t4-t3)
34
+ # total_close_time += (t5-t4)
35
+ # total_packets += 1
36
+ # puts "total receive time: #{total_receive_time}"
37
+ # puts "total process time: #{total_process_time}"
38
+ # puts "total xmit time: #{total_xmit_time}"
39
+ # puts "total close time: #{total_close_time}"
40
+ # puts ''
41
+ # puts "total receive time: #{total_receive_time/total_packets}"
42
+ # puts "total process time: #{total_process_time/total_packets}"
43
+ # puts "total xmit time: #{total_xmit_time/total_packets}"
44
+ # puts "total close time: #{total_close_time/total_packets}"
45
+ end