from migen.fhdl.structure import *
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 CSRStorage
+from migen.genlib.record import *
from migen.genlib.misc import chooser
data_width = 8
-class Interface(SimpleInterface):
+class Interface(Record):
def __init__(self):
- SimpleInterface.__init__(self, Description(
- (M_TO_S, "adr", 14),
- (M_TO_S, "we", 1),
- (M_TO_S, "dat_w", data_width),
- (S_TO_M, "dat_r", data_width)))
+ Record.__init__(self, [
+ ("adr", 14, DIR_M_TO_S),
+ ("we", 1, DIR_M_TO_S),
+ ("dat_w", data_width, DIR_M_TO_S),
+ ("dat_r", data_width, DIR_S_TO_M)])
-class Interconnect(SimpleInterconnect):
- pass
+class Interconnect(Module):
+ def __init__(self, master, slaves):
+ self.comb += master.connect(*slaves)
class Initiator(Module):
def __init__(self, generator, bus=None):
else:
return 0
-class SRAM:
+class SRAM(Module):
def __init__(self, mem_or_size, address, read_only=None, bus=None):
if isinstance(mem_or_size, Memory):
- self.mem = mem_or_size
+ mem = mem_or_size
else:
- self.mem = Memory(data_width, mem_or_size//(data_width//8))
- self.address = address
- if self.mem.width > data_width:
- self.csrw_per_memw = (self.mem.width + data_width - 1)//data_width
- self.word_bits = bits_for(self.csrw_per_memw-1)
+ mem = Memory(data_width, mem_or_size//(data_width//8))
+ if mem.width > data_width:
+ csrw_per_memw = (self.mem.width + data_width - 1)//data_width
+ word_bits = bits_for(csrw_per_memw-1)
else:
- self.csrw_per_memw = 1
- self.word_bits = 0
- page_bits = _compute_page_bits(self.mem.depth + self.word_bits)
+ csrw_per_memw = 1
+ word_bits = 0
+ page_bits = _compute_page_bits(mem.depth + word_bits)
if page_bits:
self._page = CSRStorage(page_bits, name=self.mem.name_override + "_page")
else:
self._page = None
if read_only is None:
- if hasattr(self.mem, "bus_read_only"):
- read_only = self.mem.bus_read_only
+ if hasattr(mem, "bus_read_only"):
+ read_only = mem.bus_read_only
else:
read_only = False
- self.read_only = read_only
if bus is None:
bus = Interface()
self.bus = bus
- def get_csrs(self):
- if self._page is None:
- return []
- else:
- return [self._page]
-
- def get_fragment(self):
- port = self.mem.get_port(write_capable=not self.read_only,
- we_granularity=data_width if not self.read_only and self.word_bits else 0)
+ ###
+
+ self.specials += mem
+ port = mem.get_port(write_capable=not read_only,
+ we_granularity=data_width if not read_only and word_bits else 0)
sel = Signal()
sel_r = Signal()
- sync = [sel_r.eq(sel)]
- comb = [sel.eq(self.bus.adr[9:] == self.address)]
+ self.sync += sel_r.eq(sel)
+ self.comb += sel.eq(self.bus.adr[9:] == address)
- if self.word_bits:
- word_index = Signal(self.word_bits)
- word_expanded = Signal(self.csrw_per_memw*data_width)
- sync.append(word_index.eq(self.bus.adr[:self.word_bits]))
- comb += [
+ if word_bits:
+ word_index = Signal(word_bits)
+ word_expanded = Signal(csrw_per_memw*data_width)
+ sync.append(word_index.eq(self.bus.adr[:word_bits]))
+ self.comb += [
word_expanded.eq(port.dat_r),
If(sel_r,
- chooser(word_expanded, word_index, self.bus.dat_r, n=self.csrw_per_memw, reverse=True)
+ chooser(word_expanded, word_index, self.bus.dat_r, n=csrw_per_memw, reverse=True)
)
]
- if not self.read_only:
- comb += [
- If(sel & self.bus.we, port.we.eq((1 << self.word_bits) >> self.bus.adr[:self.word_bits])),
- port.dat_w.eq(Replicate(self.bus.dat_w, self.csrw_per_memw))
+ if not read_only:
+ self.comb += [
+ If(sel & self.bus.we, port.we.eq((1 << word_bits) >> self.bus.adr[:self.word_bits])),
+ port.dat_w.eq(Replicate(self.bus.dat_w, csrw_per_memw))
]
else:
- comb += [
- If(sel_r,
- self.bus.dat_r.eq(port.dat_r)
- )
- ]
- if not self.read_only:
- comb += [
+ self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r))
+ if not read_only:
+ self.comb += [
port.we.eq(sel & self.bus.we),
port.dat_w.eq(self.bus.dat_w)
]
if self._page is None:
- comb.append(port.adr.eq(self.bus.adr[self.word_bits:len(port.adr)]))
+ self.comb += port.adr.eq(self.bus.adr[word_bits:len(port.adr)])
else:
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})
+ self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:len(port.adr)-len(pv)], pv))
+
+ def get_csrs(self):
+ if self._page is None:
+ return []
+ else:
+ return [self._page]
from migen.fhdl.structure import *
-from migen.bus.simple import *
+from migen.fhdl.module import Module
+from migen.genlib.record import *
def phase_description(a, ba, d):
- return Description(
- (M_TO_S, "address", a),
- (M_TO_S, "bank", ba),
- (M_TO_S, "cas_n", 1),
- (M_TO_S, "cke", 1),
- (M_TO_S, "cs_n", 1),
- (M_TO_S, "ras_n", 1),
- (M_TO_S, "we_n", 1),
+ return [
+ ("address", a, DIR_M_TO_S),
+ ("bank", ba, DIR_M_TO_S),
+ ("cas_n", 1, DIR_M_TO_S),
+ ("cke", 1, DIR_M_TO_S),
+ ("cs_n", 1, DIR_M_TO_S),
+ ("ras_n", 1, DIR_M_TO_S),
+ ("we_n", 1, DIR_M_TO_S),
- (M_TO_S, "wrdata", d),
- (M_TO_S, "wrdata_en", 1),
- (M_TO_S, "wrdata_mask", d//8),
+ ("wrdata", d, DIR_M_TO_S),
+ ("wrdata_en", 1, DIR_M_TO_S),
+ ("wrdata_mask", d//8, DIR_M_TO_S),
- (M_TO_S, "rddata_en", 1),
- (S_TO_M, "rddata", d),
- (S_TO_M, "rddata_valid", 1)
- )
+ ("rddata_en", 1, DIR_M_TO_S),
+ ("rddata", d, DIR_S_TO_M),
+ ("rddata_valid", 1, DIR_S_TO_M)
+ ]
-class Interface:
+class Interface(Record):
def __init__(self, a, ba, d, nphases=1):
- self.pdesc = phase_description(a, ba, d)
- self.phases = [SimpleInterface(self.pdesc) for i in range(nphases)]
+ layout = [("p"+str(i), phase_description(a, ba, d)) for i in range(nphases)]
+ Record.__init__(self, layout)
+ self.phases = [getattr(self, "p"+str(i)) for i in range(nphases)]
for p in self.phases:
p.cas_n.reset = 1
p.cs_n.reset = 1
r = []
add_suffix = len(self.phases) > 1
for n, phase in enumerate(self.phases):
- for signal in self.pdesc.desc:
- if (m2s and signal[0] == M_TO_S) or (s2m and signal[0] == S_TO_M):
+ for field, size, direction in phase.layout:
+ if (m2s and direction == DIR_M_TO_S) or (s2m and direction == DIR_S_TO_M):
if add_suffix:
- if signal[0] == M_TO_S:
+ if direction == DIR_M_TO_S:
suffix = "_p" + str(n)
else:
suffix = "_w" + str(n)
else:
suffix = ""
- r.append(("dfi_" + signal[1] + suffix, getattr(phase, signal[1])))
+ r.append(("dfi_" + field + suffix, getattr(phase, field)))
return r
-def interconnect_stmts(master, slave):
- r = []
- for pm, ps in zip(master.phases, slave.phases):
- r += simple_interconnect_stmts(master.pdesc, pm, [ps])
- return r
-
-class Interconnect:
+class Interconnect(Module):
def __init__(self, master, slave):
- self.master = master
- self.slave = slave
-
- def get_fragment(self):
- return Fragment(interconnect_stmts(self.master, self.slave))
+ self.comb += master.connect(slave)
+++ /dev/null
-from migen.fhdl.structure import *
-from migen.genlib.misc import optree
-
-(S_TO_M, M_TO_S) = range(2)
-
-# desc is a list of tuples, each made up of:
-# 0) S_TO_M/M_TO_S: data direction
-# 1) string: name
-# 2) int: width
-
-class Description:
- def __init__(self, *desc):
- self.desc = desc
-
- def get_names(self, direction, *exclude_list):
- exclude = set(exclude_list)
- return [signal[1]
- for signal in self.desc
- if signal[0] == direction and signal[1] not in exclude]
-
-class SimpleInterface:
- def __init__(self, desc):
- self.desc = desc
- modules = self.__module__.split(".")
- busname = modules[len(modules)-1]
- for signal in self.desc.desc:
- signame = signal[1]
- setattr(self, signame, Signal(signal[2], busname + "_" + signame))
-
-def simple_interconnect_stmts(desc, master, slaves):
- s2m = desc.get_names(S_TO_M)
- m2s = desc.get_names(M_TO_S)
- sl = [getattr(slave, name).eq(getattr(master, name))
- for name in m2s for slave in slaves]
- sl += [getattr(master, name).eq(
- optree("|", [getattr(slave, name) for slave in slaves])
- )
- for name in s2m]
- return sl
-
-class SimpleInterconnect:
- def __init__(self, master, slaves):
- self.master = master
- self.slaves = slaves
-
- def get_fragment(self):
- return Fragment(simple_interconnect_stmts(self.master.desc, self.master, self.slaves))
from migen.fhdl.specials import Memory
from migen.fhdl.module import Module
from migen.genlib import roundrobin
+from migen.genlib.record import *
from migen.genlib.misc import optree
-from migen.bus.simple import *
from migen.bus.transactions import *
from migen.sim.generic import Proxy
-_desc = Description(
- (M_TO_S, "adr", 30),
- (M_TO_S, "dat_w", 32),
- (S_TO_M, "dat_r", 32),
- (M_TO_S, "sel", 4),
- (M_TO_S, "cyc", 1),
- (M_TO_S, "stb", 1),
- (S_TO_M, "ack", 1),
- (M_TO_S, "we", 1),
- (M_TO_S, "cti", 3),
- (M_TO_S, "bte", 2),
- (S_TO_M, "err", 1)
-)
+_layout = [
+ ("adr", 30, DIR_M_TO_S),
+ ("dat_w", 32, DIR_M_TO_S),
+ ("dat_r", 32, DIR_S_TO_M),
+ ("sel", 4, DIR_M_TO_S),
+ ("cyc", 1, DIR_M_TO_S),
+ ("stb", 1, DIR_M_TO_S),
+ ("ack", 1, DIR_S_TO_M),
+ ("we", 1, DIR_M_TO_S),
+ ("cti", 3, DIR_M_TO_S),
+ ("bte", 2, DIR_M_TO_S),
+ ("err", 1, DIR_S_TO_M)
+]
-class Interface(SimpleInterface):
+class Interface(Record):
def __init__(self):
- SimpleInterface.__init__(self, _desc)
+ Record.__init__(self, _layout)
-class InterconnectPointToPoint(SimpleInterconnect):
+class InterconnectPointToPoint(Module):
def __init__(self, master, slave):
- SimpleInterconnect.__init__(self, master, [slave])
+ self.comb += master.connect(slave)
-class Arbiter:
+class Arbiter(Module):
def __init__(self, masters, target):
- self.masters = masters
- self.target = target
- self.rr = roundrobin.RoundRobin(len(self.masters))
-
- def get_fragment(self):
- comb = []
+ self.submodules.rr = roundrobin.RoundRobin(len(masters))
# mux master->slave signals
- for name in _desc.get_names(M_TO_S):
- choices = Array(getattr(m, name) for m in self.masters)
- comb.append(getattr(self.target, name).eq(choices[self.rr.grant]))
+ for name, size, direction in _layout:
+ if direction == DIR_M_TO_S:
+ choices = Array(getattr(m, name) for m in masters)
+ self.comb += getattr(target, name).eq(choices[self.rr.grant])
# connect slave->master signals
- for name in _desc.get_names(S_TO_M):
- source = getattr(self.target, name)
- for i, m in enumerate(self.masters):
- dest = getattr(m, name)
- if name == "ack" or name == "err":
- comb.append(dest.eq(source & (self.rr.grant == i)))
- else:
- comb.append(dest.eq(source))
+ for name, size, direction in _layout:
+ if direction == DIR_S_TO_M:
+ source = getattr(target, name)
+ for i, m in enumerate(masters):
+ dest = getattr(m, name)
+ if name == "ack" or name == "err":
+ self.comb += dest.eq(source & (self.rr.grant == i))
+ else:
+ self.comb += dest.eq(source)
# connect bus requests to round-robin selector
- reqs = [m.cyc for m in self.masters]
- comb.append(self.rr.request.eq(Cat(*reqs)))
-
- return Fragment(comb) + self.rr.get_fragment()
+ reqs = [m.cyc for m in masters]
+ self.comb += self.rr.request.eq(Cat(*reqs))
-class Decoder:
+class Decoder(Module):
# slaves is a list of pairs:
# 0) function that takes the address signal and returns a FHDL expression
# that evaluates to 1 when the slave is selected and 0 otherwise.
# register adds flip-flops after the address comparators. Improves timing,
# but breaks Wishbone combinatorial feedback.
def __init__(self, master, slaves, register=False):
- self.master = master
- self.slaves = slaves
- self.register = register
-
- def get_fragment(self):
- comb = []
- sync = []
-
- ns = len(self.slaves)
+ ns = len(slaves)
slave_sel = Signal(ns)
slave_sel_r = Signal(ns)
# decode slave addresses
- comb += [slave_sel[i].eq(fun(self.master.adr))
- for i, (fun, bus) in enumerate(self.slaves)]
- if self.register:
- sync.append(slave_sel_r.eq(slave_sel))
+ self.comb += [slave_sel[i].eq(fun(master.adr))
+ for i, (fun, bus) in enumerate(slaves)]
+ if register:
+ self.sync += slave_sel_r.eq(slave_sel)
else:
- comb.append(slave_sel_r.eq(slave_sel))
+ self.comb += slave_sel_r.eq(slave_sel)
# connect master->slaves signals except cyc
- m2s_names = _desc.get_names(M_TO_S, "cyc")
- comb += [getattr(slave[1], name).eq(getattr(self.master, name))
- for name in m2s_names for slave in self.slaves]
+ for slave in slaves:
+ for name, size, direction in _layout:
+ if direction == DIR_M_TO_S and name != "cyc":
+ self.comb += getattr(slave[1], name).eq(getattr(master, name))
# combine cyc with slave selection signals
- comb += [slave[1].cyc.eq(self.master.cyc & slave_sel[i])
- for i, slave in enumerate(self.slaves)]
+ self.comb += [slave[1].cyc.eq(master.cyc & slave_sel[i])
+ for i, slave in enumerate(slaves)]
# generate master ack (resp. err) by ORing all slave acks (resp. errs)
- comb += [
- self.master.ack.eq(optree("|", [slave[1].ack for slave in self.slaves])),
- self.master.err.eq(optree("|", [slave[1].err for slave in self.slaves]))
+ self.comb += [
+ master.ack.eq(optree("|", [slave[1].ack for slave in slaves])),
+ master.err.eq(optree("|", [slave[1].err for slave in slaves]))
]
# mux (1-hot) slave data return
- masked = [Replicate(slave_sel_r[i], len(self.master.dat_r)) & self.slaves[i][1].dat_r for i in range(len(self.slaves))]
- comb.append(self.master.dat_r.eq(optree("|", masked)))
-
- return Fragment(comb, sync)
+ masked = [Replicate(slave_sel_r[i], len(master.dat_r)) & slaves[i][1].dat_r for i in range(ns)]
+ self.comb += master.dat_r.eq(optree("|", masked))
-class InterconnectShared:
+class InterconnectShared(Module):
def __init__(self, masters, slaves, register=False):
- self._shared = Interface()
- self._arbiter = Arbiter(masters, self._shared)
- self._decoder = Decoder(self._shared, slaves, register)
-
- def get_fragment(self):
- return self._arbiter.get_fragment() + self._decoder.get_fragment()
+ shared = Interface()
+ self.submodules += Arbiter(masters, shared)
+ self.submodules += Decoder(shared, slaves, register)
class Tap(Module):
def __init__(self, bus, handler=print):
else:
bus.ack = 0
-class SRAM:
+class SRAM(Module):
def __init__(self, mem_or_size, bus=None):
if isinstance(mem_or_size, Memory):
assert(mem_or_size.width <= 32)
- self.mem = mem_or_size
+ mem = mem_or_size
else:
- self.mem = Memory(32, mem_or_size//4)
+ mem = Memory(32, mem_or_size//4)
if bus is None:
bus = Interface()
self.bus = bus
- def get_fragment(self):
+ ###
+
# memory
- port = self.mem.get_port(write_capable=True, we_granularity=8)
+ self.specials += mem
+ port = mem.get_port(write_capable=True, we_granularity=8)
# generate write enable signal
- comb = [port.we[i].eq(self.bus.cyc & self.bus.stb & self.bus.we & self.bus.sel[i])
+ self.comb += [port.we[i].eq(self.bus.cyc & self.bus.stb & self.bus.we & self.bus.sel[i])
for i in range(4)]
# address and data
- comb += [
+ self.comb += [
port.adr.eq(self.bus.adr[:len(port.adr)]),
port.dat_w.eq(self.bus.dat_w),
self.bus.dat_r.eq(port.dat_r)
]
# generate ack
- sync = [
+ self.sync += [
self.bus.ack.eq(0),
- If(self.bus.cyc & self.bus.stb & ~self.bus.ack,
- self.bus.ack.eq(1)
- )
+ If(self.bus.cyc & self.bus.stb & ~self.bus.ack, self.bus.ack.eq(1))
]
- return Fragment(comb, sync, specials={self.mem})
from migen.bus import wishbone
from migen.genlib.fsm import FSM
from migen.genlib.misc import split, displacer, chooser
-from migen.genlib.record import Record
+from migen.genlib.record import Record, layout_len
# cachesize (in 32-bit words) is the size of the data store, must be a power of 2
class WB2ASMI:
]
# Tag memory
- tag_mem = Memory(tagbits+1, 2**linebits)
- tag_port = tag_mem.get_port(write_capable=True)
-
tag_layout = [("tag", tagbits), ("dirty", 1)]
+ tag_mem = Memory(layout_len(tag_layout), 2**linebits)
+ tag_port = tag_mem.get_port(write_capable=True)
tag_do = Record(tag_layout)
tag_di = Record(tag_layout)
comb += [
- Cat(*tag_do.flatten()).eq(tag_port.dat_r),
- tag_port.dat_w.eq(Cat(*tag_di.flatten()))
+ tag_do.raw_bits().eq(tag_port.dat_r),
+ tag_port.dat_w.eq(tag_di.raw_bits())
]
comb += [