sdc: add_false_path to PathConstraint logic

This commit is contained in:
Rowan Goemans 2024-09-26 18:26:03 +02:00
parent 7f35139b8e
commit e7f8ca5ea6

View File

@ -28,6 +28,22 @@
NEXTPNR_NAMESPACE_BEGIN
bool is_startpoint(Context *ctx, const PortRef &port)
{
int clkInfoCount;
TimingPortClass cls = ctx->getPortTimingClass(port.cell, port.port, clkInfoCount);
return cls == TMG_STARTPOINT || cls == TMG_REGISTER_OUTPUT;
}
bool is_endpoint(Context *ctx, const PortRef &port)
{
int clkInfoCount;
TimingPortClass cls = ctx->getPortTimingClass(port.cell, port.port, clkInfoCount);
return cls == TMG_ENDPOINT || cls == TMG_REGISTER_OUTPUT;
}
struct SdcEntity
{
enum EntityType
@ -59,6 +75,23 @@ struct SdcEntity
return &ctx->ports.at(name);
}
PortRef get_pin(Context *ctx) const
{
if (type != ENTITY_PIN)
return PortRef{nullptr, IdString()};
CellInfo *cell = nullptr;
if (ctx->cells.count(name)) {
cell = ctx->cells.at(name).get();
} else {
return PortRef{nullptr, IdString()};
}
if (!cell->ports.count(pin))
return PortRef{nullptr, IdString()};
return PortRef{cell, pin};
}
NetInfo *get_net(Context *ctx) const
{
if (type == ENTITY_PIN) {
@ -251,6 +284,60 @@ struct SDCParser
return args;
}
// Parse an argument to -from/to into the path_constraint
void sdc_into_path_constraint(const SdcEntity &ety, bool is_from, PathConstraint &ct)
{
auto &target = is_from ? ct.from : ct.to;
auto test_port = is_from ? is_startpoint : is_endpoint;
std::string tartget_str = is_from ? "startpoint" : "endpoint";
if (ety.type == SdcEntity::ENTITY_PIN) {
auto port_ref = ety.get_pin(ctx);
if (test_port(ctx, port_ref) == false) {
log_error("\"%s.%s\" is not a timing %s (line %d)\n", port_ref.cell->name.c_str(ctx),
port_ref.port.c_str(ctx), tartget_str.c_str(), lineno);
}
target.emplace(CellPortKey(port_ref));
} else if (ety.type == SdcEntity::ENTITY_NET) {
auto net = ety.get_net(ctx);
if (is_from) {
auto port_ref = net->driver;
if (test_port(ctx, port_ref) == false) {
log_error("\"%s.%s\" is not a timing %s (line %d)\n", port_ref.cell->name.c_str(ctx),
port_ref.port.c_str(ctx), tartget_str.c_str(), lineno);
}
target.emplace(CellPortKey(port_ref));
} else {
for (const auto &usr : net->users) {
if (test_port(ctx, usr) == false) {
log_error("\"%s.%s\" is not a timing %s (line %d)\n", usr.cell->name.c_str(ctx),
usr.port.c_str(ctx), tartget_str.c_str(), lineno);
}
target.emplace(CellPortKey(usr));
}
}
} else if (ety.type == SdcEntity::ENTITY_PORT) {
auto ioport_ref = ety.get_port(ctx);
auto net = ioport_ref->net;
if (is_from) {
auto port_ref = net->driver;
if (test_port(ctx, port_ref) == false) {
log_error("\"%s.%s\" is not a timing %s (line %d)\n", port_ref.cell->name.c_str(ctx),
port_ref.port.c_str(ctx), tartget_str.c_str(), lineno);
}
target.emplace(CellPortKey(port_ref));
} else {
for (const auto &usr : net->users) {
if (test_port(ctx, usr) == false) {
log_error("\"%s.%s\" is not a timing %s (line %d)\n", usr.cell->name.c_str(ctx),
usr.port.c_str(ctx), tartget_str.c_str(), lineno);
}
target.emplace(CellPortKey(usr));
}
}
}
}
SdcValue cmd_get_nets(const std::vector<SdcValue> &arguments)
{
std::vector<SdcEntity> nets;
@ -318,7 +405,7 @@ struct SDCParser
if (pos == std::string::npos)
log_error("expected / in cell pin name '%s' (line %d)\n", s.c_str(), lineno);
pins.emplace_back(SdcEntity::ENTITY_PIN, ctx->id(s.substr(0, pos)), ctx->id(s.substr(pos + 1)));
if (pins.back().get_net(ctx) == nullptr) {
if (pins.back().get_pin(ctx).cell == nullptr) {
log_warning("cell pin '%s' not found\n", s.c_str());
pins.pop_back();
}
@ -369,8 +456,8 @@ struct SDCParser
SdcValue cmd_set_false_path(const std::vector<SdcValue> &arguments)
{
NetInfo *from = nullptr;
NetInfo *to = nullptr;
PathConstraint ct;
ct.exception = FalsePath{};
for (int i = 1; i < int(arguments.size()); i++) {
auto &arg = arguments.at(i);
@ -396,32 +483,17 @@ struct SDCParser
auto &ety = val.list.at(0);
NetInfo *net = nullptr;
if (ety.type == SdcEntity::ENTITY_PIN)
net = ety.get_net(ctx);
else if (ety.type == SdcEntity::ENTITY_NET)
net = ctx->nets.at(ety.name).get();
else if (ety.type == SdcEntity::ENTITY_PORT)
net = ctx->ports.at(ety.name).net;
else
log_error("set_false_path applies only to nets, cell pins, or IO ports (line %d)\n", lineno);
if (is_from) {
from = net;
} else {
to = net;
}
sdc_into_path_constraint(ety, is_from, ct);
}
}
if (from == nullptr) {
log_error("-from is required for set_false_path (line %d)\n", lineno);
} else if (to == nullptr) {
log_error("-to is required for set_false_path (line %d)\n", lineno);
if (ct.from.empty()) {
log_error("query specified in -from did not find any pins or ports (line %d)\n", lineno);
} else if (ct.to.empty()) {
log_error("query specified in -to did not find any pins or ports (line %d)\n", lineno);
}
log_warning("set_false_path from: %s, to: %s does not do anything(yet).\n", from->name.c_str(ctx),
to->name.c_str(ctx));
ctx->path_constraints.emplace_back(ct);
return std::string{};
}