diff options
Diffstat (limited to 'frontend')
-rw-r--r-- | frontend/frontend_base.h | 38 | ||||
-rw-r--r-- | frontend/json_frontend.cc | 189 | ||||
-rw-r--r-- | frontend/json_frontend.h | 26 |
3 files changed, 235 insertions, 18 deletions
diff --git a/frontend/frontend_base.h b/frontend/frontend_base.h index 35d4409c..426d9431 100644 --- a/frontend/frontend_base.h +++ b/frontend/frontend_base.h @@ -56,11 +56,11 @@ * PortType get_port_dir(const ModulePortDataType &port); * gets the PortType direction of a module port * - * int get_port_offset(const ModulePortDataType &port); - * gets the start bit number of a port + * int get_array_offset(const ModulePortDataType &port); + * gets the start bit number of a port or netname entry * - * bool is_port_upto(const ModulePortDataType &port); - * returns true if a port is an "upto" type port + * bool is_array_upto(const ModulePortDataType &port); + * returns true if a port/net is an "upto" type port or netname entry * * const BitVectorDataType &get_port_bits(const ModulePortDataType &port); * gets the bit vector of a module port @@ -108,6 +108,14 @@ NEXTPNR_NAMESPACE_BEGIN namespace { +// Used for hierarchy resolution +struct ModuleInfo +{ + bool is_top = false, is_blackbox = false, is_whitebox = false; + inline bool is_box() const { return is_blackbox || is_whitebox; } + std::unordered_set<IdString> instantiated_celltypes; +}; + template <typename FrontendType> struct GenericFrontend { GenericFrontend(Context *ctx, const FrontendType &impl) : ctx(ctx), impl(impl) {} @@ -119,14 +127,6 @@ template <typename FrontendType> struct GenericFrontend using netname_dat_t = typename FrontendType::NetnameDataType; using bitvector_t = typename FrontendType::BitVectorDataType; - // Used for hierarchy resolution - struct ModuleInfo - { - const mod_dat_t *mod_data; - bool is_top = false, is_blackbox = false, is_whitebox = false; - inline bool is_box() const { return is_blackbox || is_whitebox; } - std::unordered_set<IdString> instantiated_celltypes; - }; std::unordered_map<IdString, ModuleInfo> mods; IdString top; @@ -137,7 +137,6 @@ template <typename FrontendType> struct GenericFrontend impl.foreach_module([&](const std::string &name, const mod_dat_t &mod) { IdString mod_id = ctx->id(name); auto &mi = mods[mod_id]; - mi.mod_data = &mod; impl.foreach_attr(mod, [&](const std::string &name, const Property &value) { if (name == "top") mi.is_top = (value.intval != 0); @@ -147,7 +146,7 @@ template <typename FrontendType> struct GenericFrontend mi.is_whitebox = (value.intval != 0); }); impl.foreach_cell(mod, [&](const std::string &name, const cell_dat_t &cell) { - mi.instantiated_cells.insert(ctx->id(impl.get_cell_type(cell))); + mi.instantiated_celltypes.insert(ctx->id(impl.get_cell_type(cell))); }); }); // First of all, see if a top module has been manually specified @@ -230,7 +229,7 @@ template <typename FrontendType> struct GenericFrontend std::unordered_map<IdString, std::vector<int>> port_to_bus; }; - void import_module(HierModuleState &m, mod_dat_t *data) + void import_module(HierModuleState &m, const mod_dat_t &data) { std::vector<NetInfo *> index_to_net; // Import port connections; for submodules only @@ -289,10 +288,10 @@ template <typename FrontendType> struct GenericFrontend ctx->net_aliases[mergee->name] = base->name; // Update flat index of nets for (auto old_idx : net_old_indices.at(mergee->udata)) { - net_old_indices.at(base).push_back(old_idx); + net_old_indices.at(base->udata).push_back(old_idx); net_flatindex.at(old_idx) = base; } - net_old_indices.at(base).push_back(mergee->udata); + net_old_indices.at(base->udata).push_back(mergee->udata); net_flatindex.at(mergee->udata) = base; net_old_indices.at(mergee->udata).clear(); // Remove merged net from context @@ -349,6 +348,9 @@ template <typename FrontendType> struct GenericFrontend }; } // namespace -template <typename FrontendType> void run_frontend(Context *ctx, const FrontendType &impl) {} +template <typename FrontendType> void run_frontend(Context *ctx, const FrontendType &impl) +{ + GenericFrontend<FrontendType>(ctx, impl); +} NEXTPNR_NAMESPACE_END
\ No newline at end of file diff --git a/frontend/json_frontend.cc b/frontend/json_frontend.cc new file mode 100644 index 00000000..91c9f06a --- /dev/null +++ b/frontend/json_frontend.cc @@ -0,0 +1,189 @@ +/* + * 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) + { + for (const auto &mod : root.object_items()) + Func(mod.first, mod.second); + } + + template <typename TFunc> void foreach_port(const ModuleDataType &mod, TFunc Func) + { + 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 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 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) + { + 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) { return lookup_portdir(port["direction"].string_value()); } + + int get_array_offset(const Json &obj) + { + auto offset = obj["offset"]; + return offset.is_null() ? 0 : offset.int_value(); + } + + bool is_array_upto(const Json &obj) + { + auto upto = obj["upto"]; + return upto.is_null() ? false : bool(upto.int_value()); + } + + const BitVectorDataType &get_port_bits(const ModulePortDataType &port) { return port["bits"].array_items(); } + + const std::string &get_cell_type(const CellDataType &cell) { return cell["type"].string_value(); } + + Property parse_property(const Json &val) + { + 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 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 auto ¶ms = obj["parameters"]; + if (params.is_null()) + return; + for (const auto ¶m : params.object_items()) { + Func(param.first, parse_property(param.second)); + } + } + + template <typename TFunc> void foreach_port_dir(const CellDataType &cell, TFunc Func) + { + 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) + { + for (const auto &pconn : cell["connections"].object_items()) + Func(pconn.first, pconn.second); + } + + template <typename TFunc> const BitVectorDataType &get_net_bits(const NetnameDataType &net) + { + return net["bits"].array_items(); + } + + int get_vector_length(const BitVectorDataType &bits) { return int(bits.size()); } + + bool is_vector_bit_constant(const BitVectorDataType &bits, int i) + { + NPNR_ASSERT(i < int(bits.size())); + return bits[i].is_string(); + } + + char get_vector_bit_constval(const BitVectorDataType &bits, int i) + { + 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) + { + 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()); + } + run_frontend(ctx, JsonFrontendImpl(root)); + return true; +} + +NEXTPNR_NAMESPACE_END
\ No newline at end of file diff --git a/frontend/json_frontend.h b/frontend/json_frontend.h new file mode 100644 index 00000000..1e3deb8d --- /dev/null +++ b/frontend/json_frontend.h @@ -0,0 +1,26 @@ +/* + * 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 "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +bool parse_json(std::istream &in, const std::string &filename, Context *ctx); + +NEXTPNR_NAMESPACE_END
\ No newline at end of file |