New CSR API
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 30 Mar 2013 16:28:41 +0000 (17:28 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 30 Mar 2013 16:28:41 +0000 (17:28 +0100)
examples/basic/simple_gpio.py
migen/actorlib/spi.py
migen/bank/csrgen.py
migen/bank/description.py
migen/bank/eventmanager.py
migen/bus/csr.py
migen/flow/hooks.py
migen/flow/isd.py
migen/flow/network.py

index 0576473c73a3cda301420763310484fde5f857d9..cb8a3a8f2eacf87ed847d560322a04f1dafc7e14 100644 (file)
@@ -3,12 +3,11 @@ from migen.fhdl.module import Module
 from migen.fhdl import verilog
 from migen.genlib.cdc import MultiReg
 from migen.bank import description, csrgen
-from migen.bank.description import READ_ONLY, WRITE_ONLY
 
 class Example(Module):
        def __init__(self, ninputs=32, noutputs=32):
-               r_o = description.RegisterField(noutputs, atomic_write=True)
-               r_i = description.RegisterField(ninputs, READ_ONLY, WRITE_ONLY)
+               r_o = description.CSRStorage(noutputs, atomic_write=True)
+               r_i = description.CSRStatus(ninputs)
 
                self.submodules.bank = csrgen.Bank([r_o, r_i])
                self.gpio_in = Signal(ninputs)
@@ -17,10 +16,10 @@ class Example(Module):
                ###
 
                gpio_in_s = Signal(ninputs)
-               self.specials += MultiReg(self.gpio_in, gpio_in_s, "sys")
+               self.specials += MultiReg(self.gpio_in, gpio_in_s)
                self.comb += [
-                       r_i.field.w.eq(gpio_in_s),
-                       self.gpio_out.eq(r_o.field.r)
+                       self.gpio_out.eq(r_o.storage),
+                       r_i.status.eq(gpio_in_s)
                ]
 
 example = Example()
index 1981b72d17bed21893d75d4cf40c33aa48a763e0..b831c3baa446fb6c7446421e1510b942213a0fc6 100644 (file)
@@ -18,16 +18,16 @@ def _convert_layout(layout):
                        r.append((element[0], element[1]))
        return r
 
-def _create_registers_assign(layout, target, atomic, prefix=""):
-       registers = []
+def _create_csrs_assign(layout, target, atomic, prefix=""):
+       csrs = []
        assigns = []
        for element in layout:
                if isinstance(element[1], list):
-                       r_registers, r_assigns = _create_registers_assign(element[1],
+                       r_csrs, r_assigns = _create_csrs_assign(element[1],
                                atomic,
                                getattr(target, element[0]),
                                element[0] + "_")
-                       registers += r_registers
+                       csrs += r_csrs
                        assigns += r_assigns
                else:
                        name = element[0]
@@ -40,10 +40,10 @@ def _create_registers_assign(layout, target, atomic, prefix=""):
                                alignment = element[3]
                        else:
                                alignment = 0
-                       reg = RegisterField(nbits + alignment, reset=reset, atomic_write=atomic, name=prefix + name)
-                       registers.append(reg)
-                       assigns.append(getattr(target, name).eq(reg.field.r[alignment:]))
-       return registers, assigns
+                       reg = CSRStorage(nbits + alignment, reset=reset, atomic_write=atomic, name=prefix + name)
+                       csrs.append(reg)
+                       assigns.append(getattr(target, name).eq(reg.storage[alignment:]))
+       return csrs, assigns
 
 (MODE_EXTERNAL, MODE_SINGLE_SHOT, MODE_CONTINUOUS) = range(3)
 
@@ -51,23 +51,23 @@ class SingleGenerator(Actor):
        def __init__(self, layout, mode):
                self._mode = mode
                Actor.__init__(self, ("source", Source, _convert_layout(layout)))
-               self._registers, self._assigns = _create_registers_assign(layout,
+               self._csrs, self._assigns = _create_csrs_assign(layout,
                        self.token("source"), self._mode != MODE_SINGLE_SHOT)
                if mode == MODE_EXTERNAL:
                        self.trigger = Signal()
                elif mode == MODE_SINGLE_SHOT:
-                       shoot = RegisterRaw()
-                       self._registers.insert(0, shoot)
+                       shoot = CSR()
+                       self._csrs.insert(0, shoot)
                        self.trigger = shoot.re
                elif mode == MODE_CONTINUOUS:
-                       enable = RegisterField()
-                       self._registers.insert(0, enable)
-                       self.trigger = enable.field.r
+                       enable = CSRStorage()
+                       self._csrs.insert(0, enable)
+                       self.trigger = enable.storage
                else:
                        raise ValueError
        
-       def get_registers(self):
-               return self._registers
+       def get_csrs(self):
+               return self._csrs
        
        def get_fragment(self):
                stb = self.endpoints["source"].stb
@@ -79,19 +79,16 @@ class SingleGenerator(Actor):
                sync = [If(ack | ~stb, *stmts)]
                return Fragment(comb, sync)
 
-class Collector(Actor):
+class Collector(Actor, AutoCSR):
        def __init__(self, layout, depth=1024):
                Actor.__init__(self, ("sink", Sink, layout))
                self._depth = depth
                self._dw = sum(len(s) for s in self.token("sink").flatten())
                
-               self._r_wa = RegisterField(bits_for(self._depth-1), READ_WRITE, READ_WRITE)
-               self._r_wc = RegisterField(bits_for(self._depth), READ_WRITE, READ_WRITE, atomic_write=True)
-               self._r_ra = RegisterField(bits_for(self._depth-1), READ_WRITE, READ_ONLY)
-               self._r_rd = RegisterField(self._dw, READ_ONLY, WRITE_ONLY)
-       
-       def get_registers(self):
-               return [self._r_wa, self._r_wc, self._r_ra, self._r_rd]
+               self._r_wa = CSRStorage(bits_for(self._depth-1), write_from_dev=True)
+               self._r_wc = CSRStorage(bits_for(self._depth), write_from_dev=True, atomic_write=True)
+               self._r_ra = CSRStorage(bits_for(self._depth-1))
+               self._r_rd = CSRStatus(self._dw)
        
        def get_fragment(self):
                mem = Memory(self._dw, self._depth)
@@ -99,22 +96,22 @@ class Collector(Actor):
                rp = mem.get_port()
                
                comb = [
-                       If(self._r_wc.field.r != 0,
+                       If(self._r_wc.r != 0,
                                self.endpoints["sink"].ack.eq(1),
                                If(self.endpoints["sink"].stb,
-                                       self._r_wa.field.we.eq(1),
-                                       self._r_wc.field.we.eq(1),
+                                       self._r_wa.we.eq(1),
+                                       self._r_wc.we.eq(1),
                                        wp.we.eq(1)
                                )
                        ),
-                       self._r_wa.field.w.eq(self._r_wa.field.r + 1),
-                       self._r_wc.field.w.eq(self._r_wc.field.r - 1),
+                       self._r_wa.dat_w.eq(self._r_wa.storage + 1),
+                       self._r_wc.dat_w.eq(self._r_wc.storage - 1),
                        
-                       wp.adr.eq(self._r_wa.field.r),
+                       wp.adr.eq(self._r_wa.storage),
                        wp.dat_w.eq(Cat(*self.token("sink").flatten())),
                        
-                       rp.adr.eq(self._r_ra.field.r),
-                       self._r_rd.field.w.eq(rp.dat_r)
+                       rp.adr.eq(self._r_ra.storage),
+                       self._r_rd.status.eq(rp.dat_r)
                ]
                
                return Fragment(comb, specials={mem})
index 6cf26b3ecc84266dfdce3e493cda3900c8ba4eb1..01e4bf0fe8d66ef018fcad57e73536dbe1d65092 100644 (file)
@@ -1,91 +1,51 @@
 from operator import itemgetter
 
 from migen.fhdl.structure import *
+from migen.fhdl.module import Module
 from migen.bus import csr
 from migen.bank.description import *
 
-class Bank:
+class Bank(Module):
        def __init__(self, description, address=0, bus=None):
-               self.description = description
-               self.address = address
                if bus is None:
                        bus = csr.Interface()
                self.bus = bus
-       
-       def get_fragment(self):
-               comb = []
-               sync = []
                
-               sel = Signal()
-               comb.append(sel.eq(self.bus.adr[9:] == self.address))
+               ###
+
+               if not description:
+                       return
                
-               desc_exp = expand_description(self.description, csr.data_width)
-               nbits = bits_for(len(desc_exp)-1)
+               # Turn description into simple CSRs and claim ownership of compound CSR modules
+               simple_csrs = []
+               for c in description:
+                       if isinstance(c, CSR):
+                               simple_csrs.append(c)
+                       else:
+                               c.finalize(csr.data_width)
+                               simple_csrs += c.get_simple_csrs()
+                               self.submodules += c
+               nbits = bits_for(len(simple_csrs)-1)
+
+               # Decode selection
+               sel = Signal()
+               self.comb += sel.eq(self.bus.adr[9:] == address)
                
                # Bus writes
-               bwcases = {}
-               for i, reg in enumerate(desc_exp):
-                       if isinstance(reg, RegisterRaw):
-                               comb.append(reg.r.eq(self.bus.dat_w[:reg.size]))
-                               comb.append(reg.re.eq(sel & \
+               for i, c in enumerate(simple_csrs):
+                       self.comb += [
+                               c.r.eq(self.bus.dat_w[:c.size]),
+                               c.re.eq(sel & \
                                        self.bus.we & \
-                                       (self.bus.adr[:nbits] == i)))
-                       elif isinstance(reg, RegisterFields):
-                               bwra = []
-                               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.bus.dat_w[offset:offset+field.size]))
-                                       offset += field.size
-                               if bwra:
-                                       bwcases[i] = 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.bus.we & self.bus.adr[:nbits] == i, *commit_instr))
-                       else:
-                               raise TypeError
-               if bwcases:
-                       sync.append(If(sel & self.bus.we, Case(self.bus.adr[:nbits], bwcases)))
+                                       (self.bus.adr[:nbits] == i))
+                       ]
                
                # Bus reads
-               brcases = {}
-               for i, reg in enumerate(desc_exp):
-                       if isinstance(reg, RegisterRaw):
-                               brcases[i] = [self.bus.dat_r.eq(reg.w)]
-                       elif isinstance(reg, RegisterFields):
-                               brs = []
-                               reg_readable = False
-                               for field in reg.fields:
-                                       if field.access_bus == READ_ONLY or field.access_bus == READ_WRITE:
-                                               brs.append(field.storage)
-                                               reg_readable = True
-                                       else:
-                                               brs.append(Replicate(0, field.size))
-                               if reg_readable:
-                                       brcases[i] = [self.bus.dat_r.eq(Cat(*brs))]
-                       else:
-                               raise TypeError
-               if brcases:
-                       sync.append(self.bus.dat_r.eq(0))
-                       sync.append(If(sel, Case(self.bus.adr[:nbits], brcases)))
-               else:
-                       comb.append(self.bus.dat_r.eq(0))
-               
-               # Device access
-               for reg in self.description:
-                       if isinstance(reg, RegisterFields):
-                               for field in reg.fields:
-                                       if field.access_bus == READ_ONLY and field.access_dev == WRITE_ONLY:
-                                               comb.append(field.storage.eq(field.w))
-                                       else:
-                                               if field.access_dev == READ_ONLY or field.access_dev == READ_WRITE:
-                                                       comb.append(field.r.eq(field.storage))
-                                               if field.access_dev == WRITE_ONLY or field.access_dev == READ_WRITE:
-                                                       sync.append(If(field.we, field.storage.eq(field.w)))
-               
-               return Fragment(comb, sync)
+               brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(simple_csrs))
+               self.sync += [
+                       self.bus.dat_r.eq(0),
+                       If(sel, Case(self.bus.adr[:nbits], brcases))
+               ]
 
 # address_map(name, memory) returns the CSR offset at which to map
 # the CSR object (register bank or memory).
@@ -93,7 +53,7 @@ class Bank:
 # Otherwise, it is a memory object belonging to source.name.
 # address_map is called exactly once for each object at each call to
 # scan(), so it can have side effects.
-class BankArray:
+class BankArray(Module):
        def __init__(self, source, address_map):
                self.source = source
                self.address_map = address_map
@@ -103,30 +63,29 @@ class BankArray:
                self.banks = []
                self.srams = []
                for name, obj in sorted(self.source.__dict__.items(), key=itemgetter(0)):
-                       if hasattr(obj, "get_registers"):
-                               registers = obj.get_registers()
+                       if hasattr(obj, "get_csrs"):
+                               csrs = obj.get_csrs()
                        else:
-                               registers = []
+                               csrs = []
                        if hasattr(obj, "get_memories"):
                                memories = obj.get_memories()
                                for memory in memories:
                                        mapaddr = self.address_map(name, memory)
                                        mmap = csr.SRAM(memory, mapaddr)
-                                       registers += mmap.get_registers()
-                                       self.srams.append((name, memory, mmap))
-                       if registers:
+                                       self.submodules += mmap
+                                       csrs += mmap.get_csrs()
+                                       self.srams.append((name, memory, mapaddr, mmap))
+                       if csrs:
                                mapaddr = self.address_map(name, None)
-                               rmap = Bank(registers, mapaddr)
-                               self.banks.append((name, rmap))
+                               rmap = Bank(csrs, mapaddr)
+                               self.submodules += rmap
+                               self.banks.append((name, csrs, mapaddr, rmap))
 
        def get_rmaps(self):
-               return [rmap for name, rmap in self.banks]
+               return [rmap for name, csrs, mapaddr, rmap in self.banks]
 
        def get_mmaps(self):
-               return [mmap for name, memory, mmap in self.srams]
+               return [mmap for name, memory, mapaddr, mmap in self.srams]
 
        def get_buses(self):
                return [i.bus for i in self.get_rmaps() + self.get_mmaps()]
-
-       def get_fragment(self):
-               return sum([i.get_fragment() for i in self.get_rmaps() + self.get_mmaps()], Fragment())
index 160f2fb4620a5364739041126c9a9f051a4bb614..1eb5c2c11cd4e0ffc44ff82a45a5e8231b2e7085 100644 (file)
@@ -1,70 +1,92 @@
 from migen.fhdl.structure import *
 from migen.fhdl.specials import Memory
+from migen.fhdl.module import *
 from migen.fhdl.tracer import get_obj_var_name
 
-class _Register(HUID):
-       def __init__(self, name):
+class _CSRBase(HUID):
+       def __init__(self, size, name):
                HUID.__init__(self)
                self.name = get_obj_var_name(name)
                if self.name is None:
-                       raise ValueError("Cannot extract register name from code, need to specify.")
+                       raise ValueError("Cannot extract CSR name from code, need to specify.")
                if len(self.name) > 2 and self.name[:2] == "r_":
                        self.name = self.name[2:]
+               self.size = size
 
-class RegisterRaw(_Register):
+class CSR(_CSRBase):
        def __init__(self, size=1, name=None):
-               _Register.__init__(self, name)
-               self.size = size
-               self.re = Signal()
-               self.r = Signal(self.size)
-               self.w = Signal(self.size)
+               _CSRBase.__init__(self, size, name)
+               self.re = Signal(name=self.name + "_re")
+               self.r = Signal(self.size, name=self.name + "_r")
+               self.w = Signal(self.size, name=self.name + "_w")
 
-       def get_size(self):
-               return self.size
+class _CompoundCSR(_CSRBase, Module):
+       def __init__(self, size, name):
+               _CSRBase.__init__(self, size, name)
+               self.simple_csrs = []
 
-(READ_ONLY, WRITE_ONLY, READ_WRITE) = range(3)
+       def get_simple_csrs(self):
+               if not self.finalized:
+                       raise FinalizeError
+               return self.simple_csrs
 
-class Field:
-       def __init__(self, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0, atomic_write=False, name=None):
-               self.name = get_obj_var_name(name)
-               if self.name is None:
-                       raise ValueError("Cannot extract field name from code, need to specify.")
-               self.size = size
-               self.access_bus = access_bus
-               self.access_dev = access_dev
+       def do_finalize(self, busword):
+               raise NotImplementedError
+
+class CSRStatus(_CompoundCSR):
+       def __init__(self, size=1, name=None):
+               _CompoundCSR.__init__(self, size, name)
+               self.status = Signal(self.size)
+
+       def do_finalize(self, busword):
+               nwords = (self.size + busword - 1)//busword
+               for i in reversed(range(nwords)):
+                       nbits = min(self.size - i*busword, busword)
+                       sc = CSR(nbits, self.name + str(i) if nwords > 1 else self.name)
+                       self.comb += sc.w.eq(self.status[i*busword:i*busword+nbits])
+                       self.simple_csrs.append(sc)
+
+class CSRStorage(_CompoundCSR):
+       def __init__(self, size=1, reset=0, atomic_write=False, write_from_dev=False, name=None):
+               _CompoundCSR.__init__(self, size, name)
                self.storage = Signal(self.size, reset=reset)
                self.atomic_write = atomic_write
-               if self.access_bus == READ_ONLY and self.access_dev == WRITE_ONLY:
-                       self.w = Signal(self.size)
-               else:
-                       if self.access_dev == READ_ONLY or self.access_dev == READ_WRITE:
-                               self.r = Signal(self.size, reset=reset)
-                       if self.access_dev == WRITE_ONLY or self.access_dev == READ_WRITE:
-                               self.w = Signal(self.size)
-                               self.we = Signal()
-
-class RegisterFields(_Register):
-       def __init__(self, *fields, name=None):
-               _Register.__init__(self, name)
-               self.fields = fields
+               if write_from_dev:
+                       self.we = Signal()
+                       self.dat_w = Signal(self.size)
+                       self.sync += If(self.we, self.storage.eq(self.dat_w))
 
-       def get_size(self):
-               return sum(field.size for field in self.fields)
+       def do_finalize(self, busword):
+               nwords = (self.size + busword - 1)//busword
+               if nwords > 1 and self.atomic_write:
+                       backstore = Signal(self.size - busword, name=self.name + "_backstore")
+               for i in reversed(range(nwords)):
+                       nbits = min(self.size - i*busword, busword)
+                       sc = CSR(nbits, self.name + str(i) if nwords else self.name)
+                       lo = i*busword
+                       hi = lo+nbits
+                       # read
+                       self.comb += sc.w.eq(self.storage[lo:hi])
+                       # write
+                       if nwords > 1 and self.atomic_write:
+                               if i:
+                                       self.sync += If(sc.re, backstore[lo-busword:hi-busword].eq(sc.r))
+                               else:
+                                       self.sync += If(sc.re, self.storage.eq(Cat(sc.r, backstore)))
+                       else:
+                               self.sync += If(sc.re, self.storage[lo:hi].eq(sc.r))
 
-class RegisterField(RegisterFields):
-       def __init__(self, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, reset=0, atomic_write=False, name=None):
-               self.field = Field(size, access_bus, access_dev, reset, atomic_write, name="")
-               RegisterFields.__init__(self, self.field, name=name)
+                       self.simple_csrs.append(sc)
 
-def regprefix(prefix, registers):
-       for register in registers:
-               register.name = prefix + register.name
+def csrprefix(prefix, csrs):
+       for csr in csrs:
+               csr.name = prefix + csr.name
 
 def memprefix(prefix, memories):
        for memory in memories:
                memory.name_override = prefix + memory.name_override
 
-class AutoReg:
+class AutoCSR:
        def get_memories(self):
                r = []
                for k, v in self.__dict__.items():
@@ -76,88 +98,13 @@ class AutoReg:
                                r += memories
                return sorted(r, key=lambda x: x.huid)
 
-       def get_registers(self):
+       def get_csrs(self):
                r = []
                for k, v in self.__dict__.items():
-                       if isinstance(v, _Register):
+                       if isinstance(v, _CSRBase):
                                r.append(v)
-                       elif hasattr(v, "get_registers") and callable(v.get_registers):
-                               registers = v.get_registers()
-                               regprefix(k + "_", registers)
-                               r += registers
+                       elif hasattr(v, "get_csrs") and callable(v.get_csrs):
+                               csrs = v.get_csrs()
+                               csrprefix(k + "_", csrs)
+                               r += csrs
                return sorted(r, key=lambda x: x.huid)
-
-(ALIAS_NON_ATOMIC, ALIAS_ATOMIC_HOLD, ALIAS_ATOMIC_COMMIT) = range(3)
-
-class FieldAlias:
-       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
-               if mode == ALIAS_ATOMIC_HOLD:
-                       self.storage = Signal(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):
-       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 = []
-                       offset = 0
-                       totalsize = 0
-                       for field in reg.fields:
-                               offset += field.size
-                               totalsize += field.size
-                               if offset > busword:
-                                       # add padding
-                                       padding = busword - (totalsize % busword)
-                                       if padding != busword:
-                                               totalsize += padding
-                                               offset += padding
-                                       
-                                       top = field.size
-                                       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:
-                                                       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(*f, name=reg.name))
-                                               alias = FieldAlias(mode, field, top - slice2, top, commit_list)
-                                               f = [alias]
-                                               if mode == ALIAS_ATOMIC_HOLD:
-                                                       commit_list.append(alias)
-                                               top -= slice2
-                                               offset -= busword
-                               else:
-                                       f.append(field)
-                       if f:
-                               d.append(RegisterFields(*f, name=reg.name))
-               else:
-                       raise TypeError
-       return d
index d325d0de703589adbfb409da9d6adc52a0b35d6b..b8981e59d1bc5877f4d8ed80100ef6fb0fe40aa8 100644 (file)
@@ -15,7 +15,7 @@ class EventSourcePulse(_EventSource):
 class EventSourceLevel(_EventSource):
        pass
 
-class EventManager(Module, AutoReg):
+class EventManager(Module, AutoCSR):
        def __init__(self):
                self.irq = Signal()
        
@@ -23,9 +23,9 @@ class EventManager(Module, AutoReg):
                sources_u = [v for v in self.__dict__.values() if isinstance(v, _EventSource)]
                sources = sorted(sources_u, key=lambda x: x.huid)
                n = len(sources)
-               self.status = RegisterRaw(n)
-               self.pending = RegisterRaw(n)
-               self.enable = RegisterFields(*(Field(1, READ_WRITE, READ_ONLY, name="e" + str(i)) for i in range(n)))
+               self.status = CSR(n)
+               self.pending = CSR(n)
+               self.enable = CSRStorage(n)
 
                # status
                for i, source in enumerate(sources):
@@ -55,7 +55,7 @@ class EventManager(Module, AutoReg):
                        self.comb += self.pending.w[i].eq(source.pending)
                
                # IRQ
-               irqs = [self.pending.w[i] & field.r for i, field in enumerate(self.enable.fields)]
+               irqs = [self.pending.w[i] & self.enable.storage[i] for i in range(n)]
                self.comb += self.irq.eq(optree("|", irqs))
 
        def __setattr__(self, name, value):
index 82b68aed074ee0d73dcfed9c017ca40bbc83c436..a320ae864cc262bd0cb50fa299768abfa720e53d 100644 (file)
@@ -3,7 +3,7 @@ from migen.fhdl.specials import Memory
 from migen.fhdl.module import Module
 from migen.bus.simple import *
 from migen.bus.transactions import *
-from migen.bank.description import RegisterField
+from migen.bank.description import CSRStorage
 from migen.genlib.misc import chooser
 
 data_width = 8
@@ -68,7 +68,7 @@ class SRAM:
                        self.word_bits = 0
                page_bits = _compute_page_bits(self.mem.depth + self.word_bits)
                if page_bits:
-                       self._page = RegisterField(page_bits, name=self.mem.name_override + "_page")
+                       self._page = CSRStorage(page_bits, name=self.mem.name_override + "_page")
                else:
                        self._page = None
                if read_only is None:
@@ -81,7 +81,7 @@ class SRAM:
                        bus = Interface()
                self.bus = bus
        
-       def get_registers(self):
+       def get_csrs(self):
                if self._page is None:
                        return []
                else:
@@ -126,7 +126,7 @@ class SRAM:
                if self._page is None:
                        comb.append(port.adr.eq(self.bus.adr[self.word_bits:len(port.adr)]))
                else:
-                       pv = self._page.field.r
+                       pv = self._page.storage
                        comb.append(port.adr.eq(Cat(self.bus.adr[self.word_bits:len(port.adr)-len(pv)], pv)))
                
                return Fragment(comb, sync, specials={self.mem})
index 7d2d36586a9bcb695b829bfdba4eed986c4131b1..82ae60a58bd69315f244659f2b7453bccab0bfa1 100644 (file)
@@ -1,3 +1,5 @@
+from collections import defaultdict
+
 from migen.fhdl.structure import *
 from migen.fhdl.module import Module
 from migen.flow.actor import *
@@ -24,23 +26,18 @@ class EndpointSimHook(Module):
                else:
                        self.on_inactive()
 
-class DFGHook:
+class DFGHook(Module):
        def __init__(self, dfg, create):
                assert(not dfg.is_abstract())
-               self.nodepair_to_ep = dict()
-               for u, v, data in dfg.edges_iter(data=True):
-                       if (u, v) in self.nodepair_to_ep:
-                               ep_to_hook = self.nodepair_to_ep[(u, v)]
-                       else:
-                               ep_to_hook = dict()
-                               self.nodepair_to_ep[(u, v)] = ep_to_hook
+               self.nodepair_to_ep = defaultdict(dict)
+               for hookn, (u, v, data) in dfg.edges_iter(data=True):
+                       ep_to_hook = self.nodepair_to_ep[(u, v)]
                        ep = data["source"]
-                       ep_to_hook[ep] = create(u, ep, v)
+                       h = create(u, ep, v)
+                       ep_to_hook[ep] = h
+                       setattr(self.submodules, "hook"+str(hookn), h)
        
        def hooks_iter(self):
                for v1 in self.nodepair_to_ep.values():
                        for v2 in v1.values():
                                yield v2
-       
-       def get_fragment(self):
-               return sum([h.get_fragment() for h in self.hooks_iter()], Fragment())
index a112070c5d60569fae83242d63cec717a5dfee8b..1b7d2ea39ac80ecf1c1ce53383d72b631d0055e3 100644 (file)
@@ -1,38 +1,30 @@
 from migen.fhdl.structure import *
+from migen.fhdl.module import Module
 from migen.bank.description import *
 from migen.flow.hooks import DFGHook
 
 ISD_MAGIC = 0x6ab4
 
-class EndpointReporter:
+class EndpointReporter(Module, AutoCSR):
        def __init__(self, endpoint, nbits):
-               self.endpoint = endpoint
-               self.nbits = nbits
                self.reset = Signal()
                self.freeze = Signal()
                
-               self._ack_count = RegisterField(self.nbits, READ_ONLY, WRITE_ONLY)
-               self._nack_count = RegisterField(self.nbits, READ_ONLY, WRITE_ONLY)
-               self._cur_stb = Field(1, READ_ONLY, WRITE_ONLY)
-               self._cur_ack = Field(1, READ_ONLY, WRITE_ONLY)
-               self._cur_status = RegisterFields(self._cur_stb, self._cur_ack)
+               self._ack_count = CSRStatus(nbits)
+               self._nack_count = CSRStatus(nbits)
+               self._cur_status = CSRStatus(2)
        
-       def get_registers(self):
-               return [self._ack_count, self._nack_count, self._cur_status]
-       
-       def get_fragment(self):
+               ###
+
                stb = Signal()
                ack = Signal()
-               ack_count = Signal(self.nbits)
-               nack_count = Signal(self.nbits)
-               comb = [
-                       self._cur_stb.w.eq(stb),
-                       self._cur_ack.w.eq(ack)
-               ]
-               sync = [
+               self.comb += self._cur_status.status.eq(Cat(stb, ack))
+               ack_count = Signal(nbits)
+               nack_count = Signal(nbits)
+               self.sync += [
                        # register monitored signals
-                       stb.eq(self.endpoint.stb),
-                       ack.eq(self.endpoint.ack),
+                       stb.eq(endpoint.stb),
+                       ack.eq(endpoint.ack),
                        # count operations
                        If(self.reset,
                                ack_count.eq(0),
@@ -47,49 +39,31 @@ class EndpointReporter:
                                )
                        ),
                        If(~self.freeze,
-                               self._ack_count.field.w.eq(ack_count),
-                               self._nack_count.field.w.eq(nack_count)
+                               self._ack_count.status.eq(ack_count),
+                               self._nack_count.status.eq(nack_count)
                        )
                ]
-               return Fragment(comb, sync)
 
-class DFGReporter(DFGHook):
+class DFGReporter(DFGHook, AutoCSR):
        def __init__(self, dfg, nbits):
-               self._nbits = nbits
+               self._r_magic = CSRStatus(16)
+               self._r_neps = CSRStatus(8)
+               self._r_nbits = CSRStatus(8)
+               self._r_freeze = CSRStorage()
+               self._r_reset = CSR()
                
-               self._r_magic = RegisterField(16, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
-               self._r_neps = RegisterField(8, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
-               self._r_nbits = RegisterField(8, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
-               self._r_freeze = RegisterField()
-               self._r_reset = RegisterRaw()
-               
-               self.order = []
-               DFGHook.__init__(self, dfg, self._create)
-       
-       def _create(self, u, ep, v):
-               self.order.append((u, ep, v))
-               return EndpointReporter(u.actor.endpoints[ep], self._nbits)
-       
-       def print_map(self):
-               for n, (u, ep, v) in enumerate(self.order):
-                       print("#" + str(n) + ": " + str(u) + ":" + ep + "  ->  " + str(v))
-       
-       def get_registers(self):
-               registers = [self._r_magic, self._r_neps, self._r_nbits,
-                       self._r_freeze, self._r_reset]
-               for u, ep, v in self.order:
-                       registers += self.nodepair_to_ep[(u, v)][ep].get_registers()
-               return registers
-       
-       def get_fragment(self):
-               comb = [
-                       self._r_magic.field.w.eq(ISD_MAGIC),
-                       self._r_neps.field.w.eq(len(self.order)),
-                       self._r_nbits.field.w.eq(self._nbits)
+               ###
+
+               DFGHook.__init__(self, dfg,
+                       lambda u, ep, v: EndpointReporter(u.endpoints[ep], nbits))
+
+               self.comb += [
+                       self._r_magic.status.eq(ISD_MAGIC),
+                       self._r_neps.status.eq(len(self.hooks_iter())),
+                       self._r_nbits.status.eq(nbits)
                ]
                for h in self.hooks_iter():
-                       comb += [
-                               h.freeze.eq(self._r_freeze.field.r),
+                       self.comb += [
+                               h.freeze.eq(self._r_freeze.storage),
                                h.reset.eq(self._r_reset.re)
                        ]
-               return Fragment(comb) + DFGHook.get_fragment(self)
index df739eef248162c2850d7a97e38cb0c526441f35..ee6962946dd37cde2253ba9bc24a00577f353cf1 100644 (file)
@@ -211,9 +211,9 @@ class CompositeActor(Actor):
                        self.debugger = DFGReporter(self.dfg, debugger_nbits)
                Actor.__init__(self)
        
-       def get_registers(self):
+       def get_csrs(self):
                if hasattr(self, "debugger"):
-                       return self.debugger.get_registers()
+                       return self.debugger.get_csrs()
                else:
                        return []