#!/usr/bin/env python3 import argparse import datetime import os import pathlib import pprint import re import sys from edalize.edatool import get_edatool from edalize.flows.efinity import Efinity #from xml.dom import expatbuilder #import xml.etree.ElementTree as et #efinity_home = os.environ["EFINITY_HOME"] #script_path = efinity_home + "/scripts" curr_path = os.getcwd() efinix_pinout = { "Trion": { "F49": { # t4/t8 "ss_n": "G3", "cclk": "F3", "cdi0": "F2", "cdi1": "F1", "cdi2": "E2", "cdi3": "D2", }, "F81": { # t4/t8 "ss_n": "J4", "cclk": "H4", "cdi0": "F4", "cdi1": "H3", "cdi2": "J2", "cdi3": "F3", }, "F169": { # t13/t20 "ss_n": "L1", "cclk": "K1", "cdi0": "J1", "cdi1": "J2", "cdi2": "F1", "cdi3": "G2", }, "F256": { # t13/t20 "ss_n": "P3", "cclk": "H3", "cdi0": "L3", "cdi1": "N1", "cdi2": "K4", "cdi3": "L2", }, "F324": { # t20/t85/t120 "ss_n": "P15", "cclk": "N13", "cdi0": "M13", "cdi1": "N14", "cdi2": "K14", "cdi3": "K18", }, "F400": { # t20/ "ss_n": "W18", "cclk": "W19", "cdi0": "Y17", "cdi1": "Y18", "cdi2": "P15", "cdi3": "R17", }, "Q100": { # t13/t20 "ss_n": "24", "cclk": "26", "cdi0": "19", "cdi1": "18", "cdi2": "8", "cdi3": "14", }, "Q144": { # t20/ "ss_n": "31", "cclk": "30", "cdi0": "29", "cdi1": "28", "cdi2": "20", "cdi3": "19", }, "W80": { # t20/ "ss_n": "K3", "cclk": "K2", "cdi0": "J1", "cdi1": "J2", "cdi2": "F1", "cdi3": "G2", }, }, "Titanium": { "J484": { # ti180, ... "ss_n": "E2", "cclk": "J2", "cdi0": "G2", "cdi1": "H2", "cdi2": "F3", "cdi3": "G3", }, }, } timing_models = { "T8F81": "C2", "T13F256": "C3", "TI180J484": "C3", } def gen_isf_constr(gateware_name, build_path, device_name, family, pkg): # Basic settings isf_array = [ "# Device setting", "design.set_device_property(\"1A\",\"VOLTAGE\",\"3.3\",\"IOBANK\")", "design.set_device_property(\"1B\",\"VOLTAGE\",\"3.3\",\"IOBANK\")", "design.set_device_property(\"1C\",\"VOLTAGE\",\"1.1\",\"IOBANK\")", "design.set_device_property(\"2A\",\"VOLTAGE\",\"3.3\",\"IOBANK\")", "design.set_device_property(\"2B\",\"VOLTAGE\",\"3.3\",\"IOBANK\")", "", ] # JTAG settings isf_array.append("# ---------- JTAG 1 ---------") isf_array.append("design.create_block(\"jtag_soc\", block_type=\"JTAG\")") isf_array.append("design.assign_resource(\"jtag_soc\", \"JTAG_USER1\", \"JTAG\")") jtag_pads = [ "CAPTURE", "DRCK", "RESET", "RUNTEST", "SEL", "SHIFT", "TCK", "TDI", "TMS", "UPDATE", "TDO" ] for pad in jtag_pads: isf_array.append(f"design.set_property(\"jtag_soc\", \"{pad}\", \"jtag_1_{pad}\", \"JTAG\")") # SPI pins settings pins = efinix_pinout.get(family).get(pkg, None) assert pins is not None pin_lst = [ {"name" : "csn", "dir": "out", "pin": pins["ss_n"], "io_std": "3.3 V LVTTL / LVCMOS"}, {"name" : "sck", "dir": "out", "pin": pins["cclk"], "io_std": "3.3 V LVTTL / LVCMOS"}, {"name" : "sdi_dq0", "dir": "out", "pin": pins["cdi0"], "io_std": "3.3 V LVTTL / LVCMOS"}, {"name" : "sdo_dq1", "dir": "in", "pin": pins["cdi1"], "io_std": "3.3 V LVTTL / LVCMOS"}, ] for pin_cfg in pin_lst: name = pin_cfg["name"] pin_loc = pin_cfg["pin"] if pin_cfg["dir"] == "in": isf_array.append(f"design.create_input_gpio(\"{name}\")") else: isf_array.append(f"design.create_output_gpio(\"{name}\")") isf_array.append(f"design.assign_pkg_pin(\"{name}\", \"{pin_loc}\")") isf_array.append("") # Save ISF file with open(os.path.join(build_dir, build_name+".isf"), "w") as fd: fd.write("\n".join(isf_array)) if __name__ == "__main__": parser = argparse.ArgumentParser("SpiOverJtag for Efinix devices") parser.add_argument("--device", help="Efinix Device") args = parser.parse_args() assert args.device is not None device = args.device.upper() build_name = "efinix_spiOverJtag" build_dir = os.path.join(curr_path, f"tmp_efinix_{device.lower()}") timing_model = timing_models.get(device, "C3") sources = [ { 'name': os.path.join(curr_path, "efinix_spiOverJtag.v"), "file_type": "verilogSource", }, { 'name': os.path.join(build_dir, "efinix_spiOverJtag.isf"), "file_type": "ISF", }, ] force_restart = False t = re.compile(r"(T[I]*)(\d+)(\w\d+)") tt = t.match(device) if tt is None: print("fails") else: (fam, size, package) = tt.groups() assert fam in ["TI", "T"] family = {True:"Titanium", False:"Trion"}[fam == "TI"] if fam == "TI": device = device.replace("TI", "Ti") if os.path.exists(build_dir) and force_restart: os.rmdir(build_dir) if not os.path.exists(build_dir): try: os.mkdir(build_dir) except FileExistsError: pass gen_isf_constr( gateware_name = build_name, build_path = build_dir, device_name = device, family = family, pkg = package ) tool_options = { 'part' : device, 'family' : family, 'timing' : timing_model, } edam = { 'name' : build_name, 'files' : sources, 'flow_options' : tool_options, 'toplevel' : 'spiOverJtag', } backend = Efinity(edam=edam, work_root=build_dir) backend.configure() backend.build() import shutil shutil.copy(os.path.join(build_dir, "outflow", "efinix_spiOverJtag.bit"), build_dir)