Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Himbaechel xilinx : XDC improvements #1375

Merged
merged 6 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion common/kernel/basectx.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ struct BaseCtx

NetInfo *getNetByAlias(IdString alias) const
{
return nets.count(alias) ? nets.at(alias).get() : nets.at(net_aliases.at(alias)).get();
if(nets.count(alias) > 0) return nets.at(alias).get();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you run a make clangformat on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now done.

if(net_aliases.count(alias) == 0) return nullptr;
return nets.at(net_aliases.at(alias)).get();
}

// Intended to simplify Python API
Expand Down
115 changes: 93 additions & 22 deletions himbaechel/uarch/xilinx/xdc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ void XilinxImpl::parse_xdc(const std::string &filename)
std::ifstream in(filename);
if (!in)
log_error("failed to open XDC file '%s'\n", filename.c_str());
log_info("Parsing XDC file...\n");
std::string line;
std::string linebuf;
int lineno = 0;
unsigned num_errors = 0;

auto isempty = [](const std::string &str) {
return std::all_of(str.begin(), str.end(), [](char c) { return std::isspace(c); });
Expand Down Expand Up @@ -109,8 +111,10 @@ void XilinxImpl::parse_xdc(const std::string &filename)

auto get_nets = [&](std::string str) {
std::vector<NetInfo *> tgt_nets;
if (str.empty() || str.front() != '[')
log_error("failed to parse target (on line %d)\n", lineno);
if (str.empty())
return tgt_nets;
if (str.front() != '[' || str.back() != ']')
log_error("failed to parse target '%s' (on line %d)\n", str.c_str(), lineno);
str = str.substr(1, str.size() - 2);
auto split = split_to_args(str, false);
if (split.size() < 1)
Expand All @@ -119,8 +123,19 @@ void XilinxImpl::parse_xdc(const std::string &filename)
log_error("targets other than 'get_ports' or 'get_nets' are not supported (on line %d)\n", lineno);
if (split.size() < 2)
log_error("failed to parse target (on line %d)\n", lineno);
IdString netname = ctx->id(split.at(1));
str = strip_quotes(split.at(1));
if (str.empty())
return tgt_nets;
IdString netname = ctx->id(str);
NetInfo *maybe_net = ctx->getNetByAlias(netname);
if (maybe_net != nullptr) {
tgt_nets.push_back(maybe_net);
return tgt_nets;
}
// Also test the lowercase variant, for better interoperability with synthesis tools
boost::algorithm::to_lower(str);
netname = ctx->id(str);
maybe_net = ctx->getNetByAlias(netname);
if (maybe_net != nullptr)
tgt_nets.push_back(maybe_net);
return tgt_nets;
Expand All @@ -139,63 +154,119 @@ void XilinxImpl::parse_xdc(const std::string &filename)
if (arguments.empty())
continue;
std::string &cmd = arguments.front();

if (cmd == "set_property") {
std::vector<std::pair<std::string, std::string>> arg_pairs;
if (arguments.size() != 4)
log_error("expected four arguments to 'set_property' (on line %d)\n", lineno);
if (arguments.size() < 4) {
log_nonfatal_error("expected at least four arguments to 'set_property' (on line %d)\n", lineno);
num_errors++;
goto nextline;
}
else if (arguments.at(1) == "-dict") {
std::vector<std::string> dict_args = split_to_args(strip_quotes(arguments.at(2)), false);
if ((dict_args.size() % 2) != 0)
log_error("expected an even number of argument for dictionary (on line %d)\n", lineno);
if ((dict_args.size() % 2) != 0) {
log_nonfatal_error("expected an even number of argument for dictionary (on line %d)\n", lineno);
num_errors++;
goto nextline;
}
arg_pairs.reserve(dict_args.size() / 2);
for (int cursor = 0; cursor + 1 < int(dict_args.size()); cursor += 2) {
arg_pairs.emplace_back(std::move(dict_args.at(cursor)), std::move(dict_args.at(cursor + 1)));
}
} else {
arg_pairs.emplace_back(std::move(arguments.at(1)), std::move(arguments.at(2)));
}
if (arg_pairs.size() == 1 && arg_pairs.front().first == "INTERNAL_VREF") // get_iobanks not supported
// Warning : ug835 has lowercase example, so probably supporting lowercase too is needed
if (arg_pairs.size() == 1 && arg_pairs.front().first == "INTERNAL_VREF") { // get_iobanks not supported
log_warning("INTERNAL_VREF isn't supported, ignoring (on line %d)\n", lineno);
continue;
}
if (arguments.at(3).size() > 2 && arguments.at(3) == "[current_design]") {
log_warning("[current_design] isn't supported, ignoring (on line %d)\n", lineno);
continue;
}
std::vector<CellInfo *> dest = get_cells(arguments.at(3));
for (auto c : dest)
for (const auto &pair : arg_pairs)
c->attrs[ctx->id(pair.first)] = std::string(pair.second);
// All remaining arguments are supposed to designate cells
std::vector<CellInfo *> dest;
for (int cursor = 3; cursor < int(arguments.size()); cursor++) {
std::vector<CellInfo *> dest_loc = get_cells(arguments.at(cursor));
if (dest_loc.empty())
log_warning("found set_property with no cells matching '%s' (on line %d)\n", arguments.at(cursor).c_str(), lineno);
dest.insert(dest.end(), dest_loc.begin(), dest_loc.end());
}
for (auto c : dest) {
for (const auto &pair : arg_pairs) {
IdString id_prop = ctx->id(pair.first);
if (ctx->debug)
log_info("applying property '%s' = '%s' to cell '%s' (on line %d)\n", pair.first.c_str(), pair.second.c_str(), c->name.c_str(ctx), lineno);
if(c->attrs.find(id_prop) != c->attrs.end()) {
log_nonfatal_error("found multiple properties '%s' for cell '%s' (on line %d)\n", pair.first.c_str(), c->name.c_str(ctx), lineno);
num_errors++;
}
c->attrs[id_prop] = std::string(pair.second);
}
}
} else if (cmd == "create_clock") {
double period = 0;
bool got_period = false;
int cursor = 1;
for (cursor = 1; cursor < int(arguments.size()); cursor++) {
std::string opt = arguments.at(cursor);
if (opt == "-add")
;
else if (opt == "-name" || opt == "-waveform")
if (opt == "-add") {
log_warning("ignoring unsupported XDC option '%s' (on line %d)\n", opt.c_str(), lineno);
}
else if (opt == "-name" || opt == "-waveform") {
log_warning("ignoring unsupported XDC option '%s' (on line %d)\n", opt.c_str(), lineno);
cursor++;
}
else if (opt == "-period") {
cursor++;
period = std::stod(arguments.at(cursor));
got_period = true;
} else
}
else
break;
}
if (!got_period)
log_error("found create_clock without period (on line %d)", lineno);
std::vector<NetInfo *> dest = get_nets(arguments.at(cursor));
if (!got_period) {
log_nonfatal_error("found create_clock without period (on line %d)\n", lineno);
num_errors++;
goto nextline;
}
// All remaining arguments are supposed to designate ports/nets
std::vector<NetInfo *> dest;
if (cursor >= int(arguments.size()))
log_warning("found create_clock without designated nets (on line %d)\n", lineno);
for ( ; cursor < (int)arguments.size(); cursor++) {
std::vector<NetInfo *> dest_loc = get_nets(arguments.at(cursor));
if (dest_loc.empty())
log_warning("found create_clock with no nets matching '%s' (on line %d)\n", arguments.at(cursor).c_str(), lineno);
dest.insert(dest.end(), dest_loc.begin(), dest_loc.end());
}
for (auto n : dest) {
if (ctx->debug)
log_info("applying clock period constraint on net '%s' (on line %d)\n", n->name.c_str(ctx), lineno);
if (n->clkconstr.get() != nullptr) {
log_nonfatal_error("found multiple clock constraints on net '%s' (on line %d)\n", n->name.c_str(ctx), lineno);
num_errors++;
}
n->clkconstr = std::unique_ptr<ClockConstraint>(new ClockConstraint);
n->clkconstr->period = DelayPair(ctx->getDelayFromNS(period));
n->clkconstr->high = DelayPair(ctx->getDelayFromNS(period / 2));
n->clkconstr->low = DelayPair(ctx->getDelayFromNS(period / 2));
}
} else {
log_info("ignoring unsupported XDC command '%s' (on line %d)\n", cmd.c_str(), lineno);
log_warning("ignoring unsupported XDC command '%s' (on line %d)\n", cmd.c_str(), lineno);
}

nextline:
; // Phony statement to have something legal after the label
}
if (!isempty(linebuf)) {
log_nonfatal_error("unexpected end of XDC file\n");
num_errors++;
}
if (num_errors > 0) {
log_error("Stopping the program after %u errors found in XDC file\n", num_errors);
}
if (!isempty(linebuf))
log_error("unexpected end of XDC file\n");
}

NEXTPNR_NAMESPACE_END