from soc.minerva.cache import L1Cache
from soc.minerva.wishbone import make_wb_layout, WishboneArbiter, Cycle
+from soc.bus.wb_downconvert import WishboneDownConvert
+from copy import deepcopy
__all__ = ["LoadStoreUnitInterface", "BareLoadStoreUnit",
"CachedLoadStoreUnit"]
class LoadStoreUnitInterface:
def __init__(self, pspec):
self.pspec = pspec
- self.dbus = Record(make_wb_layout(pspec))
- print (self.dbus.sel.shape())
+ self.pspecslave = pspec
+ if (hasattr(pspec, "dmem_test_depth") and
+ isinstance(pspec.wb_data_wid, int) and
+ pspec.wb_data_wid != pspec.reg_wid):
+ self.dbus = Record(make_wb_layout(pspec), name="int_dbus")
+ pspecslave = deepcopy(pspec)
+ pspecslave.reg_wid = pspec.wb_data_wid
+ mask_ratio = (pspec.reg_wid // pspec.wb_data_wid)
+ pspecslave.mask_wid = pspec.mask_wid // mask_ratio
+ self.pspecslave = pspecslave
+ self.slavebus = Record(make_wb_layout(pspecslave), name="dbus")
+ self.needs_cvt = True
+ else:
+ self.needs_cvt = False
+ self.dbus = self.slavebus = Record(make_wb_layout(pspec))
+
+ # detect whether the wishbone bus is enabled / disabled
+ if (hasattr(pspec, "wb_dcache_en") and
+ isinstance(pspec.wb_dcache_en, Signal)):
+ self.jtag_en = pspec.wb_dcache_en
+ else:
+ self.jtag_en = Const(1, 1) # permanently on
+
+ print(self.dbus.sel.shape())
self.mask_wid = mask_wid = pspec.mask_wid
self.addr_wid = addr_wid = pspec.addr_wid
self.data_wid = data_wid = pspec.reg_wid
- print ("loadstoreunit addr mask data", addr_wid, mask_wid, data_wid)
- self.adr_lsbs = log2_int(mask_wid) # LSBs of addr covered by mask
+ print("loadstoreunit addr mask data", addr_wid, mask_wid, data_wid)
+ self.adr_lsbs = log2_int(mask_wid) # LSBs of addr covered by mask
badwid = addr_wid-self.adr_lsbs # TODO: is this correct?
# INPUTS
self.x_mask_i = Signal(mask_wid) # Mask of which bytes to write
self.x_ld_i = Signal() # set to do a memory load
self.x_st_i = Signal() # set to do a memory store
- self.x_st_data_i = Signal(data_wid) # The data to write when storing
+ self.x_st_data_i = Signal(data_wid) # The data to write when storing
self.x_stall_i = Signal() # do nothing until low
self.x_valid_i = Signal() # Whether x pipeline stage is
- # currently enabled (I
- # think?). Set to 1 for #now
+ # currently enabled (I
+ # think?). Set to 1 for #now
self.m_stall_i = Signal() # do nothing until low
self.m_valid_i = Signal() # Whether m pipeline stage is
- # currently enabled. Set
- # to 1 for now
+ # currently enabled. Set
+ # to 1 for now
# OUTPUTS
self.x_busy_o = Signal() # set when the memory is busy
self.m_busy_o = Signal() # set when the memory is busy
- self.m_ld_data_o = Signal(data_wid) # Data returned from memory read
+ self.m_ld_data_o = Signal(data_wid) # Data returned from memory read
# Data validity is NOT indicated by m_valid_i or x_valid_i as
# those are inputs. I believe it is valid on the next cycle
# after raising m_load where busy is low
self.m_load_err_o = Signal() # if there was an error when loading
self.m_store_err_o = Signal() # if there was an error when storing
- self.m_badaddr_o = Signal(badwid) # The address of the load/store error
+ # The address of the load/store error
+ self.m_badaddr_o = Signal(badwid)
def __iter__(self):
yield self.x_addr_i
yield self.m_load_err_o
yield self.m_store_err_o
yield self.m_badaddr_o
- for sig in self.dbus.fields.values():
+ for sig in self.slavebus.fields.values():
yield sig
def ports(self):
def elaborate(self, platform):
m = Module()
- with m.If(self.dbus.cyc):
- with m.If(self.dbus.ack | self.dbus.err | ~self.m_valid_i):
+ if self.needs_cvt:
+ self.cvt = WishboneDownConvert(self.dbus, self.slavebus)
+ m.submodules.cvt = self.cvt
+
+ with m.If(self.jtag_en): # for safety, JTAG can completely disable WB
+
+ with m.If(self.dbus.cyc):
+ with m.If(self.dbus.ack | self.dbus.err | ~self.m_valid_i):
+ m.d.sync += [
+ self.dbus.cyc.eq(0),
+ self.dbus.stb.eq(0),
+ self.dbus.sel.eq(0),
+ self.m_ld_data_o.eq(self.dbus.dat_r)
+ ]
+ with m.Elif((self.x_ld_i | self.x_st_i) &
+ self.x_valid_i & ~self.x_stall_i):
m.d.sync += [
- self.dbus.cyc.eq(0),
- self.dbus.stb.eq(0),
- self.m_ld_data_o.eq(self.dbus.dat_r)
+ self.dbus.cyc.eq(1),
+ self.dbus.stb.eq(1),
+ self.dbus.adr.eq(self.x_addr_i[self.adr_lsbs:]),
+ self.dbus.sel.eq(self.x_mask_i),
+ self.dbus.we.eq(self.x_st_i),
+ self.dbus.dat_w.eq(self.x_st_data_i)
+ ]
+ with m.Else():
+ m.d.sync += [
+ self.dbus.adr.eq(0),
+ self.dbus.sel.eq(0),
+ self.dbus.we.eq(0),
+ self.dbus.sel.eq(0),
+ self.dbus.dat_w.eq(0),
]
- with m.Elif((self.x_ld_i | self.x_st_i) &
- self.x_valid_i & ~self.x_stall_i):
- m.d.sync += [
- self.dbus.cyc.eq(1),
- self.dbus.stb.eq(1),
- self.dbus.adr.eq(self.x_addr_i[self.adr_lsbs:]),
- self.dbus.sel.eq(self.x_mask_i),
- self.dbus.we.eq(self.x_st_i),
- self.dbus.dat_w.eq(self.x_st_data_i)
- ]
- with m.Else():
- m.d.sync += [
- self.dbus.adr.eq(0),
- self.dbus.sel.eq(0),
- self.dbus.we.eq(0),
- self.dbus.sel.eq(0),
- self.dbus.dat_w.eq(0),
- ]
- with m.If(self.dbus.cyc & self.dbus.err):
- m.d.sync += [
- self.m_load_err_o.eq(~self.dbus.we),
- self.m_store_err_o.eq(self.dbus.we),
- self.m_badaddr_o.eq(self.dbus.adr)
- ]
- with m.Elif(~self.m_stall_i):
- m.d.sync += [
- self.m_load_err_o.eq(0),
- self.m_store_err_o.eq(0)
- ]
+ with m.If(self.dbus.cyc & self.dbus.err):
+ m.d.sync += [
+ self.m_load_err_o.eq(~self.dbus.we),
+ self.m_store_err_o.eq(self.dbus.we),
+ self.m_badaddr_o.eq(self.dbus.adr)
+ ]
+ with m.Elif(~self.m_stall_i):
+ m.d.sync += [
+ self.m_load_err_o.eq(0),
+ self.m_store_err_o.eq(0)
+ ]
- m.d.comb += self.x_busy_o.eq(self.dbus.cyc)
+ m.d.comb += self.x_busy_o.eq(self.dbus.cyc)
- with m.If(self.m_load_err_o | self.m_store_err_o):
- m.d.comb += self.m_busy_o.eq(0)
- with m.Else():
- m.d.comb += self.m_busy_o.eq(self.dbus.cyc)
+ with m.If(self.m_load_err_o | self.m_store_err_o):
+ m.d.comb += self.m_busy_o.eq(0)
+ with m.Else():
+ m.d.comb += self.m_busy_o.eq(self.dbus.cyc)
return m
const_bits = 30 - range_bits
return "{}{}".format("0" * const_bits, "-" * range_bits)
- if dcache.base >= (1<<self.adr_lsbs):
+ if dcache.base >= (1 << self.adr_lsbs):
with m.Case(addr_below(dcache.base >> self.adr_lsbs)):
m.d.comb += x_dcache_select.eq(0)
with m.Case(addr_below(dcache.limit >> self.adr_lsbs)):