-
Notifications
You must be signed in to change notification settings - Fork 568
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1617 from trabucayre/colognechip
build: adding colognechip toolchain
- Loading branch information
Showing
4 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from litex.build.colognechip.platform import CologneChipPlatform |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
# | ||
# This file is part of LiteX. | ||
# | ||
# Copyright (c) 2023 Gwenhael Goavec-Merou <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import os | ||
import sys | ||
import math | ||
import subprocess | ||
from shutil import which, copyfile | ||
|
||
from migen.fhdl.structure import _Fragment | ||
|
||
from litex.build.generic_platform import * | ||
from litex.build import tools | ||
from litex.build.generic_toolchain import GenericToolchain | ||
from litex.build.yosys_wrapper import YosysWrapper, yosys_args, yosys_argdict | ||
|
||
|
||
# CologneChipToolchain ----------------------------------------------------------------------------- | ||
|
||
class CologneChipToolchain(GenericToolchain): | ||
attr_translate = {} | ||
supported_build_backend = ["litex", "edalize"] | ||
|
||
def __init__(self): | ||
super().__init__() | ||
self._yosys = None | ||
self._yosys_cmds = [] | ||
self._synth_opts = "-nomx8 " | ||
|
||
def finalize(self): | ||
self._yosys = YosysWrapper( | ||
platform = self.platform, | ||
build_name = self._build_name, | ||
target = "gatemate", | ||
output_name = self._build_name+"_synth", | ||
template = [], | ||
yosys_opts = self._synth_opts, | ||
yosys_cmds = self._yosys_cmds, | ||
synth_format = "v", | ||
) | ||
|
||
# IO Constraints (.ccf) ------------------------------------------------------------------------ | ||
|
||
def _get_pin_direction(self, pinname): | ||
pins = self.platform.constraint_manager.get_io_signals() | ||
for pin in sorted(pins, key=lambda x: x.duid): | ||
if (pinname.split("[")[0] == pin.name): | ||
if pin.direction == "output": | ||
return "Pin_out" | ||
elif pin.direction == "input": | ||
return "Pin_in" | ||
else: | ||
return "Pin_inout" | ||
return "Unknown" | ||
|
||
def build_io_constraints(self): | ||
ccf = [] | ||
|
||
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)) | ||
|
||
for name, pin, other in flat_sc: | ||
pin_cst = "" | ||
if pin != "X": | ||
direction = self._get_pin_direction(name) | ||
pin_cst = f"{direction} \"{name}\" Loc = \"{pin}\"" | ||
|
||
for c in other: | ||
if isinstance(c, Misc): | ||
pin_cst += f" | {c.misc}" | ||
pin_cst += ";" | ||
ccf.append(pin_cst) | ||
|
||
if self.named_pc: | ||
ccf.extend(self.named_pc) | ||
|
||
tools.write_to_file(f"{self._build_name}.ccf", "\n".join(ccf)) | ||
return (f"{self._build_name}.ccf", "CCF") | ||
|
||
# Project (.ys) -------------------------------------------------------------------------------- | ||
|
||
def build_project(self): | ||
""" create project files (mainly Yosys ys file) | ||
""" | ||
self._yosys.build_script() | ||
|
||
# Script --------------------------------------------------------------------------------------- | ||
|
||
def build_script(self): | ||
""" create build_xxx.yy by using Yosys and p_r instances. | ||
Return | ||
====== | ||
the script name (str) | ||
""" | ||
|
||
if sys.platform in ("win32", "cygwin"): | ||
script_ext = ".bat" | ||
script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" | ||
fail_stmt = " || exit /b" | ||
else: | ||
script_ext = ".sh" | ||
script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n" | ||
fail_stmt = "" | ||
fail_stmt += "\n" | ||
|
||
# yosys call | ||
script_contents += self._yosys.get_yosys_call("script") + fail_stmt | ||
# p_r call | ||
script_contents += "p_r -ccf {build_name}.ccf -A 1 -i {build_name}_synth.v -o {build_name} -lib ccag\n".format( | ||
build_name = self._build_name) | ||
|
||
script_file = "build_" + self._build_name + script_ext | ||
tools.write_to_file(script_file, script_contents, force_unix=False) | ||
|
||
return script_file | ||
|
||
def run_script(self, script): | ||
""" run build_xxx.yy script | ||
Parameters | ||
========== | ||
script: str | ||
script name to use | ||
""" | ||
if sys.platform in ("win32", "cygwin"): | ||
shell = ["cmd", "/c"] | ||
else: | ||
shell = ["bash"] | ||
|
||
if which("yosys") is None or which("p_r") is None: | ||
msg = "Unable to find CologneChip toolchain, please:\n" | ||
msg += "- Add Yosys/p_r toolchain to your $PATH." | ||
raise OSError(msg) | ||
|
||
if subprocess.call(shell + [script]) != 0: | ||
raise OSError("Error occured during Yosys/p_r's script execution.") | ||
|
||
|
||
def add_period_constraint(self, platform, clk, period): | ||
pass | ||
|
||
def colognechip_args(parser): | ||
# TODO: yosys (default's yosys aren't supported | ||
# TODO: p_r args | ||
pass | ||
|
||
def colognechip_argdict(args): | ||
# TODO: ditto | ||
return {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# | ||
# This file is part of LiteX. | ||
# | ||
# Copyright (c) 2023 Gwenhael Goavec-Merou <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
from migen.fhdl.module import Module | ||
from migen.genlib.resetsync import AsyncResetSynchronizer | ||
|
||
from litex.build.io import * | ||
|
||
# CologneChip AsyncResetSynchronizer --------------------------------------------------------------- | ||
|
||
class CologneChipAsyncResetSynchronizerImpl(Module): | ||
def __init__(self, cd, async_reset): | ||
rst1 = Signal() | ||
self.specials += [ | ||
Instance("CC_DFF", | ||
p_CLK_INV = 0, | ||
p_EN_INV = 0, | ||
p_SR_INV = 0, | ||
p_SR_VAL = 1, | ||
i_D = 0, | ||
i_CLK = cd.clk, | ||
i_EN = 1, | ||
i_SR = async_reset, | ||
o_Q = rst1), | ||
Instance("CC_DFF", | ||
p_CLK_INV = 0, | ||
p_EN_INV = 0, | ||
p_SR_INV = 0, | ||
p_SR_VAL = 1, | ||
i_D = rst1, | ||
i_CLK = cd.clk, | ||
i_EN = 1, | ||
i_SR = async_reset, | ||
o_Q = cd.rst) | ||
] | ||
|
||
class CologneChipAsyncResetSynchronizer: | ||
@staticmethod | ||
def lower(dr): | ||
return CologneChipAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) | ||
|
||
# CologneChip DDR Input ---------------------------------------------------------------------------- | ||
|
||
class CologneChipDDRInputImpl(Module): | ||
def __init__(self, i, o1, o2, clk): | ||
self.specials += Instance("CC_IDDR", | ||
i_CLK = clk, | ||
i_D = i, | ||
o_Q0 = o1, | ||
o_Q1 = o2, | ||
) | ||
|
||
class CologneChipDDRInput: | ||
@staticmethod | ||
def lower(dr): | ||
return CologneChipInputImpl(dr.i, dr.o1, dr.o2, dr.clk) | ||
|
||
# CologneChip DDR Output --------------------------------------------------------------------------- | ||
|
||
class CologneChipDDROutputImpl(Module): | ||
def __init__(self, i1, i2, o, clk): | ||
self.specials += Instance("CC_ODDR", | ||
p_CLK_INV = 0, | ||
i_CLK = clk, | ||
i_DDR = ~clk, | ||
i_D0 = i1, | ||
i_D1 = i2, | ||
o_Q = o, | ||
) | ||
|
||
class CologneChipDDROutput: | ||
@staticmethod | ||
def lower(dr): | ||
return CologneChipDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk) | ||
|
||
# CologneChip Differential Input ------------------------------------------------------------------- | ||
|
||
class CologneChipDifferentialInputImpl(Module): | ||
def __init__(self, i_p, i_n, o): | ||
self.specials += Instance("CC_LVDS_IBUF", | ||
i_I_P = i_p, | ||
i_I_N = i_n, | ||
o_Y = o, | ||
) | ||
|
||
class CologneChipDifferentialInput: | ||
@staticmethod | ||
def lower(dr): | ||
return CologneChipDifferentialInputImpl(dr.i_p, dr.i_n, dr.o) | ||
|
||
# CologneChip Differential Output ------------------------------------------------------------------ | ||
|
||
class CologneChipDifferentialOutputImpl(Module): | ||
def __init__(self, i, o_p, o_n): | ||
self.specials += Instance("CC_LVDS_OBUF", | ||
i_A = i, | ||
o_O_P = o_p, | ||
o_O_N = o_n, | ||
) | ||
|
||
class CologneChipDifferentialOutput: | ||
@staticmethod | ||
def lower(dr): | ||
return CologneChipDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n) | ||
|
||
# CologneChip SDR Input ---------------------------------------------------------------------------- | ||
|
||
class CologneChipSDRInputImpl(Module): | ||
def __init__(self, i, o): | ||
self.specials += Instance("CC_IBUF", | ||
i_I = i, | ||
o_O = o, | ||
) | ||
|
||
class CologneChipSDRInput: | ||
@staticmethod | ||
def lower(dr): | ||
return CologneChipSDRInput(dr.i, dr.o) | ||
|
||
# CologneChip Special Overrides -------------------------------------------------------------------- | ||
|
||
colognechip_special_overrides = { | ||
AsyncResetSynchronizer: CologneChipAsyncResetSynchronizer, | ||
DDRInput: CologneChipDDRInput, | ||
DDROutput: CologneChipDDROutput, | ||
DifferentialInput: CologneChipDifferentialInput, | ||
DifferentialOutput: CologneChipDifferentialOutput, | ||
SDRInput: CologneChipSDRInput, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# | ||
# This file is part of LiteX. | ||
# | ||
# Copyright (c) 2023 Gwenhael Goavec-Merou <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import os | ||
|
||
from litex.build.generic_platform import GenericPlatform | ||
from litex.build.colognechip import common, colognechip | ||
|
||
# CologneChipPlatform ------------------------------------------------------------------------------ | ||
|
||
class CologneChipPlatform(GenericPlatform): | ||
bitstream_ext = "_00.cfg.bit" | ||
|
||
_supported_toolchains = ["colognechip"] | ||
|
||
def __init__(self, device, *args, toolchain="colognechip", devicename=None, **kwargs): | ||
GenericPlatform.__init__(self, device, *args, **kwargs) | ||
|
||
self.toolchain = colognechip.CologneChipToolchain() | ||
|
||
def get_verilog(self, *args, special_overrides=dict(), **kwargs): | ||
so = dict(common.colognechip_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) | ||
|
||
def add_period_constraint(self, clk, period): | ||
if clk is None: return | ||
self.toolchain.add_period_constraint(self, clk, period) | ||
|
||
@classmethod | ||
def fill_args(cls, toolchain, parser): | ||
""" | ||
pass parser to the specific toolchain to | ||
fill this with toolchain args | ||
Parameters | ||
========== | ||
toolchain: str | ||
toolchain name | ||
parser: argparse.ArgumentParser | ||
parser to be filled | ||
""" | ||
colognechip.colognechip_args(parser) | ||
|
||
@classmethod | ||
def get_argdict(cls, toolchain, args): | ||
""" | ||
return a dict of args | ||
Parameters | ||
========== | ||
toolchain: str | ||
toolchain name | ||
Return | ||
====== | ||
a dict of key/value for each args or an empty dict | ||
""" | ||
return colognechip.colognechip_argdict(args) |