mirror of https://github.com/openXC7/prjxray.git
Added support for differential standards.
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
parent
e8b05c6b27
commit
c396b0f9cc
|
|
@ -32,6 +32,7 @@ clean:
|
|||
@rm -rf features.csv
|
||||
@rm -rf results.json
|
||||
@rm -rf unknown_bits.jl
|
||||
@rm -rf iobs-$(VIVADO_PART).csv
|
||||
|
||||
iobs-$(VIVADO_PART).csv: ../dump_iobs.tcl
|
||||
env VIVADO_PART=$(VIVADO_PART) $(XRAY_VIVADO) -mode batch -source ../dump_iobs.tcl -nojournal -log dump_iobs.log
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ def run():
|
|||
|
||||
iosettings = "{}.I{}.{}".format(iostandard, drive, slew)
|
||||
|
||||
is_diff = "DIFF" in iostandard
|
||||
|
||||
for feature in sorted(features):
|
||||
I = [f[1] for f in result["input"] if f[0] == feature and f[1]]
|
||||
O = [
|
||||
|
|
@ -139,14 +141,15 @@ def run():
|
|||
if f[0] == feature and f[1]
|
||||
]
|
||||
|
||||
s = [
|
||||
"I" if len(I) > 0 else "",
|
||||
"O" if len(O) > 0 else "",
|
||||
"T" if len(T) > 0 else "",
|
||||
"U" if len(U) > 0 else "",
|
||||
]
|
||||
s = "".join(
|
||||
[
|
||||
"I" if len(I) > 0 else "",
|
||||
"O" if len(O) > 0 else "",
|
||||
"T" if len(T) > 0 else "",
|
||||
"U" if len(U) > 0 else "",
|
||||
])
|
||||
|
||||
csv_data[iosettings][feature] = "".join(s)
|
||||
csv_data[iosettings][feature] = s
|
||||
|
||||
# Write header
|
||||
line = [""] + sorted(features)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ IOBUF_NOT_ALLOWED = [
|
|||
'SSTL18_I',
|
||||
]
|
||||
|
||||
DIFF_MAP = {
|
||||
'SSTL135': 'DIFF_SSTL135',
|
||||
}
|
||||
|
||||
|
||||
def gen_iosettings():
|
||||
"""
|
||||
|
|
@ -92,10 +96,22 @@ def gen_iosettings():
|
|||
SLEWS = ("SLOW", "FAST")
|
||||
|
||||
for iostandard in IOSTANDARDS:
|
||||
|
||||
# Single ended
|
||||
for drive in DRIVES[iostandard]:
|
||||
for slew in SLEWS:
|
||||
yield {"iostandard": iostandard, "drive": drive, "slew": slew}
|
||||
|
||||
# Differential
|
||||
if iostandard in DIFF_MAP:
|
||||
for drive in DRIVES[iostandard]:
|
||||
for slew in SLEWS:
|
||||
yield {
|
||||
"iostandard": DIFF_MAP[iostandard],
|
||||
"drive": drive,
|
||||
"slew": slew
|
||||
}
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
|
|
@ -113,9 +129,13 @@ def run():
|
|||
design_index = 0
|
||||
while True:
|
||||
|
||||
num_inp = 0
|
||||
num_out = 0
|
||||
num_ino = 0
|
||||
|
||||
# Generate clock regions
|
||||
region_data = []
|
||||
for region in iob_sites:
|
||||
for region in sorted(list(iob_sites.keys())):
|
||||
|
||||
# Get IO settings
|
||||
try:
|
||||
|
|
@ -125,15 +145,36 @@ def run():
|
|||
|
||||
# Get sites
|
||||
sites = [
|
||||
site["name"] for site in iob_sites[region] if site["is_bonded"]
|
||||
(
|
||||
site["name"],
|
||||
site["type"],
|
||||
) for site in iob_sites[region] if site["is_bonded"]
|
||||
and not site["is_vref"] and "SING" not in site["tile"]
|
||||
]
|
||||
if not len(sites):
|
||||
continue
|
||||
|
||||
# Select 5 random sites (IBUF, IBUF, OBUF, OBUF, IOBUF)
|
||||
used_sites = random.sample(sites, 5)
|
||||
unused_sites = list(set(sites) - set(used_sites))
|
||||
# Differential / single ended
|
||||
if "DIFF" in iosettings["iostandard"]:
|
||||
|
||||
# Select 5 random sites (IBUFDS, IBUFDS, OBUFDS, OBUFDS, IOBUFDS)
|
||||
site_names = [s[0] for s in sites if s[1] == "IOB33M"]
|
||||
used_sites = random.sample(site_names, 5)
|
||||
unused_sites = list(set(site_names) - set(used_sites))
|
||||
|
||||
num_inp += 4
|
||||
num_out += 4
|
||||
num_ino += 2
|
||||
|
||||
else:
|
||||
# Select 5 random sites (IBUF, IBUF, OBUF, OBUF, IOBUF)
|
||||
site_names = [s[0] for s in sites]
|
||||
used_sites = random.sample(site_names, 5)
|
||||
unused_sites = list(set(site_names) - set(used_sites))
|
||||
|
||||
num_inp += 2
|
||||
num_out += 2
|
||||
num_ino += 1
|
||||
|
||||
# Store data
|
||||
region_data.append(
|
||||
|
|
@ -145,16 +186,14 @@ def run():
|
|||
"output": used_sites[2:4],
|
||||
"inout": used_sites[4:5],
|
||||
})
|
||||
print(region, iosettings)
|
||||
print("----")
|
||||
|
||||
# No more
|
||||
if len(region_data) == 0:
|
||||
break
|
||||
|
||||
# Generate the design
|
||||
num_inp = len(region_data) * 2
|
||||
num_out = len(region_data) * 2
|
||||
num_ino = len(region_data)
|
||||
|
||||
verilog = """
|
||||
module top (
|
||||
input wire [{num_inp}:0] inp,
|
||||
|
|
@ -163,8 +202,13 @@ module top (
|
|||
);
|
||||
""".format(num_inp=num_inp - 1, num_ino=num_ino - 1, num_out=num_out - 1)
|
||||
|
||||
inp_idx = 0
|
||||
out_idx = 0
|
||||
ino_idx = 0
|
||||
|
||||
for i, data in enumerate(region_data):
|
||||
|
||||
is_diff = "DIFF" in data["iosettings"]["iostandard"]
|
||||
use_ino = data["iosettings"]["iostandard"] not in IOBUF_NOT_ALLOWED
|
||||
|
||||
iostandard = data["iosettings"]["iostandard"]
|
||||
|
|
@ -186,16 +230,32 @@ module top (
|
|||
"obuf_0_loc": data["output"][0],
|
||||
"obuf_1_loc": data["output"][1],
|
||||
"iobuf_loc": data["inout"][0],
|
||||
"inp_0": 2 * i + 0,
|
||||
"inp_1": 2 * i + 1,
|
||||
"out_0": 2 * i + 0,
|
||||
"out_1": 2 * i + 1,
|
||||
"ino": i,
|
||||
"inp_0_p": inp_idx,
|
||||
"inp_0_n": inp_idx + 2,
|
||||
"inp_1_p": inp_idx + 1,
|
||||
"inp_1_n": inp_idx + 3,
|
||||
"out_0_p": out_idx,
|
||||
"out_0_n": out_idx + 2,
|
||||
"out_1_p": out_idx + 1,
|
||||
"out_1_n": out_idx + 3,
|
||||
"ino_p": ino_idx,
|
||||
"ino_n": ino_idx + 1,
|
||||
"ibuf_param_str": ibuf_param_str,
|
||||
"obuf_param_str": obuf_param_str,
|
||||
}
|
||||
|
||||
verilog += """
|
||||
if is_diff:
|
||||
inp_idx += 4
|
||||
out_idx += 4
|
||||
ino_idx += 2
|
||||
else:
|
||||
inp_idx += 2
|
||||
out_idx += 2
|
||||
ino_idx += 1
|
||||
|
||||
# Single ended
|
||||
if not is_diff:
|
||||
verilog += """
|
||||
|
||||
// {region}
|
||||
wire inp_0_{region};
|
||||
|
|
@ -208,41 +268,41 @@ module top (
|
|||
wire ino_t_{region};
|
||||
""".format(**keys)
|
||||
|
||||
verilog += """
|
||||
verilog += """
|
||||
(* KEEP, DONT_TOUCH, LOC="{ibuf_0_loc}" *)
|
||||
IBUF # ({ibuf_param_str}) ibuf_0_{region} (
|
||||
.I(inp[{inp_0}]),
|
||||
.I(inp[{inp_0_p}]),
|
||||
.O(inp_0_{region})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{ibuf_1_loc}" *)
|
||||
IBUF # ({ibuf_param_str}) ibuf_1_{region} (
|
||||
.I(inp[{inp_1}]),
|
||||
.I(inp[{inp_1_p}]),
|
||||
.O(inp_1_{region})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{obuf_0_loc}" *)
|
||||
OBUF # ({obuf_param_str}) obuf_0_{region} (
|
||||
.I(out_0_{region}),
|
||||
.O(out[{out_0}])
|
||||
.O(out[{out_0_p}])
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{obuf_1_loc}" *)
|
||||
OBUF # ({obuf_param_str}) obuf_1_{region} (
|
||||
.I(out_1_{region}),
|
||||
.O(out[{out_1}])
|
||||
.O(out[{out_1_p}])
|
||||
);
|
||||
""".format(**keys)
|
||||
|
||||
if use_ino:
|
||||
verilog += """
|
||||
if use_ino:
|
||||
verilog += """
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{iobuf_loc}" *)
|
||||
IOBUF # ({obuf_param_str}) iobuf_{region} (
|
||||
.I(ino_i_{region}),
|
||||
.O(ino_o_{region}),
|
||||
.T(ino_t_{region}),
|
||||
.IO(ino[{ino}])
|
||||
.IO(ino[{ino_p}])
|
||||
);
|
||||
|
||||
assign out_0_{region} = inp_0_{region};
|
||||
|
|
@ -251,14 +311,86 @@ module top (
|
|||
assign ino_t_{region} = inp_1_{region};
|
||||
""".format(**keys)
|
||||
|
||||
else:
|
||||
verilog += """
|
||||
else:
|
||||
verilog += """
|
||||
|
||||
assign out_0_{region} = inp_0_{region};
|
||||
assign out_1_{region} = inp_1_{region};
|
||||
assign ino[{ino}] = 1'b0;
|
||||
""".format(**keys)
|
||||
|
||||
# Differential
|
||||
else:
|
||||
verilog += """
|
||||
|
||||
// {region}
|
||||
wire inp_0_{region};
|
||||
wire inp_1_{region};
|
||||
wire out_0_{region};
|
||||
wire out_1_{region};
|
||||
|
||||
wire ino_i_{region};
|
||||
wire ino_o_{region};
|
||||
wire ino_t_{region};
|
||||
""".format(**keys)
|
||||
|
||||
verilog += """
|
||||
(* KEEP, DONT_TOUCH, LOC="{ibuf_0_loc}" *)
|
||||
IBUFDS # ({ibuf_param_str}) ibufds_0_{region} (
|
||||
.I(inp[{inp_0_p}]),
|
||||
.IB(inp[{inp_0_n}]),
|
||||
.O(inp_0_{region})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{ibuf_1_loc}" *)
|
||||
IBUFDS # ({ibuf_param_str}) ibufds_1_{region} (
|
||||
.I(inp[{inp_1_p}]),
|
||||
.IB(inp[{inp_1_n}]),
|
||||
.O(inp_1_{region})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{obuf_0_loc}" *)
|
||||
OBUFDS # ({obuf_param_str}) obufds_0_{region} (
|
||||
.I(out_0_{region}),
|
||||
.O(out[{out_0_p}]),
|
||||
.OB(out[{out_0_n}])
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{obuf_1_loc}" *)
|
||||
OBUFDS # ({obuf_param_str}) obufds_1_{region} (
|
||||
.I(out_1_{region}),
|
||||
.O(out[{out_1_p}]),
|
||||
.OB(out[{out_1_n}])
|
||||
);
|
||||
""".format(**keys)
|
||||
|
||||
if use_ino:
|
||||
verilog += """
|
||||
|
||||
(* KEEP, DONT_TOUCH, LOC="{iobuf_loc}" *)
|
||||
IOBUFDS # ({obuf_param_str}) iobufds_{region} (
|
||||
.I(ino_i_{region}),
|
||||
.O(ino_o_{region}),
|
||||
.T(ino_t_{region}),
|
||||
.IO(ino[{ino_p}]),
|
||||
.IOB(ino[{ino_n}])
|
||||
);
|
||||
|
||||
assign out_0_{region} = inp_0_{region};
|
||||
assign out_1_{region} = ino_o_{region};
|
||||
assign ino_i_{region} = inp_0_{region};
|
||||
assign ino_t_{region} = inp_1_{region};
|
||||
""".format(**keys)
|
||||
|
||||
else:
|
||||
verilog += """
|
||||
|
||||
assign out_0_{region} = inp_0_{region};
|
||||
assign out_1_{region} = inp_1_{region};
|
||||
assign ino[{ino_p}] = 1'b0;
|
||||
assign ino[{ino_n}] = 1'b0;
|
||||
""".format(**keys)
|
||||
|
||||
verilog += "endmodule"
|
||||
|
||||
# Write verilog
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import argparse
|
|||
|
||||
from collections import namedtuple
|
||||
|
||||
IOSettings = namedtuple("IOSettings", "iostandard, drive, slew")
|
||||
IOSettings = namedtuple("IOSettings", "iostandard, drive, slew, is_diff")
|
||||
|
||||
# =============================================================================
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ def load_feature_data(fname):
|
|||
ios = IOSettings(
|
||||
parts[0],
|
||||
int(parts[1][1:]) if parts[1][1:] != "_FIXED" else None,
|
||||
parts[2])
|
||||
parts[2], "DIFF_" in parts[0])
|
||||
|
||||
# Feature activity
|
||||
feature_data[ios] = {
|
||||
|
|
@ -73,14 +73,18 @@ def get_relevant_parameters(feature_data, iob_type):
|
|||
parameters = []
|
||||
|
||||
# Check if a feature is relevant to particular IOB type
|
||||
is_diff = "DIFF_" in iob_type
|
||||
|
||||
for feature in all_features:
|
||||
for iosettings in feature_data:
|
||||
if iob_type in feature_data[iosettings][feature]:
|
||||
parameters.append((
|
||||
feature,
|
||||
feature.replace(".", "_"),
|
||||
))
|
||||
break
|
||||
if iosettings.is_diff == is_diff:
|
||||
base_iob_type = iob_type.replace("DIFF_", "")
|
||||
if base_iob_type in feature_data[iosettings][feature]:
|
||||
parameters.append((
|
||||
feature,
|
||||
feature.replace(".", "_"),
|
||||
))
|
||||
break
|
||||
|
||||
return parameters
|
||||
|
||||
|
|
@ -123,16 +127,22 @@ def generate_parameter_assignments(parameters, feature_data, iob_type):
|
|||
"""
|
||||
verilog = []
|
||||
|
||||
is_diff = "DIFF_" in iob_type
|
||||
base_iob_type = iob_type.replace("DIFF_", "")
|
||||
|
||||
for feature, parameter in sorted(parameters):
|
||||
condition = []
|
||||
for iosettings in feature_data:
|
||||
|
||||
if iosettings.is_diff != is_diff:
|
||||
continue
|
||||
|
||||
# Feature is set
|
||||
if iob_type in feature_data[iosettings][feature]:
|
||||
if base_iob_type in feature_data[iosettings][feature]:
|
||||
cond = "IOSTANDARD == \"{}\"".format(
|
||||
iosettings.iostandard.upper())
|
||||
|
||||
if iob_type in ["O", "T"]:
|
||||
if base_iob_type in ["O", "T"]:
|
||||
if iosettings.drive is not None and "DRIVE" in feature:
|
||||
cond += " && DRIVE == {}".format(iosettings.drive)
|
||||
if "SLEW" in feature:
|
||||
|
|
@ -169,7 +179,7 @@ def run():
|
|||
|
||||
# Make parameters
|
||||
parameters = {}
|
||||
for iob_type in ["I", "O", "T"]:
|
||||
for iob_type in ["I", "O", "T", "DIFF_I", "DIFF_O", "DIFF_T"]:
|
||||
parameters[iob_type] = get_relevant_parameters(feature_data, iob_type)
|
||||
|
||||
# Parameter definition
|
||||
|
|
|
|||
Loading…
Reference in New Issue