From 4f53612725ad1fe4b4d125fe53c85dedc05e1482 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 21 Jan 2026 03:18:12 +0000 Subject: [PATCH] Add `linux_perf` command to turn Linux perf recording on and off. This is extremely useful for profiling specific passes. --- passes/cmds/Makefile.inc | 1 + passes/cmds/linux_perf.cc | 96 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 passes/cmds/linux_perf.cc diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index dc12c92c2..5e2994a53 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -37,6 +37,7 @@ OBJS += passes/cmds/chformal.o OBJS += passes/cmds/chtype.o OBJS += passes/cmds/blackbox.o OBJS += passes/cmds/ltp.o +OBJS += passes/cmds/linux_perf.o ifeq ($(DISABLE_SPAWN),0) OBJS += passes/cmds/bugpoint.o endif diff --git a/passes/cmds/linux_perf.cc b/passes/cmds/linux_perf.cc new file mode 100644 index 000000000..f57a887fb --- /dev/null +++ b/passes/cmds/linux_perf.cc @@ -0,0 +1,96 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2014 Claire Xenia Wolf + * Copyright (C) 2014 Johann Glaser + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/log_help.h" + +#include +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#ifdef __linux__ +struct LinuxPerf : public Pass { + LinuxPerf() : Pass("linux_perf", "turn linux perf recording off or on") { } + void help() override + { + log("This pass turns Linux 'perf' profiling on or off, when it has been configured to use control FIFOs.\n"); + log("\n"); + log("Example shell command line:\n"); + log("mkfifo /tmp/perf.fifo /tmp/perf-ack.fifo\n"); + log("YOSYS_PERF_CTL=/tmp/perf.fifo YOSYS_PERF_ACK=/tmp/perf-ack.fifo \\\n"); + log(" perf record --latency --delay=-1 \\\n"); + log(" --control=fifo:/tmp/perf.fifo,/tmp/perf-ack.fifo --call-graph=dwarf ./yosys -dt -p \\\n"); + log(" \"read_rtlil design.rtlil; linux_perf on; opt_clean; linux_perf off\"\n"); + log("\n"); + log(" linux_perf on\n"); + log("\n"); + log("Start perf recording. YOSYS_PERF_CTL and YOSYS_PERF_ACK must point to Linux perf control FIFOs.\n"); + log("\n"); + log(" linux_perf off\n"); + log("\n"); + log("Stop perf recording.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *) override + { + if (args.size() > 2) + cmd_error(args, 2, "Unexpected argument."); + + std::string_view ctl_msg; + if (args.size() == 2) { + if (args[1] == "on") + ctl_msg = "enable\n"; + else if (args[1] == "off") + ctl_msg = "disable\n"; + else + cmd_error(args, 1, "Unexpected argument."); + } + + const char *ctl_fifo = std::getenv("YOSYS_PERF_CTL"); + if (!ctl_fifo) + log_error("YOSYS_PERF_CTL environment variable not set."); + const char *ack_fifo = std::getenv("YOSYS_PERF_ACK"); + if (!ack_fifo) + log_error("YOSYS_PERF_ACK environment variable not set."); + + int ctl_fd = open(ctl_fifo, O_WRONLY); + if (ctl_fd < 0) + log_error("Failed to open YOSYS_PERF_CTL."); + int ack_fd = open(ack_fifo, O_RDONLY); + if (ack_fd < 0) + log_error("Failed to open YOSYS_PERF_ACK."); + int result = write(ctl_fd, ctl_msg.data(), ctl_msg.size()); + if (result != static_cast(ctl_msg.size())) + log_error("Failed to write to YOSYS_PERF_CTL."); + char buffer[64]; + result = read(ack_fd, buffer, sizeof(buffer)); + close(ctl_fd); + close(ack_fd); + if (result <= 0) + log_error("Failed to read from YOSYS_PERF_ACK."); + if (strcmp(buffer, "ack\n") != 0) + log_error("YOSYS_PERF_ACK did not return 'ack'."); + } +} LinuxPerf; +#endif + +PRIVATE_NAMESPACE_END