diff --git a/litex/build/anlogic/anlogic.py b/litex/build/anlogic/anlogic.py
index 33b972ad4..fa5fbb322 100644
--- a/litex/build/anlogic/anlogic.py
+++ b/litex/build/anlogic/anlogic.py
@@ -14,241 +14,201 @@ from shutil import which
from migen.fhdl.structure import _Fragment
from litex.build.generic_platform import *
+from litex.build.generic_toolchain import GenericToolchain
from litex.build import tools
-# Constraints (.adc and .sdc) ----------------------------------------------------------------------
-
-def _build_adc(named_sc, named_pc):
- adc = []
-
- flat_sc = []
- for name, pins, other, resource in named_sc:
- if len(pins) > 1:
- for i, p in enumerate(pins):
- flat_sc.append((f"{name}[{i}]", p, other))
- else:
- flat_sc.append((name, pins[0], other))
-
- for name, pin, other in flat_sc:
- line = f"set_pin_assignment {{{name}}} {{ LOCATION = {pin}; "
- for c in other:
- if isinstance(c, IOStandard):
- line += f" IOSTANDARD = {c.name}; "
- line += f"}}"
- adc.append(line)
-
- if named_pc:
- adc.extend(named_pc)
-
- with open("top.adc", "w") as f:
- f.write("\n".join(adc))
-
-def _build_sdc(clocks, vns):
- sdc = []
- for clk, period in sorted(clocks.items(), key=lambda x: x[0].duid):
- sdc.append(f"create_clock -name {vns.get_name(clk)} -period {str(period)} [get_ports {{{vns.get_name(clk)}}}]")
- with open("top.sdc", "w") as f:
- f.write("\n".join(sdc))
-
-# Script -------------------------------------------------------------------------------------------
-
-def _build_al(name, family, device, files):
- xml = []
-
- date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-
- # Set Device.
- xml.append(f"")
- xml.append(f"")
- xml.append(f" {date}")
- xml.append(f" 5.0.28716")
- xml.append(f" 00000000")
- xml.append(f" {name}")
- xml.append(f" ")
- xml.append(f" {family}")
- xml.append(f" {device}")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
-
- # Add Sources.
- for f, typ, lib in files:
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
-
- # Add IOs Constraints.
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" {name}")
- xml.append(f" auto")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" ")
- xml.append(f" {date}")
- xml.append(f" 0")
- xml.append(f" true")
- xml.append(f" ")
- xml.append(f"")
-
- # Generate .al.
- with open(name + ".al", "w") as f:
- f.write("\n".join(xml))
-
-def _build_tcl(name, architecture, package):
- tcl = []
-
- # Set Device.
- tcl.append(f"import_device {architecture}.db -package {package}")
-
- # Add project.
- tcl.append(f"open_project {name}.al")
-
- # Elaborate.
- tcl.append(f"elaborate -top {name}")
-
- # Add IOs Constraints.
- tcl.append("read_adc top.adc")
-
- tcl.append("optimize_rtl")
-
- # Add SDC Constraints.
- tcl.append("read_sdc top.sdc")
-
- # Perform PnR.
- tcl.append("optimize_gate")
- tcl.append("legalize_phy_inst")
- tcl.append("place")
- tcl.append("route")
- tcl.append(f"bitgen -bit \"{name}.bit\" -version 0X00 -g ucode:000000000000000000000000")
-
- # Generate .tcl.
- with open("run.tcl", "w") as f:
- f.write("\n".join(tcl))
-
-
# TangDinastyToolchain -----------------------------------------------------------------------------------
-def parse_device(device):
-
- devices = {
- "EG4S20BG256" :[ "eagle_s20", "EG4", "BG256" ],
- }
- if device not in devices.keys():
- raise ValueError("Invalid device {}".format(device))
-
- (architecture, family, package) = devices[device]
- return (architecture, family, package)
-
-class TangDinastyToolchain:
+class TangDinastyToolchain(GenericToolchain):
attr_translate = {}
def __init__(self):
- self.clocks = dict()
+ super().__init__()
+ self._architecture = ""
+ self._family = ""
+ self._package = ""
- def build(self, platform, fragment,
- build_dir = "build",
- build_name = "top",
- run = True,
- **kwargs):
+ def finalize(self):
+ self._architecture, self._family, self._package = self.parse_device()
- # Create build directory.
- cwd = os.getcwd()
- os.makedirs(build_dir, exist_ok=True)
- os.chdir(build_dir)
+ def build(self, platform, fragment, **kwargs):
- # Finalize design.
- if not isinstance(fragment, _Fragment):
- fragment = fragment.get_fragment()
- platform.finalize(fragment)
+ return self._build(platform, fragment, **kwargs)
- # Generate verilog.
- v_output = platform.get_verilog(fragment, name=build_name, **kwargs)
- named_sc, named_pc = platform.resolve_signals(v_output.ns)
- v_file = build_name + ".v"
- v_output.write(v_file)
- platform.add_source(v_file)
+ # Constraints (.adc ) --------------------------------------------------------------------------
- # Generate constraints file.
- # IOs (.adc).
- _build_adc(
- named_sc = named_sc,
- named_pc = named_pc
- )
+ def build_io_constraints(self):
+ adc = []
- # Timings (.sdc).
- _build_sdc(
- clocks = self.clocks,
- vns = v_output.ns
- )
+ flat_sc = []
+ for name, pins, other, resource in self.named_sc:
+ if len(pins) > 1:
+ for i, p in enumerate(pins):
+ flat_sc.append((f"{name}[{i}]", p, other))
+ else:
+ flat_sc.append((name, pins[0], other))
- architecture, family, package = parse_device(platform.device)
+ for name, pin, other in flat_sc:
+ line = f"set_pin_assignment {{{name}}} {{ LOCATION = {pin}; "
+ for c in other:
+ if isinstance(c, IOStandard):
+ line += f" IOSTANDARD = {c.name}; "
+ line += f"}}"
+ adc.append(line)
- # Generate project file (.al).
- al = _build_al(
- name = build_name,
- family = family,
- device = platform.device,
- files = platform.sources)
+ if self.named_pc:
+ adc.extend(self.named_pc)
- # Generate build script (.tcl).
- script = _build_tcl(
- name = build_name,
- architecture = architecture,
- package = package)
+ tools.write_to_file("top.adc", "\n".join(adc))
+ return ("top.adc", "ADC")
- # Run.
- if run:
+ # Timing Constraints (in sdc file) -------------------------------------------------------------
+
+ def build_timing_constraints(self, vns):
+ sdc = []
+ for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
+ sdc.append(f"create_clock -name {vns.get_name(clk)} -period {str(period)} [get_ports {{{vns.get_name(clk)}}}]")
+ tools.write_to_file("top.sdc", "\n".join(sdc))
+ return ("top.sdc", "SDC")
+
+ # Project (.ai) --------------------------------------------------------------------------------
+
+ def build_project(self):
+ xml = []
+
+ date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+
+ # Set Device.
+ xml.append(f"")
+ xml.append(f"")
+ xml.append(f" {date}")
+ xml.append(f" 5.0.28716")
+ xml.append(f" 00000000")
+ xml.append(f" {self._build_name}")
+ xml.append(f" ")
+ xml.append(f" {self._family}")
+ xml.append(f" {self.platform.device}")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+
+ # Add Sources.
+ for f, typ, lib in self.platform.sources:
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+
+ # Add IOs Constraints.
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" {self._build_name}")
+ xml.append(f" auto")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" ")
+ xml.append(f" {date}")
+ xml.append(f" 0")
+ xml.append(f" true")
+ xml.append(f" ")
+ xml.append(f"")
+
+ # Generate .al.
+ tools.write_to_file(self._build_name + ".al", "\n".join(xml))
+
+ # Script ---------------------------------------------------------------------------------------
+
+ def build_script(self):
+ tcl = []
+
+ # Set Device.
+ tcl.append(f"import_device {self._architecture}.db -package {self._package}")
+
+ # Add project.
+ tcl.append(f"open_project {self._build_name}.al")
+
+ # Elaborate.
+ tcl.append(f"elaborate -top {self._build_name}")
+
+ # Add IOs Constraints.
+ tcl.append("read_adc top.adc")
+
+ tcl.append("optimize_rtl")
+
+ # Add SDC Constraints.
+ tcl.append("read_sdc top.sdc")
+
+ # Perform PnR.
+ tcl.append("optimize_gate")
+ tcl.append("legalize_phy_inst")
+ tcl.append("place")
+ tcl.append("route")
+ tcl.append(f"bitgen -bit \"{self._build_name}.bit\" -version 0X00 -g ucode:000000000000000000000000")
+
+ # Generate .tcl.
+ tools.write_to_file("run.tcl", "\n".join(tcl))
+
+ return "run.tcl"
+
+ def run_script(self, script):
if which("td") is None:
msg = "Unable to find Tang Dinasty toolchain, please:\n"
msg += "- Add Tang Dinasty toolchain to your $PATH."
raise OSError(msg)
- if subprocess.call(["td", "run.tcl"]) != 0:
+ if subprocess.call(["td", script]) != 0:
raise OSError("Error occured during Tang Dinasty's script execution.")
- os.chdir(cwd)
+ def parse_device(self):
+ device = self.platform.device
- return v_output.ns
+ devices = {
+ "EG4S20BG256" :[ "eagle_s20", "EG4", "BG256" ],
+ }
+
+ if device not in devices.keys():
+ raise ValueError("Invalid device {}".format(device))
+
+ (architecture, family, package) = devices[device]
+ return (architecture, family, package)
def add_period_constraint(self, platform, clk, period):
clk.attr.add("keep")