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 soc
.debug
.jtag
import Pins
, dummy_pinset
# TODO move to suitable location
9 from c4m
.nmigen
.jtag
.tap
import IOType
11 from libresoc
.ls180
import io
12 from libresoc
.ls180io
import make_uart
, make_gpio
13 from litex
.build
.generic_platform
import ConstraintManager
16 CPU_VARIANTS
= ["standard", "standard32", "standardjtag", "ls180"]
19 def make_wb_bus(prefix
, obj
, simple
=False):
21 outpins
= ['stb', 'cyc', 'we', 'adr', 'dat_w', 'sel']
23 outpins
+= ['cti', 'bte']
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
)
30 def make_wb_slave(prefix
, obj
):
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
)
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
43 def get_field(rec
, name
):
47 return getattr(rec
, f
)
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
)
62 name
= "%s_%s" % (fn
, pin
)
64 if iotype
in (IOType
.In
, IOType
.Out
):
65 cpup
= getattr(cpu
, pin
)
66 iop
= getattr(io
, pin
)
68 if iotype
== IOType
.Out
:
69 # output from the pad is routed through C4M JTAG and so
70 # is an *INPUT* into core. ls180soc connects this to "real" peripheral
71 make_pad(res
, True, name
, "o", cpup
, iop
)
73 elif iotype
== IOType
.In
:
74 # input to the pad is routed through C4M JTAG and so
75 # is an *OUTPUT* into core. ls180soc connects this to "real" peripheral
76 make_pad(res
, False, name
, "i", cpup
, iop
)
78 elif iotype
== IOType
.InTriOut
:
79 if fn
== 'gpio': # sigh decode GPIO special-case
83 cpup
, iop
= get_field(cpu
, "i")[idx
], get_field(io
, "i")[idx
]
84 make_pad(res
, False, name
, "i", cpup
, iop
)
85 cpup
, iop
= get_field(cpu
, "o")[idx
], get_field(io
, "o")[idx
]
86 make_pad(res
, True, name
, "o", cpup
, iop
)
87 cpup
, iop
= get_field(cpu
, "oe")[idx
], get_field(io
, "oe")[idx
]
88 make_pad(res
, True, name
, "oe", cpup
, iop
)
90 if iotype
in (IOType
.In
, IOType
.InTriOut
):
92 if iotype
in (IOType
.Out
, IOType
.TriOut
, IOType
.InTriOut
):
94 if iotype
in (IOType
.TriOut
, IOType
.InTriOut
):
95 sigs
.append(("oe", 1))
100 human_name
= "Libre-SoC"
101 variants
= CPU_VARIANTS
102 endianness
= "little"
103 gcc_triple
= ("powerpc64le-linux", "powerpc64le-linux-gnu")
104 linker_output_format
= "elf64-powerpcle"
106 io_regions
= {0xc0000000: 0x10000000} # origin, length
110 return {"csr": 0xc0000000}
115 flags
+= "-mabi=elfv2 "
116 flags
+= "-msoft-float "
117 flags
+= "-mno-string "
118 flags
+= "-mno-multiple "
120 flags
+= "-mno-altivec "
121 flags
+= "-mlittle-endian "
122 flags
+= "-mstrict-align "
123 flags
+= "-fno-stack-protector "
124 flags
+= "-mcmodel=small "
125 flags
+= "-D__microwatt__ "
128 def __init__(self
, platform
, variant
="standard"):
129 self
.platform
= platform
130 self
.variant
= variant
131 self
.reset
= Signal()
132 self
.interrupt
= Signal(16)
134 if variant
== "standard32":
136 self
.dbus
= dbus
= wb
.Interface(data_width
=32, adr_width
=30)
138 self
.dbus
= dbus
= wb
.Interface(data_width
=64, adr_width
=29)
140 self
.ibus
= ibus
= wb
.Interface(data_width
=64, adr_width
=29)
142 self
.xics_icp
= icp
= wb
.Interface(data_width
=32, adr_width
=30)
143 self
.xics_ics
= ics
= wb
.Interface(data_width
=32, adr_width
=30)
145 jtag_en
= ('jtag' in variant
) or variant
== 'ls180'
147 if variant
!= "ls180":
148 self
.simple_gpio
= gpio
= wb
.Interface(data_width
=32, adr_width
=30)
150 self
.jtag_wb
= jtag_wb
= wb
.Interface(data_width
=64, adr_width
=29)
152 self
.periph_buses
= [ibus
, dbus
]
153 self
.memory_buses
= []
156 self
.periph_buses
.append(jtag_wb
)
157 self
.jtag_tck
= Signal(1)
158 self
.jtag_tms
= Signal(1)
159 self
.jtag_tdi
= Signal(1)
160 self
.jtag_tdo
= Signal(1)
162 self
.dmi_addr
= Signal(4)
163 self
.dmi_din
= Signal(64)
164 self
.dmi_dout
= Signal(64)
165 self
.dmi_wr
= Signal(1)
166 self
.dmi_ack
= Signal(1)
167 self
.dmi_req
= Signal(1)
171 self
.cpu_params
= dict(
173 i_clk
= ClockSignal(),
174 i_rst
= ResetSignal() | self
.reset
,
176 # Monitoring / Debugging
179 i_core_bigendian_i
= 0, # Signal(),
180 o_busy_o
= Signal(), # not connected
181 o_memerr_o
= Signal(), # not connected
182 o_pc_o
= Signal(64), # not connected
185 i_int_level_i
= self
.interrupt
,
190 self
.cpu_params
.update(dict(
192 o_TAP_bus__tdo
= self
.jtag_tdo
,
193 i_TAP_bus__tdi
= self
.jtag_tdi
,
194 i_TAP_bus__tms
= self
.jtag_tms
,
195 i_TAP_bus__tck
= self
.jtag_tck
,
198 self
.cpu_params
.update(dict(
200 i_dmi_addr_i
= self
.dmi_addr
,
201 i_dmi_din
= self
.dmi_din
,
202 o_dmi_dout
= self
.dmi_dout
,
203 i_dmi_req_i
= self
.dmi_req
,
204 i_dmi_we_i
= self
.dmi_wr
,
205 o_dmi_ack_o
= self
.dmi_ack
,
208 # add clock select, pll output
209 if variant
== "ls180":
210 self
.pll_48_o
= Signal()
211 self
.clk_sel
= Signal(3)
212 self
.cpu_params
['i_clk_sel_i'] = self
.clk_sel
213 self
.cpu_params
['o_pll_48_o'] = self
.pll_48_o
215 # add wishbone buses to cpu params
216 self
.cpu_params
.update(make_wb_bus("ibus", ibus
))
217 self
.cpu_params
.update(make_wb_bus("dbus", dbus
))
218 self
.cpu_params
.update(make_wb_slave("ics_wb", ics
))
219 self
.cpu_params
.update(make_wb_slave("icp_wb", icp
))
220 if variant
!= "ls180":
221 self
.cpu_params
.update(make_wb_slave("gpio_wb", gpio
))
223 self
.cpu_params
.update(make_wb_bus("jtag_wb", jtag_wb
, simple
=True))
225 if variant
== 'ls180':
226 # urr yuk. have to expose iopads / pins from core to litex
227 # then back again. cut _some_ of that out by connecting
228 self
.padresources
= io()
229 self
.pad_cm
= ConstraintManager(self
.padresources
, [])
232 for (periph
, num
) in [('uart', 0), ('gpio', 0), ('i2c', 0)]:
233 self
.cpupads
[periph
] = platform
.request(periph
, num
)
234 iopads
[periph
] = self
.pad_cm
.request(periph
, num
)
236 p
= Pins(dummy_pinset())
238 make_jtag_ioconn(self
.cpu_params
, pin
, self
.cpupads
, iopads
)
240 # add verilog sources
241 self
.add_sources(platform
)
243 def set_reset_address(self
, reset_address
):
244 assert not hasattr(self
, "reset_address")
245 self
.reset_address
= reset_address
246 assert reset_address
== 0x00000000
249 def add_sources(platform
):
250 cdir
= os
.path
.dirname(__file__
)
251 platform
.add_source(os
.path
.join(cdir
, "libresoc.v"))
253 def do_finalize(self
):
254 self
.specials
+= Instance("test_issuer", **self
.cpu_params
)