Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a1f7ecc8c56b
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c0bc94ca1c54
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Jun 17, 2015

  1. Copy the full SHA
    3b9f287 View commit details
  2. Copy the full SHA
    c0bc94c View commit details
Showing with 71 additions and 161 deletions.
  1. +2 −2 misoclib/mem/sdram/core/minicon/__init__.py
  2. +31 −150 misoclib/mem/sdram/frontend/wishbone2lasmi.py
  3. +36 −7 misoclib/soc/sdram.py
  4. +2 −2 software/libbase/system.c
4 changes: 2 additions & 2 deletions misoclib/mem/sdram/core/minicon/__init__.py
Original file line number Diff line number Diff line change
@@ -58,8 +58,8 @@ def __init__(self, geom_settings):


class MiniconSettings:
def __init__(self):
pass
def __init__(self, l2_size=0):
self.l2_size = l2_size


class Minicon(Module):
181 changes: 31 additions & 150 deletions misoclib/mem/sdram/frontend/wishbone2lasmi.py
Original file line number Diff line number Diff line change
@@ -1,168 +1,49 @@
from migen.fhdl.std import *
from migen.bus import wishbone
from migen.bank.description import *
from migen.genlib.fsm import FSM, NextState
from migen.genlib.misc import split, displacer, chooser
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 WB2LASMI(Module, AutoCSR):
def __init__(self, cachesize, lasmim):
self._cachesize = CSRStatus(8, reset=log2_int(cachesize))
self.wishbone = wishbone.Interface()
class WB2LASMI(Module):
def __init__(self, wishbone, lasmim):

###

data_width = flen(self.wishbone.dat_r)
if lasmim.dw > data_width and (lasmim.dw % data_width) != 0:
raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width))
if lasmim.dw < data_width and (data_width % lasmim.dw) != 0:
raise ValueError("WISHBONE data width must be a multiple of {dw}".format(dw=lasmim.dw))

# Split address:
# TAG | LINE NUMBER | LINE OFFSET
offsetbits = log2_int(max(lasmim.dw//data_width, 1))
addressbits = lasmim.aw + offsetbits
linebits = log2_int(cachesize) - offsetbits
tagbits = addressbits - linebits
wordbits = log2_int(max(data_width//lasmim.dw, 1))
adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
word = Signal(wordbits) if wordbits else None

# Data memory
data_mem = Memory(lasmim.dw*2**wordbits, 2**linebits)
data_port = data_mem.get_port(write_capable=True, we_granularity=8)
self.specials += data_mem, data_port

write_from_lasmi = Signal()
write_to_lasmi = Signal()
if adr_offset is None:
adr_offset_r = None
else:
adr_offset_r = Signal(offsetbits)
self.sync += adr_offset_r.eq(adr_offset)

self.comb += [
data_port.adr.eq(adr_line),
If(write_from_lasmi,
displacer(lasmim.dat_r, word, data_port.dat_w),
displacer(Replicate(1, lasmim.dw//8), word, data_port.we)
).Else(
data_port.dat_w.eq(Replicate(self.wishbone.dat_w, max(lasmim.dw//data_width, 1))),
If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
)
),
If(write_to_lasmi,
chooser(data_port.dat_r, word, lasmim.dat_w),
lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
),
chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
]


# Tag memory
tag_layout = [("tag", tagbits), ("dirty", 1)]
tag_mem = Memory(layout_len(tag_layout), 2**linebits)
tag_port = tag_mem.get_port(write_capable=True)
self.specials += tag_mem, tag_port
tag_do = Record(tag_layout)
tag_di = Record(tag_layout)
self.comb += [
tag_do.raw_bits().eq(tag_port.dat_r),
tag_port.dat_w.eq(tag_di.raw_bits())
]

self.comb += [
tag_port.adr.eq(adr_line),
tag_di.tag.eq(adr_tag)
]
if word is not None:
self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag))
else:
self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))

# Lasmim word computation, word_clr and word_inc will be simplified
# at synthesis when wordbits=0
word_clr = Signal()
word_inc = Signal()
if word is not None:
self.sync += \
If(word_clr,
word.eq(0),
).Elif(word_inc,
word.eq(word+1)
)

def word_is_last(word):
if word is not None:
return word == 2**wordbits-1
else:
return 1

# Control FSM
assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
fsm = FSM(reset_state="IDLE")
self.submodules += fsm


self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
)
fsm.act("TEST_HIT",
word_clr.eq(1),
If(tag_do.tag == adr_tag,
self.wishbone.ack.eq(1),
If(self.wishbone.we,
tag_di.dirty.eq(1),
tag_port.we.eq(1)
),
NextState("IDLE")
).Else(
If(tag_do.dirty,
NextState("EVICT_REQUEST")
).Else(
NextState("REFILL_WRTAG")
)
If(wishbone.cyc & wishbone.stb,
NextState("REQUEST")
)
)

fsm.act("EVICT_REQUEST",
fsm.act("REQUEST",
lasmim.stb.eq(1),
lasmim.we.eq(1),
If(lasmim.req_ack, NextState("EVICT_DATA"))
)
fsm.act("EVICT_DATA",
If(lasmim.dat_w_ack,
write_to_lasmi.eq(1),
word_inc.eq(1),
If(word_is_last(word),
NextState("REFILL_WRTAG"),
lasmim.we.eq(wishbone.we),
If(lasmim.req_ack,
If(wishbone.we,
NextState("WRITE_DATA")
).Else(
NextState("EVICT_REQUEST")
NextState("READ_DATA")
)
)
)

fsm.act("REFILL_WRTAG",
# Write the tag first to set the LASMI address
tag_port.we.eq(1),
word_clr.eq(1),
NextState("REFILL_REQUEST")
)
fsm.act("REFILL_REQUEST",
lasmim.stb.eq(1),
If(lasmim.req_ack, NextState("REFILL_DATA"))
fsm.act("WRITE_DATA",
If(lasmim.dat_w_ack,
lasmim.dat_we.eq(wishbone.sel),
wishbone.ack.eq(1),
NextState("IDLE")
)
)
fsm.act("REFILL_DATA",
fsm.act("READ_DATA",
If(lasmim.dat_r_ack,
write_from_lasmi.eq(1),
word_inc.eq(1),
If(word_is_last(word),
NextState("TEST_HIT"),
).Else(
NextState("REFILL_REQUEST")
)
)
wishbone.ack.eq(1),
NextState("IDLE")
),
NextState("IDLE")
)

# Address / Datapath
self.comb += [
lasmim.adr.eq(wishbone.adr),
If(lasmim.dat_w_ack,
lasmim.dat_w.eq(wishbone.dat_w),
),
wishbone.dat_r.eq(lasmim.dat_r)
]
43 changes: 36 additions & 7 deletions misoclib/soc/sdram.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
class SDRAMSoC(SoC):
csr_map = {
"sdram": 8,
"wishbone2lasmi": 9,
"l2_cache": 9,
"memtest_w": 10,
"memtest_r": 11
}
@@ -26,6 +26,13 @@ def __init__(self, platform, clk_freq, sdram_controller_settings,
else:
self.sdram_controller_settings = sdram_controller_settings
self._sdram_phy_registered = False
self._wb_sdram_ifs = []
self._wb_sdram = wishbone.Interface()

def add_wb_sdram_if(self, interface):
if self.finalized:
raise FinalizeError
self._wb_sdram_ifs.append(interface)

def register_sdram_phy(self, phy):
if self._sdram_phy_registered:
@@ -45,6 +52,12 @@ def register_sdram_phy(self, phy):
phy.module.geom_settings.colbits)*sdram_width//8
# XXX: Limit main_ram_size to 256MB, we should modify mem_map to allow larger memories.
main_ram_size = min(main_ram_size, 256*1024*1024)
l2_size = self.sdram_controller_settings.l2_size

# add a wishbone interface to the DRAM
wb_sdram = wishbone.Interface()
self.add_wb_sdram_if(wb_sdram)
self.register_mem("main_ram", self.mem_map["main_ram"], wb_sdram, main_ram_size)

# LASMICON frontend
if isinstance(self.sdram_controller_settings, LASMIconSettings):
@@ -55,26 +68,42 @@ def register_sdram_phy(self, phy):
self.submodules.memtest_w = memtest.MemtestWriter(self.sdram.crossbar.get_master())
self.submodules.memtest_r = memtest.MemtestReader(self.sdram.crossbar.get_master())

l2_size = self.sdram_controller_settings.l2_size
if l2_size:
lasmim = self.sdram.crossbar.get_master()
l2_cache = wishbone.Cache(l2_size//4, self._wb_sdram, wishbone.Interface(lasmim.dw))
# XXX Vivado ->2015.1 workaround, Vivado is not able to map correctly our L2 cache.
# Issue is reported to Xilinx and should be fixed in next releases (2015.2?).
# Remove this workaround when fixed by Xilinx.
from mibuild.xilinx.vivado import XilinxVivadoToolchain
if isinstance(self.platform.toolchain, XilinxVivadoToolchain):
from migen.fhdl.simplify import FullMemoryWE
self.submodules.wishbone2lasmi = FullMemoryWE()(wishbone2lasmi.WB2LASMI(l2_size//4, self.sdram.crossbar.get_master()))
self.submodules.l2_cache = FullMemoryWE()(l2_cache)
else:
self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(l2_size//4, self.sdram.crossbar.get_master())
self.register_mem("main_ram", self.mem_map["main_ram"], self.wishbone2lasmi.wishbone, main_ram_size)
self.submodules.l2_cache = l2_cache
self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(self.l2_cache.slave, lasmim)

# MINICON frontend
elif isinstance(self.sdram_controller_settings, MiniconSettings):
self.submodules.converter = wishbone.Converter(wishbone.Interface(), self.sdram.controller.bus)
self.register_mem("main_ram", self.mem_map["main_ram"], self.converter.master, main_ram_size)
if l2_size:
l2_cache = wishbone.Cache(l2_size//4, self._wb_sdram, self.sdram.controller.bus)
# XXX Vivado ->2015.1 workaround, Vivado is not able to map correctly our L2 cache.
# Issue is reported to Xilinx and should be fixed in next releases (2015.2?).
# Remove this workaround when fixed by Xilinx.
from mibuild.xilinx.vivado import XilinxVivadoToolchain
if isinstance(self.platform.toolchain, XilinxVivadoToolchain):
from migen.fhdl.simplify import FullMemoryWE
self.submodules.l2_cache = FullMemoryWE()(l2_cache)
else:
self.submodules.l2_cache = l2_cache
else:
self.submodules.converter = wishbone.Converter(self._wb_sdram, self.sdram.controller.bus)

def do_finalize(self):
if not self.integrated_main_ram_size:
if not self._sdram_phy_registered:
raise FinalizeError("Need to call SDRAMSoC.register_sdram_phy()")

# arbitrate wishbone interfaces to the DRAM
self.submodules.wb_sdram_con = wishbone.Arbiter(self._wb_sdram_ifs,
self._wb_sdram)
SoC.do_finalize(self)
4 changes: 2 additions & 2 deletions software/libbase/system.c
Original file line number Diff line number Diff line change
@@ -67,15 +67,15 @@ void flush_cpu_dcache(void)
#endif
}

#ifdef CSR_WISHBONE2LASMI_BASE
#ifdef CSR_L2_CACHE_BASE
void flush_l2_cache(void)
{
unsigned int l2_nwords;
unsigned int i;
register unsigned int addr;
register unsigned int dummy;

l2_nwords = 1 << wishbone2lasmi_cachesize_read();
l2_nwords = 1 << l2_cache_size_read();
for(i=0;i<2*l2_nwords;i++) {
addr = MAIN_RAM_BASE + i*4;
#if defined (__lm32__)