aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/json_frontend.cc
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-12-27 11:19:45 +0000
committerGitHub <noreply@github.com>2019-12-27 11:19:45 +0000
commit4e0ca50db137eb9d10098582be607c98601f8375 (patch)
tree7dd586694d7c3bca458502f3e6d677da1a6954b3 /frontend/json_frontend.cc
parentb6e2159cecdf79d0d94d0e6a9dda8cef6389cac1 (diff)
parent5774b13984bb151909b90ee2c668bdfb08387a2b (diff)
downloadnextpnr-4e0ca50db137eb9d10098582be607c98601f8375.tar.gz
nextpnr-4e0ca50db137eb9d10098582be607c98601f8375.tar.bz2
nextpnr-4e0ca50db137eb9d10098582be607c98601f8375.zip
Merge pull request #353 from YosysHQ/generic-frontend
New hierarchy-capable generic frontend framework and json11 based JSON frontend
Diffstat (limited to 'frontend/json_frontend.cc')
-rw-r--r--frontend/json_frontend.cc203
1 files changed, 203 insertions, 0 deletions
diff --git a/frontend/json_frontend.cc b/frontend/json_frontend.cc
new file mode 100644
index 00000000..d2e6248e
--- /dev/null
+++ b/frontend/json_frontend.cc
@@ -0,0 +1,203 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2019 David Shah <dave@ds0.me>
+ *
+ * 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 "json_frontend.h"
+#include "frontend_base.h"
+#include "json11.hpp"
+#include "log.h"
+#include "nextpnr.h"
+
+#include <streambuf>
+
+NEXTPNR_NAMESPACE_BEGIN
+
+using namespace json11;
+
+struct JsonFrontendImpl
+{
+ // See specification in frontend_base.h
+ JsonFrontendImpl(Json &root) : root(root){};
+ Json &root;
+ typedef const Json &ModuleDataType;
+ typedef const Json &ModulePortDataType;
+ typedef const Json &CellDataType;
+ typedef const Json &NetnameDataType;
+ typedef const Json::array &BitVectorDataType;
+
+ template <typename TFunc> void foreach_module(TFunc Func) const
+ {
+ for (const auto &mod : root.object_items())
+ Func(mod.first, mod.second);
+ }
+
+ template <typename TFunc> void foreach_port(const ModuleDataType &mod, TFunc Func) const
+ {
+ const auto &ports = mod["ports"];
+ if (ports.is_null())
+ return;
+ for (const auto &port : ports.object_items())
+ Func(port.first, port.second);
+ }
+
+ template <typename TFunc> void foreach_cell(const ModuleDataType &mod, TFunc Func) const
+ {
+ const auto &cells = mod["cells"];
+ if (cells.is_null())
+ return;
+ for (const auto &cell : cells.object_items())
+ Func(cell.first, cell.second);
+ }
+
+ template <typename TFunc> void foreach_netname(const ModuleDataType &mod, TFunc Func) const
+ {
+ const auto &netnames = mod["netnames"];
+ if (netnames.is_null())
+ return;
+ for (const auto &netname : netnames.object_items())
+ Func(netname.first, netname.second);
+ }
+
+ PortType lookup_portdir(const std::string &dir) const
+ {
+ if (dir == "input")
+ return PORT_IN;
+ else if (dir == "inout")
+ return PORT_INOUT;
+ else if (dir == "output")
+ return PORT_OUT;
+ else
+ NPNR_ASSERT_FALSE("invalid json port direction");
+ }
+
+ PortType get_port_dir(const ModulePortDataType &port) const
+ {
+ return lookup_portdir(port["direction"].string_value());
+ }
+
+ int get_array_offset(const Json &obj) const
+ {
+ auto offset = obj["offset"];
+ return offset.is_null() ? 0 : offset.int_value();
+ }
+
+ bool is_array_upto(const Json &obj) const
+ {
+ auto upto = obj["upto"];
+ return upto.is_null() ? false : bool(upto.int_value());
+ }
+
+ const BitVectorDataType &get_port_bits(const ModulePortDataType &port) const { return port["bits"].array_items(); }
+
+ const std::string &get_cell_type(const CellDataType &cell) const { return cell["type"].string_value(); }
+
+ Property parse_property(const Json &val) const
+ {
+ if (val.is_number())
+ return Property(val.int_value(), 32);
+ else
+ return Property::from_string(val.string_value());
+ }
+
+ template <typename TFunc> void foreach_attr(const Json &obj, TFunc Func) const
+ {
+ const auto &attrs = obj["attributes"];
+ if (attrs.is_null())
+ return;
+ for (const auto &attr : attrs.object_items()) {
+ Func(attr.first, parse_property(attr.second));
+ }
+ }
+
+ template <typename TFunc> void foreach_param(const Json &obj, TFunc Func) const
+ {
+ const auto &params = obj["parameters"];
+ if (params.is_null())
+ return;
+ for (const auto &param : params.object_items()) {
+ Func(param.first, parse_property(param.second));
+ }
+ }
+
+ template <typename TFunc> void foreach_setting(const Json &obj, TFunc Func) const
+ {
+ const auto &settings = obj["settings"];
+ if (settings.is_null())
+ return;
+ for (const auto &setting : settings.object_items()) {
+ Func(setting.first, parse_property(setting.second));
+ }
+ }
+
+ template <typename TFunc> void foreach_port_dir(const CellDataType &cell, TFunc Func) const
+ {
+ for (const auto &pdir : cell["port_directions"].object_items())
+ Func(pdir.first, lookup_portdir(pdir.second.string_value()));
+ }
+
+ template <typename TFunc> void foreach_port_conn(const CellDataType &cell, TFunc Func) const
+ {
+ for (const auto &pconn : cell["connections"].object_items())
+ Func(pconn.first, pconn.second.array_items());
+ }
+
+ const BitVectorDataType &get_net_bits(const NetnameDataType &net) const { return net["bits"].array_items(); }
+
+ int get_vector_length(const BitVectorDataType &bits) const { return int(bits.size()); }
+
+ bool is_vector_bit_constant(const BitVectorDataType &bits, int i) const
+ {
+ NPNR_ASSERT(i < int(bits.size()));
+ return bits[i].is_string();
+ }
+
+ char get_vector_bit_constval(const BitVectorDataType &bits, int i) const
+ {
+ auto s = bits.at(i).string_value();
+ NPNR_ASSERT(s.size() == 1);
+ return s.at(0);
+ }
+
+ int get_vector_bit_signal(const BitVectorDataType &bits, int i) const
+ {
+ NPNR_ASSERT(bits.at(i).is_number());
+ return bits.at(i).int_value();
+ }
+};
+
+bool parse_json(std::istream &in, const std::string &filename, Context *ctx)
+{
+ Json root;
+ {
+ if (!in)
+ log_error("Failed to open JSON file '%s'.\n", filename.c_str());
+ std::string json_str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
+ std::string error;
+ root = Json::parse(json_str, error, JsonParse::COMMENTS);
+ if (root.is_null())
+ log_error("Failed to parse JSON file '%s': %s.\n", filename.c_str(), error.c_str());
+ root = root["modules"];
+ if (root.is_null())
+ log_error("JSON file '%s' doesn't look like a netlist (doesn't contain \"modules\" key)\n",
+ filename.c_str());
+ }
+ GenericFrontend<JsonFrontendImpl>(ctx, JsonFrontendImpl(root))();
+ return true;
+}
+
+NEXTPNR_NAMESPACE_END