From 41a489f085e5d661000f33683e0b6eff0cbb03f9 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 21 Mar 2025 10:24:27 +1300 Subject: [PATCH] register: Add pass_usages and default help Experimental new formatting for describing passes that can be rendered into the standard help format, as well as being more amenable to smarter formatting for web documentation. --- kernel/register.cc | 45 +++++++++++++++++++++++++++++++++++++++++---- kernel/register.h | 20 +++++++++++++++++++- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index a55be28b2..2cacb9406 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -29,6 +29,30 @@ YOSYS_NAMESPACE_BEGIN +#define MAX_LINE_LEN 80 +void log_pass_str(const std::string &pass_str, int indent=0, bool leading_newline=false) { + if (pass_str.empty()) + return; + std::string indent_str(indent*4, ' '); + std::istringstream iss(pass_str); + if (leading_newline) + log("\n"); + for (std::string line; std::getline(iss, line);) { + log("%s", indent_str.c_str()); + auto curr_len = indent_str.length(); + std::istringstream lss(line); + for (std::string word; std::getline(lss, word, ' ');) { + if (curr_len + word.length() >= MAX_LINE_LEN) { + curr_len = 0; + log("\n%s", indent_str.c_str()); + } + log("%s ", word.c_str()); + curr_len += word.length() + 1; + } + log("\n"); + } +} + #define MAX_REG_COUNT 1000 bool echo_mode = false; @@ -41,7 +65,7 @@ std::map backend_register; std::vector Frontend::next_args; -Pass::Pass(std::string name, std::string short_help) : pass_name(name), short_help(short_help) +Pass::Pass(std::string name, std::string short_help, const vector usages) : pass_name(name), short_help(short_help), pass_usages(usages) { next_queued_pass = first_queued_pass; first_queued_pass = this; @@ -116,9 +140,22 @@ void Pass::post_execute(Pass::pre_post_exec_state_t state) void Pass::help() { - log("\n"); - log("No help message for command `%s'.\n", pass_name.c_str()); - log("\n"); + if (HasUsages()) { + for (auto usage : pass_usages) { + log_pass_str(usage.signature, 1, true); + log_pass_str(usage.description, 0, true); + for (auto option : usage.options) { + log_pass_str(option.keyword, 1, true); + log_pass_str(option.description, 2, false); + } + log_pass_str(usage.postscript, 0, true); + } + log("\n"); + } else { + log("\n"); + log("No help message for command `%s'.\n", pass_name.c_str()); + log("\n"); + } } void Pass::clear_flags() diff --git a/kernel/register.h b/kernel/register.h index 25ea9f232..31167d532 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -25,10 +25,24 @@ YOSYS_NAMESPACE_BEGIN +struct PassOption { + string keyword; + string description; +}; + +struct PassUsageBlock { + string signature = ""; + string description = ""; + vector options = {}; + string postscript = ""; +}; + struct Pass { std::string pass_name, short_help; - Pass(std::string name, std::string short_help = "** document me **"); + const vector pass_usages; + Pass(std::string name, std::string short_help = "** document me **", + const vector usages = {}); virtual ~Pass(); virtual void help(); @@ -43,6 +57,10 @@ struct Pass experimental_flag = true; } + bool HasUsages() { + return !pass_usages.empty(); + } + struct pre_post_exec_state_t { Pass *parent_pass; int64_t begin_ns;