From 8467e955e59616969a05e87edef88bbf6cff7662 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 15 Jan 2016 22:23:01 +0100 Subject: icetime progress --- icetime/icetime.cc | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 4 deletions(-) (limited to 'icetime') diff --git a/icetime/icetime.cc b/icetime/icetime.cc index ad11831..e014855 100644 --- a/icetime/icetime.cc +++ b/icetime/icetime.cc @@ -30,6 +30,9 @@ #define MAX_SPAN_HACK 1 +// add this number of ns as estimation for clock distribution mismatch +#define GLOBAL_CLK_DIST_JITTER 0.1 + FILE *fin, *fout; bool verbose = false; @@ -41,6 +44,8 @@ std::map pin_names; std::set> extra_bits; std::set io_names; +std::map net_symbols; + struct net_segment_t { int x, y, net; @@ -240,6 +245,11 @@ void read_config() int y = atoi(strtok(nullptr, " \t\r\n")); std::tuple key(b, x, y); extra_bits.insert(key); + } else + if (!strcmp(tok, ".sym")) { + int net = atoi(strtok(nullptr, " \t\r\n")); + const char *name = strtok(nullptr, " \t\r\n"); + net_symbols[net] = name; } } else if (line_nr >= 0) @@ -645,7 +655,7 @@ struct TimingAnalysis auto &driver_type = netlist_cell_types.at(driver_cell); if (is_primary(driver_cell, driver_port)) { - net_max_path_delay[net] = get_delay(driver_type, "*clkedge*", driver_port); + net_max_path_delay[net] = get_delay(driver_type, "*clkedge*", driver_port) + GLOBAL_CLK_DIST_JITTER; return 0; } @@ -747,27 +757,59 @@ struct TimingAnalysis double delay = net_max_path_delay.at(n); + std::string net_sym; + std::vector> sym_list; + std::map outsym_list; + int logic_levels = 0; bool last_line = true; auto &user = net_max_setup[n]; - if (!std::get<1>(user).empty()) { + if (!std::get<1>(user).empty()) + { lines.push_back(stringf(" %s (%s) %s [setup]: %.3f ns", std::get<1>(user).c_str(), netlist_cell_types.at(std::get<1>(user)).c_str(), std::get<2>(user).c_str(), std::get<0>(user))); delay += std::get<0>(user); + + auto &inports = get_inports(netlist_cell_types.at(std::get<1>(user))); + + for (auto &it : netlist_cell_ports.at(std::get<1>(user))) + { + if (inports.count(it.first) || it.second.empty()) + continue; + + int netidx; + char dummy_ch; + if (sscanf(it.second.c_str(), "net_%d%c", &netidx, &dummy_ch) == 1 && net_symbols.count(netidx)) + outsym_list[it.first] = net_symbols[netidx]; + } } while (1) { + int netidx; + char dummy_ch; + + if (sscanf(n.c_str(), "net_%d%c", &netidx, &dummy_ch) == 1 && net_symbols.count(netidx)) { + sym_list.push_back(std::make_pair(calc_net_max_path_delay(n), net_symbols[netidx])); + if (net_sym.empty() || net_sym[0] == '$') + net_sym = sym_list.back().second; + } + if (net_max_path_parent.count(n) == 0) { lines.push_back(stringf("%10.3f ns %s", calc_net_max_path_delay(n), n.c_str())); + if (!net_sym.empty()) { + lines.back() += stringf(" (%s)", net_sym.c_str()); + net_sym.clear(); + } + auto &driver_cell = net_driver.at(n).first; auto &driver_port = net_driver.at(n).second; auto &driver_type = netlist_cell_types.at(driver_cell); - lines.push_back(stringf(" %s (%s) [clkedge] -> %s: %.3f ns", driver_cell.c_str(), + lines.push_back(stringf(" %s (%s) [clk] -> %s: %.3f ns", driver_cell.c_str(), driver_type.c_str(), driver_port.c_str(), calc_net_max_path_delay(n))); break; } @@ -779,9 +821,15 @@ struct TimingAnalysis auto &entry = net_max_path_parent.at(n); - if (last_line || netlist_cell_types.at(std::get<1>(entry)) == "LogicCell40") { + if (last_line || netlist_cell_types.at(std::get<1>(entry)) == "LogicCell40") + { lines.push_back(stringf("%10.3f ns %s", calc_net_max_path_delay(n), n.c_str())); logic_levels++; + + if (!net_sym.empty()) { + lines.back() += stringf(" (%s)", net_sym.c_str()); + net_sym.clear(); + } } lines.push_back(stringf(" %s (%s) %s -> %s: %.3f ns", std::get<1>(entry).c_str(), @@ -796,6 +844,31 @@ struct TimingAnalysis for (int i = int(lines.size())-1; i >= 0; i--) printf("%s\n", lines[i].c_str()); + if (!sym_list.empty() || !outsym_list.empty()) + { + printf("\n"); + printf("Resolvable net names on path:\n"); + + std::string last_net; + double first_time, last_time; + + for (int i = int(sym_list.size())-1; i >= 0; i--) { + if (last_net != sym_list[i].second) { + if (!last_net.empty()) + printf("%10.3f ns ..%7.3f ns %s\n", first_time, last_time, last_net.c_str()); + first_time = sym_list[i].first; + last_net = sym_list[i].second; + } + last_time = sym_list[i].first; + } + + if (!last_net.empty()) + printf("%10.3f ns ..%7.3f ns %s\n", first_time, last_time, last_net.c_str()); + + for (auto &it : outsym_list) + printf("%23s -> %s\n", it.first.c_str(), it.second.c_str()); + } + printf("\n"); printf("Total number of logic levels: %d\n", logic_levels); printf("Total path delay: %.2f ns (%.2f MHz)\n", delay, 1000.0 / delay); @@ -1932,6 +2005,8 @@ int main(int argc, char **argv) printf("icetime topological timing analysis report\n"); printf("==========================================\n"); printf("\n"); + printf("Warning: This timing analysis report is an estimate!\n"); + printf("\n"); TimingAnalysis ta; for (auto &n : print_timing_nets) -- cgit v1.2.3