diff options
| -rw-r--r-- | unit_trace/viz/convert.py | 4 | ||||
| -rw-r--r-- | unit_trace/viz/draw.py | 42 | ||||
| -rw-r--r-- | unit_trace/viz/schedule.py | 236 | ||||
| -rw-r--r-- | unit_trace/viz/viewer.py | 1 |
4 files changed, 177 insertions, 106 deletions
diff --git a/unit_trace/viz/convert.py b/unit_trace/viz/convert.py index f37dd27..8ebdbdc 100644 --- a/unit_trace/viz/convert.py +++ b/unit_trace/viz/convert.py | |||
| @@ -54,8 +54,8 @@ def convert_trace_to_schedule(stream): | |||
| 54 | job.add_event(DeadlineEvent(record.deadline, cpu)))), | 54 | job.add_event(DeadlineEvent(record.deadline, cpu)))), |
| 55 | 'switch_to' : (lambda : | 55 | 'switch_to' : (lambda : |
| 56 | job.add_event(SwitchToEvent(record.when, cpu))), | 56 | job.add_event(SwitchToEvent(record.when, cpu))), |
| 57 | 'switch_away' : lambda : | 57 | 'switch_away' : (lambda : |
| 58 | job.add_event(SwitchAwayEvent(record.when, cpu)), | 58 | job.add_event(SwitchAwayEvent(record.when, cpu))), |
| 59 | 'assign' : (noop), | 59 | 'assign' : (noop), |
| 60 | 'completion' : (lambda : | 60 | 'completion' : (lambda : |
| 61 | job.add_event(CompleteEvent(record.when, cpu))), | 61 | job.add_event(CompleteEvent(record.when, cpu))), |
diff --git a/unit_trace/viz/draw.py b/unit_trace/viz/draw.py index e28ed24..8c48744 100644 --- a/unit_trace/viz/draw.py +++ b/unit_trace/viz/draw.py | |||
| @@ -316,7 +316,17 @@ class Canvas(object): | |||
| 316 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) | 316 | self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) |
| 317 | x += maj_sep | 317 | x += maj_sep |
| 318 | 318 | ||
| 319 | def draw_bar(self, x, y, width, height, n, selected): | 319 | def _draw_bar_border_common(self, x, y, width, height, color, thickness, clip_side): |
| 320 | if clip_side is None: | ||
| 321 | self.draw_rect(x, y, width, height, color, thickness) | ||
| 322 | elif clip_side == AlignMode.LEFT: | ||
| 323 | self.draw_polyline([(x, y), (x + width, y), (x + width, y + height), (x, y + height)], | ||
| 324 | color, thickness) | ||
| 325 | elif clip_side == AlignMode.RIGHT: | ||
| 326 | self.draw_polyline([(x + width, y), (x, y), (x, y + height), (x + width, y + height)], | ||
| 327 | color, thickness) | ||
| 328 | |||
| 329 | def draw_bar(self, x, y, width, height, n, clip_side, selected): | ||
| 320 | """Draws a bar with a certain set of dimensions, using pattern ``n'' from the | 330 | """Draws a bar with a certain set of dimensions, using pattern ``n'' from the |
| 321 | bar pattern list.""" | 331 | bar pattern list.""" |
| 322 | 332 | ||
| @@ -325,12 +335,13 @@ class Canvas(object): | |||
| 325 | 335 | ||
| 326 | # use a pattern to be pretty | 336 | # use a pattern to be pretty |
| 327 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) | 337 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) |
| 328 | self.draw_rect(x, y, width, height, color, thickness) | 338 | |
| 339 | self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side) | ||
| 329 | 340 | ||
| 330 | def add_sel_bar(self, x, y, width, height, event): | 341 | def add_sel_bar(self, x, y, width, height, event): |
| 331 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) | 342 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) |
| 332 | 343 | ||
| 333 | def draw_mini_bar(self, x, y, width, height, n, selected): | 344 | def draw_mini_bar(self, x, y, width, height, n, clip_side, selected): |
| 334 | """Like the above, except it draws a miniature version. This is usually used for | 345 | """Like the above, except it draws a miniature version. This is usually used for |
| 335 | secondary purposes (i.e. to show jobs that _should_ have been running at a certain time). | 346 | secondary purposes (i.e. to show jobs that _should_ have been running at a certain time). |
| 336 | 347 | ||
| @@ -342,7 +353,8 @@ class Canvas(object): | |||
| 342 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected] | 353 | True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected] |
| 343 | 354 | ||
| 344 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) | 355 | self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) |
| 345 | self.draw_rect(x, y, width, height, color, thickness) | 356 | |
| 357 | self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side) | ||
| 346 | 358 | ||
| 347 | def add_sel_mini_bar(self, x, y, width, height, event): | 359 | def add_sel_mini_bar(self, x, y, width, height, event): |
| 348 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) | 360 | self.add_sel_region(SelectableRegion(x, y, width, height, event)) |
| @@ -970,7 +982,7 @@ class Graph(object): | |||
| 970 | a certain time.""" | 982 | a certain time.""" |
| 971 | raise NotImplementedError | 983 | raise NotImplementedError |
| 972 | 984 | ||
| 973 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None): | 985 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None): |
| 974 | """Draws a bar over a certain time period for some task, optionally labelling it.""" | 986 | """Draws a bar over a certain time period for some task, optionally labelling it.""" |
| 975 | raise NotImplementedError | 987 | raise NotImplementedError |
| 976 | 988 | ||
| @@ -979,7 +991,7 @@ class Graph(object): | |||
| 979 | a certain time.""" | 991 | a certain time.""" |
| 980 | raise NotImplementedError | 992 | raise NotImplementedError |
| 981 | 993 | ||
| 982 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None): | 994 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, clip_side=None, job_no=None): |
| 983 | """Draws a mini bar over a certain time period for some task, optionally labelling it.""" | 995 | """Draws a mini bar over a certain time period for some task, optionally labelling it.""" |
| 984 | raise NotImplementedError | 996 | raise NotImplementedError |
| 985 | 997 | ||
| @@ -1099,7 +1111,7 @@ class TaskGraph(Graph): | |||
| 1099 | 1111 | ||
| 1100 | self.canvas.add_sel_deadline_arrow_big(x, y, height, event) | 1112 | self.canvas.add_sel_deadline_arrow_big(x, y, height, event) |
| 1101 | 1113 | ||
| 1102 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): | 1114 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
| 1103 | if start_time > end_time: | 1115 | if start_time > end_time: |
| 1104 | raise ValueError("Litmus is not a time machine") | 1116 | raise ValueError("Litmus is not a time machine") |
| 1105 | 1117 | ||
| @@ -1108,7 +1120,7 @@ class TaskGraph(Graph): | |||
| 1108 | width = self._get_bar_width(start_time, end_time) | 1120 | width = self._get_bar_width(start_time, end_time) |
| 1109 | height = self._get_bar_height() | 1121 | height = self._get_bar_height() |
| 1110 | 1122 | ||
| 1111 | self.canvas.draw_bar(x, y, width, height, cpu_no, selected) | 1123 | self.canvas.draw_bar(x, y, width, height, cpu_no, clip_side, selected) |
| 1112 | 1124 | ||
| 1113 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively | 1125 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively |
| 1114 | if job_no is not None: | 1126 | if job_no is not None: |
| @@ -1128,7 +1140,7 @@ class TaskGraph(Graph): | |||
| 1128 | 1140 | ||
| 1129 | self.canvas.add_sel_bar(x, y, width, height, event) | 1141 | self.canvas.add_sel_bar(x, y, width, height, event) |
| 1130 | 1142 | ||
| 1131 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): | 1143 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
| 1132 | if start_time > end_time: | 1144 | if start_time > end_time: |
| 1133 | raise ValueError("Litmus is not a time machine") | 1145 | raise ValueError("Litmus is not a time machine") |
| 1134 | 1146 | ||
| @@ -1137,7 +1149,7 @@ class TaskGraph(Graph): | |||
| 1137 | width = self._get_bar_width(start_time, end_time) | 1149 | width = self._get_bar_width(start_time, end_time) |
| 1138 | height = self._get_mini_bar_height() | 1150 | height = self._get_mini_bar_height() |
| 1139 | 1151 | ||
| 1140 | self.canvas.draw_mini_bar(x, y, width, height, Canvas.NULL_PATTERN, selected) | 1152 | self.canvas.draw_mini_bar(x, y, width, height, Canvas.NULL_PATTERN, clip_side, selected) |
| 1141 | 1153 | ||
| 1142 | if job_no is not None: | 1154 | if job_no is not None: |
| 1143 | x += GraphFormat.MINI_BAR_LABEL_OFS | 1155 | x += GraphFormat.MINI_BAR_LABEL_OFS |
| @@ -1245,7 +1257,7 @@ class CpuGraph(Graph): | |||
| 1245 | x = self._get_time_xpos(time) | 1257 | x = self._get_time_xpos(time) |
| 1246 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 | 1258 | y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 |
| 1247 | 1259 | ||
| 1248 | self.canvas.add_sel_suspend_triangle(x, y, height, event) | 1260 | self.canvas.add_sel_resume_triangle(x, y, height, event) |
| 1249 | 1261 | ||
| 1250 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): | 1262 | def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): |
| 1251 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR | 1263 | height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR |
| @@ -1312,7 +1324,7 @@ class CpuGraph(Graph): | |||
| 1312 | 1324 | ||
| 1313 | self.canvas.add_sel_deadline_arrow_small(x, y, height, event) | 1325 | self.canvas.add_sel_deadline_arrow_small(x, y, height, event) |
| 1314 | 1326 | ||
| 1315 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): | 1327 | def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
| 1316 | if start_time > end_time: | 1328 | if start_time > end_time: |
| 1317 | raise ValueError("Litmus is not a time machine") | 1329 | raise ValueError("Litmus is not a time machine") |
| 1318 | 1330 | ||
| @@ -1321,7 +1333,7 @@ class CpuGraph(Graph): | |||
| 1321 | width = self._get_bar_width(start_time, end_time) | 1333 | width = self._get_bar_width(start_time, end_time) |
| 1322 | height = self._get_bar_height() | 1334 | height = self._get_bar_height() |
| 1323 | 1335 | ||
| 1324 | self.canvas.draw_bar(x, y, width, height, task_no, selected) | 1336 | self.canvas.draw_bar(x, y, width, height, task_no, clip_side, selected) |
| 1325 | 1337 | ||
| 1326 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively | 1338 | # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively |
| 1327 | if job_no is not None: | 1339 | if job_no is not None: |
| @@ -1339,7 +1351,7 @@ class CpuGraph(Graph): | |||
| 1339 | 1351 | ||
| 1340 | self.canvas.add_sel_bar(x, y, width, height, event) | 1352 | self.canvas.add_sel_bar(x, y, width, height, event) |
| 1341 | 1353 | ||
| 1342 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): | 1354 | def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False): |
| 1343 | if start_time > end_time: | 1355 | if start_time > end_time: |
| 1344 | raise ValueError("Litmus is not a time machine") | 1356 | raise ValueError("Litmus is not a time machine") |
| 1345 | 1357 | ||
| @@ -1348,7 +1360,7 @@ class CpuGraph(Graph): | |||
| 1348 | width = self._get_bar_width(start_time, end_time) | 1360 | width = self._get_bar_width(start_time, end_time) |
| 1349 | height = self._get_mini_bar_height() | 1361 | height = self._get_mini_bar_height() |
| 1350 | 1362 | ||
| 1351 | self.canvas.draw_mini_bar(x, y, width, height, task_no, selected) | 1363 | self.canvas.draw_mini_bar(x, y, width, height, task_no, clip_side, selected) |
| 1352 | 1364 | ||
| 1353 | if job_no is not None: | 1365 | if job_no is not None: |
| 1354 | x += GraphFormat.MINI_BAR_LABEL_OFS | 1366 | x += GraphFormat.MINI_BAR_LABEL_OFS |
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py index 4277f1a..5efee7d 100644 --- a/unit_trace/viz/schedule.py +++ b/unit_trace/viz/schedule.py | |||
| @@ -11,6 +11,7 @@ import util | |||
| 11 | import copy | 11 | import copy |
| 12 | 12 | ||
| 13 | EVENT_LIST = None | 13 | EVENT_LIST = None |
| 14 | SPAN_EVENTS = None | ||
| 14 | 15 | ||
| 15 | class TimeSlotArray(object): | 16 | class TimeSlotArray(object): |
| 16 | """Represents another way of organizing the events. This structure organizes events by | 17 | """Represents another way of organizing the events. This structure organizes events by |
| @@ -55,20 +56,47 @@ class TimeSlotArray(object): | |||
| 55 | 56 | ||
| 56 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event) | 57 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event) |
| 57 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event) | 58 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event) |
| 59 | |||
| 60 | if event.__class__ in SPAN_END_EVENTS: | ||
| 61 | self.fill_span_event_from_end(event) | ||
| 62 | |||
| 63 | def fill_span_event_from_end(self, event): | ||
| 64 | start_slot = None | ||
| 65 | if event.corresp_start_event is None: | ||
| 66 | start_slot = self.get_time_slot(event.get_job().get_task().get_schedule().start) - 1 | ||
| 67 | else: | ||
| 68 | start_slot = self.get_time_slot(event.corresp_start_event.get_time()) | ||
| 69 | end_slot = self.get_time_slot(event.get_time()) | ||
| 70 | |||
| 71 | for slot in range(start_slot + 1, end_slot): | ||
| 72 | task_no = event.get_job().get_task().get_task_no() | ||
| 73 | cpu = event.get_cpu() | ||
| 58 | 74 | ||
| 59 | span_events = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy} | 75 | dummy = SPAN_END_EVENTS[event.__class__](task_no, cpu) |
| 60 | 76 | dummy.corresp_start_event = event.corresp_start_event | |
| 61 | for span_event in span_events: | 77 | dummy.corresp_end_event = event |
| 62 | if isinstance(event, span_event) and event.corresp_start_event is not None: | ||
| 63 | start_slot = self.get_time_slot(event.corresp_start_event.get_time()) | ||
| 64 | end_slot = time_slot | ||
| 65 | for slot in range(start_slot + 1, end_slot): | ||
| 66 | dummy = span_events[span_event](task_no, cpu) | ||
| 67 | dummy.corresp_start_event = event.corresp_start_event | ||
| 68 | dummy.corresp_end_event = event | ||
| 69 | 78 | ||
| 70 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) | 79 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) |
| 71 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) | 80 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) |
| 81 | |||
| 82 | def fill_span_event_from_start(self, event): | ||
| 83 | end_slot = None | ||
| 84 | if event.corresp_end_event is None: | ||
| 85 | end_slot = self.get_time_slot(event.get_job().get_task().get_schedule().end) + 1 | ||
| 86 | else: | ||
| 87 | end_slot = self.get_time_slot(event.corresp_end_event.get_time()) | ||
| 88 | start_slot = self.get_time_slot(event.get_time()) | ||
| 89 | |||
| 90 | for slot in range(start_slot + 1, end_slot): | ||
| 91 | task_no = event.get_job().get_task().get_task_no() | ||
| 92 | cpu = event.get_cpu() | ||
| 93 | |||
| 94 | dummy = SPAN_START_EVENTS[event.__class__](task_no, cpu) | ||
| 95 | dummy.corresp_start_event = event | ||
| 96 | dummy.corresp_end_event = event.corresp_end_event | ||
| 97 | |||
| 98 | self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) | ||
| 99 | self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) | ||
| 72 | 100 | ||
| 73 | def iter_over_period(self, start, end, start_no, end_no, list_type, event_types): | 101 | def iter_over_period(self, start, end, start_no, end_no, list_type, event_types): |
| 74 | if self.array is None: | 102 | if self.array is None: |
| @@ -142,18 +170,28 @@ class Schedule(object): | |||
| 142 | self.set_time_params(time_per_maj) | 170 | self.set_time_params(time_per_maj) |
| 143 | 171 | ||
| 144 | # we scan the graph task by task, and job by job | 172 | # we scan the graph task by task, and job by job |
| 145 | switches = {} | ||
| 146 | for event in EVENT_LIST: | ||
| 147 | switches[event] = None | ||
| 148 | for task_no, task in enumerate(self.get_task_list()): | 173 | for task_no, task in enumerate(self.get_task_list()): |
| 174 | switches = {} | ||
| 175 | for event in EVENT_LIST: | ||
| 176 | switches[event] = None | ||
| 149 | cur_cpu = [Event.NO_CPU] | 177 | cur_cpu = [Event.NO_CPU] |
| 150 | for job_no in sorted(task.get_jobs().keys()): | 178 | for job_no in sorted(task.get_jobs().keys()): |
| 151 | job = task.get_jobs()[job_no] | 179 | job = task.get_jobs()[job_no] |
| 152 | for event_time in sorted(job.get_events().keys()): | 180 | for event_time in sorted(job.get_events().keys()): |
| 153 | # could have multiple events at the same time (unlikely but possible) | 181 | # could have multiple events at the same time (unlikely but possible) |
| 154 | for event in job.get_events()[event_time]: | 182 | for event in job.get_events()[event_time]: |
| 155 | #print 'task, job, event:', task.name, job.job_no, event.__class__.__name__ | 183 | print 'task, job, event:', task.name, job.job_no, event.__class__.__name__ |
| 156 | event.scan(cur_cpu, switches) | 184 | event.scan(cur_cpu, switches) |
| 185 | |||
| 186 | # What if one of the initial "span events" (switch to or inversion starting) never got a | ||
| 187 | # corresponding end event? Well, then we assume that the end event was simply outside of | ||
| 188 | # the range of whatever we read in. So we need to fill dummies starting from the initial | ||
| 189 | # event all the way to the end of the graph, so that the renderer can see the event no matter | ||
| 190 | # how far the user scrolls to the right. | ||
| 191 | for span_event in SPAN_START_EVENTS: | ||
| 192 | event = switches[span_event] | ||
| 193 | if event is not None: | ||
| 194 | self.time_slot_array.fill_span_event_from_start(event) | ||
| 157 | 195 | ||
| 158 | def add_task(self, task): | 196 | def add_task(self, task): |
| 159 | if task.name in self.tasks: | 197 | if task.name in self.tasks: |
| @@ -311,7 +349,7 @@ class Event(DummyEvent): | |||
| 311 | sched.start = time | 349 | sched.start = time |
| 312 | if sched.end is None or time > sched.end: | 350 | if sched.end is None or time > sched.end: |
| 313 | sched.end = time | 351 | sched.end = time |
| 314 | 352 | ||
| 315 | sched.get_time_slot_array().add_event_to_time_slot(self) | 353 | sched.get_time_slot_array().add_event_to_time_slot(self) |
| 316 | 354 | ||
| 317 | class ErrorEvent(Event): | 355 | class ErrorEvent(Event): |
| @@ -387,11 +425,59 @@ class CompleteEvent(Event): | |||
| 387 | else: | 425 | else: |
| 388 | graph.draw_completion_marker_at_time(self.get_time(), self.get_job().get_task().get_task_no(), | 426 | graph.draw_completion_marker_at_time(self.get_time(), self.get_job().get_task().get_task_no(), |
| 389 | self.get_cpu(), self.is_selected()) | 427 | self.get_cpu(), self.is_selected()) |
| 428 | |||
| 429 | class SwitchToEvent(Event): | ||
| 430 | def __init__(self, time, cpu): | ||
| 431 | super(SwitchToEvent, self).__init__(time, cpu) | ||
| 432 | self.layer = Canvas.BOTTOM_LAYER | ||
| 433 | self.corresp_end_event = None | ||
| 434 | |||
| 435 | def __str__(self): | ||
| 436 | if self.corresp_end_event is None: | ||
| 437 | return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \ | ||
| 438 | + str(self.get_time()) | ||
| 439 | return 'Scheduled' + self._common_str() + ', START=' \ | ||
| 440 | + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ | ||
| 441 | + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) | ||
| 442 | |||
| 443 | def scan(self, cur_cpu, switches): | ||
| 444 | old_cur_cpu = cur_cpu[0] | ||
| 445 | cur_cpu[0] = self.get_cpu() | ||
| 446 | switches[SwitchToEvent] = self | ||
| 447 | self.corresp_end_event = None | ||
| 390 | 448 | ||
| 449 | if old_cur_cpu != Event.NO_CPU: | ||
| 450 | self.erroneous = True | ||
| 451 | print "currently scheduled somewhere, can't switch to a CPU" | ||
| 452 | |||
| 453 | super(SwitchToEvent, self).scan(cur_cpu, switches) | ||
| 454 | |||
| 455 | def render(self, graph, layer, prev_events, selectable=False): | ||
| 456 | if layer == self.layer: | ||
| 457 | end_time = None | ||
| 458 | clip = None | ||
| 459 | if self.corresp_end_event is None: | ||
| 460 | end_time = self.get_job().get_task().get_schedule().end | ||
| 461 | clip = AlignMode.RIGHT | ||
| 462 | else: | ||
| 463 | end_time = self.corresp_end_event.get_time() | ||
| 464 | |||
| 465 | prev_events[self] = None | ||
| 466 | cpu = self.get_cpu() | ||
| 467 | task_no = self.get_job().get_task().get_task_no() | ||
| 468 | if selectable: | ||
| 469 | graph.add_sel_bar_at_time(self.get_time(), end_time, | ||
| 470 | task_no, cpu, self) | ||
| 471 | else: | ||
| 472 | graph.draw_bar_at_time(self.get_time(), end_time, | ||
| 473 | task_no, cpu, self.get_job().get_job_no(), | ||
| 474 | clip, self.is_selected()) | ||
| 475 | |||
| 391 | class SwitchAwayEvent(Event): | 476 | class SwitchAwayEvent(Event): |
| 392 | def __init__(self, time, cpu): | 477 | def __init__(self, time, cpu): |
| 393 | super(SwitchAwayEvent, self).__init__(time, cpu) | 478 | super(SwitchAwayEvent, self).__init__(time, cpu) |
| 394 | self.layer = Canvas.BOTTOM_LAYER | 479 | self.layer = Canvas.BOTTOM_LAYER |
| 480 | self.corresp_start_event = None | ||
| 395 | 481 | ||
| 396 | def __str__(self): | 482 | def __str__(self): |
| 397 | if self.corresp_start_event is None: | 483 | if self.corresp_start_event is None: |
| @@ -431,63 +517,19 @@ class SwitchAwayEvent(Event): | |||
| 431 | prev_events[self] = None | 517 | prev_events[self] = None |
| 432 | cpu = self.get_cpu() | 518 | cpu = self.get_cpu() |
| 433 | task_no = self.get_job().get_task().get_task_no() | 519 | task_no = self.get_job().get_task().get_task_no() |
| 520 | start = self.get_job().get_task().get_schedule().start | ||
| 434 | if selectable: | 521 | if selectable: |
| 435 | start = self.get_job().get_task().get_schedule().start | ||
| 436 | graph.add_sel_bar_at_time(start, self.get_time(), | 522 | graph.add_sel_bar_at_time(start, self.get_time(), |
| 437 | task_no, cpu, self) | 523 | task_no, cpu, self) |
| 438 | else: | 524 | else: |
| 439 | graph.draw_bar_at_time(start, self.get_time(), | 525 | graph.draw_bar_at_time(start, self.get_time(), |
| 440 | task_no, cpu, self.get_job().get_job_no(), self.is_selected()) | 526 | task_no, cpu, self.get_job().get_job_no(), |
| 527 | AlignMode.LEFT, self.is_selected()) | ||
| 441 | else: | 528 | else: |
| 442 | if self.corresp_start_event in prev_events: | 529 | if self.corresp_start_event in prev_events: |
| 443 | return # already rendered the bar | 530 | return # already rendered the bar |
| 444 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | 531 | self.corresp_start_event.render(graph, layer, prev_events, selectable) |
| 445 | 532 | ||
| 446 | class SwitchToEvent(Event): | ||
| 447 | def __init__(self, time, cpu): | ||
| 448 | super(SwitchToEvent, self).__init__(time, cpu) | ||
| 449 | self.layer = Canvas.BOTTOM_LAYER | ||
| 450 | |||
| 451 | def __str__(self): | ||
| 452 | if self.corresp_end_event is None: | ||
| 453 | return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \ | ||
| 454 | + str(self.get_time()) | ||
| 455 | return 'Scheduled' + self._common_str() + ', START=' \ | ||
| 456 | + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ | ||
| 457 | + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) | ||
| 458 | |||
| 459 | def scan(self, cur_cpu, switches): | ||
| 460 | old_cur_cpu = cur_cpu[0] | ||
| 461 | cur_cpu[0] = self.get_cpu() | ||
| 462 | switches[SwitchToEvent] = self | ||
| 463 | self.corresp_end_event = None | ||
| 464 | |||
| 465 | if old_cur_cpu != Event.NO_CPU: | ||
| 466 | self.erroneous = True | ||
| 467 | print "currently scheduled somewhere, can't switch to a CPU" | ||
| 468 | |||
| 469 | super(SwitchToEvent, self).scan(cur_cpu, switches) | ||
| 470 | |||
| 471 | def render(self, graph, layer, prev_events, selectable=False): | ||
| 472 | if self.corresp_end_event is None: | ||
| 473 | return # fatally erroneous switch to | ||
| 474 | if layer == self.layer: | ||
| 475 | end_time = None | ||
| 476 | if self.corresp_end_event is None: | ||
| 477 | end_time = self.get_job().get_task().get_schedule().end | ||
| 478 | else: | ||
| 479 | end_time = self.corresp_end_event.get_time() | ||
| 480 | |||
| 481 | prev_events[self] = None | ||
| 482 | cpu = self.get_cpu() | ||
| 483 | task_no = self.get_job().get_task().get_task_no() | ||
| 484 | if selectable: | ||
| 485 | graph.add_sel_bar_at_time(self.get_time(), end_time, | ||
| 486 | task_no, cpu, self) | ||
| 487 | else: | ||
| 488 | graph.draw_bar_at_time(self.get_time(), end_time, | ||
| 489 | task_no, cpu, self.get_job().get_job_no(), self.is_selected()) | ||
| 490 | |||
| 491 | class ReleaseEvent(Event): | 533 | class ReleaseEvent(Event): |
| 492 | def __init__(self, time, cpu): | 534 | def __init__(self, time, cpu): |
| 493 | super(ReleaseEvent, self).__init__(time, cpu) | 535 | super(ReleaseEvent, self).__init__(time, cpu) |
| @@ -536,6 +578,7 @@ class InversionStartEvent(ErrorEvent): | |||
| 536 | def __init__(self, time): | 578 | def __init__(self, time): |
| 537 | super(InversionStartEvent, self).__init__(time, Event.NO_CPU) | 579 | super(InversionStartEvent, self).__init__(time, Event.NO_CPU) |
| 538 | self.layer = Canvas.BOTTOM_LAYER | 580 | self.layer = Canvas.BOTTOM_LAYER |
| 581 | self.corresp_end_event = None | ||
| 539 | 582 | ||
| 540 | def __str__(self): | 583 | def __str__(self): |
| 541 | if self.corresp_end_event is None: | 584 | if self.corresp_end_event is None: |
| @@ -553,28 +596,33 @@ class InversionStartEvent(ErrorEvent): | |||
| 553 | super(InversionStartEvent, self).scan(cur_cpu, switches) | 596 | super(InversionStartEvent, self).scan(cur_cpu, switches) |
| 554 | 597 | ||
| 555 | def render(self, graph, layer, prev_events, selectable=False): | 598 | def render(self, graph, layer, prev_events, selectable=False): |
| 556 | end_time = None | ||
| 557 | if self.corresp_end_event is None: | ||
| 558 | end_time = self.get_job().get_task().get_schedule().end | ||
| 559 | else: | ||
| 560 | end_time = self.corresp_end_event.get_time() | ||
| 561 | |||
| 562 | if layer == self.layer: | 599 | if layer == self.layer: |
| 563 | prev_events[self] = None | 600 | end_time = None |
| 564 | cpu = self.get_cpu() | 601 | clip = None |
| 565 | task_no = self.get_job().get_task().get_task_no() | 602 | if self.corresp_end_event is None: |
| 566 | if selectable: | 603 | end_time = self.get_job().get_task().get_schedule().end |
| 567 | graph.add_sel_mini_bar_at_time(self.get_time(), end_time, | 604 | clip = AlignMode.RIGHT |
| 568 | task_no, cpu, self) | ||
| 569 | else: | 605 | else: |
| 570 | graph.draw_mini_bar_at_time(self.get_time(), end_time, | 606 | end_time = self.corresp_end_event.get_time() |
| 571 | task_no, cpu, self.get_job().get_job_no(), self.is_selected()) | 607 | |
| 608 | if layer == self.layer: | ||
| 609 | prev_events[self] = None | ||
| 610 | cpu = self.get_cpu() | ||
| 611 | task_no = self.get_job().get_task().get_task_no() | ||
| 612 | if selectable: | ||
| 613 | graph.add_sel_mini_bar_at_time(self.get_time(), end_time, | ||
| 614 | task_no, cpu, self) | ||
| 615 | else: | ||
| 616 | graph.draw_mini_bar_at_time(self.get_time(), end_time, | ||
| 617 | task_no, cpu, self.get_job().get_job_no(), | ||
| 618 | clip, self.is_selected()) | ||
| 572 | 619 | ||
| 573 | 620 | ||
| 574 | class InversionEndEvent(ErrorEvent): | 621 | class InversionEndEvent(ErrorEvent): |
| 575 | def __init__(self, time): | 622 | def __init__(self, time): |
| 576 | super(InversionEndEvent, self).__init__(time, Event.NO_CPU) | 623 | super(InversionEndEvent, self).__init__(time, Event.NO_CPU) |
| 577 | self.layer = Canvas.BOTTOM_LAYER | 624 | self.layer = Canvas.BOTTOM_LAYER |
| 625 | self.corresp_start_event = None | ||
| 578 | 626 | ||
| 579 | def __str__(self): | 627 | def __str__(self): |
| 580 | if self.corresp_start_event is None: | 628 | if self.corresp_start_event is None: |
| @@ -607,13 +655,14 @@ class InversionEndEvent(ErrorEvent): | |||
| 607 | prev_events[self] = None | 655 | prev_events[self] = None |
| 608 | cpu = self.get_cpu() | 656 | cpu = self.get_cpu() |
| 609 | task_no = self.get_job().get_task().get_task_no() | 657 | task_no = self.get_job().get_task().get_task_no() |
| 658 | start = self.get_job().get_task().get_schedule().start | ||
| 610 | if selectable: | 659 | if selectable: |
| 611 | start = self.get_job().get_task().get_schedule().start | ||
| 612 | graph.add_sel_mini_bar_at_time(start, self.get_time(), | 660 | graph.add_sel_mini_bar_at_time(start, self.get_time(), |
| 613 | task_no, cpu, self) | 661 | task_no, cpu, self) |
| 614 | else: | 662 | else: |
| 615 | graph.draw_mini_bar_at_time(start, self.get_time(), | 663 | graph.draw_mini_bar_at_time(start, self.get_time(), |
| 616 | task_no, cpu, self.get_job().get_job_no(), self.is_selected()) | 664 | task_no, cpu, self.get_job().get_job_no(), |
| 665 | AlignMode.LEFT, self.is_selected()) | ||
| 617 | else: | 666 | else: |
| 618 | if self.corresp_start_event in prev_events: | 667 | if self.corresp_start_event in prev_events: |
| 619 | return # already rendered the bar | 668 | return # already rendered the bar |
| @@ -625,11 +674,14 @@ class InversionDummy(DummyEvent): | |||
| 625 | self.layer = Canvas.BOTTOM_LAYER | 674 | self.layer = Canvas.BOTTOM_LAYER |
| 626 | 675 | ||
| 627 | def render(self, graph, layer, prev_events, selectable=False): | 676 | def render(self, graph, layer, prev_events, selectable=False): |
| 628 | if self.corresp_start_event is not None and self.corresp_start_event in prev_events: | 677 | if self.corresp_start_event is None: |
| 629 | return # we have already been rendered | 678 | if self.corresp_end_event in prev_events: |
| 630 | if self.corresp_end_event is not None and self.corresp_end_event in prev_events: | 679 | return # we have already been rendered |
| 631 | return | 680 | self.corresp_end_event.render(graph, layer, prev_events, selectable) |
| 632 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | 681 | else: |
| 682 | if self.corresp_start_event in prev_events: | ||
| 683 | return # we have already been rendered | ||
| 684 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | ||
| 633 | 685 | ||
| 634 | class IsRunningDummy(DummyEvent): | 686 | class IsRunningDummy(DummyEvent): |
| 635 | def __init__(self, time, cpu): | 687 | def __init__(self, time, cpu): |
| @@ -637,12 +689,20 @@ class IsRunningDummy(DummyEvent): | |||
| 637 | self.layer = Canvas.BOTTOM_LAYER | 689 | self.layer = Canvas.BOTTOM_LAYER |
| 638 | 690 | ||
| 639 | def render(self, graph, layer, prev_events, selectable=False): | 691 | def render(self, graph, layer, prev_events, selectable=False): |
| 640 | if self.corresp_start_event is None or self.corresp_start_event in prev_events: | 692 | if self.corresp_start_event is None: |
| 641 | return # we have already been rendered | 693 | if self.corresp_end_event in prev_events: |
| 642 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | 694 | return # we have already been rendered |
| 695 | self.corresp_end_event.render(graph, layer, prev_events, selectable) | ||
| 696 | else: | ||
| 697 | if self.corresp_start_event in prev_events: | ||
| 698 | return # we have already been rendered | ||
| 699 | self.corresp_start_event.render(graph, layer, prev_events, selectable) | ||
| 643 | 700 | ||
| 644 | EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None, | 701 | EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None, |
| 645 | SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None, | 702 | SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None, |
| 646 | DeadlineEvent : None, IsRunningDummy : None, | 703 | DeadlineEvent : None, IsRunningDummy : None, |
| 647 | InversionStartEvent : None, InversionEndEvent : None, | 704 | InversionStartEvent : None, InversionEndEvent : None, |
| 648 | InversionDummy : None} | 705 | InversionDummy : None} |
| 706 | |||
| 707 | SPAN_START_EVENTS = { SwitchToEvent : IsRunningDummy, InversionStartEvent : InversionDummy } | ||
| 708 | SPAN_END_EVENTS = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy} | ||
diff --git a/unit_trace/viz/viewer.py b/unit_trace/viz/viewer.py index 236a467..909da76 100644 --- a/unit_trace/viz/viewer.py +++ b/unit_trace/viz/viewer.py | |||
| @@ -68,7 +68,6 @@ class GraphArea(gtk.DrawingArea): | |||
| 68 | # window manager must have caused the expose event. So just update the | 68 | # window manager must have caused the expose event. So just update the |
| 69 | # expose_event's bounding area. | 69 | # expose_event's bounding area. |
| 70 | if not self.dirtied_regions or expose_event.send_event: | 70 | if not self.dirtied_regions or expose_event.send_event: |
| 71 | print 'forced expose' | ||
| 72 | self.dirtied_regions = [(expose_event.area.x, expose_event.area.y, | 71 | self.dirtied_regions = [(expose_event.area.x, expose_event.area.y, |
| 73 | expose_event.area.width, expose_event.area.height)] | 72 | expose_event.area.width, expose_event.area.height)] |
| 74 | 73 | ||
