build: Add initial/minimal QuickLogic build support.
This commit is contained in:
parent
16702c44fe
commit
cb6861e1c8
|
@ -0,0 +1 @@
|
|||
from litex.build.quicklogic.platform import QuickLogicPlatform
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# This file is part of LiteX.
|
||||
#
|
||||
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
# QuickLogic Special Overrides ---------------------------------------------------------------------
|
||||
|
||||
quicklogic_special_overrides = {}
|
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
# This file is part of LiteX.
|
||||
#
|
||||
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
import os
|
||||
|
||||
from litex.build.generic_platform import GenericPlatform
|
||||
from litex.build.quicklogic import common, symbiflow
|
||||
|
||||
# QuickLogicPlatform -------------------------------------------------------------------------------
|
||||
|
||||
class QuickLogicPlatform(GenericPlatform):
|
||||
bitstream_ext = ".bit"
|
||||
|
||||
def __init__(self, device, *args, toolchain="symbiflow", **kwargs):
|
||||
GenericPlatform.__init__(self, device, *args, **kwargs)
|
||||
if toolchain == "symbiflow":
|
||||
self.toolchain = symbiflow.SymbiflowToolchain()
|
||||
else:
|
||||
raise ValueError("Unknown toolchain")
|
||||
|
||||
def get_verilog(self, *args, special_overrides=dict(), **kwargs):
|
||||
so = dict(common.quicklogic_special_overrides)
|
||||
so.update(special_overrides)
|
||||
return GenericPlatform.get_verilog(self, *args,
|
||||
special_overrides = so,
|
||||
attr_translate = self.toolchain.attr_translate,
|
||||
**kwargs)
|
||||
|
||||
def build(self, *args, **kwargs):
|
||||
return self.toolchain.build(self, *args, **kwargs)
|
|
@ -0,0 +1,116 @@
|
|||
#
|
||||
# This file is part of LiteX.
|
||||
#
|
||||
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from shutil import which
|
||||
|
||||
from migen.fhdl.structure import _Fragment
|
||||
|
||||
from litex.build.generic_platform import *
|
||||
from litex.build import tools
|
||||
from litex.build.quicklogic import common
|
||||
|
||||
|
||||
# IO Constraints (.pcf) ----------------------------------------------------------------------------
|
||||
|
||||
def _format_io_pcf(signame, pin, others):
|
||||
r = f"set_io {signame} {Pins(pin).identifiers[0]}\n"
|
||||
return r
|
||||
|
||||
def _build_io_pcf(named_sc, named_pc, build_name):
|
||||
pcf = ""
|
||||
for sig, pins, others, resname in named_sc:
|
||||
if len(pins) > 1:
|
||||
for i, p in enumerate(pins):
|
||||
pcf += _format_io_pcf(sig + "(" + str(i) + ")", p, others)
|
||||
else:
|
||||
pcf += _format_io_pcf(sig, pins[0], others)
|
||||
tools.write_to_file(build_name + ".pcf", pcf)
|
||||
|
||||
# Build Makefile -----------------------------------------------------------------------------------
|
||||
|
||||
def _build_makefile(platform, sources, build_dir, build_name):
|
||||
makefile = []
|
||||
|
||||
# Define Paths.
|
||||
makefile.append("mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))")
|
||||
makefile.append("current_dir := $(patsubst %/,%,$(dir $(mkfile_path)))")
|
||||
|
||||
# Create Project.
|
||||
# FIXME: Only use top file for now and ignore .init files.
|
||||
makefile.append("all:")
|
||||
makefile.append("\tql_symbiflow -compile -d {device} -P {part} -v {verilog} -t {top} -p {pcf}".format(
|
||||
device = platform.device,
|
||||
part = {"ql-eos-s3": "pd64"}.get(platform.device),
|
||||
verilog = f"{build_name}.v",
|
||||
top = build_name,
|
||||
pcf = f"{build_name}.pcf"
|
||||
))
|
||||
|
||||
# Generate Makefile.
|
||||
tools.write_to_file("Makefile", "\n".join(makefile))
|
||||
|
||||
def _run_make():
|
||||
make_cmd = ["make", "-j1"]
|
||||
|
||||
if which("ql_symbiflow") is None:
|
||||
msg = "Unable to find QuickLogic Symbiflow toolchain, please:\n"
|
||||
msg += "- Add QuickLogic Symbiflow toolchain to your $PATH."
|
||||
raise OSError(msg)
|
||||
|
||||
if subprocess.call(make_cmd) != 0:
|
||||
raise OSError("Error occured during QuickLogic Symbiflow's script execution.")
|
||||
|
||||
|
||||
# SymbiflowToolchain -------------------------------------------------------------------------------
|
||||
|
||||
class SymbiflowToolchain:
|
||||
attr_translate = {}
|
||||
|
||||
special_overrides = common.quicklogic_special_overrides
|
||||
|
||||
def __init__(self):
|
||||
self.clocks = dict()
|
||||
self.false_paths = set()
|
||||
|
||||
def build(self, platform, fragment,
|
||||
build_dir = "build",
|
||||
build_name = "top",
|
||||
run = False,
|
||||
**kwargs):
|
||||
|
||||
# Create build directory.
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
cwd = os.getcwd()
|
||||
os.chdir(build_dir)
|
||||
|
||||
# Finalize design.
|
||||
if not isinstance(fragment, _Fragment):
|
||||
fragment = fragment.get_fragment()
|
||||
platform.finalize(fragment)
|
||||
|
||||
# Generate verilog.
|
||||
v_output = platform.get_verilog(fragment, name=build_name, **kwargs)
|
||||
named_sc, named_pc = platform.resolve_signals(v_output.ns)
|
||||
top_file = build_name + ".v"
|
||||
v_output.write(top_file)
|
||||
platform.add_source(top_file)
|
||||
|
||||
# Generate .pcf IO constraints file.
|
||||
_build_io_pcf(named_sc, named_pc, build_name)
|
||||
|
||||
# Generate Makefie.
|
||||
_build_makefile(platform, platform.sources, build_dir, build_name)
|
||||
|
||||
# Run.
|
||||
if run:
|
||||
_run_make()
|
||||
|
||||
os.chdir(cwd)
|
||||
|
||||
return v_output.ns
|
Loading…
Reference in New Issue