edaede3fd30de9c00b2399792f7e847b639f7b04
1 # This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
2 # This file is Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
3 # This file is Copyright (c) 2016-2019 Tim 'mithro' Ansell <me@mith.ro>
4 # This file is Copyright (c) 2019 Sean Cross <sean@xobs.io>
9 Configuration and Status Registers
10 **********************************
12 The lowest-level description of a register is provided by the ``CSR`` class,
13 which maps to the value at a single address on the target bus. Also provided
14 are helper classes for dealing with values larger than the CSR buses data
17 * ``CSRConstant``, for constant values.
18 * ``CSRStatus``, for providing information to the CPU.
19 * ``CSRStorage``, for allowing control via the CPU.
21 Generating register banks
22 =========================
23 A module can provide bus-independent CSRs by implementing a ``get_csrs`` method
24 that returns a list of instances of the classes described above.
26 Similarly, bus-independent memories can be returned as a list by a
27 ``get_memories`` method.
29 To avoid listing those manually, a module can inherit from the ``AutoCSR``
30 class, which provides ``get_csrs`` and ``get_memories`` methods that scan for
31 CSR and memory attributes and return their list.
34 from enum
import IntEnum
37 from migen
.util
.misc
import xdir
38 from migen
.fhdl
.tracer
import get_obj_var_name
40 # CSRBase ------------------------------------------------------------------------------------------
43 def __init__(self
, size
, name
):
45 self
.name
= get_obj_var_name(name
)
47 raise ValueError("Cannot extract CSR name from code, need to specify.")
50 # CSRConstant --------------------------------------------------------------------------------------
52 class CSRConstant(DUID
):
53 """Register which contains a constant value.
55 Useful for providing information on how a HDL was instantiated to firmware
56 running on the device.
59 def __init__(self
, value
, bits_sign
=None, name
=None):
61 self
.value
= Constant(value
, bits_sign
)
62 self
.name
= get_obj_var_name(name
)
64 raise ValueError("Cannot extract CSR name from code, need to specify.")
67 """Read method for simulation."""
68 return self
.value
.value
70 # CSR ----------------------------------------------------------------------------------------------
73 """Basic CSR register.
78 Size of the CSR register in bits.
79 Must be less than CSR bus width!
82 Provide (or override the name) of the CSR register.
87 Contains the data written from the bus interface.
88 ``r`` is only valid when ``re`` is high.
91 The strobe signal for ``r``.
92 It is active for one cycle, after or during a write from the bus.
95 The value to be read from the bus.
96 Must be provided at all times.
99 The strobe signal for ``w``.
100 It is active for one cycle, after or during a read from the bus.
103 def __init__(self
, size
=1, name
=None):
104 _CSRBase
.__init
__(self
, size
, name
)
105 self
.re
= Signal(name
=self
.name
+ "_re")
106 self
.r
= Signal(self
.size
, name
=self
.name
+ "_r")
107 self
.we
= Signal(name
=self
.name
+ "_we")
108 self
.w
= Signal(self
.size
, name
=self
.name
+ "_w")
111 """Read method for simulation."""
113 value
= (yield self
.w
)
118 def write(self
, value
):
119 """Write method for simulation."""
120 yield self
.r
.eq(value
)
126 class _CompoundCSR(_CSRBase
, Module
):
127 def __init__(self
, size
, name
):
128 _CSRBase
.__init
__(self
, size
, name
)
129 self
.simple_csrs
= []
131 def get_simple_csrs(self
):
132 if not self
.finalized
:
134 return self
.simple_csrs
136 def do_finalize(self
, busword
):
137 raise NotImplementedError
139 # CSRAccess ----------------------------------------------------------------------------------------
141 class CSRAccess(IntEnum
):
146 # CSRField -----------------------------------------------------------------------------------------
148 class CSRField(Signal
):
151 Parameters / Attributes
152 -----------------------
154 Name of the CSR field.
157 Size of the CSR field in bits.
159 offset : int (optional)
160 Offset of the CSR field on the CSR register in bits.
162 reset: int (optional)
163 Reset value of the CSR field.
165 description: string (optional)
166 Description of the CSR Field (can be used to document the code and/or to be reused by tools
167 to create the documentation).
169 pulse: boolean (optional)
170 Field value is only valid for one cycle when set to True. Only valid for 1-bit fields.
172 access: enum (optional)
173 Access type of the CSR field.
175 values: list (optional)
176 A list of supported values.
177 If this is specified, a table will be generated containing the values in the specified order.
178 The `value` must be an integer in order to allow for automatic constant generation in an IDE,
179 except "do not care" bits are allowed.
180 In the three-tuple variation, the middle value represents an enum value that can be displayed
181 instead of the value.
183 ("0b0000", "disable the timer"),
184 ("0b0001", "slow", "slow timer"),
185 ("0b1xxx", "fast timer"),
189 def __init__(self
, name
, size
=1, offset
=None, reset
=0, description
=None, pulse
=False, access
=None, values
=None):
190 assert access
is None or (access
in CSRAccess
.values())
194 self
.reset_value
= reset
195 self
.description
= description
199 Signal
.__init
__(self
, size
, name
=name
, reset
=reset
)
202 class CSRFieldAggregate
:
203 """CSR Field Aggregate."""
205 def __init__(self
, fields
, access
):
206 self
.check_names(fields
)
207 self
.check_ordering_overlap(fields
)
210 if field
.access
is None:
211 field
.access
= access
212 elif field
.access
== CSRAccess
.ReadOnly
:
213 assert not field
.pulse
214 assert field
.access
== CSRAccess
.ReadOnly
215 elif field
.access
== CSRAccess
.ReadWrite
:
216 assert field
.access
in [CSRAccess
.ReadWrite
, CSRAccess
.WriteOnly
]
218 field
.access
= CSRAccess
.WriteOnly
219 setattr(self
, field
.name
, field
)
222 def check_names(fields
):
225 if field
.name
in names
:
226 raise ValueError("CSRField \"{}\" name is already used in CSR register".format(field
.name
))
228 names
.append(field
.name
)
231 def check_ordering_overlap(fields
):
234 if field
.offset
is not None:
235 if field
.offset
< offset
:
236 raise ValueError("CSRField ordering/overlap issue on \"{}\" field".format(field
.name
))
237 offset
= field
.offset
239 field
.offset
= offset
243 return self
.fields
[-1].offset
+ self
.fields
[-1].size
247 for field
in self
.fields
:
248 reset |
= (field
.reset_value
<< field
.offset
)
251 # CSRStatus ----------------------------------------------------------------------------------------
253 class CSRStatus(_CompoundCSR
):
256 The ``CSRStatus`` class is meant to be used as a status register that is read-only from the CPU.
258 The user design is expected to drive its ``status`` signal.
260 The advantage of using ``CSRStatus`` instead of using ``CSR`` and driving ``w`` is that the
261 width of ``CSRStatus`` can be arbitrary.
263 Status registers larger than the bus word width are automatically broken down into several
264 ``CSR`` registers to span several addresses.
266 *Be careful, though:* the atomicity of reads is not guaranteed.
271 Size of the CSR register in bits.
272 Can be bigger than the CSR bus width.
275 Value of the register after reset.
278 Provide (or override the name) of the ``CSRStatus`` register.
282 status : Signal(size), in
283 The value of the CSRStatus register.
286 def __init__(self
, size
=1, reset
=0, fields
=[], name
=None, description
=None):
288 self
.fields
= CSRFieldAggregate(fields
, CSRAccess
.ReadOnly
)
289 size
= self
.fields
.get_size()
290 reset
= self
.fields
.get_reset()
291 _CompoundCSR
.__init
__(self
, size
, name
)
292 self
.description
= description
293 self
.status
= Signal(self
.size
, reset
=reset
)
296 self
.comb
+= self
.status
[field
.offset
:field
.offset
+ field
.size
].eq(getattr(self
.fields
, field
.name
))
298 def do_finalize(self
, busword
):
299 nwords
= (self
.size
+ busword
- 1)//busword
300 for i
in reversed(range(nwords
)):
301 nbits
= min(self
.size
- i
*busword
, busword
)
302 sc
= CSR(nbits
, self
.name
+ str(i
) if nwords
> 1 else self
.name
)
303 self
.comb
+= sc
.w
.eq(self
.status
[i
*busword
:i
*busword
+nbits
])
304 self
.simple_csrs
.append(sc
)
305 self
.comb
+= self
.we
.eq(sc
.we
)
308 """Read method for simulation."""
310 value
= (yield self
.status
)
315 # CSRStorage ---------------------------------------------------------------------------------------
317 class CSRStorage(_CompoundCSR
):
320 The ``CSRStorage`` class provides a memory location that can be read and written by the CPU, and read and optionally written by the design.
322 It can span several CSR addresses.
327 Size of the CSR register in bits. Can be bigger than the CSR bus width.
330 Value of the register after reset.
333 If `True`, do not generate reset logic for CSRStorage.
336 Provide an mechanism for atomic CPU writes is provided. When enabled, writes to the first
337 CSR addresses go to a back-buffer whose contents are atomically copied to the main buffer
338 when the last address is written.
340 write_from_dev : bool
341 Allow the design to update the CSRStorage value. *Warning*: The atomicity of reads by the
342 CPU is not guaranteed.
345 Provide (or override the name) of the ``CSRStatus`` register.
349 storage : Signal(size), out
350 Signal providing the value of the ``CSRStorage`` object.
353 The strobe signal indicating a write to the ``CSRStorage`` register from the CPU. It is active
354 for one cycle, after or during a write from the bus.
357 The strobe signal to write to the ``CSRStorage`` register from the logic. Only available when
358 ``write_from_dev == True``
361 dat_w : Signal(), out
362 The write data to write to the ``CSRStorage`` register from the logic. Only available when
363 ``write_from_dev == True``
366 def __init__(self
, size
=1, reset
=0, reset_less
=False, fields
=[], atomic_write
=False, write_from_dev
=False, name
=None, description
=None):
368 self
.fields
= CSRFieldAggregate(fields
, CSRAccess
.ReadWrite
)
369 size
= self
.fields
.get_size()
370 reset
= self
.fields
.get_reset()
371 _CompoundCSR
.__init
__(self
, size
, name
)
372 self
.description
= description
373 self
.storage
= Signal(self
.size
, reset
=reset
, reset_less
=reset_less
)
374 self
.atomic_write
= atomic_write
378 self
.dat_w
= Signal(self
.size
)
379 self
.sync
+= If(self
.we
, self
.storage
.eq(self
.dat_w
))
380 for field
in [*fields
]:
381 field_assign
= getattr(self
.fields
, field
.name
).eq(self
.storage
[field
.offset
:field
.offset
+ field
.size
])
383 self
.comb
+= If(self
.re
, field_assign
)
385 self
.comb
+= field_assign
387 def do_finalize(self
, busword
):
388 nwords
= (self
.size
+ busword
- 1)//busword
389 if nwords
> 1 and self
.atomic_write
:
390 backstore
= Signal(self
.size
- busword
, name
=self
.name
+ "_backstore")
391 for i
in reversed(range(nwords
)):
392 nbits
= min(self
.size
- i
*busword
, busword
)
393 sc
= CSR(nbits
, self
.name
+ str(i
) if nwords
else self
.name
)
394 self
.simple_csrs
.append(sc
)
398 self
.comb
+= sc
.w
.eq(self
.storage
[lo
:hi
])
400 if nwords
> 1 and self
.atomic_write
:
402 self
.sync
+= If(sc
.re
, backstore
[lo
-busword
:hi
-busword
].eq(sc
.r
))
404 self
.sync
+= If(sc
.re
, self
.storage
.eq(Cat(sc
.r
, backstore
)))
406 self
.sync
+= If(sc
.re
, self
.storage
[lo
:hi
].eq(sc
.r
))
407 self
.sync
+= self
.re
.eq(sc
.re
)
410 """Read method for simulation."""
411 return (yield self
.storage
)
413 def write(self
, value
):
414 """Write method for simulation."""
415 yield self
.storage
.eq(value
)
417 if hasattr(self
, "fields"):
418 for field
in [*self
.fields
.fields
]:
419 yield getattr(self
.fields
, field
.name
).eq((value
>> field
.offset
) & (2**field
.size
-1))
422 if hasattr(self
, "fields"):
423 for field
in [*self
.fields
.fields
]:
425 yield getattr(self
.fields
, field
.name
).eq(0)
427 # AutoCSR & Helpers --------------------------------------------------------------------------------
429 def csrprefix(prefix
, csrs
, done
):
431 if csr
.duid
not in done
:
432 csr
.name
= prefix
+ csr
.name
436 def memprefix(prefix
, memories
, done
):
437 for memory
in memories
:
438 if memory
.duid
not in done
:
439 memory
.name_override
= prefix
+ memory
.name_override
440 done
.add(memory
.duid
)
443 def _make_gatherer(method
, cls
, prefix_cb
):
446 exclude
= self
.autocsr_exclude
447 except AttributeError:
450 prefixed
= self
.__prefixed
451 except AttributeError:
452 prefixed
= self
.__prefixed
= set()
454 for k
, v
in xdir(self
, True):
456 if isinstance(v
, cls
):
458 elif hasattr(v
, method
) and callable(getattr(v
, method
)):
459 items
= getattr(v
, method
)()
460 prefix_cb(k
+ "_", items
, prefixed
)
462 return sorted(r
, key
=lambda x
: x
.duid
)
467 """MixIn to provide bus independent access to CSR registers.
469 A module can inherit from the ``AutoCSR`` class, which provides ``get_csrs``, ``get_memories``
470 and ``get_constants`` methods that scan for CSR and memory attributes and return their list.
472 If the module has child objects that implement ``get_csrs``, ``get_memories`` or ``get_constants``,
473 they will be called by the``AutoCSR`` methods and their CSR and memories added to the lists returned,
474 with the child objects' names as prefixes.
476 get_memories
= _make_gatherer("get_memories", Memory
, memprefix
)
477 get_csrs
= _make_gatherer("get_csrs", _CSRBase
, csrprefix
)
478 get_constants
= _make_gatherer("get_constants", CSRConstant
, csrprefix
)
481 class GenericBank(Module
):
482 def __init__(self
, description
, busword
):
483 # Turn description into simple CSRs and claim ownership of compound CSR modules
484 self
.simple_csrs
= []
485 for c
in description
:
486 if isinstance(c
, CSR
):
487 assert c
.size
<= busword
488 self
.simple_csrs
.append(c
)
491 self
.simple_csrs
+= c
.get_simple_csrs()
493 self
.decode_bits
= bits_for(len(self
.simple_csrs
)-1)