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