summaryrefslogtreecommitdiff
path: root/cesar/common
diff options
context:
space:
mode:
authorNicolas Schodet2012-10-08 09:55:38 +0200
committerNicolas Schodet2012-10-19 15:17:48 +0200
commit6ba3993d4908eac19b260d82f31aac593e2bdaee (patch)
tree30f8e44b21f43b2c9ba88b023cf187325b817ce8 /cesar/common
parentf6929ea00790d83e33a10be79bebb743753d259e (diff)
cesar/common/tools/traceviewer: add medium analysis, closes #3428
Diffstat (limited to 'cesar/common')
-rw-r--r--cesar/common/tools/traceviewer/analyse/__init__.py0
-rw-r--r--cesar/common/tools/traceviewer/analyse/medium.py118
-rw-r--r--cesar/common/tools/traceviewer/command.py5
-rw-r--r--cesar/common/tools/traceviewer/trace_analyse.py9
4 files changed, 132 insertions, 0 deletions
diff --git a/cesar/common/tools/traceviewer/analyse/__init__.py b/cesar/common/tools/traceviewer/analyse/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/cesar/common/tools/traceviewer/analyse/__init__.py
diff --git a/cesar/common/tools/traceviewer/analyse/medium.py b/cesar/common/tools/traceviewer/analyse/medium.py
new file mode 100644
index 0000000000..bc379f8340
--- /dev/null
+++ b/cesar/common/tools/traceviewer/analyse/medium.py
@@ -0,0 +1,118 @@
+"""Analyse medium usage."""
+import re
+import traceviewer.trace as trace
+
+DEFAULT_MODE = 2
+
+RX_COLOR = '#00c0ff'
+TX_COLOR = '#ffc000'
+
+MAC_PREAMBLE_TCK = 3840 / 3
+MAC_PREAMBLE_HYBRID_TCK = 3456 / 3
+MAC_FC_10_TCK = 2892 / 3
+MAC_FC_AV_TCK = 4446 / 3
+MAC_DX417_TCK = 3489 / 3
+MAC_DX567_TCK = 3639 / 3
+MAC_DX3534_TCK = 6606 / 3
+
+pre_fcs_tck = [
+ MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK + MAC_FC_AV_TCK,
+ MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK + MAC_FC_AV_TCK * 2,
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK * 2,
+ ]
+dx_tck = [ MAC_DX417_TCK, MAC_DX567_TCK, MAC_DX3534_TCK ]
+
+def pre_fcs_data_tck (mode, gil, symb_nb):
+ """Compute frame occupation on medium."""
+ if symb_nb is None:
+ symb_nb = 0
+ if symb_nb <= 2:
+ return pre_fcs_tck[mode] + MAC_DX567_TCK * symb_nb
+ else:
+ return (pre_fcs_tck[mode] + MAC_DX567_TCK * 2
+ + dx_tck[gil] * (symb_nb - 2))
+
+def to_int (*args):
+ """Convert to integer if not None."""
+ return tuple (int (i) if i is not None else None
+ for i in args)
+
+rx_param_re = re.compile (r'rx param mode=(\d+)')
+rx_fc_re = re.compile (r'rx fc cb rx_date=(0x[0-9a-f]+)')
+rx_prepare_re = re.compile (r'rx (?:prepare short'
+ + r'|(?:prepare|sound) .* gil=(\d+) symb_nb=(\d+))')
+tx_param_re = re.compile (r'tx (?:param short|param|sound) mode=(\d+)'
+ + r'(?:.* gil=(\d+) symb_nb=(\d+))?')
+tx_frame_re = re.compile (r'tx frame date=(0x[0-9a-f]+) want_conf=(true|false)')
+tx_access_conf_re = re.compile (r'access conf cb')
+
+def analyse (bundle):
+ # Find phy traces.
+ phy = None
+ for t in bundle.traces:
+ name = t.name.split (': ')[-1]
+ if name == 'phy':
+ phy = t
+ break
+ if phy is None:
+ return
+ # Populate a new trace with medium usage.
+ medium = trace.Trace (bundle.name + ': medium')
+ mode = DEFAULT_MODE
+ last_rx, last_tx = None, None
+ tx_param = None
+ for t in phy.trace:
+ # RX.
+ m = rx_param_re.match (t.text)
+ if m:
+ mode = int (m.group (1))
+ next
+ m = rx_fc_re.match (t.text)
+ if m:
+ date = long (m.group (1), 0)
+ last_rx = trace.TraceEntry (date, 0, 'RX')
+ last_rx.view_text = 'RX'
+ last_rx.view_attr = RX_COLOR
+ medium.trace.append (last_rx)
+ next
+ if last_rx is not None:
+ m = rx_prepare_re.match (t.text)
+ if m:
+ gil, symb_nb = to_int (*m.groups ())
+ last_rx.duration = pre_fcs_data_tck (mode, gil, symb_nb)
+ last_rx.text = 'RX end_date=0x%08x' % (last_rx.date
+ + last_rx.duration)
+ last_rx = None
+ next
+ # TX.
+ m = tx_param_re.match (t.text)
+ if m:
+ mode = int (m.group (1))
+ tx_param = to_int (m.group (2), m.group (3))
+ next
+ if tx_param is not None:
+ m = tx_frame_re.match (t.text)
+ if m:
+ date = long (m.group (1), 0)
+ want_conf = m.group (2) == 'true'
+ duration = pre_fcs_data_tck (mode, *tx_param)
+ text = 'TX end_date=0x%08x' % (date + duration)
+ t = trace.TraceEntry (date, duration, text)
+ t.view_text = 'TX'
+ t.view_attr = TX_COLOR
+ if want_conf:
+ last_tx = t
+ else:
+ medium.trace.append (t)
+ tx_param = None
+ next
+ if last_tx is not None:
+ m = tx_access_conf_re.match (t.text)
+ if m:
+ medium.trace.append (last_tx)
+ last_tx = None
+ next
+ # Add trace unless empty.
+ if medium.trace:
+ bundle.traces.insert (0, medium)
diff --git a/cesar/common/tools/traceviewer/command.py b/cesar/common/tools/traceviewer/command.py
index 655e241846..8ba06bd274 100644
--- a/cesar/common/tools/traceviewer/command.py
+++ b/cesar/common/tools/traceviewer/command.py
@@ -2,6 +2,7 @@ from gui import Gui
from trace import read_traces_from_dump
from trace_bundle import read_bundles_from_dump
from trace_annotate import annotate
+from trace_analyse import analyse, DEFAULT_ANALYSES
from optparse import OptionParser
import gzip
@@ -26,6 +27,9 @@ def run ():
help='include only trace matching REGEX', metavar='REGEX')
opt.add_option ('-x', '--exclude', action = 'append', default = [ ],
help='exclude named TRACE', metavar='TRACE')
+ opt.add_option ('-a', '--analyse', action = 'append',
+ default = DEFAULT_ANALYSES,
+ help='add analysis module', metavar='MODULE')
(options, args) = opt.parse_args ()
# Read traces.
traces = [ ]
@@ -35,6 +39,7 @@ def run ():
for f in options.bundle + args:
bs = read_bundles_from_dump (f, open_file (f))
for b in bs:
+ analyse (b, options.analyse)
traces.extend (b.traces)
# Filter traces.
traces = [ t for t in traces if t.name not in options.exclude ]
diff --git a/cesar/common/tools/traceviewer/trace_analyse.py b/cesar/common/tools/traceviewer/trace_analyse.py
new file mode 100644
index 0000000000..94c4590383
--- /dev/null
+++ b/cesar/common/tools/traceviewer/trace_analyse.py
@@ -0,0 +1,9 @@
+"""Import module to analyse a trace bundle."""
+
+DEFAULT_ANALYSES = [ 'medium' ]
+
+def analyse (bundle, analyses):
+ for m in analyses:
+ mod = __import__ ('traceviewer.analyse.' + m,
+ globals (), locals (), [ 'analyse' ])
+ mod.analyse (bundle)