Code cleanup
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
parent
60a6e8b070
commit
1f1bae3e23
@ -254,7 +254,6 @@ void TimingAnalyser::setup_port_domains()
|
|||||||
copy_domains(port, CellPortKey(pi.net->driver), true);
|
copy_domains(port, CellPortKey(pi.net->driver), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over ports and find domain paris
|
// Iterate over ports and find domain paris
|
||||||
for (auto port : topological_order) {
|
for (auto port : topological_order) {
|
||||||
auto &pd = ports.at(port);
|
auto &pd = ports.at(port);
|
||||||
@ -296,8 +295,8 @@ void TimingAnalyser::identify_related_domains() {
|
|||||||
|
|
||||||
// For each clock net identify all nets that can possibly drive it. Compute
|
// For each clock net identify all nets that can possibly drive it. Compute
|
||||||
// cumulative delays to each of them.
|
// cumulative delays to each of them.
|
||||||
std::function<void(const NetInfo*, dict<IdString, delay_t>&, delay_t, int32_t)> find_net_drivers =
|
std::function<void(const NetInfo*, dict<IdString, delay_t>&, delay_t)> find_net_drivers =
|
||||||
[&] (const NetInfo* ni, dict<IdString, delay_t>& drivers, delay_t delay_acc, int32_t level)
|
[&] (const NetInfo* ni, dict<IdString, delay_t>& drivers, delay_t delay_acc)
|
||||||
{
|
{
|
||||||
// Get driving cell and port
|
// Get driving cell and port
|
||||||
const CellInfo* cell = ni->driver.cell;
|
const CellInfo* cell = ni->driver.cell;
|
||||||
@ -305,30 +304,14 @@ void TimingAnalyser::identify_related_domains() {
|
|||||||
|
|
||||||
bool didGoUpstream = false;
|
bool didGoUpstream = false;
|
||||||
|
|
||||||
std::string indent (level, ' ');
|
|
||||||
|
|
||||||
log("%sout %s.%s\n", indent.c_str(), cell->name.str(ctx).c_str(), port.str(ctx).c_str());
|
|
||||||
|
|
||||||
// The cell has only one port
|
// The cell has only one port
|
||||||
if (cell->ports.size() == 1) {
|
if (cell->ports.size() == 1) {
|
||||||
drivers[ni->name] = delay_acc;
|
drivers[ni->name] = delay_acc;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count cell port types
|
|
||||||
size_t num_inp = 0;
|
|
||||||
size_t num_out = 0;
|
|
||||||
for (const auto& it : cell->ports) {
|
|
||||||
const auto& pi = it.second;
|
|
||||||
if (pi.type != PORT_IN) {
|
|
||||||
num_inp++;
|
|
||||||
} else {
|
|
||||||
num_out++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the driver timing class
|
// Get the driver timing class
|
||||||
int info_count = 0;
|
int info_count = 0;
|
||||||
auto timing_class = ctx->getPortTimingClass(cell, port, info_count);
|
auto timing_class = ctx->getPortTimingClass(cell, port, info_count);
|
||||||
|
|
||||||
// The driver must be a combinational output
|
// The driver must be a combinational output
|
||||||
@ -361,16 +344,13 @@ void TimingAnalyser::identify_related_domains() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log("%sinp %s.%s\n", indent.c_str(), cell->name.str(ctx).c_str(), pi.name.str(ctx).c_str());
|
|
||||||
|
|
||||||
// Recurse
|
// Recurse
|
||||||
find_net_drivers(pi.net, drivers, delay_acc + delay.maxDelay(), level+1);
|
find_net_drivers(pi.net, drivers, delay_acc + delay.maxDelay());
|
||||||
didGoUpstream = true;
|
didGoUpstream = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did not propagate upstream through the cell, mark the net as driver
|
// Did not propagate upstream through the cell, mark the net as driver
|
||||||
if (!didGoUpstream) {
|
if (!didGoUpstream) {
|
||||||
log("%send %s\n", indent.c_str(), ni->name.str(ctx).c_str());
|
|
||||||
drivers[ni->name] = delay_acc;
|
drivers[ni->name] = delay_acc;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -381,21 +361,28 @@ void TimingAnalyser::identify_related_domains() {
|
|||||||
|
|
||||||
const NetInfo* ni = ctx->nets.at(domain.key.clock).get();
|
const NetInfo* ni = ctx->nets.at(domain.key.clock).get();
|
||||||
dict<IdString, delay_t> drivers;
|
dict<IdString, delay_t> drivers;
|
||||||
find_net_drivers(ni, drivers, 0, 0);
|
find_net_drivers(ni, drivers, 0);
|
||||||
|
|
||||||
clock_drivers[domain.key.clock] = drivers;
|
clock_drivers[domain.key.clock] = drivers;
|
||||||
|
|
||||||
log("Clock '%s' can be driven by:\n", domain.key.clock.str(ctx).c_str());
|
if (ctx->debug) {
|
||||||
for (const auto& it : drivers) {
|
log("Clock '%s' can be driven by:\n", domain.key.clock.str(ctx).c_str());
|
||||||
log(" net '%s' delay %.3fns\n", it.first.str(ctx).c_str(), ctx->getDelayNS(it.second));
|
for (const auto& it : drivers) {
|
||||||
|
const NetInfo* net = ctx->nets.at(it.first).get();
|
||||||
|
log(" %s.%s delay %.3fns\n",
|
||||||
|
net->driver.cell->name.str(ctx).c_str(),
|
||||||
|
net->driver.port.str(ctx).c_str(),
|
||||||
|
ctx->getDelayNS(it.second)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify related clocks
|
// Identify related clocks. For simplicity do it both for A->B and B->A
|
||||||
|
// cases.
|
||||||
for (const auto& c1 : clock_drivers) {
|
for (const auto& c1 : clock_drivers) {
|
||||||
for (const auto& c2 : clock_drivers) {
|
for (const auto& c2 : clock_drivers) {
|
||||||
|
|
||||||
// Evident?
|
|
||||||
if (c1 == c2) {
|
if (c1 == c2) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -417,28 +404,25 @@ void TimingAnalyser::identify_related_domains() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG //
|
if (ctx->debug) {
|
||||||
log("Clocks '%s' and '%s'\n", c1.first.str(ctx).c_str(), c2.first.str(ctx).c_str());
|
|
||||||
for (const auto& it : common_drivers) {
|
|
||||||
|
|
||||||
// TEST //
|
log("Possible common driver(s) for clocks '%s' and '%s'\n",
|
||||||
const NetInfo* ni = ctx->nets.at(it).get();
|
c1.first.str(ctx).c_str(), c2.first.str(ctx).c_str());
|
||||||
const CellInfo* cell = ni->driver.cell;
|
|
||||||
const IdString port = ni->driver.port;
|
|
||||||
|
|
||||||
int info_count;
|
for (const auto& it : common_drivers) {
|
||||||
auto timing_class = ctx->getPortTimingClass(cell, port, info_count);
|
|
||||||
// TEST //
|
|
||||||
|
|
||||||
log(" net '%s', cell %s (%s), port %s, class%d\n",
|
const NetInfo* ni = ctx->nets.at(it).get();
|
||||||
it.str(ctx).c_str(),
|
const CellInfo* cell = ni->driver.cell;
|
||||||
cell->name.str(ctx).c_str(),
|
const IdString port = ni->driver.port;
|
||||||
cell->type.str(ctx).c_str(),
|
|
||||||
port.str(ctx).c_str(),
|
log(" net '%s', cell %s (%s), port %s\n",
|
||||||
int(timing_class)
|
it.str(ctx).c_str(),
|
||||||
);
|
cell->name.str(ctx).c_str(),
|
||||||
|
cell->type.str(ctx).c_str(),
|
||||||
|
port.str(ctx).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// DEBUG //
|
|
||||||
|
|
||||||
// If there is no single driver then consider the two clocks
|
// If there is no single driver then consider the two clocks
|
||||||
// unrelated.
|
// unrelated.
|
||||||
@ -1417,7 +1401,6 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
|
|||||||
dict<IdString, CriticalPath> clock_reports;
|
dict<IdString, CriticalPath> clock_reports;
|
||||||
std::vector<CriticalPath> xclock_reports;
|
std::vector<CriticalPath> xclock_reports;
|
||||||
dict<IdString, ClockFmax> clock_fmax;
|
dict<IdString, ClockFmax> clock_fmax;
|
||||||
dict<std::pair<IdString, IdString>, ClockFmax> xclock_fmax;
|
|
||||||
std::set<IdString> empty_clocks; // set of clocks with no interior paths
|
std::set<IdString> empty_clocks; // set of clocks with no interior paths
|
||||||
|
|
||||||
if (report_critical_paths) {
|
if (report_critical_paths) {
|
||||||
@ -1453,18 +1436,6 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
|
|||||||
if (a.clock == b.clock && a.clock != ctx->id("$async$"))
|
if (a.clock == b.clock && a.clock != ctx->id("$async$"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
double Fmax;
|
|
||||||
if (a.edge == b.edge)
|
|
||||||
Fmax = 1000 / ctx->getDelayNS(path.second.path_delay);
|
|
||||||
else
|
|
||||||
Fmax = 500 / ctx->getDelayNS(path.second.path_delay);
|
|
||||||
|
|
||||||
auto key = std::make_pair(a.clock, b.clock);
|
|
||||||
if (!xclock_fmax.count(key) || Fmax < xclock_fmax.at(key).achieved) {
|
|
||||||
xclock_fmax[key].achieved = Fmax;
|
|
||||||
xclock_fmax[key].constraint = 0.0f; // Will be filled later
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &crit_path = crit_paths.at(path.first).ports;
|
auto &crit_path = crit_paths.at(path.first).ports;
|
||||||
xclock_reports.push_back(build_critical_path_report(ctx, path.first, crit_path));
|
xclock_reports.push_back(build_critical_path_report(ctx, path.first, crit_path));
|
||||||
xclock_reports.back().period = path.second.path_period;
|
xclock_reports.back().period = path.second.path_period;
|
||||||
|
@ -495,10 +495,10 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
|
|||||||
} else if (cell->type == id_DCC) {
|
} else if (cell->type == id_DCC) {
|
||||||
if (fromPort == id_CLKI && toPort == id_CLKO) {
|
if (fromPort == id_CLKI && toPort == id_CLKO) {
|
||||||
// TODO: Use actual DCC delays
|
// TODO: Use actual DCC delays
|
||||||
delay.rise.min_delay = 1000;
|
delay.rise.min_delay = 1;
|
||||||
delay.rise.max_delay = 1000;
|
delay.rise.max_delay = 1;
|
||||||
delay.fall.min_delay = 1000;
|
delay.fall.min_delay = 1;
|
||||||
delay.fall.max_delay = 1000;
|
delay.fall.max_delay = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user