summaryrefslogtreecommitdiffstats
path: root/unit_trace/viz/schedule.py
diff options
context:
space:
mode:
authorMac Mollison <mollison@cs.unc.edu>2011-01-31 16:40:54 -0500
committerMac Mollison <mollison@cs.unc.edu>2011-01-31 16:40:54 -0500
commitd2240e7a9b15d18dfd0f3cbe75f3adf1c9e7fabf (patch)
treef7d164c21716b55f3d9195f055db73505bbf951d /unit_trace/viz/schedule.py
parent85a089c42749e1394ae12321564109f25fa8154f (diff)
Added support for visualizing arbitrary actions.
(By Jonathan, cherry-picked by Mac) Conflicts: unit_trace/trace_reader.py unit_trace/viz/canvas.py unit_trace/viz/graph.py unit_trace/viz/schedule.py
Diffstat (limited to 'unit_trace/viz/schedule.py')
-rw-r--r--unit_trace/viz/schedule.py171
1 files changed, 149 insertions, 22 deletions
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py
index a44ce8d..2301b0c 100644
--- a/unit_trace/viz/schedule.py
+++ b/unit_trace/viz/schedule.py
@@ -138,6 +138,7 @@ class Schedule(object):
138 self.time_slot_array = None 138 self.time_slot_array = None
139 self.cur_task_no = 0 139 self.cur_task_no = 0
140 self.num_cpus = num_cpus 140 self.num_cpus = num_cpus
141 self.jobless = []
141 for task in task_list: 142 for task in task_list:
142 self.add_task(task) 143 self.add_task(task)
143 144
@@ -217,6 +218,23 @@ class Schedule(object):
217 task.task_no = self.cur_task_no 218 task.task_no = self.cur_task_no
218 self.cur_task_no += 1 219 self.cur_task_no += 1
219 220
221 def add_jobless(self, event):
222 self.jobless.append(event)
223
224 def sort_task_nos_numeric(self):
225 # sort task numbers by the numeric value of the task names.
226 nums = []
227
228 for task_name in self.tasks:
229 nums.append((int(task_name), task_name))
230
231 nums.sort(key=lambda t: t[0])
232 for no, task in enumerate(nums):
233 self.tasks[task[1]].task_no = no
234
235 def get_jobless(self):
236 return self.jobless
237
220 def get_tasks(self): 238 def get_tasks(self):
221 return self.tasks 239 return self.tasks
222 240
@@ -295,12 +313,12 @@ class DummyEvent(object):
295 event added by the application to speed things up or keep track of 313 event added by the application to speed things up or keep track of
296 something. Such an event won't be added to the schedule tree, but 314 something. Such an event won't be added to the schedule tree, but
297 might appear in the time slot array.""" 315 might appear in the time slot array."""
298
299 def __init__(self, time, cpu): 316 def __init__(self, time, cpu):
300 self.time = time 317 self.time = time
301 self.cpu = cpu 318 self.cpu = cpu
302 self.job = None 319 self.job = None
303 self.layer = None 320 self.layer = None
321 self.saved_schedule = None
304 322
305 def __str__(self): 323 def __str__(self):
306 return '[Dummy Event]' 324 return '[Dummy Event]'
@@ -311,6 +329,25 @@ class DummyEvent(object):
311 def get_cpu(self): 329 def get_cpu(self):
312 return self.cpu 330 return self.cpu
313 331
332 # Refactor, shouldn't depend on job
333 def get_schedule(self):
334 if self.saved_schedule is not None:
335 return self.saved_schedule
336 elif self.get_task() is not None:
337 return self.get_task().get_schedule()
338 else:
339 return None
340
341 # Needed for events not assigned to specific tasks
342 def set_schedule(self, schedule):
343 self.saved_schedule = schedule
344
345 def get_task(self):
346 if self.get_job() is not None:
347 return self.get_job().get_task()
348 else:
349 return None
350
314 def get_job(self): 351 def get_job(self):
315 return self.job 352 return self.job
316 353
@@ -342,20 +379,34 @@ class Event(DummyEvent):
342 def __str__(self): 379 def __str__(self):
343 return self.get_name() + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 380 return self.get_name() + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
344 381
345 def str_long(self): 382 def str_long(self, unit):
346 """Prints the event as a string, in ``long'' form.""" 383 if self.get_job() is not None:
347 return 'Event Type: ' + self.get_name() + \ 384 """Prints the event as a string, in ``long'' form."""
348 '\nTask Name: ' + str(self.get_job().get_task().get_name()) + \ 385 return 'Event Information\n-----------------\n' + \
349 '\n(Task no., Job no.): ' + str((self.get_job().get_task().get_task_no(), \ 386 'Event Type: ' + self.get_name() + \
350 self.get_job().get_job_no())) + \ 387 '\nTask Name: ' + str(self.get_job().get_task().get_name()) + \
351 '\nCPU: ' + str(self.get_cpu()) + \ 388 '\n(Task no., Job no.): ' + str((self.get_job().get_task().get_task_no(), \
352 '\nTime: ' + str(self.get_time()) 389 self.get_job().get_job_no())) + \
390 '\nCPU: ' + str(self.get_cpu()) + \
391 '\nTime: ' + _format_time(self.get_time(), unit) + \
392 '\n\n' + self.get_job().str_long(unit)
393 else:
394 """Prints the event as a string, in ``long'' form."""
395 return 'Event Information\n-----------------\n' + \
396 'Event Type: ' + self.get_name() + \
397 '\nTask Name: None' + \
398 '\nCPU: ' + str(self.get_cpu()) + \
399 '\nTime: ' + _format_time(self.get_time(), unit)
353 400
354 def _common_str(self): 401 def _common_str(self):
355 job = self.get_job() 402 if self.get_job() is not None:
356 task = job.get_task() 403 job = self.get_job()
357 return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \ 404 task = job.get_task()
358 job.get_job_no())) + ', CPU=' + str(self.get_cpu()) 405 return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + \
406 str((task.get_task_no(), job.get_job_no())) + \
407 ', CPU=' + str(self.get_cpu())
408 else:
409 return ', Cpu=' + str(self.get_cpu())
359 410
360 def is_erroneous(self): 411 def is_erroneous(self):
361 """An erroneous event is where something with the event is not quite right, 412 """An erroneous event is where something with the event is not quite right,
@@ -377,13 +428,56 @@ class Event(DummyEvent):
377 time in the scan, and ``switches'' gives the last time a certain switch 428 time in the scan, and ``switches'' gives the last time a certain switch
378 (e.g. SwitchToEvent, InversionStartEvent) occurred""" 429 (e.g. SwitchToEvent, InversionStartEvent) occurred"""
379 time = self.get_time() 430 time = self.get_time()
380 sched = self.get_job().get_task().get_schedule()
381 if sched.start is None or time < sched.start:
382 sched.start = time
383 if sched.end is None or time > sched.end:
384 sched.end = time
385 431
386 sched.get_time_slot_array().add_event_to_time_slot(self) 432 sched = self.get_schedule()
433
434 if sched is not None:
435 if sched.start is None or time < sched.start:
436 sched.start = time
437 if sched.end is None or time > sched.end:
438 sched.end = time
439
440 if item_nos is None:
441 item_nos = { TimeSlotArray.TASK_LIST : self.get_task().get_task_no(),
442 TimeSlotArray.CPU_LIST : self.get_cpu() }
443 sched.get_time_slot_array().add_event_to_time_slot(self, item_nos)
444
445 self.fill_span_event_from_end()
446
447 def fill_span_event_from_start(self):
448 """This method exists for events that can ``range'' over a period of time
449 (e.g. SwitchAway and SwitchTo). In case a start event is not paired with
450 an end event, or vice versa, we want to fill in dummy events to range all
451 the way to the beginning or end. Since most events occur only at a specific
452 time, this is usually a no-op."""
453 pass
454
455 def fill_span_event_from_end(self):
456 """The mirror image of the last method."""
457 pass
458
459class SpanEvent(Event):
460 def __init__(self, time, cpu, dummy_class):
461 super(SpanEvent, self).__init__(time, cpu)
462 self.dummy_class = dummy_class
463
464class SpanDummy(DummyEvent):
465 def __init__(self):
466 super(SpanDummy, self).__init__(None, None)
467
468 def get_task(self):
469 if self.corresp_start_event is not None:
470 return self.corresp_start_event.get_task()
471 if self.corresp_end_event is not None:
472 return self.corresp_end_event.get_task()
473 return None
474
475 def get_schedule(self):
476 if self.corresp_start_event is not None:
477 return self.corresp_start_event.get_schedule()
478 if self.corresp_end_event is not None:
479 return self.corresp_end_event.get_schedule()
480 return None
387 481
388class ErrorEvent(Event): 482class ErrorEvent(Event):
389 pass 483 pass
@@ -631,9 +725,42 @@ class DeadlineEvent(Event):
631 graph.add_sel_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 725 graph.add_sel_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
632 self) 726 self)
633 else: 727 else:
634 graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 728 graph.draw_deadline_arrow_at_time(self.get_time(),
635 self.get_job().get_job_no(), self.is_selected()) 729 self.get_job().get_task().get_task_no(),
730 self.get_job().get_job_no(), self.is_selected())
636 731
732class ActionEvent(Event):
733 def __init__(self, time, cpu, action):
734 super(ActionEvent, self).__init__(time, cpu)
735 self.layer = Canvas.TOP_LAYER
736 self.action = int(action)
737
738 def get_name(self):
739 return 'Action'
740
741 def scan(self, cur_cpu, switches):
742 item_nos = { TimeSlotArray.TASK_LIST : self.get_task().get_task_no(),
743 TimeSlotArray.CPU_LIST : TimeSlotArray.POST_ITEM_NO }
744 super(ActionEvent, self).scan(cur_cpu, switches, item_nos)
745
746 def render(self, graph, layer, prev_events, selectable=False):
747 prev_events[self] = None
748 if layer == Canvas.TOP_LAYER:
749
750 # TODO: need a more official way of doing this
751 task_no = -1
752 job_no = -1
753 if self.get_job() is not None:
754 task_no = self.get_job().get_task().get_task_no()
755 job_no = self.get_job().get_job_no()
756
757 if selectable:
758 graph.add_sel_action_symbol_at_time(self.get_time(), task_no,
759 self.get_cpu(), self)
760 else:
761 graph.draw_action_symbol_at_time(self.get_time(), task_no,
762 self.get_cpu(), self.action,
763 job_no, self.is_selected())
637 764
638class InversionStartEvent(ErrorEvent): 765class InversionStartEvent(ErrorEvent):
639 def __init__(self, time): 766 def __init__(self, time):
@@ -791,7 +918,7 @@ EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None,
791 SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None, 918 SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None,
792 DeadlineEvent : None, IsRunningDummy : None, 919 DeadlineEvent : None, IsRunningDummy : None,
793 InversionStartEvent : None, InversionEndEvent : None, 920 InversionStartEvent : None, InversionEndEvent : None,
794 InversionDummy : None} 921 InversionDummy : None, TaskDummy : None, CPUDummy : None, ActionEvent: None}
795 922
796SPAN_START_EVENTS = { SwitchToEvent : IsRunningDummy, InversionStartEvent : InversionDummy } 923SPAN_START_EVENTS = { SwitchToEvent : IsRunningDummy, InversionStartEvent : InversionDummy }
797SPAN_END_EVENTS = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy} 924SPAN_END_EVENTS = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy}