diff options
| -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  | 
