blob: cda6904e02687a3f0ed2aa55a2d968c5ba9888ee [file] [log] [blame]
#!/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("<meta name=\"fasm_params\">")
for feature, parameter in sorted(parameters):
xml.append(" {} = {}".format(feature, parameter))
xml.append("</meta>")
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()