bank: refactoring

This commit is contained in:
Sebastien Bourdeauducq 2012-02-06 13:55:50 +01:00
parent 1a86f26a66
commit f3ddfffc47
3 changed files with 41 additions and 40 deletions

View file

@ -5,21 +5,18 @@ from migen.bank import description, csrgen
ninputs = 4 ninputs = 4
noutputs = 4 noutputs = 4
oreg = description.Register("o") oreg = description.RegisterField("o", noutputs)
ofield = description.Field(oreg, "val", noutputs) ireg = description.RegisterRaw("i", ninputs)
ireg = description.Register("i")
ifield = description.Field(ireg, "val", ninputs, description.READ_ONLY, description.WRITE_ONLY)
# input path # input path
gpio_in = Signal(BV(ninputs)) gpio_in = Signal(BV(ninputs))
gpio_in_s = Signal(BV(ninputs)) # synchronizer gpio_in_s = Signal(BV(ninputs)) # synchronizer
incomb = [ifield.dev_we.eq(1)] insync = [gpio_in_s.eq(gpio_in), ireg.w.eq(gpio_in_s)]
insync = [gpio_in_s.eq(gpio_in), ifield.dev_w.eq(gpio_in_s)] inf = Fragment(sync=insync)
inf = Fragment(incomb, insync)
bank = csrgen.Bank([oreg, ireg]) bank = csrgen.Bank([oreg, ireg])
f = bank.get_fragment() + inf f = bank.get_fragment() + inf
oreg.field.r.name_override = "gpio_out"
i = bank.interface i = bank.interface
ofield.dev_r.name_override = "gpio_out" v = verilog.convert(f, {i.d_o, oreg.field.r, i.a_i, i.we_i, i.d_i, gpio_in})
v = verilog.convert(f, {i.d_o, ofield.dev_r, i.a_i, i.we_i, i.d_i, gpio_in})
print(v) print(v)

View file

@ -20,7 +20,12 @@ class Bank:
# Bus writes # Bus writes
bwcases = [] bwcases = []
for i, reg in enumerate(self.description): for i, reg in enumerate(self.description):
if reg.raw is None: if isinstance(reg, RegisterRaw):
comb.append(reg.r.eq(self.interface.d_i[:reg.size]))
comb.append(reg.re.eq(sel & \
self.interface.we_i & \
(self.interface.a_i[:nbits] == Constant(i, BV(nbits)))))
elif isinstance(reg, RegisterFields):
bwra = [Constant(i, BV(nbits))] bwra = [Constant(i, BV(nbits))]
for j, field in enumerate(reg.fields): for j, field in enumerate(reg.fields):
if field.access_bus == WRITE_ONLY or field.access_bus == READ_WRITE: if field.access_bus == WRITE_ONLY or field.access_bus == READ_WRITE:
@ -28,17 +33,16 @@ class Bank:
if len(bwra) > 1: if len(bwra) > 1:
bwcases.append(bwra) bwcases.append(bwra)
else: else:
comb.append(reg.dev_r.eq(self.interface.d_i[:reg.raw.width])) raise TypeError
comb.append(reg.dev_re.eq(sel & \
self.interface.we_i & \
(self.interface.a_i[:nbits] == Constant(i, BV(nbits)))))
if bwcases: if bwcases:
sync.append(If(sel & self.interface.we_i, Case(self.interface.a_i[:nbits], *bwcases))) sync.append(If(sel & self.interface.we_i, Case(self.interface.a_i[:nbits], *bwcases)))
# Bus reads # Bus reads
brcases = [] brcases = []
for i, reg in enumerate(self.description): for i, reg in enumerate(self.description):
if reg.raw is None: if isinstance(reg, RegisterRaw):
brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(reg.w)])
elif isinstance(reg, RegisterFields):
brs = [] brs = []
reg_readable = False reg_readable = False
for j, field in enumerate(reg.fields): for j, field in enumerate(reg.fields):
@ -53,7 +57,7 @@ class Bank:
else: else:
brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(brs[0])]) brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(brs[0])])
else: else:
brcases.append([Constant(i, BV(nbits)), self.interface.d_o.eq(reg.dev_w)]) raise TypeError
if brcases: if brcases:
sync.append(self.interface.d_o.eq(Constant(0, BV(8)))) sync.append(self.interface.d_o.eq(Constant(0, BV(8))))
sync.append(If(sel, Case(self.interface.a_i[:nbits], *brcases))) sync.append(If(sel, Case(self.interface.a_i[:nbits], *brcases)))
@ -62,11 +66,11 @@ class Bank:
# Device access # Device access
for reg in self.description: for reg in self.description:
if reg.raw is None: if isinstance(reg, RegisterFields):
for field in reg.fields: for field in reg.fields:
if field.access_dev == READ_ONLY or field.access_dev == READ_WRITE: if field.access_dev == READ_ONLY or field.access_dev == READ_WRITE:
comb.append(field.dev_r.eq(field.storage)) comb.append(field.r.eq(field.storage))
if field.access_dev == WRITE_ONLY or field.access_dev == READ_WRITE: if field.access_dev == WRITE_ONLY or field.access_dev == READ_WRITE:
sync.append(If(field.dev_we, field.storage.eq(field.dev_w))) sync.append(If(field.we, field.storage.eq(field.w)))
return Fragment(comb, sync) return Fragment(comb, sync)

View file

@ -1,34 +1,34 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
class Register: class RegisterRaw:
def __init__(self, name, raw=None): def __init__(self, name, size=1):
self.name = name self.name = name
self.raw = raw self.size = size
if raw is not None: self.re = Signal()
self.dev_re = Signal(name=name + "_re") self.r = Signal(BV(self.size))
self.dev_r = Signal(raw, name + "_r") self.w = Signal(BV(self.size))
self.dev_w = Signal(raw, name + "_w")
else:
self.fields = []
def add_field(self, f):
self.fields.append(f)
(READ_ONLY, WRITE_ONLY, READ_WRITE) = range(3) (READ_ONLY, WRITE_ONLY, READ_WRITE) = range(3)
class Field: class Field:
def __init__(self, parent, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0): def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0):
self.parent = parent
self.name = name self.name = name
self.size = size self.size = size
self.access_bus = access_bus self.access_bus = access_bus
self.access_dev = access_dev self.access_dev = access_dev
self.reset = reset self.storage = Signal(BV(self.size), reset=reset)
fullname = parent.name + "_" + name
self.storage = Signal(BV(self.size), fullname)
if self.access_dev == READ_ONLY or self.access_dev == READ_WRITE: if self.access_dev == READ_ONLY or self.access_dev == READ_WRITE:
self.dev_r = Signal(BV(self.size), fullname + "_r") self.r = Signal(BV(self.size))
if self.access_dev == WRITE_ONLY or self.access_dev == READ_WRITE: if self.access_dev == WRITE_ONLY or self.access_dev == READ_WRITE:
self.dev_w = Signal(BV(self.size), fullname + "_w") self.w = Signal(BV(self.size))
self.dev_we = Signal(name=fullname + "_we") self.we = Signal()
self.parent.add_field(self)
class RegisterFields:
def __init__(self, name, fields):
self.name = name
self.fields = fields
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])