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.
  • 12 commits
  • 8 files changed
  • 0 commit comments
  • 1 contributor
View
44 migen/bank/csrgen.py
@@ -84,3 +84,47 @@ def get_fragment(self):
sync.append(If(field.we, field.storage.eq(field.w)))
return Fragment(comb, sync)
+
+# address_map(name, memory) returns the CSR offset at which to map
+# the CSR object (register bank or memory).
+# If memory=None, the object is the register bank of object source.name.
+# 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:
+ def __init__(self, source, address_map):
+ self.source = source
+ self.address_map = address_map
+ self.scan()
+
+ def scan(self):
+ self.banks = []
+ self.srams = []
+ for name, obj in self.source.__dict__.items():
+ if hasattr(obj, "get_registers"):
+ registers = obj.get_registers()
+ else:
+ registers = []
+ 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(mmap)
+ if registers:
+ mapaddr = self.address_map(name, None)
+ rmap = Bank(registers, mapaddr)
+ self.banks.append(rmap)
+
+ def get_banks(self):
+ return self.banks
+
+ def get_srams(self):
+ return self.srams
+
+ def get_buses(self):
+ return [i.bus for i in self.banks + self.srams]
+
+ def get_fragment(self):
+ return sum([i.get_fragment() for i in self.banks + self.srams], Fragment())
View
55 migen/bank/description.py
@@ -1,17 +1,14 @@
-from migen.fhdl.structure import *
+from copy import copy
-def regprefix(prefix, registers):
- for register in registers:
- register.name = prefix + register.name
- return registers
+from migen.fhdl.structure import *
+from migen.fhdl.specials import Memory
-def memprefix(prefix, memories):
- for memory in memories:
- memory.name_override = prefix + memory.name_override
- return memories
+class Register(HUID):
+ pass
-class RegisterRaw:
+class RegisterRaw(Register):
def __init__(self, name, size=1):
+ Register.__init__(self)
self.name = name
self.size = size
self.re = Signal()
@@ -37,8 +34,9 @@ def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, re
self.w = Signal(self.size)
self.we = Signal()
-class RegisterFields:
+class RegisterFields(Register):
def __init__(self, name, fields):
+ Register.__init__(self)
self.name = name
self.fields = fields
@@ -47,6 +45,41 @@ def __init__(self, name, size=1, access_bus=READ_WRITE, access_dev=READ_ONLY, re
self.field = Field(name, size, access_bus, access_dev, reset, atomic_write)
RegisterFields.__init__(self, name, [self.field])
+def regprefix(prefix, registers):
+ r = []
+ for register in registers:
+ c = copy(register)
+ c.name = prefix + c.name
+ r.append(c)
+ return r
+
+def memprefix(prefix, memories):
+ r = []
+ for memory in memories:
+ c = copy(memory)
+ c.name_override = prefix + c.name_override
+ r.append(c)
+ return memories
+
+class AutoReg:
+ def get_memories(self):
+ r = []
+ for k, v in self.__dict__.items():
+ if isinstance(v, Memory):
+ r.append(v)
+ elif hasattr(v, "get_memories") and callable(v.get_memories):
+ r += memprefix(k + "_", v.get_memories())
+ return sorted(r, key=lambda x: x.huid)
+
+ def get_registers(self):
+ r = []
+ for k, v in self.__dict__.items():
+ if isinstance(v, Register):
+ r.append(v)
+ elif hasattr(v, "get_registers") and callable(v.get_registers):
+ r += regprefix(k + "_", v.get_registers())
+ return sorted(r, key=lambda x: x.huid)
+
(ALIAS_NON_ATOMIC, ALIAS_ATOMIC_HOLD, ALIAS_ATOMIC_COMMIT) = range(3)
class FieldAlias:
View
49 migen/bank/eventmanager.py
@@ -1,9 +1,11 @@
from migen.fhdl.structure import *
+from migen.fhdl.module import Module
from migen.bank.description import *
from migen.genlib.misc import optree
-class EventSource:
+class EventSource(HUID):
def __init__(self):
+ HUID.__init__(self)
self.trigger = Signal()
self.pending = Signal()
@@ -13,52 +15,51 @@ class EventSourcePulse(EventSource):
class EventSourceLevel(EventSource):
pass
-class EventManager:
- def __init__(self, *sources):
- self.sources = sources
+class EventManager(Module, AutoReg):
+ def __init__(self):
self.irq = Signal()
- n = len(self.sources)
+
+ def do_finalize(self):
+ 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("status", n)
self.pending = RegisterRaw("pending", n)
self.enable = RegisterFields("enable",
[Field("s" + str(i), access_bus=READ_WRITE, access_dev=READ_ONLY) for i in range(n)])
-
- def get_registers(self):
- return [self.status, self.pending, self.enable]
-
- def get_fragment(self):
- comb = []
- sync = []
-
+
# status
- for i, source in enumerate(self.sources):
+ for i, source in enumerate(sources):
if isinstance(source, EventSourcePulse):
- comb.append(self.status.w[i].eq(0))
+ self.comb += self.status.w[i].eq(0)
elif isinstance(source, EventSourceLevel):
- comb.append(self.status.w[i].eq(source.trigger))
+ self.comb += self.status.w[i].eq(source.trigger)
else:
raise TypeError
# pending
- for i, source in enumerate(self.sources):
+ for i, source in enumerate(sources):
# W1C
- sync.append(If(self.pending.re & self.pending.r[i], source.pending.eq(0)))
+ self.sync += If(self.pending.re & self.pending.r[i], source.pending.eq(0))
if isinstance(source, EventSourcePulse):
# set on a positive trigger pulse
- sync.append(If(source.trigger, source.pending.eq(1)))
+ self.sync += If(source.trigger, source.pending.eq(1))
elif isinstance(source, EventSourceLevel):
# set on the falling edge of the trigger
old_trigger = Signal()
- sync += [
+ self.sync += [
old_trigger.eq(source.trigger),
If(~source.trigger & old_trigger, source.pending.eq(1))
]
else:
raise TypeError
- comb.append(self.pending.w[i].eq(source.pending))
+ 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)]
- comb.append(self.irq.eq(optree("|", irqs)))
-
- return Fragment(comb, sync)
+ self.comb += self.irq.eq(optree("|", irqs))
+
+ def __setattr__(self, name, value):
+ if isinstance(value, EventSource) and self.finalized:
+ raise FinalizeError
+ object.__setattr__(self, name, value)
View
123 migen/bus/asmibus.py
@@ -1,21 +1,17 @@
from migen.fhdl.structure import *
+from migen.fhdl.module import Module, FinalizeError
from migen.genlib.misc import optree
from migen.bus.transactions import *
-from migen.sim.generic import Proxy, PureSimulable
-
-class FinalizeError(Exception):
- pass
+from migen.sim.generic import Proxy
(SLOT_EMPTY, SLOT_PENDING, SLOT_PROCESSING) = range(3)
-class Slot:
+class Slot(Module):
def __init__(self, aw, time):
self.state = Signal(2)
self.we = Signal()
self.adr = Signal(aw)
- self.time = time
- if self.time:
- self._counter = Signal(max=time+1)
+ if time:
self.mature = Signal()
self.allocate = Signal()
@@ -24,9 +20,9 @@ def __init__(self, aw, time):
self.process = Signal()
self.call = Signal()
- def get_fragment(self):
- comb = []
- sync = [
+ ###
+
+ self.sync += [
If(self.allocate,
self.state.eq(SLOT_PENDING),
self.we.eq(self.allocate_we),
@@ -35,24 +31,21 @@ def get_fragment(self):
If(self.process, self.state.eq(SLOT_PROCESSING)),
If(self.call, self.state.eq(SLOT_EMPTY))
]
- if self.time:
- comb += [
- self.mature.eq(self._counter == 0)
- ]
- sync += [
+ if time:
+ _counter = Signal(max=time+1)
+ self.comb += self.mature.eq(self._counter == 0)
+ self.sync += [
If(self.allocate,
self._counter.eq(self.time)
).Elif(self._counter != 0,
self._counter.eq(self._counter - 1)
)
]
- return Fragment(comb, sync)
-class Port:
+class Port(Module):
def __init__(self, hub, nslots):
self.hub = hub
- self.slots = [Slot(self.hub.aw, self.hub.time) for i in range(nslots)]
- self.finalized = False
+ self.submodules.slots = [Slot(self.hub.aw, self.hub.time) for i in range(nslots)]
# request issuance
self.adr = Signal(self.hub.aw)
@@ -67,36 +60,20 @@ def __init__(self, hub, nslots):
self.dat_r = Signal(self.hub.dw)
self.dat_w = Signal(self.hub.dw)
self.dat_wm = Signal(self.hub.dw//8)
-
- def finalize(self, tagbits, base):
- if self.finalized:
- raise FinalizeError
- self.finalized = True
+
+ def set_position(self, tagbits, base):
self.tagbits = tagbits
self.base = base
+
+ def do_finalize(self):
nslots = len(self.slots)
if nslots > 1:
self.tag_issue = Signal(max=nslots)
- self.tag_call = Signal(tagbits)
-
- def get_call_expression(self, slotn=0):
- if not self.finalized:
- raise FinalizeError
- return self.call \
- & (self.tag_call == (self.base + slotn))
-
- def get_fragment(self):
- if not self.finalized:
- raise FinalizeError
-
- slots_fragment = sum([s.get_fragment() for s in self.slots], Fragment())
-
- comb = []
- sync = []
-
+ self.tag_call = Signal(self.tagbits)
+
# allocate
for s in self.slots:
- comb += [
+ self.comb += [
s.allocate_we.eq(self.we),
s.allocate_adr.eq(self.adr)
]
@@ -107,26 +84,29 @@ def get_fragment(self):
s.allocate.eq(self.stb),
self.tag_issue.eq(n) if needs_tags else None
).Else(choose_slot)
- comb.append(choose_slot)
- comb.append(self.ack.eq(optree("|",
- [s.state == SLOT_EMPTY for s in self.slots])))
-
+ self.comb += choose_slot
+ self.comb += self.ack.eq(optree("|",
+ [s.state == SLOT_EMPTY for s in self.slots]))
+
# call
- comb += [s.call.eq(self.get_call_expression(n))
+ self.comb += [s.call.eq(self.get_call_expression(n))
for n, s in enumerate(self.slots)]
-
- return slots_fragment + Fragment(comb, sync)
+
+ def get_call_expression(self, slotn=0):
+ if not self.finalized:
+ raise FinalizeError
+ return self.call \
+ & (self.tag_call == (self.base + slotn))
-class Hub:
+class Hub(Module):
def __init__(self, aw, dw, time=0):
self.aw = aw
self.dw = dw
self.time = time
self.ports = []
- self.finalized = False
self.call = Signal()
- # tag_call is created by finalize()
+ # tag_call is created by do_finalize()
self.dat_r = Signal(self.dw)
self.dat_w = Signal(self.dw)
self.dat_wm = Signal(self.dw//8)
@@ -138,41 +118,34 @@ def get_port(self, nslots=1):
self.ports.append(new_port)
return new_port
- def finalize(self):
- if self.finalized:
- raise FinalizeError
- self.finalized = True
+ def do_finalize(self):
nslots = sum([len(port.slots) for port in self.ports])
tagbits = bits_for(nslots-1)
base = 0
for port in self.ports:
- port.finalize(tagbits, base)
+ port.set_position(tagbits, base)
+ port.finalize()
base += len(port.slots)
+ self.submodules += self.ports
self.tag_call = Signal(tagbits)
-
- def get_slots(self):
- if not self.finalized:
- raise FinalizeError
- return sum([port.slots for port in self.ports], [])
-
- def get_fragment(self):
- if not self.finalized:
- raise FinalizeError
- ports = sum([port.get_fragment() for port in self.ports], Fragment())
- comb = []
+
for port in self.ports:
- comb += [
+ self.comb += [
port.call.eq(self.call),
port.tag_call.eq(self.tag_call),
port.dat_r.eq(self.dat_r)
]
- comb += [
+ self.comb += [
self.dat_w.eq(optree("|", [port.dat_w for port in self.ports])),
self.dat_wm.eq(optree("|", [port.dat_wm for port in self.ports]))
]
- return ports + Fragment(comb)
+
+ def get_slots(self):
+ if not self.finalized:
+ raise FinalizeError
+ return sum([port.slots for port in self.ports], [])
-class Tap(PureSimulable):
+class Tap(Module):
def __init__(self, hub, handler=print):
self.hub = hub
self.handler = handler
@@ -212,7 +185,7 @@ def do_simulation(self, s):
transaction.latency = s.cycle_counter - transaction.latency + 1
self.transaction = transaction
-class Initiator(PureSimulable):
+class Initiator(Module):
def __init__(self, generator, port):
self.generator = generator
self.port = port
@@ -287,7 +260,7 @@ def select_slot(self, pending_slots):
self.last_slot += 1
return self.last_slot
-class Target(PureSimulable):
+class Target(Module):
def __init__(self, model, hub):
self.model = model
self.hub = hub
View
123 migen/fhdl/autofragment.py
@@ -1,123 +0,0 @@
-import inspect
-
-from migen.fhdl.structure import *
-from migen.fhdl.specials import Special
-
-def from_local():
- f = Fragment()
- frame = inspect.currentframe().f_back
- ns = frame.f_locals
- for x in ns:
- obj = ns[x]
- if hasattr(obj, "get_fragment"):
- f += obj.get_fragment()
- return f
-
-def from_attributes(obj):
- f = Fragment()
- for x in obj.__dict__.values():
- if hasattr(x, "get_fragment"):
- f += x.get_fragment()
- return f
-
-class _FModuleProxy:
- def __init__(self, fm):
- object.__setattr__(self, "_fm", fm)
-
-class _FModuleComb(_FModuleProxy):
- def __iadd__(self, other):
- if isinstance(other, (list, tuple)):
- self._fm._fragment.comb += other
- else:
- self._fm._fragment.comb.append(other)
- return self
-
-def _cd_append(d, key, statements):
- try:
- l = d[key]
- except KeyError:
- l = []
- d[key] = l
- if isinstance(statements, (list, tuple)):
- l += statements
- else:
- l.append(statements)
-
-class _FModuleSyncCD:
- def __init__(self, fm, cd):
- self._fm = fm
- self._cd = cd
-
- def __iadd__(self, other):
- _cd_append(self._fm._fragment.sync, self._cd, other)
- return self
-
-class _FModuleSync(_FModuleProxy):
- def __iadd__(self, other):
- _cd_append(self._fm._fragment.sync, "sys", other)
- return self
-
- def __getattr__(self, name):
- return _FModuleSyncCD(self._fm, name)
-
- def __setattr__(self, name, value):
- if not isinstance(value, _FModuleSyncCD):
- raise AttributeError("Attempted to assign sync property - use += instead")
-
-class _FModuleSpecials(_FModuleProxy):
- def __iadd__(self, other):
- if isinstance(other, (set, list, tuple)):
- self._fm._fragment.specials |= set(other)
- else:
- self._fm._fragment.specials.add(other)
- return self
-
-class _FModuleSubmodules(_FModuleProxy):
- def __iadd__(self, other):
- if isinstance(other, (list, tuple)):
- self._fm._submodules += other
- else:
- self._fm._submodules.append(other)
- return self
-
-class FModule:
- auto_attr = True
-
- def get_fragment(self):
- assert(not hasattr(self, "_fragment"))
- self._fragment = Fragment()
- self._submodules = []
- self.build_fragment()
- if hasattr(self, "do_simulation"):
- self._fragment.sim.append(self.do_simulation)
- for submodule in self._submodules:
- f += submodule.get_fragment()
- if self.auto_attr:
- for x in self.__dict__.values():
- if isinstance(x, Special):
- self._fragment.specials.add(x)
- elif hasattr(x, "get_fragment"):
- self._fragment += x.get_fragment()
- return self._fragment
-
- def __getattr__(self, name):
- if name == "comb":
- return _FModuleComb(self)
- elif name == "sync":
- return _FModuleSync(self)
- elif name == "specials":
- return _FModuleSpecials(self)
- elif name == "submodules":
- return _FModuleSubmodules(self)
- else:
- raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'")
-
- def __setattr__(self, name, value):
- if name in ["comb", "sync", "specials", "submodules"]:
- if not isinstance(value, _FModuleProxy):
- raise AttributeError("Attempted to assign special FModule property - use += instead")
- else:
- object.__setattr__(self, name, value)
-
- def build_fragment(self):
- raise NotImplementedError("FModule.build_fragment needs to be overloaded")
View
129 migen/fhdl/module.py
@@ -0,0 +1,129 @@
+import collections
+
+from migen.fhdl.structure import *
+from migen.fhdl.specials import Special
+from migen.fhdl.tools import flat_iteration
+
+class FinalizeError(Exception):
+ pass
+
+def _flat_list(e):
+ if isinstance(e, collections.Iterable):
+ return flat_iteration(e)
+ else:
+ return [e]
+
+class _ModuleProxy:
+ def __init__(self, fm):
+ object.__setattr__(self, "_fm", fm)
+
+class _ModuleComb(_ModuleProxy):
+ def __iadd__(self, other):
+ self._fm._fragment.comb += _flat_list(other)
+ return self
+
+def _cd_append(d, key, statements):
+ try:
+ l = d[key]
+ except KeyError:
+ l = []
+ d[key] = l
+ l += _flat_list(statements)
+
+class _ModuleSyncCD:
+ def __init__(self, fm, cd):
+ self._fm = fm
+ self._cd = cd
+
+ def __iadd__(self, other):
+ _cd_append(self._fm._fragment.sync, self._cd, other)
+ return self
+
+class _ModuleSync(_ModuleProxy):
+ def __iadd__(self, other):
+ _cd_append(self._fm._fragment.sync, "sys", other)
+ return self
+
+ def __getattr__(self, name):
+ return _ModuleSyncCD(self._fm, name)
+
+ def __setattr__(self, name, value):
+ if not isinstance(value, _ModuleSyncCD):
+ raise AttributeError("Attempted to assign sync property - use += instead")
+
+# _ModuleForwardAttr enables user classes to do e.g.:
+# self.subm.foobar = SomeModule()
+# and then access the submodule with self.foobar.
+class _ModuleForwardAttr:
+ def __setattr__(self, name, value):
+ self.__iadd__(value)
+ setattr(self._fm, name, value)
+
+class _ModuleSpecials(_ModuleProxy, _ModuleForwardAttr):
+ def __iadd__(self, other):
+ self._fm._fragment.specials |= set(_flat_list(other))
+ return self
+
+class _ModuleSubmodules(_ModuleProxy, _ModuleForwardAttr):
+ def __iadd__(self, other):
+ self._fm._submodules += _flat_list(other)
+ return self
+
+class Module:
+ def get_fragment(self):
+ assert(not self._get_fragment_called)
+ self._get_fragment_called = True
+ self.finalize()
+ return self._fragment
+
+ def __getattr__(self, name):
+ if name == "comb":
+ return _ModuleComb(self)
+ elif name == "sync":
+ return _ModuleSync(self)
+ elif name == "specials":
+ return _ModuleSpecials(self)
+ elif name == "submodules":
+ return _ModuleSubmodules(self)
+
+ # hack to have initialized regular attributes without using __init__
+ # (which would require derived classes to call it)
+ elif name == "finalized":
+ self.finalized = False
+ return self.finalized
+ elif name == "_fragment":
+ try:
+ sim = [self.do_simulation]
+ except AttributeError:
+ sim = []
+ self._fragment = Fragment(sim=sim)
+ return self._fragment
+ elif name == "_submodules":
+ self._submodules = []
+ return self._submodules
+ elif name == "_get_fragment_called":
+ self._get_fragment_called = False
+ return self._get_fragment_called
+
+ else:
+ raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'")
+
+ def __setattr__(self, name, value):
+ if name in ["comb", "sync", "specials", "submodules"]:
+ if not isinstance(value, _ModuleProxy):
+ raise AttributeError("Attempted to assign special Module property - use += instead")
+ else:
+ object.__setattr__(self, name, value)
+
+ def finalize(self):
+ if not self.finalized:
+ self.finalized = True
+ for submodule in self._submodules:
+ self._fragment += submodule.get_fragment()
+ self._submodules = []
+ self.do_finalize()
+ for submodule in self._submodules:
+ self._fragment += submodule.get_fragment()
+
+ def do_finalize(self):
+ pass
View
4 migen/fhdl/tools.py
@@ -1,10 +1,12 @@
+import collections
+
from migen.fhdl.structure import *
from migen.fhdl.structure import _Operator, _Slice, _Assign, _ArrayProxy
from migen.fhdl.visit import NodeVisitor, NodeTransformer
def flat_iteration(l):
for element in l:
- if isinstance(element, (list, tuple)):
+ if isinstance(element, collections.Iterable):
for element2 in flat_iteration(element):
yield element2
else:
View
3  migen/pytholite/reg.py
@@ -3,9 +3,6 @@
from migen.fhdl.structure import *
from migen.fhdl import visit as fhdl
-class FinalizeError(Exception):
- pass
-
class AbstractLoad:
def __init__(self, target, source):
self.target = target

No commit comments for this range

Something went wrong with that request. Please try again.