3 from nmigen_soc
.periph
import ConstantMap
, ConstantBool
, ConstantInt
7 from ..cores
import litedram
8 from ..periph
.intc
import InterruptController
9 from ..periph
.sram
import SRAMPeripheral
10 from ..periph
.serial
import AsyncSerialPeripheral
11 from ..periph
.timer
import TimerPeripheral
14 __all__
= ["CPUSoC", "BIOSBuilder"]
18 cpu
= socproperty(CPU
)
19 intc
= socproperty(InterruptController
)
20 bootrom
= socproperty(SRAMPeripheral
)
21 scratchpad
= socproperty(SRAMPeripheral
)
22 uart
= socproperty(AsyncSerialPeripheral
)
23 timer
= socproperty(TimerPeripheral
)
25 # TODO: implement a CRG peripheral and expose clock frequencies through CSRs.
26 sync_clk_freq
= socproperty(int)
30 return ConstantMapCollection(
31 CPU
= self
.cpu
.constant_map
,
32 INTC
= self
.intc
.constant_map
,
33 BOOTROM
= self
.bootrom
.constant_map
,
34 SCRATCHPAD
= self
.scratchpad
.constant_map
,
35 UART
= self
.uart
.constant_map
,
36 TIMER
= self
.timer
.constant_map
,
38 CLOCK_FREQ
= self
.sync_clk_freq
,
43 def build(self
, build_dir
, name
=None, do_build
=True, do_init
=False):
46 plan
= BIOSBuilder().prepare(self
, build_dir
, name
)
50 products
= plan
.execute_local(build_dir
)
54 with products
.extract(f
"{__name__}/bios/bios.bin") as bios_filename
:
55 with
open(bios_filename
, "rb") as f
:
56 words
= iter(lambda: f
.read(self
.cpu
.data_width
// 8), b
'')
57 bios
= [int.from_bytes(w
, self
.cpu
.byteorder
) for w
in words
]
58 self
.bootrom
.init
= bios
61 def kconfig_format(key
, const
, prefix
="CONFIG_"):
62 if not isinstance(key
, str) or not key
:
63 raise ValueError("Key must be a non-empty string, not {!r}".format(key
))
64 if isinstance(const
, ConstantBool
):
65 value
= "y" if const
.value
else "n"
66 elif isinstance(const
, ConstantAddr
):
67 value
= hex(const
.value
)
68 elif isinstance(const
, ConstantInt
):
71 raise TypeError("Unsupported constant type, must be ConstantBool, ConstantAddr or "
72 "ConstantInt, not {!r}"
74 return "{}{}={}".format(prefix
, key
.upper(), value
)
77 def cpp_format(key
, const
, prefix
=""):
78 if not isinstance(key
, str) or not key
:
79 raise ValueError("Key must be a non-empty string, not {!r}".format(key
))
80 if isinstance(const
, ConstantBool
):
81 value
= 1 if const
.value
else 0
82 elif isinstance(const
, ConstantAddr
):
83 value
= "{:#x}UL".format(const
.value
)
84 elif isinstance(const
, ConstantInt
):
85 value
= "{}{}".format(const
.value
, "U" if not const
.signed
else "")
87 raise TypeError("Unsupported constant type, must be ConstantBool, ConstantAddr or "
88 "ConstantInt, not {!r}"
90 return "#define {}{} {}".format(prefix
, key
.upper(), value
)
93 class BIOSBuilder(ConfigBuilder
):
95 **ConfigBuilder
.file_templates
,
96 "/".join([__name__
, "{{name}}.config"]): r
"""
99 # Configuration constants
100 {% for key, value in constants.flatten(separator="_") %}
101 {{kconfig_format(key, value)}}
105 {% for window, (start, stop, step) in soc.memory_map.windows() %}
106 {% set window_name = window.name.upper() %}
107 {{kconfig_format(window_name + "_BASE", ConstantAddr(start))}}
108 {{kconfig_format(window_name + "_LIMIT", ConstantAddr(stop))}}
111 "/".join([__name__
, "litex_config.h"]): r
"""
113 #ifndef __LITEX_CONFIG_H_LAMBDASOC
114 #define __LITEX_CONFIG_H_LAMBDASOC
116 // Configuration constants
117 {% for key, value in constants.flatten(separator="_") %}
118 {{cpp_format(key, value, prefix="LX_CONFIG_")}}
122 {% for window, (start, stop, step) in soc.memory_map.windows() %}
123 {% set window_name = window.name.upper() %}
124 {{cpp_format(window_name + "_BASE", ConstantAddr(start), prefix="LX_CONFIG_")}}
125 {{cpp_format(window_name + "_LIMIT", ConstantAddr(stop), prefix="LX_CONFIG_")}}
128 {% if soc.sdram is not none %}
129 #define LX_CONFIG_MAIN_RAM_BASE LX_CONFIG_SDRAM_BASE
130 #define LX_CONFIG_MAIN_RAM_SIZE LX_CONFIG_SDRAM_SIZE
132 #define LX_CONFIG_MAIN_RAM_BASE LX_CONFIG_SRAM_BASE
133 #define LX_CONFIG_MAIN_RAM_SIZE LX_CONFIG_SRAM_SIZE
139 command_templates
= [
140 *ConfigBuilder
.command_templates
,
142 {% if soc.sdram is not none %}
143 litedram_dir={{build_dir}}/{{litedram_pkg}}/{{soc.sdram.core.name}}
146 KCONFIG_CONFIG={{bios_dir}}/{{name}}.config
147 make -C {{software_dir}}/bios 1>&2
151 def prepare(self
, soc
, build_dir
, name
, **render_params
):
152 if not isinstance(soc
, CPUSoC
):
153 raise TypeError("SoC must be an instance of CPUSoC, not {!r}"
156 render_params
.update({
157 "kconfig_format": kconfig_format
,
158 "cpp_format": cpp_format
,
159 "bios_dir": os
.path
.abspath(f
"{build_dir}/{__name__}"),
160 "litedram_pkg": litedram
.__name
__,
163 return super().prepare(soc
, build_dir
, name
, **render_params
)