@@ -104,8 +104,6 @@ class Interface(Record):
104
104
Address width. At most ``(2 ** addr_width) * data_width`` register bits will be available.
105
105
data_width : int
106
106
Data width. Registers are accessed in ``data_width`` sized chunks.
107
- alignment : int
108
- Register and window alignment. See :class:`MemoryMap`.
109
107
name : str
110
108
Name of the underlying record.
111
109
@@ -132,7 +130,7 @@ class Interface(Record):
132
130
nothing.
133
131
"""
134
132
135
- def __init__ (self , * , addr_width , data_width , alignment = 0 , name = None ):
133
+ def __init__ (self , * , addr_width , data_width , name = None ):
136
134
if not isinstance (addr_width , int ) or addr_width <= 0 :
137
135
raise ValueError ("Address width must be a positive integer, not {!r}"
138
136
.format (addr_width ))
@@ -141,8 +139,7 @@ def __init__(self, *, addr_width, data_width, alignment=0, name=None):
141
139
.format (data_width ))
142
140
self .addr_width = addr_width
143
141
self .data_width = data_width
144
- self .memory_map = MemoryMap (addr_width = addr_width , data_width = data_width ,
145
- alignment = alignment )
142
+ self ._map = None
146
143
147
144
super ().__init__ ([
148
145
("addr" , addr_width ),
@@ -152,6 +149,29 @@ def __init__(self, *, addr_width, data_width, alignment=0, name=None):
152
149
("w_stb" , 1 ),
153
150
], name = name , src_loc_at = 1 )
154
151
152
+ @property
153
+ def memory_map (self ):
154
+ if self ._map is None :
155
+ raise NotImplementedError ("Bus interface {!r} does not have a memory map"
156
+ .format (self ))
157
+ return self ._map
158
+
159
+ @memory_map .setter
160
+ def memory_map (self , memory_map ):
161
+ if not isinstance (memory_map , MemoryMap ):
162
+ raise TypeError ("Memory map must be an instance of MemoryMap, not {!r}"
163
+ .format (memory_map ))
164
+ if memory_map .addr_width != self .addr_width :
165
+ raise ValueError ("Memory map has address width {}, which is not the same as "
166
+ "bus interface address width {}"
167
+ .format (memory_map .addr_width , self .addr_width ))
168
+ if memory_map .data_width != self .data_width :
169
+ raise ValueError ("Memory map has data width {}, which is not the same as "
170
+ "bus interface data width {}"
171
+ .format (memory_map .data_width , self .data_width ))
172
+ memory_map .freeze ()
173
+ self ._map = memory_map
174
+
155
175
156
176
class Multiplexer (Elaboratable ):
157
177
"""CSR register multiplexer.
@@ -201,9 +221,18 @@ class Multiplexer(Elaboratable):
201
221
CSR bus providing access to registers.
202
222
"""
203
223
def __init__ (self , * , addr_width , data_width , alignment = 0 ):
204
- self .bus = Interface (addr_width = addr_width , data_width = data_width , alignment = alignment ,
205
- name = "csr" )
206
- self ._map = self .bus .memory_map
224
+ self ._map = MemoryMap (addr_width = addr_width , data_width = data_width , alignment = alignment )
225
+ self ._bus = None
226
+
227
+ @property
228
+ def bus (self ):
229
+ if self ._bus is None :
230
+ self ._map .freeze ()
231
+ self ._bus = Interface (addr_width = self ._map .addr_width ,
232
+ data_width = self ._map .data_width ,
233
+ name = "csr" )
234
+ self ._bus .memory_map = self ._map
235
+ return self ._bus
207
236
208
237
def align_to (self , alignment ):
209
238
"""Align the implicit address of the next register.
@@ -212,7 +241,7 @@ def align_to(self, alignment):
212
241
"""
213
242
return self ._map .align_to (alignment )
214
243
215
- def add (self , element , * , addr = None , alignment = None ):
244
+ def add (self , element , * , addr = None , alignment = None , extend = False ):
216
245
"""Add a register.
217
246
218
247
See :meth:`MemoryMap.add_resource` for details.
@@ -221,8 +250,9 @@ def add(self, element, *, addr=None, alignment=None):
221
250
raise TypeError ("Element must be an instance of csr.Element, not {!r}"
222
251
.format (element ))
223
252
224
- size = (element .width + self .bus .data_width - 1 ) // self .bus .data_width
225
- return self ._map .add_resource (element , size = size , addr = addr , alignment = alignment )
253
+ size = (element .width + self ._map .data_width - 1 ) // self ._map .data_width
254
+ return self ._map .add_resource (element , size = size , addr = addr , alignment = alignment ,
255
+ extend = extend )
226
256
227
257
def elaborate (self , platform ):
228
258
m = Module ()
@@ -306,32 +336,41 @@ class Decoder(Elaboratable):
306
336
CSR bus providing access to subordinate buses.
307
337
"""
308
338
def __init__ (self , * , addr_width , data_width , alignment = 0 ):
309
- self .bus = Interface (addr_width = addr_width , data_width = data_width , alignment = alignment ,
310
- name = "csr" )
311
- self ._map = self .bus .memory_map
339
+ self ._map = MemoryMap (addr_width = addr_width , data_width = data_width , alignment = alignment )
340
+ self ._bus = None
312
341
self ._subs = dict ()
313
342
343
+ @property
344
+ def bus (self ):
345
+ if self ._bus is None :
346
+ self ._map .freeze ()
347
+ self ._bus = Interface (addr_width = self ._map .addr_width ,
348
+ data_width = self ._map .data_width ,
349
+ name = "csr" )
350
+ self ._bus .memory_map = self ._map
351
+ return self ._bus
352
+
314
353
def align_to (self , alignment ):
315
354
"""Align the implicit address of the next window.
316
355
317
356
See :meth:`MemoryMap.align_to` for details.
318
357
"""
319
358
return self ._map .align_to (alignment )
320
359
321
- def add (self , sub_bus , * , addr = None ):
360
+ def add (self , sub_bus , * , addr = None , extend = False ):
322
361
"""Add a window to a subordinate bus.
323
362
324
363
See :meth:`MemoryMap.add_resource` for details.
325
364
"""
326
365
if not isinstance (sub_bus , Interface ):
327
366
raise TypeError ("Subordinate bus must be an instance of csr.Interface, not {!r}"
328
367
.format (sub_bus ))
329
- if sub_bus .data_width != self .bus .data_width :
368
+ if sub_bus .data_width != self ._map .data_width :
330
369
raise ValueError ("Subordinate bus has data width {}, which is not the same as "
331
370
"decoder data width {}"
332
- .format (sub_bus .data_width , self .bus .data_width ))
371
+ .format (sub_bus .data_width , self ._map .data_width ))
333
372
self ._subs [sub_bus .memory_map ] = sub_bus
334
- return self ._map .add_window (sub_bus .memory_map , addr = addr )
373
+ return self ._map .add_window (sub_bus .memory_map , addr = addr , extend = extend )
335
374
336
375
def elaborate (self , platform ):
337
376
m = Module ()
0 commit comments