Last active
July 4, 2023 17:03
-
-
Save dylanliuh2o/a9f9fcfbd5aac072def43d783de8873c to your computer and use it in GitHub Desktop.
simple cli program framework
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <format> | |
#include <string> | |
#include <vector> | |
#include <map> | |
struct Pass; | |
std::map<std::string, Pass*> pass_register; | |
// Assuming a series of design data is stored here | |
// The following series of commands will manipulate the design database | |
struct DesignDatabase { | |
// ... | |
// ... | |
}; | |
// pass.cc | |
// root class of all commands | |
struct Pass { | |
Pass(std::string cmd_name, std::string description) | |
{ | |
pass_register[cmd_name] = this; | |
} | |
virtual void help() = 0; | |
virtual void execute(std::vector<std::string> args) = 0; | |
}; | |
// help.cc | |
struct HelpPass final : Pass { | |
HelpPass() : Pass("help", "Get help.") { } | |
void help() override | |
{ | |
std::cout << "\n"; | |
std::cout << " help <command_name>\n"; | |
std::cout << "\n"; | |
} | |
void execute(std::vector<std::string> args) override | |
{ | |
std::cout << std::format("Executing command '{}' now...\n", args.front()); | |
std::string cmd_name; | |
// setting up arguments | |
for (decltype(args)::size_type i = 1; i < args.size(); i++) { | |
if (i == 1) { | |
cmd_name = args[i]; | |
continue; | |
} | |
} | |
if (!pass_register.count(cmd_name)) { | |
std::cerr << std::format("Command '{}' not found!\n", cmd_name); | |
return; | |
} | |
pass_register[cmd_name]->help(); | |
} | |
} HelpPass; | |
// readfile.cc | |
struct ReadFilePass final : Pass { | |
ReadFilePass() : Pass("read_file", "Read design files.") { } | |
void help() override | |
{ | |
std::cout << "\n"; | |
std::cout << " read_file [options]\n"; | |
std::cout << "\n"; | |
std::cout << " -verilog <filename>\n"; | |
std::cout << "\n"; | |
std::cout << " read file in verilog mode\n"; | |
std::cout << "\n"; | |
std::cout << " -sv <filename>\n"; | |
std::cout << "\n"; | |
std::cout << " read file in system-verilog mode\n"; | |
std::cout << "\n"; | |
std::cout << " -f <filelist>\n"; | |
std::cout << "\n"; | |
std::cout << " read files from filelist\n"; | |
std::cout << "\n"; | |
} | |
void execute(std::vector<std::string> args) override | |
{ | |
std::cout << std::format("Executing command '{}' now...\n", args.front()); | |
enum class FileMode { | |
VERILOG = 0, | |
SVERILOG, | |
}; | |
FileMode file_mode { FileMode::VERILOG }; | |
std::string filelist_path; | |
// setting up arguments | |
for (decltype(args)::size_type i = 1; i < args.size(); i++) { | |
if (args[i] == "-verilog") { | |
continue; | |
} | |
if (args[i] == "-sv") { | |
file_mode = FileMode::SVERILOG; | |
continue; | |
} | |
if (args[i] == "-f") { | |
if (i + 1 >= args.size()) { | |
std::cerr << "Missing <filelist> after '-f'!\n"; | |
} | |
filelist_path = args[++i]; | |
} | |
} | |
// do something... | |
// finished | |
std::cout << std::format("Command '{}' finished.\n", args.front()); | |
} | |
} ReadFilePass; | |
// analyze.cc | |
struct AnalyzePass final : Pass { | |
AnalyzePass() : Pass("analyze", "Analyze files being read.") { } | |
void help() override | |
{ | |
std::cout << "\n"; | |
std::cout << " analyze [options]\n"; | |
std::cout << "\n"; | |
std::cout << " -nolibreset\n"; | |
std::cout << "\n"; | |
std::cout << " maintain libraries in memory after analyzing\n"; | |
std::cout << "\n"; | |
} | |
void execute(std::vector<std::string> args) override | |
{ | |
std::cout << std::format("Executing command '{}' now...\n", args.front()); | |
// setting up arguments | |
bool nolibreset = false; | |
for (decltype(args)::size_type i = 1; i < args.size(); i++) { | |
if (args[i] == "-nolibreset") { | |
nolibreset = true; | |
continue; | |
} | |
} | |
// do something... | |
// finished | |
std::cout << std::format("Command '{}' finished.\n", args.front()); | |
} | |
} AnalyzePass; | |
// elaborate.cc | |
struct ElaboratePass final : Pass { | |
ElaboratePass() : Pass("elaborate", "Elaborate design being analyzed.") { } | |
void help() override | |
{ | |
std::cout << "\n"; | |
std::cout << " elaborate <top_module_name>\n"; | |
std::cout << "\n"; | |
} | |
void execute(std::vector<std::string> args) override | |
{ | |
std::cout << std::format("Executing command '{}' now...\n", args.front()); | |
std::string top_module_name; | |
// setting up arguments | |
for (decltype(args)::size_type i = 1; i < args.size(); i++) { | |
if (i == 1) { | |
top_module_name = args[i]; | |
continue; | |
} | |
} | |
if (top_module_name.empty()) { | |
std::cerr << "Please specify top module!\n"; | |
return; | |
} | |
// do something... | |
// finished | |
std::cout << std::format("Command '{}' finished.\n", args.front()); | |
} | |
} ElaboratePass; | |
// optimize.cc | |
struct OptimizePass final : Pass { | |
OptimizePass() : Pass("optimize", "Do optimization on current design.") { } | |
void help() override | |
{ | |
std::cout << "\n"; | |
std::cout << " optimize\n"; | |
std::cout << "\n"; | |
} | |
void execute(std::vector<std::string> args) override | |
{ | |
std::cout << std::format("Executing command '{}' now...\n", args.front()); | |
// setting up arguments | |
for (decltype(args)::size_type i = 1; i < args.size(); i++) { | |
; | |
} | |
// do something... | |
// finished | |
std::cout << std::format("Command '{}' finished.\n", args.front()); | |
} | |
} OptimizePass; | |
// verify.cc | |
struct VerifyPass final : Pass { | |
VerifyPass() : Pass("verify", "verify current design.") { } | |
void help() override | |
{ | |
std::cout << "\n"; | |
std::cout << " verify\n"; | |
std::cout << "\n"; | |
} | |
void execute(std::vector<std::string> args) override | |
{ | |
std::cout << std::format("Executing command '{}' now...\n", args.front()); | |
// setting up arguments | |
for (decltype(args)::size_type i = 1; i < args.size(); i++) { | |
; | |
} | |
// do something... | |
// finished | |
std::cout << std::format("Command '{}' finished.\n", args.front()); | |
} | |
} VerifyPass; | |
// report.cc | |
struct ReportPass final : Pass { | |
ReportPass() : Pass("report", "Report result.") { } | |
void help() override | |
{ | |
std::cout << "\n"; | |
std::cout << " report [options]\n"; | |
std::cout << "\n"; | |
std::cout << " -o <output_file>\n"; | |
std::cout << "\n"; | |
std::cout << " specify output file\n"; | |
std::cout << "\n"; | |
} | |
void execute(std::vector<std::string> args) override | |
{ | |
std::cout << std::format("Executing command '{}' now...\n", args.front()); | |
// setting up arguments | |
for (decltype(args)::size_type i = 1; i < args.size(); i++) { | |
; | |
} | |
// do something... | |
// finished | |
std::cout << std::format("Command '{}' finished.\n", args.front()); | |
} | |
} ReportPass; | |
int main() | |
{ | |
std::vector<std::vector<std::string>> user_script { | |
{ "help", "read_file" }, | |
{ "help", "analyze" }, | |
{ "help", "elaborate" }, | |
{ "help", "optimize" }, | |
{ "help", "verify" }, | |
{ "help", "report" }, | |
{ "read_file", "-f", "../work/filelist", "-sv"}, | |
{ "analyze", "-nolibreset" }, | |
{ "elaborate", "main" }, | |
{ "optimize" }, | |
{ "verify" }, | |
{ "report", "-o", "report.log" }, | |
}; | |
for (auto args : user_script) { | |
if (args.size() < 1) { | |
// error handling | |
std::cerr << "Somthing went wrong!\n"; | |
break; | |
} | |
std::string cmd_name = args.front(); | |
if (!pass_register.count(cmd_name)) { | |
// error handling | |
std::cerr << std::format("Command '{}' not found!\n", cmd_name); | |
break; | |
} | |
pass_register[cmd_name]->execute(args); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment