xref: /linux/tools/verification/rvgen/rvgen/dot2k.py (revision f75c03a761b737c4ee94c17f154967261f00ab4d)
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) -> str:
25        return self.monitor_type.upper()
26
27    def fill_tracepoint_handlers_skel(self) -> str:
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(p, %s%s);" % (handle, event, self.enum_suffix));
42            else:
43                buff.append("\tda_%s(%s%s);" % (handle, event, self.enum_suffix));
44            buff.append("}")
45            buff.append("")
46        return '\n'.join(buff)
47
48    def fill_tracepoint_attach_probe(self) -> str:
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) -> str:
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) -> list[str]:
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        buff.append("#define MONITOR_NAME %s" % (self.name))
70        buff.append("")
71
72        return buff
73
74    def fill_model_h(self) -> str:
75        #
76        # Adjust the definition names
77        #
78        self.enum_states_def = "states_%s" % self.name
79        self.enum_events_def = "events_%s" % self.name
80        self.struct_automaton_def = "automaton_%s" % self.name
81        self.var_automaton_def = "automaton_%s" % self.name
82
83        buff = self.fill_model_h_header()
84        buff += self.format_model()
85
86        return '\n'.join(buff)
87
88    def fill_monitor_class_type(self) -> str:
89        if self.monitor_type == "per_task":
90            return "DA_MON_EVENTS_ID"
91        return "DA_MON_EVENTS_IMPLICIT"
92
93    def fill_monitor_class(self) -> str:
94        if self.monitor_type == "per_task":
95            return "da_monitor_id"
96        return "da_monitor"
97
98    def fill_tracepoint_args_skel(self, tp_type: str) -> str:
99        buff = []
100        tp_args_event = [
101                ("char *", "state"),
102                ("char *", "event"),
103                ("char *", "next_state"),
104                ("bool ",  "final_state"),
105                ]
106        tp_args_error = [
107                ("char *", "state"),
108                ("char *", "event"),
109                ]
110        tp_args_id = ("int ", "id")
111        tp_args = tp_args_event if tp_type == "event" else tp_args_error
112        if self.monitor_type == "per_task":
113            tp_args.insert(0, tp_args_id)
114        tp_proto_c = ", ".join([a+b for a,b in tp_args])
115        tp_args_c = ", ".join([b for a,b in tp_args])
116        buff.append("	     TP_PROTO(%s)," % tp_proto_c)
117        buff.append("	     TP_ARGS(%s)" % tp_args_c)
118        return '\n'.join(buff)
119
120    def fill_main_c(self) -> str:
121        main_c = super().fill_main_c()
122
123        min_type = self.get_minimun_type()
124        nr_events = len(self.events)
125        monitor_type = self.fill_monitor_type()
126
127        main_c = main_c.replace("%%MIN_TYPE%%", min_type)
128        main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events))
129        main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type)
130
131        return main_c
132