litex/migen/bank/csrgen.py

72 lines
2.2 KiB
Python

from ..fhdl import structure as f
from ..bus.csr import *
from .description import *
from functools import partial
class Bank:
def __init__(self, description, address=0):
self.description = description
self.address = address
self.interface = Slave()
d = partial(f.Declare, self)
d("_sel")
def GetFragment(self):
a = f.Assign
comb = []
sync = []
comb.append(a(self._sel, self.interface.a_i[12:] == f.Constant(self.address, f.BV(4))))
nregs = len(self.description)
nbits = f.BitsFor(nregs-1)
# Bus writes
bwcases = []
for i in range(nregs):
reg = self.description[i]
nfields = len(reg.fields)
bwra = []
for j in range(nfields):
field = reg.fields[j]
if field.access_bus == WRITE_ONLY or field.access_bus == READ_WRITE:
bwra.append(a(field.storage, self.interface.d_i[j]))
if bwra:
bwcases.append((f.Constant(i, f.BV(nbits)), bwra))
if bwcases:
sync.append(f.If(self._sel & self.interface.we_i, [f.Case(self.interface.a_i[:nbits], bwcases)]))
# Bus reads
brcases = []
for i in range(nregs):
reg = self.description[i]
nfields = len(reg.fields)
brs = []
reg_readable = False
for j in range(nfields):
field = reg.fields[j]
if field.access_bus == READ_ONLY or field.access_bus == READ_WRITE:
brs.append(field.storage)
reg_readable = True
else:
brs.append(f.Constant(0, f.bv(field.size)))
if reg_readable:
if len(brs) > 1:
brcases.append((f.Constant(i, f.BV(nbits)), [a(self.interface.d_o, f.Cat(*brs))]))
else:
brcases.append((f.Constant(i, f.BV(nbits)), [a(self.interface.d_o, brs[0])]))
if brcases:
sync.append(a(self.interface.d_o, f.Constant(0, f.BV(32))))
sync.append(f.If(self._sel, [f.Case(self.interface.a_i[:nbits], brcases)]))
else:
comb.append(a(self.interface.d_o, f.Constant(0, f.BV(32))))
# Device access
for reg in self.description:
for field in reg.fields:
if field.access_dev == READ_ONLY or field.access_dev == READ_WRITE:
comb.append(a(field.dev_r, field.storage))
if field.access_dev == WRITE_ONLY or field.access_dev == READ_WRITE:
sync.append(f.If(field.dev_we, [a(field.storage, field.dev_w)]))
return f.Fragment(comb, sync)