Support for default connection for a DSP control port in case a flip-flop does not have matching one.

Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
diff --git a/dsp_ff-plugin/dsp_ff.cc b/dsp_ff-plugin/dsp_ff.cc
index 952c0dd..e88af20 100644
--- a/dsp_ff-plugin/dsp_ff.cc
+++ b/dsp_ff-plugin/dsp_ff.cc
@@ -86,7 +86,7 @@
 
         /// A dict of associated cell ports indexed by their function (like "clk, "rst")
         /// along with the default value to connect when unused.
-        dict<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::State>> assoc;
+        dict<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::Const>> assoc;
 
         struct {
             /// A dict of parameters to be set in the cell after integration
@@ -116,6 +116,7 @@
 
     // ..........................................
 
+    /// Describes unique flip-flop configuration that is exclusive.
     struct FlopData {
         RTLIL::IdString type;
         dict<RTLIL::IdString, RTLIL::SigBit> conns;
@@ -148,8 +149,29 @@
 
     // ..........................................
 
+    /// Loads FF and DSP integration rules from a file
     void load_rules(const std::string& a_FileName) {
 
+        // Parses a string and returns a vector of fields delimited by the
+        // given character.
+        auto getFields = [](const std::string& a_String,
+                             const char a_Delim = ' ',
+                             bool a_KeepEmpty = false)
+        {
+            std::vector<std::string> fields;
+            std::stringstream ss(a_String);
+
+            while (ss.good()) {
+                std::string field;
+                std::getline(ss, field, a_Delim);
+                if (!field.empty() || a_KeepEmpty) {
+                    fields.push_back(field);
+                }
+            }
+
+            return fields;
+        };
+
         // Parses a vector of strings like "<name>=<value>" starting from the
         // second one on the list
         auto parseNameValue = [&](const std::vector<std::string>& strs) {
@@ -202,7 +224,7 @@
             }
 
             // Split the line
-            const auto fields = get_fields(line);
+            const auto fields = getFields(line);
             log_assert(fields.size() >= 1);
 
             // DSP section
@@ -285,53 +307,71 @@
 
             // Signals
             else if (fields[0] == "clk") {
-                if (fields.size() != 2) {
-                    log_error(" syntax error: '%s'\n", line.c_str());
-                }
                 if (tok.size() == 0 || (tok.back() != "port" && tok.back() != "ff")) {
                     log_error(" unexpected keyword '%s'\n", fields[0].c_str());
                 }
 
                 // Associated clock
                 if (tok.back() == "port") {
+                    if (fields.size() != 3) {
+                        log_error(" syntax error: '%s'\n", line.c_str());
+                    }
                     auto& ports = dspTypes.back().ports;
-                    ports.back().assoc[RTLIL::escape_id("clk")] = std::make_pair(RTLIL::escape_id(fields[1]), RTLIL::S0);
+                    ports.back().assoc[RTLIL::escape_id("clk")] = std::make_pair(
+                        RTLIL::escape_id(fields[1]),
+                        RTLIL::Const::from_string(fields[2])
+                    );
                 }
                 else if (tok.back() == "ff") {
+                    if (fields.size() != 2) {
+                        log_error(" syntax error: '%s'\n", line.c_str());
+                    }
                     flopTypes.back().ports[RTLIL::escape_id("clk")] = RTLIL::escape_id(fields[1]);
                 }
             }
             else if (fields[0] == "rst") {
-                if (fields.size() != 2) {
-                    log_error(" syntax error: '%s'\n", line.c_str());
-                }
                 if (tok.size() == 0 || (tok.back() != "port" && tok.back() != "ff")) {
                     log_error(" unexpected keyword '%s'\n", fields[0].c_str());
                 }
 
                 // Associated reset
                 if (tok.back() == "port") {
+                    if (fields.size() != 3) {
+                        log_error(" syntax error: '%s'\n", line.c_str());
+                    }
                     auto& ports = dspTypes.back().ports;
-                    ports.back().assoc[RTLIL::escape_id("rst")] = std::make_pair(RTLIL::escape_id(fields[1]), RTLIL::S0);
+                    ports.back().assoc[RTLIL::escape_id("rst")] = std::make_pair(
+                        RTLIL::escape_id(fields[1]),
+                        RTLIL::Const::from_string(fields[2])
+                    );
                 }
                 else if (tok.back() == "ff") {
+                    if (fields.size() != 2) {
+                        log_error(" syntax error: '%s'\n", line.c_str());
+                    }
                     flopTypes.back().ports[RTLIL::escape_id("rst")] = RTLIL::escape_id(fields[1]);
                 }
             }
             else if (fields[0] == "ena") {
-                if (fields.size() != 2) {
-                    log_error(" syntax error: '%s'\n", line.c_str());
-                }
                 if (tok.size() == 0 || (tok.back() != "port" && tok.back() != "ff")) {
                     log_error(" unexpected keyword '%s'\n", fields[0].c_str());
                 }
 
                 // Associated enable
                 if (tok.back() == "port") {
+                    if (fields.size() != 3) {
+                        log_error(" syntax error: '%s'\n", line.c_str());
+                    }
                     auto& ports = dspTypes.back().ports;
-                    ports.back().assoc[RTLIL::escape_id("ena")] = std::make_pair(RTLIL::escape_id(fields[1]), RTLIL::S0);
+                    ports.back().assoc[RTLIL::escape_id("ena")] = std::make_pair(
+                        RTLIL::escape_id(fields[1]),
+                        RTLIL::Const::from_string(fields[2])
+                    );
                 }
                 else if (tok.back() == "ff") {
+                    if (fields.size() != 2) {
+                        log_error(" syntax error: '%s'\n", line.c_str());
+                    }
                     flopTypes.back().ports[RTLIL::escape_id("ena")] = RTLIL::escape_id(fields[1]);
                 }
             }
@@ -442,25 +482,6 @@
         }
     } 
 
-    // TODO: make lambda
-    std::vector<std::string> get_fields(const std::string& a_String,
-                                        const char a_Delim = ' ',
-                                        bool a_KeepEmpty = false)
-    {
-        std::vector<std::string> fields;
-        std::stringstream ss(a_String);
-
-        while (ss.good()) {
-            std::string field;
-            std::getline(ss, field, a_Delim);
-            if (!field.empty() || a_KeepEmpty) {
-                fields.push_back(field);
-            }
-        }
-
-        return fields;
-    }
-
     void dump_rules() {
 
         // Dump DSP types
@@ -965,7 +986,7 @@
             const auto& key  = it.first;
             const auto& port = it.second.first;
  
-            auto conn = RTLIL::SigBit(it.second.second);
+            auto conn = RTLIL::SigBit(RTLIL::SigChunk(it.second.second));
             if (flopData.conns.count(key)) {
                 conn = flopData.conns.at(key);
             }