aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nexus/arch.h2
-rw-r--r--nexus/main.cc12
-rw-r--r--nexus/pdc.cc44
3 files changed, 56 insertions, 2 deletions
diff --git a/nexus/arch.h b/nexus/arch.h
index 886ee557..3beef3cd 100644
--- a/nexus/arch.h
+++ b/nexus/arch.h
@@ -1444,7 +1444,7 @@ struct Arch : BaseCtx
// List of IO constraints, used by PDC parser
std::unordered_map<IdString, std::unordered_map<IdString, Property>> io_attr;
- void parse_pdc(std::istream &in) const;
+ void read_pdc(std::istream &in);
// -------------------------------------------------
void write_fasm(std::ostream &out) const;
diff --git a/nexus/main.cc b/nexus/main.cc
index 9549a573..83b22977 100644
--- a/nexus/main.cc
+++ b/nexus/main.cc
@@ -50,6 +50,7 @@ po::options_description NexusCommandHandler::getArchOptions()
specific.add_options()("chipdb", po::value<std::string>(), "name of chip database binary");
specific.add_options()("device", po::value<std::string>(), "device name");
specific.add_options()("fasm", po::value<std::string>(), "fasm file to write");
+ specific.add_options()("pdc", po::value<std::string>(), "physical constraints file");
return specific;
}
@@ -72,7 +73,16 @@ std::unique_ptr<Context> NexusCommandHandler::createContext(std::unordered_map<s
return std::unique_ptr<Context>(new Context(chipArgs));
}
-void NexusCommandHandler::customAfterLoad(Context *ctx) {}
+void NexusCommandHandler::customAfterLoad(Context *ctx)
+{
+ if (vm.count("pdc")) {
+ std::string filename = vm["pdc"].as<std::string>();
+ std::ifstream in(filename);
+ if (!in)
+ log_error("Failed to open input PDC file %s.\n", filename.c_str());
+ ctx->read_pdc(in);
+ }
+}
int main(int argc, char *argv[])
{
diff --git a/nexus/pdc.cc b/nexus/pdc.cc
index 6a571026..60cc511c 100644
--- a/nexus/pdc.cc
+++ b/nexus/pdc.cc
@@ -21,6 +21,8 @@
#include "log.h"
#include "nextpnr.h"
+#include <iterator>
+
NEXTPNR_NAMESPACE_BEGIN
struct TCLEntity
@@ -76,6 +78,8 @@ struct PDCParser
int lineno = 1;
Context *ctx;
+ PDCParser(const std::string &buf, Context *ctx) : buf(buf), ctx(ctx){};
+
inline bool eof() const { return pos == int(buf.size()); }
inline char peek() const { return buf.at(pos); }
@@ -193,10 +197,14 @@ struct PDCParser
const std::string &cmd = arg0.str;
if (cmd == "get_ports")
return cmd_get_ports(arguments);
+ else if (cmd == "get_cells")
+ return cmd_get_cells(arguments);
else if (cmd == "ldc_set_location")
return cmd_ldc_set_location(arguments);
else if (cmd == "ldc_set_port")
return cmd_ldc_set_port(arguments);
+ else
+ log_error("Unsupported PDC command '%s'\n", cmd.c_str());
}
std::vector<TCLValue> get_arguments()
@@ -208,6 +216,8 @@ struct PDCParser
auto result = evaluate(get_arguments());
NPNR_ASSERT(check_get(']'));
args.push_back(result);
+ } else if (peek() == ']') {
+ break;
} else {
args.push_back(get_str());
}
@@ -233,6 +243,23 @@ struct PDCParser
return ports;
}
+ TCLValue cmd_get_cells(const std::vector<TCLValue> &arguments)
+ {
+ std::vector<TCLEntity> cells;
+ for (int i = 1; i < int(arguments.size()); i++) {
+ auto &arg = arguments.at(i);
+ if (!arg.is_string)
+ log_error("get_cells expected string arguments (line %d)\n", lineno);
+ std::string s = arg.str;
+ if (s.at(0) == '-')
+ log_error("unsupported argument '%s' to get_cells (line %d)\n", s.c_str(), lineno);
+ IdString id = ctx->id(s);
+ if (ctx->cells.count(id))
+ cells.emplace_back(TCLEntity::ENTITY_CELL, id);
+ }
+ return cells;
+ }
+
TCLValue cmd_ldc_set_location(const std::vector<TCLValue> &arguments)
{
std::string site;
@@ -296,6 +323,23 @@ struct PDCParser
}
return std::string{};
}
+
+ void operator()()
+ {
+ while (!eof()) {
+ skip_blank(true);
+ auto args = get_arguments();
+ if (args.empty())
+ continue;
+ evaluate(args);
+ }
+ }
};
+void Arch::read_pdc(std::istream &in)
+{
+ std::string buf(std::istreambuf_iterator<char>(in), {});
+ PDCParser(buf, getCtx())();
+}
+
NEXTPNR_NAMESPACE_END