From 3a2a0c4dd80c40cd34b783113c058f5047e6e793 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 6 Feb 2012 16:15:27 +0100 Subject: [PATCH] bank: support registers larger than the bus word width --- examples/simple_gpio.py | 2 +- migen/bank/csrgen.py | 17 ++++++++++------- migen/bank/description.py | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/examples/simple_gpio.py b/examples/simple_gpio.py index 426df02c..b53a323a 100644 --- a/examples/simple_gpio.py +++ b/examples/simple_gpio.py @@ -3,7 +3,7 @@ from migen.fhdl import verilog from migen.bank import description, csrgen ninputs = 4 -noutputs = 4 +noutputs = 31 oreg = description.RegisterField("o", noutputs) ireg = description.RegisterRaw("i", ninputs) diff --git a/migen/bank/csrgen.py b/migen/bank/csrgen.py index 89457935..6007ab50 100644 --- a/migen/bank/csrgen.py +++ b/migen/bank/csrgen.py @@ -15,11 +15,12 @@ class Bank: 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 & \ @@ -27,9 +28,11 @@ class Bank: (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: @@ -39,13 +42,13 @@ class Bank: # 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 @@ -53,7 +56,7 @@ class Bank: 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: diff --git a/migen/bank/description.py b/migen/bank/description.py index 14d2d136..325738f7 100644 --- a/migen/bank/description.py +++ b/migen/bank/description.py @@ -32,3 +32,43 @@ class RegisterField(RegisterFields): 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 -- 2.30.2