From fffaaa613f498cb83f8d885e5a8b75dc41a9c157 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 6 Aug 2018 19:32:17 +0200 Subject: Added project loader --- common/command.cc | 15 +++++++++- common/command.h | 2 ++ common/project.cc | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/project.h | 42 ++++++++++++++++++++++++++ ecp5/arch.h | 1 + ecp5/project.cc | 57 +++++++++++++++++++++++++++++++++++ generic/arch.cc | 2 +- generic/arch.h | 2 ++ generic/project.cc | 41 +++++++++++++++++++++++++ ice40/arch.h | 1 + ice40/project.cc | 71 ++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 common/project.cc create mode 100644 common/project.h create mode 100644 ecp5/project.cc create mode 100644 generic/project.cc create mode 100644 ice40/project.cc diff --git a/common/command.cc b/common/command.cc index f144db37..9eace237 100644 --- a/common/command.cc +++ b/common/command.cc @@ -187,7 +187,9 @@ int CommandHandler::executeMain(std::unique_ptr ctx) log_error("Loading design failed.\n"); customAfterLoad(ctx.get()); + } + if (vm.count("json") || vm.count("load")) { if (!ctx->pack() && !ctx->force) log_error("Packing design failed.\n"); ctx->check(); @@ -215,6 +217,11 @@ int CommandHandler::executeMain(std::unique_ptr ctx) deinit_python(); } #endif + + if (vm.count("save")) { + project.save(ctx.get(), vm["save"].as()); + } + return 0; } @@ -235,7 +242,13 @@ int CommandHandler::exec() if (executeBeforeContext()) return 0; - std::unique_ptr ctx = createContext(); + + std::unique_ptr ctx; + if (vm.count("load")) { + ctx = project.load(vm["load"].as()); + } else { + ctx = createContext(); + } setupContext(ctx.get()); setupArchContext(ctx.get()); return executeMain(std::move(ctx)); diff --git a/common/command.h b/common/command.h index e6595f6a..13d5a250 100644 --- a/common/command.h +++ b/common/command.h @@ -23,6 +23,7 @@ #include #include "nextpnr.h" +#include "project.h" NEXTPNR_NAMESPACE_BEGIN @@ -61,6 +62,7 @@ class CommandHandler po::positional_options_description pos; int argc; char **argv; + ProjectHandler project; }; NEXTPNR_NAMESPACE_END diff --git a/common/project.cc b/common/project.cc new file mode 100644 index 00000000..8e043f36 --- /dev/null +++ b/common/project.cc @@ -0,0 +1,87 @@ +/* + * 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 +#include +#include "project.h" +#include "log.h" +#include "jsonparse.h" +#include + +NEXTPNR_NAMESPACE_BEGIN + +void ProjectHandler::save(Context *ctx, std::string filename) +{ + std::ofstream f(filename); + pt::ptree root; + root.put("project.version", 1); + root.put("project.name", boost::filesystem::basename(filename)); + root.put("project.arch.name", ctx->archId().c_str(ctx)); + root.put("project.arch.type", ctx->archArgsToId(ctx->archArgs()).c_str(ctx)); +/* root.put("project.input.json", );*/ + root.put("project.params.freq", int(ctx->target_freq / 1e6)); + root.put("project.params.seed", ctx->rngstate); + saveArch(ctx,root); + pt::write_json(f, root); +} + +std::unique_ptr ProjectHandler::load(std::string filename) +{ + std::unique_ptr ctx; + try { + pt::ptree root; + boost::filesystem::path proj(filename); + pt::read_json(filename, root); + log_info("Loading project %s...\n", filename.c_str()); + log_break(); + + int version = root.get("project.version"); + if (version != 1) + log_error("Wrong project format version.\n"); + + + ctx = createContext(root); + + std::string arch_name = root.get("project.arch.name"); + if (arch_name != ctx->archId().c_str(ctx.get())) + log_error("Unsuported project architecture.\n"); + + auto project = root.get_child("project"); + auto input = project.get_child("input"); + std::string filename = input.get("json"); + boost::filesystem::path json = proj.parent_path() / filename; + std::ifstream f(json.string()); + if (!parse_json_file(f, filename, ctx.get())) + log_error("Loading design failed.\n"); + + if (project.count("params")) { + auto params = project.get_child("params"); + if (params.count("freq")) + ctx->target_freq = params.get("freq") * 1e6; + if (params.count("seed")) + ctx->rngseed(params.get("seed")); + } + loadArch(ctx.get(),root, proj.parent_path().string()); + } catch (...) { + log_error("Error loading project file.\n"); + } + return ctx; +} + +NEXTPNR_NAMESPACE_END diff --git a/common/project.h b/common/project.h new file mode 100644 index 00000000..14f03ecd --- /dev/null +++ b/common/project.h @@ -0,0 +1,42 @@ +/* + * 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 PROJECT_H +#define PROJECT_H + +#include +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +namespace pt = boost::property_tree; + +struct ProjectHandler +{ + void save(Context *ctx, std::string filename); + std::unique_ptr load(std::string filename); + // implemented per arch + void saveArch(Context *ctx, pt::ptree &root); + std::unique_ptr createContext(pt::ptree &root); + void loadArch(Context *ctx, pt::ptree &root, std::string path); +}; + +NEXTPNR_NAMESPACE_END + +#endif // PROJECT_H diff --git a/ecp5/arch.h b/ecp5/arch.h index 6daf543d..223f1ec5 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -415,6 +415,7 @@ struct Arch : BaseCtx std::string getChipName() const; IdString archId() const { return id("ecp5"); } + ArchArgs archArgs() const { return args; } IdString archArgsToId(ArchArgs args) const; IdString belTypeToId(BelType type) const; diff --git a/ecp5/project.cc b/ecp5/project.cc new file mode 100644 index 00000000..a9b48bbe --- /dev/null +++ b/ecp5/project.cc @@ -0,0 +1,57 @@ +/* + * 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 +#include +#include "project.h" +#include "log.h" +#include + +NEXTPNR_NAMESPACE_BEGIN + +void ProjectHandler::saveArch(Context *ctx, pt::ptree &root) +{ + root.put("project.arch.package", ctx->archArgs().package); + root.put("project.arch.speed", ctx->archArgs().speed); +} + +std::unique_ptr ProjectHandler::createContext(pt::ptree &root) +{ + ArchArgs chipArgs; + std::string arch_type = root.get("project.arch.type"); + if (arch_type == "25k") { + chipArgs.type = ArchArgs::LFE5U_25F; + } + if (arch_type == "45k") { + chipArgs.type = ArchArgs::LFE5U_45F; + } + if (arch_type == "85k") { + chipArgs.type = ArchArgs::LFE5U_85F; + } + chipArgs.package = root.get("project.arch.package"); + chipArgs.speed = root.get("project.arch.speed"); + + return std::unique_ptr(new Context(chipArgs)); +} + +void ProjectHandler::loadArch(Context *ctx, pt::ptree &root, std::string path) +{ +} + +NEXTPNR_NAMESPACE_END diff --git a/generic/arch.cc b/generic/arch.cc index a0ab58f8..3389ac0d 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -175,7 +175,7 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy) // --------------------------------------------------------------- -Arch::Arch(ArchArgs) : chipName("generic") {} +Arch::Arch(ArchArgs args) : chipName("generic"), args(args) {} void IdString::initialize_arch(const BaseCtx *ctx) {} diff --git a/generic/arch.h b/generic/arch.h index d3e8f69e..10cd1d5a 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -118,11 +118,13 @@ struct Arch : BaseCtx // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. + ArchArgs args; Arch(ArchArgs args); std::string getChipName() const { return chipName; } IdString archId() const { return id("generic"); } + ArchArgs archArgs() const { return args; } IdString archArgsToId(ArchArgs args) const { return id("none"); } IdString belTypeToId(BelType type) const { return type; } diff --git a/generic/project.cc b/generic/project.cc new file mode 100644 index 00000000..e412d8dc --- /dev/null +++ b/generic/project.cc @@ -0,0 +1,41 @@ +/* + * 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 +#include "project.h" +#include "log.h" +#include + +NEXTPNR_NAMESPACE_BEGIN + +void ProjectHandler::saveArch(Context *ctx, pt::ptree &root) +{ +} + +std::unique_ptr ProjectHandler::createContext(pt::ptree &root) +{ + ArchArgs chipArgs; + return std::unique_ptr(new Context(chipArgs)); +} + +void ProjectHandler::loadArch(Context *ctx, pt::ptree &root, std::string path) +{ +} + +NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.h b/ice40/arch.h index d3076416..bc968b74 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -411,6 +411,7 @@ struct Arch : BaseCtx std::string getChipName() const; IdString archId() const { return id("ice40"); } + ArchArgs archArgs() const { return args; } IdString archArgsToId(ArchArgs args) const; IdString belTypeToId(BelType type) const; diff --git a/ice40/project.cc b/ice40/project.cc new file mode 100644 index 00000000..53401d63 --- /dev/null +++ b/ice40/project.cc @@ -0,0 +1,71 @@ +/* + * 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 +#include "project.h" +#include "log.h" +#include +#include "pcf.h" + +NEXTPNR_NAMESPACE_BEGIN + +void ProjectHandler::saveArch(Context *ctx, pt::ptree &root) +{ + root.put("project.arch.package", ctx->archArgs().package); + // if(!pcfFilename.empty()) + // root.put("project.input.pcf", pcfFilename); +} + +std::unique_ptr ProjectHandler::createContext(pt::ptree &root) +{ + ArchArgs chipArgs; + std::string arch_type = root.get("project.arch.type"); + if (arch_type == "lp384") { + chipArgs.type = ArchArgs::LP384; + } + if (arch_type == "lp1k") { + chipArgs.type = ArchArgs::LP1K; + } + if (arch_type == "lp8k") { + chipArgs.type = ArchArgs::LP8K; + } + if (arch_type == "hx1k") { + chipArgs.type = ArchArgs::HX1K; + } + if (arch_type == "hx8k") { + chipArgs.type = ArchArgs::HX8K; + } + if (arch_type == "up5k") { + chipArgs.type = ArchArgs::UP5K; + } + chipArgs.package = root.get("project.arch.package"); + + return std::unique_ptr(new Context(chipArgs)); +} + +void ProjectHandler::loadArch(Context *ctx, pt::ptree &root, std::string path) +{ + auto input = root.get_child("project").get_child("input"); + boost::filesystem::path pcf = boost::filesystem::path(path) / input.get("pcf"); + std::ifstream f(pcf.string()); + if (!apply_pcf(ctx, f)) + log_error("Loading PCF failed.\n"); +} + +NEXTPNR_NAMESPACE_END -- cgit v1.2.3