xref: /linux/tools/verification/rvgen/rvgen/dot2k.py (revision cce86e03a27fdce11684c85ee33c528124904d8d) !
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0-only
3#
4# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
5#
6# dot2k: transform dot files into a monitor for the Linux kernel.
7#
8# For further information, see:
9#   Documentation/trace/rv/da_monitor_synthesis.rst
10
11from .dot2c import Dot2c
12from .generator import Monitor
13
14
15class dot2k(Monitor, Dot2c):
16    template_dir = "dot2k"
17
18    def __init__(self, file_path, MonitorType, extra_params={}):
19        self.monitor_type = MonitorType
20        Monitor.__init__(self, extra_params)
21        Dot2c.__init__(self, file_path, extra_params.get("model_name"))
22        self.enum_suffix = "_%s" % self.name
23
24    def fill_monitor_type(self):
25        return self.monitor_type.upper()
26
27    def fill_tracepoint_handlers_skel(self):
28        buff = []
29        for event in self.events:
30            buff.append("static void handle_%s(void *data, /* XXX: fill header */)" % event)
31            buff.append("{")
32            handle = "handle_event"
33            if self.is_start_event(event):
34                buff.append("\t/* XXX: validate that this event always leads to the initial state */")
35                handle = "handle_start_event"
36            elif self.is_start_run_event(event):
37                buff.append("\t/* XXX: validate that this event is only valid in the initial state */")
38                handle = "handle_start_run_event"
39            if self.monitor_type == "per_task":
40                buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;");
41                buff.append("\tda_%s_%s(p, %s%s);" % (handle, self.name, event, self.enum_suffix));
42            else:
43                buff.append("\tda_%s_%s(%s%s);" % (handle, self.name, event, self.enum_suffix));
44            buff.append("}")
45            buff.append("")
46        return '\n'.join(buff)
47
48    def fill_tracepoint_attach_probe(self):
49        buff = []
50        for event in self.events:
51            buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
52        return '\n'.join(buff)
53
54    def fill_tracepoint_detach_helper(self):
55        buff = []
56        for event in self.events:
57            buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
58        return '\n'.join(buff)
59
60    def fill_model_h_header(self):
61        buff = []
62        buff.append("/* SPDX-License-Identifier: GPL-2.0 */")
63        buff.append("/*")
64        buff.append(" * Automatically generated C representation of %s automaton" % (self.name))
65        buff.append(" * For further information about this format, see kernel documentation:")
66        buff.append(" *   Documentation/trace/rv/deterministic_automata.rst")
67        buff.append(" */")
68        buff.append("")
69
70        return buff
71
72    def fill_model_h(self):
73        #
74        # Adjust the definition names
75        #
76        self.enum_states_def = "states_%s" % self.name
77        self.enum_events_def = "events_%s" % self.name
78        self.struct_automaton_def = "automaton_%s" % self.name
79        self.var_automaton_def = "automaton_%s" % self.name
80
81        buff = self.fill_model_h_header()
82        buff += self.format_model()
83
84        return '\n'.join(buff)
85
86    def fill_monitor_class_type(self):
87        if self.monitor_type == "per_task":
88            return "DA_MON_EVENTS_ID"
89        return "DA_MON_EVENTS_IMPLICIT"
90
91    def fill_monitor_class(self):
92        if self.monitor_type == "per_task":
93            return "da_monitor_id"
94        return "da_monitor"
95
96    def fill_tracepoint_args_skel(self, tp_type):
97        buff = []
98        tp_args_event = [
99                ("char *", "state"),
100                ("char *", "event"),
101                ("char *", "next_state"),
102                ("bool ",  "final_state"),
103                ]
104        tp_args_error = [
105                ("char *", "state"),
106                ("char *", "event"),
107                ]
108        tp_args_id = ("int ", "id")
109        tp_args = tp_args_event if tp_type == "event" else tp_args_error
110        if self.monitor_type == "per_task":
111            tp_args.insert(0, tp_args_id)
112        tp_proto_c = ", ".join([a+b for a,b in tp_args])
113        tp_args_c = ", ".join([b for a,b in tp_args])
114        buff.append("	     TP_PROTO(%s)," % tp_proto_c)
115        buff.append("	     TP_ARGS(%s)" % tp_args_c)
116        return '\n'.join(buff)
117
118    def fill_main_c(self):
119        main_c = super().fill_main_c()
120
121        min_type = self.get_minimun_type()
122        nr_events = len(self.events)
123        monitor_type = self.fill_monitor_type()
124
125        main_c = main_c.replace("%%MIN_TYPE%%", min_type)
126        main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events))
127        main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type)
128
129        return main_c
130