tools: Add initial LiteX standalone SoC generator.

Allow generating standalone SoC with CPU/Peripherals that can be re-integrated in
external design or top level LiteX SoCs.

Example of of use:
python3 litex_soc_gen.py --cpu-type=vexriscv --bus-standard=wishbone --build
python3 litex_soc_gen.py --cpu-type=naxriscv --bus-standard=axi-lite --build
This commit is contained in:
Florent Kermarrec 2022-05-05 17:33:12 +02:00
parent e7cee80670
commit e8b6200225
1 changed files with 126 additions and 0 deletions

126
litex/tools/litex_soc_gen.py Executable file
View File

@ -0,0 +1,126 @@
#!/usr/bin/env python3
#
# This file is part of LiteX.
#
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
"""
LiteX standalone SoC generator.
This generator reduces the scope of LiteX to CPU/Peripherals selection/integration and to the creation
of SoC with MMAP/Streaming DMA interfaces that can be reintegrated in external designs (or LiteX SoC).
Think of it as a mini Nios SOPC Builder/ Zynq or Microblaze Subsystem generator that offers you the
possibility to reuse any of CPU supported by LiteX :)
"""
import argparse
from migen import *
from litex.build.generic_platform import *
from litex.soc.integration.soc_core import *
from litex.soc.integration.soc import SoCRegion
from litex.soc.integration.builder import *
from litex.soc.interconnect import wishbone
from litex.soc.interconnect import axi
# IOs/Interfaces -----------------------------------------------------------------------------------
def get_common_ios():
return [
# Clk/Rst.
("clk", 0, Pins(1)),
("rst", 0, Pins(1)),
]
def get_uart_ios():
return [
# Serial
("uart", 0,
Subsignal("tx", Pins(1)),
Subsignal("rx", Pins(1)),
)
]
# Platform -----------------------------------------------------------------------------------------
class Platform(GenericPlatform):
def build(self, fragment, build_dir, build_name, **kwargs):
os.makedirs(build_dir, exist_ok=True)
os.chdir(build_dir)
conv_output = self.get_verilog(fragment, name=build_name)
conv_output.write(f"{build_name}.v")
# LiteX SoC Generator ------------------------------------------------------------------------------
class LiteXSoCGenerator(SoCMini):
def __init__(self, name="litex_soc", sys_clk_freq=int(50e6), **kwargs):
# Platform ---------------------------------------------------------------------------------
platform = Platform(device="", io=get_common_ios())
platform.name = name
platform.add_extension(get_uart_ios())
# CRG --------------------------------------------------------------------------------------
self.submodules.crg = CRG(
clk = platform.request("clk"),
rst = platform.request("rst"),
)
# SoC --------------------------------------------------------------------------------------
if kwargs["uart_name"] == "serial":
kwargs["uart_name"] = "uart"
SoCCore.__init__(self, platform, clk_freq=sys_clk_freq, **kwargs)
# MMAP Slave Interface ---------------------------------------------------------------------
s_bus = {
"wishbone" : wishbone.Interface(),
"axi-lite" : axi.AXILiteInterface(),
}[kwargs["bus_standard"]]
self.bus.add_master(name="mmap_s", master=s_bus)
platform.add_extension(s_bus.get_ios("mmap_s"))
wb_pads = platform.request("mmap_s")
self.comb += s_bus.connect_to_pads(wb_pads, mode="slave")
# MMAP Master Interface --------------------------------------------------------------------
# FIXME: Allow Region configuration.
m_bus = {
"wishbone" : wishbone.Interface(),
"axi-lite" : axi.AXILiteInterface(),
}[kwargs["bus_standard"]]
wb_region = SoCRegion(origin=0x2000_0000, size=0x1000_0000, cached=True) # FIXME.
self.bus.add_slave(name="mmap_m", slave=m_bus, region=wb_region)
platform.add_extension(m_bus.get_ios("mmap_m"))
wb_pads = platform.request("mmap_m")
self.comb += m_bus.connect_to_pads(wb_pads, mode="master")
# Build --------------------------------------------------------------------------------------------
def main():
# Arguments.
from litex.soc.integration.soc import LiteXSoCArgumentParser
parser = LiteXSoCArgumentParser(description="LiteX standalone SoC generator")
target_group = parser.add_argument_group(title="Generator options")
target_group.add_argument("--name", default="litex_soc", help="SoC Name.")
target_group.add_argument("--build", action="store_true", help="Build SoC.")
target_group.add_argument("--sys-clk-freq", default=int(50e6), help="System clock frequency.")
builder_args(parser)
soc_core_args(parser)
args = parser.parse_args()
# SoC.
soc = LiteXSoCGenerator(
name = args.name,
sys_clk_freq = int(float(args.sys_clk_freq)),
**soc_core_argdict(args)
)
# Build.
builder = Builder(soc, **builder_argdict(args))
builder.build(build_name=args.name, run=args.build)
if __name__ == "__main__":
main()