import os
+from nmigen_soc.periph import ConstantMap, ConstantBool, ConstantInt
+
from .base import *
from ..cpu import CPU
+from ..cores import litedram
from ..periph.intc import InterruptController
from ..periph.sram import SRAMPeripheral
-from ..periph.sdram import SDRAMPeripheral
from ..periph.serial import AsyncSerialPeripheral
from ..periph.timer import TimerPeripheral
class CPUSoC(SoC):
- cpu = socproperty(CPU)
- intc = socproperty(InterruptController)
- rom = socproperty(SRAMPeripheral)
- ram = socproperty(SRAMPeripheral)
- sdram = socproperty(SDRAMPeripheral, weak=True)
- uart = socproperty(AsyncSerialPeripheral)
- timer = socproperty(TimerPeripheral)
+ cpu = socproperty(CPU)
+ intc = socproperty(InterruptController)
+ bootrom = socproperty(SRAMPeripheral)
+ scratchpad = socproperty(SRAMPeripheral)
+ uart = socproperty(AsyncSerialPeripheral)
+ timer = socproperty(TimerPeripheral)
# TODO: implement a CRG peripheral and expose clock frequencies through CSRs.
- clk_freq = socproperty(int)
-
- def build(self, name=None,
- litedram_dir="build/litedram",
- build_dir="build/soc", do_build=True,
- do_init=False):
+ sync_clk_freq = socproperty(int)
+
+ @property
+ def constants(self):
+ return ConstantMapCollection(
+ CPU = self.cpu.constant_map,
+ INTC = self.intc.constant_map,
+ BOOTROM = self.bootrom.constant_map,
+ SCRATCHPAD = self.scratchpad.constant_map,
+ UART = self.uart.constant_map,
+ TIMER = self.timer.constant_map,
+ SOC = ConstantMap(
+ CLOCK_FREQ = self.sync_clk_freq,
+ CSR_DATA_WIDTH = 32,
+ ),
+ )
+
+ def build(self, build_dir, name=None, do_build=True, do_init=False):
"""TODO
"""
- plan = BIOSBuilder().prepare(self, build_dir, name,
- litedram_dir=os.path.abspath(litedram_dir))
+ plan = BIOSBuilder().prepare(self, build_dir, name)
if not do_build:
return plan
if not do_init:
return products
- with products.extract("bios/bios.bin") as bios_filename:
+ with products.extract(f"{__name__}/bios/bios.bin") as bios_filename:
with open(bios_filename, "rb") as f:
words = iter(lambda: f.read(self.cpu.data_width // 8), b'')
bios = [int.from_bytes(w, self.cpu.byteorder) for w in words]
- self.rom.init = bios
+ self.bootrom.init = bios
+
+
+def kconfig_format(key, const, prefix="CONFIG_"):
+ if not isinstance(key, str) or not key:
+ raise ValueError("Key must be a non-empty string, not {!r}".format(key))
+ if isinstance(const, ConstantBool):
+ value = "y" if const.value else "n"
+ elif isinstance(const, ConstantAddr):
+ value = hex(const.value)
+ elif isinstance(const, ConstantInt):
+ value = const.value
+ else:
+ raise TypeError("Unsupported constant type, must be ConstantBool, ConstantAddr or "
+ "ConstantInt, not {!r}"
+ .format(const))
+ return "{}{}={}".format(prefix, key.upper(), value)
+
+
+def cpp_format(key, const, prefix=""):
+ if not isinstance(key, str) or not key:
+ raise ValueError("Key must be a non-empty string, not {!r}".format(key))
+ if isinstance(const, ConstantBool):
+ value = 1 if const.value else 0
+ elif isinstance(const, ConstantAddr):
+ value = "{:#x}UL".format(const.value)
+ elif isinstance(const, ConstantInt):
+ value = "{}{}".format(const.value, "U" if not const.signed else "")
+ else:
+ raise TypeError("Unsupported constant type, must be ConstantBool, ConstantAddr or "
+ "ConstantInt, not {!r}"
+ .format(const))
+ return "#define {}{} {}".format(prefix, key.upper(), value)
class BIOSBuilder(ConfigBuilder):
file_templates = {
**ConfigBuilder.file_templates,
- "{{name}}.config": r"""
+ "/".join([__name__, "{{name}}.config"]): r"""
# {{autogenerated}}
- CONFIG_CPU_{{soc.cpu.name.upper()}}=y
- CONFIG_CPU_RESET_ADDR={{hex(soc.cpu.reset_addr)}}
- CONFIG_CPU_BYTEORDER="{{soc.cpu.byteorder}}"
- CONFIG_ARCH_{{soc.cpu.arch.upper()}}=y
- {% if soc.cpu.muldiv == "soft" %}
- CONFIG_{{soc.cpu.arch.upper()}}_MULDIV_SOFT=y
- {% else %}
- CONFIG_{{soc.cpu.arch.upper()}}_MULDIV_SOFT=n
- {% endif %}
- CONFIG_ROM_START={{hex(periph_addr(soc.rom))}}
- CONFIG_ROM_SIZE={{hex(soc.rom.size)}}
- CONFIG_RAM_START={{hex(periph_addr(soc.ram))}}
- CONFIG_RAM_SIZE={{hex(soc.ram.size)}}
- CONFIG_UART_START={{hex(periph_addr(soc.uart))}}
- CONFIG_UART_IRQNO={{soc.intc.find_index(soc.uart.irq)}}
- CONFIG_UART_RX_RINGBUF_SIZE_LOG2=7
- CONFIG_UART_TX_RINGBUF_SIZE_LOG2=7
- CONFIG_TIMER_START={{hex(periph_addr(soc.timer))}}
- CONFIG_TIMER_IRQNO={{soc.intc.find_index(soc.timer.irq)}}
- CONFIG_TIMER_CTR_WIDTH={{soc.timer.width}}
- CONFIG_CLOCK_FREQ={{soc.clk_freq}}
- {% if soc.sdram is not none %}
- CONFIG_WITH_SDRAM=y
- CONFIG_SDRAM_START={{hex(periph_addr(soc.sdram))}}
- CONFIG_SDRAM_SIZE={{hex(soc.sdram.core.size)}}
- {% else %}
- CONFIG_WITH_SDRAM=n
- {% endif %}
+ # Configuration constants
+ {% for key, value in constants.flatten(separator="_") %}
+ {{kconfig_format(key, value)}}
+ {% endfor %}
+
+ # Memory regions
+ {% for window, (start, stop, step) in soc.memory_map.windows() %}
+ {% set window_name = window.name.upper() %}
+ {{kconfig_format(window_name + "_BASE", ConstantAddr(start))}}
+ {{kconfig_format(window_name + "_LIMIT", ConstantAddr(stop))}}
+ {% endfor %}
""",
- "litex_config.h": r"""
+ "/".join([__name__, "litex_config.h"]): r"""
// {{autogenerated}}
#ifndef __LITEX_CONFIG_H_LAMBDASOC
#define __LITEX_CONFIG_H_LAMBDASOC
- #define LX_CONFIG_TIMER_START {{hex(periph_addr(soc.timer))}}
+ // Configuration constants
+ {% for key, value in constants.flatten(separator="_") %}
+ {{cpp_format(key, value, prefix="LX_CONFIG_")}}
+ {% endfor %}
+
+ // Memory regions
+ {% for window, (start, stop, step) in soc.memory_map.windows() %}
+ {% set window_name = window.name.upper() %}
+ {{cpp_format(window_name + "_BASE", ConstantAddr(start), prefix="LX_CONFIG_")}}
+ {{cpp_format(window_name + "_LIMIT", ConstantAddr(stop), prefix="LX_CONFIG_")}}
+ {% endfor %}
{% if soc.sdram is not none %}
- #define LX_CONFIG_SDRAM_START {{hex(periph_addr(soc.sdram))}}UL
- #define LX_CONFIG_SDRAM_SIZE {{hex(soc.sdram.core.size)}}UL
- #define LX_CONFIG_SDRAM_CACHE_SIZE {{soc.sdram._cache.size}}
- #define LX_CONFIG_MEMTEST_DATA_SIZE 2*1024*1024
- #define LX_CONFIG_MEMTEST_ADDR_SIZE 65536
+ #define LX_CONFIG_MAIN_RAM_BASE LX_CONFIG_SDRAM_BASE
+ #define LX_CONFIG_MAIN_RAM_SIZE LX_CONFIG_SDRAM_SIZE
+ {% else %}
+ #define LX_CONFIG_MAIN_RAM_BASE LX_CONFIG_SRAM_BASE
+ #define LX_CONFIG_MAIN_RAM_SIZE LX_CONFIG_SRAM_SIZE
{% endif %}
#endif
*ConfigBuilder.command_templates,
r"""
{% if soc.sdram is not none %}
- litedram_dir={{litedram_dir}}/{{soc.sdram.core.name}}
+ litedram_dir={{build_dir}}/{{litedram_pkg}}/{{soc.sdram.core.name}}
{% endif %}
- build={{build_dir}}
- KCONFIG_CONFIG={{build_dir}}/{{name}}.config
+ build={{bios_dir}}
+ KCONFIG_CONFIG={{bios_dir}}/{{name}}.config
make -C {{software_dir}}/bios 1>&2
""",
]
- def prepare(self, soc, build_dir, name, litedram_dir):
+ def prepare(self, soc, build_dir, name, **render_params):
if not isinstance(soc, CPUSoC):
raise TypeError("SoC must be an instance of CPUSoC, not {!r}"
.format(soc))
- return super().prepare(soc, build_dir, name, litedram_dir=litedram_dir)
+
+ render_params.update({
+ "kconfig_format": kconfig_format,
+ "cpp_format": cpp_format,
+ "bios_dir": os.path.abspath(f"{build_dir}/{__name__}"),
+ "litedram_pkg": litedram.__name__,
+ })
+
+ return super().prepare(soc, build_dir, name, **render_params)