add extra variant to litex core
[soc.git] / src / soc / litex / florent / libresoc / core.py
1 import os
2
3 from migen import ClockSignal, ResetSignal, Signal, Instance, Cat
4
5 from litex.soc.interconnect import wishbone as wb
6 from litex.soc.cores.cpu import CPU
7
8 from soc.config.pinouts import get_pinspecs
9 from soc.debug.jtag import Pins
10 from c4m.nmigen.jtag.tap import IOType
11
12 from libresoc.ls180 import io
13 from litex.build.generic_platform import ConstraintManager
14
15
16 CPU_VARIANTS = ["standard", "standard32", "standardjtag", "ls180",
17 "standardjtagnoirq"]
18
19
20 def make_wb_bus(prefix, obj, simple=False):
21 res = {}
22 outpins = ['stb', 'cyc', 'we', 'adr', 'dat_w', 'sel']
23 if not simple:
24 outpins += ['cti', 'bte']
25 for o in outpins:
26 res['o_%s__%s' % (prefix, o)] = getattr(obj, o)
27 for i in ['ack', 'err', 'dat_r']:
28 res['i_%s__%s' % (prefix, i)] = getattr(obj, i)
29 return res
30
31 def make_wb_slave(prefix, obj):
32 res = {}
33 for i in ['stb', 'cyc', 'cti', 'bte', 'we', 'adr', 'dat_w', 'sel']:
34 res['i_%s__%s' % (prefix, i)] = getattr(obj, i)
35 for o in ['ack', 'err', 'dat_r']:
36 res['o_%s__%s' % (prefix, o)] = getattr(obj, o)
37 return res
38
39 def make_pad(res, dirn, name, suffix, cpup, iop):
40 cpud, iod = ('i', 'o') if dirn else ('o', 'i')
41 res['%s_%s__core__%s' % (cpud, name, suffix)] = cpup
42 res['%s_%s__pad__%s' % (iod, name, suffix)] = iop
43
44 def get_field(rec, name):
45 for f in rec.layout:
46 f = f[0]
47 if f.endswith(name):
48 return getattr(rec, f)
49
50
51 def make_jtag_ioconn(res, pin, cpupads, iopads):
52 (fn, pin, iotype, pin_name, scan_idx) = pin
53 #serial_tx__core__o, serial_rx__pad__i,
54 # special-case sdram_clock
55 if pin == 'clock' and fn == 'sdr':
56 cpu = cpupads['sdram_clock']
57 io = iopads['sdram_clock']
58 else:
59 cpu = cpupads[fn]
60 io = iopads[fn]
61 print ("cpupads", cpupads)
62 print ("iopads", iopads)
63 print ("pin", fn, pin, iotype, pin_name)
64 print ("cpu fn", cpu)
65 print ("io fn", io)
66 name = "%s_%s" % (fn, pin)
67 print ("name", name)
68 sigs = []
69
70 if iotype in (IOType.In, IOType.Out):
71 ps = pin.split("_")
72 if pin == 'clock' and fn == 'sdr':
73 cpup = cpu
74 iop = io
75 elif len(ps) == 2 and ps[-1].isdigit():
76 pin, idx = ps
77 idx = int(idx)
78 cpup = getattr(cpu, pin)[idx]
79 iop = getattr(io, pin)[idx]
80 elif pin.isdigit():
81 idx = int(pin)
82 cpup = cpu[idx]
83 iop = io[idx]
84 else:
85 cpup = getattr(cpu, pin)
86 iop = getattr(io, pin)
87
88 if iotype == IOType.Out:
89 # output from the pad is routed through C4M JTAG and so
90 # is an *INPUT* into core. ls180soc connects this to "real" peripheral
91 make_pad(res, True, name, "o", cpup, iop)
92
93 elif iotype == IOType.In:
94 # input to the pad is routed through C4M JTAG and so
95 # is an *OUTPUT* into core. ls180soc connects this to "real" peripheral
96 make_pad(res, False, name, "i", cpup, iop)
97
98 elif iotype == IOType.InTriOut:
99 if fn == 'gpio': # sigh decode GPIO special-case
100 idx = int(pin[1:])
101 else:
102 idx = 0
103 cpup, iop = get_field(cpu, "i")[idx], get_field(io, "i")[idx]
104 make_pad(res, False, name, "i", cpup, iop)
105 cpup, iop = get_field(cpu, "o")[idx], get_field(io, "o")[idx]
106 make_pad(res, True, name, "o", cpup, iop)
107 cpup, iop = get_field(cpu, "oe")[idx], get_field(io, "oe")[idx]
108 make_pad(res, True, name, "oe", cpup, iop)
109
110 if iotype in (IOType.In, IOType.InTriOut):
111 sigs.append(("i", 1))
112 if iotype in (IOType.Out, IOType.TriOut, IOType.InTriOut):
113 sigs.append(("o", 1))
114 if iotype in (IOType.TriOut, IOType.InTriOut):
115 sigs.append(("oe", 1))
116
117
118 class LibreSoC(CPU):
119 name = "libre_soc"
120 human_name = "Libre-SoC"
121 variants = CPU_VARIANTS
122 endianness = "little"
123 gcc_triple = ("powerpc64le-linux", "powerpc64le-linux-gnu")
124 linker_output_format = "elf64-powerpcle"
125 nop = "nop"
126 io_regions = {0xc0000000: 0x10000000} # origin, length
127
128 @property
129 def mem_map(self):
130 return {"csr": 0xc0000000}
131
132 @property
133 def gcc_flags(self):
134 flags = "-m64 "
135 flags += "-mabi=elfv2 "
136 flags += "-msoft-float "
137 flags += "-mno-string "
138 flags += "-mno-multiple "
139 flags += "-mno-vsx "
140 flags += "-mno-altivec "
141 flags += "-mlittle-endian "
142 flags += "-mstrict-align "
143 flags += "-fno-stack-protector "
144 flags += "-mcmodel=small "
145 flags += "-D__microwatt__ "
146 return flags
147
148 def __init__(self, platform, variant="standard"):
149 self.platform = platform
150 self.variant = variant
151 self.reset = Signal()
152 irq_en = "noirq" not in variant
153
154 if irq_en:
155 self.interrupt = Signal(16)
156
157 if variant == "standard32":
158 self.data_width = 32
159 self.dbus = dbus = wb.Interface(data_width=32, adr_width=30)
160 else:
161 self.dbus = dbus = wb.Interface(data_width=64, adr_width=29)
162 self.data_width = 64
163 self.ibus = ibus = wb.Interface(data_width=64, adr_width=29)
164
165 self.xics_icp = icp = wb.Interface(data_width=32, adr_width=30)
166 self.xics_ics = ics = wb.Interface(data_width=32, adr_width=30)
167
168 jtag_en = ('jtag' in variant) or variant == 'ls180'
169
170 if "gpiotest" in variant:
171 self.simple_gpio = gpio = wb.Interface(data_width=32, adr_width=30)
172 if jtag_en:
173 self.jtag_wb = jtag_wb = wb.Interface(data_width=64, adr_width=29)
174
175 self.periph_buses = [ibus, dbus]
176 self.memory_buses = []
177
178 if jtag_en:
179 self.periph_buses.append(jtag_wb)
180 self.jtag_tck = Signal(1)
181 self.jtag_tms = Signal(1)
182 self.jtag_tdi = Signal(1)
183 self.jtag_tdo = Signal(1)
184 else:
185 self.dmi_addr = Signal(4)
186 self.dmi_din = Signal(64)
187 self.dmi_dout = Signal(64)
188 self.dmi_wr = Signal(1)
189 self.dmi_ack = Signal(1)
190 self.dmi_req = Signal(1)
191
192 # # #
193
194 self.cpu_params = dict(
195 # Clock / Reset
196 i_clk = ClockSignal(),
197 i_rst = ResetSignal() | self.reset,
198
199 # Monitoring / Debugging
200 i_pc_i = 0,
201 i_pc_i_ok = 0,
202 i_core_bigendian_i = 0, # Signal(),
203 o_busy_o = Signal(), # not connected
204 o_memerr_o = Signal(), # not connected
205 o_pc_o = Signal(64), # not connected
206
207 )
208
209 if irq_en:
210 # interrupts
211 self.cpu_params['i_int_level_i'] = self.interrupt
212
213 if jtag_en:
214 self.cpu_params.update(dict(
215 # JTAG Debug bus
216 o_TAP_bus__tdo = self.jtag_tdo,
217 i_TAP_bus__tdi = self.jtag_tdi,
218 i_TAP_bus__tms = self.jtag_tms,
219 i_TAP_bus__tck = self.jtag_tck,
220 ))
221 else:
222 self.cpu_params.update(dict(
223 # DMI Debug bus
224 i_dmi_addr_i = self.dmi_addr,
225 i_dmi_din = self.dmi_din,
226 o_dmi_dout = self.dmi_dout,
227 i_dmi_req_i = self.dmi_req,
228 i_dmi_we_i = self.dmi_wr,
229 o_dmi_ack_o = self.dmi_ack,
230 ))
231
232 # add clock select, pll output
233 if variant == "ls180":
234 self.pll_48_o = Signal()
235 self.clk_sel = Signal(3)
236 self.cpu_params['i_clk_sel_i'] = self.clk_sel
237 self.cpu_params['o_pll_48_o'] = self.pll_48_o
238
239 # add wishbone buses to cpu params
240 self.cpu_params.update(make_wb_bus("ibus", ibus))
241 self.cpu_params.update(make_wb_bus("dbus", dbus))
242 self.cpu_params.update(make_wb_slave("ics_wb", ics))
243 self.cpu_params.update(make_wb_slave("icp_wb", icp))
244 if "gpiotest" in variant:
245 self.cpu_params.update(make_wb_slave("gpio_wb", gpio))
246 if jtag_en:
247 self.cpu_params.update(make_wb_bus("jtag_wb", jtag_wb, simple=True))
248
249 if variant == 'ls180':
250 # urr yuk. have to expose iopads / pins from core to litex
251 # then back again. cut _some_ of that out by connecting
252 self.padresources = io()
253 self.pad_cm = ConstraintManager(self.padresources, [])
254 self.cpupads = {}
255 iopads = {}
256 litexmap = {}
257 subset = {'uart', 'mtwi', 'eint', 'gpio', 'mspi0', 'mspi1',
258 'pwm', 'sd0', 'sdr'}
259 for periph in subset:
260 origperiph = periph
261 num = None
262 if periph[-1].isdigit():
263 periph, num = periph[:-1], int(periph[-1])
264 print ("periph request", periph, num)
265 if periph == 'mspi':
266 if num == 0:
267 periph, num = 'spimaster', None
268 else:
269 periph, num = 'spisdcard', None
270 elif periph == 'sdr':
271 periph = 'sdram'
272 elif periph == 'mtwi':
273 periph = 'i2c'
274 elif periph == 'sd':
275 periph, num = 'sdcard', None
276 litexmap[origperiph] = (periph, num)
277 self.cpupads[origperiph] = platform.request(periph, num)
278 iopads[origperiph] = self.pad_cm.request(periph, num)
279 if periph == 'sdram':
280 # special-case sdram clock
281 ck = platform.request("sdram_clock")
282 self.cpupads['sdram_clock'] = ck
283 ck = self.pad_cm.request("sdram_clock")
284 iopads['sdram_clock'] = ck
285
286 pinset = get_pinspecs(subset=subset)
287 p = Pins(pinset)
288 for pin in list(p):
289 make_jtag_ioconn(self.cpu_params, pin, self.cpupads, iopads)
290
291 # add verilog sources
292 self.add_sources(platform)
293
294 def set_reset_address(self, reset_address):
295 assert not hasattr(self, "reset_address")
296 self.reset_address = reset_address
297 assert reset_address == 0x00000000
298
299 @staticmethod
300 def add_sources(platform):
301 cdir = os.path.dirname(__file__)
302 platform.add_source(os.path.join(cdir, "libresoc.v"))
303
304 def do_finalize(self):
305 self.specials += Instance("test_issuer", **self.cpu_params)
306