Merge pull request #239 from antmicro/extract_common_frontends_part

Extract common parts of UHDM frontends to UhdmCommonFrontend
diff --git a/uhdm-plugin/Makefile b/uhdm-plugin/Makefile
index 9f43dc0..223a126 100644
--- a/uhdm-plugin/Makefile
+++ b/uhdm-plugin/Makefile
@@ -9,6 +9,7 @@
 NAME = uhdm
 SOURCES = UhdmAst.cc \
 	  uhdmastfrontend.cc \
+	  uhdmcommonfrontend.cc \
 	  uhdmsurelogastfrontend.cc \
 	  uhdmastreport.cc
 
diff --git a/uhdm-plugin/uhdmastfrontend.cc b/uhdm-plugin/uhdmastfrontend.cc
index c857076..9a22339 100644
--- a/uhdm-plugin/uhdmastfrontend.cc
+++ b/uhdm-plugin/uhdmastfrontend.cc
@@ -19,9 +19,7 @@
  *
  */
 
-#include "UhdmAst.h"
-#include "frontends/ast/ast.h"
-#include "kernel/yosys.h"
+#include "uhdmcommonfrontend.h"
 
 namespace UHDM
 {
@@ -31,15 +29,9 @@
 
 YOSYS_NAMESPACE_BEGIN
 
-/* Stub for AST::process */
-static void set_line_num(int) {}
-
-/* Stub for AST::process */
-static int get_line_num(void) { return 1; }
-
-struct UhdmAstFrontend : public Frontend {
-    UhdmAstFrontend() : Frontend("uhdm", "read UHDM file") {}
-    void help()
+struct UhdmAstFrontend : public UhdmCommonFrontend {
+    UhdmAstFrontend() : UhdmCommonFrontend("uhdm", "read UHDM file") {}
+    void help() override
     {
         //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
         log("\n");
@@ -47,70 +39,27 @@
         log("\n");
         log("Load design from a UHDM file into the current design\n");
         log("\n");
-        log("    -noassert\n");
-        log("        ignore assert() statements");
-        log("\n");
-        log("    -debug\n");
-        log("        print debug info to stdout");
-        log("\n");
-        log("    -report [directory]\n");
-        log("        write a coverage report for the UHDM file\n");
-        log("\n");
-        log("    -defer\n");
-        log("        only read the abstract syntax tree and defer actual compilation\n");
-        log("        to a later 'hierarchy' command. Useful in cases where the default\n");
-        log("        parameters of modules yield invalid or not synthesizable code.\n");
-        log("\n");
+        this->print_read_options();
     }
-    void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+    AST::AstNode *parse(std::string filename) override
     {
-        log_header(design, "Executing UHDM frontend.\n");
-
-        UhdmAstShared shared;
-        UhdmAst uhdm_ast(shared);
-        bool defer = false;
-
-        std::string report_directory;
-        for (size_t i = 1; i < args.size(); i++) {
-            if (args[i] == "-debug") {
-                shared.debug_flag = true;
-            } else if (args[i] == "-report" && ++i < args.size()) {
-                report_directory = args[i];
-                shared.stop_on_error = false;
-            } else if (args[i] == "-noassert") {
-                shared.no_assert = true;
-            } else if (args[i] == "-defer") {
-                defer = true;
-            }
-        }
-        extra_args(f, filename, args, args.size() - 1);
-
-        AST::current_filename = filename;
-        AST::set_line_num = &set_line_num;
-        AST::get_line_num = &get_line_num;
-        struct AST::AstNode *current_ast;
-
         UHDM::Serializer serializer;
 
         std::vector<vpiHandle> restoredDesigns = serializer.Restore(filename);
         for (auto design : restoredDesigns) {
             std::stringstream strstr;
-            UHDM::visit_object(design, 1, "", &shared.report.unhandled, shared.debug_flag ? std::cout : strstr);
+            UHDM::visit_object(design, 1, "", &this->shared.report.unhandled, this->shared.debug_flag ? std::cout : strstr);
         }
-        current_ast = uhdm_ast.visit_designs(restoredDesigns);
-        if (!report_directory.empty()) {
-            shared.report.write(report_directory);
+        UhdmAst uhdm_ast(this->shared);
+        AST::AstNode *current_ast = uhdm_ast.visit_designs(restoredDesigns);
+        if (!this->report_directory.empty()) {
+            this->shared.report.write(this->report_directory);
         }
         for (auto design : restoredDesigns)
             vpi_release_handle(design);
-        bool dump_ast1 = shared.debug_flag;
-        bool dump_ast2 = shared.debug_flag;
-        bool dont_redefine = false;
-        bool default_nettype_wire = true;
-        AST::process(design, current_ast, dump_ast1, dump_ast2, false, false, false, false, false, false, false, false, false, false, false, false,
-                     false, false, dont_redefine, false, defer, default_nettype_wire);
-        delete current_ast;
+        return current_ast;
     }
+    void call_log_header(RTLIL::Design *design) override { log_header(design, "Executing UHDM frontend.\n"); }
 } UhdmAstFrontend;
 
 YOSYS_NAMESPACE_END
diff --git a/uhdm-plugin/uhdmcommonfrontend.cc b/uhdm-plugin/uhdmcommonfrontend.cc
new file mode 100644
index 0000000..b340797
--- /dev/null
+++ b/uhdm-plugin/uhdmcommonfrontend.cc
@@ -0,0 +1,86 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2020 Antmicro
+
+ *  Based on frontends/json/jsonparse.cc
+ *
+ *  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 "uhdmcommonfrontend.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+/* Stub for AST::process */
+static void set_line_num(int) {}
+
+/* Stub for AST::process */
+static int get_line_num(void) { return 1; }
+
+void UhdmCommonFrontend::print_read_options()
+{
+    log("    -noassert\n");
+    log("        ignore assert() statements");
+    log("\n");
+    log("    -debug\n");
+    log("        print debug info to stdout");
+    log("\n");
+    log("    -report [directory]\n");
+    log("        write a coverage report for the UHDM file\n");
+    log("\n");
+    log("    -defer\n");
+    log("        only read the abstract syntax tree and defer actual compilation\n");
+    log("        to a later 'hierarchy' command. Useful in cases where the default\n");
+    log("        parameters of modules yield invalid or not synthesizable code.\n");
+    log("\n");
+}
+
+void UhdmCommonFrontend::execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+{
+    this->call_log_header(design);
+    this->args = args;
+
+    bool defer = false;
+    for (size_t i = 1; i < args.size(); i++) {
+        if (args[i] == "-debug") {
+            this->shared.debug_flag = true;
+        } else if (args[i] == "-report" && ++i < args.size()) {
+            this->report_directory = args[i];
+            this->shared.stop_on_error = false;
+        } else if (args[i] == "-noassert") {
+            this->shared.no_assert = true;
+        } else if (args[i] == "-defer") {
+            defer = true;
+        }
+    }
+    extra_args(f, filename, args, args.size() - 1);
+
+    AST::current_filename = filename;
+    AST::set_line_num = &set_line_num;
+    AST::get_line_num = &get_line_num;
+
+    bool dump_ast1 = this->shared.debug_flag;
+    bool dump_ast2 = this->shared.debug_flag;
+    bool dont_redefine = false;
+    bool default_nettype_wire = true;
+
+    AST::AstNode *current_ast = parse(filename);
+
+    AST::process(design, current_ast, dump_ast1, dump_ast2, false, false, false, false, false, false, false, false, false, false, false, false, false,
+                 false, dont_redefine, false, defer, default_nettype_wire);
+    delete current_ast;
+}
+
+YOSYS_NAMESPACE_END
diff --git a/uhdm-plugin/uhdmcommonfrontend.h b/uhdm-plugin/uhdmcommonfrontend.h
new file mode 100644
index 0000000..f2d12a8
--- /dev/null
+++ b/uhdm-plugin/uhdmcommonfrontend.h
@@ -0,0 +1,42 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2020 Antmicro
+
+ *  Based on frontends/json/jsonparse.cc
+ *
+ *  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 "UhdmAst.h"
+#include "frontends/ast/ast.h"
+#include "kernel/yosys.h"
+#include <string>
+#include <vector>
+
+YOSYS_NAMESPACE_BEGIN
+
+struct UhdmCommonFrontend : public Frontend {
+    UhdmAstShared shared;
+    std::string report_directory;
+    std::vector<std::string> args;
+    UhdmCommonFrontend(std::string name, std::string short_help) : Frontend(name, short_help) {}
+    virtual void print_read_options();
+    virtual void help() = 0;
+    virtual AST::AstNode *parse(std::string filename) = 0;
+    virtual void call_log_header(RTLIL::Design *design) = 0;
+    void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design);
+};
+
+YOSYS_NAMESPACE_END
diff --git a/uhdm-plugin/uhdmsurelogastfrontend.cc b/uhdm-plugin/uhdmsurelogastfrontend.cc
index 5e0ca4b..ce79772 100644
--- a/uhdm-plugin/uhdmsurelogastfrontend.cc
+++ b/uhdm-plugin/uhdmsurelogastfrontend.cc
@@ -22,6 +22,7 @@
 #include "UhdmAst.h"
 #include "frontends/ast/ast.h"
 #include "kernel/yosys.h"
+#include "uhdmcommonfrontend.h"
 
 #if defined(_MSC_VER)
 #include <direct.h>
@@ -76,9 +77,16 @@
     return the_design;
 }
 
-struct UhdmSurelogAstFrontend : public Frontend {
-    UhdmSurelogAstFrontend() : Frontend("verilog_with_uhdm", "generate/read UHDM file") {}
-    void help()
+struct UhdmSurelogAstFrontend : public UhdmCommonFrontend {
+    UhdmSurelogAstFrontend() : UhdmCommonFrontend("verilog_with_uhdm", "generate/read UHDM file") {}
+    void print_read_options() override
+    {
+        log("    -process\n");
+        log("        loads design from given UHDM file\n");
+        log("\n");
+        UhdmCommonFrontend::print_read_options();
+    }
+    void help() override
     {
         //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
         log("\n");
@@ -86,56 +94,14 @@
         log("\n");
         log("Generate or load design from a UHDM file into the current design\n");
         log("\n");
-        log("    -process\n");
-        log("        loads design from given UHDM file\n");
-        log("\n");
-        log("    -noassert\n");
-        log("        ignore assert() statements");
-        log("\n");
-        log("    -debug\n");
-        log("        print debug info to stdout");
-        log("\n");
-        log("    -report [directory]\n");
-        log("        write a coverage report for the UHDM file\n");
-        log("\n");
-        log("    -defer\n");
-        log("        only read the abstract syntax tree and defer actual compilation\n");
-        log("        to a later 'hierarchy' command. Useful in cases where the default\n");
-        log("        parameters of modules yield invalid or not synthesizable code.\n");
-        log("\n");
+        this->print_read_options();
     }
-    void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+    AST::AstNode *parse(std::string filename) override
     {
-        log_header(design, "Executing Verilog with UHDM frontend.\n");
-
-        UhdmAstShared shared;
-        UhdmAst uhdm_ast(shared);
-        bool defer = false;
-
-        std::string report_directory;
-        auto it = args.begin();
-        while (it != args.end()) {
-            if (*it == "-debug") {
-                shared.debug_flag = true;
-                it = args.erase(it);
-            } else if (*it == "-report" && (it = args.erase(it)) < args.end()) {
-                report_directory = *it;
-                shared.stop_on_error = false;
-                it = args.erase(it);
-            } else if (*it == "-noassert") {
-                shared.no_assert = true;
-                it = args.erase(it);
-            } else if (*it == "-defer") {
-                defer = true;
-                it = args.erase(it);
-            } else {
-                ++it;
-            }
-        }
         std::vector<const char *> cstrings;
-        cstrings.reserve(args.size());
-        for (size_t i = 0; i < args.size(); ++i)
-            cstrings.push_back(const_cast<char *>(args[i].c_str()));
+        cstrings.reserve(this->args.size());
+        for (size_t i = 0; i < this->args.size(); ++i)
+            cstrings.push_back(const_cast<char *>(this->args[i].c_str()));
 
         SURELOG::SymbolTable *symbolTable = new SURELOG::SymbolTable();
         SURELOG::ErrorContainer *errors = new SURELOG::ErrorContainer(symbolTable);
@@ -146,22 +112,21 @@
         }
         SURELOG::scompiler *compiler = nullptr;
         const std::vector<vpiHandle> uhdm_design = executeCompilation(symbolTable, errors, clp, compiler);
-        struct AST::AstNode *current_ast = uhdm_ast.visit_designs(uhdm_design);
-        if (report_directory != "") {
-            shared.report.write(report_directory);
-        }
-        bool dump_ast1 = shared.debug_flag;
-        bool dump_ast2 = shared.debug_flag;
-        bool dont_redefine = false;
-        bool default_nettype_wire = true;
-        AST::process(design, current_ast, dump_ast1, dump_ast2, false, false, false, false, false, false, false, false, false, false, false, false,
-                     false, false, dont_redefine, false, defer, default_nettype_wire);
-        delete current_ast;
+
         SURELOG::shutdown_compiler(compiler);
         delete clp;
         delete symbolTable;
         delete errors;
+
+        UhdmAst uhdm_ast(this->shared);
+        AST::AstNode *current_ast = uhdm_ast.visit_designs(uhdm_design);
+        if (report_directory != "") {
+            shared.report.write(report_directory);
+        }
+
+        return current_ast;
     }
+    void call_log_header(RTLIL::Design *design) override { log_header(design, "Executing Verilog with UHDM frontend.\n"); }
 } UhdmSurelogAstFrontend;
 
 YOSYS_NAMESPACE_END