1 from litex
.gen
import *
2 from litex
.gen
.genlib
.record
import *
3 from litex
.gen
.genlib
.misc
import chooser
4 from litex
.gen
.util
.misc
import xdir
6 from litex
.soc
.interconnect
import csr
7 from litex
.soc
.interconnect
.csr
import CSRStorage
11 ("adr", "address_width", DIR_M_TO_S
),
12 ("we", 1, DIR_M_TO_S
),
13 ("dat_w", "data_width", DIR_M_TO_S
),
14 ("dat_r", "data_width", DIR_S_TO_M
)
18 class Interface(Record
):
19 def __init__(self
, data_width
=8, address_width
=14):
20 Record
.__init
__(self
, set_layout_parameters(_layout
,
21 data_width
=data_width
, address_width
=address_width
))
24 class Interconnect(Module
):
25 def __init__(self
, master
, slaves
):
26 self
.comb
+= master
.connect(*slaves
)
30 def __init__(self
, mem_or_size
, address
, read_only
=None, init
=None, bus
=None):
34 data_width
= len(self
.bus
.dat_w
)
35 if isinstance(mem_or_size
, Memory
):
38 mem
= Memory(data_width
, mem_or_size
//(data_width
//8), init
=init
)
39 csrw_per_memw
= (mem
.width
+ data_width
- 1)//data_width
40 word_bits
= log2_int(csrw_per_memw
)
41 page_bits
= log2_int((mem
.depth
*csrw_per_memw
+ 511)//512, False)
43 self
._page
= CSRStorage(page_bits
, name
=mem
.name_override
+ "_page")
47 if hasattr(mem
, "bus_read_only"):
48 read_only
= mem
.bus_read_only
54 port
= mem
.get_port(write_capable
=not read_only
)
55 self
.specials
+= mem
, port
59 self
.sync
+= sel_r
.eq(sel
)
60 self
.comb
+= sel
.eq(self
.bus
.adr
[9:] == address
)
63 word_index
= Signal(word_bits
)
64 word_expanded
= Signal(csrw_per_memw
*data_width
)
65 self
.sync
+= word_index
.eq(self
.bus
.adr
[:word_bits
])
67 word_expanded
.eq(port
.dat_r
),
69 chooser(word_expanded
, word_index
, self
.bus
.dat_r
, n
=csrw_per_memw
, reverse
=True)
74 for i
in range(csrw_per_memw
-1):
75 wreg
= Signal(data_width
)
76 self
.sync
+= If(sel
& self
.bus
.we
& (self
.bus
.adr
[:word_bits
] == i
), wreg
.eq(self
.bus
.dat_w
))
78 memword_chunks
= [self
.bus
.dat_w
] + list(reversed(wregs
))
80 port
.we
.eq(sel
& self
.bus
.we
& (self
.bus
.adr
[:word_bits
] == csrw_per_memw
- 1)),
81 port
.dat_w
.eq(Cat(*memword_chunks
))
84 self
.comb
+= If(sel_r
, self
.bus
.dat_r
.eq(port
.dat_r
))
87 port
.we
.eq(sel
& self
.bus
.we
),
88 port
.dat_w
.eq(self
.bus
.dat_w
)
91 if self
._page
is None:
92 self
.comb
+= port
.adr
.eq(self
.bus
.adr
[word_bits
:word_bits
+len(port
.adr
)])
94 pv
= self
._page
.storage
95 self
.comb
+= port
.adr
.eq(Cat(self
.bus
.adr
[word_bits
:word_bits
+len(port
.adr
)-len(pv
)], pv
))
98 if self
._page
is None:
104 class CSRBank(csr
.GenericBank
):
105 def __init__(self
, description
, address
=0, bus
=None):
112 csr
.GenericBank
.__init
__(self
, description
, len(self
.bus
.dat_w
))
115 self
.comb
+= sel
.eq(self
.bus
.adr
[9:] == address
)
117 for i
, c
in enumerate(self
.simple_csrs
):
119 c
.r
.eq(self
.bus
.dat_w
[:c
.size
]),
122 (self
.bus
.adr
[:self
.decode_bits
] == i
))
125 brcases
= dict((i
, self
.bus
.dat_r
.eq(c
.w
)) for i
, c
in enumerate(self
.simple_csrs
))
127 self
.bus
.dat_r
.eq(0),
128 If(sel
, Case(self
.bus
.adr
[:self
.decode_bits
], brcases
))
132 # address_map(name, memory) returns the CSR offset at which to map
133 # the CSR object (register bank or memory).
134 # If memory=None, the object is the register bank of object source.name.
135 # Otherwise, it is a memory object belonging to source.name.
136 # address_map is called exactly once for each object at each call to
137 # scan(), so it can have side effects.
138 class CSRBankArray(Module
):
139 def __init__(self
, source
, address_map
, *ifargs
, **ifkwargs
):
141 self
.address_map
= address_map
142 self
.scan(ifargs
, ifkwargs
)
144 def scan(self
, ifargs
, ifkwargs
):
147 for name
, obj
in xdir(self
.source
, True):
148 if hasattr(obj
, "get_csrs"):
149 csrs
= obj
.get_csrs()
152 if hasattr(obj
, "get_memories"):
153 memories
= obj
.get_memories()
154 for memory
in memories
:
155 mapaddr
= self
.address_map(name
, memory
)
158 sram_bus
= Interface(*ifargs
, **ifkwargs
)
159 mmap
= csr
.SRAM(memory
, mapaddr
, bus
=sram_bus
)
160 self
.submodules
+= mmap
161 csrs
+= mmap
.get_csrs()
162 self
.srams
.append((name
, memory
, mapaddr
, mmap
))
164 mapaddr
= self
.address_map(name
, None)
167 bank_bus
= Interface(*ifargs
, **ifkwargs
)
168 rmap
= CSRBank(csrs
, mapaddr
, bus
=bank_bus
)
169 self
.submodules
+= rmap
170 self
.banks
.append((name
, csrs
, mapaddr
, rmap
))
173 return [rmap
for name
, csrs
, mapaddr
, rmap
in self
.banks
]
176 return [mmap
for name
, memory
, mapaddr
, mmap
in self
.srams
]
179 return [i
.bus
for i
in self
.get_rmaps() + self
.get_mmaps()]