mirror of https://github.com/openXC7/prjxray.git
223 lines
6.6 KiB
Python
223 lines
6.6 KiB
Python
#!/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()
|