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