diff --git a/common/command.cc b/common/command.cc index 3eafdb17..242e5037 100644 --- a/common/command.cc +++ b/common/command.cc @@ -35,6 +35,7 @@ #include "command.h" #include "design_utils.h" #include "jsonparse.h" +#include "jsonwrite.h" #include "log.h" #include "timing.h" #include "util.h" @@ -120,6 +121,7 @@ po::options_description CommandHandler::getGeneralOptions() #endif general.add_options()("json", po::value(), "JSON design file to ingest"); + general.add_options()("write", po::value(), "JSON design file to write"); general.add_options()("seed", po::value(), "seed value for random number generator"); general.add_options()("randomize-seed,r", "randomize seed value for random number generator"); @@ -303,6 +305,12 @@ int CommandHandler::executeMain(std::unique_ptr ctx) customBitstream(ctx.get()); } + if (vm.count("write")) { + std::string filename = vm["write"].as(); + std::ofstream f(filename); + if (!write_json_file(f, filename, ctx.get())) + log_error("Loading design failed.\n"); + } if (vm.count("save")) { project.save(ctx.get(), vm["save"].as()); } diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc new file mode 100644 index 00000000..b35a61cf --- /dev/null +++ b/json/jsonwrite.cc @@ -0,0 +1,167 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "jsonwrite.h" +#include +#include +#include +#include +#include +#include +#include +#include "nextpnr.h" +#include "version.h" + +NEXTPNR_NAMESPACE_BEGIN + +namespace JsonWriter { + +std::string get_string(std::string str) +{ + std::string newstr = "\""; + for (char c : str) { + if (c == '\\') + newstr += c; + newstr += c; + } + return newstr + "\""; +} + +std::string get_name(IdString name, Context *ctx) +{ + return get_string(name.c_str(ctx)); +} + +void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, bool for_module=false) +{ + bool first = true; + for (auto ¶m : parameters) { + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first,ctx).c_str()); + f << get_string(param.second); + first = false; + } +} +void write_module(std::ostream &f, Context *ctx) +{ + f << stringf(" %s: {\n", get_string("top").c_str()); + // TODO: check if this is better to be separate + /*f << stringf(" \"settings\": {"); + write_parameters(f, ctx, ctx->settings, true); + f << stringf("\n },\n");*/ + f << stringf(" \"attributes\": {"); + // TODO: Top level attributes + f << stringf("\n },\n"); + f << stringf(" \"ports\": {"); + // TODO: Top level ports + f << stringf("\n },\n"); + + auto fn = ctx->nets.hash_function(); + + f << stringf(" \"cells\": {"); + bool first = true; + for (auto &pair : ctx->cells) { + auto &c = pair.second; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(c->name, ctx).c_str()); + f << stringf(" \"hide_name\": %s,\n", c->name.c_str(ctx)[0] == '$' ? "1" : "0"); + f << stringf(" \"type\": %s,\n", get_name(c->type, ctx).c_str()); + f << stringf(" \"parameters\": {"); + write_parameters(f, ctx, c->params); + f << stringf("\n },\n"); + f << stringf(" \"attributes\": {"); + write_parameters(f, ctx, c->attrs); + f << stringf("\n },\n"); + f << stringf(" \"port_directions\": {"); + bool first2 = true; + for (auto &conn : c->ports) { + auto &p = conn.second; + if (p.net) { + std::string direction = (p.type == PORT_IN) ? "input" : (p.type == PORT_OUT) ? "output" : "inout"; + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: \"%s\"", get_name(conn.first, ctx).c_str(), direction.c_str()); + first2 = false; + } + } + f << stringf("\n },\n"); + f << stringf(" \"connections\": {"); + first2 = true; + + for (auto &conn : c->ports) { + auto &p = conn.second; + if (p.net) { + f << stringf("%s\n", first2 ? "" : ","); + f << stringf(" %s: %d", get_name(conn.first,ctx).c_str(), fn(p.net->name)); + first2 = false; + } + } + f << stringf("\n }\n"); + + f << stringf(" }"); + first = false; + } + + f << stringf("\n },\n"); + + f << stringf(" \"netnames\": {"); + first = true; + for (auto &pair : ctx->nets) { + auto &w = pair.second; + f << stringf("%s\n", first ? "" : ","); + f << stringf(" %s: {\n", get_name(w->name, ctx).c_str()); + f << stringf(" \"hide_name\": %s,\n", w->name.c_str(ctx)[0] == '$' ? "1" : "0"); + f << stringf(" \"bits\": [ %d ] ,\n", fn(pair.first)); + f << stringf(" \"attributes\": {"); + write_parameters(f, ctx, w->attrs); + f << stringf("\n }\n"); + f << stringf(" }"); + first = false; + } + + f << stringf("\n }\n"); + f << stringf(" }"); +} + +void write_context(std::ostream &f, Context *ctx) +{ + f << stringf("{\n"); + f << stringf(" \"creator\": %s,\n", get_string( "Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")").c_str()); + f << stringf(" \"modules\": {\n"); + write_module(f, ctx); + f << stringf("\n }"); + f << stringf("\n}\n"); +} + +}; // End Namespace JsonWriter + +bool write_json_file(std::ostream &f, std::string &filename, Context *ctx) +{ + try { + using namespace JsonWriter; + if (!f) + log_error("failed to open JSON file.\n"); + write_context(f, ctx); + log_break(); + return true; + } catch (log_execution_error_exception) { + return false; + } +} + +NEXTPNR_NAMESPACE_END diff --git a/json/jsonwrite.h b/json/jsonwrite.h new file mode 100644 index 00000000..9240bc96 --- /dev/null +++ b/json/jsonwrite.h @@ -0,0 +1,33 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef JSON_WRITER +#define JSON_WRITER + +#include +#include +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +extern bool write_json_file(std::ostream &, std::string &, Context *); + +NEXTPNR_NAMESPACE_END + +#endif