#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Copyright (C) 2017-2020 The Project X-Ray Authors. # # Use of this source code is governed by a ISC-style # license that can be found in the LICENSE file or at # https://opensource.org/licenses/ISC # # SPDX-License-Identifier: ISC """ This script generates code snippets for cell definition, technology mapping and VPR architecture definition. It reads correlation of IOB fasm features with IO standard settings such as IOSTANDARD, DRIVE and SLEW and generates: - Verilog model parameter definitions that match fasm features. - Xilinx's IOB parameter translation to those features. - Assignment of model parameters to the actual fasm features for VPR arch def. Generated code snippets need to be manually copied to relevant places in the target code / arch. def. """ import os import argparse import csv from collections import namedtuple IOSettings = namedtuple("IOSettings", "iostandard, drive, slew, is_diff") # ============================================================================= def load_feature_data(fname): """ Load feature vs. IO settings correlation data from a CSV file. """ # Load the data from CSV feature_data = {} with open(fname, "r") as fp: for line in csv.DictReader(fp): # Get IOSettings ios_parts = line["iosettings"].split(".") ios = IOSettings( ios_parts[0], int(ios_parts[1][1:]) if ios_parts[1][1:] != "_FIXED" else None, ios_parts[2], "DIFF_" in ios_parts[0]) # Feature activity feature_data[ios] = {k: line[k] for k in list(line.keys())[1:]} return feature_data def filter_feature_data(feature_data): """ Filters fasm features and leaves only those related to IO settings. """ for data in feature_data.values(): for feature in dict(data): if "DISABLE" in feature: del data[feature] if "PULLTYPE" in feature: del data[feature] if "IN_TERM" in feature: del data[feature] if "LOW_PWR" in feature: del data[feature] return feature_data def get_relevant_parameters(feature_data, iob_type): """ Gets features relevant to a specific IOB type and assign them verilog parameter names. """ # Get all features and make parameter names all_features = set( [f for data in feature_data.values() for f in data.keys()]) 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 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 # ============================================================================= def generate_parameter_defs(parameters): """ Generates verilog parameter definitions for the IOB cell model. """ verilog = [] for feature, parameter in sorted(parameters): verilog.append("parameter [0:0] {} = 1'b0;".format(parameter)) return "\n".join(verilog) def generate_parameter_map(parameters): """ Generates mapping of parameters for fasm features for architecture definition. """ xml = [] xml.append("") for feature, parameter in sorted(parameters): xml.append(" {} = {}".format(feature, parameter)) xml.append("") return "\n".join(xml) def generate_parameter_assignments(parameters, feature_data, iob_type): """ Generates parameter assignmets to be used inside the techmap. For each IOB cell parameter a set of conditions is generated based on feature activity observation. """ 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 base_iob_type in feature_data[iosettings][feature]: cond = "IOSTANDARD == \"{}\"".format( iosettings.iostandard.upper()) 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: cond += " && SLEW == \"{}\"".format(iosettings.slew) condition.append(cond) condition = sorted(list(set(condition))) condition_str = " || \n".join([" ({})".format(c) for c in condition]) verilog.append(".{}(\n{}\n)".format(parameter, condition_str)) return ",\n".join(verilog) # ============================================================================= def run(): """ Main. """ # Parse arguments parser = argparse.ArgumentParser() parser.add_argument("features", type=str, help="Input CSV file") args = parser.parse_args() # Load iosettings vs. feature map feature_data = load_feature_data(args.features) # Reject non-iostandard related features feature_data = filter_feature_data(feature_data) # Make parameters parameters = {} 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 with open("cells_sim.v", "w") as fp: for iob_type, params in parameters.items(): fp.write("// {} {}\n\n".format(iob_type, "=" * 70)) verilog = generate_parameter_defs(params) fp.write(verilog + "\n\n") # Parameter assignments with open("cells_map.v", "w") as fp: for iob_type, params in parameters.items(): fp.write("// {} {}\n\n".format(iob_type, "=" * 70)) verilog = generate_parameter_assignments( params, feature_data, iob_type) fp.write(verilog + "\n\n") # Parameter assignments with open("arch.xml", "w") as fp: for iob_type, params in parameters.items(): fp.write("\n\n".format(iob_type)) xml = generate_parameter_map(params) fp.write(xml + "\n\n") if __name__ == "__main__": run()