Skip to content

Commit 8a6264c

Browse files
committed
build: efinix: add function to add ip
add function to add efinix IP. Signed-off-by: Fin Maaß <[email protected]>
1 parent 9bacbe1 commit 8a6264c

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

litex/build/efinix/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from litex.build.efinix.programmer import EfinixProgrammer
22
from litex.build.efinix.dbparser import EfinixDbParser
33
from litex.build.efinix.ifacewriter import InterfaceWriter, InterfaceWriterBlock, InterfaceWriterXMLBlock
4+
from litex.build.efinix.ipmwriter import IPMWriter, IPMWriterBlock, IPMWriterXMLBlock
45
from litex.build.efinix.platform import EfinixPlatform

litex/build/efinix/efinity.py

+11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from litex.build.efinix import common
2929
from litex.build.efinix import InterfaceWriter
30+
from litex.build.efinix import IPMWriter
3031

3132

3233
# Efinity Toolchain --------------------------------------------------------------------------------
@@ -40,6 +41,7 @@ def __init__(self, efinity_path):
4041
self.efinity_path = efinity_path
4142
os.environ["EFXPT_HOME"] = self.efinity_path + "/pt"
4243
self.ifacewriter = InterfaceWriter(efinity_path)
44+
self.ipmwriter = IPMWriter(efinity_path)
4345
self.excluded_ios = []
4446
self.additional_sdc_commands = []
4547
self.additional_iface_commands = []
@@ -285,6 +287,15 @@ def build_project(self):
285287
xml_str = xml_str.toprettyxml(indent=" ")
286288
tools.write_to_file("{}.xml".format(self._build_name), xml_str)
287289

290+
if len(self.ipmwriter.blocks) > 0:
291+
ipm_header = self.ipmwriter.header(self._build_name, self.platform.device, self.platform.family)
292+
ipm = self.ipmwriter.generate(self.platform.device)
293+
294+
tools.write_to_file("ipm.py", ipm_header + ipm )
295+
296+
if tools.subprocess_call_filtered([self.efinity_path + "/bin/python3", "ipm.py"], common.colors) != 0:
297+
raise OSError("Error occurred during Efinity ip script execution.")
298+
288299
if tools.subprocess_call_filtered([self.efinity_path + "/bin/python3", "iface.py"], common.colors) != 0:
289300
raise OSError("Error occurred during Efinity peri script execution.")
290301

litex/build/efinix/ipmwriter.py

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#
2+
# This file is part of LiteX.
3+
#
4+
# Copyright (c) 2024 Fin Maaß <[email protected]>
5+
# SPDX-License-Identifier: BSD-2-Clause
6+
7+
from migen import *
8+
9+
from litex.build import tools
10+
11+
12+
# Interface Writer Block ---------------------------------------------------------------------------
13+
14+
class IPMWriterBlock(dict):
15+
def generate(self):
16+
raise NotImplementedError # Must be overloaded
17+
18+
class IPMWriterXMLBlock(dict):
19+
def generate(self):
20+
raise NotImplementedError # Must be overloaded
21+
22+
# Interface Writer --------------------------------------------------------------------------------
23+
24+
class IPMWriter:
25+
def __init__(self, efinity_path):
26+
self.efinity_path = efinity_path
27+
self.blocks = []
28+
self.filename = ""
29+
self.platform = None
30+
31+
def set_build_params(self, platform, build_name):
32+
self.filename = build_name
33+
self.platform = platform
34+
35+
36+
37+
def header(self, build_name, partnumber, family):
38+
header = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision()
39+
header += """
40+
import os
41+
import sys
42+
import pprint
43+
from pathlib import Path
44+
45+
home = "{0}"
46+
47+
os.environ["EFXIPM_HOME"] = home + "/ipm"
48+
49+
sys.path.append(home + "/ipm/bin")
50+
sys.path.append(home + "/lib/python3.11/site-packages")
51+
52+
from ipm_api_service.design import IPMDesignAPI
53+
from ipm_api_service.projectxml import ProjectXML
54+
55+
from common.logger import Logger
56+
57+
Logger.setup_logger(log_path_str=Path(".").absolute())
58+
59+
is_verbose = {1}
60+
project_xml_path = Path(".").absolute()/"{2}.xml"
61+
62+
design = IPMDesignAPI(device_name="{3}", family_name="{4}", is_verbose=is_verbose)
63+
projectxml = ProjectXML(project_xml_path=project_xml_path, is_verbose=is_verbose)
64+
65+
# pprint.pprint(design.get_ip_list())
66+
67+
68+
"""
69+
return header.format(self.efinity_path, "True", build_name, partnumber, family)
70+
71+
def get_block(self, name):
72+
for b in self.blocks:
73+
if b["name"] == name:
74+
return b
75+
return None
76+
77+
def generate_ip_block(self, block, verbose=True):
78+
name = block["name"]
79+
cmd = "# ---------- IP {} ---------\n".format(name)
80+
cmd += f'design.create_ip(module_name="{name}",vendor="{block["vendor"]}",library="{block["library"]}",name="{block["ip_name"]}")\n'
81+
if "configs" in block:
82+
cmd += '# Configs\n'
83+
cmd += f'{name}_configs = {{\n'
84+
for p, v in block["configs"].items():
85+
cmd += f' "{p}":"{v}",\n'
86+
cmd += f'}}\n\n'
87+
cmd += f'design.config_ip(module_name="{name}", configs = {name}_configs)\n'
88+
89+
cmd += f'success, validated_param_result, param_template_list = design.validate_ip(module_name="{name}")\n\n'
90+
91+
cmd += f'if success:\n'
92+
cmd += f' result = design.generate_ip(module_name="{name}")\n'
93+
cmd += f' if not projectxml.is_ip_exists(module_name="{name}"):\n'
94+
cmd += f' projectxml.add_ip(module_name="{name}")\n'
95+
cmd += f' projectxml.save()\n'
96+
97+
cmd += "# ---------- END IP {} ---------\n\n".format(name)
98+
return cmd
99+
100+
def generate(self, partnumber):
101+
output = ""
102+
for block in self.blocks:
103+
if isinstance(block, IPMWriterBlock):
104+
output += block.generate()
105+
else:
106+
if block["type"] == "IP":
107+
output += self.generate_ip_block(block)
108+
return output

0 commit comments

Comments
 (0)