blob: 6bd53e14d730b631eea70757d0d3146fbc4bc9ac [file] [log] [blame]
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