| import re | |
| import tiles | |
| import json | |
| lc_input_re = re.compile(r'(J?[ABCDM]|CLK|LSR|CE)\d') | |
| lc_output_re = re.compile(r'J?[FQ]\d') | |
| def get_span(wire): | |
| if (wire.startswith("H") or wire.startswith("V")) and wire[1:3].isdigit(): | |
| return "span" + wire[2] + wire[0].lower() + wire[3].lower() | |
| return None | |
| def is_denorm(wire): | |
| if (wire.startswith("H06") or wire.startswith("V06")) and not wire.endswith("03"): | |
| return True | |
| if (wire.startswith("H02") or wire.startswith("V02")) and not wire.endswith("01"): | |
| return True | |
| return False | |
| def get_distance(a, b): | |
| ra, ca = tiles.pos_from_name(a, (126, 95), 0) | |
| rb, cb = tiles.pos_from_name(b, (126, 95), 0) | |
| return abs(ra-rb) + abs(ca-cb) | |
| def format_rel(a, b): | |
| ra, ca = tiles.pos_from_name(a, (126, 95), 0) | |
| rb, cb = tiles.pos_from_name(b, (126, 95), 0) | |
| rel = "" | |
| if rb < ra: | |
| rel += "n{}".format(ra-rb) | |
| elif rb > ra: | |
| rel += "s{}".format(rb-ra) | |
| if cb < ca: | |
| rel += "w{}".format(ca-cb) | |
| elif cb > ca: | |
| rel += "e{}".format(cb-ca) | |
| if rel != "": | |
| rel = "_" + rel | |
| return rel | |
| def get_pip_class(source, sink): | |
| source_loc, source_base = source.split("_", 1) | |
| sink_loc, sink_base = sink.split("_", 1) | |
| if is_denorm(source_base) or is_denorm(sink_base): | |
| return None | |
| if source_base.endswith("_SLICE") or source_base.startswith("MUX") or sink_base.endswith("_SLICE"): | |
| return "slice_internal" | |
| if sink_base.endswith("_EBR") or source_base.endswith("_EBR"): | |
| return "ebr_internal" | |
| if "TEST" in sink_base or "TEST" in source_base: | |
| return None | |
| if "ALU" in sink_base or "ALU" in source_base or "MULT" in sink_base or "MULT" in source_base or "PRADD" in sink_base: | |
| return "dsp_internal" | |
| if lc_input_re.match(sink_base): | |
| if lc_output_re.match(source_base): | |
| return "{}_to_{}".format(source_base[:-1].lower(), sink_base[:-1].lower()) | |
| elif get_span(source_base) is not None: | |
| return get_span(source_base) + "_to_" + sink_base[:-1].lower() + format_rel(source_loc, sink_loc) | |
| elif "HPBX" in source_base: | |
| return "global_to_" + sink_base[:-1].lower() | |
| else: | |
| return None | |
| elif get_span(sink_base) is not None: | |
| if lc_output_re.match(source_base): | |
| return source_base[:-1].lower() + "_to_" + get_span(sink_base) + format_rel(source_loc, sink_loc) | |
| elif get_span(source_base) is not None: | |
| return get_span(source_base) + "_to_" + get_span(sink_base) + format_rel(source_loc, sink_loc) | |
| elif "HPBX" in source_base: | |
| return "global_to_" + get_span(sink_base) | |
| elif "BOUNCE" in source_base: | |
| return None | |
| else: | |
| assert False, (source, sink) | |
| elif source_base.startswith("LSR") and sink_base.startswith("MUXLSR"): | |
| return "lsr_to_muxlsr" | |
| else: | |
| return None | |
| # Force these pip classes to have a 0 fanout adder for a better solution | |
| zero_fanout_classes = { | |
| "span0hr_to_ce", | |
| "span0vt_to_lsr", | |
| "span1he_to_m", | |
| "span1he_to_m_w1", | |
| "span1he_to_span2vn_n1", | |
| "span1he_to_span6he_e3", | |
| "span1hw_to_m", | |
| "span1hw_to_m_w1", | |
| "span1hw_to_span6hw_w4", | |
| "span1vn_to_span2vn_n1", | |
| "span1vn_to_span6he_e3", | |
| "span1vn_to_span6hw_w3", | |
| "span2he_to_lsr", | |
| "span2he_to_lsr_e1", | |
| "span2he_to_m", | |
| "span2he_to_span2vn_n1", | |
| "span2he_to_span2vn_n1e1", | |
| "span2he_to_span6he_e4", | |
| "span2hw_to_lsr", | |
| "span2hw_to_lsr_w1", | |
| "span2hw_to_m", | |
| "span2hw_to_m_w1", | |
| "span2hw_to_span2vn_n1", | |
| "span2hw_to_span2vn_n1w1", | |
| "span2hw_to_span6hw_w4", | |
| "span6vs_to_span1vs_s3", | |
| "span6vn_to_span6he_e3", | |
| "span6vn_to_span6he_n3e3", | |
| "span6vn_to_span6hw_w3", | |
| "span6vs_to_span2vn_s2", | |
| "span6vs_to_span6he_e3", | |
| "span6vs_to_span6hw_s3w3", | |
| "span1he_to_span1hw", | |
| "span1vn_to_m_s1", | |
| "span1vs_to_m", | |
| "span6he_to_span1he_e3", | |
| "span2vs_to_c", | |
| "span0hr_to_m", | |
| } | |
| def force_zero_fanout_pip(name): | |
| return name.startswith("jf") or name.startswith("jq") or "to_j" in name or name.startswith("q_to_") or name == "slice_internal" or name == "ebr_internal" or name in zero_fanout_classes | |
| # Force these pip classes to have zero delay to avoid linear dependence and unstable results | |
| zero_delay_classes = { | |
| "ebr_internal", | |
| "f_to_span1he_e1", | |
| "f_to_span1hw", | |
| "f_to_span1vs", | |
| "f_to_span2vn_n1", | |
| "f_to_span6hw_w3", | |
| "jf_to_span1he_e1", | |
| "jf_to_span1hw", | |
| "jf_to_span2vn_n1", | |
| "jq_to_span1hw", | |
| "jq_to_span6hw_w3", | |
| "lsr_to_muxlsr", | |
| "q_to_span1hw", | |
| "q_to_span1vs", | |
| "q_to_span2vn_n1", | |
| "q_to_span6he_e3", | |
| "q_to_span6hw_w3", | |
| "span0hl_to_c" | |
| "span0hl_to_ce", | |
| "span0hl_to_d", | |
| "span0hl_to_m", | |
| "span0vt_to_lsr", | |
| "span1he_to_span2vn_n1", | |
| "span1he_to_span6he_e3", | |
| "span1hw_to_span6hw_w4", | |
| "span1vn_to_span2vn_n1", | |
| "span1vn_to_span6he_e3", | |
| "span1vn_to_span6hw_w3", | |
| "span2he_to_lsr", | |
| "span2he_to_lsr_e1", | |
| "span2he_to_span2vn_n1", | |
| "span2he_to_span2vn_n1e1", | |
| "span2he_to_span6he_e4", | |
| "span2hw_to_lsr", | |
| "span2hw_to_lsr_w1", | |
| "span2hw_to_span2vn_n1", | |
| "span2hw_to_span2vn_n1w1", | |
| "span2hw_to_span6hw_w4", | |
| "span2vs_to_d", | |
| "span2vs_to_span0hr", | |
| "span2vs_to_span0vb", | |
| "span6vn_to_span1vs_n3", | |
| "span6vs_to_span1vs_s3", | |
| "span6vs_to_span2vn_s2", | |
| "span6vs_to_span6hw_w3", | |
| "span6vn_to_span6he_e3", | |
| "span6vn_to_span6he_n3e3", | |
| "span6vn_to_span6hw_w3", | |
| "span6vs_to_span2vn_s2", | |
| "span6vs_to_span6he_e3", | |
| "span6vs_to_span6hw_s3w3", | |
| "span1he_to_span1hw", | |
| "span6he_to_span1he_e3", | |
| } | |
| def force_zero_delay_pip(name): | |
| return name in zero_delay_classes |