diff options
author | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2011-01-27 00:51:17 -0500 |
---|---|---|
committer | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2011-01-27 00:51:17 -0500 |
commit | c4edd95d28b9212e09e8caca0d6b11937f453995 (patch) | |
tree | 7237b64d71c9e9856e13a687eab336691a1a26f6 /unit_trace/viz | |
parent | 27f0b6ca2baac29c1b61001306caf4186f5c108a (diff) |
Added support for visualizing arbitrary actions.wip-events
Diffstat (limited to 'unit_trace/viz')
-rw-r--r-- | unit_trace/viz/canvas.py | 63 | ||||
-rw-r--r-- | unit_trace/viz/convert.py | 31 | ||||
-rw-r--r-- | unit_trace/viz/graph.py | 72 | ||||
-rw-r--r-- | unit_trace/viz/schedule.py | 125 |
4 files changed, 243 insertions, 48 deletions
diff --git a/unit_trace/viz/canvas.py b/unit_trace/viz/canvas.py index badebe9..2c977ae 100644 --- a/unit_trace/viz/canvas.py +++ b/unit_trace/viz/canvas.py | |||
@@ -521,14 +521,44 @@ class Canvas(object): | |||
521 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, | 521 | self.add_sel_region(SelectableRegion(x - big_arrowhead_height / Canvas.SQRT3, |
522 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) | 522 | y, 2.0 * big_arrowhead_height / Canvas.SQRT3, height, event)) |
523 | 523 | ||
524 | def draw_action_symbol(self, item, action, x, y, height, selected): | ||
525 | """Draws a release arrow: x, y should give the top (northernmost | ||
526 | point) of the arrow. The height includes the arrowhead.""" | ||
527 | |||
528 | color = {False : GraphFormat.BORDER_COLOR, | ||
529 | True : GraphFormat.HIGHLIGHT_COLOR}[selected] | ||
530 | |||
531 | colors = [self.get_bar_pattern(item).get_color_list()[0], color] | ||
532 | draw_funcs = [self.__class__.fill_polyline, self.__class__.draw_polyline] | ||
533 | |||
534 | for i in range(0, 2): | ||
535 | color = colors[i] | ||
536 | draw_func = draw_funcs[i] | ||
537 | |||
538 | draw_func(self, [(x, y), (x - height / Canvas.SQRT3, \ | ||
539 | y - height), \ | ||
540 | (x + height / Canvas.SQRT3, \ | ||
541 | y - height), \ | ||
542 | (x, y)], color, GraphFormat.BORDER_THICKNESS) | ||
543 | |||
544 | self.draw_label(str(action), x, y - height / 2 - .1 * height, | ||
545 | GraphFormat.DEF_FOPTS_LABEL, | ||
546 | AlignMode.CENTER, AlignMode.CENTER, True) | ||
547 | |||
548 | def add_sel_action_symbol(self, x, y, height, event): | ||
549 | self.add_sel_region(SelectableRegion(x - height / Canvas.SQRT3, | ||
550 | y - height, 2.0 * height / Canvas.SQRT3, height, event)) | ||
551 | |||
524 | def draw_release_arrow_small(self, x, y, height, selected): | 552 | def draw_release_arrow_small(self, x, y, height, selected): |
525 | """Draws a small release arrow (most likely coming off the x-axis, although | 553 | """Draws a small release arrow (most likely coming off the x-axis, although |
526 | this method doesn't enforce this): x, y should give the top of the arrow""" | 554 | this method doesn't enforce this): x, y should give the top of the arrow""" |
527 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height | 555 | small_arrowhead_height = GraphFormat.SMALL_ARROWHEAD_FACTOR * height |
528 | 556 | ||
529 | color = {False : GraphFormat.BORDER_COLOR, True : GraphFormat.HIGHLIGHT_COLOR}[selected] | 557 | color = {False : GraphFormat.BORDER_COLOR, |
558 | True : GraphFormat.HIGHLIGHT_COLOR}[selected] | ||
530 | 559 | ||
531 | self.draw_line((x, y), (x - small_arrowhead_height, y + small_arrowhead_height), \ | 560 | self.draw_line((x, y), |
561 | (x - small_arrowhead_height, y + small_arrowhead_height), | ||
532 | color, GraphFormat.BORDER_THICKNESS) | 562 | color, GraphFormat.BORDER_THICKNESS) |
533 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ | 563 | self.draw_line((x, y), (x + small_arrowhead_height, y + small_arrowhead_height), \ |
534 | color, GraphFormat.BORDER_THICKNESS) | 564 | color, GraphFormat.BORDER_THICKNESS) |
@@ -754,13 +784,35 @@ class CairoCanvas(Canvas): | |||
754 | self.surface.ctx.set_line_width(thickness * self.scale) | 784 | self.surface.ctx.set_line_width(thickness * self.scale) |
755 | self.surface.ctx.stroke() | 785 | self.surface.ctx.stroke() |
756 | 786 | ||
787 | def draw_circle(self, x, y, radius, fill_color, border_color, | ||
788 | thickness, do_snap=True): | ||
789 | p = self.surface.get_real_coor(x, y) | ||
790 | if do_snap: | ||
791 | p = (snap(p[0]), snap(p[1])) | ||
792 | |||
793 | self.surface.ctx.save() | ||
794 | self.surface.ctx.arc(p[0], p[1], radius, 0.0, 2 * math.pi) | ||
795 | self.surface.ctx.set_source_rgb(border_color[0], | ||
796 | border_color[1], | ||
797 | border_color[2]) | ||
798 | self.surface.ctx.set_line_width(thickness * self.scale) | ||
799 | self.surface.ctx.stroke() | ||
800 | self.surface.ctx.arc(p[0], p[1], radius, 0.0, 2 * math.pi) | ||
801 | self.surface.ctx.set_source_rgb(fill_color[0], | ||
802 | fill_color[1], | ||
803 | fill_color[2]) | ||
804 | self.surface.ctx.fill() | ||
805 | self.surface.ctx.restore() | ||
806 | |||
757 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): | 807 | def _polyline_common(self, coor_list, color, thickness, do_snap=True): |
758 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) for coor in coor_list] | 808 | real_coor_list = [self.surface.get_real_coor(coor[0], coor[1]) \ |
809 | for coor in coor_list] | ||
759 | 810 | ||
760 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) | 811 | self.surface.ctx.move_to(real_coor_list[0][0], real_coor_list[0][1]) |
761 | if do_snap: | 812 | if do_snap: |
762 | for i in range(0, len(real_coor_list)): | 813 | for i in range(0, len(real_coor_list)): |
763 | real_coor_list[i] = (snap(real_coor_list[i][0]), snap(real_coor_list[i][1])) | 814 | real_coor_list[i] = (snap(real_coor_list[i][0]), |
815 | snap(real_coor_list[i][1])) | ||
764 | 816 | ||
765 | for coor in real_coor_list[1:]: | 817 | for coor in real_coor_list[1:]: |
766 | self.surface.ctx.line_to(coor[0], coor[1]) | 818 | self.surface.ctx.line_to(coor[0], coor[1]) |
@@ -830,7 +882,8 @@ class CairoCanvas(Canvas): | |||
830 | f_descent_factor, width_factor, f_height_factor, | 882 | f_descent_factor, width_factor, f_height_factor, |
831 | do_snap) | 883 | do_snap) |
832 | 884 | ||
833 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | 885 | def draw_label(self, text, x, y, fopts=GraphFormat.DEF_FOPTS_LABEL, |
886 | halign=AlignMode.LEFT, valign=AlignMode.BOTTOM, do_snap=True): | ||
834 | """Draws a label with the given parameters, with the given horizontal and vertical justification.""" | 887 | """Draws a label with the given parameters, with the given horizontal and vertical justification.""" |
835 | 888 | ||
836 | actual_x, actual_y, width, height, f_height = self.get_label_dim(text, x, y, fopts, halign, valign, do_snap) | 889 | actual_x, actual_y, width, height, f_height = self.get_label_dim(text, x, y, fopts, halign, valign, do_snap) |
diff --git a/unit_trace/viz/convert.py b/unit_trace/viz/convert.py index d19bc73..278a541 100644 --- a/unit_trace/viz/convert.py +++ b/unit_trace/viz/convert.py | |||
@@ -16,14 +16,17 @@ def get_type_num(type): | |||
16 | return nums[type] | 16 | return nums[type] |
17 | 17 | ||
18 | def _get_job_from_record(sched, record): | 18 | def _get_job_from_record(sched, record): |
19 | tname = _pid_to_task_name(record.pid) | 19 | if record.pid == 0: |
20 | job_no = record.job | 20 | return None |
21 | if tname not in sched.get_tasks(): | 21 | else: |
22 | sched.add_task(Task(tname, [])) | 22 | tname = _pid_to_task_name(record.pid) |
23 | if job_no not in sched.get_tasks()[tname].get_jobs(): | 23 | job_no = record.job |
24 | sched.get_tasks()[tname].add_job(Job(job_no, [])) | 24 | if tname not in sched.get_tasks(): |
25 | job = sched.get_tasks()[tname].get_jobs()[job_no] | 25 | sched.add_task(Task(tname, [])) |
26 | return job | 26 | if job_no not in sched.get_tasks()[tname].get_jobs(): |
27 | sched.get_tasks()[tname].add_job(Job(job_no, [])) | ||
28 | job = sched.get_tasks()[tname].get_jobs()[job_no] | ||
29 | return job | ||
27 | 30 | ||
28 | def convert_trace_to_schedule(stream): | 31 | def convert_trace_to_schedule(stream): |
29 | """The main function of interest in this module. Coverts a stream of records | 32 | """The main function of interest in this module. Coverts a stream of records |
@@ -45,12 +48,20 @@ def convert_trace_to_schedule(stream): | |||
45 | if not hasattr(record, 'deadline'): | 48 | if not hasattr(record, 'deadline'): |
46 | record.deadline = None | 49 | record.deadline = None |
47 | 50 | ||
51 | # This whole method should be refactored for this posibility | ||
52 | if job is None: | ||
53 | if record.type_name == "action": | ||
54 | event = ActionEvent(record.when, cpu, record.action) | ||
55 | event.set_schedule(sched) | ||
56 | sched.add_jobless(event) | ||
57 | continue | ||
58 | |||
48 | actions = { | 59 | actions = { |
49 | 'name' : (noop), | 60 | 'name' : (noop), |
50 | 'params' : (noop), | 61 | 'params' : (noop), |
51 | 'release' : (lambda : | 62 | 'release' : (lambda : |
52 | (job.add_event(ReleaseEvent(record.when, cpu)), | 63 | (job.add_event(ReleaseEvent(record.when, cpu)), |
53 | job.add_event(DeadlineEvent(record.deadline, cpu)))), | 64 | job.add_event(DeadlineEvent(record.deadline, cpu)))), |
54 | 'switch_to' : (lambda : | 65 | 'switch_to' : (lambda : |
55 | job.add_event(SwitchToEvent(record.when, cpu))), | 66 | job.add_event(SwitchToEvent(record.when, cpu))), |
56 | 'switch_away' : (lambda : | 67 | 'switch_away' : (lambda : |
@@ -62,6 +73,8 @@ def convert_trace_to_schedule(stream): | |||
62 | job.add_event(SuspendEvent(record.when, cpu))), | 73 | job.add_event(SuspendEvent(record.when, cpu))), |
63 | 'resume' : (lambda : | 74 | 'resume' : (lambda : |
64 | job.add_event(ResumeEvent(record.when, cpu))), | 75 | job.add_event(ResumeEvent(record.when, cpu))), |
76 | 'action' : (lambda : | ||
77 | job.add_event(ActionEvent(record.when, cpu, record.action))), | ||
65 | 'sys_release' : (noop) | 78 | 'sys_release' : (noop) |
66 | } | 79 | } |
67 | 80 | ||
diff --git a/unit_trace/viz/graph.py b/unit_trace/viz/graph.py index 73c4ce4..e157335 100644 --- a/unit_trace/viz/graph.py +++ b/unit_trace/viz/graph.py | |||
@@ -8,11 +8,12 @@ than the canvas classes (time and task/cpu number rather than plain coordinates) | |||
8 | update themselves, unlike the Canvas which can only overwrite itself.""" | 8 | update themselves, unlike the Canvas which can only overwrite itself.""" |
9 | 9 | ||
10 | class Graph(object): | 10 | class Graph(object): |
11 | DEF_BAR_PLIST = [Pattern([(0.0, 0.9, 0.9)]), Pattern([(0.9, 0.3, 0.0)]), Pattern([(0.9, 0.7, 0.0)]), | 11 | DEF_BAR_PLIST = [Pattern([(0.0, 0.9, 0.9)]), Pattern([(0.9, 0.3, 0.0)]), |
12 | Pattern([(0.0, 0.0, 0.8)]), Pattern([(0.0, 0.2, 0.9)]), Pattern([(0.0, 0.6, 0.6)]), | 12 | Pattern([(0.9, 0.7, 0.0)]), Pattern([(0.0, 0.0, 0.8)]), |
13 | Pattern([(0.0, 0.2, 0.9)]), Pattern([(0.0, 0.6, 0.6)]), | ||
13 | Pattern([(0.75, 0.75, 0.75)])] | 14 | Pattern([(0.75, 0.75, 0.75)])] |
14 | DEF_ITEM_CLIST = [(0.3, 0.0, 0.0), (0.0, 0.3, 0.0), (0.0, 0.0, 0.3), (0.3, 0.3, 0.0), (0.0, 0.3, 0.3), | 15 | DEF_ITEM_CLIST = [(0.3, 0.0, 0.0), (0.0, 0.3, 0.0), (0.0, 0.0, 0.3), |
15 | (0.3, 0.0, 0.3)] | 16 | (0.3, 0.3, 0.0), (0.0, 0.3, 0.3), (0.3, 0.0, 0.3)] |
16 | 17 | ||
17 | def __init__(self, CanvasType, surface, start_time, end_time, y_item_list, top_item_list, attrs=GraphFormat(), | 18 | def __init__(self, CanvasType, surface, start_time, end_time, y_item_list, top_item_list, attrs=GraphFormat(), |
18 | item_clist=DEF_ITEM_CLIST, bar_plist=DEF_BAR_PLIST): | 19 | item_clist=DEF_ITEM_CLIST, bar_plist=DEF_BAR_PLIST): |
@@ -166,9 +167,12 @@ class Graph(object): | |||
166 | """get x so that x is at instant ``time'' on the graph""" | 167 | """get x so that x is at instant ``time'' on the graph""" |
167 | return self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + 1.0 * (time - self.start_time) / self.attrs.time_per_maj * self.attrs.maj_sep | 168 | return self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + 1.0 * (time - self.start_time) / self.attrs.time_per_maj * self.attrs.maj_sep |
168 | 169 | ||
170 | def get_item_yorigin(self, item_no): | ||
171 | return self.origin[1] - self._get_y_axis_height() + self.attrs.y_item_size * item_no; | ||
172 | |||
169 | def get_item_ypos(self, item_no): | 173 | def get_item_ypos(self, item_no): |
170 | """get y so that y is where the top of a bar would be in item #n's area""" | 174 | """get y so that y is where the top of a bar would be in item #n's area""" |
171 | return self.origin[1] - self._get_y_axis_height() + self.attrs.y_item_size * (item_no + 0.5 - GraphFormat.BAR_SIZE_FACTOR / 2.0) | 175 | return self.get_item_yorigin(item_no) + self.attrs.y_item_size * (0.5 - GraphFormat.BAR_SIZE_FACTOR / 2.0) |
172 | 176 | ||
173 | def _get_bar_width(self, start_time, end_time): | 177 | def _get_bar_width(self, start_time, end_time): |
174 | return 1.0 * (end_time - start_time) / self.attrs.time_per_maj * self.attrs.maj_sep | 178 | return 1.0 * (end_time - start_time) / self.attrs.time_per_maj * self.attrs.maj_sep |
@@ -256,6 +260,8 @@ class Graph(object): | |||
256 | for event in sched.get_time_slot_array().get_events(slots, | 260 | for event in sched.get_time_slot_array().get_events(slots, |
257 | self.list_type, schedule.EVENT_LIST): | 261 | self.list_type, schedule.EVENT_LIST): |
258 | events_to_render[event.get_layer()][event] = None | 262 | events_to_render[event.get_layer()][event] = None |
263 | for event in sched.get_jobless(): | ||
264 | events_to_render[event.get_layer()][event] = None | ||
259 | 265 | ||
260 | return events_to_render | 266 | return events_to_render |
261 | 267 | ||
@@ -403,6 +409,16 @@ class Graph(object): | |||
403 | a certain time.""" | 409 | a certain time.""" |
404 | raise NotImplementedError | 410 | raise NotImplementedError |
405 | 411 | ||
412 | def draw_action_symbol_at_time(self, time, task_no, cpu_no, action, | ||
413 | job_no, selected=False): | ||
414 | """Draws an action symbol at a certain time for some task and job""" | ||
415 | raise NotImplementedError | ||
416 | |||
417 | def add_sel_action_symbol_at_time(self, time, task_no, cpu_no, event): | ||
418 | """Same as above, except instead of drawing adds a selectable region at | ||
419 | a certain time.""" | ||
420 | raise NotImplementedError | ||
421 | |||
406 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None): | 422 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None): |
407 | """Draws a bar over a certain time period for some task, optionally labelling it.""" | 423 | """Draws a bar over a certain time period for some task, optionally labelling it.""" |
408 | raise NotImplementedError | 424 | raise NotImplementedError |
@@ -526,6 +542,33 @@ class TaskGraph(Graph): | |||
526 | 542 | ||
527 | self.canvas.add_sel_deadline_arrow_big(x, y, height, event) | 543 | self.canvas.add_sel_deadline_arrow_big(x, y, height, event) |
528 | 544 | ||
545 | def draw_action_symbol_at_time(self, time, task_no, cpu_no, action, | ||
546 | job_no=None, selected=False): | ||
547 | x = self.get_time_xpos(time) | ||
548 | y = None | ||
549 | |||
550 | if task_no != -1: | ||
551 | y = self.get_item_ypos(task_no) | ||
552 | else: | ||
553 | y = self.origin[1] | ||
554 | |||
555 | height = 1.5 * (self.get_item_ypos(0) - self.get_item_yorigin(0)) | ||
556 | |||
557 | self.canvas.draw_action_symbol(cpu_no, action, x, y, height, selected) | ||
558 | |||
559 | def add_sel_action_symbol_at_time(self, time, task_no, cpu_no, event): | ||
560 | x = self.get_time_xpos(time) | ||
561 | y = None | ||
562 | |||
563 | if task_no != -1: | ||
564 | y = self.get_item_ypos(task_no) | ||
565 | else: | ||
566 | y = self.origin[1] | ||
567 | |||
568 | height = 1.5 * (self.get_item_ypos(0) - self.get_item_yorigin(0)) | ||
569 | |||
570 | self.canvas.add_sel_action_symbol(x, y, height, event) | ||
571 | |||
529 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): | 572 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
530 | if start_time > end_time: | 573 | if start_time > end_time: |
531 | raise ValueError("Litmus is not a time machine") | 574 | raise ValueError("Litmus is not a time machine") |
@@ -699,10 +742,27 @@ class CpuGraph(Graph): | |||
699 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR | 742 | height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR |
700 | 743 | ||
701 | x = self.get_time_xpos(time) | 744 | x = self.get_time_xpos(time) |
702 | y = self.origin[1] - height | 745 | y = self.get_item_ypos(task_no) |
703 | 746 | ||
704 | self.canvas.add_sel_deadline_arrow_small(x, y, height, event) | 747 | self.canvas.add_sel_deadline_arrow_small(x, y, height, event) |
705 | 748 | ||
749 | def draw_action_symbol_at_time(self, time, task_no, cpu_no, action, | ||
750 | job_no=None, selected=False): | ||
751 | x = self.get_time_xpos(time) | ||
752 | y = self.get_item_ypos(cpu_no) | ||
753 | |||
754 | height = 1.5 * (y - self.get_item_yorigin(cpu_no)) | ||
755 | |||
756 | self.canvas.draw_action_symbol(task_no, action, x, y, height, selected) | ||
757 | |||
758 | def add_sel_action_symbol_at_time(self, time, task_no, cpu_no, event): | ||
759 | x = self.get_time_xpos(time) | ||
760 | y = self.get_item_ypos(cpu_no) | ||
761 | |||
762 | height = 1.5 * (y - self.get_item_yorigin(cpu_no)) | ||
763 | |||
764 | self.canvas.add_sel_action_symbol(x, y, height, event) | ||
765 | |||
706 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): | 766 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
707 | if start_time > end_time: | 767 | if start_time > end_time: |
708 | raise ValueError("Litmus is not a time machine") | 768 | raise ValueError("Litmus is not a time machine") |
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py index 542524b..fcce10d 100644 --- a/unit_trace/viz/schedule.py +++ b/unit_trace/viz/schedule.py | |||
@@ -181,6 +181,7 @@ class Schedule(object): | |||
181 | self.time_slot_array = None | 181 | self.time_slot_array = None |
182 | self.cur_task_no = 0 | 182 | self.cur_task_no = 0 |
183 | self.num_cpus = num_cpus | 183 | self.num_cpus = num_cpus |
184 | self.jobless = [] | ||
184 | for task in task_list: | 185 | for task in task_list: |
185 | self.add_task(task) | 186 | self.add_task(task) |
186 | 187 | ||
@@ -264,6 +265,9 @@ class Schedule(object): | |||
264 | task.task_no = self.cur_task_no | 265 | task.task_no = self.cur_task_no |
265 | self.cur_task_no += 1 | 266 | self.cur_task_no += 1 |
266 | 267 | ||
268 | def add_jobless(self, event): | ||
269 | self.jobless.append(event) | ||
270 | |||
267 | def sort_task_nos_numeric(self): | 271 | def sort_task_nos_numeric(self): |
268 | # sort task numbers by the numeric value of the task names. | 272 | # sort task numbers by the numeric value of the task names. |
269 | nums = [] | 273 | nums = [] |
@@ -275,6 +279,9 @@ class Schedule(object): | |||
275 | for no, task in enumerate(nums): | 279 | for no, task in enumerate(nums): |
276 | self.tasks[task[1]].task_no = no | 280 | self.tasks[task[1]].task_no = no |
277 | 281 | ||
282 | def get_jobless(self): | ||
283 | return self.jobless | ||
284 | |||
278 | def get_tasks(self): | 285 | def get_tasks(self): |
279 | return self.tasks | 286 | return self.tasks |
280 | 287 | ||
@@ -418,12 +425,12 @@ class DummyEvent(object): | |||
418 | event added by the application to speed things up or keep track of | 425 | event added by the application to speed things up or keep track of |
419 | something. Such an event won't be added to the schedule tree, but | 426 | something. Such an event won't be added to the schedule tree, but |
420 | might appear in the time slot array.""" | 427 | might appear in the time slot array.""" |
421 | |||
422 | def __init__(self, time, cpu): | 428 | def __init__(self, time, cpu): |
423 | self.time = time | 429 | self.time = time |
424 | self.cpu = cpu | 430 | self.cpu = cpu |
425 | self.job = None | 431 | self.job = None |
426 | self.layer = None | 432 | self.layer = None |
433 | self.saved_schedule = None | ||
427 | 434 | ||
428 | def get_time(self): | 435 | def get_time(self): |
429 | return self.time | 436 | return self.time |
@@ -431,11 +438,24 @@ class DummyEvent(object): | |||
431 | def get_cpu(self): | 438 | def get_cpu(self): |
432 | return self.cpu | 439 | return self.cpu |
433 | 440 | ||
441 | # Refactor, shouldn't depend on job | ||
434 | def get_schedule(self): | 442 | def get_schedule(self): |
435 | return self.get_task().get_schedule() | 443 | if self.saved_schedule is not None: |
444 | return self.saved_schedule | ||
445 | elif self.get_task() is not None: | ||
446 | return self.get_task().get_schedule() | ||
447 | else: | ||
448 | return None | ||
449 | |||
450 | # Needed for events not assigned to specific tasks | ||
451 | def set_schedule(self, schedule): | ||
452 | self.saved_schedule = schedule | ||
436 | 453 | ||
437 | def get_task(self): | 454 | def get_task(self): |
438 | return self.get_job().get_task() | 455 | if self.get_job() is not None: |
456 | return self.get_job().get_task() | ||
457 | else: | ||
458 | return None | ||
439 | 459 | ||
440 | def get_job(self): | 460 | def get_job(self): |
441 | return self.job | 461 | return self.job |
@@ -476,21 +496,33 @@ class Event(DummyEvent): | |||
476 | ' ' + str(unit) | 496 | ' ' + str(unit) |
477 | 497 | ||
478 | def str_long(self, unit): | 498 | def str_long(self, unit): |
479 | """Prints the event as a string, in ``long'' form.""" | 499 | if self.get_job() is not None: |
480 | return 'Event Information\n-----------------\n' + \ | 500 | """Prints the event as a string, in ``long'' form.""" |
481 | 'Event Type: ' + self.get_name() + \ | 501 | return 'Event Information\n-----------------\n' + \ |
482 | '\nTask Name: ' + str(self.get_job().get_task().get_name()) + \ | 502 | 'Event Type: ' + self.get_name() + \ |
483 | '\n(Task no., Job no.): ' + str((self.get_job().get_task().get_task_no(), \ | 503 | '\nTask Name: ' + str(self.get_job().get_task().get_name()) + \ |
484 | self.get_job().get_job_no())) + \ | 504 | '\n(Task no., Job no.): ' + str((self.get_job().get_task().get_task_no(), \ |
485 | '\nCPU: ' + str(self.get_cpu()) + \ | 505 | self.get_job().get_job_no())) + \ |
486 | '\nTime: ' + _format_time(self.get_time(), unit) + \ | 506 | '\nCPU: ' + str(self.get_cpu()) + \ |
487 | '\n\n' + self.get_job().str_long(unit) | 507 | '\nTime: ' + _format_time(self.get_time(), unit) + \ |
508 | '\n\n' + self.get_job().str_long(unit) | ||
509 | else: | ||
510 | """Prints the event as a string, in ``long'' form.""" | ||
511 | return 'Event Information\n-----------------\n' + \ | ||
512 | 'Event Type: ' + self.get_name() + \ | ||
513 | '\nTask Name: None' + \ | ||
514 | '\nCPU: ' + str(self.get_cpu()) + \ | ||
515 | '\nTime: ' + _format_time(self.get_time(), unit) | ||
488 | 516 | ||
489 | def _common_str(self): | 517 | def _common_str(self): |
490 | job = self.get_job() | 518 | if self.get_job() is not None: |
491 | task = job.get_task() | 519 | job = self.get_job() |
492 | return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \ | 520 | task = job.get_task() |
493 | job.get_job_no())) + ', CPU=' + str(self.get_cpu()) | 521 | return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + \ |
522 | str((task.get_task_no(), job.get_job_no())) + \ | ||
523 | ', CPU=' + str(self.get_cpu()) | ||
524 | else: | ||
525 | return ', Cpu=' + str(self.get_cpu()) | ||
494 | 526 | ||
495 | def is_erroneous(self): | 527 | def is_erroneous(self): |
496 | """An erroneous event is where something with the event is not quite right, | 528 | """An erroneous event is where something with the event is not quite right, |
@@ -507,16 +539,20 @@ class Event(DummyEvent): | |||
507 | time in the scan, and ``switches'' gives the last time a certain switch | 539 | time in the scan, and ``switches'' gives the last time a certain switch |
508 | (e.g. SwitchToEvent, InversionStartEvent) occurred""" | 540 | (e.g. SwitchToEvent, InversionStartEvent) occurred""" |
509 | time = self.get_time() | 541 | time = self.get_time() |
542 | |||
510 | sched = self.get_schedule() | 543 | sched = self.get_schedule() |
511 | if sched.start is None or time < sched.start: | 544 | |
512 | sched.start = time | 545 | if sched is not None: |
513 | if sched.end is None or time > sched.end: | 546 | if sched.start is None or time < sched.start: |
514 | sched.end = time | 547 | sched.start = time |
515 | 548 | if sched.end is None or time > sched.end: | |
516 | if item_nos is None: | 549 | sched.end = time |
517 | item_nos = { TimeSlotArray.TASK_LIST : self.get_task().get_task_no(), | 550 | |
518 | TimeSlotArray.CPU_LIST : self.get_cpu() } | 551 | if item_nos is None: |
519 | sched.get_time_slot_array().add_event_to_time_slot(self, item_nos) | 552 | item_nos = { TimeSlotArray.TASK_LIST : self.get_task().get_task_no(), |
553 | TimeSlotArray.CPU_LIST : self.get_cpu() } | ||
554 | sched.get_time_slot_array().add_event_to_time_slot(self, item_nos) | ||
555 | |||
520 | self.fill_span_event_from_end() | 556 | self.fill_span_event_from_end() |
521 | 557 | ||
522 | def fill_span_event_from_start(self): | 558 | def fill_span_event_from_start(self): |
@@ -843,9 +879,42 @@ class DeadlineEvent(Event): | |||
843 | graph.add_sel_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), | 879 | graph.add_sel_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), |
844 | self) | 880 | self) |
845 | else: | 881 | else: |
846 | graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), | 882 | graph.draw_deadline_arrow_at_time(self.get_time(), |
847 | self.get_job().get_job_no(), self.is_selected()) | 883 | self.get_job().get_task().get_task_no(), |
884 | self.get_job().get_job_no(), self.is_selected()) | ||
848 | 885 | ||
886 | class ActionEvent(Event): | ||
887 | def __init__(self, time, cpu, action): | ||
888 | super(ActionEvent, self).__init__(time, cpu) | ||
889 | self.layer = Canvas.TOP_LAYER | ||
890 | self.action = int(action) | ||
891 | |||
892 | def get_name(self): | ||
893 | return 'Action' | ||
894 | |||
895 | def scan(self, cur_cpu, switches): | ||
896 | item_nos = { TimeSlotArray.TASK_LIST : self.get_task().get_task_no(), | ||
897 | TimeSlotArray.CPU_LIST : TimeSlotArray.POST_ITEM_NO } | ||
898 | super(ActionEvent, self).scan(cur_cpu, switches, item_nos) | ||
899 | |||
900 | def render(self, graph, layer, prev_events, selectable=False): | ||
901 | prev_events[self] = None | ||
902 | if layer == Canvas.TOP_LAYER: | ||
903 | |||
904 | # TODO: need a more official way of doing this | ||
905 | task_no = -1 | ||
906 | job_no = -1 | ||
907 | if self.get_job() is not None: | ||
908 | task_no = self.get_job().get_task().get_task_no() | ||
909 | job_no = self.get_job().get_job_no() | ||
910 | |||
911 | if selectable: | ||
912 | graph.add_sel_action_symbol_at_time(self.get_time(), task_no, | ||
913 | self.get_cpu(), self) | ||
914 | else: | ||
915 | graph.draw_action_symbol_at_time(self.get_time(), task_no, | ||
916 | self.get_cpu(), self.action, | ||
917 | job_no, self.is_selected()) | ||
849 | 918 | ||
850 | class InversionStartEvent(StartSpanEvent): | 919 | class InversionStartEvent(StartSpanEvent): |
851 | def __init__(self, time): | 920 | def __init__(self, time): |
@@ -1041,7 +1110,7 @@ EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None, | |||
1041 | SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None, | 1110 | SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None, |
1042 | DeadlineEvent : None, IsRunningDummy : None, | 1111 | DeadlineEvent : None, IsRunningDummy : None, |
1043 | InversionStartEvent : None, InversionEndEvent : None, | 1112 | InversionStartEvent : None, InversionEndEvent : None, |
1044 | InversionDummy : None, TaskDummy : None, CPUDummy : None} | 1113 | InversionDummy : None, TaskDummy : None, CPUDummy : None, ActionEvent: None} |
1045 | 1114 | ||
1046 | SPAN_START_EVENTS = { SwitchToEvent : IsRunningDummy, InversionStartEvent : InversionDummy } | 1115 | SPAN_START_EVENTS = { SwitchToEvent : IsRunningDummy, InversionStartEvent : InversionDummy } |
1047 | SPAN_END_EVENTS = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy} | 1116 | SPAN_END_EVENTS = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy} |