3 from migen
import ClockSignal
, ResetSignal
, Signal
, Instance
, Cat
5 from litex
.soc
.interconnect
import wishbone
as wb
6 from litex
.soc
.cores
.cpu
import CPU
8 from litex
.build
.generic_platform
import ConstraintManager
11 CPU_VARIANTS
= ["standard", "standard32", "standardjtag",
12 "standardjtagtestgpio", "ls180", "ls180sram4k",
17 def make_wb_bus(prefix
, obj
, simple
=False):
19 outpins
= ['stb', 'cyc', 'we', 'adr', 'dat_w', 'sel']
21 outpins
+= ['cti', 'bte']
23 res
['o_%s__%s' % (prefix
, o
)] = getattr(obj
, o
)
24 for i
in ['ack', 'err', 'dat_r']:
25 res
['i_%s__%s' % (prefix
, i
)] = getattr(obj
, i
)
28 def make_wb_slave(prefix
, obj
, simple
=False, err
=True):
30 inpins
= ['stb', 'cyc', 'we', 'adr', 'dat_w', 'sel']
32 inpins
+= ['cti', 'bte']
34 res
['i_%s__%s' % (prefix
, i
)] = getattr(obj
, i
)
35 outpins
= ['ack', 'dat_r']
39 res
['o_%s__%s' % (prefix
, o
)] = getattr(obj
, o
)
42 def make_pad(res
, dirn
, name
, suffix
, cpup
, iop
):
43 cpud
, iod
= ('i', 'o') if dirn
else ('o', 'i')
44 cname
= '%s_%s__core__%s' % (cpud
, name
, suffix
)
45 pname
= '%s_%s__pad__%s' % (iod
, name
, suffix
)
46 print ("make pad", name
, dirn
, cpud
, iod
, cname
, pname
, suffix
, cpup
, iop
)
47 res
[cname
], res
[pname
] = cpup
, iop
49 def get_field(rec
, name
):
52 print ("get_field", f
, name
)
56 return getattr(rec
, f
)
59 def make_jtag_ioconn(res
, pin
, cpupads
, iopads
):
60 # XXX normally this is NOT done, however to avoid import problems
61 # in litex, move the import into where it is optionally called
62 from c4m
.nmigen
.jtag
.tap
import IOType
64 (fn
, pin
, iotype
, pin_name
, scan_idx
) = pin
65 #serial_tx__core__o, serial_rx__pad__i,
66 # special-case sdram_clock
67 #if pin == 'clock' and fn == 'sdr':
68 # cpu = cpupads['sdram_clock']
69 # io = iopads['sdram_clock']
75 print ("make_jtag_ioconn", scan_idx
)
76 print ("cpupads", cpupads
)
77 print ("iopads", iopads
)
78 print ("pin", fn
, pin
, iotype
, pin_name
)
81 name
= "%s_%s" % (fn
, pin
)
85 if iotype
in (IOType
.In
, IOType
.Out
):
87 #if pin == 'clock' and fn == 'sdr':
90 if len(ps
) == 2 and ps
[-1].isdigit():
93 print ("ps split", pin
, idx
)
94 cpup
= getattr(cpu
, pin
)[idx
]
95 iop
= getattr(io
, pin
)[idx
]
96 elif pin
.isdigit() and fn
!= 'eint':
103 cpup
= getattr(cpu
, pin
)
104 iop
= getattr(io
, pin
)
106 if iotype
== IOType
.Out
:
107 # output from the pad is routed through C4M JTAG and so
108 # is an *INPUT* into core. ls180soc connects this to "real" peripheral
109 make_pad(res
, True, name
, "o", cpup
, iop
)
111 elif iotype
== IOType
.In
:
112 # input to the pad is routed through C4M JTAG and so
113 # is an *OUTPUT* into core. ls180soc connects this to "real" peripheral
114 make_pad(res
, False, name
, "i", cpup
, iop
)
116 elif iotype
== IOType
.InTriOut
:
117 if fn
== 'gpio': # sigh decode GPIO special-case
121 elif fn
.startswith('sd') and pin
.startswith('data'):
126 idx
= int(pin
.split('_')[-1])
128 pfx
= pin
.split('_')[0]+"_"
133 print ("gpio tri", fn
, pin
, iotype
, pin_name
, scan_idx
, idx
)
135 cpup
, iop
= get_field(cpu
, pfx
+"i")[idx
], \
136 get_field(io
, pfx
+"i")[idx
]
137 make_pad(res
, False, name
, "i", cpup
, iop
)
139 cpup
, iop
= get_field(cpu
, pfx
+"o")[idx
], \
140 get_field(io
, pfx
+"o")[idx
]
141 make_pad(res
, True, name
, "o", cpup
, iop
)
143 cpup
, iop
= get_field(cpu
, pfx
+"oe")[oe_idx
], \
144 get_field(io
, pfx
+"oe")[oe_idx
]
145 make_pad(res
, True, name
, "oe", cpup
, iop
)
147 if iotype
in (IOType
.In
, IOType
.InTriOut
):
148 sigs
.append(("i", 1))
149 if iotype
in (IOType
.Out
, IOType
.TriOut
, IOType
.InTriOut
):
150 sigs
.append(("o", 1))
151 if iotype
in (IOType
.TriOut
, IOType
.InTriOut
):
152 sigs
.append(("oe", 1))
157 human_name
= "Libre-SoC"
158 variants
= CPU_VARIANTS
159 endianness
= "little"
160 gcc_triple
= ("powerpc64le-linux", "powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu")
161 linker_output_format
= "elf64-powerpcle"
163 io_regions
= {0xc0000000: 0x10000000} # origin, length
167 return {"csr": 0xc0000000}
172 flags
+= "-mabi=elfv2 "
173 flags
+= "-msoft-float "
174 flags
+= "-mno-string "
175 flags
+= "-mno-multiple "
177 flags
+= "-mno-altivec "
178 flags
+= "-mlittle-endian "
179 flags
+= "-mstrict-align "
180 flags
+= "-fno-stack-protector "
181 flags
+= "-mcmodel=small "
182 flags
+= "-D__microwatt__ "
185 def __init__(self
, platform
, variant
="standard"):
186 self
.platform
= platform
187 self
.variant
= variant
188 self
.reset
= Signal()
189 self
.cpu_clk
= ClockSignal()
191 irq_en
= "noirq" not in variant
194 self
.interrupt
= Signal(16)
196 if variant
== "standard32":
198 self
.dbus
= dbus
= wb
.Interface(data_width
=32, adr_width
=30)
200 self
.dbus
= dbus
= wb
.Interface(data_width
=64, adr_width
=29)
202 self
.ibus
= ibus
= wb
.Interface(data_width
=64, adr_width
=29)
204 self
.xics_icp
= icp
= wb
.Interface(data_width
=32, adr_width
=30)
205 self
.xics_ics
= ics
= wb
.Interface(data_width
=32, adr_width
=30)
207 jtag_en
= ('jtag' in variant
) or ('ls180' in variant
)
209 if "testgpio" in variant
:
210 self
.simple_gpio
= gpio
= wb
.Interface(data_width
=32, adr_width
=30)
212 self
.jtag_wb
= jtag_wb
= wb
.Interface(data_width
=32, adr_width
=30)
214 self
.srams
= srams
= []
215 if "sram4k" in variant
:
217 srams
.append(wb
.Interface(data_width
=64, adr_width
=29))
219 self
.periph_buses
= [ibus
, dbus
]
220 self
.memory_buses
= []
223 self
.periph_buses
.append(jtag_wb
)
224 self
.jtag_tck
= Signal(1)
225 self
.jtag_tms
= Signal(1)
226 self
.jtag_tdi
= Signal(1)
227 self
.jtag_tdo
= Signal(1)
229 self
.dmi_addr
= Signal(4)
230 self
.dmi_din
= Signal(64)
231 self
.dmi_dout
= Signal(64)
232 self
.dmi_wr
= Signal(1)
233 self
.dmi_ack
= Signal(1)
234 self
.dmi_req
= Signal(1)
238 self
.cpu_params
= dict(
240 i_clk
= self
.cpu_clk
,
241 i_rst
= ResetSignal() | self
.reset
,
243 # Monitoring / Debugging
244 i_core_bigendian_i
= 0, # Signal(),
245 o_busy_o
= Signal(), # not connected
246 o_memerr_o
= Signal(), # not connected
247 o_pc_o
= Signal(64), # not connected
250 # these have been taken out
251 #self.cpu_params['i_pc_i'] = Signal(64)
252 #self.cpu_params['i_pc_i_ok'] = 0
256 self
.cpu_params
['i_int_level_i'] = self
.interrupt
259 self
.cpu_params
.update(dict(
261 o_TAP_bus__tdo
= self
.jtag_tdo
,
262 i_TAP_bus__tdi
= self
.jtag_tdi
,
263 i_TAP_bus__tms
= self
.jtag_tms
,
264 i_TAP_bus__tck
= self
.jtag_tck
,
267 self
.cpu_params
.update(dict(
269 i_dmi_addr_i
= self
.dmi_addr
,
270 i_dmi_din
= self
.dmi_din
,
271 o_dmi_dout
= self
.dmi_dout
,
272 i_dmi_req_i
= self
.dmi_req
,
273 i_dmi_we_i
= self
.dmi_wr
,
274 o_dmi_ack_o
= self
.dmi_ack
,
277 # add clock select, pll output
278 if "ls180" in variant
and "pll" not in variant
:
279 self
.pll_vco_o
= Signal()
280 self
.clk_sel
= Signal(2)
281 self
.pll_test_o
= Signal()
282 self
.pll_24_i
= Signal()
283 self
.pllclk_o
= ClockSignal("pll")
284 self
.cpu_params
['i_clk_sel_i'] = self
.clk_sel
285 self
.cpu_params
['i_clk_24_i'] = self
.pll_24_i
286 self
.cpu_params
['o_pll_vco_o'] = self
.pll_vco_o
287 self
.cpu_params
['o_pll_test_o'] = self
.pll_test_o
288 self
.cpu_params
['o_pllclk_clk'] = self
.pllclk_o
290 # add wishbone buses to cpu params
291 self
.cpu_params
.update(make_wb_bus("ibus", ibus
, True))
292 self
.cpu_params
.update(make_wb_bus("dbus", dbus
, True))
293 self
.cpu_params
.update(make_wb_slave("ics_wb", ics
, True))
294 self
.cpu_params
.update(make_wb_slave("icp_wb", icp
, True))
295 if "testgpio" in variant
:
296 self
.cpu_params
.update(make_wb_slave("gpio_wb", gpio
))
298 self
.cpu_params
.update(make_wb_bus("jtag_wb", jtag_wb
, simple
=True))
299 if "sram4k" in variant
:
300 for i
, sram
in enumerate(srams
):
301 self
.cpu_params
.update(make_wb_slave("sram4k_%d_wb" % i
,
305 # and set ibus advanced tags to zero (disable)
306 self
.cpu_params
['i_ibus__cti'] = 0
307 self
.cpu_params
['i_ibus__bte'] = 0
308 self
.cpu_params
['i_dbus__cti'] = 0
309 self
.cpu_params
['i_dbus__bte'] = 0
311 if "ls180" in variant
:
312 # XXX normally this is NOT done, however to avoid import problems
313 # in litex, move the import into where it is optionally called
314 # then, for non-ls180 platforms, huge numbers of dependencies
315 # behind these simple-looking imports are not needed.
316 # For normal FPGA usage ("standard" variants) you DO NOT need this.
317 # it is ONLY for ASICs, for managing JTAG TAP Boundary Scans.
319 from soc
.config
.pinouts
import get_pinspecs
320 from soc
.debug
.jtag
import Pins
321 from libresoc
.ls180
import io
323 # urr yuk. have to expose iopads / pins from core to litex
324 # then back again. cut _some_ of that out by connecting up
325 # padresources. this mirrors what is done inside litex
326 self
.padresources
= io()
327 self
.pad_cm
= ConstraintManager(self
.padresources
, [])
331 subset
= {'uart', 'mtwi', 'eint', 'mspi0',
337 for periph
in subset
:
340 if periph
[-1].isdigit():
341 periph
, num
= periph
[:-1], int(periph
[-1])
342 print ("periph request", periph
, num
)
345 periph
, num
= 'spimaster', None
347 periph
, num
= 'spisdcard', None
348 elif periph
== 'sdr':
350 elif periph
== 'mtwi':
353 periph
, num
= 'sdcard', None
354 litexmap
[origperiph
] = (periph
, num
)
355 self
.cpupads
[origperiph
] = self
.pad_cm
.request(periph
, num
)
356 iopads
[origperiph
] = platform
.request(periph
, num
)
357 #if periph == 'sdram':
358 # # special-case sdram clock
359 # ck = self.pad_cm.request("sdram_clock")
360 # self.cpupads['sdram_clock'] = ck
361 # ck = platform.request("sdram_clock")
362 # iopads['sdram_clock'] = ck
364 # for the 180nm ASIC, obtain the pinspecs so that JTAG can be
365 # routed in and back out again. litex is such hell (migen)
366 # that trying to create an auto-generated boundary scan in
367 # migen is just not sane.
368 pinset
= get_pinspecs(subset
=subset
)
371 make_jtag_ioconn(self
.cpu_params
, pin
, self
.cpupads
, iopads
)
373 # add verilog sources
374 self
.add_sources(platform
)
376 def set_reset_address(self
, reset_address
):
377 assert not hasattr(self
, "reset_address")
378 self
.reset_address
= reset_address
379 assert reset_address
== 0x00000000
382 def add_sources(platform
):
383 cdir
= os
.path
.dirname(__file__
)
384 platform
.add_source(os
.path
.join(cdir
, "libresoc.v"))
385 platform
.add_source(os
.path
.join(cdir
, "pll.v"))
386 platform
.add_source(os
.path
.join(cdir
, "SPBlock_512W64B8W.v"))
388 def do_finalize(self
):
389 self
.specials
+= Instance("test_issuer", **self
.cpu_params
)