Skip to content

Instantly share code, notes, and snippets.

@dylanliuh2o
Last active July 4, 2023 17:03
Show Gist options
  • Save dylanliuh2o/a9f9fcfbd5aac072def43d783de8873c to your computer and use it in GitHub Desktop.
Save dylanliuh2o/a9f9fcfbd5aac072def43d783de8873c to your computer and use it in GitHub Desktop.
simple cli program framework
#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