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")