Fix handling of some formal cells in btor back-end
[yosys.git] / backends / json / json.cc
index 107009ee4e80bc9d904cf75ade9f22776741fee9..42eedc606273c15ea477b7c6269b6dff00af0515 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  yosys -- Yosys Open SYnthesis Suite
  *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
  *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
@@ -33,6 +33,7 @@ struct JsonWriter
        std::ostream &f;
        bool use_selection;
        bool aig_mode;
+       bool compat_int_mode;
 
        Design *design;
        Module *module;
@@ -42,16 +43,32 @@ struct JsonWriter
        dict<SigBit, string> sigids;
        pool<Aig> aig_models;
 
-       JsonWriter(std::ostream &f, bool use_selection, bool aig_mode) :
-                       f(f), use_selection(use_selection), aig_mode(aig_mode) { }
+       JsonWriter(std::ostream &f, bool use_selection, bool aig_mode, bool compat_int_mode) :
+                       f(f), use_selection(use_selection), aig_mode(aig_mode),
+                       compat_int_mode(compat_int_mode) { }
 
        string get_string(string str)
        {
                string newstr = "\"";
                for (char c : str) {
                        if (c == '\\')
+                               newstr += "\\\\";
+                       else if (c == '"')
+                               newstr += "\\\"";
+                       else if (c == '\b')
+                               newstr += "\\b";
+                       else if (c == '\f')
+                               newstr += "\\f";
+                       else if (c == '\n')
+                               newstr += "\\n";
+                       else if (c == '\r')
+                               newstr += "\\r";
+                       else if (c == '\t')
+                               newstr += "\\t";
+                       else if (c < 0x20)
+                               newstr += stringf("\\u%04X", c);
+                       else
                                newstr += c;
-                       newstr += c;
                }
                return newstr + "\"";
        }
@@ -102,8 +119,7 @@ struct JsonWriter
                        if (state < 2)
                                str += " ";
                        f << get_string(str);
-               } else
-               if (GetSize(value) == 32 && value.is_fully_def()) {
+               } else if (compat_int_mode && GetSize(value) <= 32 && value.is_fully_def()) {
                        if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
                                f << stringf("%d", value.as_int());
                        else
@@ -134,12 +150,22 @@ struct JsonWriter
                // reserve 0 and 1 to avoid confusion with "0" and "1"
                sigidcounter = 2;
 
+               if (module->has_processes()) {
+                       log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", log_id(module));
+               }
+
                f << stringf("    %s: {\n", get_name(module->name).c_str());
 
                f << stringf("      \"attributes\": {");
                write_parameters(module->attributes, /*for_module=*/true);
                f << stringf("\n      },\n");
 
+               if (module->parameter_default_values.size()) {
+                       f << stringf("      \"parameter_default_values\": {");
+                       write_parameters(module->parameter_default_values, /*for_module=*/true);
+                       f << stringf("\n      },\n");
+               }
+
                f << stringf("      \"ports\": {");
                bool first = true;
                for (auto n : module->ports) {
@@ -153,6 +179,8 @@ struct JsonWriter
                                f << stringf("          \"offset\": %d,\n", w->start_offset);
                        if (w->upto)
                                f << stringf("          \"upto\": 1,\n");
+                       if (w->is_signed)
+                               f << stringf("          \"signed\": %d,\n", w->is_signed);
                        f << stringf("          \"bits\": %s\n", get_bits(w).c_str());
                        f << stringf("        }");
                        first = false;
@@ -207,6 +235,27 @@ struct JsonWriter
                }
                f << stringf("\n      },\n");
 
+               if (!module->memories.empty()) {
+                       f << stringf("      \"memories\": {");
+                       first = true;
+                       for (auto &it : module->memories) {
+                               if (use_selection && !module->selected(it.second))
+                                       continue;
+                               f << stringf("%s\n", first ? "" : ",");
+                               f << stringf("        %s: {\n", get_name(it.second->name).c_str());
+                               f << stringf("          \"hide_name\": %s,\n", it.second->name[0] == '$' ? "1" : "0");
+                               f << stringf("          \"attributes\": {");
+                               write_parameters(it.second->attributes);
+                               f << stringf("\n          },\n");
+                               f << stringf("          \"width\": %d,\n", it.second->width);
+                               f << stringf("          \"start_offset\": %d,\n", it.second->start_offset);
+                               f << stringf("          \"size\": %d\n", it.second->size);
+                               f << stringf("        }");
+                               first = false;
+                       }
+                       f << stringf("\n      },\n");
+               }
+
                f << stringf("      \"netnames\": {");
                first = true;
                for (auto w : module->wires()) {
@@ -220,6 +269,8 @@ struct JsonWriter
                                f << stringf("          \"offset\": %d,\n", w->start_offset);
                        if (w->upto)
                                f << stringf("          \"upto\": 1,\n");
+                       if (w->is_signed)
+                               f << stringf("          \"signed\": %d,\n", w->is_signed);
                        f << stringf("          \"attributes\": {");
                        write_parameters(w->attributes);
                        f << stringf("\n          }\n");
@@ -283,7 +334,7 @@ struct JsonWriter
 
 struct JsonBackend : public Backend {
        JsonBackend() : Backend("json", "write design to a JSON file") { }
-       void help() YS_OVERRIDE
+       void help() override
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
@@ -294,12 +345,25 @@ struct JsonBackend : public Backend {
                log("    -aig\n");
                log("        include AIG models for the different gate types\n");
                log("\n");
+               log("    -compat-int\n");
+               log("        emit 32-bit or smaller fully-defined parameter values directly\n");
+               log("        as JSON numbers (for compatibility with old parsers)\n");
+               log("\n");
                log("\n");
                log("The general syntax of the JSON output created by this command is as follows:\n");
                log("\n");
                log("    {\n");
+               log("      \"creator\": \"Yosys <version info>\",\n");
                log("      \"modules\": {\n");
                log("        <module_name>: {\n");
+               log("          \"attributes\": {\n");
+               log("            <attribute_name>: <attribute_value>,\n");
+               log("            ...\n");
+               log("          },\n");
+               log("          \"parameter_default_values\": {\n");
+               log("            <parameter_name>: <parameter_value>,\n");
+               log("            ...\n");
+               log("          },\n");
                log("          \"ports\": {\n");
                log("            <port_name>: <port_details>,\n");
                log("            ...\n");
@@ -308,6 +372,10 @@ struct JsonBackend : public Backend {
                log("            <cell_name>: <cell_details>,\n");
                log("            ...\n");
                log("          },\n");
+               log("          \"memories\": {\n");
+               log("            <memory_name>: <memory_details>,\n");
+               log("            ...\n");
+               log("          },\n");
                log("          \"netnames\": {\n");
                log("            <net_name>: <net_details>,\n");
                log("            ...\n");
@@ -324,13 +392,19 @@ struct JsonBackend : public Backend {
                log("    {\n");
                log("      \"direction\": <\"input\" | \"output\" | \"inout\">,\n");
                log("      \"bits\": <bit_vector>\n");
+               log("      \"offset\": <the lowest bit index in use, if non-0>\n");
+               log("      \"upto\": <1 if the port bit indexing is MSB-first>\n");
                log("    }\n");
                log("\n");
+               log("The \"offset\" and \"upto\" fields are skipped if their value would be 0.");
+               log("They don't affect connection semantics, and are only used to preserve original");
+               log("HDL bit indexing.");
                log("And <cell_details> is:\n");
                log("\n");
                log("    {\n");
                log("      \"hide_name\": <1 | 0>,\n");
                log("      \"type\": <cell_type>,\n");
+               log("      \"model\": <AIG model name, if -aig option used>,\n");
                log("      \"parameters\": {\n");
                log("        <parameter_name>: <parameter_value>,\n");
                log("        ...\n");
@@ -349,11 +423,26 @@ struct JsonBackend : public Backend {
                log("      },\n");
                log("    }\n");
                log("\n");
+               log("And <memory_details> is:\n");
+               log("\n");
+               log("    {\n");
+               log("      \"hide_name\": <1 | 0>,\n");
+               log("      \"attributes\": {\n");
+               log("        <attribute_name>: <attribute_value>,\n");
+               log("        ...\n");
+               log("      },\n");
+               log("      \"width\": <memory width>\n");
+               log("      \"start_offset\": <the lowest valid memory address>\n");
+               log("      \"size\": <memory size>\n");
+               log("    }\n");
+               log("\n");
                log("And <net_details> is:\n");
                log("\n");
                log("    {\n");
                log("      \"hide_name\": <1 | 0>,\n");
                log("      \"bits\": <bit_vector>\n");
+               log("      \"offset\": <the lowest bit index in use, if non-0>\n");
+               log("      \"upto\": <1 if the port bit indexing is MSB-first>\n");
                log("    }\n");
                log("\n");
                log("The \"hide_name\" fields are set to 1 when the name of this cell or net is\n");
@@ -368,10 +457,9 @@ struct JsonBackend : public Backend {
                log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n");
                log("\"z\" instead of a number.\n");
                log("\n");
-               log("Numeric 32-bit parameter and attribute values are written as decimal values.\n");
-               log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n");
-               log("as string holding the binary representation of the value. Strings are written\n");
-               log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n");
+               log("Bit vectors (including integers) are written as string holding the binary");
+               log("representation of the value. Strings are written as strings, with an appended");
+               log("blank in cases of strings of the form /[01xz]* */.\n");
                log("\n");
                log("For example the following Verilog code:\n");
                log("\n");
@@ -382,9 +470,15 @@ struct JsonBackend : public Backend {
                log("\n");
                log("Translates to the following JSON output:\n");
                log("\n");
+
                log("    {\n");
+               log("      \"creator\": \"Yosys 0.9+2406 (git sha1 fb1168d8, clang 9.0.1 -fPIC -Os)\",\n");
                log("      \"modules\": {\n");
                log("        \"test\": {\n");
+               log("          \"attributes\": {\n");
+               log("            \"cells_not_processed\": \"00000000000000000000000000000001\",\n");
+               log("            \"src\": \"test.v:1.1-4.10\"\n");
+               log("          },\n");
                log("          \"ports\": {\n");
                log("            \"x\": {\n");
                log("              \"direction\": \"input\",\n");
@@ -400,33 +494,34 @@ struct JsonBackend : public Backend {
                log("              \"hide_name\": 0,\n");
                log("              \"type\": \"foo\",\n");
                log("              \"parameters\": {\n");
-               log("                \"Q\": 1337,\n");
-               log("                \"P\": 42\n");
+               log("                \"P\": \"00000000000000000000000000101010\",\n");
+               log("                \"Q\": \"00000000000000000000010100111001\"\n");
                log("              },\n");
                log("              \"attributes\": {\n");
-               log("                \"keep\": 1,\n");
-               log("                \"src\": \"test.v:2\"\n");
+               log("                \"keep\": \"00000000000000000000000000000001\",\n");
+               log("                \"module_not_derived\": \"00000000000000000000000000000001\",\n");
+               log("                \"src\": \"test.v:3.1-3.55\"\n");
                log("              },\n");
                log("              \"connections\": {\n");
-               log("                \"C\": [ 2, 2, 2, 2, \"0\", \"1\", \"0\", \"1\" ],\n");
+               log("                \"A\": [ 3, 2 ],\n");
                log("                \"B\": [ 2, 3 ],\n");
-               log("                \"A\": [ 3, 2 ]\n");
+               log("                \"C\": [ 2, 2, 2, 2, \"0\", \"1\", \"0\", \"1\" ]\n");
                log("              }\n");
                log("            }\n");
                log("          },\n");
                log("          \"netnames\": {\n");
-               log("            \"y\": {\n");
+               log("            \"x\": {\n");
                log("              \"hide_name\": 0,\n");
-               log("              \"bits\": [ 3 ],\n");
+               log("              \"bits\": [ 2 ],\n");
                log("              \"attributes\": {\n");
-               log("                \"src\": \"test.v:1\"\n");
+               log("                \"src\": \"test.v:1.19-1.20\"\n");
                log("              }\n");
                log("            },\n");
-               log("            \"x\": {\n");
+               log("            \"y\": {\n");
                log("              \"hide_name\": 0,\n");
-               log("              \"bits\": [ 2 ],\n");
+               log("              \"bits\": [ 3 ],\n");
                log("              \"attributes\": {\n");
-               log("                \"src\": \"test.v:1\"\n");
+               log("                \"src\": \"test.v:1.22-1.23\"\n");
                log("              }\n");
                log("            }\n");
                log("          }\n");
@@ -492,9 +587,10 @@ struct JsonBackend : public Backend {
                log("format. A program processing this format must ignore all unknown fields.\n");
                log("\n");
        }
-       void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
        {
                bool aig_mode = false;
+               bool compat_int_mode = false;
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++)
@@ -503,20 +599,24 @@ struct JsonBackend : public Backend {
                                aig_mode = true;
                                continue;
                        }
+                       if (args[argidx] == "-compat-int") {
+                               compat_int_mode = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(f, filename, args, argidx);
 
                log_header(design, "Executing JSON backend.\n");
 
-               JsonWriter json_writer(*f, false, aig_mode);
+               JsonWriter json_writer(*f, false, aig_mode, compat_int_mode);
                json_writer.write_design(design);
        }
 } JsonBackend;
 
 struct JsonPass : public Pass {
        JsonPass() : Pass("json", "write design in JSON format") { }
-       void help() YS_OVERRIDE
+       void help() override
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
@@ -530,13 +630,18 @@ struct JsonPass : public Pass {
                log("    -aig\n");
                log("        also include AIG models for the different gate types\n");
                log("\n");
+               log("    -compat-int\n");
+               log("        emit 32-bit or smaller fully-defined parameter values directly\n");
+               log("        as JSON numbers (for compatibility with old parsers)\n");
+               log("\n");
                log("See 'help write_json' for a description of the JSON format used.\n");
                log("\n");
        }
-       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       void execute(std::vector<std::string> args, RTLIL::Design *design) override
        {
                std::string filename;
                bool aig_mode = false;
+               bool compat_int_mode = false;
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++)
@@ -549,6 +654,10 @@ struct JsonPass : public Pass {
                                aig_mode = true;
                                continue;
                        }
+                       if (args[argidx] == "-compat-int") {
+                               compat_int_mode = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -569,7 +678,7 @@ struct JsonPass : public Pass {
                        f = &buf;
                }
 
-               JsonWriter json_writer(*f, true, aig_mode);
+               JsonWriter json_writer(*f, true, aig_mode, compat_int_mode);
                json_writer.write_design(design);
 
                if (!filename.empty()) {