def elaborate(self, platform):
m = Module()
- # Instead of a straightforward multiplexer for reads, use a per-element address comparator,
- # AND the shadow register chunk with the comparator output, and OR all of those together.
- # If the toolchain doesn't already synthesize multiplexer trees this way, this trick can
- # save a significant amount of logic, since e.g. one 4-LUT can pack one 2-MUX, but two
- # 2-AND or 2-OR gates.
+ # Instead of a straightforward multiplexer for reads, use a
+ # per-element address comparator, AND the shadow register chunk
+ # with the comparator output, and OR all of those together. If
+ # the toolchain doesn't already synthesize multiplexer trees this
+ # way, this trick can save a significant amount of logic, since
+ # e.g. one 4-LUT can pack one 2-MUX, but two 2-AND or 2-OR gates.
r_data_fanin = 0
for elem, (elem_start, elem_end) in self._map.resources():
m.d.comb += elem.w_data.eq(shadow)
m.d.sync += elem.w_stb.eq(0)
- # Enumerate every address used by the register explicitly, rather than using
- # arithmetic comparisons, since some toolchains (e.g. Yosys) are too eager to infer
- # carry chains for comparisons, even with a constant. (Register sizes don't have
- # to be powers of 2.)
+ # Enumerate every address used by the register explicitly,
+ # rather than using arithmetic comparisons, since some
+ # toolchains (e.g. Yosys) are too eager to infer carry chains
+ # for comparisons, even with a constant. (Register sizes don't
+ # have to be powers of 2.)
with m.Switch(self.bus.addr):
for chunk_offset, chunk_addr in enumerate(
range(elem_start, elem_end)):
if elem.access.writable():
if chunk_addr == elem_end - 1:
- # Delay by 1 cycle, avoiding combinatorial paths through
- # the CSR bus and into CSR registers.
+ # Delay by 1 cycle, avoiding combinatorial
+ # paths through the CSR bus and into
+ # CSR registers.
m.d.sync += elem.w_stb.eq(self.bus.w_stb)
with m.If(self.bus.w_stb):
m.d.sync += shadow_slice.eq(self.bus.w_data)
sub_bus = self._subs[sub_map]
m.d.comb += sub_bus.addr.eq(self.bus.addr[:sub_bus.addr_width])
- # The CSR bus interface is defined to output zero when idle, allowing us to avoid
- # adding a multiplexer here.
+ # The CSR bus interface is defined to output zero when
+ # idle, allowing us to avoid adding a multiplexer here.
r_data_fanin |= sub_bus.r_data
m.d.comb += sub_bus.w_data.eq(self.bus.w_data)
granularity=csr_bus.data_width,
name="wb")
- # Since granularity of the Wishbone interface matches the data width of the CSR bus,
- # no width conversion is performed, even if the Wishbone data width is
- # greater.
+ # Since granularity of the Wishbone interface matches the data
+ # width of the CSR bus, no width conversion is performed, even
+ # if the Wishbone data width is greater.
self.wb_bus.memory_map.add_window(self.csr_bus.memory_map)
def elaborate(self, platform):
if overlap in self._resources:
resource_range = self._resources[overlap]
overlap_descrs.append("resource {!r} at {:#x}..{:#x}"
- .format(overlap,
- resource_range.start,
+ .format(overlap,
+ resource_range.start,
resource_range.stop))
if overlap in self._windows:
window_range = self._windows[overlap]
else:
ratio = 1
size = (1 << window.addr_width) // ratio
- # For resources, the alignment argument of add_resource() affects both address and size
- # of the resource; aligning only the address should be done using align_to(). For windows,
- # changing the size (beyond the edge case of the window size being smaller than alignment
- # of the bus) is unlikely to be useful, so there is no alignment argument. The address of
- # a window can still be aligned using align_to().
+ # For resources, the alignment argument of add_resource()
+ # affects both address and size of the resource; aligning only
+ # the address should be done using align_to(). For windows,
+ # changing the size (beyond the edge case of the window size being
+ # smaller than alignment of the bus) is unlikely to be useful,
+ # so there is no alignment argument. The address of a window
+ # can still be aligned using align_to().
alignment = max(self.alignment, window.addr_width // ratio)
addr_range = self._compute_addr_range(
@staticmethod
def _translate(start, end, width, window, window_range):
assert (end - start) % window_range.step == 0
- # Accessing a resource through a dense and then a sparse window results in very strange
- # layouts that cannot be easily represented, so reject those.
+ # Accessing a resource through a dense and then a sparse
+ # window results in very strange layouts that cannot be easily
+ # represented, so reject those.
assert window_range.step == 1 or width == window.data_width
size = (end - start) // window_range.step
start += window_range.start
# Wishbone B4)
bus_busy = self.bus.cyc
if hasattr(self.bus, "lock"):
- # If LOCK is not asserted, we also wait for STB to be deasserted before granting bus
- # ownership to the next initiator. If we didn't, the next bus owner could receive
- # an ACK (or ERR, RTY) from the previous transaction when targeting the same
- # peripheral.
+ # If LOCK is not asserted, we also wait for STB to be
+ # deasserted before granting bus ownership to the next
+ # initiator. If we didn't, the next bus owner could receive
+ # an ACK (or ERR, RTY) from the previous transaction when
+ # targeting the same peripheral.
bus_busy &= self.bus.lock | self.bus.stb
m.d.comb += [