Refactor into AigerReader class
authorEddie Hung <eddieh@ece.ubc.ca>
Fri, 8 Feb 2019 20:04:26 +0000 (12:04 -0800)
committerEddie Hung <eddieh@ece.ubc.ca>
Fri, 8 Feb 2019 20:04:26 +0000 (12:04 -0800)
frontends/aiger/aigerparse.cc
frontends/aiger/aigerparse.h

index 4bc3918becf64eac4b6033c8287fc0d7a1b142ba..365bf1b694e13c76aee42b84ad98c3ea4943aa9f 100644 (file)
@@ -30,24 +30,84 @@ YOSYS_NAMESPACE_BEGIN
 
 #define log_debug log
 
-static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name);
-static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name);
-
-void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name)
+AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name)
+    : design(design), f(f), clk_name(clk_name)
 {
-    auto module = new RTLIL::Module;
+    module = new RTLIL::Module;
     module->name = RTLIL::escape_id("aig"); // TODO: Name?
     if (design->module(module->name))
         log_error("Duplicate definition of module %s!\n", log_id(module->name));
+}
 
+void AigerReader::parse_aiger()
+{
     std::string header;
     f >> header;
+    if (header != "aag" && header != "aig")
+        log_error("Unsupported AIGER file!\n");
+
+    // Parse rest of header
+    if (!(f >> M >> I >> L >> O >> A))
+        log_error("Invalid AIGER header\n");
+
+    // Optional values
+    B = C = J = F = 0;
+    for (auto &i : std::array<std::reference_wrapper<unsigned>,4>{B, C, J, F}) {
+        if (f.peek() != ' ') break;
+        if (!(f >> i))
+            log_error("Invalid AIGER header\n");
+    }
+
+    std::string line;
+    std::getline(f, line); // Ignore up to start of next line, as standard
+                           // says anything that follows could be used for
+                           // optional sections
+
+    log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F);
+
+    line_count = 1;
+
     if (header == "aag")
-        parse_aiger_ascii(module, f, clk_name);
+        parse_aiger_ascii();
     else if (header == "aig")
-        parse_aiger_binary(module, f, clk_name);
+        parse_aiger_binary();
     else
-        log_error("Unsupported AIGER file!\n");
+        log_abort();
+
+    // Parse footer (symbol table, comments, etc.)
+    unsigned l1;
+    std::string s;
+    for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) {
+        if (c == 'i' || c == 'l' || c == 'o') {
+            f.ignore(1);
+            if (!(f >> l1 >> s))
+                log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count);
+
+            if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size()))
+                log_error("Line %u has invalid symbol position!\n", line_count);
+
+            RTLIL::Wire* wire;
+            if (c == 'i') wire = inputs[l1];
+            else if (c == 'l') wire = latches[l1];
+            else if (c == 'o') wire = outputs[l1];
+            else log_abort();
+
+            module->rename(wire, stringf("\\%s", s.c_str()));
+        }
+        else if (c == 'b' || c == 'j' || c == 'f') {
+            // TODO
+        }
+        else if (c == 'c') {
+            f.ignore(1);
+            if (f.peek() == '\n')
+                break;
+            // Else constraint (TODO)
+            break;
+        }
+        else
+            log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c);
+        std::getline(f, line); // Ignore up to start of next line
+    }
 
     module->fixup_ports();
     design->add(module);
@@ -81,38 +141,14 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera
     return wire;
 }
 
-static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F)
+void AigerReader::parse_aiger_ascii()
 {
-    if (!(f >> M >> I >> L >> O >> A))
-        log_error("Invalid AIGER header\n");
-    for (auto &i : std::array<std::reference_wrapper<unsigned>,4>{B, C, J, F}) {
-        if (f.peek() != ' ') break;
-        if (!(f >> i))
-            log_error("Invalid AIGER header\n");
-    }
-
-    std::string line;
-    std::getline(f, line); // Ignore up to start of next line, as standard
-                           // says anything that follows could be used for
-                           // optional sections
-    
-    log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F);
-}
-
-static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name)
-{
-    unsigned M, I, L, O, A;
-    unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9
-    parse_aiger_header(f, M, I, L, O, A, B, C, J, F);
-
-    unsigned line_count = 1;
     std::string line;
     std::stringstream ss;
 
     unsigned l1, l2, l3;
 
     // Parse inputs
-    std::vector<RTLIL::Wire*> inputs;
     for (unsigned i = 0; i < I; ++i, ++line_count) {
         if (!(f >> l1))
             log_error("Line %u cannot be interpreted as an input!\n", line_count);
@@ -124,7 +160,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin
     }
 
     // Parse latches
-    std::vector<RTLIL::Wire*> latches;
     RTLIL::Wire *clk_wire = nullptr;
     if (L > 0) {
         RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str());
@@ -165,7 +200,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin
     }
 
     // Parse outputs
-    std::vector<RTLIL::Wire*> outputs;
     for (unsigned i = 0; i < O; ++i, ++line_count) {
         if (!(f >> l1))
             log_error("Line %u cannot be interpreted as an output!\n", line_count);
@@ -210,39 +244,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin
                and_cell->setPort("\\Y", o_wire);
     }
     std::getline(f, line); // Ignore up to start of next line
-
-    std::string s;
-    for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) {
-        if (c == 'i' || c == 'l' || c == 'o') {
-            f.ignore(1);
-            if (!(f >> l1 >> s))
-                log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count);
-
-            if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size()))
-                log_error("Line %u has invalid symbol position!\n", line_count);
-
-            RTLIL::Wire* wire;
-            if (c == 'i') wire = inputs[l1];
-            else if (c == 'l') wire = latches[l1];
-            else if (c == 'o') wire = outputs[l1];
-            else log_abort();
-
-            module->rename(wire, stringf("\\%s", s.c_str()));
-        }
-        else if (c == 'b' || c == 'j' || c == 'f') {
-            // TODO
-        }
-        else if (c == 'c') {
-            f.ignore(1);
-            if (f.peek() == '\n')
-                break;
-            // Else constraint (TODO)
-            break;
-        }
-        else
-            log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c);
-        std::getline(f, line); // Ignore up to start of next line
-    }
 }
 
 static unsigned parse_next_delta_literal(std::istream &f, unsigned ref)
@@ -254,18 +255,12 @@ static unsigned parse_next_delta_literal(std::istream &f, unsigned ref)
     return ref - (x | (ch << (7 * i)));
 }
 
-static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name)
+void AigerReader::parse_aiger_binary()
 {
-    unsigned M, I, L, O, A;
-    unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9
-    parse_aiger_header(f, M, I, L, O, A, B, C, J, F);
-
-    unsigned line_count = 1;
     unsigned l1, l2, l3;
     std::string line;
 
     // Parse inputs
-    std::vector<RTLIL::Wire*> inputs;
     for (unsigned i = 1; i <= I; ++i) {
         RTLIL::Wire *wire = createWireIfNotExists(module, i << 1);
         wire->port_input = true;
@@ -273,7 +268,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri
     }
 
     // Parse latches
-    std::vector<RTLIL::Wire*> latches;
     RTLIL::Wire *clk_wire = nullptr;
     if (L > 0) {
         RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str());
@@ -314,7 +308,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri
     }
 
     // Parse outputs
-    std::vector<RTLIL::Wire*> outputs;
     for (unsigned i = 0; i < O; ++i, ++line_count) {
         if (!(f >> l1))
             log_error("Line %u cannot be interpreted as an output!\n", line_count);
@@ -385,7 +378,8 @@ struct AigerFrontend : public Frontend {
                }
                extra_args(f, filename, args, argidx);
 
-               parse_aiger(design, *f);
+        AigerReader reader(design, *f);
+               reader.parse_aiger();
        }
 } AigerFrontend;
 
index 6a250aa67feaeb1610f3dc5cbe6ded12fc37799b..3e8ef09fc08c8ba49a76a41b46e83e9fe996d0b1 100644 (file)
 
 YOSYS_NAMESPACE_BEGIN
 
-extern void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name="clk");
+struct AigerReader
+{
+    RTLIL::Design *design;
+    std::istream &f;
+    std::string clk_name;
+    RTLIL::Module *module;
+
+    unsigned M, I, L, O, A;
+    unsigned B, C, J, F; // Optional in AIGER 1.9
+    unsigned line_count;
+
+    std::vector<RTLIL::Wire*> inputs;
+    std::vector<RTLIL::Wire*> latches;
+    std::vector<RTLIL::Wire*> outputs;
+
+    AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name="clk");
+    void parse_aiger();
+    void parse_aiger_ascii();
+    void parse_aiger_binary();
+};
 
 YOSYS_NAMESPACE_END