xref: /openbmc/linux/tools/verification/dot2/dot2k.py (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
124bce201SDaniel Bristot de Oliveira#!/usr/bin/env python3
224bce201SDaniel Bristot de Oliveira# SPDX-License-Identifier: GPL-2.0-only
324bce201SDaniel Bristot de Oliveira#
424bce201SDaniel Bristot de Oliveira# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
524bce201SDaniel Bristot de Oliveira#
624bce201SDaniel Bristot de Oliveira# dot2k: transform dot files into a monitor for the Linux kernel.
7*d57aff24SDaniel Bristot de Oliveira#
8*d57aff24SDaniel Bristot de Oliveira# For further information, see:
9*d57aff24SDaniel Bristot de Oliveira#   Documentation/trace/rv/da_monitor_synthesis.rst
1024bce201SDaniel Bristot de Oliveira
1124bce201SDaniel Bristot de Oliveirafrom dot2.dot2c import Dot2c
1224bce201SDaniel Bristot de Oliveiraimport platform
1324bce201SDaniel Bristot de Oliveiraimport os
1424bce201SDaniel Bristot de Oliveira
1524bce201SDaniel Bristot de Oliveiraclass dot2k(Dot2c):
1624bce201SDaniel Bristot de Oliveira    monitor_types = { "global" : 1, "per_cpu" : 2, "per_task" : 3 }
1724bce201SDaniel Bristot de Oliveira    monitor_templates_dir = "dot2k/rv_templates/"
1824bce201SDaniel Bristot de Oliveira    monitor_type = "per_cpu"
1924bce201SDaniel Bristot de Oliveira
2024bce201SDaniel Bristot de Oliveira    def __init__(self, file_path, MonitorType):
2124bce201SDaniel Bristot de Oliveira        super().__init__(file_path)
2224bce201SDaniel Bristot de Oliveira
2324bce201SDaniel Bristot de Oliveira        self.monitor_type = self.monitor_types.get(MonitorType)
2424bce201SDaniel Bristot de Oliveira        if self.monitor_type == None:
2524bce201SDaniel Bristot de Oliveira            raise Exception("Unknown monitor type: %s" % MonitorType)
2624bce201SDaniel Bristot de Oliveira
2724bce201SDaniel Bristot de Oliveira        self.monitor_type = MonitorType
2824bce201SDaniel Bristot de Oliveira        self.__fill_rv_templates_dir()
2924bce201SDaniel Bristot de Oliveira        self.main_c = self.__open_file(self.monitor_templates_dir + "main_" + MonitorType + ".c")
3024bce201SDaniel Bristot de Oliveira        self.enum_suffix = "_%s" % self.name
3124bce201SDaniel Bristot de Oliveira
3224bce201SDaniel Bristot de Oliveira    def __fill_rv_templates_dir(self):
3324bce201SDaniel Bristot de Oliveira
3424bce201SDaniel Bristot de Oliveira        if os.path.exists(self.monitor_templates_dir) == True:
3524bce201SDaniel Bristot de Oliveira            return
3624bce201SDaniel Bristot de Oliveira
3724bce201SDaniel Bristot de Oliveira        if platform.system() != "Linux":
3824bce201SDaniel Bristot de Oliveira            raise Exception("I can only run on Linux.")
3924bce201SDaniel Bristot de Oliveira
4024bce201SDaniel Bristot de Oliveira        kernel_path = "/lib/modules/%s/build/tools/verification/dot2/dot2k_templates/" % (platform.release())
4124bce201SDaniel Bristot de Oliveira
4224bce201SDaniel Bristot de Oliveira        if os.path.exists(kernel_path) == True:
4324bce201SDaniel Bristot de Oliveira            self.monitor_templates_dir = kernel_path
4424bce201SDaniel Bristot de Oliveira            return
4524bce201SDaniel Bristot de Oliveira
4624bce201SDaniel Bristot de Oliveira        if os.path.exists("/usr/share/dot2/dot2k_templates/") == True:
4724bce201SDaniel Bristot de Oliveira            self.monitor_templates_dir = "/usr/share/dot2/dot2k_templates/"
4824bce201SDaniel Bristot de Oliveira            return
4924bce201SDaniel Bristot de Oliveira
5024bce201SDaniel Bristot de Oliveira        raise Exception("Could not find the template directory, do you have the kernel source installed?")
5124bce201SDaniel Bristot de Oliveira
5224bce201SDaniel Bristot de Oliveira
5324bce201SDaniel Bristot de Oliveira    def __open_file(self, path):
5424bce201SDaniel Bristot de Oliveira        try:
5524bce201SDaniel Bristot de Oliveira            fd = open(path)
5624bce201SDaniel Bristot de Oliveira        except OSError:
5724bce201SDaniel Bristot de Oliveira            raise Exception("Cannot open the file: %s" % path)
5824bce201SDaniel Bristot de Oliveira
5924bce201SDaniel Bristot de Oliveira        content = fd.read()
6024bce201SDaniel Bristot de Oliveira
6124bce201SDaniel Bristot de Oliveira        return content
6224bce201SDaniel Bristot de Oliveira
6324bce201SDaniel Bristot de Oliveira    def __buff_to_string(self, buff):
6424bce201SDaniel Bristot de Oliveira        string = ""
6524bce201SDaniel Bristot de Oliveira
6624bce201SDaniel Bristot de Oliveira        for line in buff:
6724bce201SDaniel Bristot de Oliveira            string = string + line + "\n"
6824bce201SDaniel Bristot de Oliveira
6924bce201SDaniel Bristot de Oliveira        # cut off the last \n
7024bce201SDaniel Bristot de Oliveira        return string[:-1]
7124bce201SDaniel Bristot de Oliveira
7224bce201SDaniel Bristot de Oliveira    def fill_tracepoint_handlers_skel(self):
7324bce201SDaniel Bristot de Oliveira        buff = []
7424bce201SDaniel Bristot de Oliveira        for event in self.events:
7524bce201SDaniel Bristot de Oliveira            buff.append("static void handle_%s(void *data, /* XXX: fill header */)" % event)
7624bce201SDaniel Bristot de Oliveira            buff.append("{")
7724bce201SDaniel Bristot de Oliveira            if self.monitor_type == "per_task":
7824bce201SDaniel Bristot de Oliveira                buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;");
7924bce201SDaniel Bristot de Oliveira                buff.append("\tda_handle_event_%s(p, %s%s);" % (self.name, event, self.enum_suffix));
8024bce201SDaniel Bristot de Oliveira            else:
8124bce201SDaniel Bristot de Oliveira                buff.append("\tda_handle_event_%s(%s%s);" % (self.name, event, self.enum_suffix));
8224bce201SDaniel Bristot de Oliveira            buff.append("}")
8324bce201SDaniel Bristot de Oliveira            buff.append("")
8424bce201SDaniel Bristot de Oliveira        return self.__buff_to_string(buff)
8524bce201SDaniel Bristot de Oliveira
8624bce201SDaniel Bristot de Oliveira    def fill_tracepoint_attach_probe(self):
8724bce201SDaniel Bristot de Oliveira        buff = []
8824bce201SDaniel Bristot de Oliveira        for event in self.events:
8924bce201SDaniel Bristot de Oliveira            buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
9024bce201SDaniel Bristot de Oliveira        return self.__buff_to_string(buff)
9124bce201SDaniel Bristot de Oliveira
9224bce201SDaniel Bristot de Oliveira    def fill_tracepoint_detach_helper(self):
9324bce201SDaniel Bristot de Oliveira        buff = []
9424bce201SDaniel Bristot de Oliveira        for event in self.events:
9524bce201SDaniel Bristot de Oliveira            buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
9624bce201SDaniel Bristot de Oliveira        return self.__buff_to_string(buff)
9724bce201SDaniel Bristot de Oliveira
9824bce201SDaniel Bristot de Oliveira    def fill_main_c(self):
9924bce201SDaniel Bristot de Oliveira        main_c = self.main_c
10024bce201SDaniel Bristot de Oliveira        min_type = self.get_minimun_type()
10124bce201SDaniel Bristot de Oliveira        nr_events = self.events.__len__()
10224bce201SDaniel Bristot de Oliveira        tracepoint_handlers = self.fill_tracepoint_handlers_skel()
10324bce201SDaniel Bristot de Oliveira        tracepoint_attach = self.fill_tracepoint_attach_probe()
10424bce201SDaniel Bristot de Oliveira        tracepoint_detach = self.fill_tracepoint_detach_helper()
10524bce201SDaniel Bristot de Oliveira
10624bce201SDaniel Bristot de Oliveira        main_c = main_c.replace("MIN_TYPE", min_type)
10724bce201SDaniel Bristot de Oliveira        main_c = main_c.replace("MODEL_NAME", self.name)
10824bce201SDaniel Bristot de Oliveira        main_c = main_c.replace("NR_EVENTS", str(nr_events))
10924bce201SDaniel Bristot de Oliveira        main_c = main_c.replace("TRACEPOINT_HANDLERS_SKEL", tracepoint_handlers)
11024bce201SDaniel Bristot de Oliveira        main_c = main_c.replace("TRACEPOINT_ATTACH", tracepoint_attach)
11124bce201SDaniel Bristot de Oliveira        main_c = main_c.replace("TRACEPOINT_DETACH", tracepoint_detach)
11224bce201SDaniel Bristot de Oliveira
11324bce201SDaniel Bristot de Oliveira        return main_c
11424bce201SDaniel Bristot de Oliveira
11524bce201SDaniel Bristot de Oliveira    def fill_model_h_header(self):
11624bce201SDaniel Bristot de Oliveira        buff = []
11724bce201SDaniel Bristot de Oliveira        buff.append("/*")
11824bce201SDaniel Bristot de Oliveira        buff.append(" * Automatically generated C representation of %s automaton" % (self.name))
11924bce201SDaniel Bristot de Oliveira        buff.append(" * For further information about this format, see kernel documentation:")
12024bce201SDaniel Bristot de Oliveira        buff.append(" *   Documentation/trace/rv/deterministic_automata.rst")
12124bce201SDaniel Bristot de Oliveira        buff.append(" */")
12224bce201SDaniel Bristot de Oliveira        buff.append("")
12324bce201SDaniel Bristot de Oliveira
12424bce201SDaniel Bristot de Oliveira        return buff
12524bce201SDaniel Bristot de Oliveira
12624bce201SDaniel Bristot de Oliveira    def fill_model_h(self):
12724bce201SDaniel Bristot de Oliveira        #
12824bce201SDaniel Bristot de Oliveira        # Adjust the definition names
12924bce201SDaniel Bristot de Oliveira        #
13024bce201SDaniel Bristot de Oliveira        self.enum_states_def = "states_%s" % self.name
13124bce201SDaniel Bristot de Oliveira        self.enum_events_def = "events_%s" % self.name
13224bce201SDaniel Bristot de Oliveira        self.struct_automaton_def = "automaton_%s" % self.name
13324bce201SDaniel Bristot de Oliveira        self.var_automaton_def = "automaton_%s" % self.name
13424bce201SDaniel Bristot de Oliveira
13524bce201SDaniel Bristot de Oliveira        buff = self.fill_model_h_header()
13624bce201SDaniel Bristot de Oliveira        buff += self.format_model()
13724bce201SDaniel Bristot de Oliveira
13824bce201SDaniel Bristot de Oliveira        return self.__buff_to_string(buff)
13924bce201SDaniel Bristot de Oliveira
14024bce201SDaniel Bristot de Oliveira    def __create_directory(self):
14124bce201SDaniel Bristot de Oliveira        try:
14224bce201SDaniel Bristot de Oliveira            os.mkdir(self.name)
14324bce201SDaniel Bristot de Oliveira        except FileExistsError:
14424bce201SDaniel Bristot de Oliveira            return
14524bce201SDaniel Bristot de Oliveira        except:
14624bce201SDaniel Bristot de Oliveira            print("Fail creating the output dir: %s" % self.name)
14724bce201SDaniel Bristot de Oliveira
14824bce201SDaniel Bristot de Oliveira    def __create_file(self, file_name, content):
14924bce201SDaniel Bristot de Oliveira        path = "%s/%s" % (self.name, file_name)
15024bce201SDaniel Bristot de Oliveira        try:
15124bce201SDaniel Bristot de Oliveira            file = open(path, 'w')
15224bce201SDaniel Bristot de Oliveira        except FileExistsError:
15324bce201SDaniel Bristot de Oliveira            return
15424bce201SDaniel Bristot de Oliveira        except:
15524bce201SDaniel Bristot de Oliveira            print("Fail creating file: %s" % path)
15624bce201SDaniel Bristot de Oliveira
15724bce201SDaniel Bristot de Oliveira        file.write(content)
15824bce201SDaniel Bristot de Oliveira
15924bce201SDaniel Bristot de Oliveira        file.close()
16024bce201SDaniel Bristot de Oliveira
16124bce201SDaniel Bristot de Oliveira    def __get_main_name(self):
16224bce201SDaniel Bristot de Oliveira        path = "%s/%s" % (self.name, "main.c")
16324bce201SDaniel Bristot de Oliveira        if os.path.exists(path) == False:
16424bce201SDaniel Bristot de Oliveira           return "main.c"
16524bce201SDaniel Bristot de Oliveira        return "__main.c"
16624bce201SDaniel Bristot de Oliveira
16724bce201SDaniel Bristot de Oliveira    def print_files(self):
16824bce201SDaniel Bristot de Oliveira        main_c = self.fill_main_c()
16924bce201SDaniel Bristot de Oliveira        model_h = self.fill_model_h()
17024bce201SDaniel Bristot de Oliveira
17124bce201SDaniel Bristot de Oliveira        self.__create_directory()
17224bce201SDaniel Bristot de Oliveira
17324bce201SDaniel Bristot de Oliveira        path = "%s.c" % self.name
17424bce201SDaniel Bristot de Oliveira        self.__create_file(path, main_c)
17524bce201SDaniel Bristot de Oliveira
17624bce201SDaniel Bristot de Oliveira        path = "%s.h" % self.name
17724bce201SDaniel Bristot de Oliveira        self.__create_file(path, model_h)
178