Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 3 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
View
2  examples/basic/simple_gpio.py
@@ -6,7 +6,7 @@
ninputs = 32
noutputs = 32
-oreg = description.RegisterField("o", noutputs)
+oreg = description.RegisterField("o", noutputs, atomic_write=True)
ireg = description.RegisterField("i", ninputs, READ_ONLY, WRITE_ONLY)
# input path
View
3  migen/actorlib/spi.py
@@ -10,9 +10,8 @@ def __init__(self, layout, depth=1024):
self._depth = depth
self._dw = sum(len(s) for s in self.token("sink").flatten())
- # TODO: reg_wc should have atomic update
self._reg_wa = RegisterField("write_address", bits_for(self._depth-1), access_bus=READ_WRITE, access_dev=READ_WRITE)
- self._reg_wc = RegisterField("write_count", bits_for(self._depth), access_bus=READ_WRITE, access_dev=READ_WRITE)
+ self._reg_wc = RegisterField("write_count", bits_for(self._depth), access_bus=READ_WRITE, access_dev=READ_WRITE, atomic_update=True)
self._reg_ra = RegisterField("read_address", bits_for(self._depth-1), access_bus=READ_WRITE, access_dev=READ_ONLY)
self._reg_rd = RegisterField("read_data", self._dw, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
View
12 migen/bank/csrgen.py
@@ -29,7 +29,6 @@ def get_fragment(self):
self.interface.we & \
(self.interface.adr[:nbits] == Constant(i, BV(nbits)))))
elif isinstance(reg, RegisterFields):
- sync.append(reg.re.eq(0))
bwra = [Constant(i, BV(nbits))]
offset = 0
for field in reg.fields:
@@ -37,8 +36,12 @@ def get_fragment(self):
bwra.append(field.storage.eq(self.interface.dat_w[offset:offset+field.size]))
offset += field.size
if len(bwra) > 1:
- bwra.append(reg.re.eq(1))
bwcases.append(bwra)
+ # commit atomic writes
+ for field in reg.fields:
+ if isinstance(field, FieldAlias) and field.commit_list:
+ commit_instr = [hf.commit_to.eq(hf.storage) for hf in field.commit_list]
+ sync.append(If(sel & self.interface.we & self.interface.adr[:nbits] == i, *commit_instr))
else:
raise TypeError
if bwcases:
@@ -59,10 +62,7 @@ def get_fragment(self):
else:
brs.append(Constant(0, BV(field.size)))
if reg_readable:
- if len(brs) > 1:
- brcases.append([Constant(i, BV(nbits)), self.interface.dat_r.eq(Cat(*brs))])
- else:
- brcases.append([Constant(i, BV(nbits)), self.interface.dat_r.eq(brs[0])])
+ brcases.append([Constant(i, BV(nbits)), self.interface.dat_r.eq(Cat(*brs))])
else:
raise TypeError
if brcases:
View
73 migen/bank/description.py
@@ -11,12 +11,13 @@ def __init__(self, name, size=1):
(READ_ONLY, WRITE_ONLY, READ_WRITE) = range(3)
class Field:
- def __init__(self, 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, atomic_write=False):
self.name = name
self.size = size
self.access_bus = access_bus
self.access_dev = access_dev
self.storage = Signal(BV(self.size), reset=reset)
+ self.atomic_write = atomic_write
if self.access_bus == READ_ONLY and self.access_dev == WRITE_ONLY:
self.w = Signal(BV(self.size))
else:
@@ -27,25 +28,32 @@ def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, re
self.we = Signal()
class RegisterFields:
- def __init__(self, name, fields, re=None):
+ def __init__(self, name, fields):
self.name = name
self.fields = fields
- if re is None:
- self.re = Signal()
- else:
- self.re = re
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)
+ def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0, atomic_write=False):
+ self.field = Field(name, size, access_bus, access_dev, reset, atomic_write)
super().__init__(name, [self.field])
+(ALIAS_NON_ATOMIC, ALIAS_ATOMIC_HOLD, ALIAS_ATOMIC_COMMIT) = range(3)
+
class FieldAlias:
- def __init__(self, f, start, end):
+ def __init__(self, mode, f, start, end, commit_list):
+ self.mode = mode
self.size = end - start
self.access_bus = f.access_bus
self.access_dev = f.access_dev
- self.storage = f.storage[start:end]
+ if mode == ALIAS_ATOMIC_HOLD:
+ self.storage = Signal(BV(end-start), name="atomic_hold")
+ self.commit_to = f.storage[start:end]
+ else:
+ self.storage = f.storage[start:end]
+ if mode == ALIAS_ATOMIC_COMMIT:
+ self.commit_list = commit_list
+ else:
+ self.commit_list = []
# device access is through the original field
def expand_description(description, busword):
@@ -57,32 +65,49 @@ def expand_description(description, busword):
d.append(reg)
elif isinstance(reg, RegisterFields):
f = []
- size = 0
+ offset = 0
+ totalsize = 0
for field in reg.fields:
- size += field.size
- if size > busword:
+ offset += field.size
+ totalsize += field.size
+ if offset > busword:
# add padding
- totalsize = sum([field.size for field in reg.fields])
padding = busword - (totalsize % busword)
- if padding == busword:
- padding = 0
- size += padding
+ if padding != busword:
+ totalsize += padding
+ offset += padding
top = field.size
- while size > busword:
- slice1 = busword - size + top
- slice2 = min(size - busword, busword)
+ commit_list = []
+ while offset > busword:
+ if field.atomic_write:
+ if offset - busword > busword:
+ mode = ALIAS_ATOMIC_HOLD
+ else:
+ # last iteration
+ mode = ALIAS_ATOMIC_COMMIT
+ else:
+ mode = ALIAS_NON_ATOMIC
+
+ slice1 = busword - offset + top
+ slice2 = min(offset - busword, busword)
if slice1:
- f.append(FieldAlias(field, top - slice1, top))
+ alias = FieldAlias(mode, field, top - slice1, top, commit_list)
+ f.append(alias)
+ if mode == ALIAS_ATOMIC_HOLD:
+ commit_list.append(alias)
top -= slice1
d.append(RegisterFields(reg.name, f))
- f = [FieldAlias(field, top - slice2, top)]
+ alias = FieldAlias(mode, field, top - slice2, top, commit_list)
+ f = [alias]
+ if mode == ALIAS_ATOMIC_HOLD:
+ commit_list.append(alias)
top -= slice2
- size -= busword
+ offset -= busword
else:
f.append(field)
if f:
- d.append(RegisterFields(reg.name, f, reg.re))
+ d.append(RegisterFields(reg.name, f))
else:
raise TypeError
return d

No commit comments for this range

Something went wrong with that request. Please try again.