diff options
author | Clifford Wolf <clifford@clifford.at> | 2016-01-15 18:25:02 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2016-01-15 18:25:02 +0100 |
commit | 0cfb6eed910091584a1bbd5cc5a35c6634e1c55e (patch) | |
tree | 9112042a77c3977fba84d492821969847616ba2d /icetime | |
parent | d939d1b92f6e1a46aa8a573d3f7d19cc8e342950 (diff) | |
download | icestorm-0cfb6eed910091584a1bbd5cc5a35c6634e1c55e.tar.gz icestorm-0cfb6eed910091584a1bbd5cc5a35c6634e1c55e.tar.bz2 icestorm-0cfb6eed910091584a1bbd5cc5a35c6634e1c55e.zip |
icetime progress
Diffstat (limited to 'icetime')
-rw-r--r-- | icetime/.gitignore | 1 | ||||
-rw-r--r-- | icetime/Makefile | 10 | ||||
-rw-r--r-- | icetime/icetime.cc | 372 | ||||
-rw-r--r-- | icetime/mktest.py | 1 | ||||
-rw-r--r-- | icetime/timings.py | 49 |
5 files changed, 312 insertions, 121 deletions
diff --git a/icetime/.gitignore b/icetime/.gitignore index 8fee1fd..fd24fa8 100644 --- a/icetime/.gitignore +++ b/icetime/.gitignore @@ -1,4 +1,5 @@ icetime +timings.inc test[0-9]* *.d *.o diff --git a/icetime/Makefile b/icetime/Makefile index 7edfc6c..31f1ac5 100644 --- a/icetime/Makefile +++ b/icetime/Makefile @@ -6,6 +6,12 @@ all: icetime icetime: icetime.o +icetime.o: icetime.cc timings.inc + +timings.inc: timings.py + python3 timings.py > timings.inc.new + mv timings.inc.new timings.inc + install: all mkdir -p $(DESTDIR)$(PREFIX)/bin cp icetime $(DESTDIR)$(PREFIX)/bin/icetime @@ -24,7 +30,7 @@ test0 test1 test2 test3 test4 test5 test6 test7 test8 test9: icetime yosys $@.ys run0 run1 run2 run3 run4 run5 run6 run7 run8 run9: icetime - ./icetime -P tq144 -p $(subst run,test,$@).pcf $(subst run,test,$@).asc $(subst run,test,$@)_out.v + ./icetime -t -P tq144 -p $(subst run,test,$@).pcf $(subst run,test,$@).asc $(subst run,test,$@)_out.v show0 show1 show2 show3 show4 show5 show6 show7 show8 show9: icetime bash show.sh $(subst show,test,$@) @@ -35,7 +41,7 @@ test: test0 test1 test2 test3 test4 test5 test6 test7 test8 test9 show: show0 show1 show2 show3 show4 show5 show6 show7 show8 show9 clean: - rm -f icetime *.o *.d + rm -f icetime timings.inc *.o *.d rm -rf test[0-9]* -include *.d diff --git a/icetime/icetime.cc b/icetime/icetime.cc index 09a4ca4..ad11831 100644 --- a/icetime/icetime.cc +++ b/icetime/icetime.cc @@ -31,6 +31,7 @@ #define MAX_SPAN_HACK 1 FILE *fin, *fout; +bool verbose = false; std::string config_device, selected_package; std::vector<std::vector<std::string>> config_tile_type; @@ -460,28 +461,43 @@ void read_chipdb() std::pair<int, int>(x, y); } - -#if 1 - for (int net : used_nets) + if (verbose) { - printf("// NET %d:\n", net); - for (auto seg : net_to_segments[net]) - printf("// SEG %d %d %s\n", seg.x, seg.y, seg.name.c_str()); - for (auto other : net_buffers[net]) - printf("// BUFFER %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, - connection_pos[std::pair<int, int>(net, other)].second, other); - for (auto other : net_rbuffers[net]) - printf("// RBUFFER %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, - connection_pos[std::pair<int, int>(net, other)].second, other); - for (auto other : net_routing[net]) - printf("// ROUTE %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, - connection_pos[std::pair<int, int>(net, other)].second, other); + for (int net : used_nets) + { + printf("// NET %d:\n", net); + for (auto seg : net_to_segments[net]) + printf("// SEG %d %d %s\n", seg.x, seg.y, seg.name.c_str()); + for (auto other : net_buffers[net]) + printf("// BUFFER %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, + connection_pos[std::pair<int, int>(net, other)].second, other); + for (auto other : net_rbuffers[net]) + printf("// RBUFFER %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, + connection_pos[std::pair<int, int>(net, other)].second, other); + for (auto other : net_routing[net]) + printf("// ROUTE %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, + connection_pos[std::pair<int, int>(net, other)].second, other); + } } -#endif } bool is_primary(std::string cell_name, std::string out_port) { + auto cell_type = netlist_cell_types[cell_name]; + + if (cell_type == "SB_RAM40_4K") + return true; + + if (cell_type == "LogicCell40" && out_port == "lcout") + { + // SEQ_MODE = "4'bX..."; + bool dff_enable = netlist_cell_params[cell_name]["SEQ_MODE"][3] == '1'; + return dff_enable; + } + + if (cell_type == "PRE_IO") + return true; + return false; } @@ -556,7 +572,7 @@ const std::set<std::string> &get_inports(std::string cell_type) inports_map["ICE_CARRY_IN_MUX"] = { "carryinitin" }; inports_map["LogicCell40"] = { "clk", "carryin", "in0", "in1", "in2", "in3", "sr", "ce" }; - inports_map["PRE_IO"] = { "INPUTCLK", "OUTPUTCLK", "LATCHINPUTVALUE", "CLOCKENABLE", "OUTPUTENABLE", "DOUT1", "DOUT0" }; + inports_map["PRE_IO"] = { "INPUTCLK", "OUTPUTCLK", "LATCHINPUTVALUE", "CLOCKENABLE", "OUTPUTENABLE", "DOUT1", "DOUT0", "PADIN" }; inports_map["SB_RAM40_4K"] = { "RCLK", "RCLKE", "RE", "WCLK", "WCLKE", "WE" }; @@ -569,6 +585,8 @@ const std::set<std::string> &get_inports(std::string cell_type) inports_map["SB_RAM40_4K"].insert(stringf("RADDR[%d]", i)); inports_map["SB_RAM40_4K"].insert(stringf("WADDR[%d]", i)); } + + inports_map["INTERCONN"] = { "I" }; } if (inports_map.count(cell_type) == 0) { @@ -579,9 +597,21 @@ const std::set<std::string> &get_inports(std::string cell_type) return inports_map.at(cell_type); } +#include "timings.inc" + double get_delay(std::string cell_type, std::string in_port, std::string out_port) { - return 1.0; + if (cell_type == "INTERCONN") + return 0; + + if (config_device == "1k") + return get_delay_1k(cell_type, in_port, out_port); + + if (config_device == "8k") + return get_delay_8k(cell_type, in_port, out_port); + + fprintf(stderr, "No built-in timing database for '%s' devices!\n", config_device.c_str()); + exit(1); } struct TimingAnalysis @@ -589,6 +619,9 @@ struct TimingAnalysis // net_driver[<net_name>] = { <cell_name>, <cell_port> } std::map<std::string, std::pair<std::string, std::string>> net_driver; + // net_max_setup[<net_name>] = { <setup_time>, <cell_name>, <cell_port> } + std::map<std::string, std::tuple<double, std::string, std::string>> net_max_setup; + // net_max_path_parent[<net_name>] = { <parent_net>, <cell_name>, <inport>, <outport>, <delay> } std::map<std::string, std::tuple<std::string, std::string, std::string, std::string, double>> net_max_path_parent; @@ -609,20 +642,28 @@ struct TimingAnalysis auto &driver_cell = net_driver.at(net).first; auto &driver_port = net_driver.at(net).second; + auto &driver_type = netlist_cell_types.at(driver_cell); if (is_primary(driver_cell, driver_port)) { - net_max_path_delay[net] = 0; + net_max_path_delay[net] = get_delay(driver_type, "*clkedge*", driver_port); return 0; } - auto &driver_type = netlist_cell_types.at(driver_cell); - auto &driver_inputs = get_inports(driver_type); - - for (auto &inport : driver_inputs) + for (auto &inport : get_inports(driver_type)) { - if (inport == "clk" || inport == "INPUTCLK" || inport == "OUTPUTCLK") + if (inport == "clk" || inport == "INPUTCLK" || inport == "OUTPUTCLK" || inport == "PADIN") continue; + if (driver_type == "LogicCell40" && driver_port == "carryout") { + if (inport == "in0" || inport == "in3") + continue; + } + + if (driver_type == "LogicCell40" && (driver_port == "ltout" || driver_port == "lcout")) { + if (inport == "carryin") + continue; + } + std::string *in_net = &netlist_cell_ports.at(driver_cell).at(inport); while (net_assignments.count(*in_net)) in_net = &net_assignments.at(*in_net); @@ -657,8 +698,20 @@ struct TimingAnalysis if (net_name == "") continue; - if (get_inports(netlist_cell_types.at(cell_name)).count(port_name)) + auto &cell_type = netlist_cell_types.at(cell_name); + + if (get_inports(cell_type).count(port_name)) { + std::string n = net_name; + while (1) { + double setup_time = get_delay(cell_type, port_name, "*setup*"); + if (setup_time >= std::get<0>(net_max_setup[n])) + net_max_setup[n] = std::make_tuple(setup_time, cell_name, port_name); + if (net_assignments.count(n) == 0) + break; + n = net_assignments.at(n); + } continue; + } net_driver[net_name] = { cell_name, port_name }; all_nets.insert(net_name); @@ -667,7 +720,7 @@ struct TimingAnalysis global_max_path_delay = 0; for (auto &net : all_nets) { - double d = calc_net_max_path_delay(net); + double d = calc_net_max_path_delay(net) + std::get<0>(net_max_setup[net]); if (d > global_max_path_delay) { global_max_path_delay = d; global_max_path_net = net; @@ -675,18 +728,47 @@ struct TimingAnalysis } } - void report() + void report(std::string n = std::string()) { std::vector<std::string> lines; std::set<std::string> visited_nets; - std::string n = global_max_path_net; + if (n.empty()) { + n = global_max_path_net; + printf("Report for longest path:\n\n"); + } else { + printf("Requested report for net %s:\n\n", n.c_str()); + } + + if (net_max_path_delay.count(n) == 0) { + printf("Net not found: %s\n", n.c_str()); + return; + } + + double delay = net_max_path_delay.at(n); + + int logic_levels = 0; bool last_line = true; + auto &user = net_max_setup[n]; + + 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); + } + while (1) { - if (net_max_path_parent.count(n) == 0) { + 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())); + + 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(), + driver_type.c_str(), driver_port.c_str(), calc_net_max_path_delay(n))); break; } @@ -697,8 +779,10 @@ 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++; + } lines.push_back(stringf(" %s (%s) %s -> %s: %.3f ns", std::get<1>(entry).c_str(), netlist_cell_types.at(std::get<1>(entry)).c_str(), std::get<2>(entry).c_str(), @@ -711,6 +795,11 @@ struct TimingAnalysis for (int i = int(lines.size())-1; i >= 0; i--) printf("%s\n", lines[i].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); + printf("\n"); } }; @@ -1517,27 +1606,28 @@ void make_interconn(const net_segment_t &src, FILE *graph_f) worker.build_net_tree(src.net); worker.build_seg_tree(src); -#if 1 - printf("// INTERCONN %d %d %s %d\n", src.x, src.y, src.name.c_str(), src.net); - std::function<void(int,int)> print_net_tree = [&] (int net, int indent) { - printf("// %*sNET_TREE %d\n", indent, "", net); - for (int child : worker.net_tree.at(net)) - print_net_tree(child, indent+2); - }; - std::function<void(const net_segment_t&,int,bool)> print_seg_tree = [&] (const net_segment_t &seg, int indent, bool chain) { - printf("// %*sSEG_TREE %d %d %s %d\n", indent, chain ? "`" : "", seg.x, seg.y, seg.name.c_str(), seg.net); - if (worker.seg_tree.count(seg)) { - auto &children = worker.seg_tree.at(seg); - bool child_chain = children.size() == 1; - for (auto &child : children) - print_seg_tree(child, child_chain ? (chain ? indent : indent+1) : indent+2, child_chain); - } else { - printf("// %*s DEAD_END (!)\n", indent, ""); - } - }; - print_net_tree(src.net, 2); - print_seg_tree(src, 2, false); -#endif + if (verbose) + { + printf("// INTERCONN %d %d %s %d\n", src.x, src.y, src.name.c_str(), src.net); + std::function<void(int,int)> print_net_tree = [&] (int net, int indent) { + printf("// %*sNET_TREE %d\n", indent, "", net); + for (int child : worker.net_tree.at(net)) + print_net_tree(child, indent+2); + }; + std::function<void(const net_segment_t&,int,bool)> print_seg_tree = [&] (const net_segment_t &seg, int indent, bool chain) { + printf("// %*sSEG_TREE %d %d %s %d\n", indent, chain ? "`" : "", seg.x, seg.y, seg.name.c_str(), seg.net); + if (worker.seg_tree.count(seg)) { + auto &children = worker.seg_tree.at(seg); + bool child_chain = children.size() == 1; + for (auto &child : children) + print_seg_tree(child, child_chain ? (chain ? indent : indent+1) : indent+2, child_chain); + } else { + printf("// %*s DEAD_END (!)\n", indent, ""); + } + }; + print_net_tree(src.net, 2); + print_seg_tree(src, 2, false); + } for (auto &seg : worker.target_segs) { net_assignments[net_name(seg.net)] = seg_name(seg); @@ -1564,13 +1654,26 @@ void help(const char *cmd) printf(" write a graphviz description of the interconnect tree\n"); printf(" that includes the given net to 'icetime_graph.dot'.\n"); printf("\n"); + printf(" -t\n"); + printf(" print a timing estimate (based on topological timing\n"); + printf(" analysis)\n"); + printf("\n"); + printf(" -T <net_name>\n"); + printf(" print a timing estimate for the specified net\n"); + printf("\n"); + printf(" -v\n"); + printf(" verbose mode (print all interconnect trees)\n"); + printf("\n"); exit(1); } int main(int argc, char **argv) { + bool print_timing = false; + std::vector<std::string> print_timing_nets; + int opt; - while ((opt = getopt(argc, argv, "p:P:g:")) != -1) + while ((opt = getopt(argc, argv, "p:P:g:tT:v")) != -1) { switch (opt) { @@ -1584,6 +1687,15 @@ int main(int argc, char **argv) case 'g': graph_nets.insert(atoi(optarg)); break; + case 't': + print_timing = true; + break; + case 'T': + print_timing_nets.push_back(optarg); + break; + case 'v': + verbose = true; + break; default: help(argv[0]); } @@ -1595,7 +1707,7 @@ int main(int argc, char **argv) perror("Can't open input file"); exit(1); } - fout = stdout; + fout = nullptr; } else if (optind+2 == argc) { fin = fopen(argv[optind], "r"); @@ -1603,10 +1715,14 @@ int main(int argc, char **argv) perror("Can't open input file"); exit(1); } - fout = fopen(argv[optind+1], "w"); - if (fout == nullptr) { - perror("Can't open output file"); - exit(1); + if (std::string(argv[optind+1]) == "-") { + fout = stdout; + } else { + fout = fopen(argv[optind+1], "w"); + if (fout == nullptr) { + perror("Can't open output file"); + exit(1); + } } } else help(argv[0]); @@ -1731,84 +1847,102 @@ int main(int argc, char **argv) extra_wires.insert(port.second); } - fprintf(fout, "module chip ("); - const char *io_sep = ""; - for (auto io : io_names) { - fprintf(fout, "%s%s", io_sep, io.c_str()); - io_sep = ", "; - } - fprintf(fout, ");\n"); + if (fout != NULL) + { + fprintf(fout, "module chip ("); + const char *io_sep = ""; + for (auto io : io_names) { + fprintf(fout, "%s%s", io_sep, io.c_str()); + io_sep = ", "; + } + fprintf(fout, ");\n"); - for (int net : declared_nets) - fprintf(fout, " wire net_%d;\n", net); + for (int net : declared_nets) + fprintf(fout, " wire net_%d;\n", net); - for (auto net : extra_wires) - fprintf(fout, " wire %s;\n", net.c_str()); - - for (auto &it : net_assignments) - fprintf(fout, " assign %s = %s;\n", it.first.c_str(), it.second.c_str()); + for (auto net : extra_wires) + fprintf(fout, " wire %s;\n", net.c_str()); - fprintf(fout, " wire gnd, vcc;\n"); - fprintf(fout, " GND gnd_cell (.Y(gnd));\n"); - fprintf(fout, " VCC vcc_cell (.Y(vcc));\n"); + for (auto &it : net_assignments) + fprintf(fout, " assign %s = %s;\n", it.first.c_str(), it.second.c_str()); - for (auto &str : extra_vlog) - fprintf(fout, "%s", str.c_str()); + fprintf(fout, " wire gnd, vcc;\n"); + fprintf(fout, " GND gnd_cell (.Y(gnd));\n"); + fprintf(fout, " VCC vcc_cell (.Y(vcc));\n"); - for (auto it : netlist_cell_types) - { - const char *sep = ""; - fprintf(fout, " %s ", it.second.c_str()); - if (netlist_cell_params.count(it.first)) { - fprintf(fout, "#("); - for (auto port : netlist_cell_params[it.first]) { - fprintf(fout, "%s\n .%s(%s)", sep, port.first.c_str(), port.second.c_str()); - sep = ","; + for (auto &str : extra_vlog) + fprintf(fout, "%s", str.c_str()); + + for (auto it : netlist_cell_types) + { + const char *sep = ""; + fprintf(fout, " %s ", it.second.c_str()); + if (netlist_cell_params.count(it.first)) { + fprintf(fout, "#("); + for (auto port : netlist_cell_params[it.first]) { + fprintf(fout, "%s\n .%s(%s)", sep, port.first.c_str(), port.second.c_str()); + sep = ","; + } + fprintf(fout, "\n ) "); + sep = ""; } - fprintf(fout, "\n ) "); - sep = ""; - } - fprintf(fout, "%s (", it.first.c_str()); - std::map<std::string, std::vector<std::string>> multibit_ports; + fprintf(fout, "%s (", it.first.c_str()); + std::map<std::string, std::vector<std::string>> multibit_ports; - for (auto port : netlist_cell_ports[it.first]) - { - size_t open_bracket_pos = port.first.find('['); - if (open_bracket_pos != std::string::npos) { - std::string base_name = port.first.substr(0, open_bracket_pos); - int bit_index = atoi(port.first.substr(open_bracket_pos+1).c_str()); - if (multibit_ports[base_name].size() <= bit_index) - multibit_ports[base_name].resize(bit_index+1); - multibit_ports[base_name][bit_index] = port.second; - continue; + for (auto port : netlist_cell_ports[it.first]) + { + size_t open_bracket_pos = port.first.find('['); + if (open_bracket_pos != std::string::npos) { + std::string base_name = port.first.substr(0, open_bracket_pos); + int bit_index = atoi(port.first.substr(open_bracket_pos+1).c_str()); + if (multibit_ports[base_name].size() <= bit_index) + multibit_ports[base_name].resize(bit_index+1); + multibit_ports[base_name][bit_index] = port.second; + continue; + } + + fprintf(fout, "%s\n .%s(%s)", sep, port.first.c_str(), port.second.c_str()); + sep = ","; } - fprintf(fout, "%s\n .%s(%s)", sep, port.first.c_str(), port.second.c_str()); - sep = ","; - } + for (auto it : multibit_ports) + { + fprintf(fout, "%s\n .%s({", sep, it.first.c_str()); + sep = ","; - for (auto it : multibit_ports) - { - fprintf(fout, "%s\n .%s({", sep, it.first.c_str()); - sep = ","; - - const char *sepsep = ""; - for (int i = int(it.second.size())-1; i >= 0; i--) { - std::string wire_name = it.second[i]; - fprintf(fout, "%s%s", sepsep, wire_name.c_str()); - sepsep = ", "; + const char *sepsep = ""; + for (int i = int(it.second.size())-1; i >= 0; i--) { + std::string wire_name = it.second[i]; + fprintf(fout, "%s%s", sepsep, wire_name.c_str()); + sepsep = ", "; + } + fprintf(fout, "})"); } - fprintf(fout, "})"); + + fprintf(fout, "\n );\n"); } - fprintf(fout, "\n );\n"); + fprintf(fout, "endmodule\n"); } - fprintf(fout, "endmodule\n"); - - TimingAnalysis ta; - ta.report(); + if (print_timing || !print_timing_nets.empty()) + { + printf("\n"); + printf("icetime topological timing analysis report\n"); + printf("==========================================\n"); + printf("\n"); + + TimingAnalysis ta; + for (auto &n : print_timing_nets) + ta.report(n); + ta.report(); + } + else + { + TimingAnalysis ta; + printf("// Timing estimate: %.2f ns (%.2f MHz)\n", ta.global_max_path_delay, 1000.0 / ta.global_max_path_delay); + } return 0; } diff --git a/icetime/mktest.py b/icetime/mktest.py index b56a12f..ec33ec3 100644 --- a/icetime/mktest.py +++ b/icetime/mktest.py @@ -148,6 +148,7 @@ with open("%s.ys" % sys.argv[1], "w") as f: print("equiv_status -assert", file=f) assert os.system("bash ../icefuzz/icecube.sh %s.v" % sys.argv[1]) == 0 +os.rename("%s.tmp/outputs/netlist/top_timing.rpt" % sys.argv[1], "%s.rpt" % sys.argv[1]) os.rename("%s.v" % sys.argv[1], "%s_in.v" % sys.argv[1]) if False: diff --git a/icetime/timings.py b/icetime/timings.py new file mode 100644 index 0000000..e559338 --- /dev/null +++ b/icetime/timings.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +import re + +print("// auto-generated by timings.py from ../icefuzz/timings_*.txt") + +def timings_to_c(chip, f): + print("") + print("double get_delay_%s(std::string cell_type, std::string in_port, std::string out_port)" % chip) + print("{") + + in_cell = False + + for line in f: + fields = line.split() + if len(fields) == 0: + continue + + if fields[0] == "CELL": + if in_cell: + print(" }") + print(" if (cell_type == \"%s\") {" % fields[1]) + in_cell = True + + if fields[0] == "SETUP": + inport = fields[1].split(":")[1] + delay = max([0 if s == "*" else float(s) / 1000 for s in fields[3].split(":")]) + print(" if (in_port == \"%s\" && out_port == \"*setup*\") return %.5f;" % (inport, delay)) + + if fields[0] == "IOPATH": + if fields[1].startswith("posedge:") or fields[1].startswith("negedge:"): + fields[1] = "*clkedge*" + delay = max([0 if s == "*" else float(s) / 1000 for s in fields[3].split(":") + fields[4].split(":")]) + print(" if (in_port == \"%s\" && out_port == \"%s\") return %.5f;" % (fields[1], fields[2], delay)) + + + if in_cell: + print(" }") + print(" if (in_port == \"*clkedge*\"|| out_port == \"*setup*\") return 0;") + print(" fprintf(stderr, \"Unable to resolve delay for path %s -> %s in cell type %s!\\n\", in_port.c_str(), out_port.c_str(), cell_type.c_str());") + print(" exit(1);") + print("}") + +with open("../icefuzz/timings_1k.txt", "r") as f: + timings_to_c("1k", f); + +with open("../icefuzz/timings_8k.txt", "r") as f: + timings_to_c("8k", f); + |