Merge pull request #17 from mithro/master
[litex.git] / litex / soc / integration / soc_core.py
1 from operator import itemgetter
2
3 from litex.gen import *
4
5 from litex.soc.cores import identifier, timer, uart
6 from litex.soc.cores.cpu import lm32, mor1kx, picorv32
7 from litex.soc.interconnect import wishbone, csr_bus, wishbone2csr
8
9
10 __all__ = ["mem_decoder", "SoCCore", "soc_core_args", "soc_core_argdict"]
11
12
13 def mem_decoder(address, start=26, end=29):
14 return lambda a: a[start:end] == ((address >> (start+2)) & (2**(end-start))-1)
15
16
17 class SoCCore(Module):
18 csr_map = {
19 "crg": 0, # user
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)
24 "buttons": 5, # user
25 "leds": 6, # user
26 }
27 interrupt_map = {
28 "uart": 0,
29 "timer0": 1,
30 }
31 mem_map = {
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)
36 }
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,
45 ident="",
46 with_timer=True):
47 self.platform = platform
48 self.clk_freq = clk_freq
49
50 self.cpu_type = cpu_type
51 if integrated_rom_size:
52 cpu_reset_address = 0
53 self.cpu_reset_address = cpu_reset_address
54
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
58
59 self.with_uart = with_uart
60 self.uart_baudrate = uart_baudrate
61
62 self.shadow_base = shadow_base
63
64 self.csr_data_width = csr_data_width
65 self.csr_address_width = csr_address_width
66
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)
70
71 self._wb_masters = []
72 self._wb_slaves = []
73
74 self.config = dict()
75
76 if cpu_type is not None:
77 if cpu_type == "lm32":
78 self.add_cpu_or_bridge(lm32.LM32(platform, self.cpu_reset_address))
79 elif cpu_type == "or1k":
80 self.add_cpu_or_bridge(mor1kx.MOR1KX(platform, self.cpu_reset_address))
81 elif cpu_type == "riscv32":
82 self.add_cpu_or_bridge(picorv32.PicoRV32(platform, self.cpu_reset_address))
83 else:
84 raise ValueError("Unsupported CPU type: {}".format(cpu_type))
85 self.add_wb_master(self.cpu_or_bridge.ibus)
86 self.add_wb_master(self.cpu_or_bridge.dbus)
87 self.config["CPU_TYPE"] = str(cpu_type).upper()
88
89 if integrated_rom_size:
90 self.submodules.rom = wishbone.SRAM(integrated_rom_size, read_only=True)
91 self.register_rom(self.rom.bus, integrated_rom_size)
92
93 if integrated_sram_size:
94 self.submodules.sram = wishbone.SRAM(integrated_sram_size)
95 self.register_mem("sram", self.mem_map["sram"], self.sram.bus, integrated_sram_size)
96
97 # Note: Main Ram can be used when no external SDRAM is available and use SDRAM mapping.
98 if integrated_main_ram_size:
99 self.submodules.main_ram = wishbone.SRAM(integrated_main_ram_size)
100 self.register_mem("main_ram", self.mem_map["main_ram"], self.main_ram.bus, integrated_main_ram_size)
101
102 self.submodules.wishbone2csr = wishbone2csr.WB2CSR(
103 bus_csr=csr_bus.Interface(csr_data_width, csr_address_width))
104 self.config["CSR_DATA_WIDTH"] = csr_data_width
105 self.add_constant("CSR_DATA_WIDTH", csr_data_width)
106 self.register_mem("csr", self.mem_map["csr"], self.wishbone2csr.wishbone)
107
108 if with_uart:
109 self.submodules.uart_phy = uart.RS232PHY(platform.request("serial"), clk_freq, uart_baudrate)
110 self.submodules.uart = uart.UART(self.uart_phy)
111
112 if ident:
113 self.submodules.identifier = identifier.Identifier(ident)
114 self.config["CLOCK_FREQUENCY"] = int(clk_freq)
115 self.add_constant("SYSTEM_CLOCK_FREQUENCY", int(clk_freq))
116
117 if with_timer:
118 self.submodules.timer0 = timer.Timer()
119
120 def add_cpu_or_bridge(self, cpu_or_bridge):
121 if self.finalized:
122 raise FinalizeError
123 if hasattr(self, "cpu_or_bridge"):
124 raise NotImplementedError("More than one CPU is not supported")
125 self.submodules.cpu_or_bridge = cpu_or_bridge
126
127 def initialize_rom(self, data):
128 self.rom.mem.init = data
129
130 def add_wb_master(self, wbm):
131 if self.finalized:
132 raise FinalizeError
133 self._wb_masters.append(wbm)
134
135 def add_wb_slave(self, address_decoder, interface):
136 if self.finalized:
137 raise FinalizeError
138 self._wb_slaves.append((address_decoder, interface))
139
140 def add_memory_region(self, name, origin, length):
141 def in_this_region(addr):
142 return addr >= origin and addr < origin + length
143 for n, o, l in self._memory_regions:
144 if n == name or in_this_region(o) or in_this_region(o+l-1):
145 raise ValueError("Memory region conflict between {} and {}".format(n, name))
146
147 self._memory_regions.append((name, origin, length))
148
149 def register_mem(self, name, address, interface, size=None):
150 self.add_wb_slave(mem_decoder(address), interface)
151 if size is not None:
152 self.add_memory_region(name, address, size)
153
154 def register_rom(self, interface, rom_size=0xa000):
155 self.add_wb_slave(mem_decoder(self.mem_map["rom"]), interface)
156 self.add_memory_region("rom", self.cpu_reset_address, rom_size)
157
158 def get_memory_regions(self):
159 return self._memory_regions
160
161 def check_csr_region(self, name, origin):
162 for n, o, l, obj in self._csr_regions:
163 if n == name or o == origin:
164 raise ValueError("CSR region conflict between {} and {}".format(n, name))
165
166 def add_csr_region(self, name, origin, busword, obj):
167 self.check_csr_region(name, origin)
168 self._csr_regions.append((name, origin, busword, obj))
169
170 def get_csr_regions(self):
171 return self._csr_regions
172
173 def add_constant(self, name, value=None):
174 self._constants.append((name, value))
175
176 def get_constants(self):
177 r = []
178 for name, interrupt in sorted(self.interrupt_map.items(), key=itemgetter(1)):
179 r.append((name.upper() + "_INTERRUPT", interrupt))
180 r += self._constants
181 return r
182
183 def get_csr_dev_address(self, name, memory):
184 if memory is not None:
185 name = name + "_" + memory.name_override
186 try:
187 return self.csr_map[name]
188 except ValueError:
189 return None
190
191 def do_finalize(self):
192 registered_mems = {regions[0] for regions in self._memory_regions}
193 if self.cpu_type is not None:
194 for mem in "rom", "sram":
195 if mem not in registered_mems:
196 raise FinalizeError("CPU needs a {} to be registered with SoC.register_mem()".format(mem))
197
198 if len(self._wb_masters):
199 # Wishbone
200 self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
201 self._wb_slaves, register=True)
202
203 # CSR
204 self.submodules.csrbankarray = csr_bus.CSRBankArray(self,
205 self.get_csr_dev_address,
206 data_width=self.csr_data_width, address_width=self.csr_address_width)
207 self.submodules.csrcon = csr_bus.Interconnect(
208 self.wishbone2csr.csr, self.csrbankarray.get_buses())
209 for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
210 self.add_csr_region(name, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, csrs)
211 for name, memory, mapaddr, mmap in self.csrbankarray.srams:
212 self.add_csr_region(name + "_" + memory.name_override, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, memory)
213 for name, constant in self.csrbankarray.constants:
214 self._constants.append(((name + "_" + constant.name).upper(), constant.value.value))
215 for name, value in sorted(self.config.items(), key=itemgetter(0)):
216 self._constants.append(("CONFIG_" + name.upper(), value))
217
218 # Interrupts
219 if hasattr(self.cpu_or_bridge, "interrupt"):
220 for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)):
221 if hasattr(self, k):
222 self.comb += self.cpu_or_bridge.interrupt[v].eq(getattr(self, k).ev.irq)
223
224 def build(self, *args, **kwargs):
225 return self.platform.build(self, *args, **kwargs)
226
227
228 def soc_core_args(parser):
229 parser.add_argument("--cpu-type", default=None,
230 help="select CPU: lm32, or1k, riscv32")
231 parser.add_argument("--integrated-rom-size", default=None, type=int,
232 help="size/enable the integrated (BIOS) ROM")
233 parser.add_argument("--integrated-main-ram-size", default=None, type=int,
234 help="size/enable the integrated main RAM")
235
236
237 def soc_core_argdict(args):
238 r = dict()
239 for a in "cpu_type", "integrated_rom_size", "integrated_main_ram_size":
240 arg = getattr(args, a)
241 if arg is not None:
242 r[a] = arg
243 return r