Add "read_blif -wideports"
authorClifford Wolf <clifford@clifford.at>
Mon, 6 Feb 2017 13:48:03 +0000 (14:48 +0100)
committerClifford Wolf <clifford@clifford.at>
Mon, 6 Feb 2017 13:48:03 +0000 (14:48 +0100)
frontends/blif/blifparse.cc
frontends/blif/blifparse.h

index 6d4d608704fa3e3e5edd0ea5fbd7d483e4437a11..f610a25c3cb2908ca3257730a1eb4ea6405cef83 100644 (file)
@@ -55,7 +55,30 @@ static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count,
        }
 }
 
-void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode)
+static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
+{
+       int pos = -1;
+
+       if (name.empty() || name.back() != ']')
+               goto failed;
+
+       for (int i = 0; i+1 < GetSize(name); i++) {
+               if (name[i] == '[')
+                       pos = i;
+               else if (name[i] < '0' || name[i] > '9')
+                       pos = -1;
+               else if (i == pos+1 && name[i] == '0')
+                       pos = -1;
+       }
+
+       if (pos >= 0)
+               return std::pair<RTLIL::IdString, int>("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1)+1);
+
+failed:
+       return std::pair<RTLIL::IdString, int>("\\" + name, 0);
+}
+
+void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode, bool wideports)
 {
        RTLIL::Module *module = nullptr;
        RTLIL::Const *lutptr = NULL;
@@ -96,6 +119,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
        dict<RTLIL::IdString, RTLIL::Const> *obj_attributes = nullptr;
        dict<RTLIL::IdString, RTLIL::Const> *obj_parameters = nullptr;
 
+       dict<RTLIL::IdString, std::pair<int, bool>> wideports_cache;
+
        size_t buffer_size = 4096;
        char *buffer = (char*)malloc(buffer_size);
        int line_count = 0;
@@ -148,7 +173,32 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
 
                        if (!strcmp(cmd, ".end"))
                        {
+                               for (auto &wp : wideports_cache)
+                               {
+                                       auto name = wp.first;
+                                       int width = wp.second.first;
+                                       bool isinput = wp.second.second;
+
+                                       RTLIL::Wire *wire = module->addWire(name, width);
+                                       wire->port_input = isinput;
+                                       wire->port_output = !isinput;
+
+                                       for (int i = 0; i < width; i++) {
+                                               RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
+                                               RTLIL::Wire *other_wire = module->wire(other_name);
+                                               if (other_wire) {
+                                                       other_wire->port_input = false;
+                                                       other_wire->port_output = false;
+                                                       if (isinput)
+                                                               module->connect(other_wire, SigSpec(wire, i));
+                                                       else
+                                                               module->connect(SigSpec(wire, i), other_wire);
+                                               }
+                                       }
+                               }
+
                                module->fixup_ports();
+                               wideports_cache.clear();
 
                                if (run_clean)
                                {
@@ -187,9 +237,11 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
                                continue;
                        }
 
-                       if (!strcmp(cmd, ".inputs") || !strcmp(cmd, ".outputs")) {
+                       if (!strcmp(cmd, ".inputs") || !strcmp(cmd, ".outputs"))
+                       {
                                char *p;
-                               while ((p = strtok(NULL, " \t\r\n")) != NULL) {
+                               while ((p = strtok(NULL, " \t\r\n")) != NULL)
+                               {
                                        RTLIL::IdString wire_name(stringf("\\%s", p));
                                        RTLIL::Wire *wire = module->wire(wire_name);
                                        if (wire == nullptr)
@@ -198,6 +250,14 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
                                                wire->port_input = true;
                                        else
                                                wire->port_output = true;
+
+                                       if (wideports) {
+                                               std::pair<RTLIL::IdString, int> wp = wideports_split(p);
+                                               if (wp.second > 0) {
+                                                       wideports_cache[wp.first].first = std::max(wideports_cache[wp.first].first, wp.second);
+                                                       wideports_cache[wp.first].second = !strcmp(cmd, ".inputs");
+                                               }
+                                       }
                                }
                                obj_attributes = nullptr;
                                obj_parameters = nullptr;
@@ -452,6 +512,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
                }
        }
 
+       return;
+
 error:
        log_error("Syntax error in line %d!\n", line_count);
 }
@@ -469,10 +531,15 @@ struct BlifFrontend : public Frontend {
                log("    -sop\n");
                log("        Create $sop cells instead of $lut cells\n");
                log("\n");
+               log("    -wideports\n");
+               log("        Merge ports that match the pattern 'name[int]' into a single\n");
+               log("        multi-bit port 'name'.\n");
+               log("\n");
        }
        virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
        {
                bool sop_mode = false;
+               bool wideports = false;
 
                log_header(design, "Executing BLIF frontend.\n");
 
@@ -483,11 +550,15 @@ struct BlifFrontend : public Frontend {
                                sop_mode = true;
                                continue;
                        }
+                       if (arg == "-wideports") {
+                               wideports = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(f, filename, args, argidx);
 
-               parse_blif(design, *f, "", true, sop_mode);
+               parse_blif(design, *f, "", true, sop_mode, wideports);
        }
 } BlifFrontend;
 
index 058087d814c52ba1889b68d453b55648edc15ba2..955b6aacfedf221e725f344488dc1d7db31a00b4 100644 (file)
@@ -24,7 +24,8 @@
 
 YOSYS_NAMESPACE_BEGIN
 
-extern void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean = false, bool sop_mode = false);
+extern void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name,
+               bool run_clean = false, bool sop_mode = false, bool wideports = false);
 
 YOSYS_NAMESPACE_END