diff --git a/minitests/iostandard/features/Makefile b/minitests/iostandard/features/Makefile index d28866a0..04485600 100644 --- a/minitests/iostandard/features/Makefile +++ b/minitests/iostandard/features/Makefile @@ -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 diff --git a/minitests/iostandard/features/analyze.py b/minitests/iostandard/features/analyze.py index 7849a324..b5203d82 100644 --- a/minitests/iostandard/features/analyze.py +++ b/minitests/iostandard/features/analyze.py @@ -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) diff --git a/minitests/iostandard/features/generate.py b/minitests/iostandard/features/generate.py index a02bfe8a..7c7fd2a4 100644 --- a/minitests/iostandard/features/generate.py +++ b/minitests/iostandard/features/generate.py @@ -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 diff --git a/minitests/iostandard/features/snippets.py b/minitests/iostandard/features/snippets.py index 776f9346..503b7f90 100644 --- a/minitests/iostandard/features/snippets.py +++ b/minitests/iostandard/features/snippets.py @@ -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