1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2009, 2010 Benjamin Poirier <benjamin.poirier@polymtl.ca>
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 2.1 of the License, or (at
7 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #define _ISOC99_SOURCE
25 #include <netinet/in.h>
31 #include "sync_chain.h"
32 #include "event_processing_lttng_common.h"
34 #include "event_processing_lttng_standard.h"
36 /* IPv4 Ethertype, taken from <linux/if_ether.h>, unlikely to change as it's
37 * defined by IANA: http://www.iana.org/assignments/ethernet-numbers
39 #define ETH_P_IP 0x0800
42 // Functions common to all processing modules
43 static void initProcessingLTTVStandard(SyncState
* const syncState
, ...);
44 static void destroyProcessingLTTVStandard(SyncState
* const syncState
);
46 static void finalizeProcessingLTTVStandard(SyncState
* const syncState
);
47 static void printProcessingStatsLTTVStandard(SyncState
* const syncState
);
48 static void writeProcessingGraphVariablesLTTVStandard(SyncState
* const
49 syncState
, const unsigned int i
);
50 static void writeProcessingTraceTraceOptionsLTTVStandard(SyncState
* const
51 syncState
, const unsigned int i
, const unsigned int j
);
52 static void writeProcessingTraceTimeOptionsLTTVStandard(SyncState
* const
53 syncState
, const unsigned int i
, const unsigned int j
);
55 // Functions specific to this module
56 static gboolean
processEventLTTVStandard(void* hookData
, void* callData
);
57 static void partialDestroyProcessingLTTVStandard(SyncState
* const syncState
);
60 static ProcessingModule processingModuleLTTVStandard
= {
61 .name
= "LTTV-standard",
62 .initProcessing
= &initProcessingLTTVStandard
,
63 .destroyProcessing
= &destroyProcessingLTTVStandard
,
64 .finalizeProcessing
= &finalizeProcessingLTTVStandard
,
65 .printProcessingStats
= &printProcessingStatsLTTVStandard
,
67 .writeVariables
= &writeProcessingGraphVariablesLTTVStandard
,
68 .writeTraceTraceOptions
= &writeProcessingTraceTraceOptionsLTTVStandard
,
69 .writeTraceTimeOptions
= &writeProcessingTraceTimeOptionsLTTVStandard
,
75 * Processing Module registering function
77 void registerProcessingLTTVStandard()
79 g_queue_push_tail(&processingModules
, &processingModuleLTTVStandard
);
86 * Allocate and initialize data structures for synchronizing a traceset.
87 * Register event hooks.
90 * syncState: container for synchronization data.
91 * This function allocates these processingData members:
96 * traceSetContext: LttvTracesetContext*, set of LTTV traces
98 static void initProcessingLTTVStandard(SyncState
* const syncState
, ...)
101 ProcessingDataLTTVStandard
* processingData
;
104 processingData
= malloc(sizeof(ProcessingDataLTTVStandard
));
105 syncState
->processingData
= processingData
;
106 va_start(ap
, syncState
);
107 processingData
->traceSetContext
= va_arg(ap
, LttvTracesetContext
*);
110 lttv_traceset_number(processingData
->traceSetContext
->ts
);
111 processingData
->hookListList
= g_array_sized_new(FALSE
, FALSE
,
112 sizeof(GArray
*), syncState
->traceNb
);
114 processingData
->traceNumTable
= g_hash_table_new(&g_direct_hash
, NULL
);
115 for(i
= 0; i
< syncState
->traceNb
; i
++)
117 g_hash_table_insert(processingData
->traceNumTable
,
118 processingData
->traceSetContext
->traces
[i
]->t
,
119 GUINT_TO_POINTER(i
));
122 processingData
->pendingRecv
= malloc(sizeof(GHashTable
*) *
124 for(i
= 0; i
< syncState
->traceNb
; i
++)
126 processingData
->pendingRecv
[i
]= g_hash_table_new_full(&g_direct_hash
,
127 NULL
, NULL
, &gdnDestroyEvent
);
130 if (syncState
->stats
)
132 processingData
->stats
= calloc(1, sizeof(ProcessingStatsLTTVStandard
));
136 processingData
->stats
= NULL
;
139 if (syncState
->graphsStream
)
141 processingData
->graphs
= malloc(syncState
->traceNb
*
142 sizeof(ProcessingGraphsLTTVStandard
));
144 for(i
= 0; i
< syncState
->traceNb
; i
++)
146 LttTrace
* traceI
= processingData
->traceSetContext
->traces
[i
]->t
;
148 processingData
->graphs
[i
].startFreq
= traceI
->start_freq
;
149 processingData
->graphs
[i
].freqScale
= traceI
->freq_scale
;
154 processingData
->graphs
= NULL
;
157 registerHooks(processingData
->hookListList
,
158 processingData
->traceSetContext
, &processEventLTTVStandard
, syncState
,
159 syncState
->matchingModule
->canMatch
);
164 * Call the partial processing destroyer, obtain and adjust the factors from
168 * syncState container for synchronization data.
170 static void finalizeProcessingLTTVStandard(SyncState
* const syncState
)
174 double minOffset
, minDrift
;
175 unsigned int refFreqTrace
;
176 ProcessingDataLTTVStandard
* processingData
;
178 processingData
= (ProcessingDataLTTVStandard
*) syncState
->processingData
;
180 partialDestroyProcessingLTTVStandard(syncState
);
182 factors
= syncState
->matchingModule
->finalizeMatching(syncState
);
184 /* The offsets are adjusted so the lowest one is 0. This is done because
185 * of a Lttv specific limitation: events cannot have negative times. By
186 * having non-negative offsets, events cannot be moved backwards to
190 for (i
= 0; i
< syncState
->traceNb
; i
++)
192 minOffset
= MIN(g_array_index(factors
, Factors
, i
).offset
, minOffset
);
195 for (i
= 0; i
< syncState
->traceNb
; i
++)
197 g_array_index(factors
, Factors
, i
).offset
-= minOffset
;
200 /* Because the timestamps are corrected at the TSC level (not at the
201 * LttTime level) all trace frequencies must be made equal. We choose to
202 * use the frequency of the system with the lowest drift
206 for (i
= 0; i
< syncState
->traceNb
; i
++)
208 if (g_array_index(factors
, Factors
, i
).drift
< minDrift
)
210 minDrift
= g_array_index(factors
, Factors
, i
).drift
;
214 g_assert(syncState
->traceNb
== 0 || minDrift
!= INFINITY
);
216 // Write the factors to the LttTrace structures
217 for (i
= 0; i
< syncState
->traceNb
; i
++)
220 Factors
* traceFactors
;
222 t
= processingData
->traceSetContext
->traces
[i
]->t
;
223 traceFactors
= &g_array_index(factors
, Factors
, i
);
225 t
->drift
= traceFactors
->drift
;
226 t
->offset
= traceFactors
->offset
;
228 processingData
->traceSetContext
->traces
[refFreqTrace
]->t
->start_freq
;
230 processingData
->traceSetContext
->traces
[refFreqTrace
]->t
->freq_scale
;
231 t
->start_time_from_tsc
=
232 ltt_time_from_uint64(tsc_to_uint64(t
->freq_scale
, t
->start_freq
,
233 t
->drift
* t
->start_tsc
+ t
->offset
));
236 g_array_free(factors
, TRUE
);
238 lttv_traceset_context_compute_time_span(processingData
->traceSetContext
,
239 &processingData
->traceSetContext
->time_span
);
241 g_debug("traceset start %ld.%09ld end %ld.%09ld",
242 processingData
->traceSetContext
->time_span
.start_time
.tv_sec
,
243 processingData
->traceSetContext
->time_span
.start_time
.tv_nsec
,
244 processingData
->traceSetContext
->time_span
.end_time
.tv_sec
,
245 processingData
->traceSetContext
->time_span
.end_time
.tv_nsec
);
250 * Print statistics related to processing Must be called after
251 * finalizeProcessing.
254 * syncState container for synchronization data.
256 static void printProcessingStatsLTTVStandard(SyncState
* const syncState
)
258 ProcessingDataLTTVStandard
* processingData
;
260 if (!syncState
->stats
)
265 processingData
= (ProcessingDataLTTVStandard
*) syncState
->processingData
;
267 printf("LTTV processing stats:\n");
268 printf("\treceived frames: %d\n", processingData
->stats
->totRecv
);
269 printf("\treceived frames that are IP: %d\n",
270 processingData
->stats
->totRecvIp
);
271 if (syncState
->matchingModule
->canMatch
[TCP
])
273 printf("\treceived and processed packets that are TCP: %d\n",
274 processingData
->stats
->totRecvTCP
);
276 if (syncState
->matchingModule
->canMatch
[UDP
])
278 printf("\treceived and processed packets that are UDP: %d\n",
279 processingData
->stats
->totRecvUDP
);
281 if (syncState
->matchingModule
->canMatch
[TCP
])
283 printf("\tsent packets that are TCP: %d\n",
284 processingData
->stats
->totOutE
);
290 * Unregister event hooks. Deallocate processingData.
293 * syncState: container for synchronization data.
294 * This function deallocates these processingData members:
297 static void destroyProcessingLTTVStandard(SyncState
* const syncState
)
299 ProcessingDataLTTVStandard
* processingData
;
301 processingData
= (ProcessingDataLTTVStandard
*) syncState
->processingData
;
303 if (processingData
== NULL
)
308 partialDestroyProcessingLTTVStandard(syncState
);
310 if (syncState
->stats
)
312 free(processingData
->stats
);
315 if (syncState
->graphsStream
)
317 free(processingData
->graphs
);
320 free(syncState
->processingData
);
321 syncState
->processingData
= NULL
;
326 * Unregister event hooks. Deallocate some of processingData.
328 * This function can be called right after the events have been processed to
329 * free some data structures that are not needed for finalization.
332 * syncState: container for synchronization data.
333 * This function deallocates these members:
338 static void partialDestroyProcessingLTTVStandard(SyncState
* const syncState
)
341 ProcessingDataLTTVStandard
* processingData
;
343 processingData
= (ProcessingDataLTTVStandard
*) syncState
->processingData
;
345 if (processingData
== NULL
|| processingData
->traceNumTable
== NULL
)
350 g_hash_table_destroy(processingData
->traceNumTable
);
351 processingData
->traceNumTable
= NULL
;
353 for(i
= 0; i
< syncState
->traceNb
; i
++)
356 g_debug("Cleaning up pendingRecv list");
357 g_hash_table_destroy(processingData
->pendingRecv
[i
]);
359 free(processingData
->pendingRecv
);
361 unregisterHooks(processingData
->hookListList
,
362 processingData
->traceSetContext
);
367 * Lttv hook function that will be called for network events
370 * hookData: LttvTraceHook* for the type of event that generated the call
371 * callData: LttvTracefileContext* at the moment of the event
374 * FALSE Always returns FALSE, meaning to keep processing hooks for
377 static gboolean
processEventLTTVStandard(void* hookData
, void* callData
)
379 LttvTraceHook
* traceHook
;
380 LttvTracefileContext
* tfc
;
386 unsigned long traceNum
;
387 struct marker_info
* info
;
388 SyncState
* syncState
;
389 ProcessingDataLTTVStandard
* processingData
;
392 traceHook
= (LttvTraceHook
*) hookData
;
393 tfc
= (LttvTracefileContext
*) callData
;
394 trace
= tfc
->t_context
->t
;
395 syncState
= (SyncState
*) traceHook
->hook_data
;
396 processingData
= (ProcessingDataLTTVStandard
*) syncState
->processingData
;
397 event
= ltt_tracefile_get_event(tfc
->tf
);
398 info
= marker_get_info_from_id(tfc
->tf
->mdata
, event
->event_id
);
399 tsc
= ltt_event_cycle_count(event
);
400 time
= ltt_event_time(event
);
401 wTime
.seconds
= time
.tv_sec
;
402 wTime
.nanosec
= time
.tv_nsec
;
404 g_assert(g_hash_table_lookup_extended(processingData
->traceNumTable
,
405 trace
, NULL
, &traceNumP
));
406 traceNum
= GPOINTER_TO_INT(traceNumP
);
408 g_debug("Process event: time: %ld.%09ld trace: %ld (%p) name: %s ",
409 time
.tv_sec
, time
.tv_nsec
, traceNum
, trace
,
410 g_quark_to_string(info
->name
));
412 if (info
->name
== LTT_EVENT_DEV_XMIT_EXTENDED
)
416 if (!ltt_event_get_unsigned(event
,
417 lttv_trace_get_hook_field(traceHook
, 1)) == ETH_P_IP
||
418 !ltt_event_get_unsigned(event
,
419 lttv_trace_get_hook_field(traceHook
, 2)) == IPPROTO_TCP
)
424 if (!syncState
->matchingModule
->canMatch
[TCP
])
429 if (syncState
->stats
)
431 processingData
->stats
->totOutE
++;
434 outE
= malloc(sizeof(Event
));
435 outE
->traceNum
= traceNum
;
437 outE
->wallTime
= wTime
;
439 outE
->copy
= ©TCPEvent
;
440 outE
->destroy
= &destroyTCPEvent
;
441 outE
->event
.tcpEvent
= malloc(sizeof(TCPEvent
));
442 outE
->event
.tcpEvent
->direction
= OUT
;
443 outE
->event
.tcpEvent
->segmentKey
= malloc(sizeof(SegmentKey
));
444 outE
->event
.tcpEvent
->segmentKey
->connectionKey
.saddr
=
445 htonl(ltt_event_get_unsigned(event
,
446 lttv_trace_get_hook_field(traceHook
, 3)));
447 outE
->event
.tcpEvent
->segmentKey
->connectionKey
.daddr
=
448 htonl(ltt_event_get_unsigned(event
,
449 lttv_trace_get_hook_field(traceHook
, 4)));
450 outE
->event
.tcpEvent
->segmentKey
->tot_len
=
451 ltt_event_get_unsigned(event
, lttv_trace_get_hook_field(traceHook
,
453 outE
->event
.tcpEvent
->segmentKey
->ihl
= ltt_event_get_unsigned(event
,
454 lttv_trace_get_hook_field(traceHook
, 6));
455 outE
->event
.tcpEvent
->segmentKey
->connectionKey
.source
=
456 ltt_event_get_unsigned(event
, lttv_trace_get_hook_field(traceHook
,
458 outE
->event
.tcpEvent
->segmentKey
->connectionKey
.dest
=
459 ltt_event_get_unsigned(event
, lttv_trace_get_hook_field(traceHook
,
461 outE
->event
.tcpEvent
->segmentKey
->seq
= ltt_event_get_unsigned(event
,
462 lttv_trace_get_hook_field(traceHook
, 9));
463 outE
->event
.tcpEvent
->segmentKey
->ack_seq
=
464 ltt_event_get_unsigned(event
, lttv_trace_get_hook_field(traceHook
,
466 outE
->event
.tcpEvent
->segmentKey
->doff
= ltt_event_get_unsigned(event
,
467 lttv_trace_get_hook_field(traceHook
, 11));
468 outE
->event
.tcpEvent
->segmentKey
->ack
= ltt_event_get_unsigned(event
,
469 lttv_trace_get_hook_field(traceHook
, 12));
470 outE
->event
.tcpEvent
->segmentKey
->rst
= ltt_event_get_unsigned(event
,
471 lttv_trace_get_hook_field(traceHook
, 13));
472 outE
->event
.tcpEvent
->segmentKey
->syn
= ltt_event_get_unsigned(event
,
473 lttv_trace_get_hook_field(traceHook
, 14));
474 outE
->event
.tcpEvent
->segmentKey
->fin
= ltt_event_get_unsigned(event
,
475 lttv_trace_get_hook_field(traceHook
, 15));
477 syncState
->matchingModule
->matchEvent(syncState
, outE
);
479 g_debug("Output event done");
481 else if (info
->name
== LTT_EVENT_DEV_RECEIVE
)
485 if (syncState
->stats
)
487 processingData
->stats
->totRecv
++;
490 protocol
= ltt_event_get_unsigned(event
,
491 lttv_trace_get_hook_field(traceHook
, 1));
493 if (protocol
== ETH_P_IP
)
498 if (syncState
->stats
)
500 processingData
->stats
->totRecvIp
++;
503 inE
= malloc(sizeof(Event
));
504 inE
->traceNum
= traceNum
;
506 inE
->wallTime
= wTime
;
507 inE
->event
.tcpEvent
= NULL
;
508 inE
->copy
= ©Event
;
509 inE
->destroy
= &destroyEvent
;
511 skb
= (void*) (long) ltt_event_get_long_unsigned(event
,
512 lttv_trace_get_hook_field(traceHook
, 0));
513 g_hash_table_replace(processingData
->pendingRecv
[traceNum
], skb
,
516 g_debug("Adding inE %p for skb %p to pendingRecv", inE
, skb
);
519 else if (info
->name
== LTT_EVENT_TCPV4_RCV_EXTENDED
)
524 // Search pendingRecv for an event with the same skb
525 skb
= (void*) (long) ltt_event_get_long_unsigned(event
,
526 lttv_trace_get_hook_field(traceHook
, 0));
529 g_hash_table_lookup(processingData
->pendingRecv
[traceNum
], skb
);
532 // This should only happen in case of lost events
533 g_warning("No matching pending receive event found");
537 if (syncState
->stats
)
539 processingData
->stats
->totRecvTCP
++;
542 // If it's there, remove it and proceed with a receive event
543 g_hash_table_steal(processingData
->pendingRecv
[traceNum
], skb
);
546 inE
->event
.tcpEvent
= malloc(sizeof(TCPEvent
));
547 inE
->copy
= ©TCPEvent
;
548 inE
->destroy
= &destroyTCPEvent
;
549 inE
->event
.tcpEvent
->direction
= IN
;
550 inE
->event
.tcpEvent
->segmentKey
= malloc(sizeof(SegmentKey
));
551 inE
->event
.tcpEvent
->segmentKey
->connectionKey
.saddr
=
552 htonl(ltt_event_get_unsigned(event
,
553 lttv_trace_get_hook_field(traceHook
, 1)));
554 inE
->event
.tcpEvent
->segmentKey
->connectionKey
.daddr
=
555 htonl(ltt_event_get_unsigned(event
,
556 lttv_trace_get_hook_field(traceHook
, 2)));
557 inE
->event
.tcpEvent
->segmentKey
->tot_len
=
558 ltt_event_get_unsigned(event
,
559 lttv_trace_get_hook_field(traceHook
, 3));
560 inE
->event
.tcpEvent
->segmentKey
->ihl
=
561 ltt_event_get_unsigned(event
,
562 lttv_trace_get_hook_field(traceHook
, 4));
563 inE
->event
.tcpEvent
->segmentKey
->connectionKey
.source
=
564 ltt_event_get_unsigned(event
,
565 lttv_trace_get_hook_field(traceHook
, 5));
566 inE
->event
.tcpEvent
->segmentKey
->connectionKey
.dest
=
567 ltt_event_get_unsigned(event
,
568 lttv_trace_get_hook_field(traceHook
, 6));
569 inE
->event
.tcpEvent
->segmentKey
->seq
=
570 ltt_event_get_unsigned(event
,
571 lttv_trace_get_hook_field(traceHook
, 7));
572 inE
->event
.tcpEvent
->segmentKey
->ack_seq
=
573 ltt_event_get_unsigned(event
,
574 lttv_trace_get_hook_field(traceHook
, 8));
575 inE
->event
.tcpEvent
->segmentKey
->doff
=
576 ltt_event_get_unsigned(event
,
577 lttv_trace_get_hook_field(traceHook
, 9));
578 inE
->event
.tcpEvent
->segmentKey
->ack
=
579 ltt_event_get_unsigned(event
,
580 lttv_trace_get_hook_field(traceHook
, 10));
581 inE
->event
.tcpEvent
->segmentKey
->rst
=
582 ltt_event_get_unsigned(event
,
583 lttv_trace_get_hook_field(traceHook
, 11));
584 inE
->event
.tcpEvent
->segmentKey
->syn
=
585 ltt_event_get_unsigned(event
,
586 lttv_trace_get_hook_field(traceHook
, 12));
587 inE
->event
.tcpEvent
->segmentKey
->fin
=
588 ltt_event_get_unsigned(event
,
589 lttv_trace_get_hook_field(traceHook
, 13));
591 syncState
->matchingModule
->matchEvent(syncState
, inE
);
593 g_debug("TCP input event %p for skb %p done", inE
, skb
);
596 else if (info
->name
== LTT_EVENT_UDPV4_RCV_EXTENDED
)
601 // Search pendingRecv for an event with the same skb
602 skb
= (void*) (long) ltt_event_get_long_unsigned(event
,
603 lttv_trace_get_hook_field(traceHook
, 0));
606 g_hash_table_lookup(processingData
->pendingRecv
[traceNum
], skb
);
609 // This should only happen in case of lost events
610 g_warning("No matching pending receive event found");
616 if (syncState
->stats
)
618 processingData
->stats
->totRecvUDP
++;
621 // If it's there, remove it and proceed with a receive event
622 g_hash_table_steal(processingData
->pendingRecv
[traceNum
], skb
);
625 inE
->event
.udpEvent
= malloc(sizeof(UDPEvent
));
626 inE
->copy
= ©UDPEvent
;
627 inE
->destroy
= &destroyUDPEvent
;
628 inE
->event
.udpEvent
->direction
= IN
;
629 inE
->event
.udpEvent
->datagramKey
= malloc(sizeof(DatagramKey
));
630 inE
->event
.udpEvent
->datagramKey
->saddr
=
631 htonl(ltt_event_get_unsigned(event
,
632 lttv_trace_get_hook_field(traceHook
, 1)));
633 inE
->event
.udpEvent
->datagramKey
->daddr
=
634 htonl(ltt_event_get_unsigned(event
,
635 lttv_trace_get_hook_field(traceHook
, 2)));
636 inE
->event
.udpEvent
->unicast
= ltt_event_get_unsigned(event
,
637 lttv_trace_get_hook_field(traceHook
, 3)) == 0 ? false : true;
638 inE
->event
.udpEvent
->datagramKey
->ulen
=
639 ltt_event_get_unsigned(event
,
640 lttv_trace_get_hook_field(traceHook
, 4));
641 inE
->event
.udpEvent
->datagramKey
->source
=
642 ltt_event_get_unsigned(event
,
643 lttv_trace_get_hook_field(traceHook
, 5));
644 inE
->event
.udpEvent
->datagramKey
->dest
=
645 ltt_event_get_unsigned(event
,
646 lttv_trace_get_hook_field(traceHook
, 6));
647 dataStart
= ltt_event_get_long_unsigned(event
,
648 lttv_trace_get_hook_field(traceHook
, 7));
649 g_assert_cmpuint(sizeof(inE
->event
.udpEvent
->datagramKey
->dataKey
),
650 ==, sizeof(guint64
));
651 if (inE
->event
.udpEvent
->datagramKey
->ulen
- 8 >=
652 sizeof(inE
->event
.udpEvent
->datagramKey
->dataKey
))
654 memcpy(inE
->event
.udpEvent
->datagramKey
->dataKey
, &dataStart
,
655 sizeof(inE
->event
.udpEvent
->datagramKey
->dataKey
));
659 memset(inE
->event
.udpEvent
->datagramKey
->dataKey
, 0,
660 sizeof(inE
->event
.udpEvent
->datagramKey
->dataKey
));
661 memcpy(inE
->event
.udpEvent
->datagramKey
->dataKey
, &dataStart
,
662 inE
->event
.udpEvent
->datagramKey
->ulen
- 8);
665 syncState
->matchingModule
->matchEvent(syncState
, inE
);
667 g_debug("UDP input event %p for skb %p done", inE
, skb
);
672 g_assert_not_reached();
680 * Write the processing-specific variables in the gnuplot script.
683 * syncState: container for synchronization data
686 static void writeProcessingGraphVariablesLTTVStandard(SyncState
* const
687 syncState
, const unsigned int i
)
689 ProcessingDataLTTVStandard
* processingData
= syncState
->processingData
;
690 ProcessingGraphsLTTVStandard
* traceI
= &processingData
->graphs
[i
];
692 fprintf(syncState
->graphsStream
, "clock_freq_%u= %.3f\n", i
, (double)
693 traceI
->startFreq
/ traceI
->freqScale
);
698 * Write the processing-specific options in the gnuplot script.
701 * syncState: container for synchronization data
702 * i: first trace number
703 * j: second trace number, garanteed to be larger than i
705 static void writeProcessingTraceTraceOptionsLTTVStandard(SyncState
* const
706 syncState
, const unsigned int i
, const unsigned int j
)
708 fprintf(syncState
->graphsStream
,
709 "set key inside right bottom\n"
710 "set xlabel \"Clock %1$u\"\n"
711 "set xtics nomirror\n"
712 "set ylabel \"Clock %2$u\"\n"
713 "set ytics nomirror\n"
714 "set x2label \"Clock %1$d (s)\"\n"
715 "set x2range [GPVAL_X_MIN / clock_freq_%1$u : GPVAL_X_MAX / clock_freq_%1$u]\n"
717 "set y2label \"Clock %2$d (s)\"\n"
718 "set y2range [GPVAL_Y_MIN / clock_freq_%2$u : GPVAL_Y_MAX / clock_freq_%2$u]\n"
719 "set y2tics\n", i
, j
);
724 * Write the processing-specific options in the gnuplot script.
727 * syncState: container for synchronization data
728 * i: first trace number
729 * j: second trace number, garanteed to be larger than i
731 static void writeProcessingTraceTimeOptionsLTTVStandard(SyncState
* const
732 syncState
, const unsigned int i
, const unsigned int j
)
734 fprintf(syncState
->graphsStream
,
735 "set key inside right bottom\n"
736 "set xlabel \"Clock %1$u\"\n"
737 "set xtics nomirror\n"
738 "set ylabel \"time (s)\"\n"
739 "set ytics nomirror\n"
740 "set x2label \"Clock %1$d (s)\"\n"
741 "set x2range [GPVAL_X_MIN / clock_freq_%1$u : GPVAL_X_MAX / clock_freq_%1$u]\n"