| /** |
| * Copyright (c) 2020-2021 Robert Bosch GmbH. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Robert Bosch GmbH - initial API and implementation |
| */ |
| |
| package org.eclipse.app4mc.slg.ros2.generators |
| |
| class RosAmlGenerator { |
| |
| // Suppress default constructor |
| private new() { |
| throw new IllegalStateException("Utility class"); |
| } |
| |
| static def String toCpp() ''' |
| #include "aml.h" |
| #include <mutex> |
| |
| std::mutex lock_; |
| static long perf_event_define(pid_t proccess_id, int group_fd, uint64_t pinned, uint32_t event_type, uint64_t event) |
| { |
| struct perf_event_attr hw_event; |
| pid_t pid = proccess_id; // measure the current process/thread |
| int cpu = -1; // measure on any cpu |
| unsigned long flags = 0; |
| int fd_current; |
| |
| memset(&hw_event, 0, sizeof(struct perf_event_attr)); |
| hw_event.type = event_type; |
| hw_event.size = sizeof(struct perf_event_attr); |
| hw_event.config = event; |
| hw_event.disabled = 1; // off by default. specifies whether the counter starts out disabled or enabled. |
| hw_event.exclude_kernel = 1; // excluding events that happen in the kernel-space |
| hw_event.exclude_hv = 1; // excluding events that happen in the hypervisor |
| hw_event.pinned = pinned; // specifies the counter to be on the CPU if at all possible. applies only to hardware counters and only to group leaders. |
| hw_event.exclude_user = 0; // excludes events that happen in user space |
| hw_event.exclude_callchain_kernel = 1; // Do not include kernel callchains. |
| hw_event.exclude_callchain_user = 0; // Do not include user callchains. |
| // hw_event.inherit = 1; // Inherit does not work for some combinations of read_format values, such as PERF_FORMAT_GROUP. |
| //hw_event.exclusive = 1; // not working for counters other than cycle counter |
| //hw_event.exclude_idle = 1; // doesn't work |
| |
| hw_event.read_format = PERF_FORMAT_GROUP; // Allows all counter values in an event group to be read with one read |
| fd_current = syscall(__NR_perf_event_open, &hw_event, pid, cpu, group_fd, flags); |
| if (fd_current == -1) { |
| int error_num = errno; |
| |
| printf("Error opening leader %llx\n", hw_event.config); |
| printf("Errno error code %d\n", error_num); |
| exit(EXIT_FAILURE); |
| } |
| |
| return fd_current; |
| } |
| |
| int instrument_start(pid_t pid, uint64_t event_list[], int total_events){ |
| lock_.lock(); |
| static int called = 0; |
| static int fd; |
| if(!called) { |
| int i; |
| fd = perf_event_define(pid, -1, 1, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); |
| //perf_event_define(pid, fd, 0, PERF_TYPE_RAW, ) |
| for (i = 0; i < total_events; i++) |
| perf_event_define(pid, fd, 0, PERF_TYPE_RAW, event_list[i]); |
| |
| /* Example usage: |
| |
| perf_event_define(fd, 0, PERF_TYPE_RAW, 0x0008); |
| perf_event_define(fd, 0, PERF_TYPE_RAW, 0x0012); |
| perf_event_define(fd, 0, PERF_TYPE_RAW, 0x0004); |
| perf_event_define(fd, 0, PERF_TYPE_RAW, 0x0003); |
| perf_event_define(fd, 0, PERF_TYPE_RAW, 0x0016); |
| perf_event_define(fd, 0, PERF_TYPE_RAW, 0x0017); |
| |
| int fd = perf_event_define(-1, 1, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); |
| perf_event_define(fd, 0, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); |
| perf_event_define(fd, 0, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); |
| perf_event_define(fd , 0, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); |
| perf_event_define(fd , 0, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); |
| perf_event_define(fd , 0, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)); |
| perf_event_define(fd , 0, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)); |
| |
| */ |
| called = 1; |
| } |
| |
| ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); |
| ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); |
| |
| return fd; |
| } |
| |
| struct read_format { |
| uint64_t nr; // The number of events |
| struct { |
| uint64_t value; // The value of the event |
| } values[]; |
| }; |
| |
| void instrument_stop(int fd, char* filename){ |
| ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP); |
| char buf[4096]; |
| read(fd, buf, sizeof(buf)); |
| |
| |
| int i = 0; |
| struct read_format* rf = (struct read_format*) buf; |
| |
| FILE * file_pointer; |
| file_pointer = fopen(filename, "a"); |
| |
| for (i = 0; i < rf->nr; i++) |
| fprintf(file_pointer, "%" PRId64 "\t", rf->values[i].value); |
| fprintf(file_pointer, "\n"); |
| |
| fclose(file_pointer); |
| //close(fd); |
| lock_.unlock(); |
| } |
| |
| void instrument_read(int fd){ |
| char buf[4096]; |
| read(fd, buf, sizeof(buf)); |
| |
| int i; |
| struct read_format* rf = (struct read_format*) buf; |
| |
| FILE * file_pointer; |
| file_pointer = fopen("output.log", "a"); |
| |
| for (i = 0; i < rf->nr; i++) |
| fprintf(file_pointer, "%" PRId64 "\t", rf->values[i].value); |
| fprintf(file_pointer, "\n"); |
| |
| fclose(file_pointer); |
| ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); |
| } |
| |
| |
| void instrument_read_to_file(int fd, char* filename){ |
| ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP); |
| char buf[4096]; |
| read(fd, buf, sizeof(buf)); |
| |
| int i; |
| struct read_format* rf = (struct read_format*) buf; |
| |
| FILE * file_pointer; |
| file_pointer = fopen(filename, "a"); |
| |
| for (i = 0; i < rf->nr; i++) |
| fprintf(file_pointer, "%" PRId64 "\t", rf->values[i].value); |
| fprintf(file_pointer, "\n"); |
| |
| fclose(file_pointer); |
| ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); |
| ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); |
| } |
| |
| void instrument_reset(int fd) { |
| ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); |
| } |
| |
| ''' |
| |
| static def String toH() ''' |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/ioctl.h> |
| #include <linux/perf_event.h> |
| #include <linux/hw_breakpoint.h> |
| #include <asm/unistd.h> |
| #include <inttypes.h> |
| |
| #include <errno.h> |
| |
| int instrument_start(pid_t pid, uint64_t event_list[], int total_events); |
| void instrument_stop(int fd, char* filename); |
| void instrument_read(int fd); |
| void instrument_reset(int fd); |
| void instrument_read_to_file(int fd, char* filename); |
| ''' |
| |
| } |