1 from operator
import itemgetter
3 from litex
.gen
import *
5 from litex
.soc
.cores
import identifier
, timer
, uart
6 from litex
.soc
.cores
.cpu
import lm32
, mor1kx
7 from litex
.soc
.interconnect
import wishbone
, csr_bus
, wishbone2csr
10 __all__
= ["mem_decoder", "SoCCore", "soc_core_args", "soc_core_argdict"]
13 def mem_decoder(address
, start
=26, end
=29):
14 return lambda a
: a
[start
:end
] == ((address
>> (start
+2)) & (2**(end
-start
))-1)
17 class SoCCore(Module
):
20 "uart_phy": 1, # provided by default (optional)
21 "uart": 2, # provided by default (optional)
22 "identifier_mem": 3, # provided by default (optional)
23 "timer0": 4, # provided by default (optional)
32 "rom": 0x00000000, # (default shadow @0x80000000)
33 "sram": 0x10000000, # (default shadow @0x90000000)
34 "main_ram": 0x40000000, # (default shadow @0xc0000000)
35 "csr": 0x60000000, # (default shadow @0xe0000000)
37 def __init__(self
, platform
, clk_freq
,
38 cpu_type
="lm32", cpu_reset_address
=0x00000000,
39 integrated_rom_size
=0,
40 integrated_sram_size
=4096,
41 integrated_main_ram_size
=0,
42 shadow_base
=0x80000000,
43 csr_data_width
=8, csr_address_width
=14,
44 with_uart
=True, uart_baudrate
=115200,
47 self
.platform
= platform
48 self
.clk_freq
= clk_freq
50 self
.cpu_type
= cpu_type
51 if integrated_rom_size
:
53 self
.cpu_reset_address
= cpu_reset_address
55 self
.integrated_rom_size
= integrated_rom_size
56 self
.integrated_sram_size
= integrated_sram_size
57 self
.integrated_main_ram_size
= integrated_main_ram_size
59 self
.with_uart
= with_uart
60 self
.uart_baudrate
= uart_baudrate
62 self
.shadow_base
= shadow_base
64 self
.csr_data_width
= csr_data_width
65 self
.csr_address_width
= csr_address_width
67 self
._memory
_regions
= [] # list of (name, origin, length)
68 self
._csr
_regions
= [] # list of (name, origin, busword, csr_list/Memory)
69 self
._constants
= [] # list of (name, value)
74 if cpu_type
is not None:
75 if cpu_type
== "lm32":
76 self
.add_cpu_or_bridge(lm32
.LM32(platform
, self
.cpu_reset_address
))
77 elif cpu_type
== "or1k":
78 self
.add_cpu_or_bridge(mor1kx
.MOR1KX(platform
, self
.cpu_reset_address
))
80 raise ValueError("Unsupported CPU type: {}".format(cpu_type
))
81 self
.add_wb_master(self
.cpu_or_bridge
.ibus
)
82 self
.add_wb_master(self
.cpu_or_bridge
.dbus
)
84 if integrated_rom_size
:
85 self
.submodules
.rom
= wishbone
.SRAM(integrated_rom_size
, read_only
=True)
86 self
.register_rom(self
.rom
.bus
, integrated_rom_size
)
88 if integrated_sram_size
:
89 self
.submodules
.sram
= wishbone
.SRAM(integrated_sram_size
)
90 self
.register_mem("sram", self
.mem_map
["sram"], self
.sram
.bus
, integrated_sram_size
)
92 # Note: Main Ram can be used when no external SDRAM is available and use SDRAM mapping.
93 if integrated_main_ram_size
:
94 self
.submodules
.main_ram
= wishbone
.SRAM(integrated_main_ram_size
)
95 self
.register_mem("main_ram", self
.mem_map
["main_ram"], self
.main_ram
.bus
, integrated_main_ram_size
)
97 self
.submodules
.wishbone2csr
= wishbone2csr
.WB2CSR(
98 bus_csr
=csr_bus
.Interface(csr_data_width
, csr_address_width
))
99 self
.register_mem("csr", self
.mem_map
["csr"], self
.wishbone2csr
.wishbone
)
102 self
.submodules
.uart_phy
= uart
.RS232PHY(platform
.request("serial"), clk_freq
, uart_baudrate
)
103 self
.submodules
.uart
= uart
.UART(self
.uart_phy
)
106 self
.submodules
.identifier
= identifier
.Identifier(ident
)
107 self
.add_constant("SYSTEM_CLOCK_FREQUENCY", int(clk_freq
))
110 self
.submodules
.timer0
= timer
.Timer()
112 def add_cpu_or_bridge(self
, cpu_or_bridge
):
115 if hasattr(self
, "cpu_or_bridge"):
116 raise NotImplementedError("More than one CPU is not supported")
117 self
.submodules
.cpu_or_bridge
= cpu_or_bridge
119 def initialize_rom(self
, data
):
120 self
.rom
.mem
.init
= data
122 def add_wb_master(self
, wbm
):
125 self
._wb
_masters
.append(wbm
)
127 def add_wb_slave(self
, address_decoder
, interface
):
130 self
._wb
_slaves
.append((address_decoder
, interface
))
132 def add_memory_region(self
, name
, origin
, length
):
133 def in_this_region(addr
):
134 return addr
>= origin
and addr
< origin
+ length
135 for n
, o
, l
in self
._memory
_regions
:
136 if n
== name
or in_this_region(o
) or in_this_region(o
+l
-1):
137 raise ValueError("Memory region conflict between {} and {}".format(n
, name
))
139 self
._memory
_regions
.append((name
, origin
, length
))
141 def register_mem(self
, name
, address
, interface
, size
=None):
142 self
.add_wb_slave(mem_decoder(address
), interface
)
144 self
.add_memory_region(name
, address
, size
)
146 def register_rom(self
, interface
, rom_size
=0xa000):
147 self
.add_wb_slave(mem_decoder(self
.mem_map
["rom"]), interface
)
148 self
.add_memory_region("rom", self
.cpu_reset_address
, rom_size
)
150 def get_memory_regions(self
):
151 return self
._memory
_regions
153 def check_csr_region(self
, name
, origin
):
154 for n
, o
, l
, obj
in self
._csr
_regions
:
155 if n
== name
or o
== origin
:
156 raise ValueError("CSR region conflict between {} and {}".format(n
, name
))
158 def add_csr_region(self
, name
, origin
, busword
, obj
):
159 self
.check_csr_region(name
, origin
)
160 self
._csr
_regions
.append((name
, origin
, busword
, obj
))
162 def get_csr_regions(self
):
163 return self
._csr
_regions
165 def add_constant(self
, name
, value
=None):
166 self
._constants
.append((name
, value
))
168 def get_constants(self
):
170 for name
, interrupt
in sorted(self
.interrupt_map
.items(), key
=itemgetter(1)):
171 r
.append((name
.upper() + "_INTERRUPT", interrupt
))
175 def do_finalize(self
):
176 registered_mems
= {regions
[0] for regions
in self
._memory
_regions
}
177 if self
.cpu_type
is not None:
178 for mem
in "rom", "sram":
179 if mem
not in registered_mems
:
180 raise FinalizeError("CPU needs a {} to be registered with SoC.register_mem()".format(mem
))
183 self
.submodules
.wishbonecon
= wishbone
.InterconnectShared(self
._wb
_masters
,
184 self
._wb
_slaves
, register
=True)
187 self
.submodules
.csrbankarray
= csr_bus
.CSRBankArray(self
,
188 lambda name
, memory
: self
.csr_map
[name
if memory
is None else name
+ "_" + memory
.name_override
],
189 data_width
=self
.csr_data_width
, address_width
=self
.csr_address_width
)
190 self
.submodules
.csrcon
= csr_bus
.Interconnect(
191 self
.wishbone2csr
.csr
, self
.csrbankarray
.get_buses())
192 for name
, csrs
, mapaddr
, rmap
in self
.csrbankarray
.banks
:
193 self
.add_csr_region(name
, (self
.mem_map
["csr"] + 0x800*mapaddr
) | self
.shadow_base
, self
.csr_data_width
, csrs
)
194 for name
, memory
, mapaddr
, mmap
in self
.csrbankarray
.srams
:
195 self
.add_csr_region(name
+ "_" + memory
.name_override
, (self
.mem_map
["csr"] + 0x800*mapaddr
) | self
.shadow_base
, self
.csr_data_width
, memory
)
198 for k
, v
in sorted(self
.interrupt_map
.items(), key
=itemgetter(1)):
200 self
.comb
+= self
.cpu_or_bridge
.interrupt
[v
].eq(getattr(self
, k
).ev
.irq
)
202 def build(self
, *args
, **kwargs
):
203 self
.platform
.build(self
, *args
, **kwargs
)
206 def soc_core_args(parser
):
207 parser
.add_argument("--cpu-type", default
=None,
208 help="select CPU: lm32, or1k")
209 parser
.add_argument("--integrated-rom-size", default
=None, type=int,
210 help="size/enable the integrated (BIOS) ROM")
211 parser
.add_argument("--integrated-main-ram-size", default
=None, type=int,
212 help="size/enable the integrated main RAM")
215 def soc_core_argdict(args
):
217 for a
in "cpu_type", "integrated_rom_size", "integrated_main_ram_size":
218 arg
= getattr(args
, a
)