diff --git a/litex/build/efinix/__init__.py b/litex/build/efinix/__init__.py index 3533c75f86..91e1fc6c6f 100644 --- a/litex/build/efinix/__init__.py +++ b/litex/build/efinix/__init__.py @@ -1,4 +1,5 @@ from litex.build.efinix.programmer import EfinixProgrammer from litex.build.efinix.dbparser import EfinixDbParser from litex.build.efinix.ifacewriter import InterfaceWriter, InterfaceWriterBlock, InterfaceWriterXMLBlock +from litex.build.efinix.ipmwriter import IPMWriter, IPMWriterBlock, IPMWriterXMLBlock from litex.build.efinix.platform import EfinixPlatform \ No newline at end of file diff --git a/litex/build/efinix/efinity.py b/litex/build/efinix/efinity.py index c0643478e1..9e5c396624 100644 --- a/litex/build/efinix/efinity.py +++ b/litex/build/efinix/efinity.py @@ -27,6 +27,7 @@ from litex.build.efinix import common from litex.build.efinix import InterfaceWriter +from litex.build.efinix import IPMWriter # Efinity Toolchain -------------------------------------------------------------------------------- @@ -40,6 +41,7 @@ def __init__(self, efinity_path): self.efinity_path = efinity_path os.environ["EFXPT_HOME"] = self.efinity_path + "/pt" self.ifacewriter = InterfaceWriter(efinity_path) + self.ipmwriter = IPMWriter(efinity_path) self.excluded_ios = [] self.additional_sdc_commands = [] self.additional_iface_commands = [] @@ -309,6 +311,15 @@ def build_project(self): xml_str = xml_str.toprettyxml(indent=" ") tools.write_to_file("{}.xml".format(self._build_name), xml_str) + if len(self.ipmwriter.blocks) > 0: + ipm_header = self.ipmwriter.header(self._build_name, self.platform.device, self.platform.family) + ipm = self.ipmwriter.generate(self.platform.device) + + tools.write_to_file("ipm.py", ipm_header + ipm ) + + if tools.subprocess_call_filtered([self.efinity_path + "/bin/python3", "ipm.py"], common.colors) != 0: + raise OSError("Error occurred during Efinity ip script execution.") + if tools.subprocess_call_filtered([self.efinity_path + "/bin/python3", "iface.py"], common.colors) != 0: raise OSError("Error occurred during Efinity peri script execution.") diff --git a/litex/build/efinix/ipmwriter.py b/litex/build/efinix/ipmwriter.py new file mode 100644 index 0000000000..a04d19fed5 --- /dev/null +++ b/litex/build/efinix/ipmwriter.py @@ -0,0 +1,108 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2024 Fin Maaß +# SPDX-License-Identifier: BSD-2-Clause + +from migen import * + +from litex.build import tools + + +# Interface Writer Block --------------------------------------------------------------------------- + +class IPMWriterBlock(dict): + def generate(self): + raise NotImplementedError # Must be overloaded + +class IPMWriterXMLBlock(dict): + def generate(self): + raise NotImplementedError # Must be overloaded + +# Interface Writer -------------------------------------------------------------------------------- + +class IPMWriter: + def __init__(self, efinity_path): + self.efinity_path = efinity_path + self.blocks = [] + self.filename = "" + self.platform = None + + def set_build_params(self, platform, build_name): + self.filename = build_name + self.platform = platform + + + + def header(self, build_name, partnumber, family): + header = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + header += """ +import os +import sys +import pprint +from pathlib import Path + +home = "{0}" + +os.environ["EFXIPM_HOME"] = home + "/ipm" + +sys.path.append(home + "/ipm/bin") +sys.path.append(home + "/lib/python3.11/site-packages") + +from ipm_api_service.design import IPMDesignAPI +from ipm_api_service.projectxml import ProjectXML + +from common.logger import Logger + +Logger.setup_logger(log_path_str=Path(".").absolute()) + +is_verbose = {1} +project_xml_path = Path(".").absolute()/"{2}.xml" + +design = IPMDesignAPI(device_name="{3}", family_name="{4}", is_verbose=is_verbose) +projectxml = ProjectXML(project_xml_path=project_xml_path, is_verbose=is_verbose) + +# pprint.pprint(design.get_ip_list()) + + +""" + return header.format(self.efinity_path, "True", build_name, partnumber, family) + + def get_block(self, name): + for b in self.blocks: + if b["name"] == name: + return b + return None + + def generate_ip_block(self, block, verbose=True): + name = block["name"] + cmd = "# ---------- IP {} ---------\n".format(name) + cmd += f'design.create_ip(module_name="{name}",vendor="{block["vendor"]}",library="{block["library"]}",name="{block["ip_name"]}")\n' + if "configs" in block: + cmd += '# Configs\n' + cmd += f'{name}_configs = {{\n' + for p, v in block["configs"].items(): + cmd += f' "{p}":"{v}",\n' + cmd += f'}}\n\n' + cmd += f'design.config_ip(module_name="{name}", configs = {name}_configs)\n' + + cmd += f'success, validated_param_result, param_template_list = design.validate_ip(module_name="{name}")\n\n' + + cmd += f'if success:\n' + cmd += f' result = design.generate_ip(module_name="{name}")\n' + cmd += f' if not projectxml.is_ip_exists(module_name="{name}"):\n' + cmd += f' projectxml.add_ip(module_name="{name}")\n' + cmd += f' projectxml.save()\n' + + cmd += "# ---------- END IP {} ---------\n\n".format(name) + return cmd + + def generate(self, partnumber): + output = "" + for block in self.blocks: + if isinstance(block, IPMWriterBlock): + output += block.generate() + else: + if block["type"] == "IP": + output += self.generate_ip_block(block) + return output