mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-26 18:45:34 +00:00
add some comments to timeest
This commit is contained in:
parent
28c7f202ca
commit
9c9a0e3e45
1 changed files with 25 additions and 4 deletions
|
@ -61,6 +61,8 @@ struct EstimateSta {
|
||||||
samplers.push_back(std::make_pair(cell, bit));
|
samplers.push_back(std::make_pair(cell, bit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we include a discount factor for cells that can be implemented using carry chain logic
|
||||||
|
// and to account for the AIG model not being balanced
|
||||||
int cell_type_factor(IdString type)
|
int cell_type_factor(IdString type)
|
||||||
{
|
{
|
||||||
if (type.in(ID($gt), ID($ge), ID($lt), ID($le), ID($add), ID($sub),
|
if (type.in(ID($gt), ID($ge), ID($lt), ID($le), ID($add), ID($sub),
|
||||||
|
@ -81,11 +83,13 @@ struct EstimateSta {
|
||||||
{
|
{
|
||||||
log("Domain %s\n", log_signal(clk));
|
log("Domain %s\n", log_signal(clk));
|
||||||
|
|
||||||
|
// first, we collect launch and sample points and convert the combinational logic to AIG
|
||||||
std::vector<Cell *> combinational;
|
std::vector<Cell *> combinational;
|
||||||
|
|
||||||
for (auto cell : m->cells()) {
|
for (auto cell : m->cells()) {
|
||||||
SigSpec launch, sample;
|
SigSpec launch, sample;
|
||||||
if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
|
if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
|
||||||
|
// collect launch and sample points for FF cell
|
||||||
FfData ff(nullptr, cell);
|
FfData ff(nullptr, cell);
|
||||||
if (!ff.has_clk) {
|
if (!ff.has_clk) {
|
||||||
log_warning("Ignoring unsupported storage element '%s' (%s)\n",
|
log_warning("Ignoring unsupported storage element '%s' (%s)\n",
|
||||||
|
@ -107,6 +111,7 @@ struct EstimateSta {
|
||||||
} else if (cell->type == ID($scopeinfo)) {
|
} else if (cell->type == ID($scopeinfo)) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
// find or build AIG model of combinational cell
|
||||||
auto fingerprint = std::make_pair(cell->type, cell->parameters);
|
auto fingerprint = std::make_pair(cell->type, cell->parameters);
|
||||||
if (!aigs.count(fingerprint)) {
|
if (!aigs.count(fingerprint)) {
|
||||||
aigs.emplace(fingerprint, Aig(cell));
|
aigs.emplace(fingerprint, Aig(cell));
|
||||||
|
@ -121,11 +126,14 @@ struct EstimateSta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// since we're now taking reference into `aigs`, we can no longer modify it
|
||||||
|
// and thus have to fill `cell_aigs` in a separate loop
|
||||||
for (auto cell : combinational) {
|
for (auto cell : combinational) {
|
||||||
auto fingerprint = std::make_pair(cell->type, cell->parameters);
|
auto fingerprint = std::make_pair(cell->type, cell->parameters);
|
||||||
cell_aigs.emplace(cell, &aigs.at(fingerprint));
|
cell_aigs.emplace(cell, &aigs.at(fingerprint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collect launch and sample points for memory cells
|
||||||
for (auto &mem : Mem::get_all_memories(m)) {
|
for (auto &mem : Mem::get_all_memories(m)) {
|
||||||
for (auto &rd : mem.rd_ports) {
|
for (auto &rd : mem.rd_ports) {
|
||||||
if (!rd.clk_enable) {
|
if (!rd.clk_enable) {
|
||||||
|
@ -143,6 +151,9 @@ struct EstimateSta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now we toposort the combinational logic
|
||||||
|
|
||||||
|
// each toposort node is either a SigBit or a pair of Cell * / AigNode *
|
||||||
TopoSort<std::tuple<SigBit, Cell *, AigNode *>> topo;
|
TopoSort<std::tuple<SigBit, Cell *, AigNode *>> topo;
|
||||||
|
|
||||||
auto desc_aig = [&](Cell *cell, AigNode &node) {
|
auto desc_aig = [&](Cell *cell, AigNode &node) {
|
||||||
|
@ -152,6 +163,7 @@ struct EstimateSta {
|
||||||
return std::make_tuple(sigmap(bit), (Cell *) NULL, (AigNode *) NULL);
|
return std::make_tuple(sigmap(bit), (Cell *) NULL, (AigNode *) NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// collect edges of the AIG graph
|
||||||
for (auto cell : combinational) {
|
for (auto cell : combinational) {
|
||||||
assert(cell_aigs.count(cell));
|
assert(cell_aigs.count(cell));
|
||||||
Aig &aig = *cell_aigs.at(cell);
|
Aig &aig = *cell_aigs.at(cell);
|
||||||
|
@ -186,11 +198,15 @@ struct EstimateSta {
|
||||||
if (!topo.sort())
|
if (!topo.sort())
|
||||||
log_error("Module '%s' contains combinational loops", log_id(m));
|
log_error("Module '%s' contains combinational loops", log_id(m));
|
||||||
|
|
||||||
|
// now we determine how long it takes for signals to stabilize
|
||||||
|
|
||||||
|
// `levels` records the time after a clock edge after which a signal is stable
|
||||||
dict<std::tuple<SigBit, Cell *, AigNode *>, arrivalint> levels;
|
dict<std::tuple<SigBit, Cell *, AigNode *>, arrivalint> levels;
|
||||||
|
|
||||||
for (auto node : topo.sorted)
|
for (auto node : topo.sorted)
|
||||||
levels[node] = INF_PAST;
|
levels[node] = INF_PAST;
|
||||||
|
|
||||||
|
// launch points are at 0 by definition
|
||||||
for (auto pair : launchers)
|
for (auto pair : launchers)
|
||||||
levels[desc_sig(pair.second)] = 0;
|
levels[desc_sig(pair.second)] = 0;
|
||||||
|
|
||||||
|
@ -200,22 +216,26 @@ struct EstimateSta {
|
||||||
Cell *cell = std::get<1>(node);
|
Cell *cell = std::get<1>(node);
|
||||||
Aig &aig = *cell_aigs.at(cell);
|
Aig &aig = *cell_aigs.at(cell);
|
||||||
if (!aig_node->portname.empty()) {
|
if (!aig_node->portname.empty()) {
|
||||||
|
// for a cell port, copy `levels` value from port bit
|
||||||
SigBit bit = cell->getPort(aig_node->portname)[aig_node->portbit];
|
SigBit bit = cell->getPort(aig_node->portname)[aig_node->portbit];
|
||||||
levels[node] = levels[desc_sig(bit)];
|
levels[node] = levels[desc_sig(bit)];
|
||||||
} else if (aig_node->left_parent < 0 && aig_node->right_parent < 0) {
|
} else if (aig_node->left_parent < 0 && aig_node->right_parent < 0) {
|
||||||
// constant, nothing to do
|
// constant, nothing to do
|
||||||
} else {
|
} else {
|
||||||
|
// for each AIG node, find maximum of parents and add a cell-specific delay
|
||||||
int left = levels[desc_aig(cell, aig.nodes[aig_node->left_parent])];
|
int left = levels[desc_aig(cell, aig.nodes[aig_node->left_parent])];
|
||||||
int right = levels[desc_aig(cell, aig.nodes[aig_node->right_parent])];
|
int right = levels[desc_aig(cell, aig.nodes[aig_node->right_parent])];
|
||||||
levels[node] = (std::max(left, right) + cell_type_factor(cell->type));
|
levels[node] = (std::max(left, right) + cell_type_factor(cell->type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy `levels` value to any output ports
|
||||||
for (auto &oport : aig_node->outports) {
|
for (auto &oport : aig_node->outports) {
|
||||||
levels[desc_sig(cell->getPort(oport.first)[oport.second])] = levels[node];
|
levels[desc_sig(cell->getPort(oport.first)[oport.second])] = levels[node];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now find the length of the critical path (slowest path in the design)
|
||||||
arrivalint crit = INF_PAST;
|
arrivalint crit = INF_PAST;
|
||||||
for (auto pair : samplers)
|
for (auto pair : samplers)
|
||||||
if (levels[desc_sig(pair.second)] > crit)
|
if (levels[desc_sig(pair.second)] > crit)
|
||||||
|
@ -232,6 +252,7 @@ struct EstimateSta {
|
||||||
// some compile-time errors related to hashing
|
// some compile-time errors related to hashing
|
||||||
dict<std::tuple<SigBit, Cell *, AigNode *>, bool> critical;
|
dict<std::tuple<SigBit, Cell *, AigNode *>, bool> critical;
|
||||||
|
|
||||||
|
// actually find one critical path, or all such paths if requested
|
||||||
for (auto pair : samplers) {
|
for (auto pair : samplers) {
|
||||||
if (levels[desc_sig(pair.second)] == crit) {
|
if (levels[desc_sig(pair.second)] == crit) {
|
||||||
critical[desc_sig(pair.second)] = true;
|
critical[desc_sig(pair.second)] = true;
|
||||||
|
@ -240,6 +261,7 @@ struct EstimateSta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// walk backwards through toposorted nodes and set critical flag on nodes in critical path
|
||||||
for (auto it = topo.sorted.rbegin(); it != topo.sorted.rend(); it++) {
|
for (auto it = topo.sorted.rbegin(); it != topo.sorted.rend(); it++) {
|
||||||
auto node = *it;
|
auto node = *it;
|
||||||
AigNode *aig_node = std::get<2>(node);
|
AigNode *aig_node = std::get<2>(node);
|
||||||
|
@ -248,22 +270,20 @@ struct EstimateSta {
|
||||||
Aig &aig = *cell_aigs.at(cell);
|
Aig &aig = *cell_aigs.at(cell);
|
||||||
|
|
||||||
for (auto &oport : aig_node->outports) {
|
for (auto &oport : aig_node->outports) {
|
||||||
//levels[desc_sig(cell->getPort(oport.first)[oport.second])] = levels[node];
|
|
||||||
if (critical.count(desc_sig(cell->getPort(oport.first)[oport.second])))
|
if (critical.count(desc_sig(cell->getPort(oport.first)[oport.second])))
|
||||||
critical[node] = true;
|
critical[node] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aig_node->portname.empty()) {
|
if (!aig_node->portname.empty()) {
|
||||||
SigBit bit = cell->getPort(aig_node->portname)[aig_node->portbit];
|
SigBit bit = cell->getPort(aig_node->portname)[aig_node->portbit];
|
||||||
//levels[node] = levels[desc_sig(bit)];
|
|
||||||
if (critical.count(node))
|
if (critical.count(node))
|
||||||
critical[desc_sig(bit)] = true;
|
critical[desc_sig(bit)] = true;
|
||||||
} else if (aig_node->left_parent < 0 && aig_node->right_parent < 0) {
|
} else if (aig_node->left_parent < 0 && aig_node->right_parent < 0) {
|
||||||
// constant, nothing to do
|
// constant, nothing to do
|
||||||
} else {
|
} else {
|
||||||
|
// figure out which parent is on the critical path
|
||||||
auto left = desc_aig(cell, aig.nodes[aig_node->left_parent]);
|
auto left = desc_aig(cell, aig.nodes[aig_node->left_parent]);
|
||||||
auto right = desc_aig(cell, aig.nodes[aig_node->right_parent]);
|
auto right = desc_aig(cell, aig.nodes[aig_node->right_parent]);
|
||||||
//levels[node] = (std::max(left, right) + 1);
|
|
||||||
int crit_input_lvl = levels[node] - cell_type_factor(cell->type);
|
int crit_input_lvl = levels[node] - cell_type_factor(cell->type);
|
||||||
if (critical.count(node)) {
|
if (critical.count(node)) {
|
||||||
bool left_critical = (levels[left] == crit_input_lvl);
|
bool left_critical = (levels[left] == crit_input_lvl);
|
||||||
|
@ -284,6 +304,7 @@ struct EstimateSta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finally print the path we found
|
||||||
SigPool bits_to_select;
|
SigPool bits_to_select;
|
||||||
pool<IdString> to_select;
|
pool<IdString> to_select;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue