3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-11-05 13:56:04 +00:00
This commit is contained in:
Martin Povišer 2025-11-03 11:57:27 +00:00 committed by GitHub
commit 7f145c9d98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 52 additions and 15 deletions

View file

@ -39,7 +39,8 @@ const arrivalint INF_PAST = std::numeric_limits<arrivalint>::min();
struct EstimateSta { struct EstimateSta {
SigMap sigmap; SigMap sigmap;
Module *m; Module *m;
SigBit clk; std::optional<SigBit> clk;
bool top_port_endpoints = false;
dict<std::pair<RTLIL::IdString, dict<RTLIL::IdString, RTLIL::Const>>, Aig> aigs; dict<std::pair<RTLIL::IdString, dict<RTLIL::IdString, RTLIL::Const>>, Aig> aigs;
dict<Cell *, Aig *> cell_aigs; dict<Cell *, Aig *> cell_aigs;
@ -73,15 +74,18 @@ struct EstimateSta {
} }
// TODO: ignores clock polarity // TODO: ignores clock polarity
EstimateSta(Module *m, SigBit clk) EstimateSta(Module *m, std::optional<SigBit> clk, bool top_port_endpoints)
: sigmap(m), m(m), clk(clk) : sigmap(m), m(m), clk(clk), top_port_endpoints(top_port_endpoints)
{ {
sigmap.apply(clk); if (clk.has_value())
sigmap.apply(*clk);
} }
void run() void run()
{ {
log("Domain %s\n", log_signal(clk)); log("\nModule %s\n", log_id(m));
if (clk.has_value())
log("Domain %s\n", log_signal(*clk));
// first, we collect launch and sample points and convert the combinational logic to AIG // first, we collect launch and sample points and convert the combinational logic to AIG
std::vector<Cell *> combinational; std::vector<Cell *> combinational;
@ -151,6 +155,22 @@ struct EstimateSta {
} }
} }
// add top module port launching/sampling, if requested
if (top_port_endpoints) {
SigSpec all_inputs, all_outputs;
for (auto port_id : m->ports) {
Wire *port = m->wire(port_id);
if (port->port_input && !port->port_output) {
all_inputs.append(port);
} else if (port->port_output && !port->port_input) {
all_outputs.append(port);
} else if (port->port_output && port->port_input) {
log_warning("Ignoring bi-directional port %s\n", log_id(port));
}
}
add_seq(nullptr, all_inputs, all_outputs);
}
// now we toposort the combinational logic // now we toposort the combinational logic
// each toposort node is either a SigBit or a pair of Cell * / AigNode * // each toposort node is either a SigBit or a pair of Cell * / AigNode *
@ -360,7 +380,7 @@ struct TimeestPass : Pass {
log("\n"); log("\n");
log(" timeest [-clk <clk_signal>] [options] [selection]\n"); log(" timeest [-clk <clk_signal>] [options] [selection]\n");
log("\n"); log("\n");
log("Estimate the critical path in clock domain <clk_signal> by counting AIG nodes.\n"); log("Estimate the critical path by counting AIG nodes.\n");
log("\n"); log("\n");
log(" -all_paths\n"); log(" -all_paths\n");
log(" Print or select nodes from all critical paths instead of focusing on\n"); log(" Print or select nodes from all critical paths instead of focusing on\n");
@ -374,7 +394,8 @@ struct TimeestPass : Pass {
{ {
log_header(d, "Executing TIMEEST pass. (estimate timing)\n"); log_header(d, "Executing TIMEEST pass. (estimate timing)\n");
std::string clk; std::string clk_name;
bool clk_domain_specified = false;
bool all_paths = false; bool all_paths = false;
bool select = false; bool select = false;
size_t argidx; size_t argidx;
@ -388,26 +409,30 @@ struct TimeestPass : Pass {
continue; continue;
} }
if (args[argidx] == "-clk" && argidx + 1 < args.size()) { if (args[argidx] == "-clk" && argidx + 1 < args.size()) {
clk = args[++argidx]; clk_domain_specified = true;
clk_name = args[++argidx];
continue; continue;
} }
break; break;
} }
extra_args(args, argidx, d); extra_args(args, argidx, d);
if (clk.empty())
log_cmd_error("No -clk argument provided\n");
if (select && d->selected_modules().size() > 1) if (select && d->selected_modules().size() > 1)
log_cmd_error("The -select option operates on a single selected module\n"); log_cmd_error("The -select option operates on a single selected module\n");
for (auto m : d->selected_modules()) { for (auto m : d->selected_modules()) {
if (!m->wire(RTLIL::escape_id(clk))) { std::optional<SigBit> clk;
log_warning("No domain '%s' in module %s\n", clk, log_id(m));
continue; if (clk_domain_specified) {
if (!m->wire(RTLIL::escape_id(clk_name))) {
log_warning("No domain '%s' in module %s\n", clk, log_id(m));
continue;
}
clk = SigBit(m->wire(RTLIL::escape_id(clk_name)), 0);
} }
EstimateSta sta(m, SigBit(m->wire(RTLIL::escape_id(clk)), 0)); EstimateSta sta(m, clk, /*top_port_endpoints=*/ !clk_domain_specified);
sta.all_paths = all_paths; sta.all_paths = all_paths;
sta.select = select; sta.select = select;
sta.run(); sta.run();

12
tests/various/timeest.ys Normal file
View file

@ -0,0 +1,12 @@
read_verilog <<EOF
module top(input [3:0] a, input [3:0] b, output [7:0] y);
assign y = a * b;
endmodule
module top2(input [7:0] a, input [7:0] b, output [15:0] y);
assign y = a * b;
endmodule
EOF
synth
timeest