Merge pull request #382 from kanndil/clock_gating

Adding clock gating plugin
diff --git a/.github/workflows/build-and-test.sh b/.github/workflows/build-and-test.sh
index 7d0401e..69fd8a7 100755
--- a/.github/workflows/build-and-test.sh
+++ b/.github/workflows/build-and-test.sh
@@ -19,12 +19,22 @@
 
 source .github/workflows/common.sh
 
+if [ -z "${PLUGIN_NAME}" ]; then
+	echo "Missing \${PLUGIN_NAME} env value"
+	exit 1
+fi
+
 ##########################################################################
 
 start_section Building
 
+if [ "$PLUGIN_NAME" == "xdc" ] || [ "$PLUGIN_NAME" == "sdc" ]; then 
+    make design_introspection.so -j`nproc`
+	make install_design_introspection -j`nproc`
+fi 
+
 export CXXFLAGS=-Werror
-make UHDM_INSTALL_DIR=`pwd`/env/conda/envs/yosys-plugins/ plugins -j`nproc`
+make UHDM_INSTALL_DIR=`pwd`/env/conda/envs/yosys-plugins/ ${PLUGIN_NAME}.so -j`nproc`
 unset CXXFLAGS
 
 end_section
@@ -32,19 +42,19 @@
 ##########################################################################
 
 start_section Installing
-make install -j`nproc`
+make install_${PLUGIN_NAME} -j`nproc`
 end_section
 
 ##########################################################################
 
 start_section Testing
-make test -j`nproc`
+make test_${PLUGIN_NAME} -j`nproc`
 end_section
 
 ##########################################################################
 
 start_section Cleanup
-make plugins_clean -j`nproc`
+make clean_${PLUGIN_NAME} -j`nproc`
 end_section
 
 ##########################################################################
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4ab1814..1ab44d1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,6 +23,22 @@
   Run-tests:
     runs-on: ubuntu-20.04
 
+    strategy:
+      fail-fast: false
+      matrix:
+        plugin:
+          - fasm
+          - xdc
+          - params
+          - sdc
+          - ql-iob
+          - design_introspection
+          - integrateinv
+          - ql-qlf
+          - systemverilog
+          - uhdm
+          - dsp-ff
+
     steps:
 
     - uses: actions/checkout@v2
@@ -61,3 +77,4 @@
         source .github/workflows/build-and-test.sh
       env:
         OS: ${{ runner.os }}
+        PLUGIN_NAME: ${{ matrix.plugin }}
diff --git a/environment.yml b/environment.yml
index dc51454..35b3ed9 100644
--- a/environment.yml
+++ b/environment.yml
@@ -20,5 +20,5 @@
   - litex-hub
 dependencies:
   - litex-hub::yosys=0.17_7_g990c9b8e1=20220512_085338_py37
-  - litex-hub::surelog=0.0_5519_g900fb2499=20221223_060448_py37
+  - litex-hub::surelog=0.0_5580_g493120558=20230116_180937_py37
   - litex-hub::iverilog
diff --git a/sdc-plugin/buffers.cc b/sdc-plugin/buffers.cc
index 9c2308a..13177a7 100644
--- a/sdc-plugin/buffers.cc
+++ b/sdc-plugin/buffers.cc
@@ -18,6 +18,9 @@
 #include "buffers.h"
 #include <cassert>
 #include <cmath>
+#include <limits>
+#include <string>
+#include <vector>
 
 const std::vector<std::string> Pll::inputs = {"CLKIN1", "CLKIN2"};
 const std::vector<std::string> Pll::outputs = {"CLKOUT0", "CLKOUT1", "CLKOUT2", "CLKOUT3", "CLKOUT4", "CLKOUT5"};
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc
index 3936d03..3c2ae3e 100644
--- a/systemverilog-plugin/UhdmAst.cc
+++ b/systemverilog-plugin/UhdmAst.cc
@@ -1743,15 +1743,13 @@
                     move_type_to_new_typedef(current_node, node);
                 }
             });
-            visit_one_to_many({vpiModule, vpiInterface, vpiTaskFunc, vpiParameter, vpiParamAssign, vpiPort, vpiNet, vpiArrayNet, vpiGenScopeArray,
-                               vpiProcess, vpiClockingBlock, vpiAssertion},
-                              obj_h, [&](AST::AstNode *node) {
-                                  if (node) {
-                                      if (node->type == AST::AST_ASSIGN && node->children.size() < 2)
-                                          return;
-                                      add_or_replace_child(current_node, node);
-                                  }
-                              });
+            visit_one_to_many({vpiModule, vpiParameter, vpiParamAssign, vpiNet, vpiArrayNet, vpiProcess}, obj_h, [&](AST::AstNode *node) {
+                if (node) {
+                    if (node->type == AST::AST_ASSIGN && node->children.size() < 2)
+                        return;
+                    add_or_replace_child(current_node, node);
+                }
+            });
         }
     } else {
         // Not a top module, create instance
@@ -1869,7 +1867,7 @@
                 add_or_replace_child(module_node, node);
             }
         });
-        visit_one_to_many({vpiInterface, vpiModule, vpiPort, vpiGenScopeArray, vpiContAssign}, obj_h, [&](AST::AstNode *node) {
+        visit_one_to_many({vpiInterface, vpiModule, vpiPort, vpiGenScopeArray, vpiContAssign, vpiTaskFunc}, obj_h, [&](AST::AstNode *node) {
             if (node) {
                 add_or_replace_child(module_node, node);
             }
@@ -4261,10 +4259,11 @@
     visit_one_to_one({vpiExpr}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
 }
 
-void UhdmAst::process_unsupported_stmt(const UHDM::BaseClass *object)
+void UhdmAst::process_unsupported_stmt(const UHDM::BaseClass *object, bool is_error)
 {
-    log_error("%.*s:%d: Currently not supported object of type '%s'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
-              object->VpiLineNo(), UHDM::VpiTypeName(obj_h).c_str());
+    const auto log_func = is_error ? log_error : log_warning;
+    std::string prefix = object->VpiLineNo() ? (std::string(object->VpiFile()) + ":" + std::to_string(object->VpiLineNo()) + ": ") : "";
+    log_func("%sCurrently not supported object of type '%s'\n", prefix.c_str(), UHDM::VpiTypeName(obj_h).c_str());
 }
 
 AST::AstNode *UhdmAst::process_object(vpiHandle obj_handle)
@@ -4386,6 +4385,9 @@
     case vpiInitial:
         process_initial();
         break;
+    case vpiFinal:
+        process_unsupported_stmt(object, false);
+        break;
     case vpiNamedBegin:
         process_begin(true);
         break;
@@ -4535,6 +4537,13 @@
     case vpiClockingBlock:
         process_unsupported_stmt(object);
         break;
+    case vpiTypeParameter:
+        // Instances in an `uhdmTopModules` tree already have all parameter references
+        // substituted with the parameter type/value by Surelog,
+        // so the plugin doesn't need to process the parameter itself.
+        // Other parameter types are handled by the plugin
+        // mainly because they were implemented before Surelog did the substitution.
+        break;
     case vpiProgram:
     default:
         report_error("%.*s:%d: Encountered unhandled object '%.*s' of type '%s'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
diff --git a/systemverilog-plugin/UhdmAst.h b/systemverilog-plugin/UhdmAst.h
index 6d6a8f6..bbd0460 100644
--- a/systemverilog-plugin/UhdmAst.h
+++ b/systemverilog-plugin/UhdmAst.h
@@ -151,7 +151,7 @@
     void process_gate();
     void process_primterm();
     void simplify_parameter(::Yosys::AST::AstNode *parameter, ::Yosys::AST::AstNode *module_node = nullptr);
-    void process_unsupported_stmt(const UHDM::BaseClass *object);
+    void process_unsupported_stmt(const UHDM::BaseClass *object, bool is_error = true);
 
     UhdmAst(UhdmAst *p, UhdmAstShared &s, const std::string &i) : parent(p), shared(s), indent(i)
     {