@@ -87,68 +87,7 @@ def name(self, n):
87
87
as_wires (self ).name = n
88
88
89
89
90
- class _MemReadBase (object ):
91
- """ This is the base class for the memories and ROM blocks and
92
- it implements the read and initialization operations needed for
93
- both of them.
94
- """
95
-
96
- # FIXME: right now read port is built unconditionally (no read enable)
97
-
98
- def __init__ (self , bitwidth , addrwidth , name , max_read_ports , asynchronous , block ):
99
- self .max_read_ports = max_read_ports
100
- self .read_ports = 0
101
- self .block = working_block (block )
102
- name = next_tempvar_name (name )
103
-
104
- if bitwidth <= 0 :
105
- raise PyrtlError ('bitwidth must be >= 1' )
106
- if addrwidth <= 0 :
107
- raise PyrtlError ('addrwidth must be >= 1' )
108
-
109
- self .bitwidth = bitwidth
110
- self .name = name
111
- self .addrwidth = addrwidth
112
- self .readport_nets = []
113
- self .id = _memIndex .next_index ()
114
- self .asynchronous = asynchronous
115
- self .block ._add_memblock (self )
116
-
117
- def __getitem__ (self , item ):
118
- """ Builds circuitry to retrieve an item from the memory """
119
- item = as_wires (item , bitwidth = self .addrwidth , truncating = False )
120
- if len (item ) > self .addrwidth :
121
- raise PyrtlError ('memory index bitwidth > addrwidth' )
122
- return _MemIndexed (mem = self , index = item )
123
-
124
- def _readaccess (self , addr ):
125
- # FIXME: add conditional read ports
126
- return self ._build_read_port (addr )
127
-
128
- def _build_read_port (self , addr ):
129
- if self .max_read_ports is not None :
130
- self .read_ports += 1
131
- if self .read_ports > self .max_read_ports :
132
- raise PyrtlError ('maximum number of read ports (%d) exceeded' % self .max_read_ports )
133
- data = WireVector (bitwidth = self .bitwidth )
134
- readport_net = LogicNet (
135
- op = 'm' ,
136
- op_param = (self .id , self ),
137
- args = (addr ,),
138
- dests = (data ,))
139
- working_block ().add_net (readport_net )
140
- self .readport_nets .append (readport_net )
141
- return data
142
-
143
- def __setitem__ (self , key , value ):
144
- """ Not legal on a object that only allows for reads"""
145
- raise PyrtlError ("error, invalid call __setitem__ made on _MemReadBase" )
146
-
147
- def _make_copy (self , block ):
148
- pass
149
-
150
-
151
- class MemBlock (_MemReadBase ):
90
+ class MemBlock (object ):
152
91
""" MemBlock is the object for specifying block memories. It can be
153
92
indexed like an array for both reading and writing. Writes under a conditional
154
93
are automatically converted to enabled writes. For example, consider the following
@@ -205,19 +144,61 @@ def __init__(self, bitwidth, addrwidth, name='', max_read_ports=2, max_write_por
205
144
that memories with high numbers of ports may not be possible to map to physical memories
206
145
such as block rams or existing memory hardware macros.
207
146
"""
208
- super (MemBlock , self ).__init__ (bitwidth , addrwidth , name , max_read_ports ,
209
- asynchronous , block )
147
+ self .max_read_ports = max_read_ports
148
+ self .num_read_ports = 0
149
+ self .block = working_block (block )
150
+ name = next_tempvar_name (name )
151
+
152
+ if bitwidth <= 0 :
153
+ raise PyrtlError ('bitwidth must be >= 1' )
154
+ if addrwidth <= 0 :
155
+ raise PyrtlError ('addrwidth must be >= 1' )
156
+
157
+ self .bitwidth = bitwidth
158
+ self .name = name
159
+ self .addrwidth = addrwidth
160
+ self .readport_nets = []
161
+ self .id = _memIndex .next_index ()
162
+ self .asynchronous = asynchronous
163
+ self .block ._add_memblock (self )
164
+
210
165
self .max_write_ports = max_write_ports
211
- self .write_ports = 0
166
+ self .num_write_ports = 0
212
167
self .writeport_nets = []
213
168
169
+ def __getitem__ (self , item ):
170
+ """ Builds circuitry to retrieve an item from the memory """
171
+ item = as_wires (item , bitwidth = self .addrwidth , truncating = False )
172
+ if len (item ) > self .addrwidth :
173
+ raise PyrtlError ('memory index bitwidth > addrwidth' )
174
+ return _MemIndexed (mem = self , index = item )
175
+
214
176
def __setitem__ (self , item , assignment ):
215
177
""" Builds circuitry to set an item in the memory """
216
178
if isinstance (assignment , _MemAssignment ):
217
179
self ._assignment (item , assignment .rhs , is_conditional = assignment .is_conditional )
218
180
else :
219
181
raise PyrtlError ('error, assigment to memories should use "<<=" not "=" operator' )
220
182
183
+ def _readaccess (self , addr ):
184
+ # FIXME: add conditional read ports
185
+ return self ._build_read_port (addr )
186
+
187
+ def _build_read_port (self , addr ):
188
+ if self .max_read_ports is not None :
189
+ self .num_read_ports += 1
190
+ if self .num_read_ports > self .max_read_ports :
191
+ raise PyrtlError ('maximum number of read ports (%d) exceeded' % self .max_read_ports )
192
+ data = WireVector (bitwidth = self .bitwidth )
193
+ readport_net = LogicNet (
194
+ op = 'm' ,
195
+ op_param = (self .id , self ),
196
+ args = (addr ,),
197
+ dests = (data ,))
198
+ working_block ().add_net (readport_net )
199
+ self .readport_nets .append (readport_net )
200
+ return data
201
+
221
202
def _assignment (self , item , val , is_conditional ):
222
203
from .conditional import _build
223
204
@@ -246,8 +227,8 @@ def _assignment(self, item, val, is_conditional):
246
227
def _build (self , addr , data , enable ):
247
228
""" Builds a write port. """
248
229
if self .max_write_ports is not None :
249
- self .write_ports += 1
250
- if self .write_ports > self .max_write_ports :
230
+ self .num_write_ports += 1
231
+ if self .num_write_ports > self .max_write_ports :
251
232
raise PyrtlError ('maximum number of write ports (%d) exceeded' %
252
233
self .max_write_ports )
253
234
writeport_net = LogicNet (
@@ -269,7 +250,7 @@ def _make_copy(self, block=None):
269
250
block = block )
270
251
271
252
272
- class RomBlock (_MemReadBase ):
253
+ class RomBlock (MemBlock ):
273
254
""" PyRTL Read Only Memory.
274
255
275
256
RomBlocks are the read only memory block for PyRTL. They support the same read interface
@@ -302,8 +283,9 @@ def __init__(self, bitwidth, addrwidth, romdata, name='', max_read_ports=2,
302
283
:param block: The block to add to, defaults to the working block
303
284
"""
304
285
305
- super (RomBlock , self ).__init__ (bitwidth , addrwidth , name , max_read_ports ,
306
- asynchronous , block )
286
+ super (RomBlock , self ).__init__ (bitwidth = bitwidth , addrwidth = addrwidth , name = name ,
287
+ max_read_ports = max_read_ports , max_write_ports = 0 ,
288
+ asynchronous = asynchronous , block = block )
307
289
self .data = romdata
308
290
self .build_new_roms = build_new_roms
309
291
self .current_copy = self
@@ -317,6 +299,9 @@ def __getitem__(self, item):
317
299
# If you really know what you are doing, use a Const WireVector instead.
318
300
return super (RomBlock , self ).__getitem__ (item )
319
301
302
+ def __setitem__ (self , item , assignment ):
303
+ raise PyrtlError ('no writing to a read-only memory' )
304
+
320
305
def _get_read_data (self , address ):
321
306
import types
322
307
try :
@@ -361,7 +346,7 @@ def _get_read_data(self, address):
361
346
362
347
def _build_read_port (self , addr ):
363
348
if self .build_new_roms and \
364
- (self .current_copy .read_ports >= self .current_copy .max_read_ports ):
349
+ (self .current_copy .num_read_ports >= self .current_copy .max_read_ports ):
365
350
self .current_copy = self ._make_copy ()
366
351
return super (RomBlock , self .current_copy )._build_read_port (addr )
367
352
0 commit comments