From 69b449c8759efa15f52add21b1c7f6dc1ceada3a Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 12 Oct 2020 11:19:31 +0100 Subject: nexus: Initial PDC parser integration Signed-off-by: David Shah --- nexus/arch.h | 2 +- nexus/main.cc | 12 +++++++++++- nexus/pdc.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++ 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> 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(), "name of chip database binary"); specific.add_options()("device", po::value(), "device name"); specific.add_options()("fasm", po::value(), "fasm file to write"); + specific.add_options()("pdc", po::value(), "physical constraints file"); return specific; } @@ -72,7 +73,16 @@ std::unique_ptr NexusCommandHandler::createContext(std::unordered_map(new Context(chipArgs)); } -void NexusCommandHandler::customAfterLoad(Context *ctx) {} +void NexusCommandHandler::customAfterLoad(Context *ctx) +{ + if (vm.count("pdc")) { + std::string filename = vm["pdc"].as(); + 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 + 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 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 &arguments) + { + std::vector 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 &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(in), {}); + PDCParser(buf, getCtx())(); +} + NEXTPNR_NAMESPACE_END -- cgit v1.2.3