diff options
-rw-r--r-- | common/command.cc | 3 | ||||
-rw-r--r-- | common/command.h | 2 | ||||
-rw-r--r-- | common/log.cc | 12 | ||||
-rw-r--r-- | common/log.h | 3 | ||||
-rw-r--r-- | common/placer1.cc | 9 | ||||
-rw-r--r-- | common/placer1.h | 6 | ||||
-rw-r--r-- | common/project.cc | 26 | ||||
-rw-r--r-- | common/router1.cc | 10 | ||||
-rw-r--r-- | common/router1.h | 13 | ||||
-rw-r--r-- | common/settings.h | 63 | ||||
-rw-r--r-- | docs/archapi.md | 15 | ||||
-rw-r--r-- | ecp5/arch.cc | 8 | ||||
-rw-r--r-- | ecp5/arch.h | 18 | ||||
-rw-r--r-- | generic/arch.cc | 25 | ||||
-rw-r--r-- | generic/arch.h | 10 | ||||
-rw-r--r-- | gui/basewindow.cc | 2 | ||||
-rw-r--r-- | gui/designwidget.cc | 15 | ||||
-rw-r--r-- | gui/ice40/mainwindow.cc | 2 | ||||
-rw-r--r-- | ice40/arch.cc | 54 | ||||
-rw-r--r-- | ice40/arch.h | 11 | ||||
-rw-r--r-- | ice40/chipdb.py | 214 | ||||
-rw-r--r-- | ice40/family.cmake | 4 | ||||
-rw-r--r-- | ice40/gfx.cc | 153 | ||||
-rw-r--r-- | ice40/gfx.h | 155 | ||||
-rw-r--r-- | ice40/pcf.cc | 2 | ||||
-rw-r--r-- | ice40/project.cc | 4 | ||||
-rw-r--r-- | json/jsonparse.cc | 34 |
27 files changed, 797 insertions, 76 deletions
diff --git a/common/command.cc b/common/command.cc index d5639e9a..ab0c92f2 100644 --- a/common/command.cc +++ b/common/command.cc @@ -144,7 +144,7 @@ void CommandHandler::setupContext(Context *ctx) } if (vm.count("cstrweight")) { - // ctx->placer_constraintWeight = vm["cstrweight"].as<float>(); + settings->set("placer1/constraintWeight", vm["cstrweight"].as<float>()); } if (vm.count("freq")) { @@ -261,6 +261,7 @@ int CommandHandler::exec() } else { ctx = createContext(); } + settings = std::unique_ptr<Settings>(new Settings(ctx.get())); setupContext(ctx.get()); setupArchContext(ctx.get()); return executeMain(std::move(ctx)); diff --git a/common/command.h b/common/command.h index 13d5a250..900cf74b 100644 --- a/common/command.h +++ b/common/command.h @@ -24,6 +24,7 @@ #include <boost/program_options.hpp> #include "nextpnr.h" #include "project.h" +#include "settings.h" NEXTPNR_NAMESPACE_BEGIN @@ -56,6 +57,7 @@ class CommandHandler protected: po::variables_map vm; ArchArgs chipArgs; + std::unique_ptr<Settings> settings; private: po::options_description options; diff --git a/common/log.cc b/common/log.cc index df5430bb..e30449ad 100644 --- a/common/log.cc +++ b/common/log.cc @@ -46,6 +46,18 @@ void (*log_error_atexit)() = NULL; // static bool next_print_log = false; static int log_newline_count = 0; +std::string stringf(const char *fmt, ...) +{ + std::string string; + va_list ap; + + va_start(ap, fmt); + string = vstringf(fmt, ap); + va_end(ap); + + return string; +} + std::string vstringf(const char *fmt, va_list ap) { std::string string; diff --git a/common/log.h b/common/log.h index 74b9f0f5..b5fddf53 100644 --- a/common/log.h +++ b/common/log.h @@ -51,6 +51,9 @@ extern bool log_quiet_warnings; extern std::string log_last_error; extern void (*log_error_atexit)(); +std::string stringf(const char *fmt, ...); +std::string vstringf(const char *fmt, va_list ap); + extern std::ostream clog; void log(const char *format, ...) NPNR_ATTRIBUTE(format(printf, 1, 2)); void log_always(const char *format, ...) NPNR_ATTRIBUTE(format(printf, 1, 2)); diff --git a/common/placer1.cc b/common/placer1.cc index 88f2fc47..363b4d58 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -23,6 +23,7 @@ #include "placer1.h" #include <algorithm> +#include <boost/lexical_cast.hpp> #include <cmath> #include <iostream> #include <limits> @@ -108,14 +109,12 @@ class SAPlacer if (bel_type != cell->type) { log_error("Bel \'%s\' of type \'%s\' does not match cell " "\'%s\' of type \'%s\'\n", - loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx), - cell->type.c_str(ctx)); + loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx), cell->type.c_str(ctx)); } if (!ctx->isValidBelForCell(cell, bel)) { log_error("Bel \'%s\' of type \'%s\' is not valid for cell " "\'%s\' of type \'%s\'\n", - loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx), - cell->type.c_str(ctx)); + loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx), cell->type.c_str(ctx)); } ctx->bindBel(bel, cell, STRENGTH_USER); @@ -492,6 +491,8 @@ class SAPlacer std::vector<decltype(NetInfo::udata)> old_udata; }; +Placer1Cfg::Placer1Cfg(Context *ctx) : Settings(ctx) { constraintWeight = get<float>("placer1/constraintWeight", 10); } + bool placer1(Context *ctx, Placer1Cfg cfg) { try { diff --git a/common/placer1.h b/common/placer1.h index d8f64b84..55db1fa5 100644 --- a/common/placer1.h +++ b/common/placer1.h @@ -20,12 +20,14 @@ #define PLACE_H #include "nextpnr.h" +#include "settings.h" NEXTPNR_NAMESPACE_BEGIN -struct Placer1Cfg +struct Placer1Cfg : public Settings { - float constraintWeight = 10; + Placer1Cfg(Context *ctx); + float constraintWeight; }; extern bool placer1(Context *ctx, Placer1Cfg cfg); diff --git a/common/project.cc b/common/project.cc index 949f6878..b0ebe961 100644 --- a/common/project.cc +++ b/common/project.cc @@ -18,6 +18,7 @@ */ #include "project.h" +#include <algorithm> #include <boost/filesystem/convenience.hpp> #include <boost/property_tree/json_parser.hpp> #include <fstream> @@ -64,17 +65,36 @@ void ProjectHandler::save(Context *ctx, std::string filename) 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)); - std::string fn = ctx->settings[ctx->id("project/input/json")]; + std::string fn = ctx->settings[ctx->id("input/json")]; root.put("project.input.json", make_relative(fn, proj.parent_path()).string()); root.put("project.params.freq", int(ctx->target_freq / 1e6)); root.put("project.params.seed", ctx->rngstate); saveArch(ctx, root, proj.parent_path().string()); + for (auto const &item : ctx->settings) { + std::string path = "project.settings."; + path += item.first.c_str(ctx); + std::replace(path.begin(), path.end(), '/', '.'); + root.put(path, item.second); + } pt::write_json(f, root); } catch (...) { log_error("Error saving project file.\n"); } } +void addSettings(Context *ctx, std::string path, pt::ptree sub) +{ + for (pt::ptree::value_type &v : sub) { + const std::string &key = v.first; + const boost::property_tree::ptree &subtree = v.second; + if (subtree.empty()) { + ctx->settings.emplace(ctx->id(path + key), subtree.get_value<std::string>().c_str()); + } else { + addSettings(ctx, path + key + "/", subtree); + } + } +} + std::unique_ptr<Context> ProjectHandler::load(std::string filename) { std::unique_ptr<Context> ctx; @@ -110,6 +130,10 @@ std::unique_ptr<Context> ProjectHandler::load(std::string filename) if (params.count("seed")) ctx->rngseed(params.get<uint64_t>("seed")); } + if (project.count("settings")) { + addSettings(ctx.get(), "", project.get_child("settings")); + } + loadArch(ctx.get(), root, proj.parent_path().string()); } catch (...) { log_error("Error loading project file.\n"); diff --git a/common/router1.cc b/common/router1.cc index 0733a61e..5cd4414c 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -682,6 +682,14 @@ void cleanupReroute(Context *ctx, const Router1Cfg &cfg, RipupScoreboard &scores NEXTPNR_NAMESPACE_BEGIN +Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx) +{ + maxIterCnt = get<int>("router1/maxIterCnt", 200); + cleanupReroute = get<bool>("router1/cleanupReroute", true); + fullCleanupReroute = get<bool>("router1/fullCleanupReroute", true); + useEstimate = get<bool>("router1/useEstimate", true); +} + bool router1(Context *ctx, const Router1Cfg &cfg) { try { @@ -953,7 +961,7 @@ bool Context::getActualRouteDelay(WireId src_wire, WireId dst_wire, delay_t *del std::unordered_map<WireId, PipId> *route, bool useEstimate) { RipupScoreboard scores; - Router1Cfg cfg; + Router1Cfg cfg(this); cfg.useEstimate = useEstimate; Router router(this, cfg, scores, src_wire, dst_wire); diff --git a/common/router1.h b/common/router1.h index 0380adc2..a184cbe7 100644 --- a/common/router1.h +++ b/common/router1.h @@ -21,15 +21,18 @@ #define ROUTER1_H #include "nextpnr.h" +#include "settings.h" NEXTPNR_NAMESPACE_BEGIN -struct Router1Cfg +struct Router1Cfg : Settings { - int maxIterCnt = 200; - bool cleanupReroute = true; - bool fullCleanupReroute = true; - bool useEstimate = true; + Router1Cfg(Context *ctx); + + int maxIterCnt; + bool cleanupReroute; + bool fullCleanupReroute; + bool useEstimate; }; extern bool router1(Context *ctx, const Router1Cfg &cfg); diff --git a/common/settings.h b/common/settings.h new file mode 100644 index 00000000..e1f1166a --- /dev/null +++ b/common/settings.h @@ -0,0 +1,63 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com> + * + * 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 SETTINGS_H +#define SETTINGS_H + +#include <boost/lexical_cast.hpp> +#include "log.h" +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +class Settings +{ + public: + explicit Settings(Context *ctx) : ctx(ctx) {} + + template <typename T> T get(const char *name, T defaultValue) + { + try { + IdString id = ctx->id(name); + auto pair = ctx->settings.emplace(id, std::to_string(defaultValue)); + if (!pair.second) { + return boost::lexical_cast<T>(pair.first->second); + } + + } catch (boost::bad_lexical_cast &) { + log_error("Problem reading setting %s, using default value\n", name); + } + return defaultValue; + } + + template <typename T> void set(const char *name, T value) + { + IdString id = ctx->id(name); + auto pair = ctx->settings.emplace(id, std::to_string(value)); + if (!pair.second) { + ctx->settings[pair.first->first] = value; + } + } + + private: + Context *ctx; +}; + +NEXTPNR_NAMESPACE_END + +#endif // SETTINGS_H diff --git a/docs/archapi.md b/docs/archapi.md index 473cdd2e..73443c15 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -151,6 +151,11 @@ Return a list of all bels on the device. Return the type of a given bel. +### const\_range\<std\:\:pair\<IdString, std::string\>\> getBelAttrs(BelId bel) const + +Return the attributes for that bel. Bel attributes are only informal. They are displayed by the GUI but are otherwise +unused. An implementation may simply return an empty range. + ### WireId getBelPinWire(BelId bel, IdString pin) const Return the wire connected to the given bel pin. @@ -180,6 +185,11 @@ Get the type of a wire. The wire type is purely informal and isn't used by any of the core algorithms. Implementations may simply return `IdString()`. +### const\_range\<std\:\:pair\<IdString, std::string\>\> getWireAttrs(WireId wire) const + +Return the attributes for that wire. Wire attributes are only informal. They are displayed by the GUI but are otherwise +unused. An implementation may simply return an empty range. + ### uint32\_t getWireChecksum(WireId wire) const Return a (preferably unique) number that represents this wire. This is used in design state checksum calculations. @@ -242,6 +252,11 @@ Get the name for a pip. (Pip names must be unique.) Get the type of a pip. Pip types are purely informal and implementations may simply return `IdString()`. +### const\_range\<std\:\:pair\<IdString, std::string\>\> getPipAttrs(PipId pip) const + +Return the attributes for that pip. Pip attributes are only informal. They are displayed by the GUI but are otherwise +unused. An implementation may simply return an empty range. + ### Loc getPipLocation(PipId pip) const Get the X/Y/Z location of a given pip. Pip locations do not need to be unique, and in most cases they aren't. So diff --git a/ecp5/arch.cc b/ecp5/arch.cc index d6152e95..b2ce4acb 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -385,13 +385,9 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay // ----------------------------------------------------------------------- -bool Arch::place() { return placer1(getCtx(), Placer1Cfg()); } +bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); } -bool Arch::route() -{ - Router1Cfg cfg; - return router1(getCtx(), cfg); -} +bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } // ----------------------------------------------------------------------- diff --git a/ecp5/arch.h b/ecp5/arch.h index 410ab15d..712c6e0a 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -524,6 +524,12 @@ struct Arch : BaseCtx return id; } + std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId) const + { + std::vector<std::pair<IdString, std::string>> ret; + return ret; + } + WireId getBelPinWire(BelId bel, IdString pin) const; BelPinRange getWireBelPins(WireId wire) const @@ -555,6 +561,12 @@ struct Arch : BaseCtx IdString getWireType(WireId wire) const { return IdString(); } + std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId) const + { + std::vector<std::pair<IdString, std::string>> ret; + return ret; + } + uint32_t getWireChecksum(WireId wire) const { return wire.index; } void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) @@ -635,6 +647,12 @@ struct Arch : BaseCtx IdString getPipType(PipId pip) const { return IdString(); } + std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId) const + { + std::vector<std::pair<IdString, std::string>> ret; + return ret; + } + uint32_t getPipChecksum(PipId pip) const { return pip.index; } void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) diff --git a/generic/arch.cc b/generic/arch.cc index d306a9ec..583c74d8 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -184,6 +184,21 @@ void Arch::setGroupDecal(GroupId group, DecalXY decalxy) refreshUiGroup(group); } +void Arch::setWireAttr(IdString wire, IdString key, const std::string &value) +{ + wires.at(wire).attrs[key] = value; +} + +void Arch::setPipAttr(IdString pip, IdString key, const std::string &value) +{ + pips.at(pip).attrs[key] = value; +} + +void Arch::setBelAttr(IdString bel, IdString key, const std::string &value) +{ + bels.at(bel).attrs[key] = value; +} + // --------------------------------------------------------------- Arch::Arch(ArchArgs args) : chipName("generic"), args(args) {} @@ -251,6 +266,8 @@ const std::vector<BelId> &Arch::getBels() const { return bel_ids; } IdString Arch::getBelType(BelId bel) const { return bels.at(bel).type; } +const std::map<IdString, std::string> &Arch::getBelAttrs(BelId bel) const { return bels.at(bel).attrs; } + WireId Arch::getBelPinWire(BelId bel, IdString pin) const { return bels.at(bel).pins.at(pin).wire; } PortType Arch::getBelPinType(BelId bel, IdString pin) const { return bels.at(bel).pins.at(pin).type; } @@ -276,6 +293,8 @@ IdString Arch::getWireName(WireId wire) const { return wire; } IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; } +const std::map<IdString, std::string> &Arch::getWireAttrs(WireId wire) const { return wires.at(wire).attrs; } + uint32_t Arch::getWireChecksum(WireId wire) const { // FIXME @@ -328,6 +347,8 @@ IdString Arch::getPipName(PipId pip) const { return pip; } IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; } +const std::map<IdString, std::string> &Arch::getPipAttrs(PipId pip) const { return pips.at(pip).attrs; } + uint32_t Arch::getPipChecksum(PipId wire) const { // FIXME @@ -425,9 +446,9 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay // --------------------------------------------------------------- -bool Arch::place() { return placer1(getCtx(), Placer1Cfg()); } +bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); } -bool Arch::route() { return router1(getCtx(), Router1Cfg()); } +bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } // --------------------------------------------------------------- diff --git a/generic/arch.h b/generic/arch.h index 7549a75b..22966e2a 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -32,6 +32,7 @@ struct WireInfo; struct PipInfo { IdString name, type; + std::map<IdString, std::string> attrs; NetInfo *bound_net; WireId srcWire, dstWire; DelayInfo delay; @@ -42,6 +43,7 @@ struct PipInfo struct WireInfo { IdString name, type; + std::map<IdString, std::string> attrs; NetInfo *bound_net; std::vector<PipId> downhill, uphill, aliases; BelPin uphill_bel_pin; @@ -61,6 +63,7 @@ struct PinInfo struct BelInfo { IdString name, type; + std::map<IdString, std::string> attrs; CellInfo *bound_cell; std::unordered_map<IdString, PinInfo> pins; DecalXY decalxy; @@ -120,6 +123,10 @@ struct Arch : BaseCtx void setBelDecal(BelId bel, DecalXY decalxy); void setGroupDecal(GroupId group, DecalXY decalxy); + void setWireAttr(IdString wire, IdString key, const std::string &value); + void setPipAttr(IdString pip, IdString key, const std::string &value); + void setBelAttr(IdString bel, IdString key, const std::string &value); + // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. @@ -151,6 +158,7 @@ struct Arch : BaseCtx CellInfo *getConflictingBelCell(BelId bel) const; const std::vector<BelId> &getBels() const; IdString getBelType(BelId bel) const; + const std::map<IdString, std::string> &getBelAttrs(BelId bel) const; WireId getBelPinWire(BelId bel, IdString pin) const; PortType getBelPinType(BelId bel, IdString pin) const; std::vector<IdString> getBelPins(BelId bel) const; @@ -158,6 +166,7 @@ struct Arch : BaseCtx WireId getWireByName(IdString name) const; IdString getWireName(WireId wire) const; IdString getWireType(WireId wire) const; + const std::map<IdString, std::string> &getWireAttrs(WireId wire) const; uint32_t getWireChecksum(WireId wire) const; void bindWire(WireId wire, NetInfo *net, PlaceStrength strength); void unbindWire(WireId wire); @@ -171,6 +180,7 @@ struct Arch : BaseCtx PipId getPipByName(IdString name) const; IdString getPipName(PipId pip) const; IdString getPipType(PipId pip) const; + const std::map<IdString, std::string> &getPipAttrs(PipId pip) const; uint32_t getPipChecksum(PipId pip) const; void bindPip(PipId pip, NetInfo *net, PlaceStrength strength); void unbindPip(PipId pip); diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 66df3ca4..4444c8e9 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -420,7 +420,7 @@ void BaseMainWindow::disableActions() actionNew->setEnabled(true);
actionOpen->setEnabled(true);
- if (ctx->settings.find(ctx->id("project/input/json")) != ctx->settings.end())
+ if (ctx->settings.find(ctx->id("input/json")) != ctx->settings.end())
actionSave->setEnabled(true);
else
actionSave->setEnabled(false);
diff --git a/gui/designwidget.cc b/gui/designwidget.cc index 896ef071..1b0e617e 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -411,6 +411,11 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->nameOf(ctx->getConflictingBelCell(bel)),
ElementType::CELL);
+ QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
+ for (auto &item : ctx->getBelAttrs(bel)) {
+ addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
+ }
+
QtProperty *belpinsItem = addSubGroup(topItem, "Ports");
for (const auto &item : ctx->getBelPins(bel)) {
QtProperty *portInfoItem = addSubGroup(belpinsItem, item.c_str(ctx));
@@ -433,6 +438,11 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
ElementType::NET);
+ QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
+ for (auto &item : ctx->getWireAttrs(wire)) {
+ addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
+ }
+
DelayInfo delay = ctx->getWireDelay(wire);
QtProperty *delayItem = addSubGroup(topItem, "Delay");
@@ -492,6 +502,11 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),
ElementType::WIRE);
+ QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
+ for (auto &item : ctx->getPipAttrs(pip)) {
+ addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
+ }
+
DelayInfo delay = ctx->getPipDelay(pip);
QtProperty *delayItem = addSubGroup(topItem, "Delay");
diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index 9fe80717..f270b112 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -191,7 +191,7 @@ void MainWindow::onRouteFinished() { actionSaveAsc->setEnabled(true); } void MainWindow::onProjectLoaded()
{
- if (ctx->settings.find(ctx->id("project/input/pcf")) != ctx->settings.end())
+ if (ctx->settings.find(ctx->id("input/pcf")) != ctx->settings.end())
actionLoadPCF->setEnabled(false);
}
diff --git a/ice40/arch.cc b/ice40/arch.cc index 7e2dd7f7..91dc5d66 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -226,6 +226,12 @@ PortType Arch::getBelPinType(BelId bel, IdString pin) const return PORT_INOUT; } +std::vector<std::pair<IdString, std::string>> Arch::getBelAttrs(BelId) const +{ + std::vector<std::pair<IdString, std::string>> ret; + return ret; +} + WireId Arch::getBelPinWire(BelId bel, IdString pin) const { WireId ret; @@ -331,6 +337,28 @@ IdString Arch::getWireType(WireId wire) const return IdString(); } +std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) const +{ + std::vector<std::pair<IdString, std::string>> ret; + auto &wi = chip_info->wire_data[wire.index]; + + ret.push_back(std::make_pair(id("INDEX"), stringf("%d", wi.netidx))); + + ret.push_back(std::make_pair(id("GRID_X"), stringf("%d", wi.x))); + ret.push_back(std::make_pair(id("GRID_Y"), stringf("%d", wi.y))); + ret.push_back(std::make_pair(id("GRID_Z"), stringf("%d", wi.z))); + +#if 0 + for (int i = 0; i < wi.num_segments; i++) { + auto &si = wi.segments[i]; + ret.push_back(std::make_pair(id(stringf("segment[%d]", i)), + stringf("X%d/Y%d/%s", si.x, si.y, chip_info->tile_wire_names[si.index].get()))); + } +#endif + + return ret; +} + // ----------------------------------------------------------------------- PipId Arch::getPipByName(IdString name) const @@ -372,6 +400,15 @@ IdString Arch::getPipName(PipId pip) const #endif } +IdString Arch::getPipType(PipId pip) const { return IdString(); } + +std::vector<std::pair<IdString, std::string>> Arch::getPipAttrs(PipId) const +{ + std::vector<std::pair<IdString, std::string>> ret; + return ret; +} + + // ----------------------------------------------------------------------- BelId Arch::getPackagePinBel(const std::string &pin) const @@ -565,18 +602,9 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay // ----------------------------------------------------------------------- -bool Arch::place() -{ - Placer1Cfg cfg; - cfg.constraintWeight = placer_constraintWeight; - return placer1(getCtx(), cfg); -} +bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); } -bool Arch::route() -{ - Router1Cfg cfg; - return router1(getCtx(), cfg); -} +bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } // ----------------------------------------------------------------------- @@ -727,7 +755,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const GraphicElement el; el.type = GraphicElement::TYPE_BOX; el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; - el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1; + el.x1 = chip_info->bel_data[bel.index].x + lut_swbox_x1; el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2; el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 + (4 * chip_info->bel_data[bel.index].z) * logic_cell_pitch; @@ -741,7 +769,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const GraphicElement el; el.type = GraphicElement::TYPE_BOX; el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; - el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1; + el.x1 = chip_info->bel_data[bel.index].x + lut_swbox_x1; el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2; el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 + i; el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + i + 7 * logic_cell_pitch; diff --git a/ice40/arch.h b/ice40/arch.h index 8fd1af23..871b25fb 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -108,6 +108,8 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD { }; RelPtr<char> name; + int32_t netidx; + int32_t num_uphill, num_downhill; RelPtr<int32_t> pips_uphill, pips_downhill; @@ -225,6 +227,7 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD { RelPtr<BelConfigPOD> bel_config; RelPtr<PackageInfoPOD> packages_data; RelPtr<CellTimingPOD> cell_timing; + RelPtr<RelPtr<char>> tile_wire_names; }); #if defined(_MSC_VER) @@ -502,6 +505,8 @@ struct Arch : BaseCtx return IdString(chip_info->bel_data[bel.index].type); } + std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const; + WireId getBelPinWire(BelId bel, IdString pin) const; PortType getBelPinType(BelId bel, IdString pin) const; std::vector<IdString> getBelPins(BelId bel) const; @@ -517,6 +522,7 @@ struct Arch : BaseCtx } IdString getWireType(WireId wire) const; + std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const; uint32_t getWireChecksum(WireId wire) const { return wire.index; } @@ -692,7 +698,8 @@ struct Arch : BaseCtx IdString getPipName(PipId pip) const; - IdString getPipType(PipId pip) const { return IdString(); } + IdString getPipType(PipId pip) const; + std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const; uint32_t getPipChecksum(PipId pip) const { return pip.index; } @@ -832,8 +839,6 @@ struct Arch : BaseCtx } NPNR_ASSERT_FALSE("Expected PLL pin to share an output with an SB_IO D_IN_{0,1}"); } - - float placer_constraintWeight = 10; }; void ice40DelayFuzzerMain(Context *ctx); diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 7bdf82f0..a28cba4a 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -50,6 +50,7 @@ tiletypes = dict() wiretypes = dict() gfx_wire_ids = dict() +gfx_wire_names = list() wire_segments = dict() fast_timings = None @@ -93,6 +94,136 @@ with open(args.gfxh) as f: idx = len(gfx_wire_ids) name = line.strip().rstrip(",") gfx_wire_ids[name] = idx + gfx_wire_names.append(name) + +def gfx_wire_alias(old, new): + assert old in gfx_wire_ids + assert new not in gfx_wire_ids + gfx_wire_ids[new] = gfx_wire_ids[old] + +# GFX aliases for RAM tiles + +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_RAM_RADDR_0") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_RAM_RADDR_1") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_2", "TILE_WIRE_RAM_RADDR_2") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_RAM_RADDR_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_0", "TILE_WIRE_RAM_RADDR_4") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_1", "TILE_WIRE_RAM_RADDR_5") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_2", "TILE_WIRE_RAM_RADDR_6") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_3", "TILE_WIRE_RAM_RADDR_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_0", "TILE_WIRE_RAM_RADDR_8") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_1", "TILE_WIRE_RAM_RADDR_9") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_2", "TILE_WIRE_RAM_RADDR_10") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_RAM_WADDR_0") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_RAM_WADDR_1") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_2", "TILE_WIRE_RAM_WADDR_2") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_RAM_WADDR_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_0", "TILE_WIRE_RAM_WADDR_4") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_1", "TILE_WIRE_RAM_WADDR_5") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_2", "TILE_WIRE_RAM_WADDR_6") +gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_3", "TILE_WIRE_RAM_WADDR_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_0", "TILE_WIRE_RAM_WADDR_8") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_1", "TILE_WIRE_RAM_WADDR_9") +gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_2", "TILE_WIRE_RAM_WADDR_10") + +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_0", "TILE_WIRE_RAM_MASK_0") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_1", "TILE_WIRE_RAM_MASK_1") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_2", "TILE_WIRE_RAM_MASK_2") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_3", "TILE_WIRE_RAM_MASK_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_RAM_MASK_4") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_RAM_MASK_5") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_2", "TILE_WIRE_RAM_MASK_6") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_RAM_MASK_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_0", "TILE_WIRE_RAM_MASK_8") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_1", "TILE_WIRE_RAM_MASK_9") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_2", "TILE_WIRE_RAM_MASK_10") +gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_3", "TILE_WIRE_RAM_MASK_11") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_RAM_MASK_12") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_RAM_MASK_13") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_2", "TILE_WIRE_RAM_MASK_14") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_RAM_MASK_15") + +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_0", "TILE_WIRE_RAM_WDATA_0") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_1", "TILE_WIRE_RAM_WDATA_1") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_2", "TILE_WIRE_RAM_WDATA_2") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_3", "TILE_WIRE_RAM_WDATA_3") + +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_0", "TILE_WIRE_RAM_WDATA_4") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_1", "TILE_WIRE_RAM_WDATA_5") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_2", "TILE_WIRE_RAM_WDATA_6") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_3", "TILE_WIRE_RAM_WDATA_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_0", "TILE_WIRE_RAM_WDATA_8") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_1", "TILE_WIRE_RAM_WDATA_9") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_2", "TILE_WIRE_RAM_WDATA_10") +gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_3", "TILE_WIRE_RAM_WDATA_11") + +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_0", "TILE_WIRE_RAM_WDATA_12") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_1", "TILE_WIRE_RAM_WDATA_13") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_2", "TILE_WIRE_RAM_WDATA_14") +gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_3", "TILE_WIRE_RAM_WDATA_15") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_RAM_RDATA_0") +gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_RAM_RDATA_1") +gfx_wire_alias("TILE_WIRE_LUTFF_2_OUT", "TILE_WIRE_RAM_RDATA_2") +gfx_wire_alias("TILE_WIRE_LUTFF_3_OUT", "TILE_WIRE_RAM_RDATA_3") +gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_RAM_RDATA_4") +gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_RAM_RDATA_5") +gfx_wire_alias("TILE_WIRE_LUTFF_6_OUT", "TILE_WIRE_RAM_RDATA_6") +gfx_wire_alias("TILE_WIRE_LUTFF_7_OUT", "TILE_WIRE_RAM_RDATA_7") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_RAM_RDATA_8") +gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_RAM_RDATA_9") +gfx_wire_alias("TILE_WIRE_LUTFF_2_OUT", "TILE_WIRE_RAM_RDATA_10") +gfx_wire_alias("TILE_WIRE_LUTFF_3_OUT", "TILE_WIRE_RAM_RDATA_11") +gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_RAM_RDATA_12") +gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_RAM_RDATA_13") +gfx_wire_alias("TILE_WIRE_LUTFF_6_OUT", "TILE_WIRE_RAM_RDATA_14") +gfx_wire_alias("TILE_WIRE_LUTFF_7_OUT", "TILE_WIRE_RAM_RDATA_15") + +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_RAM_RCLKE") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_RAM_WCLKE") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_RAM_RCLK") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_RAM_WCLK") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_RAM_RE") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_RAM_WE") + +# GFX aliases for IO tiles + +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_IO_0_D_OUT_0") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_IO_0_D_OUT_1") +gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_IO_0_OUT_ENB") + +gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_IO_0_D_IN_0") +gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_IO_0_D_IN_1") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_IO_1_D_OUT_0") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_IO_1_D_OUT_1") +gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_IO_1_OUT_ENB") + +gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_IO_1_D_IN_0") +gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_IO_1_D_IN_1") + +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_IO_GLOBAL_CEN") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_IO_GLOBAL_INCLK") +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_IO_GLOBAL_OUTCLK") + +gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_G0", "TILE_WIRE_IO_GLOBAL_LATCH") + +for neigh in "BNL BNR BOT LFT RGT TNL TNR TOP".split(): + for i in range(8): + gfx_wire_alias("TILE_WIRE_NEIGH_OP_%s_%d" % (neigh, i), "TILE_WIRE_LOGIC_OP_%s_%d" % (neigh, i)) + +# End of GFX aliases + def read_timings(filename): db = dict() @@ -165,6 +296,18 @@ def maj_wire_name(name): return name[2] in ("sp12_v_b_0", "sp12_v_b_1") return False +def norm_wire_xy(x, y, name): + if name.startswith("glb_netwk_"): + return None + if name.startswith("neigh_op_"): + return None + if name.startswith("logic_op_"): + return None + if name.startswith("io_global/latch"): + return None + return None # FIXME + return (x, y) + def cmp_wire_names(newname, oldname): if maj_wire_name(newname): return True @@ -508,11 +651,13 @@ with open(args.filename, "r") as f: wire_names_r[mode[1]] = wname if mode[1] not in wire_xy: wire_xy[mode[1]] = list() - wire_xy[mode[1]].append((int(line[0]), int(line[1]))) + wire_xy[mode[1]].append(wname) if mode[1] not in wire_segments: wire_segments[mode[1]] = dict() if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids: - wire_segments[mode[1]][(wname[0], wname[1])] = wname[2] + if (wname[0], wname[1]) not in wire_segments[mode[1]]: + wire_segments[mode[1]][(wname[0], wname[1])] = list() + wire_segments[mode[1]][(wname[0], wname[1])].append(wname[2]) continue if mode[0] in ("buffer", "routing"): @@ -561,7 +706,9 @@ def add_wire(x, y, name): wire_names_r[wire_idx] = wname wire_segments[wire_idx] = dict() if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids: - wire_segments[wire_idx][(wname[0], wname[1])] = wname[2] + if (wname[0], wname[1]) not in wire_segments[wire_idx]: + wire_segments[wire_idx][(wname[0], wname[1])] = list() + wire_segments[wire_idx][(wname[0], wname[1])].append(wname[2]) return wire_idx def add_switch(x, y, bel=-1): @@ -932,6 +1079,10 @@ bba.post('NEXTPNR_NAMESPACE_END') bba.push("chipdb_blob_%s" % dev_name) bba.r("chip_info_%s" % dev_name, "chip_info") +bba.l("tile_wire_names") +for name in gfx_wire_names: + bba.s(name, name) + for bel in range(len(bel_name)): bba.l("bel_wires_%d" % bel, "BelWirePOD") for data in sorted(bel_wires[bel]): @@ -1028,20 +1179,32 @@ for wire in range(num_wires): info["num_bel_pins"] = num_bel_pins info["list_bel_pins"] = ("wire%d_bels" % wire) if num_bel_pins > 0 else None - if wire in wire_xy: - avg_x, avg_y = 0, 0 + pos_xy = None + first = None - for x, y in wire_xy[wire]: - avg_x += x - avg_y += y - avg_x /= len(wire_xy[wire]) - avg_y /= len(wire_xy[wire]) + if wire in wire_xy: + for x, y, n in wire_xy[wire]: + norm_xy = norm_wire_xy(x, y, n) + if norm_xy is None: + continue + if pos_xy is None: + pos_xy = norm_xy + first = (x, y, n) + elif pos_xy != norm_xy: + print("Conflicting positions for wire %s: (%d, %d, %s) -> (%d, %d), (%d, %d, %s) -> (%d, %d)" % \ + ((info["name"],) + first + pos_xy + (x, y, n) + norm_xy), file=sys.stderr) + assert 0 + if (pos_xy is None) and (len(wire_xy[wire]) > 1): + # print("Only 'None' positions for wire %s." % info["name"], file=sys.stderr) + # assert 0 + pass - info["x"] = int(round(avg_x)) - info["y"] = int(round(avg_y)) - else: + if pos_xy is None: info["x"] = wire_names_r[wire][0] info["y"] = wire_names_r[wire][1] + else: + info["x"] = pos_xy[0] + info["y"] = pos_xy[1] wireinfo.append(info) @@ -1102,14 +1265,21 @@ for t in range(num_tile_types): bba.l("wire_data_%s" % dev_name, "WireInfoPOD") for wire, info in enumerate(wireinfo): bba.s(info["name"], "name") + bba.u32(wire, "netidx") + bba.u32(info["num_uphill"], "num_uphill") bba.u32(info["num_downhill"], "num_downhill") bba.r(info["list_uphill"], "pips_uphill") bba.r(info["list_downhill"], "pips_downhill") bba.u32(info["num_bel_pins"], "num_bel_pins") bba.r(info["list_bel_pins"], "bel_pins") - bba.u32(len(wire_segments[wire]), "num_segments") - if len(wire_segments[wire]): + + num_segments = 0 + for segs in wire_segments[wire].values(): + num_segments += len(segs) + bba.u32(num_segments, "num_segments") + + if num_segments: bba.r("wire_segments_%d" % wire, "segments") else: bba.u32(0, "segments") @@ -1125,24 +1295,25 @@ for wire, info in enumerate(wireinfo): for wire in range(num_wires): if len(wire_segments[wire]): bba.l("wire_segments_%d" % wire, "WireSegmentPOD") - for xy, seg in sorted(wire_segments[wire].items()): - bba.u8(xy[0], "x") - bba.u8(xy[1], "y") - bba.u16(gfx_wire_ids["TILE_WIRE_" + seg.upper().replace("/", "_")], "index") + for xy, segs in sorted(wire_segments[wire].items()): + for seg in segs: + bba.u8(xy[0], "x") + bba.u8(xy[1], "y") + bba.u16(gfx_wire_ids["TILE_WIRE_" + seg.upper().replace("/", "_")], "index") bba.l("pip_data_%s" % dev_name, "PipInfoPOD") for info in pipinfo: src_seg = -1 src_segname = wire_names_r[info["src"]] if (info["x"], info["y"]) in wire_segments[info["src"]]: - src_segname = wire_segments[info["src"]][(info["x"], info["y"])] + src_segname = wire_segments[info["src"]][(info["x"], info["y"])][0] src_seg = gfx_wire_ids["TILE_WIRE_" + src_segname.upper().replace("/", "_")] src_segname = src_segname.replace("/", ".") dst_seg = -1 dst_segname = wire_names_r[info["dst"]] if (info["x"], info["y"]) in wire_segments[info["dst"]]: - dst_segname = wire_segments[info["dst"]][(info["x"], info["y"])] + dst_segname = wire_segments[info["dst"]][(info["x"], info["y"])][0] dst_seg = gfx_wire_ids["TILE_WIRE_" + dst_segname.upper().replace("/", "_")] dst_segname = dst_segname.replace("/", ".") @@ -1276,5 +1447,6 @@ bba.r("bits_info_%s" % dev_name, "bits_info") bba.r("bel_config_%s" % dev_name if len(extra_cell_config) > 0 else None, "bel_config") bba.r("package_info_%s" % dev_name, "packages_data") bba.r("cell_timings_%s" % dev_name, "cell_timing") +bba.r("tile_wire_names", "tile_wire_names") bba.pop() diff --git a/ice40/family.cmake b/ice40/family.cmake index f558a14d..0e1d36e6 100644 --- a/ice40/family.cmake +++ b/ice40/family.cmake @@ -36,7 +36,7 @@ if (MSVC) set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h) add_custom_command(OUTPUT ${DEV_CC_BBA_DB} COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -p ${DEV_CONSTIDS_INC} -g ${DEV_GFXH} ${OPT_FAST} ${OPT_SLOW} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB} - DEPENDS ${DEV_TXT_DB} ${DB_PY} + DEPENDS ${DEV_CONSTIDS_INC} ${DEV_GFXH} ${DEV_TXT_DB} ${DB_PY} ) add_custom_command(OUTPUT ${DEV_CC_DB} COMMAND bbasm ${DEV_CC_BBA_DB} ${DEV_CC_DB} @@ -69,7 +69,7 @@ else() add_custom_command(OUTPUT ${DEV_CC_BBA_DB} COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -p ${DEV_CONSTIDS_INC} -g ${DEV_GFXH} ${OPT_FAST} ${OPT_SLOW} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB}.new COMMAND mv ${DEV_CC_BBA_DB}.new ${DEV_CC_BBA_DB} - DEPENDS ${DEV_TXT_DB} ${DB_PY} + DEPENDS ${DEV_CONSTIDS_INC} ${DEV_GFXH} ${DEV_TXT_DB} ${DB_PY} ) add_custom_command(OUTPUT ${DEV_CC_DB} COMMAND bbasm --c ${DEV_CC_BBA_DB} ${DEV_CC_DB}.new diff --git a/ice40/gfx.cc b/ice40/gfx.cc index 1ab2fb3c..79350ad0 100644 --- a/ice40/gfx.cc +++ b/ice40/gfx.cc @@ -339,6 +339,78 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, g.push_back(el); } + // IO Span-4 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN4_HORZ_0 && id <= TILE_WIRE_SPAN4_HORZ_47) { + int idx = id - TILE_WIRE_SPAN4_HORZ_0; + float y1 = y + 1.0 - (0.03 + 0.0025 * (48 - (idx ^ 1))); + + el.x1 = x; + el.x2 = x + 1.0; + el.y1 = y1; + el.y2 = y1; + g.push_back(el); + + el.x1 = x + main_swbox_x1 + 0.0025 * ((idx ^ 1) + 35); + el.x2 = el.x1; + el.y1 = y1; + el.y2 = y + main_swbox_y2; + g.push_back(el); + } + + if (id >= TILE_WIRE_SPAN4_VERT_0 && id <= TILE_WIRE_SPAN4_VERT_47) { + int idx = id - TILE_WIRE_SPAN4_VERT_0; + float x1 = x + 0.03 + 0.0025 * (48 - (idx ^ 1)); + + el.x1 = x1; + el.x2 = x1; + el.y1 = y; + el.y2 = y + 1.0; + g.push_back(el); + + el.y1 = y + 1.0 - (0.03 + 0.0025 * (270 - (idx ^ 1))); + el.y2 = el.y1; + el.x1 = x1; + el.x2 = x + main_swbox_x1; + g.push_back(el); + } + + // IO Span-12 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN12_HORZ_0 && id <= TILE_WIRE_SPAN12_HORZ_23) { + int idx = id - TILE_WIRE_SPAN12_HORZ_0; + float y1 = y + 1.0 - (0.03 + 0.0025 * (88 - (idx ^ 1))); + + el.x1 = x; + el.x2 = x + 1.0; + el.y1 = y1; + el.y2 = y1; + g.push_back(el); + + el.x1 = x + main_swbox_x1 + 0.0025 * ((idx ^ 1) + 5); + el.x2 = el.x1; + el.y1 = y1; + el.y2 = y + main_swbox_y2; + g.push_back(el); + } + + if (id >= TILE_WIRE_SPAN12_VERT_0 && id <= TILE_WIRE_SPAN12_VERT_23) { + int idx = id - TILE_WIRE_SPAN12_VERT_0; + float x1 = x + 0.03 + 0.0025 * (88 - (idx ^ 1)); + + el.x1 = x1; + el.x2 = x1; + el.y1 = y; + el.y2 = y + 1.0; + g.push_back(el); + + el.y1 = y + 1.0 - (0.03 + 0.0025 * (300 - (idx ^ 1))); + el.y2 = el.y1; + el.x1 = x1; + el.x2 = x + main_swbox_x1; + g.push_back(el); + } + // Global2Local if (id >= TILE_WIRE_GLB2LOCAL_0 && id <= TILE_WIRE_GLB2LOCAL_3) { @@ -457,6 +529,42 @@ void gfxTileWire(std::vector<GraphicElement> &g, int x, int y, GfxTileWireId id, } } + // LC Control for IO and BRAM + + if (id >= TILE_WIRE_FUNC_GLOBAL_CEN && id <= TILE_WIRE_FUNC_GLOBAL_S_R) { + int idx = id - TILE_WIRE_FUNC_GLOBAL_CEN; + + el.x1 = x + main_swbox_x2 - 0.005 * (idx + 5); + el.x2 = el.x1; + el.y1 = y + main_swbox_y1; + el.y2 = el.y1 - 0.005 * (idx + 2); + g.push_back(el); + + el.y1 = el.y2; + el.x2 = x + logic_cell_x2 - 0.005 * (2 - idx + 5); + g.push_back(el); + + el.y2 = y + logic_cell_y1; + el.x1 = el.x2; + g.push_back(el); + } + + if (id == TILE_WIRE_FABOUT) { + el.y1 = y + main_swbox_y1; + el.y2 = el.y1 - 0.005 * 4; + el.x1 = x + main_swbox_x2 - 0.005 * 9; + el.x2 = el.x1; + g.push_back(el); + } + + if (id == TILE_WIRE_FUNC_GLOBAL_G0) { + el.y1 = y + logic_cell_y1; + el.y2 = el.y1 - 0.005 * 4; + el.x1 = x + logic_cell_x2 - 0.005 * 3; + el.x2 = el.x1; + g.push_back(el); + } + // LC Cascade if (id >= TILE_WIRE_LUTFF_0_LOUT && id <= TILE_WIRE_LUTFF_6_LOUT) { @@ -571,6 +679,38 @@ static bool getWireXY_main(GfxTileWireId id, float &x, float &y) return true; } + // IO Span-4 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN4_HORZ_0 && id <= TILE_WIRE_SPAN4_HORZ_47) { + int idx = id - TILE_WIRE_SPAN4_HORZ_0; + x = main_swbox_x1 + 0.0025 * ((idx ^ 1) + 35); + y = main_swbox_y2; + return true; + } + + if (id >= TILE_WIRE_SPAN4_VERT_0 && id <= TILE_WIRE_SPAN4_VERT_47) { + int idx = id - TILE_WIRE_SPAN4_VERT_0; + y = 1.0 - (0.03 + 0.0025 * (270 - (idx ^ 1))); + x = main_swbox_x1; + return true; + } + + // IO Span-12 Wires connecting to fabric + + if (id >= TILE_WIRE_SPAN12_HORZ_0 && id <= TILE_WIRE_SPAN12_HORZ_23) { + int idx = id - TILE_WIRE_SPAN12_HORZ_0; + x = main_swbox_x1 + 0.0025 * ((idx ^ 1) + 5); + y = main_swbox_y2; + return true; + } + + if (id >= TILE_WIRE_SPAN12_VERT_0 && id <= TILE_WIRE_SPAN12_VERT_23) { + int idx = id - TILE_WIRE_SPAN12_VERT_0; + y = 1.0 - (0.03 + 0.0025 * (300 - (idx ^ 1))); + x = main_swbox_x1; + return true; + } + // Global2Local if (id >= TILE_WIRE_GLB2LOCAL_0 && id <= TILE_WIRE_GLB2LOCAL_3) { @@ -626,6 +766,19 @@ static bool getWireXY_main(GfxTileWireId id, float &x, float &y) return true; } + if (id >= TILE_WIRE_FUNC_GLOBAL_CEN && id <= TILE_WIRE_FUNC_GLOBAL_S_R) { + int idx = id - TILE_WIRE_FUNC_GLOBAL_CEN; + x = main_swbox_x2 - 0.005 * (idx + 5); + y = main_swbox_y1; + return true; + } + + if (id == TILE_WIRE_FABOUT) { + x = main_swbox_x2 - 0.005 * 9; + y = main_swbox_y1; + return true; + } + return false; } diff --git a/ice40/gfx.h b/ice40/gfx.h index 8ee7b0b6..5401a410 100644 --- a/ice40/gfx.h +++ b/ice40/gfx.h @@ -205,6 +205,13 @@ enum GfxTileWireId TILE_WIRE_LUTFF_GLOBAL_CLK, TILE_WIRE_LUTFF_GLOBAL_S_R, + TILE_WIRE_FUNC_GLOBAL_CEN, + TILE_WIRE_FUNC_GLOBAL_CLK, + TILE_WIRE_FUNC_GLOBAL_S_R, + + TILE_WIRE_FUNC_GLOBAL_G0, + TILE_WIRE_FABOUT, + TILE_WIRE_CARRY_IN, TILE_WIRE_CARRY_IN_MUX, @@ -509,6 +516,154 @@ enum GfxTileWireId TILE_WIRE_SP12_H_L_22, TILE_WIRE_SP12_H_L_23, + TILE_WIRE_SPAN4_VERT_0, + TILE_WIRE_SPAN4_VERT_1, + TILE_WIRE_SPAN4_VERT_2, + TILE_WIRE_SPAN4_VERT_3, + TILE_WIRE_SPAN4_VERT_4, + TILE_WIRE_SPAN4_VERT_5, + TILE_WIRE_SPAN4_VERT_6, + TILE_WIRE_SPAN4_VERT_7, + TILE_WIRE_SPAN4_VERT_8, + TILE_WIRE_SPAN4_VERT_9, + TILE_WIRE_SPAN4_VERT_10, + TILE_WIRE_SPAN4_VERT_11, + TILE_WIRE_SPAN4_VERT_12, + TILE_WIRE_SPAN4_VERT_13, + TILE_WIRE_SPAN4_VERT_14, + TILE_WIRE_SPAN4_VERT_15, + TILE_WIRE_SPAN4_VERT_16, + TILE_WIRE_SPAN4_VERT_17, + TILE_WIRE_SPAN4_VERT_18, + TILE_WIRE_SPAN4_VERT_19, + TILE_WIRE_SPAN4_VERT_20, + TILE_WIRE_SPAN4_VERT_21, + TILE_WIRE_SPAN4_VERT_22, + TILE_WIRE_SPAN4_VERT_23, + TILE_WIRE_SPAN4_VERT_24, + TILE_WIRE_SPAN4_VERT_25, + TILE_WIRE_SPAN4_VERT_26, + TILE_WIRE_SPAN4_VERT_27, + TILE_WIRE_SPAN4_VERT_28, + TILE_WIRE_SPAN4_VERT_29, + TILE_WIRE_SPAN4_VERT_30, + TILE_WIRE_SPAN4_VERT_31, + TILE_WIRE_SPAN4_VERT_32, + TILE_WIRE_SPAN4_VERT_33, + TILE_WIRE_SPAN4_VERT_34, + TILE_WIRE_SPAN4_VERT_35, + TILE_WIRE_SPAN4_VERT_36, + TILE_WIRE_SPAN4_VERT_37, + TILE_WIRE_SPAN4_VERT_38, + TILE_WIRE_SPAN4_VERT_39, + TILE_WIRE_SPAN4_VERT_40, + TILE_WIRE_SPAN4_VERT_41, + TILE_WIRE_SPAN4_VERT_42, + TILE_WIRE_SPAN4_VERT_43, + TILE_WIRE_SPAN4_VERT_44, + TILE_WIRE_SPAN4_VERT_45, + TILE_WIRE_SPAN4_VERT_46, + TILE_WIRE_SPAN4_VERT_47, + + TILE_WIRE_SPAN4_HORZ_0, + TILE_WIRE_SPAN4_HORZ_1, + TILE_WIRE_SPAN4_HORZ_2, + TILE_WIRE_SPAN4_HORZ_3, + TILE_WIRE_SPAN4_HORZ_4, + TILE_WIRE_SPAN4_HORZ_5, + TILE_WIRE_SPAN4_HORZ_6, + TILE_WIRE_SPAN4_HORZ_7, + TILE_WIRE_SPAN4_HORZ_8, + TILE_WIRE_SPAN4_HORZ_9, + TILE_WIRE_SPAN4_HORZ_10, + TILE_WIRE_SPAN4_HORZ_11, + TILE_WIRE_SPAN4_HORZ_12, + TILE_WIRE_SPAN4_HORZ_13, + TILE_WIRE_SPAN4_HORZ_14, + TILE_WIRE_SPAN4_HORZ_15, + TILE_WIRE_SPAN4_HORZ_16, + TILE_WIRE_SPAN4_HORZ_17, + TILE_WIRE_SPAN4_HORZ_18, + TILE_WIRE_SPAN4_HORZ_19, + TILE_WIRE_SPAN4_HORZ_20, + TILE_WIRE_SPAN4_HORZ_21, + TILE_WIRE_SPAN4_HORZ_22, + TILE_WIRE_SPAN4_HORZ_23, + TILE_WIRE_SPAN4_HORZ_24, + TILE_WIRE_SPAN4_HORZ_25, + TILE_WIRE_SPAN4_HORZ_26, + TILE_WIRE_SPAN4_HORZ_27, + TILE_WIRE_SPAN4_HORZ_28, + TILE_WIRE_SPAN4_HORZ_29, + TILE_WIRE_SPAN4_HORZ_30, + TILE_WIRE_SPAN4_HORZ_31, + TILE_WIRE_SPAN4_HORZ_32, + TILE_WIRE_SPAN4_HORZ_33, + TILE_WIRE_SPAN4_HORZ_34, + TILE_WIRE_SPAN4_HORZ_35, + TILE_WIRE_SPAN4_HORZ_36, + TILE_WIRE_SPAN4_HORZ_37, + TILE_WIRE_SPAN4_HORZ_38, + TILE_WIRE_SPAN4_HORZ_39, + TILE_WIRE_SPAN4_HORZ_40, + TILE_WIRE_SPAN4_HORZ_41, + TILE_WIRE_SPAN4_HORZ_42, + TILE_WIRE_SPAN4_HORZ_43, + TILE_WIRE_SPAN4_HORZ_44, + TILE_WIRE_SPAN4_HORZ_45, + TILE_WIRE_SPAN4_HORZ_46, + TILE_WIRE_SPAN4_HORZ_47, + + TILE_WIRE_SPAN12_VERT_0, + TILE_WIRE_SPAN12_VERT_1, + TILE_WIRE_SPAN12_VERT_2, + TILE_WIRE_SPAN12_VERT_3, + TILE_WIRE_SPAN12_VERT_4, + TILE_WIRE_SPAN12_VERT_5, + TILE_WIRE_SPAN12_VERT_6, + TILE_WIRE_SPAN12_VERT_7, + TILE_WIRE_SPAN12_VERT_8, + TILE_WIRE_SPAN12_VERT_9, + TILE_WIRE_SPAN12_VERT_10, + TILE_WIRE_SPAN12_VERT_11, + TILE_WIRE_SPAN12_VERT_12, + TILE_WIRE_SPAN12_VERT_13, + TILE_WIRE_SPAN12_VERT_14, + TILE_WIRE_SPAN12_VERT_15, + TILE_WIRE_SPAN12_VERT_16, + TILE_WIRE_SPAN12_VERT_17, + TILE_WIRE_SPAN12_VERT_18, + TILE_WIRE_SPAN12_VERT_19, + TILE_WIRE_SPAN12_VERT_20, + TILE_WIRE_SPAN12_VERT_21, + TILE_WIRE_SPAN12_VERT_22, + TILE_WIRE_SPAN12_VERT_23, + + TILE_WIRE_SPAN12_HORZ_0, + TILE_WIRE_SPAN12_HORZ_1, + TILE_WIRE_SPAN12_HORZ_2, + TILE_WIRE_SPAN12_HORZ_3, + TILE_WIRE_SPAN12_HORZ_4, + TILE_WIRE_SPAN12_HORZ_5, + TILE_WIRE_SPAN12_HORZ_6, + TILE_WIRE_SPAN12_HORZ_7, + TILE_WIRE_SPAN12_HORZ_8, + TILE_WIRE_SPAN12_HORZ_9, + TILE_WIRE_SPAN12_HORZ_10, + TILE_WIRE_SPAN12_HORZ_11, + TILE_WIRE_SPAN12_HORZ_12, + TILE_WIRE_SPAN12_HORZ_13, + TILE_WIRE_SPAN12_HORZ_14, + TILE_WIRE_SPAN12_HORZ_15, + TILE_WIRE_SPAN12_HORZ_16, + TILE_WIRE_SPAN12_HORZ_17, + TILE_WIRE_SPAN12_HORZ_18, + TILE_WIRE_SPAN12_HORZ_19, + TILE_WIRE_SPAN12_HORZ_20, + TILE_WIRE_SPAN12_HORZ_21, + TILE_WIRE_SPAN12_HORZ_22, + TILE_WIRE_SPAN12_HORZ_23, + TILE_WIRE_PLLIN, TILE_WIRE_PLLOUT_A, TILE_WIRE_PLLOUT_B diff --git a/ice40/pcf.cc b/ice40/pcf.cc index d9fc4e68..af5b3e17 100644 --- a/ice40/pcf.cc +++ b/ice40/pcf.cc @@ -66,7 +66,7 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in) log_error("unsupported pcf command '%s'\n", cmd.c_str()); } } - ctx->settings.emplace(ctx->id("project/input/pcf"), filename); + ctx->settings.emplace(ctx->id("input/pcf"), filename); return true; } catch (log_execution_error_exception) { return false; diff --git a/ice40/project.cc b/ice40/project.cc index 8ca10e36..47c0903d 100644 --- a/ice40/project.cc +++ b/ice40/project.cc @@ -28,8 +28,8 @@ NEXTPNR_NAMESPACE_BEGIN void ProjectHandler::saveArch(Context *ctx, pt::ptree &root, std::string path) { root.put("project.arch.package", ctx->archArgs().package); - if (ctx->settings.find(ctx->id("project/input/pcf")) != ctx->settings.end()) { - std::string fn = ctx->settings[ctx->id("project/input/pcf")]; + if (ctx->settings.find(ctx->id("input/pcf")) != ctx->settings.end()) { + std::string fn = ctx->settings[ctx->id("input/pcf")]; root.put("project.input.pcf", make_relative(fn, path).string()); } } diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 9e86f93e..a690bf18 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -52,7 +52,7 @@ struct JsonNode std::map<string, JsonNode *> data_dict; std::vector<string> data_dict_keys; - JsonNode(std::istream &f) + JsonNode(std::istream &f, int &lineno) { type = 0; data_number = 0; @@ -63,6 +63,8 @@ struct JsonNode if (ch == EOF) log_error("Unexpected EOF in JSON file.\n"); + if (ch == '\n') + lineno++; if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') continue; @@ -91,9 +93,12 @@ struct JsonNode break; } - if ('0' <= ch && ch <= '9') { + if (('0' <= ch && ch <= '9') || ('-' == ch)) { type = 'N'; - data_number = ch - '0'; + if (ch == '-') + data_number = 0; + else + data_number = ch - '0'; data_string += ch; while (1) { @@ -114,6 +119,8 @@ struct JsonNode data_string += ch; } + if (data_string[0] == '-') + data_number = -data_number; data_string = ""; break; @@ -148,6 +155,8 @@ struct JsonNode if (ch == EOF) log_error("Unexpected EOF in JSON file.\n"); + if (ch == '\n') + lineno++; if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == ',') continue; @@ -155,7 +164,7 @@ struct JsonNode break; f.unget(); - data_array.push_back(new JsonNode(f)); + data_array.push_back(new JsonNode(f, lineno)); } break; @@ -170,6 +179,8 @@ struct JsonNode if (ch == EOF) log_error("Unexpected EOF in JSON file.\n"); + if (ch == '\n') + lineno++; if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == ',') continue; @@ -177,7 +188,7 @@ struct JsonNode break; f.unget(); - JsonNode key(f); + JsonNode key(f, lineno); while (1) { ch = f.get(); @@ -185,6 +196,8 @@ struct JsonNode if (ch == EOF) log_error("Unexpected EOF in JSON file.\n"); + if (ch == '\n') + lineno++; if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == ':') continue; @@ -192,10 +205,10 @@ struct JsonNode break; } - JsonNode *value = new JsonNode(f); + JsonNode *value = new JsonNode(f, lineno); if (key.type != 'S') - log_error("Unexpected non-string key in JSON dict.\n"); + log_error("Unexpected non-string key in JSON dict, line %d.\n", lineno); data_dict[key.data_string] = value; data_dict_keys.push_back(key.data_string); @@ -204,7 +217,7 @@ struct JsonNode break; } - log_error("Unexpected character in JSON file: '%c'\n", ch); + log_error("Unexpected character in JSON file, line %d: '%c'\n", lineno, ch); } } @@ -736,8 +749,9 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) { try { using namespace JsonParser; + int lineno = 1; - JsonNode root(f); + JsonNode root(f, lineno); if (root.type != 'D') log_error("JSON root node is not a dictionary.\n"); @@ -754,7 +768,7 @@ bool parse_json_file(std::istream &f, std::string &filename, Context *ctx) log_info("Checksum: 0x%08x\n", ctx->checksum()); log_break(); - ctx->settings.emplace(ctx->id("project/input/json"), filename); + ctx->settings.emplace(ctx->id("input/json"), filename); return true; } catch (log_execution_error_exception) { return false; |