nexus: Initial PDC parser integration

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2020-10-12 11:19:31 +01:00
parent 12013b4c1f
commit 69b449c875
3 changed files with 56 additions and 2 deletions

View File

@ -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;

View File

@ -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[])
{

View File

@ -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