sel = Signal()
comb.append(sel.eq(self.interface.a_i[9:] == Constant(self.address, BV(5))))
- nbits = bits_for(len(self.description)-1)
+ desc_exp = expand_description(self.description, 8)
+ nbits = bits_for(len(desc_exp)-1)
# Bus writes
bwcases = []
- for i, reg in enumerate(self.description):
+ for i, reg in enumerate(desc_exp):
if isinstance(reg, RegisterRaw):
comb.append(reg.r.eq(self.interface.d_i[:reg.size]))
comb.append(reg.re.eq(sel & \
(self.interface.a_i[:nbits] == Constant(i, BV(nbits)))))
elif isinstance(reg, RegisterFields):
bwra = [Constant(i, BV(nbits))]
- for j, field in enumerate(reg.fields):
+ offset = 0
+ for field in reg.fields:
if field.access_bus == WRITE_ONLY or field.access_bus == READ_WRITE:
- bwra.append(field.storage.eq(self.interface.d_i[j]))
+ bwra.append(field.storage.eq(self.interface.d_i[offset:offset+field.size]))
+ offset += field.size
if len(bwra) > 1:
bwcases.append(bwra)
else:
# Bus reads
brcases = []
- for i, reg in enumerate(self.description):
+ for i, reg in enumerate(desc_exp):
if isinstance(reg, RegisterRaw):
brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(reg.w)])
elif isinstance(reg, RegisterFields):
brs = []
reg_readable = False
- for j, field in enumerate(reg.fields):
+ for field in reg.fields:
if field.access_bus == READ_ONLY or field.access_bus == READ_WRITE:
brs.append(field.storage)
reg_readable = True
brs.append(Constant(0, BV(field.size)))
if reg_readable:
if len(brs) > 1:
- brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(f.Cat(*brs))])
+ brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(Cat(*brs))])
else:
brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(brs[0])])
else:
def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0):
self.field = Field(name, size, access_bus, access_dev, reset)
RegisterFields.__init__(self, name, [self.field])
+
+class FieldAlias:
+ def __init__(self, f, start, end):
+ self.size = end - start
+ self.access_bus = f.access_bus
+ self.access_dev = f.access_dev
+ self.storage = f.storage[start:end]
+ # device access is through the original field
+
+def expand_description(description, busword):
+ d = []
+ for reg in description:
+ if isinstance(reg, RegisterRaw):
+ if reg.size > busword:
+ raise ValueError("Raw register larger than a bus word")
+ d.append(reg)
+ elif isinstance(reg, RegisterFields):
+ f = []
+ size = 0
+ for field in reg.fields:
+ size += field.size
+ if size > busword:
+ top = field.size
+ while size > busword:
+ slice1 = busword - size + top
+ slice2 = min(size - busword, busword)
+ if slice1:
+ f.append(FieldAlias(field, top - slice1, top))
+ top -= slice1
+ d.append(RegisterFields(reg.name, f))
+ f = [FieldAlias(field, top - slice2, top)]
+ top -= slice2
+ size -= busword
+ else:
+ f.append(field)
+ if f:
+ d.append(RegisterFields(reg.name, f))
+ else:
+ raise TypeError
+ return d