ba = settings.geom.bankbits + log2_int(nranks)
self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba))
+ self._address_align = address_align
+ self._n = n
+
def elaborate(self, platform):
m = Module()
cmd_buffer = stream.Buffer(cmd_buffer_layout) # 1 depth buffer to detect row change
m.submodules += cmd_buffer_lookahead, cmd_buffer
m.d.comb += [
- self.req.connect(cmd_buffer_lookahead.sink, include={"valid", "ready", "we", "addr"}),
+ #self.req.connect(cmd_buffer_lookahead.sink, include={"valid", "ready", "payload.we", "payload.addr"}),
+ cmd_buffer_lookahead.sink.valid.eq(self.req.valid),
+ cmd_buffer_lookahead.sink.ready.eq(self.req.ready),
+ cmd_buffer_lookahead.sink.payload.we.eq(self.req.we),
+ cmd_buffer_lookahead.sink.payload.addr.eq(self.req.addr),
+
cmd_buffer_lookahead.source.connect(cmd_buffer.sink),
cmd_buffer.source.ready.eq(self.req.wdata_ready | self.req.rdata_valid),
self.req.lock.eq(cmd_buffer_lookahead.source.valid | cmd_buffer.source.valid),
]
- slicer = _AddressSlicer(self.settings.geom.colbits, address_align)
+ slicer = _AddressSlicer(self.settings.geom.colbits, self._address_align)
# Row tracking -----------------------------------------------------------------------------
row = Signal(self.settings.geom.rowbits)
# Address generation -----------------------------------------------------------------------
row_col_n_addr_sel = Signal()
- m.d.comb += cmd.ba.eq(n)
+ m.d.comb += self.cmd.ba.eq(self._n)
with m.If(row_col_n_addr_sel):
- m.d.comb += cmd.a.eq(slicer.row(cmd_buffer.source.addr))
+ m.d.comb += self.cmd.a.eq(slicer.row(cmd_buffer.source.addr))
with m.Else():
- m.d.comb += cmd.a.eq((auto_precharge << 10) | slicer.col(cmd_buffer.source.addr))
+ m.d.comb += self.cmd.a.eq((auto_precharge << 10) | slicer.col(cmd_buffer.source.addr))
# tWTP (write-to-precharge) controller -----------------------------------------------------
write_latency = math.ceil(self.settings.phy.cwl / self.settings.phy.nphases)
precharge_time = write_latency + self.settings.timing.tWR + self.settings.timing.tCCD # AL=0
m.submodules.twtpcon = twtpcon = tXXDController(precharge_time)
- m.d.comb += twtpcon.valid.eq(cmd.valid & cmd.ready & cmd.is_write)
+ m.d.comb += twtpcon.valid.eq(self.cmd.valid & self.cmd.ready & self.cmd.is_write)
# tRC (activate-activate) controller -------------------------------------------------------
m.submodules.trccon = trccon = tXXDController(self.settings.timing.tRC)
- m.d.comb += trccon.valid.eq(cmd.valid & cmd.ready & row_open)
+ m.d.comb += trccon.valid.eq(self.cmd.valid & self.cmd.ready & row_open)
# tRAS (activate-precharge) controller -----------------------------------------------------
m.submodules.trascon = trascon = tXXDController(self.settings.timing.tRAS)
- m.d.comb += trascon.valid.eq(cmd.valid & cmd.ready & row_open)
+ m.d.comb += trascon.valid.eq(self.cmd.valid & self.cmd.ready & row_open)
# Auto Precharge generation ----------------------------------------------------------------
# generate auto precharge when current and next cmds are to different rows
- if settings.with_auto_precharge:
+ if self.settings.with_auto_precharge:
with m.If(cmd_buffer_lookahead.source.valid & cmd_buffer.source.valid):
with m.If(slicer.row(cmd_buffer_lookahead.source.addr) != slicer.row(cmd_buffer.source.addr)):
m.d.comb += auto_precharge.eq(row_close == 0)
# Note: tRRD, tFAW, tCCD, tWTR timings are enforced by the multiplexer
with m.FSM():
with m.State("Regular"):
- with m.If(refresh_req):
+ with m.If(self.refresh_req):
m.next = "Refresh"
with m.Elif(cmd_buffer.source.valid):
with m.If(row_opened):
with m.If(row_hit):
m.d.comb += [
- cmd.valid.eq(1),
- cmd.cas.eq(1),
+ self.cmd.valid.eq(1),
+ self.cmd.cas.eq(1),
]
with m.If(cmd_buffer.source.we):
m.d.comb += [
- self.req.wdata_ready.eq(cmd.ready),
- cmd.is_write.eq(1),
- cmd.we.eq(1),
+ self.req.wdata_ready.eq(self.cmd.ready),
+ self.cmd.is_write.eq(1),
+ self.cmd.we.eq(1),
]
with m.Else():
m.d.comb += [
- self.req.rdata_valid.eq(cmd.ready),
- cmd.is_read.eq(1),
+ self.req.rdata_valid.eq(self.cmd.ready),
+ self.cmd.is_read.eq(1),
]
- with m.If(cmd.ready & auto_precharge):
+ with m.If(self.cmd.ready & auto_precharge):
m.next = "Autoprecharge"
with m.Else():
m.next = "Precharge"
with m.If(twtpcon.ready & trascon.ready):
m.d.comb += [
- cmd.valid.eq(1),
- cmd.ras.eq(1),
- cmd.we.eq(1),
- cmd.is_cmd.eq(1),
+ self.cmd.valid.eq(1),
+ self.cmd.ras.eq(1),
+ self.cmd.we.eq(1),
+ self.cmd.is_cmd.eq(1),
]
- with m.If(cmd.ready):
+ with m.If(self.cmd.ready):
m.next = "tRP"
with m.State("Autoprecharge"):
m.d.comb += [
row_col_n_addr_sel.eq(1),
row_open.eq(1),
- cmd.valid.eq(1),
- cmd.is_cmd.eq(1),
- cmd.ras.eq(1),
+ self.cmd.valid.eq(1),
+ self.cmd.is_cmd.eq(1),
+ self.cmd.ras.eq(1),
]
- with m.If(cmd.ready):
+ with m.If(self.cmd.ready):
m.next = "tRCD"
with m.State("Refresh"):
m.d.comb += [
row_close.eq(1),
- cmd.is_cmd.eq(1),
+ self.cmd.is_cmd.eq(1),
]
with m.If(twtpcon.ready):
- m.d.comb += refresh_gnt.eq(1)
- with m.If(~refresh_req):
+ m.d.comb += self.refresh_gnt.eq(1)
+ with m.If(~self.refresh_req):
m.next = "Regular"
delayed_enter(m, "tRP", "Activate", self.settings.timing.tRP - 1)
data_width = self.controller.data_width
# Crossbar port ----------------------------------------------------------------------------
- port = LiteDRAMNativePort(
+ port = gramNativePort(
mode = mode,
address_width = self.rca_bits + self.bank_bits - self.rank_bits,
data_width = self.controller.data_width,
# Clock domain crossing --------------------------------------------------------------------
if clock_domain != "sys":
- new_port = LiteDRAMNativePort(
+ new_port = gramNativePort(
mode = mode,
address_width = port.address_width,
data_width = port.data_width,
clock_domain = clock_domain,
id = port.id)
- self.submodules += LiteDRAMNativePortCDC(new_port, port)
+ self.submodules += gramNativePortCDC(new_port, port)
port = new_port
# Data width convertion --------------------------------------------------------------------
addr_shift = -log2_int(data_width//self.controller.data_width)
else:
addr_shift = log2_int(self.controller.data_width//data_width)
- new_port = LiteDRAMNativePort(
+ new_port = gramNativePort(
mode = mode,
address_width = port.address_width + addr_shift,
data_width = data_width,
# Address mapping --------------------------------------------------------------------------
cba_shifts = {"ROW_BANK_COL": controller.settings.geom.colbits - controller.address_align}
cba_shift = cba_shifts[controller.settings.address_mapping]
- m_ba = [m.get_bank_address(self.bank_bits, cba_shift)for m in self.masters]
- m_rca = [m.get_row_column_address(self.bank_bits, self.rca_bits, cba_shift) for m in self.masters]
+ m_ba = [master.get_bank_address(self.bank_bits, cba_shift) for master in self.masters]
+ m_rca = [master.get_row_column_address(self.bank_bits, self.rca_bits, cba_shift) for master in self.masters]
master_readys = [0]*nmasters
master_wdata_readys = [0]*nmasters
m.d.comb += master.rdata.valid.eq(master_rdata_valid)
# Route data writes ------------------------------------------------------------------------
- wdata_cases = {}
- for nm, master in enumerate(self.masters):
- wdata_cases[2**nm] = [
- controller.wdata.eq(master.wdata.data),
- controller.wdata_we.eq(master.wdata.we)
- ]
- wdata_cases["default"] = [
- controller.wdata.eq(0),
- controller.wdata_we.eq(0)
- ]
- m.d.comb += Case(Cat(*master_wdata_readys), wdata_cases)
+ with m.Switch(Cat(*master_wdata_readys)):
+ with m.Case():
+ m.d.comb += [
+ controller.wdata.eq(0),
+ controller.wdata_we.eq(0),
+ ]
+ for nm, master in enumerate(self.masters):
+ with m.Case(2**nm):
+ m.d.comb = [
+ controller.wdata.eq(master.wdata.data),
+ controller.wdata_we.eq(master.wdata.we),
+ ]
# Route data reads -------------------------------------------------------------------------
for master in self.masters:
# This file is Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
-from migen import *
+from nmigen import *
+from nmigen.compat import Case
-from litex.soc.interconnect import stream
-
-from litedram.common import *
+from gram.common import *
+import gram.stream as stream
# LiteDRAMNativePortCDC ----------------------------------------------------------------------------
-class LiteDRAMNativePortCDC(Module):
+class gramNativePortCDC(Elaboratable):
def __init__(self, port_from, port_to,
cmd_depth = 4,
wdata_depth = 16,
assert port_from.data_width == port_to.data_width
assert port_from.mode == port_to.mode
- address_width = port_from.address_width
- data_width = port_from.data_width
- mode = port_from.mode
- clock_domain_from = port_from.clock_domain
- clock_domain_to = port_to.clock_domain
+ self._port_from = port_from
+ self._port_to = port_to
+ self._cmd_depth = cmd_depth
+ self._wdata_depth = wdata_depth
+ self._rdata_depth = rdata_depth
+
+ def elaborate(self, platform):
+ m = Module()
- # # #
+ port_from = self._port_from
+ port_to = self._port_to
+ cmd_depth = self._cmd_depth
+ wdata_depth = self._wdata_depth
+ rdata_depth = self._rdata_depth
+
+ address_width = port_from.address_width
+ data_width = port_from.data_width
+ mode = port_from.mode
+ clock_domain_from = port_from.clock_domain
+ clock_domain_to = port_to.clock_domain
cmd_fifo = stream.AsyncFIFO(
[("we", 1), ("addr", address_width)], cmd_depth)
cmd_fifo = ClockDomainsRenamer(
{"write": clock_domain_from,
"read": clock_domain_to})(cmd_fifo)
- self.submodules += cmd_fifo
- self.submodules += stream.Pipeline(
+ m.submodules += cmd_fifo
+ m.submodules += stream.Pipeline(
port_from.cmd, cmd_fifo, port_to.cmd)
if mode == "write" or mode == "both":
wdata_fifo = ClockDomainsRenamer(
{"write": clock_domain_from,
"read": clock_domain_to})(wdata_fifo)
- self.submodules += wdata_fifo
- self.submodules += stream.Pipeline(
+ m.submodules += wdata_fifo
+ m.submodules += stream.Pipeline(
port_from.wdata, wdata_fifo, port_to.wdata)
if mode == "read" or mode == "both":
rdata_fifo = ClockDomainsRenamer(
{"write": clock_domain_to,
"read": clock_domain_from})(rdata_fifo)
- self.submodules += rdata_fifo
- self.submodules += stream.Pipeline(
+ m.submodules += rdata_fifo
+ m.submodules += stream.Pipeline(
port_to.rdata, rdata_fifo, port_from.rdata)
+ return m
+
# LiteDRAMNativePortDownConverter ------------------------------------------------------------------
-class LiteDRAMNativePortDownConverter(Module):
+class gramNativePortDownConverter(Elaboratable):
"""LiteDRAM port DownConverter
This module reduces user port data width to fit controller data width.
if port_from.data_width % port_to.data_width:
raise ValueError("Ratio must be an int")
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
+
+ def elaborate(self, platform):
+ m = Module()
+
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
ratio = port_from.data_width//port_to.data_width
mode = port_from.mode
counter = Signal(max=ratio)
counter_reset = Signal()
counter_ce = Signal()
- self.sync += \
- If(counter_reset,
- counter.eq(0)
- ).Elif(counter_ce,
- counter.eq(counter + 1)
- )
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- counter_reset.eq(1),
- If(port_from.cmd.valid,
- NextState("CONVERT")
- )
- )
- fsm.act("CONVERT",
- port_to.cmd.valid.eq(1),
- port_to.cmd.we.eq(port_from.cmd.we),
- port_to.cmd.addr.eq(port_from.cmd.addr*ratio + counter),
- If(port_to.cmd.ready,
- counter_ce.eq(1),
- If(counter == ratio - 1,
- port_from.cmd.ready.eq(1),
- NextState("IDLE")
- )
- )
- )
+ with m.If(counter_reset):
+ m.d.sync += counter.eq(0)
+ with m.Elif(counter_ce):
+ m.d.sync += counter.eq(counter+1)
+
+ with m.FSM():
+ with m.State("Idle"):
+ m.d.comb += counter_reset.eq(1)
+ with m.If(port_from.cmd.valid):
+ m.next = "Convert"
+
+ with m.State("Convert"):
+ m.d.comb += [
+ port_to.cmd.valid.eq(1),
+ port_to.cmd.we.eq(port_from.cmd.we),
+ port_to.cmd.addr.eq(port_from.cmd.addr*ratio + counter),
+ ]
+ with m.If(port_to.cmd.ready):
+ m.d.comb += counter_ce.eq(1)
+ with m.If(counter == ratio - 1):
+ m.d.comb += port_from.cmd.ready.eq(1)
+ m.next = "Idle"
if mode == "write" or mode == "both":
wdata_converter = stream.StrideConverter(
port_from.wdata.description,
port_to.wdata.description,
reverse=reverse)
- self.submodules += wdata_converter
- self.submodules += stream.Pipeline(
+ m.submodules += wdata_converter
+ m.submodules += stream.Pipeline(
port_from.wdata, wdata_converter, port_to.wdata)
if mode == "read" or mode == "both":
port_to.rdata.description,
port_from.rdata.description,
reverse=reverse)
- self.submodules += rdata_converter
- self.submodules += stream.Pipeline(
+ m.submodules += rdata_converter
+ m.submodules += stream.Pipeline(
port_to.rdata, rdata_converter, port_from.rdata)
+ return m
+
# LiteDRAMNativeWritePortUpConverter ---------------------------------------------------------------
-class LiteDRAMNativeWritePortUpConverter(Module):
+class gramNativeWritePortUpConverter(Elaboratable):
# TODO: finish and remove hack
"""LiteDRAM write port UpConverter
if port_to.data_width % port_from.data_width:
raise ValueError("Ratio must be an int")
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
+
+ def elaborate(self, platform):
+ m = Module()
+
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
ratio = port_to.data_width//port_from.data_width
counter.eq(counter + 1)
)
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- port_from.cmd.ready.eq(1),
- If(port_from.cmd.valid,
- counter_ce.eq(1),
- NextValue(we, port_from.cmd.we),
- NextValue(address, port_from.cmd.addr),
- NextState("RECEIVE")
- )
- )
- fsm.act("RECEIVE",
- port_from.cmd.ready.eq(1),
- If(port_from.cmd.valid,
- counter_ce.eq(1),
- If(counter == ratio-1,
- NextState("GENERATE")
- )
- )
- )
- fsm.act("GENERATE",
- port_to.cmd.valid.eq(1),
- port_to.cmd.we.eq(we),
- port_to.cmd.addr.eq(address[log2_int(ratio):]),
- If(port_to.cmd.ready,
- NextState("IDLE")
- )
- )
+ with m.FSM():
+ with m.State("Idle"):
+ m.d.comb += port_from.cmd.ready.eq(1)
+ with m.If(port_from.cmd.valid):
+ m.d.sync += [
+ we.eq(port_from.cmd.we),
+ address.eq(port_from.cmd.addr),
+ ]
+ m.next = "Receive"
+
+ with m.State("Receive"):
+ m.d.comb += port_from.cmd.ready.eq(1)
+ with m.If(port_from.cmd.valid):
+ m.d.comb += counter_ce.eq(1)
+ with m.If(counter == ratio-1):
+ m.next = "Generate"
+
+ with m.State("Generate"):
+ m.d.comb += [
+ port_to.cmd.valid.eq(1),
+ port_to.cmd.we.eq(we),
+ port_to.cmd.addr.eq(address[log2_int(ratio):]),
+ ]
+ with m.If(port_to.cmd.ready):
+ m.next = "Idle"
wdata_converter = stream.StrideConverter(
port_from.wdata.description,
port_to.wdata.description,
reverse=reverse)
- self.submodules += wdata_converter
- self.submodules += stream.Pipeline(
+ m.submodules += wdata_converter
+ m.submodules += stream.Pipeline(
port_from.wdata,
wdata_converter,
port_to.wdata)
+ return m
+
# LiteDRAMNativeReadPortUpConverter ----------------------------------------------------------------
-class LiteDRAMNativeReadPortUpConverter(Module):
+class gramNativeReadPortUpConverter(Elaboratable):
"""LiteDRAM port UpConverter
This module increase user port data width to fit controller data width.
if port_to.data_width % port_from.data_width:
raise ValueError("Ratio must be an int")
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
- ratio = port_to.data_width//port_from.data_width
+ def elaborate(self, platform):
+ m = Module()
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
+
+ ratio = port_to.data_width//port_from.data_width
# Command ----------------------------------------------------------------------------------
cmd_buffer = stream.SyncFIFO([("sel", ratio)], 4)
- self.submodules += cmd_buffer
+ m.submodules += cmd_buffer
- counter = Signal(max=ratio)
+ counter = Signal(range(ratio))
counter_ce = Signal()
- self.sync += \
- If(counter_ce,
- counter.eq(counter + 1)
- )
+ with m.If(counter_ce):
+ m.d.sync += counter.eq(counter+1)
- self.comb += \
- If(port_from.cmd.valid,
- If(counter == 0,
+ with m.If(port_from.cmd.valid):
+ with m.If(counter == 0):
+ m.d.comb += [
port_to.cmd.valid.eq(1),
port_to.cmd.addr.eq(port_from.cmd.addr[log2_int(ratio):]),
port_from.cmd.ready.eq(port_to.cmd.ready),
- counter_ce.eq(port_to.cmd.ready)
- ).Else(
+ counter_ce.eq(port_to.cmd.ready),
+ ]
+ with m.Else():
+ m.d.comb += [
port_from.cmd.ready.eq(1),
- counter_ce.eq(1)
- )
- )
+ counter_ce.eq(1),
+ ]
# TODO: fix sel
- self.comb += \
- If(port_to.cmd.valid & port_to.cmd.ready,
+ with m.If(port_to.cmd.valid & port_to.cmd.ready):
+ m.d.comb += [
cmd_buffer.sink.valid.eq(1),
- cmd_buffer.sink.sel.eq(2**ratio-1)
- )
+ cmd_buffer.sink.sel.eq(2**ratio-1),
+ ]
# Datapath ---------------------------------------------------------------------------------
port_to.rdata.description,
port_from.rdata.description,
reverse=reverse)
- self.submodules += rdata_buffer, rdata_converter
+ m.submodules += rdata_buffer, rdata_converter
rdata_chunk = Signal(ratio, reset=1)
rdata_chunk_valid = Signal()
- self.sync += \
- If(rdata_converter.source.valid &
- rdata_converter.source.ready,
- rdata_chunk.eq(Cat(rdata_chunk[ratio-1], rdata_chunk[:ratio-1]))
- )
+ with m.If(rdata_converter.source.valid & rdata_converter.source.ready):
+ m.d.sync += rdata_chunk.eq(Cat(rdata_chunk[ratio-1], rdata_chunk[:ratio-1]))
- self.comb += [
+ m.d.comb += [
port_to.rdata.connect(rdata_buffer.sink),
rdata_buffer.source.connect(rdata_converter.sink),
rdata_chunk_valid.eq((cmd_buffer.source.sel & rdata_chunk) != 0),
- If(port_from.flush,
- rdata_converter.source.ready.eq(1)
- ).Elif(cmd_buffer.source.valid,
- If(rdata_chunk_valid,
+ cmd_buffer.source.ready.eq(rdata_converter.source.ready & rdata_chunk[ratio-1]),
+ ]
+
+ with m.If(port_from.flush):
+ m.d.comb += rdata_converter.source.ready.eq(1)
+ with m.Elif(cmd_buffer.source.valid):
+ with m.If(rdata_chunk_valid):
+ m.d.comb += [
port_from.rdata.valid.eq(rdata_converter.source.valid),
port_from.rdata.data.eq(rdata_converter.source.data),
- rdata_converter.source.ready.eq(port_from.rdata.ready)
- ).Else(
- rdata_converter.source.ready.eq(1)
- )
- ),
- cmd_buffer.source.ready.eq(
- rdata_converter.source.ready & rdata_chunk[ratio-1])
- ]
+ rdata_converter.source.ready.eq(port_from.rdata.ready),
+ ]
+ with m.Else():
+ m.d.comb += rdata_converter.source.ready.eq(1)
+
+ return m
# LiteDRAMNativePortConverter ----------------------------------------------------------------------
-class LiteDRAMNativePortConverter(Module):
+class LiteDRAMNativePortConverter(Elaboratable):
def __init__(self, port_from, port_to, reverse=False):
assert port_from.clock_domain == port_to.clock_domain
assert port_from.mode == port_to.mode
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
+
+ def elaborate(self, platform):
+ m = Module()
+
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
mode = port_from.mode
if port_from.data_width > port_to.data_width:
- converter = LiteDRAMNativePortDownConverter(port_from, port_to, reverse)
- self.submodules += converter
+ converter = gramNativePortDownConverter(port_from, port_to, reverse)
+ m.submodules += converter
elif port_from.data_width < port_to.data_width:
if mode == "write":
- converter = LiteDRAMNativeWritePortUpConverter(port_from, port_to, reverse)
+ converter = gramNativeWritePortUpConverter(port_from, port_to, reverse)
elif mode == "read":
- converter = LiteDRAMNativeReadPortUpConverter(port_from, port_to, reverse)
+ converter = gramNativeReadPortUpConverter(port_from, port_to, reverse)
else:
raise NotImplementedError
- self.submodules += converter
+ m.submodules += converter
else:
- self.comb += [
+ m.d.comb += [
port_from.cmd.connect(port_to.cmd),
port_from.wdata.connect(port_to.wdata),
port_to.rdata.connect(port_from.rdata)
]
+
+ return m
-from litedram.phy.gensdrphy import GENSDRPHY
-
-from litedram.phy.s6ddrphy import S6HalfRateDDRPHY, S6QuarterRateDDRPHY
-from litedram.phy.s7ddrphy import V7DDRPHY, K7DDRPHY, A7DDRPHY
-from litedram.phy.usddrphy import USDDRPHY, USPDDRPHY
-
-from litedram.phy.ecp5ddrphy import ECP5DDRPHY, ECP5DDRPHYInit
-
-# backward compatibility (remove when no longer needed)
-from litedram.phy import s7ddrphy as a7ddrphy
-from litedram.phy import s7ddrphy as k7ddrphy
+from gram.phy.ecp5ddrphy import ECP5DDRPHY, ECP5DDRPHYInit
# TODO:
# - add multirank support.
-from migen import *
+from nmigen import *
-from litedram.common import burst_lengths
-from litedram.phy.dfi import *
-from litedram.modules import _speedgrade_timings, _technology_timings
+from gram.common import burst_lengths
+from gram.phy.dfi import *
+from gram.modules import _speedgrade_timings, _technology_timings
from functools import reduce
from operator import or_
self.source.first.eq(self.sink.first),
self.source.last.eq(self.sink.last),
self.source.payload.eq(self.sink.payload),
- self.source.param.eq(self.sink.param),
+ #self.source.param.eq(self.sink.param), # TODO ensure this can be commented
]
m.d.comb += self.sink.ready.eq(~self.source.valid | self.source.ready)
+++ /dev/null
-0x0000012e,0x61d2c8d5
-0x000000d9,0x8ec8f8f6
-0x00000135,0xf9f6145f
-0x0000033c,0xe653e338
-0x000002ff,0xbb609ae9
-0x0000037a,0xb42e5587
-0x00000228,0xce227592
-0x00000317,0xbd257969
-0x0000036e,0x7fe31c88
-0x0000011f,0xda6ba38d
-0x000002c7,0x141f40ad
-0x000000ab,0xa7c88a54
-0x000003f1,0xa48ddec4
-0x00000123,0xd800a7fe
-0x00000098,0x45a96b1d
-0x0000003b,0x4a75a15d
-0x0000004f,0x90e04e1a
-0x00000361,0x9af6660b
-0x000000fc,0xa4830b72
-0x00000033,0xb063ccb3
-0x000000c1,0xf60e53ac
-0x000002d2,0x47d9b283
-0x0000013f,0xe19843f7
-0x0000031d,0x30920818
-0x000001c3,0x2a830514
-0x000002c6,0xee6a0e7e
-0x00000104,0x6ab2c91c
-0x00000100,0x2dc79361
-0x000001e7,0xe9bf7c25
-0x00000149,0x29adfad6
-0x00000109,0x4f6c5d4a
-0x00000285,0x9ec316ff
-0x000001c4,0xf7768be4
-0x00000082,0x7478d35c
-0x000001a9,0x1832672d
-0x000001e5,0x12449eee
-0x000002f3,0x90a205e0
-0x00000217,0x266d0830
-0x0000039a,0xe6a207ac
-0x00000265,0x8fd00e38
-0x0000005e,0xc71ce3cc
-0x00000116,0x03808ba0
-0x0000025d,0x9db362a9
-0x000002d8,0x04ab3a95
-0x0000018b,0xd8ccace2
-0x0000007d,0x9443ab73
-0x00000187,0x7933b972
-0x0000015e,0xcf6daccc
-0x000002bc,0xbb9aa01c
-0x00000274,0x790bce70
-0x00000227,0xa2e56a6d
-0x0000002a,0xf2a9f0c7
-0x00000173,0x0cd5e422
-0x00000164,0x96c0513f
-0x000001fb,0x5d766d17
-0x000001a0,0x55ea28bb
-0x000002bd,0x38d65dfa
-0x00000142,0x7212fb34
-0x000000b5,0x3b5fa506
-0x00000354,0x6a89900a
-0x000001ac,0x2ce6be3f
-0x00000342,0xb956396b
-0x00000281,0x118b84ad
-0x00000300,0x6e091a3c
-0x0000029f,0x854141b2
-0x000000c6,0x3aafa04b
-0x00000107,0x907c2cb4
-0x0000000a,0xc965666f
-0x0000024c,0x2792b3a0
-0x00000203,0x1d19c1e1
-0x00000332,0x9f8ff8ce
-0x00000092,0x86c77fe4
-0x00000101,0x5d59d5f3
-0x00000025,0x5dedd914
-0x00000258,0x9c886d9e
-0x00000243,0x90a6e12a
-0x00000247,0x75f3803e
-0x000001ad,0x68843b6d
-0x00000071,0x63b4de04
-0x0000026e,0x622eab11
-0x0000034b,0xb42696c1
-0x00000195,0x7685880a
-0x000002ce,0x008d2d65
-0x000001c5,0xc064168f
-0x00000019,0xf93530a6
-0x000001b3,0xec1b06db
-0x000002f9,0x7ce508d3
-0x00000078,0xae78c8eb
-0x00000134,0x64c63926
-0x00000255,0xd3646539
-0x00000010,0xa158c47d
-0x000000f1,0xf18d4c56
-0x0000001d,0x3a693620
-0x000000e5,0x76b47c71
-0x0000001e,0xa741d479
-0x0000017f,0x84f156b2
-0x000000cb,0x8cc414d8
-0x000001a4,0xcd6cd47f
-0x000003e4,0x37307894
-0x000001a1,0x041c0b6e
-0x00000236,0x67741810
-0x000000b1,0x573222c0
-0x00000248,0x68e8f7f4
-0x00000316,0x16265757
-0x000001ed,0x85df14f1
-0x0000028e,0x54ec8e2f
-0x000002c8,0xfae5e756
-0x000003a4,0x2cd32729
-0x0000035b,0x8ce13b5a
-0x0000022d,0x943ce80f
-0x00000345,0x278ff629
-0x0000008d,0x94a9c2ec
-0x00000111,0xba4e5642
-0x00000011,0x22b3909c
-0x000000f7,0x55338938
-0x00000186,0x9218fd6c
-0x000000e0,0x3c48a497
-0x0000033a,0xda233663
-0x00000048,0x58855816
-0x0000029d,0x4df9feb1
-0x00000382,0x9f0f2502
-0x00000132,0xddaed3fe
-0x000001a7,0xfde6bdba
-0x00000128,0x448fce9a
-0x0000037e,0x42aaaa1e
-0x000001a8,0x4ea6f4df
-0x000000ec,0x912aeb2c
-0x00000056,0xde7d8aeb
-0x000003e6,0x15f855a1
-0x0000001c,0xe0225e1e
-0x00000080,0x3686bfb7
-0x000000da,0x7724b050
-0x000001b2,0xfec50f9a
-0x000003c8,0x68d72fa8
-0x00000225,0x65df6eb6
-0x00000049,0x5b181430
-0x0000027e,0x35ec0cd3
-0x00000348,0xc1f5138a
-0x0000036a,0x47b36f4d
-0x00000178,0x073f863c
-0x000001fc,0xf6ccbf5f
-0x000003b3,0x3729f5ba
-0x00000356,0x7f6d4988
-0x00000378,0x31d541ce
-0x000001bf,0xe26033b2
-0x000002f4,0x4d009701
-0x0000012a,0x383e7b20
-0x000002f6,0x4ecb429b
-0x000002ea,0xac934081
-0x000001d7,0xdf607028
-0x0000005b,0x3d48a4d7
-0x000000dc,0x9b2eed8e
-0x00000089,0xe8170872
-0x0000007c,0x64439e56
-0x0000000e,0x3bb95a3c
-0x00000239,0x36e6a900
-0x000001d8,0xc4c42852
-0x0000002d,0xa3a1a282
-0x0000000f,0x4f3c81e2
-0x000002c2,0x5d291767
-0x000002fb,0x2e48dcfa
-0x00000119,0xc07a0c3c
-0x000002e8,0x1cce5cbd
-0x00000333,0x3a3a7e63
-0x00000110,0x4b501b3a
-0x000001af,0xb1287fe3
-0x000001db,0xee4a7258
-0x0000018c,0xe9276e99
-0x0000013c,0x5bf99b5f
-0x0000010b,0x2b1a09ff
-0x0000031b,0xd9f78b82
-0x000003d9,0x505c7a02
-0x0000000d,0x9c568cbf
-0x00000330,0x6f043b79
-0x000001f1,0x994dda6a
-0x0000000b,0xd09629fa
-0x00000136,0x41991be6
-0x0000004d,0x5e6a2d20
-0x00000198,0x0e0474d7
-0x000000ac,0x951f892d
-0x00000022,0xc9ec5c7c
-0x0000000c,0x95301582
-0x000002ef,0x08da98c7
-0x000003fb,0x43b4fd33
-0x000001eb,0x9e9b01ba
-0x000000a3,0x325f8442
-0x00000209,0x74878d2f
-0x00000159,0x4f1ec90f
-0x00000172,0x6089924d
-0x0000021a,0xaedaaeb8
-0x0000029a,0x7107bf13
-0x000001e1,0x584d3369
-0x00000106,0x75579cb1
-0x00000148,0x34bb1175
-0x00000398,0xb5d2e270
-0x000001ff,0x5a4cd7c1
-0x000003df,0x5ab6637c
-0x0000032f,0xa588b2ab
-0x0000033d,0x893d9f9c
-0x00000183,0x6c833e74
-0x0000019d,0x9584ba23
-0x000000d4,0x7499251f
-0x00000384,0x38c04aee
-0x000002d7,0x2f780083
-0x0000003c,0x25ea371f
-0x0000014d,0xa422c342
-0x000000a5,0xbb8ca7b1
-0x000000b4,0x600bfbb7
-0x000003a2,0x7536026b
-0x0000019f,0xf3056983
-0x000003b5,0x14819baa
-0x0000025b,0x22bfc5b4
-0x000001f4,0xf3dcc407
-0x000003d4,0xdd204ebc
-0x000000e8,0x19371324
-0x0000031a,0x388f82b1
-0x000000b8,0xaa3c9d73
-0x00000370,0xdf89cab0
-0x00000251,0x149453d0
-0x00000177,0x060e6abb
-0x000001d3,0x64c800bf
-0x000002e0,0x197fe27c
-0x000001bc,0x112c0c05
-0x00000339,0x5c1d0545
-0x0000011d,0xa9cb28e3
-0x00000020,0x9d16cec1
-0x0000037b,0xf46e9e3d
-0x00000182,0x99e052fd
-0x00000389,0xbd93a71e
-0x000002b4,0x4bdf2842
-0x000002fc,0xa93be104
-0x00000192,0x1fd37c83
-0x0000020e,0x542b2943
-0x00000001,0x6a1469d3
-0x00000146,0xbfca75e9
-0x0000010e,0x8e00b2ee
-0x00000141,0x4a5c4324
-0x00000023,0x7cfd7c93
-0x00000235,0xce9539ab
-0x000002a0,0xe31e7f99
-0x00000231,0xbb3e3d23
-0x00000214,0x6eaa5dfc
-0x00000319,0x9f719f0d
-0x00000175,0x5ae51df8
-0x000002b0,0xa993d4c0
-0x000002da,0x9bb2a247
-0x00000053,0xd8d2dec4
-0x000003e0,0xaae00f7b
-0x00000309,0x3f866f74
-0x00000276,0x4cf2e344
-0x00000055,0x4ba9a459
-0x00000216,0xee2ceffb
-0x00000139,0xc9e720fb
-0x00000338,0xc6204e59
-0x00000271,0xc98ed7f6
-0x000002a4,0xfd31d029
-0x00000286,0xdbcc04cb
-0x0000037f,0x19bfb426
-0x00000064,0x0def53ae
-0x00000335,0xbd34fdea
-0x00000205,0x331768f4
-0x0000035c,0xa0e11fea
-0x00000375,0x43bd9bcf
-0x00000246,0xf1f27dd0
-0x00000018,0x3a703637
-0x00000388,0x4ca11d1c
-0x00000169,0x7a808c4a
-0x00000143,0xde360dec
-0x00000088,0xf788f2f8
-0x000002c3,0x20fc77bb
-0x0000018a,0x171ffa1c
-0x000003bd,0xc1285057
-0x0000032b,0x47a437ab
-0x000003ce,0xab34d83e
-0x00000066,0x9c21cc65
-0x00000163,0x16b89209
-0x000001a5,0x39ed216e
-0x000000d7,0x24e89199
-0x00000125,0xcd425b63
-0x000002e7,0xa3d10901
-0x00000219,0x16d97533
-0x00000363,0xceb7cdc8
-0x000002c9,0xb7ca8bb3
-0x000002a1,0xc9a18b20
-0x00000027,0xaf3a93d3
-0x00000343,0x724cf43c
-0x0000016d,0x709cdc2b
-0x000003fa,0x0bb57a27
-0x000003d0,0x50ebce7d
-0x000003b4,0xcca0fcbd
-0x000001d2,0xd47c15f9
-0x00000171,0x23e44721
-0x0000014b,0xfa40a59c
-0x000002bf,0x2669def1
-0x000003de,0x029d6b69
-0x00000390,0xd6467cb3
-0x00000013,0x2fa1f2fe
-0x00000329,0x39b5b021
-0x00000391,0x7155d9e6
-0x000000a4,0xe65f6a8b
-0x0000010d,0xeb081ac3
-0x000001d9,0xc3333042
-0x0000001a,0xa7b3a7a1
-0x0000005c,0x15cc2a0b
-0x000001df,0x58349e33
-0x00000081,0xbce62295
-0x00000129,0x4d34e0a5
-0x0000037d,0xae0fb82d
-0x0000033f,0xbab64099
-0x000000ae,0x19cf9f0c
-0x00000085,0xf65025dc
-0x0000030d,0x156184eb
-0x000000f3,0xd44874cb
-0x000003c4,0x234a08dc
-0x00000073,0x89be0b06
-0x0000008c,0x9c2f3f36
-0x0000006a,0x6dbd974e
-0x000003ae,0xb1c0fac8
-0x0000036c,0x0158019e
-0x0000003f,0x60d2350b
-0x000000c3,0xe0bf851a
-0x0000005d,0x57f4331e
-0x00000160,0x2d01f727
-0x00000074,0xe7420f16
-0x0000001b,0x65193a81
-0x000003b6,0x5404408b
-0x000000fe,0x4a912205
-0x0000020f,0xaf1ec7e3
-0x000003f2,0x65284d10
-0x00000038,0xc38902f9
-0x0000006b,0x93f02e10
-0x00000029,0xb73538b1
-0x000002ab,0x3832c214
-0x000001f3,0x7f04e0fe
-0x000002e2,0x863662da
-0x0000010f,0x6a7b7b52
-0x00000360,0x313fa92d
-0x000002e1,0x29574441
-0x00000133,0x8503d7a1
-0x00000072,0xdf037127
-0x00000318,0x1f0a5242
-0x00000154,0x5d171f74
-0x00000197,0xa236ca17
-0x000000c5,0x344b386f
-0x0000023b,0xbbfca537
-0x000002dc,0x8ecdbd48
-0x000000d3,0x68417535
-0x000002c4,0xa87d737e
-0x00000302,0x5b4ac57d
-0x000003b1,0x7208c47a
-0x00000264,0xe967870e
-0x00000230,0x6b8a64a4
-0x000001c0,0xa90e1999
-0x000000d0,0xfe6134c9
-0x000000e4,0x0d1e3e4f
-0x000003ed,0x2765a290
-0x0000038a,0xadefbc7a
-0x00000290,0x2253d279
-0x000001da,0xef8c14da
-0x00000204,0xfa11139c
-0x00000024,0x51773a21
-0x0000022c,0x82e40079
-0x000003e1,0x0d25dc31
-0x000002fa,0xae982f52
-0x000000aa,0xbdf45ea4
-0x0000026f,0x4441d881
-0x00000362,0x9129843f
-0x000000d8,0x34175578
-0x000001f6,0x01663b92
-0x000003cc,0x341926d0
-0x00000352,0x4dc5fcc0
-0x00000036,0x1566a8eb
-0x00000273,0xfdc7e15c
-0x000000af,0xbaed2374
-0x00000041,0x1a0b8317
-0x000001dd,0xd18f699a
-0x000000a8,0x90cb209a
-0x00000257,0xbf67c32e
-0x0000003d,0x0cbb59c4
-0x00000093,0xfe60eac3
-0x00000336,0xcf5be5dc
-0x00000084,0x660900fc
-0x00000320,0xaf5e2207
-0x0000032e,0x397069f3
-0x000001b7,0x9ed88604
-0x0000005a,0xd9e0f4a5
-0x000001cb,0xf2081a29
-0x00000270,0xe42a12a4
-0x0000027b,0x48fb577a
-0x000003c3,0x239ff442
-0x0000015f,0xcef290ee
-0x0000002b,0xe894ca29
-0x000002e6,0x00605a5d
-0x000003d8,0x8a3309b1
-0x000003ba,0x715efaae
-0x00000113,0xa0d1f6a8
-0x000001e8,0x744fd2ca
-0x00000065,0x326f3881
-0x00000305,0xf508ccfc
-0x00000215,0x594d1b47
-0x000002d4,0x89b4ec73
-0x000001a2,0xf12e7ff3
-0x000003ab,0x270a33a1
-0x000002d9,0x95c40cc3
-0x000001f0,0xadb2d1e6
-0x00000334,0x1f8b03c2
-0x00000359,0x0c8c22df
-0x00000016,0xfdef90f8
-0x00000321,0x6d16c2b6
-0x0000012d,0x4a4a85aa
-0x00000112,0x1b9612a0
-0x000000c2,0x11b7b67a
-0x000003a8,0x0d2ddd6b
-0x0000028c,0x9bac58e1
-0x0000001f,0x38060223
-0x00000299,0xa69b4430
-0x0000034e,0x92075ea3
-0x00000068,0x24693370
-0x00000091,0xe20db412
-0x0000029e,0x78539957
-0x00000385,0x7a646c06
-0x0000002c,0xd00f800a
-0x00000188,0x0846d6bc
-0x000001e0,0x1702b043
-0x000002cb,0x1f438aea
-0x0000005f,0xa43309be
-0x00000147,0x1609f9c1
-0x000002f7,0x7b851f8e
-0x000002dd,0x6bf738a3
-0x000000ca,0x1a50ad66
-0x000001e9,0x37a9593f
-0x0000006f,0x6de45853
-0x0000015c,0xeb6cb24e
-0x00000030,0xce267ad7
-0x0000002e,0x4ec1453b
-0x000001d1,0xfc14bec4
-0x00000017,0x876d7392
-0x000002f8,0x9ac12c44
-0x000000f6,0xf524d27d
-0x0000035d,0x30a11607
-0x00000394,0xd3b26a18
-0x00000355,0xee8a455a
-0x00000261,0x98c20113
-0x000000d5,0x37fbdd7f
-0x00000325,0x85269178
-0x0000011e,0xf74a97ad
-0x0000028d,0xb144ba63
-0x000000ef,0xec40f103
-0x000002be,0xda839587
-0x00000061,0xe116a87a
-0x000002ae,0xb615d223
-0x000001ab,0x81c40cec
-0x000000cd,0xe644b747
-0x0000006e,0x82bd6a8c
-0x00000000,0xf000849b
-0x0000032d,0xb22bc4c2
-0x00000368,0x7510c7f3
-0x00000067,0xe616e21e
-0x00000358,0xb2b4e853
-0x000002a3,0x1a809df7
-0x000000a0,0xbd9649c3
-0x000003d2,0x93cb8b68
-0x00000046,0xf4aa0c1b
-0x0000026a,0xb84137a0
-0x000000f4,0x5519ed9c
-0x0000025e,0x27785441
-0x000000e2,0xf7c05a5c
-0x00000346,0x99448f63
-0x0000008b,0xf7808cc8
-0x0000036b,0xa20fdf9e
-0x000000bc,0x0d624554
-0x0000017b,0x328aa94c
-0x0000023f,0xab882098
-0x0000033b,0xcb5d14ad
-0x00000114,0x62fca8d3
-0x000003fc,0x80a34a21
-0x000001bd,0x2027292c
-0x00000328,0x6b1ed1f1
-0x000000b6,0x3cd89d38
-0x0000027c,0xf3f04d4e
-0x000003d5,0x482e2cce
-0x00000054,0x5d084c63
-0x000002df,0x9694542a
-0x000003b8,0x823d6559
-0x00000289,0xc3adcb32
-0x0000035f,0x88e8e6db
-0x0000024f,0xc288d6fb
-0x000001cc,0xf5a0c23e
-0x0000015a,0x04c6ac85
-0x000000e6,0xa2c708a6
-0x000000cc,0x214ae76e
-0x0000039e,0x75bf1bc8
-0x000003c9,0x3191a7eb
-0x000000e9,0xec7d07db
-0x00000060,0xe0710b88
-0x000002a7,0x73d0cd4e
-0x000003db,0x1e017f85
-0x000000a2,0x489b1f6c
-0x00000076,0x60529d31
-0x0000004b,0x93b6355e
-0x00000063,0xe9691ee0
-0x000001ea,0xf1d3e628
-0x000000a6,0x3eaf45d5
-0x0000034a,0x079bc1db
-0x00000003,0x2b83ee22
-0x000003cb,0xb38d5007
-0x00000315,0x005c5340
-0x000003f9,0xf61bec1d
-0x000003fe,0x459a3987
-0x000001b4,0x955aa611
-0x000000c9,0x0b8502a7
-0x0000025c,0x919b4b7f
-0x00000323,0x4e0b307c
-0x0000039c,0x25e20b80
-0x00000035,0x15d35def
-0x00000155,0xed7988b9
-0x0000007a,0x0d259437
-0x0000031c,0xc448416c
-0x00000379,0x588b1ea1
-0x000000ee,0xda9033f2
-0x0000017c,0x5d8510dd
-0x0000017d,0x7a845fad
-0x0000009d,0x285e125f
-0x000003ac,0xc3a8f4f8
-0x00000044,0x562f95f9
-0x000001c2,0xcbcbfc47
-0x000001f8,0x8bb3c481
-0x000002f1,0x5eb9554d
-0x0000007e,0x3cd4d757
-0x000003c2,0xf24687c9
-0x00000208,0x22fe40f5
-0x000001c6,0xbd394a93
-0x00000207,0x9f8abb23
-0x0000003e,0x3b084161
-0x00000310,0x5dd566f4
-0x0000038e,0x93cfc737
-0x0000015d,0x248175bd
-0x0000009c,0x06a757d2
-0x00000220,0x6298f764
-0x000001cd,0xb7493bd3
-0x00000340,0xcab3638c
-0x0000016a,0xba6f41df
-0x000000de,0xb583bd95
-0x000000b3,0x55ee3276
-0x00000105,0xe60a6ea0
-0x00000292,0xfa17da23
-0x000001c7,0xc02731ee
-0x0000039b,0x314a1f3f
-0x00000324,0xaa0e0330
-0x000003ef,0x5606084c
-0x000000bb,0x3f139afc
-0x0000027d,0x04af2287
-0x0000025f,0x1ddf8f9e
-0x00000242,0x0f8a411a
-0x000003c1,0xc6518d07
-0x00000303,0x465f710f
-0x0000002f,0xed4d052e
-0x0000024b,0x1343c957
-0x00000393,0x5c0a5fe4
-0x000002c5,0x0465e58d
-0x0000009e,0x2c09e0a8
-0x00000008,0x853a3b86
-0x0000009f,0x0bb6972d
-0x000002d3,0x961b173f
-0x000000f0,0x9756f025
-0x00000245,0x5d446cad
-0x000001b9,0xdd7862a5
-0x000002b5,0xc2d1e49b
-0x00000090,0x5dcb1a93
-0x0000019b,0x17c5f622
-0x0000007f,0x2048e019
-0x000000bf,0xe575efda
-0x00000050,0x29f4ff94
-0x00000326,0x5af3c8fa
-0x0000019e,0xae8ad590
-0x000002ad,0x4325de4c
-0x0000030c,0xd00530a4
-0x000002cc,0xf3f7fcf7
-0x0000032c,0xbc35a67f
-0x0000016c,0x2ad3a928
-0x000000f8,0x4ddf8b47
-0x0000004c,0x349d1982
-0x0000039f,0x8e06d477
-0x000003ee,0x67e0cbc5
-0x0000021b,0xbbbd1879
-0x0000004a,0x2c55a027
-0x000002a2,0x2634f218
-0x000003cf,0x3d73d279
-0x000000eb,0x6e78b973
-0x0000021e,0xdd01d278
-0x00000127,0xd6fd8840
-0x00000059,0xadb7fd4a
-0x000002ec,0x3ced1d8a
-0x0000038f,0x1dad4ff2
-0x000002b3,0xa7b024d8
-0x000002d6,0xead8cd71
-0x00000184,0x1ee19ab9
-0x00000120,0xa362afd8
-0x00000260,0xb2d1429d
-0x00000005,0x6aa3df1a
-0x00000308,0x1ebb5208
-0x000000ff,0xa9df5014
-0x00000087,0x32938571
-0x00000126,0x59d446f1
-0x00000293,0xde9d5490
-0x0000029c,0xa779710c
-0x000002a9,0x62c7737d
-0x000003bc,0xa800328e
-0x000002ca,0xd5b99fa7
-0x00000249,0x06ec5c2f
-0x000003ff,0x588a9bdc
-0x00000371,0x33386477
-0x000000c4,0x2feeb727
-0x000000fd,0xe950d114
-0x0000033e,0xcccfdb62
-0x000003af,0x9cbb4ec8
-0x00000045,0x4e91087f
-0x000000ea,0xfa9c9aac
-0x000000be,0x6af216ea
-0x0000010c,0x632ae74f
-0x000001e2,0xb101bded
-0x0000020a,0x7a41e224
-0x00000238,0x4c4b3a6e
-0x00000158,0xb7328634
-0x000001be,0xe102181b
-0x000003a9,0x5c529dd4
-0x000003a7,0xec370158
-0x00000108,0x889d6ebe
-0x0000025a,0x95906629
-0x00000350,0xcf1cd4e7
-0x000001f5,0x7c295b29
-0x000003bb,0xeae747ee
-0x00000349,0x82ae2057
-0x000003b9,0x7a249f88
-0x000001b0,0x2563614b
-0x00000174,0x325549b4
-0x000000e3,0x6e51ae06
-0x00000006,0xb845331b
-0x000003b0,0xbf77e74d
-0x00000322,0x444d330a
-0x00000191,0x83d91767
-0x000000ad,0x477af9ba
-0x0000021f,0xc071f857
-0x0000008f,0x3e8a5d1a
-0x0000029b,0x9b0431fd
-0x000002a8,0xcebb2ae6
-0x00000165,0x1a2c3cd4
-0x00000157,0x1629e3fe
-0x000003d1,0x9dc7627c
-0x00000121,0xe1ff1567
-0x0000007b,0x51610f6c
-0x000000d1,0x7d5918b4
-0x000002b8,0x74025419
-0x00000395,0x6001080f
-0x000000b7,0xbdfa2c1a
-0x000001b1,0xe0b9b238
-0x0000038d,0xae0f8b86
-0x00000291,0x7d585c4d
-0x0000018f,0x7381b5ac
-0x000002ba,0xc3081096
-0x000000ce,0x7f15786e
-0x0000022e,0x424bc3fc
-0x0000006c,0xee2cc7a7
-0x000001a6,0xb3b219a0
-0x0000034d,0x9a9e73fe
-0x00000118,0x63d7a149
-0x0000026d,0x1d6d3ea4
-0x00000162,0x44b271c9
-0x00000241,0xd6da9f44
-0x0000030b,0x3f8a78d2
-0x000001ba,0xd2c0fe52
-0x000000bd,0x723c8910
-0x00000234,0xbf48bec5
-0x000001b8,0xa7874edb
-0x00000226,0xdd6aa284
-0x00000144,0xe7d2458c
-0x00000012,0xd6d8c04a
-0x0000017a,0xf6ae9915
-0x00000014,0xb00b0422
-0x000002f0,0x88041d25
-0x00000069,0x61278220
-0x0000030f,0xf2c3811d
-0x00000037,0x9d861d63
-0x000002d5,0x6c37dd6c
-0x000000c7,0xc80f3a17
-0x000001d4,0xdf893fdc
-0x000002ed,0xc5ec640d
-0x000002d1,0xa1bdec12
-0x000001ee,0x4e254439
-0x00000311,0x178b04fc
-0x0000019a,0x8da6f6b4
-0x000003e8,0x82797f9b
-0x00000152,0x9b9c0438
-0x0000014c,0x909b71e7
-0x000002b9,0x57eefc02
-0x00000279,0x21f30dd9
-0x0000013b,0x282ecf47
-0x0000012b,0xb8240d6c
-0x00000272,0x56ce2bbb
-0x00000040,0xba39ad57
-0x0000026c,0x35592672
-0x000003e3,0x4eb09c06
-0x000003f3,0x341149c8
-0x000001e3,0xe89b8254
-0x000002c0,0x2dd5663b
-0x0000009a,0x9e6c6b56
-0x00000021,0x12fd7034
-0x00000387,0xa027ea96
-0x000001ce,0x8af8e5c7
-0x000003f0,0x4d341384
-0x00000267,0xd2f19763
-0x0000018d,0x765671c5
-0x000000a1,0xaf382a64
-0x00000221,0x7fd9a647
-0x000002fe,0x7d1b99ca
-0x00000277,0x4db2b052
-0x000003dc,0xd5a05d52
-0x00000058,0x4ccbf2d4
-0x000000c0,0x33761998
-0x00000254,0xa34acbad
-0x000001d5,0xe2064af6
-0x0000021d,0x33c319ae
-0x00000083,0x8af6070c
-0x00000062,0x2c5c3595
-0x000001b5,0x53c1a11a
-0x00000365,0xb7641db3
-0x000000fa,0x8f168750
-0x000003d7,0x62700567
-0x0000035e,0x30cf6a3c
-0x00000297,0xaece2cae
-0x0000030e,0x4a431c09
-0x000001f2,0xb088d216
-0x0000023a,0x96ce06c1
-0x00000176,0x8a9abb34
-0x00000115,0x311a4837
-0x0000031e,0x5e85164b
-0x00000047,0x00a0eeb5
-0x000001a3,0xf84eca18
-0x000000f2,0x2cbee27a
-0x0000014e,0x2f191aee
-0x000000b9,0x3b12a538
-0x0000026b,0x472f6ac7
-0x00000233,0xa4337bf2
-0x00000052,0xf6959222
-0x000002b7,0xfe1c9ccf
-0x0000024a,0x4e6efdf3
-0x00000218,0x5496f22a
-0x0000024d,0xcfdaf597
-0x00000009,0x17453936
-0x0000032a,0x8c570977
-0x00000313,0xa5a96add
-0x00000179,0xfb73e3f9
-0x00000180,0x31c27b51
-0x000002fd,0x2d15a0cd
-0x0000012f,0xc475fc25
-0x000002a5,0xdf36df3c
-0x000003be,0xbccd34d7
-0x00000140,0x3f11ac6c
-0x000002af,0x4f8f60de
-0x00000200,0x6b3ed957
-0x00000372,0x3134dec0
-0x000002bb,0x4677e498
-0x000000a9,0xc657ff78
-0x00000351,0xdaa8f98a
-0x00000170,0x865000f4
-0x000001c1,0x0daad104
-0x000003f6,0x54381f7c
-0x00000282,0xae0de4fd
-0x0000039d,0x930925cc
-0x0000020b,0xc04f5b79
-0x00000007,0xe60b3af3
-0x0000027f,0xcb230d4d
-0x0000034f,0x6e94cf18
-0x00000026,0x979b5acb
-0x000002b2,0xd69292e1
-0x00000137,0x298e7abb
-0x000001dc,0xaab2730d
-0x0000020d,0x50b57ca0
-0x00000298,0x5f9276c5
-0x0000022a,0x63391f81
-0x00000314,0x00f61207
-0x0000030a,0x1d94bc11
-0x0000017e,0xece45f2a
-0x00000196,0x3376ea4f
-0x00000212,0x394c781e
-0x0000015b,0xaa45c8e4
-0x00000262,0xee189cde
-0x000000b2,0x0cf81cad
-0x000003e5,0x6a469268
-0x00000122,0x0fe0bf0f
-0x000003ca,0x299b8fa4
-0x0000035a,0x18a3db69
-0x00000266,0x0387ddf8
-0x000001c8,0x76d2e831
-0x000001d0,0xd3132dbd
-0x00000206,0xfa3a0f73
-0x00000373,0x837f807f
-0x00000015,0x8f88a8ab
-0x00000386,0x3c2ee566
-0x000003f7,0x56d51358
-0x00000223,0xe644ada5
-0x000002f5,0x8f20bddd
-0x0000011b,0xa72467ed
-0x000001ef,0x0eeb3073
-0x000000d2,0xfceccbcc
-0x000002f2,0x722f9ca7
-0x000002ac,0x134a4fbb
-0x00000301,0x3cc98027
-0x0000014f,0xfbec5bf5
-0x000003d3,0x628b4ab9
-0x000001f7,0xf8e6291c
-0x000002d0,0x326e58d8
-0x000001ae,0x78256d64
-0x00000057,0x403e8c61
-0x0000008a,0x1d7338bc
-0x0000013e,0x1e11634f
-0x000002de,0xaf0f3eb1
-0x00000199,0xae5c4f27
-0x00000102,0xb0bac110
-0x000003c6,0x485052b8
-0x0000016e,0x5a38a789
-0x00000252,0x54542916
-0x00000002,0x39b180bd
-0x00000250,0x230f1e18
-0x000002db,0x1da31dad
-0x0000018e,0xbf914fb7
-0x000003c0,0x63f13c95
-0x00000369,0xbc276edd
-0x00000288,0xf2e5c78c
-0x00000211,0x8be09b81
-0x00000193,0xa9dd3901
-0x000003d6,0x564698ff
-0x000000dd,0x654586cd
-0x0000013d,0x17f8cdf8
-0x000003dd,0xf55532d7
-0x000000e1,0xd21d0301
-0x00000344,0x8e5c90b7
-0x00000347,0xce2ea106
-0x000002b6,0xe1456d48
-0x00000096,0x1690a90b
-0x000002e4,0xbfcf1ee5
-0x00000284,0x9bbd41e7
-0x00000376,0x0a1b239d
-0x00000194,0xb8c0425c
-0x000001cf,0x5a5f67b8
-0x0000019c,0x8c1365bf
-0x00000269,0x7ccc3095
-0x000001fe,0xeff19023
-0x00000028,0x4c6c96e1
-0x00000075,0x6031fafc
-0x000000e7,0x6d066ff7
-0x00000213,0x83a12826
-0x000003a1,0xdff42be1
-0x000000d6,0x74721815
-0x00000094,0x5e9436ba
-0x000003ec,0x0f91f2dd
-0x00000167,0x2f5d9a5c
-0x000001bb,0x41b606be
-0x00000222,0x455c3f18
-0x0000038c,0x41938755
-0x00000034,0xf3e676b0
-0x00000031,0xb3b105f0
-0x00000043,0xaebbd49c
-0x00000079,0x32e9f285
-0x00000130,0x90514309
-0x00000253,0xda947617
-0x000003c7,0x3a454ada
-0x00000131,0x6d9bb5fa
-0x00000278,0x5c094e3b
-0x00000256,0x19969979
-0x00000357,0x8f966e1a
-0x00000185,0xba65d2f8
-0x00000263,0x19417509
-0x000000db,0x1eaadeab
-0x00000232,0xef46402c
-0x00000240,0x215c8ec5
-0x000003b7,0x1d7489dd
-0x00000086,0xa9d49edc
-0x000000f5,0xb85554dc
-0x00000099,0x5d964de7
-0x000003fd,0x6722db64
-0x00000312,0x829a6b53
-0x000001fd,0xf5abdab3
-0x000002c1,0xe5662f67
-0x000003c5,0x2a5f11dd
-0x000002ee,0x69769d62
-0x000001d6,0x76155587
-0x0000016f,0xf474b542
-0x000003b2,0x0e03d080
-0x0000006d,0xcce03f59
-0x00000244,0xae332051
-0x00000366,0xa5d17a7b
-0x0000022b,0x0bb8f348
-0x00000150,0xd9d81433
-0x000000f9,0x06f2b1ca
-0x000000ed,0x10f3cbb5
-0x0000028a,0xb92f3a08
-0x0000038b,0x2e7839fc
-0x0000036d,0x8a55891d
-0x00000306,0x004434c7
-0x0000027a,0x2c2fe04e
-0x0000010a,0x23317858
-0x000003cd,0xb2e47f17
-0x000003a0,0xed86f8e0
-0x0000013a,0xf295d26e
-0x00000042,0xbd71be15
-0x0000016b,0xf52fcd29
-0x000003a3,0x80b123f1
-0x000003f4,0xc7b11df1
-0x000003ad,0x93a20006
-0x000003eb,0x52d781ac
-0x000002b1,0x6a5e69a3
-0x0000011a,0x0f63315c
-0x00000117,0x33659391
-0x00000051,0x1a05f763
-0x0000009b,0xde4ef3eb
-0x00000161,0xcd7d1638
-0x000001ec,0xee053da6
-0x000001ca,0x42044d3f
-0x000001de,0xcd1d0123
-0x0000028f,0x51f7b994
-0x000003bf,0x108f008e
-0x00000032,0x1ec7d1cb
-0x00000124,0xab39af81
-0x00000189,0x1678f062
-0x000002cd,0x510dc040
-0x00000331,0x4d33628a
-0x00000229,0x944e008a
-0x00000341,0x5a7a5372
-0x00000166,0xa92e5b7d
-0x00000337,0x174610f0
-0x000002e3,0x38695e89
-0x0000023e,0x96675159
-0x000003da,0x64ab9558
-0x00000097,0x3f86cd0f
-0x000000fb,0x107b81b4
-0x000002eb,0x7fd9a144
-0x00000039,0x30a2b470
-0x00000145,0x5f730f7d
-0x0000011c,0x966cf066
-0x00000275,0x21d87efc
-0x00000202,0xa470e81e
-0x00000380,0x7f1c9cfe
-0x000002a6,0x83ef8a4a
-0x00000392,0x7f080fa5
-0x00000304,0x24a98eb9
-0x000003f8,0xd1a6e7cb
-0x00000224,0xc8497258
-0x000003a6,0x6b304020
-0x00000201,0x30733eea
-0x0000004e,0xe5996b9a
-0x00000383,0x11421776
-0x000000cf,0x35b5d61d
-0x00000367,0x630ff9ae
-0x000001aa,0xbee7db59
-0x0000021c,0x341d6960
-0x00000283,0x89c0976d
-0x00000070,0x599deb7b
-0x000003a5,0xb79a547e
-0x000003aa,0x990a9aeb
-0x00000399,0xd867d08c
-0x000001b6,0x9c822c9e
-0x00000153,0x05f7124a
-0x00000296,0x1014c48d
-0x000002e5,0xc948f761
-0x00000190,0x74483f9b
-0x00000077,0x805f10a1
-0x00000280,0xb6fdd0fe
-0x000000c8,0xb7147ac4
-0x000003e9,0x39daa1ed
-0x00000259,0xc3d82fe5
-0x000002e9,0x1781b102
-0x000002aa,0xfb0674fd
-0x00000396,0xa2f79ac4
-0x00000353,0x796131a3
-0x00000294,0x3a4f253c
-0x00000268,0x8819efeb
-0x00000364,0xbbac1595
-0x000003f5,0x6468a5f3
-0x00000103,0xd39a7cf1
-0x00000004,0x2d311b72
-0x000002cf,0xbeda8a15
-0x0000031f,0x92221439
-0x00000374,0xb790d8a9
-0x0000020c,0x45db5760
-0x000003e2,0x6332d00f
-0x0000028b,0xcfb7b189
-0x000001c9,0x6380385f
-0x0000037c,0x443714c5
-0x00000397,0x3a84c720
-0x00000377,0x6cd3807c
-0x000000a7,0xeed1718a
-0x00000168,0xb2d6b00f
-0x000000ba,0xd4143f6b
-0x000001e6,0x70a5cba8
-0x0000003a,0x6db46c23
-0x00000138,0x8b1cbc57
-0x00000327,0x1417447b
-0x0000023d,0xf824f9fe
-0x000000b0,0xa4afe544
-0x0000024e,0xcdeefb90
-0x00000156,0x9116659d
-0x00000095,0xbec1d9ff
-0x000003ea,0x418440ad
-0x000001e4,0x60b154d8
-0x00000381,0x05bee376
-0x0000023c,0x56313370
-0x000000df,0x2271ed24
-0x00000237,0x5e79fb1a
-0x0000034c,0x00a28d23
-0x00000307,0x9a60280a
-0x00000287,0x4aebb908
-0x0000036f,0x15b250b7
-0x000003e7,0xc03cd972
-0x0000022f,0x07b8b4f6
-0x00000295,0xba38ebb6
-0x00000210,0xba34a72a
-0x000001f9,0x3f3d8c6d
-0x000001fa,0xeec12a22
-0x00000151,0xcf258683
-0x0000012c,0x52c63dee
-0x00000181,0x7a1b33cb
-0x0000014a,0x87b6f8b2
-0x0000008e,0x18c0f3a6
+++ /dev/null
-#!/usr/bin/env python3
-
-# This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-import csv
-import logging
-import argparse
-from operator import and_
-from functools import reduce
-from itertools import zip_longest
-
-from migen import *
-from migen.genlib.misc import WaitTimer
-
-from litex.build.sim.config import SimConfig
-
-from litex.soc.interconnect.csr import *
-from litex.soc.integration.soc_sdram import *
-from litex.soc.integration.builder import *
-
-from litex.tools.litex_sim import SimSoC
-
-from litedram.frontend.bist import _LiteDRAMBISTGenerator, _LiteDRAMBISTChecker
-from litedram.frontend.bist import _LiteDRAMPatternGenerator, _LiteDRAMPatternChecker
-
-# LiteDRAM Benchmark SoC ---------------------------------------------------------------------------
-
-class LiteDRAMBenchmarkSoC(SimSoC):
- def __init__(self,
- mode = "bist",
- sdram_module = "MT48LC16M16",
- sdram_data_width = 32,
- bist_base = 0x0000000,
- bist_end = 0x0100000,
- bist_length = 1024,
- bist_random = False,
- bist_alternating = False,
- num_generators = 1,
- num_checkers = 1,
- access_pattern = None,
- **kwargs):
- assert mode in ["bist", "pattern"]
- assert not (mode == "pattern" and access_pattern is None)
-
- # SimSoC -----------------------------------------------------------------------------------
- SimSoC.__init__(self,
- with_sdram = True,
- sdram_module = sdram_module,
- sdram_data_width = sdram_data_width,
- **kwargs
- )
-
- # BIST/Pattern Generator / Checker ---------------------------------------------------------
- if mode == "pattern":
- make_generator = lambda: _LiteDRAMPatternGenerator(self.sdram.crossbar.get_port(), init=access_pattern)
- make_checker = lambda: _LiteDRAMPatternChecker(self.sdram.crossbar.get_port(), init=access_pattern)
- if mode == "bist":
- make_generator = lambda: _LiteDRAMBISTGenerator(self.sdram.crossbar.get_port())
- make_checker = lambda: _LiteDRAMBISTChecker(self.sdram.crossbar.get_port())
-
- generators = [make_generator() for _ in range(num_generators)]
- checkers = [make_checker() for _ in range(num_checkers)]
- self.submodules += generators + checkers
-
- if mode == "pattern":
- def bist_config(module):
- return []
-
- if not bist_alternating:
- address_set = set()
- for addr, _ in access_pattern:
- assert addr not in address_set, \
- "Duplicate address 0x%08x in access_pattern, write will overwrite previous value!" % addr
- address_set.add(addr)
- if mode == "bist":
- # Make sure that we perform at least one access
- bist_length = max(bist_length, self.sdram.controller.interface.data_width // 8)
- def bist_config(module):
- return [
- module.base.eq(bist_base),
- module.end.eq(bist_end),
- module.length.eq(bist_length),
- module.random_addr.eq(bist_random),
- ]
-
- assert not (bist_random and not bist_alternating), \
- "Write to random address may overwrite previously written data before reading!"
-
- # Check address correctness
- assert bist_end > bist_base
- assert bist_end <= 2**(len(generators[0].end)) - 1, "End address outside of range"
- bist_addr_range = bist_end - bist_base
- assert bist_addr_range > 0 and bist_addr_range & (bist_addr_range - 1) == 0, \
- "Length of the address range must be a power of 2"
-
- def combined_read(modules, signal, operator):
- sig = Signal()
- self.comb += sig.eq(reduce(operator, (getattr(m, signal) for m in modules)))
- return sig
-
- def combined_write(modules, signal):
- sig = Signal()
- self.comb += [getattr(m, signal).eq(sig) for m in modules]
- return sig
-
- # Sequencer --------------------------------------------------------------------------------
- class LiteDRAMCoreControl(Module, AutoCSR):
- def __init__(self):
- self.init_done = CSRStorage()
- self.init_error = CSRStorage()
- self.submodules.ddrctrl = ddrctrl = LiteDRAMCoreControl()
- self.add_csr("ddrctrl")
-
- display = Signal()
- finish = Signal()
- self.submodules.fsm = fsm = FSM(reset_state="WAIT-INIT")
- fsm.act("WAIT-INIT",
- If(self.ddrctrl.init_done.storage, # Written by CPU when initialization is done
- NextState("BIST-GENERATOR")
- )
- )
- if bist_alternating:
- # Force generators to wait for checkers and vice versa. Connect them in pairs, with each
- # unpaired connected to the first of the others.
- bist_connections = []
- for generator, checker in zip_longest(generators, checkers):
- g = generator or generators[0]
- c = checker or checkers[0]
- bist_connections += [
- g.run_cascade_in.eq(c.run_cascade_out),
- c.run_cascade_in.eq(g.run_cascade_out),
- ]
-
- fsm.act("BIST-GENERATOR",
- combined_write(generators + checkers, "start").eq(1),
- *bist_connections,
- *map(bist_config, generators + checkers),
- If(combined_read(checkers, "done", and_),
- NextState("DISPLAY")
- )
- )
- else:
- fsm.act("BIST-GENERATOR",
- combined_write(generators, "start").eq(1),
- *map(bist_config, generators),
- If(combined_read(generators, "done", and_),
- NextState("BIST-CHECKER")
- )
- )
- fsm.act("BIST-CHECKER",
- combined_write(checkers, "start").eq(1),
- *map(bist_config, checkers),
- If(combined_read(checkers, "done", and_),
- NextState("DISPLAY")
- )
- )
- fsm.act("DISPLAY",
- display.eq(1),
- NextState("FINISH")
- )
- fsm.act("FINISH",
- finish.eq(1)
- )
-
- # Simulation Results -----------------------------------------------------------------------
- def max_signal(signals):
- signals = iter(signals)
- s = next(signals)
- out = Signal(len(s))
- self.comb += out.eq(s)
- for curr in signals:
- prev = out
- out = Signal(max(len(prev), len(curr)))
- self.comb += If(prev > curr, out.eq(prev)).Else(out.eq(curr))
- return out
-
- generator_ticks = max_signal((g.ticks for g in generators))
- checker_errors = max_signal((c.errors for c in checkers))
- checker_ticks = max_signal((c.ticks for c in checkers))
-
- self.sync += [
- If(display,
- Display("BIST-GENERATOR ticks: %08d", generator_ticks),
- Display("BIST-CHECKER errors: %08d", checker_errors),
- Display("BIST-CHECKER ticks: %08d", checker_ticks),
- )
- ]
-
- # Simulation End ---------------------------------------------------------------------------
- end_timer = WaitTimer(2**16)
- self.submodules += end_timer
- self.comb += end_timer.wait.eq(finish)
- self.sync += If(end_timer.done, Finish())
-
-# Build --------------------------------------------------------------------------------------------
-
-def load_access_pattern(filename):
- with open(filename, newline="") as f:
- reader = csv.reader(f)
- access_pattern = [(int(addr, 0), int(data, 0)) for addr, data in reader]
- return access_pattern
-
-def main():
- parser = argparse.ArgumentParser(description="LiteDRAM Benchmark SoC Simulation")
- builder_args(parser)
- soc_sdram_args(parser)
- parser.add_argument("--threads", default=1, help="Set number of threads (default=1)")
- parser.add_argument("--sdram-module", default="MT48LC16M16", help="Select SDRAM chip")
- parser.add_argument("--sdram-data-width", default=32, help="Set SDRAM chip data width")
- parser.add_argument("--sdram-verbosity", default=0, help="Set SDRAM checker verbosity")
- parser.add_argument("--trace", action="store_true", help="Enable VCD tracing")
- parser.add_argument("--trace-start", default=0, help="Cycle to start VCD tracing")
- parser.add_argument("--trace-end", default=-1, help="Cycle to end VCD tracing")
- parser.add_argument("--opt-level", default="O0", help="Compilation optimization level")
- parser.add_argument("--bist-base", default="0x00000000", help="Base address of the test (default=0)")
- parser.add_argument("--bist-length", default="1024", help="Length of the test (default=1024)")
- parser.add_argument("--bist-random", action="store_true", help="Use random data during the test")
- parser.add_argument("--bist-alternating", action="store_true", help="Perform alternating writes/reads (WRWRWR... instead of WWW...RRR...)")
- parser.add_argument("--num-generators", default=1, help="Number of BIST generators")
- parser.add_argument("--num-checkers", default=1, help="Number of BIST checkers")
- parser.add_argument("--access-pattern", help="Load access pattern (address, data) from CSV (ignores --bist-*)")
- parser.add_argument("--log-level", default="info", help="Set logging verbosity",
- choices=["critical", "error", "warning", "info", "debug"])
- args = parser.parse_args()
-
- root_logger = logging.getLogger()
- root_logger.setLevel(getattr(logging, args.log_level.upper()))
-
- soc_kwargs = soc_sdram_argdict(args)
- builder_kwargs = builder_argdict(args)
-
- sim_config = SimConfig(default_clk="sys_clk")
- sim_config.add_module("serial2console", "serial")
-
- # Configuration --------------------------------------------------------------------------------
- soc_kwargs["uart_name"] = "sim"
- soc_kwargs["sdram_module"] = args.sdram_module
- soc_kwargs["sdram_data_width"] = int(args.sdram_data_width)
- soc_kwargs["sdram_verbosity"] = int(args.sdram_verbosity)
- soc_kwargs["bist_base"] = int(args.bist_base, 0)
- soc_kwargs["bist_length"] = int(args.bist_length, 0)
- soc_kwargs["bist_random"] = args.bist_random
- soc_kwargs["bist_alternating"] = args.bist_alternating
- soc_kwargs["num_generators"] = int(args.num_generators)
- soc_kwargs["num_checkers"] = int(args.num_checkers)
-
- if args.access_pattern:
- soc_kwargs["access_pattern"] = load_access_pattern(args.access_pattern)
-
- # SoC ------------------------------------------------------------------------------------------
- soc = LiteDRAMBenchmarkSoC(mode="pattern" if args.access_pattern else "bist", **soc_kwargs)
-
- # Build/Run ------------------------------------------------------------------------------------
- builder_kwargs["csr_csv"] = "csr.csv"
- builder = Builder(soc, **builder_kwargs)
- vns = builder.build(
- threads = args.threads,
- sim_config = sim_config,
- opt_level = args.opt_level,
- trace = args.trace,
- trace_start = int(args.trace_start),
- trace_end = int(args.trace_end)
- )
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-# ============================================================
-# Auto-generated on 2020-02-12 15:41:38 by ./gen_config.py
-# ------------------------------------------------------------
-# {'name_format': 'test_%d',
-# 'sdram_module': ['MT41K128M16', 'MT46V32M16', 'MT48LC16M16'],
-# 'sdram_data_width': [32],
-# 'bist_alternating': [True, False],
-# 'bist_length': [1, 1024],
-# 'bist_random': [True, False],
-# 'num_generators': [1, 3],
-# 'num_checkers': [1, 3],
-# 'access_pattern': ['access_pattern.csv']}
-# ============================================================
-{
- "test_0": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_1": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_2": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_3": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_4": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_5": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_6": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_7": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_8": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_9": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_10": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_11": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_12": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_13": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_14": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_15": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_16": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_17": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_18": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_19": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_20": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_21": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_22": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_23": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_24": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_25": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_26": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_27": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_28": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_29": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_30": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_31": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_32": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_33": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_34": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_35": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_36": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_37": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_38": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_39": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_40": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_41": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_42": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_43": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_44": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_45": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_46": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_47": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_48": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_49": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_50": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_51": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_52": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_53": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_54": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_55": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_56": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_57": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_58": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_59": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_60": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": true
- }
- },
- "test_61": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_62": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": true
- }
- },
- "test_63": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_64": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_65": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_66": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_67": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_68": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_69": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_70": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1,
- "bist_random": false
- }
- },
- "test_71": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "bist_length": 1024,
- "bist_random": false
- }
- },
- "test_72": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_73": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_74": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_75": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_76": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_77": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_78": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_79": {
- "sdram_module": "MT41K128M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_80": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_81": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_82": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_83": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_84": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_85": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_86": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_87": {
- "sdram_module": "MT46V32M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_88": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_89": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_90": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_91": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": true,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_92": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_93": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 1,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_94": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 1,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- },
- "test_95": {
- "sdram_module": "MT48LC16M16",
- "sdram_data_width": 32,
- "bist_alternating": false,
- "num_generators": 3,
- "num_checkers": 3,
- "access_pattern": {
- "pattern_file": "access_pattern.csv"
- }
- }
-}
+++ /dev/null
-# This file is Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2016 Tim 'mithro' Ansell <mithro@mithis.com>
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import os
-import random
-import itertools
-from functools import partial
-from operator import or_
-
-from migen import *
-
-
-def seed_to_data(seed, random=True, nbits=32):
- if nbits == 32:
- if random:
- return (seed * 0x31415979 + 1) & 0xffffffff
- else:
- return seed
- else:
- assert nbits%32 == 0
- data = 0
- for i in range(nbits//32):
- data = data << 32
- data |= seed_to_data(seed*nbits//32 + i, random, 32)
- return data
-
-
-@passive
-def timeout_generator(ticks):
- # raise exception after given timeout effectively stopping simulation
- # because of @passive, simulation can end even if this generator is still running
- for _ in range(ticks):
- yield
- raise TimeoutError("Timeout after %d ticks" % ticks)
-
-
-class NativePortDriver:
- """Generates sequences for reading/writing to LiteDRAMNativePort
-
- The write/read versions with wait_data=False are a cheap way to perform
- burst during which the port is being held locked, but this way all the
- data is being lost (would require separate coroutine to handle data).
- """
- def __init__(self, port):
- self.port = port
-
- def read(self, address, wait_data=True):
- yield self.port.cmd.valid.eq(1)
- yield self.port.cmd.we.eq(0)
- yield self.port.cmd.addr.eq(address)
- yield
- while (yield self.port.cmd.ready) == 0:
- yield
- yield self.port.cmd.valid.eq(0)
- yield
- if wait_data:
- while (yield self.port.rdata.valid) == 0:
- yield
- data = (yield self.port.rdata.data)
- yield self.port.rdata.ready.eq(1)
- yield
- yield self.port.rdata.ready.eq(0)
- yield
- return data
- else:
- yield self.port.rdata.ready.eq(1)
-
- def write(self, address, data, we=None, wait_data=True):
- if we is None:
- we = 2**self.port.wdata.we.nbits - 1
- yield self.port.cmd.valid.eq(1)
- yield self.port.cmd.we.eq(1)
- yield self.port.cmd.addr.eq(address)
- yield
- while (yield self.port.cmd.ready) == 0:
- yield
- yield self.port.cmd.valid.eq(0)
- yield self.port.wdata.valid.eq(1)
- yield self.port.wdata.data.eq(data)
- yield self.port.wdata.we.eq(we)
- yield
- if wait_data:
- while (yield self.port.wdata.ready) == 0:
- yield
- yield self.port.wdata.valid.eq(0)
- yield
-
-
-class CmdRequestRWDriver:
- """Simple driver for Endpoint(cmd_request_rw_layout())"""
- def __init__(self, req, i=0, ep_layout=True, rw_layout=True):
- self.req = req
- self.rw_layout = rw_layout # if False, omit is_* signals
- self.ep_layout = ep_layout # if False, omit endpoint signals (valid, etc.)
-
- # used to distinguish commands
- self.i = self.bank = self.row = self.col = i
-
- def request(self, char):
- # convert character to matching command invocation
- return {
- "w": self.write,
- "r": self.read,
- "W": partial(self.write, auto_precharge=True),
- "R": partial(self.read, auto_precharge=True),
- "a": self.activate,
- "p": self.precharge,
- "f": self.refresh,
- "_": self.nop,
- }[char]()
-
- def activate(self):
- yield from self._drive(valid=1, is_cmd=1, ras=1, a=self.row, ba=self.bank)
-
- def precharge(self, all_banks=False):
- a = 0 if not all_banks else (1 << 10)
- yield from self._drive(valid=1, is_cmd=1, ras=1, we=1, a=a, ba=self.bank)
-
- def refresh(self):
- yield from self._drive(valid=1, is_cmd=1, cas=1, ras=1, ba=self.bank)
-
- def write(self, auto_precharge=False):
- assert not (self.col & (1 << 10))
- col = self.col | (1 << 10) if auto_precharge else self.col
- yield from self._drive(valid=1, is_write=1, cas=1, we=1, a=col, ba=self.bank)
-
- def read(self, auto_precharge=False):
- assert not (self.col & (1 << 10))
- col = self.col | (1 << 10) if auto_precharge else self.col
- yield from self._drive(valid=1, is_read=1, cas=1, a=col, ba=self.bank)
-
- def nop(self):
- yield from self._drive()
-
- def _drive(self, **kwargs):
- signals = ["a", "ba", "cas", "ras", "we"]
- if self.rw_layout:
- signals += ["is_cmd", "is_read", "is_write"]
- if self.ep_layout:
- signals += ["valid", "first", "last"]
- for s in signals:
- yield getattr(self.req, s).eq(kwargs.get(s, 0))
- # drive ba even for nop, to be able to distinguish bank machines anyway
- if "ba" not in kwargs:
- yield self.req.ba.eq(self.bank)
-
-
-class DRAMMemory:
- def __init__(self, width, depth, init=[]):
- self.width = width
- self.depth = depth
- self.mem = []
- for d in init:
- self.mem.append(d)
- for _ in range(depth-len(init)):
- self.mem.append(0)
-
- # "W" enables write msgs, "R" - read msgs and "1" both
- self._debug = os.environ.get("DRAM_MEM_DEBUG", "0")
-
- def show_content(self):
- for addr in range(self.depth):
- print("0x{:08x}: 0x{:0{dwidth}x}".format(addr, self.mem[addr], dwidth=self.width//4))
-
- def _warn(self, address):
- if address > self.depth * self.width:
- print("! adr > 0x{:08x}".format(
- self.depth * self.width))
-
- def _write(self, address, data, we):
- mask = reduce(or_, [0xff << (8 * bit) for bit in range(self.width//8)
- if (we & (1 << bit)) != 0], 0)
- data = data & mask
- self.mem[address%self.depth] = data
- if self._debug in ["1", "W"]:
- print("W 0x{:08x}: 0x{:0{dwidth}x}".format(address, self.mem[address%self.depth],
- dwidth=self.width//4))
- self._warn(address)
-
- def _read(self, address):
- if self._debug in ["1", "R"]:
- print("R 0x{:08x}: 0x{:0{dwidth}x}".format(address, self.mem[address%self.depth],
- dwidth=self.width//4))
- self._warn(address)
- return self.mem[address%self.depth]
-
- @passive
- def read_handler(self, dram_port, rdata_valid_random=0):
- address = 0
- pending = 0
- prng = random.Random(42)
- yield dram_port.cmd.ready.eq(0)
- while True:
- yield dram_port.rdata.valid.eq(0)
- if pending:
- while prng.randrange(100) < rdata_valid_random:
- yield
- yield dram_port.rdata.valid.eq(1)
- yield dram_port.rdata.data.eq(self._read(address))
- yield
- yield dram_port.rdata.valid.eq(0)
- yield dram_port.rdata.data.eq(0)
- pending = 0
- elif (yield dram_port.cmd.valid):
- pending = not (yield dram_port.cmd.we)
- address = (yield dram_port.cmd.addr)
- if pending:
- yield dram_port.cmd.ready.eq(1)
- yield
- yield dram_port.cmd.ready.eq(0)
- yield
-
- @passive
- def write_handler(self, dram_port, wdata_ready_random=0):
- address = 0
- pending = 0
- prng = random.Random(42)
- yield dram_port.cmd.ready.eq(0)
- while True:
- yield dram_port.wdata.ready.eq(0)
- if pending:
- while (yield dram_port.wdata.valid) == 0:
- yield
- while prng.randrange(100) < wdata_ready_random:
- yield
- yield dram_port.wdata.ready.eq(1)
- yield
- self._write(address, (yield dram_port.wdata.data), (yield dram_port.wdata.we))
- yield dram_port.wdata.ready.eq(0)
- yield
- pending = 0
- yield
- elif (yield dram_port.cmd.valid):
- pending = (yield dram_port.cmd.we)
- address = (yield dram_port.cmd.addr)
- if pending:
- yield dram_port.cmd.ready.eq(1)
- yield
- yield dram_port.cmd.ready.eq(0)
- yield
-
-
-class MemoryTestDataMixin:
- @property
- def bist_test_data(self):
- data = {
- "8bit": dict(
- base = 2,
- end = 2 + 8, # (end - base) must be pow of 2
- length = 5,
- # 2 3 4 5 6 7=2+5
- expected = [0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00],
- ),
- "32bit": dict(
- base = 0x04,
- end = 0x04 + 8,
- length = 5 * 4,
- expected = [
- 0x00000000, # 0x00
- 0x00000000, # 0x04
- 0x00000001, # 0x08
- 0x00000002, # 0x0c
- 0x00000003, # 0x10
- 0x00000004, # 0x14
- 0x00000000, # 0x18
- 0x00000000, # 0x1c
- ],
- ),
- "64bit": dict(
- base = 0x10,
- end = 0x10 + 8,
- length = 5 * 8,
- expected = [
- 0x0000000000000000, # 0x00
- 0x0000000000000000, # 0x08
- 0x0000000000000000, # 0x10
- 0x0000000000000001, # 0x18
- 0x0000000000000002, # 0x20
- 0x0000000000000003, # 0x28
- 0x0000000000000004, # 0x30
- 0x0000000000000000, # 0x38
- ],
- ),
- "32bit_masked": dict(
- base = 0x04,
- end = 0x04 + 0x04, # TODO: fix address masking to be consistent
- length = 6 * 4,
- expected = [ # due to masking
- 0x00000000, # 0x00
- 0x00000004, # 0x04
- 0x00000005, # 0x08
- 0x00000002, # 0x0c
- 0x00000003, # 0x10
- 0x00000000, # 0x14
- 0x00000000, # 0x18
- 0x00000000, # 0x1c
- ],
- ),
- }
- data["32bit_long_sequential"] = dict(
- base = 16,
- end = 16 + 128,
- length = 64,
- expected = [0x00000000] * 128
- )
- expected = data["32bit_long_sequential"]["expected"]
- expected[16//4:(16 + 64)//4] = list(range(64//4))
- return data
-
- @property
- def pattern_test_data(self):
- data = {
- "8bit": dict(
- pattern=[
- # address, data
- (0x00, 0xaa),
- (0x05, 0xbb),
- (0x02, 0xcc),
- (0x07, 0xdd),
- ],
- expected=[
- # data, address
- 0xaa, # 0x00
- 0x00, # 0x01
- 0xcc, # 0x02
- 0x00, # 0x03
- 0x00, # 0x04
- 0xbb, # 0x05
- 0x00, # 0x06
- 0xdd, # 0x07
- ],
- ),
- "32bit": dict(
- pattern=[
- # address, data
- (0x00, 0xabadcafe),
- (0x07, 0xbaadf00d),
- (0x02, 0xcafefeed),
- (0x01, 0xdeadc0de),
- ],
- expected=[
- # data, address
- 0xabadcafe, # 0x00
- 0xdeadc0de, # 0x04
- 0xcafefeed, # 0x08
- 0x00000000, # 0x0c
- 0x00000000, # 0x10
- 0x00000000, # 0x14
- 0x00000000, # 0x18
- 0xbaadf00d, # 0x1c
- ],
- ),
- "64bit": dict(
- pattern=[
- # address, data
- (0x00, 0x0ddf00dbadc0ffee),
- (0x05, 0xabadcafebaadf00d),
- (0x02, 0xcafefeedfeedface),
- (0x07, 0xdeadc0debaadbeef),
- ],
- expected=[
- # data, address
- 0x0ddf00dbadc0ffee, # 0x00
- 0x0000000000000000, # 0x08
- 0xcafefeedfeedface, # 0x10
- 0x0000000000000000, # 0x18
- 0x0000000000000000, # 0x20
- 0xabadcafebaadf00d, # 0x28
- 0x0000000000000000, # 0x30
- 0xdeadc0debaadbeef, # 0x38
- ],
- ),
- "64bit_to_32bit": dict(
- pattern=[
- # address, data
- (0x00, 0x0d15ea5e00facade),
- (0x05, 0xabadcafe8badf00d),
- (0x01, 0xcafefeedbaadf00d),
- (0x02, 0xfee1deaddeadc0de),
- ],
- expected=[
- # data, word, address
- 0x00facade, # 0 0x00
- 0x0d15ea5e, # 1 0x04
- 0xbaadf00d, # 2 0x08
- 0xcafefeed, # 3 0x0c
- 0xdeadc0de, # 4 0x10
- 0xfee1dead, # 5 0x14
- 0x00000000, # 6 0x18
- 0x00000000, # 7 0x1c
- 0x00000000, # 8 0x20
- 0x00000000, # 9 0x24
- 0x8badf00d, # 10 0x28
- 0xabadcafe, # 11 0x2c
- 0x00000000, # 12 0x30
- ]
- ),
- "32bit_to_8bit": dict(
- pattern=[
- # address, data
- (0x00, 0x00112233),
- (0x05, 0x44556677),
- (0x01, 0x8899aabb),
- (0x02, 0xccddeeff),
- ],
- expected=[
- # data, address
- 0x33, # 0x00
- 0x22, # 0x01
- 0x11, # 0x02
- 0x00, # 0x03
- 0xbb, # 0x04
- 0xaa, # 0x05
- 0x99, # 0x06
- 0x88, # 0x07
- 0xff, # 0x08
- 0xee, # 0x09
- 0xdd, # 0x0a
- 0xcc, # 0x0b
- 0x00, # 0x0c
- 0x00, # 0x0d
- 0x00, # 0x0e
- 0x00, # 0x0f
- 0x00, # 0x10
- 0x00, # 0x11
- 0x00, # 0x12
- 0x00, # 0x13
- 0x77, # 0x14
- 0x66, # 0x15
- 0x55, # 0x16
- 0x44, # 0x17
- 0x00, # 0x18
- 0x00, # 0x19
- ]
- ),
- "8bit_to_32bit": dict(
- pattern=[
- # address, data
- (0x00, 0x00),
- (0x01, 0x11),
- (0x02, 0x22),
- (0x03, 0x33),
- (0x10, 0x44),
- (0x11, 0x55),
- (0x12, 0x66),
- (0x13, 0x77),
- (0x08, 0x88),
- (0x09, 0x99),
- (0x0a, 0xaa),
- (0x0b, 0xbb),
- (0x0c, 0xcc),
- (0x0d, 0xdd),
- (0x0e, 0xee),
- (0x0f, 0xff),
- ],
- expected=[
- # data, address
- 0x33221100, # 0x00
- 0x00000000, # 0x04
- 0xbbaa9988, # 0x08
- 0xffeeddcc, # 0x0c
- 0x77665544, # 0x10
- 0x00000000, # 0x14
- 0x00000000, # 0x18
- 0x00000000, # 0x1c
- ]
- ),
- "8bit_to_32bit_not_aligned": dict(
- pattern=[
- # address, data
- (0x00, 0x00),
- (0x05, 0x11),
- (0x0a, 0x22),
- (0x0f, 0x33),
- (0x1d, 0x44),
- (0x15, 0x55),
- (0x13, 0x66),
- (0x18, 0x77),
- ],
- expected=[
- # data, address
- 0x00000000, # 0x00
- 0x00001100, # 0x04
- 0x00220000, # 0x08
- 0x33000000, # 0x0c
- 0x66000000, # 0x10
- 0x00005500, # 0x14
- 0x00000077, # 0x18
- 0x00440000, # 0x1c
- ]
- ),
- "32bit_to_256bit": dict(
- pattern=[
- # address, data
- (0x00, 0x00000000),
- (0x01, 0x11111111),
- (0x02, 0x22222222),
- (0x03, 0x33333333),
- (0x04, 0x44444444),
- (0x05, 0x55555555),
- (0x06, 0x66666666),
- (0x07, 0x77777777),
- (0x10, 0x88888888),
- (0x11, 0x99999999),
- (0x12, 0xaaaaaaaa),
- (0x13, 0xbbbbbbbb),
- (0x14, 0xcccccccc),
- (0x15, 0xdddddddd),
- (0x16, 0xeeeeeeee),
- (0x17, 0xffffffff),
- ],
- expected=[
- # data, address
- 0x7777777766666666555555554444444433333333222222221111111100000000, # 0x00
- 0x0000000000000000000000000000000000000000000000000000000000000000, # 0x20
- 0xffffffffeeeeeeeeddddddddccccccccbbbbbbbbaaaaaaaa9999999988888888, # 0x40
- 0x0000000000000000000000000000000000000000000000000000000000000000, # 0x60
- ]
- ),
- "32bit_to_256bit_not_aligned": dict(
- pattern=[
- # address, data
- (0x00, 0x00000000),
- (0x01, 0x11111111),
- (0x02, 0x22222222),
- (0x03, 0x33333333),
- (0x04, 0x44444444),
- (0x05, 0x55555555),
- (0x06, 0x66666666),
- (0x07, 0x77777777),
- (0x14, 0x88888888),
- (0x15, 0x99999999),
- (0x16, 0xaaaaaaaa),
- (0x17, 0xbbbbbbbb),
- (0x18, 0xcccccccc),
- (0x19, 0xdddddddd),
- (0x1a, 0xeeeeeeee),
- (0x1b, 0xffffffff),
- ],
- expected=[
- # data, address
- 0x7777777766666666555555554444444433333333222222221111111100000000, # 0x00
- 0x0000000000000000000000000000000000000000000000000000000000000000, # 0x20
- 0xbbbbbbbbaaaaaaaa999999998888888800000000000000000000000000000000, # 0x40
- 0x00000000000000000000000000000000ffffffffeeeeeeeeddddddddcccccccc, # 0x60
- ]
- ),
- "32bit_not_aligned": dict(
- pattern=[
- # address, data
- (0x00, 0xabadcafe),
- (0x07, 0xbaadf00d),
- (0x02, 0xcafefeed),
- (0x01, 0xdeadc0de),
- ],
- expected=[
- # data, address
- 0xabadcafe, # 0x00
- 0xdeadc0de, # 0x04
- 0xcafefeed, # 0x08
- 0x00000000, # 0x0c
- 0x00000000, # 0x10
- 0x00000000, # 0x14
- 0x00000000, # 0x18
- 0xbaadf00d, # 0x1c
- ],
- ),
- "32bit_duplicates": dict(
- pattern=[
- # address, data
- (0x00, 0xabadcafe),
- (0x07, 0xbaadf00d),
- (0x00, 0xcafefeed),
- (0x07, 0xdeadc0de),
- ],
- expected=[
- # data, address
- 0xcafefeed, # 0x00
- 0x00000000, # 0x04
- 0x00000000, # 0x08
- 0x00000000, # 0x0c
- 0x00000000, # 0x10
- 0x00000000, # 0x14
- 0x00000000, # 0x18
- 0xdeadc0de, # 0x1c
- ],
- ),
- "32bit_sequential": dict(
- pattern=[
- # address, data
- (0x02, 0xabadcafe),
- (0x03, 0xbaadf00d),
- (0x04, 0xcafefeed),
- (0x05, 0xdeadc0de),
- ],
- expected=[
- # data, address
- 0x00000000, # 0x00
- 0x00000000, # 0x04
- 0xabadcafe, # 0x08
- 0xbaadf00d, # 0x0c
- 0xcafefeed, # 0x10
- 0xdeadc0de, # 0x14
- 0x00000000, # 0x18
- 0x00000000, # 0x1c
- ],
- ),
- "32bit_long_sequential": dict(pattern=[], expected=[0] * 64),
- }
-
- # 32bit_long_sequential
- for i in range(32):
- data["32bit_long_sequential"]["pattern"].append((i, 64 + i))
- data["32bit_long_sequential"]["expected"][i] = 64 + i
-
- def half_width(data, from_width):
- half_mask = 2**(from_width//2) - 1
- chunks = [(val & half_mask, (val >> from_width//2) & half_mask) for val in data]
- return list(itertools.chain.from_iterable(chunks))
-
- # down conversion
- data["64bit_to_16bit"] = dict(
- pattern = data["64bit_to_32bit"]["pattern"].copy(),
- expected = half_width(data["64bit_to_32bit"]["expected"], from_width=32),
- )
- data["64bit_to_8bit"] = dict(
- pattern = data["64bit_to_16bit"]["pattern"].copy(),
- expected = half_width(data["64bit_to_16bit"]["expected"], from_width=16),
- )
-
- # up conversion
- data["8bit_to_16bit"] = dict(
- pattern = data["8bit_to_32bit"]["pattern"].copy(),
- expected = half_width(data["8bit_to_32bit"]["expected"], from_width=32),
- )
- data["32bit_to_128bit"] = dict(
- pattern = data["32bit_to_256bit"]["pattern"].copy(),
- expected = half_width(data["32bit_to_256bit"]["expected"], from_width=256),
- )
- data["32bit_to_64bit"] = dict(
- pattern = data["32bit_to_128bit"]["pattern"].copy(),
- expected = half_width(data["32bit_to_128bit"]["expected"], from_width=128),
- )
-
- return data
+++ /dev/null
-#!/usr/bin/env python3
-
-import random
-import argparse
-
-def main():
- description = """
- Generate random access pattern for LiteDRAM Pattern Generator/Checker.
-
- Each address in range [base, base+length) will be accessed only once, but in random order.
- This ensures that no data will be overwritten.
- """
- parser = argparse.ArgumentParser(description=description)
- parser.add_argument("base", help="Base address")
- parser.add_argument("length", help="Number of (address, data) pairs")
- parser.add_argument("data_width", help="Width of data (used to determine max value)")
- parser.add_argument("--seed", help="Use given random seed (int)")
- args = parser.parse_args()
-
- if args.seed:
- random.seed(int(args.seed, 0))
-
- base = int(args.base, 0)
- length = int(args.length, 0)
- data_width = int(args.data_width, 0)
-
- address = list(range(length))
- random.shuffle(address)
- data = [random.randrange(0, 2**data_width) for _ in range(length)]
-
- for a, d in zip(address, data):
- print("0x{:08x}, 0x{:08x}".format(a, d))
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-#!/usr/bin/env python3
-
-import sys
-import json
-import pprint
-import argparse
-import datetime
-import itertools
-
-
-defaults = {
- "--sdram-module": [
- "IS42S16160",
- "IS42S16320",
- "MT48LC4M16",
- "MT48LC16M16",
- "AS4C16M16",
- "AS4C32M16",
- "AS4C32M8",
- "M12L64322A",
- "M12L16161A",
- "MT46V32M16",
- "MT46H32M16",
- "MT46H32M32",
- "MT47H128M8",
- "MT47H32M16",
- "MT47H64M16",
- "P3R1GE4JGF",
- "MT41K64M16",
- "MT41J128M16",
- "MT41K128M16",
- "MT41J256M16",
- "MT41K256M16",
- "K4B1G0446F",
- "K4B2G1646F",
- "H5TC4G63CFR",
- "IS43TR16128B",
- "MT8JTF12864",
- "MT8KTF51264",
- #"MT18KSF1G72HZ",
- #"AS4C256M16D3A",
- #"MT16KTF1G64HZ",
- #"EDY4016A",
- #"MT40A1G8",
- #"MT40A512M16",
- ],
- "--sdram-data-width": [32],
- "--bist-alternating": [True, False],
- "--bist-length": [1, 4096],
- "--bist-random": [True, False],
- "--num-generators": [1],
- "--num-checkers": [1],
- "--access-pattern": ["access_pattern.csv"]
-}
-
-
-def convert_string_arg(args, arg, type):
- map_func = {
- bool: lambda s: {"false": False, "true": True}[s.lower()],
- int: lambda s: int(s, 0),
- }
- setattr(args, arg, [map_func[type](val) if not isinstance(val, type) else val for val in getattr(args, arg)])
-
-
-def generate_header(args):
- header = "Auto-generated on {} by {}".format(
- datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- sys.argv[0],
- )
- #args_str = pprint.pformat(vars(args), sort_dicts=False) # FIXME: python3.7 specific?
- args_str = pprint.pformat(vars(args))
- arg_lines = args_str.split("\n")
- lines = [60*"=", header, 60*"-", *arg_lines, 60*"="]
- return "\n".join("# " + line for line in lines)
-
-
-def main():
- parser = argparse.ArgumentParser(description="Generate configuration for all possible argument combinations.",
- formatter_class=argparse.ArgumentDefaultsHelpFormatter)
- parser.add_argument("--name-format", default="test_%d", help="Name format for i-th test")
- for name, default in defaults.items():
- parser.add_argument(name, nargs="+", default=default, help="%s options" % name)
- args = parser.parse_args()
-
- # Make sure not to write those as strings
- convert_string_arg(args, "sdram_data_width", int)
- convert_string_arg(args, "bist_alternating", bool)
- convert_string_arg(args, "bist_length", int)
- convert_string_arg(args, "bist_random", bool)
- convert_string_arg(args, "num_generators", int)
- convert_string_arg(args, "num_checkers", int)
-
- common_args = ("sdram_module", "sdram_data_width", "bist_alternating", "num_generators", "num_checkers")
- generated_pattern_args = ("bist_length", "bist_random")
- custom_pattern_args = ("access_pattern", )
-
- def generated_pattern_configuration(values):
- config = dict(zip(common_args + generated_pattern_args, values))
- # Move access pattern parameters deeper
- config["access_pattern"] = {
- "bist_length": config.pop("bist_length"),
- "bist_random": config.pop("bist_random"),
- }
- return config
-
- def custom_pattern_configuration(values):
- config = dict(zip(common_args + custom_pattern_args, values))
- # "rename" --access-pattern to access_pattern.pattern_file due to name difference between
- # command line args and run_benchmarks.py configuration format
- config["access_pattern"] = {
- "pattern_file": config.pop("access_pattern"),
- }
- return config
-
- # Iterator over the product of given command line arguments
- def args_product(names):
- return itertools.product(*(getattr(args, name) for name in names))
-
- generated_pattern_iter = zip(itertools.repeat(generated_pattern_configuration), args_product(common_args + generated_pattern_args))
- custom_pattern_iter = zip(itertools.repeat(custom_pattern_configuration), args_product(common_args + custom_pattern_args))
-
- i = 0
- configurations = {}
- for config_generator, values in itertools.chain(generated_pattern_iter, custom_pattern_iter):
- config = config_generator(values)
- # Ignore unsupported case: bist_random=True and bist_alternating=False
- if config["access_pattern"].get("bist_random", False) and not config["bist_alternating"]:
- continue
- configurations[args.name_format % i] = config
- i += 1
-
- json_str = json.dumps(configurations, indent=4)
- print(generate_header(args))
- print(json_str)
-
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-#ifndef __GENERATED_SDRAM_PHY_H
-#define __GENERATED_SDRAM_PHY_H
-#include <hw/common.h>
-#include <generated/csr.h>
-
-#define DFII_CONTROL_SEL 0x01
-#define DFII_CONTROL_CKE 0x02
-#define DFII_CONTROL_ODT 0x04
-#define DFII_CONTROL_RESET_N 0x08
-
-#define DFII_COMMAND_CS 0x01
-#define DFII_COMMAND_WE 0x02
-#define DFII_COMMAND_CAS 0x04
-#define DFII_COMMAND_RAS 0x08
-#define DFII_COMMAND_WRDATA 0x10
-#define DFII_COMMAND_RDDATA 0x20
-
-#define SDRAM_PHY_K7DDRPHY
-#define SDRAM_PHY_PHASES 4
-#define SDRAM_PHY_WRITE_LEVELING_CAPABLE
-#define SDRAM_PHY_READ_LEVELING_CAPABLE
-#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/2
-#define SDRAM_PHY_DELAYS 32
-#define SDRAM_PHY_BITSLIPS 16
-
-static void cdelay(int i);
-
-__attribute__((unused)) static void command_p0(int cmd)
-{
- sdram_dfii_pi0_command_write(cmd);
- sdram_dfii_pi0_command_issue_write(1);
-}
-__attribute__((unused)) static void command_p1(int cmd)
-{
- sdram_dfii_pi1_command_write(cmd);
- sdram_dfii_pi1_command_issue_write(1);
-}
-__attribute__((unused)) static void command_p2(int cmd)
-{
- sdram_dfii_pi2_command_write(cmd);
- sdram_dfii_pi2_command_issue_write(1);
-}
-__attribute__((unused)) static void command_p3(int cmd)
-{
- sdram_dfii_pi3_command_write(cmd);
- sdram_dfii_pi3_command_issue_write(1);
-}
-
-
-#define sdram_dfii_pird_address_write(X) sdram_dfii_pi1_address_write(X)
-#define sdram_dfii_piwr_address_write(X) sdram_dfii_pi1_address_write(X)
-#define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi1_baddress_write(X)
-#define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi1_baddress_write(X)
-#define command_prd(X) command_p1(X)
-#define command_pwr(X) command_p1(X)
-
-#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
-
-const unsigned long sdram_dfii_pix_wrdata_addr[SDRAM_PHY_PHASES] = {
- CSR_SDRAM_DFII_PI0_WRDATA_ADDR,
- CSR_SDRAM_DFII_PI1_WRDATA_ADDR,
- CSR_SDRAM_DFII_PI2_WRDATA_ADDR,
- CSR_SDRAM_DFII_PI3_WRDATA_ADDR
-};
-
-const unsigned long sdram_dfii_pix_rddata_addr[SDRAM_PHY_PHASES] = {
- CSR_SDRAM_DFII_PI0_RDDATA_ADDR,
- CSR_SDRAM_DFII_PI1_RDDATA_ADDR,
- CSR_SDRAM_DFII_PI2_RDDATA_ADDR,
- CSR_SDRAM_DFII_PI3_RDDATA_ADDR
-};
-
-#define DDRX_MR1 6
-
-static void init_sequence(void)
-{
- /* Release reset */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(0);
- sdram_dfii_control_write(DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
- cdelay(50000);
-
- /* Bring CKE high */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(0);
- sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
- cdelay(10000);
-
- /* Load Mode Register 2, CWL=6 */
- sdram_dfii_pi0_address_write(0x208);
- sdram_dfii_pi0_baddress_write(2);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 3 */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(3);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 1 */
- sdram_dfii_pi0_address_write(0x6);
- sdram_dfii_pi0_baddress_write(1);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 0, CL=7, BL=8 */
- sdram_dfii_pi0_address_write(0x930);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
- cdelay(200);
-
- /* ZQ Calibration */
- sdram_dfii_pi0_address_write(0x400);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_WE|DFII_COMMAND_CS);
- cdelay(200);
-
-}
-#endif
+++ /dev/null
-dfii_control_sel = 0x01
-dfii_control_cke = 0x02
-dfii_control_odt = 0x04
-dfii_control_reset_n = 0x08
-
-dfii_command_cs = 0x01
-dfii_command_we = 0x02
-dfii_command_cas = 0x04
-dfii_command_ras = 0x08
-dfii_command_wrdata = 0x10
-dfii_command_rddata = 0x20
-
-ddrx_mr1 = 0x6
-
-init_sequence = [
- ("Release reset", 0, 0, dfii_control_odt|dfii_control_reset_n, 50000),
- ("Bring CKE high", 0, 0, dfii_control_cke|dfii_control_odt|dfii_control_reset_n, 10000),
- ("Load Mode Register 2, CWL=6", 520, 2, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 3", 0, 3, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 1", 6, 1, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 0, CL=7, BL=8", 2352, 0, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 200),
- ("ZQ Calibration", 1024, 0, dfii_command_we|dfii_command_cs, 200),
-]
+++ /dev/null
-#ifndef __GENERATED_SDRAM_PHY_H
-#define __GENERATED_SDRAM_PHY_H
-#include <hw/common.h>
-#include <generated/csr.h>
-
-#define DFII_CONTROL_SEL 0x01
-#define DFII_CONTROL_CKE 0x02
-#define DFII_CONTROL_ODT 0x04
-#define DFII_CONTROL_RESET_N 0x08
-
-#define DFII_COMMAND_CS 0x01
-#define DFII_COMMAND_WE 0x02
-#define DFII_COMMAND_CAS 0x04
-#define DFII_COMMAND_RAS 0x08
-#define DFII_COMMAND_WRDATA 0x10
-#define DFII_COMMAND_RDDATA 0x20
-
-#define SDRAM_PHY_USDDRPHY
-#define SDRAM_PHY_PHASES 4
-#define SDRAM_PHY_WRITE_LEVELING_CAPABLE
-#define SDRAM_PHY_WRITE_LEVELING_REINIT
-#define SDRAM_PHY_READ_LEVELING_CAPABLE
-#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/2
-#define SDRAM_PHY_DELAYS 512
-#define SDRAM_PHY_BITSLIPS 16
-
-static void cdelay(int i);
-
-__attribute__((unused)) static void command_p0(int cmd)
-{
- sdram_dfii_pi0_command_write(cmd);
- sdram_dfii_pi0_command_issue_write(1);
-}
-__attribute__((unused)) static void command_p1(int cmd)
-{
- sdram_dfii_pi1_command_write(cmd);
- sdram_dfii_pi1_command_issue_write(1);
-}
-__attribute__((unused)) static void command_p2(int cmd)
-{
- sdram_dfii_pi2_command_write(cmd);
- sdram_dfii_pi2_command_issue_write(1);
-}
-__attribute__((unused)) static void command_p3(int cmd)
-{
- sdram_dfii_pi3_command_write(cmd);
- sdram_dfii_pi3_command_issue_write(1);
-}
-
-
-#define sdram_dfii_pird_address_write(X) sdram_dfii_pi1_address_write(X)
-#define sdram_dfii_piwr_address_write(X) sdram_dfii_pi2_address_write(X)
-#define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi1_baddress_write(X)
-#define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi2_baddress_write(X)
-#define command_prd(X) command_p1(X)
-#define command_pwr(X) command_p2(X)
-
-#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
-
-const unsigned long sdram_dfii_pix_wrdata_addr[SDRAM_PHY_PHASES] = {
- CSR_SDRAM_DFII_PI0_WRDATA_ADDR,
- CSR_SDRAM_DFII_PI1_WRDATA_ADDR,
- CSR_SDRAM_DFII_PI2_WRDATA_ADDR,
- CSR_SDRAM_DFII_PI3_WRDATA_ADDR
-};
-
-const unsigned long sdram_dfii_pix_rddata_addr[SDRAM_PHY_PHASES] = {
- CSR_SDRAM_DFII_PI0_RDDATA_ADDR,
- CSR_SDRAM_DFII_PI1_RDDATA_ADDR,
- CSR_SDRAM_DFII_PI2_RDDATA_ADDR,
- CSR_SDRAM_DFII_PI3_RDDATA_ADDR
-};
-
-#define DDRX_MR1 769
-
-static void init_sequence(void)
-{
- /* Release reset */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(0);
- sdram_dfii_control_write(DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
- cdelay(50000);
-
- /* Bring CKE high */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(0);
- sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
- cdelay(10000);
-
- /* Load Mode Register 3 */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(3);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 6 */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(6);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 5 */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(5);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 4 */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(4);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 2, CWL=9 */
- sdram_dfii_pi0_address_write(0x200);
- sdram_dfii_pi0_baddress_write(2);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 1 */
- sdram_dfii_pi0_address_write(0x301);
- sdram_dfii_pi0_baddress_write(1);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register 0, CL=11, BL=8 */
- sdram_dfii_pi0_address_write(0x110);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
- cdelay(200);
-
- /* ZQ Calibration */
- sdram_dfii_pi0_address_write(0x400);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_WE|DFII_COMMAND_CS);
- cdelay(200);
-
-}
-#endif
+++ /dev/null
-dfii_control_sel = 0x01
-dfii_control_cke = 0x02
-dfii_control_odt = 0x04
-dfii_control_reset_n = 0x08
-
-dfii_command_cs = 0x01
-dfii_command_we = 0x02
-dfii_command_cas = 0x04
-dfii_command_ras = 0x08
-dfii_command_wrdata = 0x10
-dfii_command_rddata = 0x20
-
-ddrx_mr1 = 0x301
-
-init_sequence = [
- ("Release reset", 0, 0, dfii_control_odt|dfii_control_reset_n, 50000),
- ("Bring CKE high", 0, 0, dfii_control_cke|dfii_control_odt|dfii_control_reset_n, 10000),
- ("Load Mode Register 3", 0, 3, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 6", 0, 6, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 5", 0, 5, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 4", 0, 4, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 2, CWL=9", 512, 2, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 1", 769, 1, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register 0, CL=11, BL=8", 272, 0, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 200),
- ("ZQ Calibration", 1024, 0, dfii_command_we|dfii_command_cs, 200),
-]
+++ /dev/null
-#ifndef __GENERATED_SDRAM_PHY_H
-#define __GENERATED_SDRAM_PHY_H
-#include <hw/common.h>
-#include <generated/csr.h>
-
-#define DFII_CONTROL_SEL 0x01
-#define DFII_CONTROL_CKE 0x02
-#define DFII_CONTROL_ODT 0x04
-#define DFII_CONTROL_RESET_N 0x08
-
-#define DFII_COMMAND_CS 0x01
-#define DFII_COMMAND_WE 0x02
-#define DFII_COMMAND_CAS 0x04
-#define DFII_COMMAND_RAS 0x08
-#define DFII_COMMAND_WRDATA 0x10
-#define DFII_COMMAND_RDDATA 0x20
-
-#define SDRAM_PHY_GENSDRPHY
-#define SDRAM_PHY_PHASES 1
-
-static void cdelay(int i);
-
-__attribute__((unused)) static void command_p0(int cmd)
-{
- sdram_dfii_pi0_command_write(cmd);
- sdram_dfii_pi0_command_issue_write(1);
-}
-
-
-#define sdram_dfii_pird_address_write(X) sdram_dfii_pi0_address_write(X)
-#define sdram_dfii_piwr_address_write(X) sdram_dfii_pi0_address_write(X)
-#define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi0_baddress_write(X)
-#define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi0_baddress_write(X)
-#define command_prd(X) command_p0(X)
-#define command_pwr(X) command_p0(X)
-
-#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
-
-const unsigned long sdram_dfii_pix_wrdata_addr[SDRAM_PHY_PHASES] = {
- CSR_SDRAM_DFII_PI0_WRDATA_ADDR
-};
-
-const unsigned long sdram_dfii_pix_rddata_addr[SDRAM_PHY_PHASES] = {
- CSR_SDRAM_DFII_PI0_RDDATA_ADDR
-};
-
-static void init_sequence(void)
-{
- /* Bring CKE high */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(0);
- sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
- cdelay(20000);
-
- /* Precharge All */
- sdram_dfii_pi0_address_write(0x400);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Load Mode Register / Reset DLL, CL=2, BL=1 */
- sdram_dfii_pi0_address_write(0x120);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
- cdelay(200);
-
- /* Precharge All */
- sdram_dfii_pi0_address_write(0x400);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-
- /* Auto Refresh */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS);
- cdelay(4);
-
- /* Auto Refresh */
- sdram_dfii_pi0_address_write(0x0);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS);
- cdelay(4);
-
- /* Load Mode Register / CL=2, BL=1 */
- sdram_dfii_pi0_address_write(0x20);
- sdram_dfii_pi0_baddress_write(0);
- command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
- cdelay(200);
-
-}
-#endif
+++ /dev/null
-dfii_control_sel = 0x01
-dfii_control_cke = 0x02
-dfii_control_odt = 0x04
-dfii_control_reset_n = 0x08
-
-dfii_command_cs = 0x01
-dfii_command_we = 0x02
-dfii_command_cas = 0x04
-dfii_command_ras = 0x08
-dfii_command_wrdata = 0x10
-dfii_command_rddata = 0x20
-
-init_sequence = [
- ("Bring CKE high", 0, 0, dfii_control_cke|dfii_control_odt|dfii_control_reset_n, 20000),
- ("Precharge All", 1024, 0, dfii_command_ras|dfii_command_we|dfii_command_cs, 0),
- ("Load Mode Register / Reset DLL, CL=2, BL=1", 288, 0, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 200),
- ("Precharge All", 1024, 0, dfii_command_ras|dfii_command_we|dfii_command_cs, 0),
- ("Auto Refresh", 0, 0, dfii_command_ras|dfii_command_cas|dfii_command_cs, 4),
- ("Auto Refresh", 0, 0, dfii_command_ras|dfii_command_cas|dfii_command_cs, 4),
- ("Load Mode Register / CL=2, BL=1", 32, 0, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, 200),
-]
+++ /dev/null
-#!/usr/bin/env python3
-
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-# Limitations/TODO
-# - add configurable sdram_clk_freq - using hardcoded value now
-# - sdram_controller_data_width - try to expose the value from litex_sim to avoid duplicated code
-
-import os
-import re
-import sys
-import json
-import argparse
-import datetime
-import subprocess
-from collections import defaultdict, namedtuple
-
-import yaml
-try:
- import numpy as np
- import pandas as pd
- import matplotlib
- from matplotlib.ticker import FuncFormatter, PercentFormatter, ScalarFormatter
- _summary = True
-except ImportError as e:
- _summary = False
- print("[WARNING] Results summary not available:", e, file=sys.stderr)
-
-from litex.tools.litex_sim import get_sdram_phy_settings, sdram_module_nphases
-from litedram import modules as litedram_modules
-from litedram.common import Settings as _Settings
-
-from test import benchmark
-
-# Benchmark configuration --------------------------------------------------------------------------
-
-class Settings(_Settings):
- def as_dict(self):
- d = dict()
- for attr, value in vars(self).items():
- if attr == "self" or attr.startswith("_"):
- continue
- if isinstance(value, Settings):
- value = value.as_dict()
- d[attr] = value
- return d
-
-
-class GeneratedAccess(Settings):
- def __init__(self, bist_length, bist_random):
- self.set_attributes(locals())
-
- @property
- def length(self):
- return self.bist_length
-
- def as_args(self):
- args = ["--bist-length=%d" % self.bist_length]
- if self.bist_random:
- args.append("--bist-random")
- return args
-
-
-class CustomAccess(Settings):
- def __init__(self, pattern_file):
- self.set_attributes(locals())
-
- @property
- def pattern(self):
- # We have to load the file to know pattern length, cache it when requested
- if not hasattr(self, "_pattern"):
- path = self.pattern_file
- if not os.path.isabs(path):
- benchmark_dir = os.path.dirname(benchmark.__file__)
- path = os.path.join(benchmark_dir, path)
- self._pattern = benchmark.load_access_pattern(path)
- return self._pattern
-
- @property
- def length(self):
- return len(self.pattern)
-
- def as_args(self):
- return ["--access-pattern=%s" % self.pattern_file]
-
-
-class BenchmarkConfiguration(Settings):
- def __init__(self, name, sdram_module, sdram_data_width, bist_alternating,
- num_generators, num_checkers, access_pattern):
- self.set_attributes(locals())
-
- def as_args(self):
- args = [
- "--sdram-module=%s" % self.sdram_module,
- "--sdram-data-width=%d" % self.sdram_data_width,
- "--num-generators=%d" % self.num_generators,
- "--num-checkers=%d" % self.num_checkers,
- ]
- if self.bist_alternating:
- args.append("--bist-alternating")
- args += self.access_pattern.as_args()
- return args
-
- def __eq__(self, other):
- if not isinstance(other, BenchmarkConfiguration):
- return NotImplemented
- return self.as_dict() == other.as_dict()
-
- @property
- def length(self):
- return self.access_pattern.length
-
- @classmethod
- def from_dict(cls, d):
- access_cls = CustomAccess if "pattern_file" in d["access_pattern"] else GeneratedAccess
- d["access_pattern"] = access_cls(**d["access_pattern"])
- return cls(**d)
-
- @classmethod
- def load_yaml(cls, yaml_file):
- with open(yaml_file) as f:
- description = yaml.safe_load(f)
- configs = []
- for name, desc in description.items():
- desc["name"] = name
- configs.append(cls.from_dict(desc))
- return configs
-
- def __repr__(self):
- return "BenchmarkConfiguration(%s)" % self.as_dict()
-
- @property
- def sdram_clk_freq(self):
- return 100e6 # FIXME: Value of 100MHz is hardcoded in litex_sim
-
- @property
- def sdram_memtype(self):
- # Use values from module class (no need to instantiate it)
- sdram_module_cls = getattr(litedram_modules, self.sdram_module)
- return sdram_module_cls.memtype
-
- @property
- def sdram_controller_data_width(self):
- nphases = sdram_module_nphases[self.sdram_memtype]
- dfi_databits = self.sdram_data_width * (1 if self.sdram_memtype == "SDR" else 2)
- return dfi_databits * nphases
-
-# Benchmark results --------------------------------------------------------------------------------
-
-# Constructs python regex named group
-def ng(name, regex):
- return r"(?P<{}>{})".format(name, regex)
-
-
-def _compiled_pattern(stage, var):
- pattern_fmt = r"{stage}\s+{var}:\s+{value}"
- pattern = pattern_fmt.format(
- stage = stage,
- var = var,
- value = ng("value", "[0-9]+"),
- )
- return re.compile(pattern)
- result = re.search(pattern, benchmark_output)
-
-
-class BenchmarkResult:
- # Pre-compiled patterns for all benchmarks
- patterns = {
- "generator_ticks": _compiled_pattern("BIST-GENERATOR", "ticks"),
- "checker_errors": _compiled_pattern("BIST-CHECKER", "errors"),
- "checker_ticks": _compiled_pattern("BIST-CHECKER", "ticks"),
- }
-
- @staticmethod
- def find(pattern, output):
- result = pattern.search(output)
- assert result is not None, \
- "Could not find pattern {} in output".format(pattern)
- return int(result.group("value"))
-
- def __init__(self, output):
- self._output = output
- for attr, pattern in self.patterns.items():
- setattr(self, attr, self.find(pattern, output))
-
- def __repr__(self):
- d = {attr: getattr(self, attr) for attr in self.patterns.keys()}
- return "BenchmarkResult(%s)" % d
-
-# Results summary ----------------------------------------------------------------------------------
-
-def human_readable(value):
- binary_prefixes = ["", "k", "M", "G", "T"]
- mult = 1.0
- for prefix in binary_prefixes:
- if value * mult < 1024:
- break
- mult /= 1024
- return mult, prefix
-
-
-def clocks_fmt(clocks):
- return "{:d} clk".format(int(clocks))
-
-
-def bandwidth_fmt(bw):
- mult, prefix = human_readable(bw)
- return "{:.1f} {}bps".format(bw * mult, prefix)
-
-
-def efficiency_fmt(eff):
- return "{:.1f} %".format(eff * 100)
-
-
-def get_git_file_path(filename):
- cmd = ["git", "ls-files", "--full-name", filename]
- proc = subprocess.run(cmd, stdout=subprocess.PIPE, cwd=os.path.dirname(__file__))
- return proc.stdout.decode().strip() if proc.returncode == 0 else ""
-
-
-def get_git_revision_hash(short=False):
- short = ["--short"] if short else []
- cmd = ["git", "rev-parse", *short, "HEAD"]
- proc = subprocess.run(cmd, stdout=subprocess.PIPE, cwd=os.path.dirname(__file__))
- return proc.stdout.decode().strip() if proc.returncode == 0 else ""
-
-
-class ResultsSummary:
- def __init__(self, run_data, plots_dir="plots"):
- self.plots_dir = plots_dir
-
- # Because .sdram_controller_data_width may fail for unimplemented modules
- def except_none(func):
- try:
- return func()
- except:
- return None
-
- # Gather results into tabular data
- column_mappings = {
- "name": lambda d: d.config.name,
- "sdram_module": lambda d: d.config.sdram_module,
- "sdram_data_width": lambda d: d.config.sdram_data_width,
- "bist_alternating": lambda d: d.config.bist_alternating,
- "num_generators": lambda d: d.config.num_generators,
- "num_checkers": lambda d: d.config.num_checkers,
- "bist_length": lambda d: getattr(d.config.access_pattern, "bist_length", None),
- "bist_random": lambda d: getattr(d.config.access_pattern, "bist_random", None),
- "pattern_file": lambda d: getattr(d.config.access_pattern, "pattern_file", None),
- "length": lambda d: d.config.length,
- "generator_ticks": lambda d: getattr(d.result, "generator_ticks", None), # None means benchmark failure
- "checker_errors": lambda d: getattr(d.result, "checker_errors", None),
- "checker_ticks": lambda d: getattr(d.result, "checker_ticks", None),
- "ctrl_data_width": lambda d: except_none(lambda: d.config.sdram_controller_data_width),
- "sdram_memtype": lambda d: except_none(lambda: d.config.sdram_memtype),
- "clk_freq": lambda d: d.config.sdram_clk_freq,
- }
- columns = {name: [mapping(data) for data in run_data] for name, mapping, in column_mappings.items()}
- self._df = df = pd.DataFrame(columns)
-
- # Replace None with NaN
- df.fillna(value=np.nan, inplace=True)
-
- # Compute other metrics based on ticks and configuration parameters
- df["clk_period"] = 1 / df["clk_freq"]
- # Bandwidth is the number of bits per time
- # in case with N generators/checkers we actually process N times more data
- df["write_bandwidth"] = (8 * df["length"] * df["num_generators"]) / (df["generator_ticks"] * df["clk_period"])
- df["read_bandwidth"] = (8 * df["length"] * df["num_checkers"]) / (df["checker_ticks"] * df["clk_period"])
-
- # Efficiency calculated as number of write/read commands to number of cycles spent on writing/reading (ticks)
- # for multiple generators/checkers multiply by their number
- df["cmd_count"] = df["length"] / (df["ctrl_data_width"] / 8)
- df["write_efficiency"] = df["cmd_count"] * df["num_generators"] / df["generator_ticks"]
- df["read_efficiency"] = df["cmd_count"] * df["num_checkers"] / df["checker_ticks"]
-
- df["write_latency"] = df[df["bist_length"] == 1]["generator_ticks"]
- df["read_latency"] = df[df["bist_length"] == 1]["checker_ticks"]
-
- # Boolean distinction between latency benchmarks and sequence benchmarks,
- # as thier results differ significanly
- df["is_latency"] = ~pd.isna(df["write_latency"])
- assert (df["is_latency"] == ~pd.isna(df["read_latency"])).all(), \
- "write_latency and read_latency should both have a value or both be NaN"
-
- # Data formatting for text summary
- self.text_formatters = {
- "write_bandwidth": bandwidth_fmt,
- "read_bandwidth": bandwidth_fmt,
- "write_efficiency": efficiency_fmt,
- "read_efficiency": efficiency_fmt,
- "write_latency": clocks_fmt,
- "read_latency": clocks_fmt,
- }
-
- # Data formatting for plot summary
- self.plot_xticks_formatters = {
- "write_bandwidth": FuncFormatter(lambda value, pos: bandwidth_fmt(value)),
- "read_bandwidth": FuncFormatter(lambda value, pos: bandwidth_fmt(value)),
- "write_efficiency": PercentFormatter(1.0),
- "read_efficiency": PercentFormatter(1.0),
- "write_latency": ScalarFormatter(),
- "read_latency": ScalarFormatter(),
- }
-
- def df(self, ok=True, failures=False):
- is_failure = lambda df: pd.isna(df["generator_ticks"]) | pd.isna(df["checker_ticks"]) | pd.isna(df["checker_errors"])
- df = self._df
- if not ok: # remove ok
- is_ok = ~is_failure(df)
- df = df[~is_ok]
- if not failures: # remove failures
- df = df[~is_failure(df)]
- return df
-
- def header(self, text):
- return "===> {}".format(text)
-
- def print_df(self, title, df):
- # Make sure all data will be shown
- with pd.option_context("display.max_rows", None, "display.max_columns", None, "display.width", None):
- print(self.header(title + ":"))
- print(df)
-
- def get_summary(self, df, mask=None, columns=None, column_formatting=None, sort_kwargs=None):
- # Work on a copy
- df = df.copy()
-
- if sort_kwargs is not None:
- df = df.sort_values(**sort_kwargs)
-
- if column_formatting is not None:
- for column, mapping in column_formatting.items():
- old = "_{}".format(column)
- df[old] = df[column].copy()
- df[column] = df[column].map(lambda value: mapping(value) if not pd.isna(value) else value)
-
- df = df[mask] if mask is not None else df
- df = df[columns] if columns is not None else df
-
- return df
-
- def text_summary(self):
- for title, df in self.groupped_results():
- self.print_df(title, df)
- print()
-
- def html_summary(self, output_dir):
- import jinja2
-
- tables = {}
- names = {}
- for title, df in self.groupped_results():
- table_id = title.lower().replace(" ", "_")
-
- tables[table_id] = df.to_html(table_id=table_id, border=0)
- names[table_id] = title
-
- template_dir = os.path.join(os.path.dirname(__file__), "summary")
- env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir))
- template = env.get_template("summary.html.jinja2")
-
- os.makedirs(output_dir, exist_ok=True)
- with open(os.path.join(output_dir, "summary.html"), "w") as f:
- f.write(template.render(
- title = "LiteDRAM benchmarks summary",
- tables = tables,
- names = names,
- script_path = get_git_file_path(__file__),
- revision = get_git_revision_hash(),
- revision_short = get_git_revision_hash(short=True),
- generation_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- ))
-
- def groupped_results(self, formatters=None):
- df = self.df()
-
- if formatters is None:
- formatters = self.text_formatters
-
- common_columns = [
- "name", "sdram_module", "sdram_memtype", "sdram_data_width",
- "bist_alternating", "num_generators", "num_checkers"
- ]
- latency_columns = ["write_latency", "read_latency"]
- performance_columns = [
- "write_bandwidth", "read_bandwidth", "write_efficiency", "read_efficiency"
- ]
- failure_columns = [
- "bist_length", "bist_random", "pattern_file", "length",
- "generator_ticks", "checker_errors", "checker_ticks"
- ]
-
- yield "Latency", self.get_summary(df,
- mask = df["is_latency"] == True,
- columns = common_columns + latency_columns,
- column_formatting = formatters,
- )
- yield "Custom access pattern", self.get_summary(df,
- mask = (df["is_latency"] == False) & (~pd.isna(df["pattern_file"])),
- columns = common_columns + ["length", "pattern_file"] + performance_columns,
- column_formatting = formatters,
- ),
- yield "Sequential access pattern", self.get_summary(df,
- mask = (df["is_latency"] == False) & (pd.isna(df["pattern_file"])) & (df["bist_random"] == False),
- columns = common_columns + ["bist_length"] + performance_columns, # could be length
- column_formatting = formatters,
- ),
- yield "Random access pattern", self.get_summary(df,
- mask = (df["is_latency"] == False) & (pd.isna(df["pattern_file"])) & (df["bist_random"] == True),
- columns = common_columns + ["bist_length"] + performance_columns,
- column_formatting = formatters,
- ),
- yield "Failures", self.get_summary(self.df(ok=False, failures=True),
- columns = common_columns + failure_columns,
- column_formatting = None,
- ),
-
- def plot_summary(self, plots_dir="plots", backend="Agg", theme="default", save_format="png", **savefig_kw):
- matplotlib.use(backend)
- import matplotlib.pyplot as plt
- plt.style.use(theme)
-
- for title, df in self.groupped_results(formatters={}):
- for column in self.plot_xticks_formatters.keys():
- if column not in df.columns or df[column].empty:
- continue
- axis = self.plot_df(title, df, column)
-
- # construct path
- def path_name(name):
- return name.lower().replace(" ", "_")
-
- filename = "{}.{}".format(path_name(column), save_format)
- path = os.path.join(plots_dir, path_name(title), filename)
- os.makedirs(os.path.dirname(path), exist_ok=True)
-
- # save figure
- axis.get_figure().savefig(path, **savefig_kw)
-
- if backend != "Agg":
- plt.show()
-
- def plot_df(self, title, df, column, fig_width=6.4, fig_min_height=2.2, save_format="png", save_filename=None):
- if save_filename is None:
- save_filename = os.path.join(self.plots_dir, title.lower().replace(" ", "_"))
-
- axis = df.plot(kind="barh", x="name", y=column, title=title, grid=True, legend=False)
- fig = axis.get_figure()
-
- if column in self.plot_xticks_formatters:
- axis.xaxis.set_major_formatter(self.plot_xticks_formatters[column])
- axis.xaxis.set_tick_params(rotation=15)
- axis.spines["top"].set_visible(False)
- axis.spines["right"].set_visible(False)
- axis.set_axisbelow(True)
- axis.set_ylabel("") # No need for label as we have only one series
-
- # For large number of rows, the bar labels start overlapping
- # use fixed ratio between number of rows and height of figure
- n_ok = 16
- new_height = (fig_width / n_ok) * len(df)
- fig.set_size_inches(fig_width, max(fig_min_height, new_height))
-
- # Remove empty spaces
- fig.tight_layout()
-
- return axis
-
-# Run ----------------------------------------------------------------------------------------------
-
-class RunCache(list):
- RunData = namedtuple("RunData", ["config", "result"])
-
- def dump_json(self, filename):
- json_data = [{"config": data.config.as_dict(), "output": getattr(data.result, "_output", None) } for data in self]
- with open(filename, "w") as f:
- json.dump(json_data, f)
-
- @classmethod
- def load_json(cls, filename):
- with open(filename, "r") as f:
- json_data = json.load(f)
- loaded = []
- for data in json_data:
- config = BenchmarkConfiguration.from_dict(data["config"])
- result = BenchmarkResult(data["output"]) if data["output"] is not None else None
- loaded.append(cls.RunData(config=config, result=result))
- return loaded
-
-
-def run_python(script, args, **kwargs):
- command = ["python3", script, *args]
- proc = subprocess.run(command, stdout=subprocess.PIPE, cwd=os.path.dirname(script), **kwargs)
- return str(proc.stdout)
-
-
-BenchmarkArgs = namedtuple("BenchmarkArgs", ["config", "output_dir", "ignore_failures", "timeout"])
-
-
-def run_single_benchmark(fargs):
- # Run as separate process, because else we cannot capture all output from verilator
- print(" {}: {}".format(fargs.config.name, " ".join(fargs.config.as_args())))
- try:
- args = fargs.config.as_args() + ["--output-dir", fargs.output_dir, "--log-level", "warning"]
- output = run_python(benchmark.__file__, args, timeout=fargs.timeout)
- result = BenchmarkResult(output)
- # Exit if checker had any read error
- if result.checker_errors != 0:
- raise RuntimeError("Error during benchmark: checker_errors = {}, args = {}".format(
- result.checker_errors, fargs.config.as_args()
- ))
- except Exception as e:
- if fargs.ignore_failures:
- print(" {}: ERROR: {}".format(fargs.config.name, e))
- return None
- else:
- raise
- print(" {}: ok".format(fargs.config.name))
- return result
-
-
-InQueueItem = namedtuple("InQueueItem", ["index", "config"])
-OutQueueItem = namedtuple("OutQueueItem", ["index", "result"])
-
-
-def run_parallel(configurations, output_base_dir, njobs, ignore_failures, timeout):
- from multiprocessing import Process, Queue
- import queue
-
- def worker(in_queue, out_queue, out_dir):
- while True:
- in_item = in_queue.get()
- if in_item is None:
- return
- fargs = BenchmarkArgs(in_item.config, out_dir, ignore_failures, timeout)
- result = run_single_benchmark(fargs)
- out_queue.put(OutQueueItem(in_item.index, result))
-
- if njobs == 0:
- njobs = os.cpu_count()
- print("Using {:d} parallel jobs".format(njobs))
-
- # Use one directory per worker, as running each benchmark in separate directory
- # takes too much disk space (~2GB per 100 benchmarks)
- dir_pool = [os.path.join(output_base_dir, "worker_%02d" % i) for i in range(njobs)]
-
- in_queue, out_queue = Queue(), Queue()
- workers = [Process(target=worker, args=(in_queue, out_queue, dir)) for dir in dir_pool]
- for w in workers:
- w.start()
-
- # Put all benchmark configurations with index to retrieve them in order
- for i, config in enumerate(configurations):
- in_queue.put(InQueueItem(i, config))
-
- # Send "finish signal" for each worker
- for _ in workers:
- in_queue.put(None)
-
- # Retrieve results in proper order
- out_items = [out_queue.get() for _ in configurations]
- results = [out.result for out in sorted(out_items, key=lambda o: o.index)]
-
- for p in workers:
- p.join()
-
- return results
-
-
-def run_benchmarks(configurations, output_base_dir, njobs, ignore_failures, timeout):
- print("Running {:d} benchmarks ...".format(len(configurations)))
- if njobs == 1:
- results = [run_single_benchmark(BenchmarkArgs(config, output_base_dir, ignore_failures, timeout))
- for config in configurations]
- else:
- results = run_parallel(configurations, output_base_dir, njobs, ignore_failures, timeout)
- run_data = [RunCache.RunData(config, result) for config, result in zip(configurations, results)]
- return run_data
-
-
-def main(argv=None):
- parser = argparse.ArgumentParser(description="Run LiteDRAM benchmarks and collect the results.")
- parser.add_argument("config", help="YAML config file")
- parser.add_argument("--names", nargs="*", help="Limit benchmarks to given names")
- parser.add_argument("--regex", help="Limit benchmarks to names matching the regex")
- parser.add_argument("--not-regex", help="Limit benchmarks to names not matching the regex")
- parser.add_argument("--html", action="store_true", help="Generate HTML summary")
- parser.add_argument("--html-output-dir", default="html", help="Output directory for generated HTML")
- parser.add_argument("--plot", action="store_true", help="Generate plots with results summary")
- parser.add_argument("--plot-format", default="png", help="Specify plots file format (default=png)")
- parser.add_argument("--plot-backend", default="Agg", help="Optionally specify matplotlib GUI backend")
- parser.add_argument("--plot-transparent", action="store_true", help="Use transparent background when saving plots")
- parser.add_argument("--plot-output-dir", default="plots", help="Specify where to save the plots")
- parser.add_argument("--plot-theme", default="default", help="Use different matplotlib theme")
- parser.add_argument("--fail-fast", action="store_true", help="Exit on any benchmark error, do not continue")
- parser.add_argument("--output-dir", default="build", help="Directory to store benchmark build output")
- parser.add_argument("--njobs", default=0, type=int, help="Use N parallel jobs to run benchmarks (default=0, which uses CPU count)")
- parser.add_argument("--heartbeat", default=0, type=int, help="Print heartbeat message with given interval (default=0 => never)")
- parser.add_argument("--timeout", default=None, help="Set timeout for a single benchmark")
- parser.add_argument("--results-cache", help="""Use given JSON file as results cache. If the file exists,
- it will be loaded instead of running actual benchmarks,
- else benchmarks will be run normally, and then saved
- to the given file. This allows to easily rerun the script
- to generate different summary without having to rerun benchmarks.""")
- args = parser.parse_args(argv)
-
- if not args.results_cache and not _summary:
- print("Summary not available and not running with --results-cache - run would not produce any results! Aborting.",
- file=sys.stderr)
- sys.exit(1)
-
- # Load and filter configurations
- configurations = BenchmarkConfiguration.load_yaml(args.config)
- filters = {
- "regex": lambda config: re.search(args.regex, config.name),
- "not_regex": lambda config: not re.search(args.not_regex, config.name),
- "names": lambda config: config.name in args.names,
- }
- for arg, f in filters.items():
- if getattr(args, arg):
- configurations = filter(f, configurations)
- configurations = list(configurations)
-
- # Load outputs from cache if it exsits
- cache_exists = args.results_cache and os.path.isfile(args.results_cache)
- if args.results_cache and cache_exists:
- cache = RunCache.load_json(args.results_cache)
-
- # Take only those that match configurations
- names_to_load = [c.name for c in configurations]
- run_data = [data for data in cache if data.config.name in names_to_load]
- else: # Run all the benchmarks normally
- if args.heartbeat:
- heartbeat_cmd = ["/bin/sh", "-c", "while true; do sleep %d; echo Heartbeat...; done" % args.heartbeat]
- heartbeat = subprocess.Popen(heartbeat_cmd)
- if args.timeout is not None:
- args.timeout = int(args.timeout)
- run_data = run_benchmarks(configurations, args.output_dir, args.njobs, not args.fail_fast, args.timeout)
- if args.heartbeat:
- heartbeat.kill()
-
- # Store outputs in cache
- if args.results_cache and not cache_exists:
- cache = RunCache(run_data)
- cache.dump_json(args.results_cache)
-
- # Display summary
- if _summary:
- summary = ResultsSummary(run_data)
- summary.text_summary()
- if args.html:
- summary.html_summary(args.html_output_dir)
- if args.plot:
- summary.plot_summary(
- plots_dir=args.plot_output_dir,
- backend=args.plot_backend,
- theme=args.plot_theme,
- save_format=args.plot_format,
- transparent=args.plot_transparent,
- )
-
- # Exit with error when there is no single benchmark that succeeded
- succeeded = sum(1 if d.result is not None else 0 for d in run_data)
- if succeeded == 0:
- sys.exit(1)
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT16KTF1G64HZ-1G6P1,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT16KTF1G64HZ-1G6P1,1,DDR3-SPD REVISON,13\r
-MT16KTF1G64HZ-1G6P1,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT16KTF1G64HZ-1G6P1,3,DDR3-MODULE TYPE (FORM FACTOR),03\r
-MT16KTF1G64HZ-1G6P1,4,DDR3-SDRAM DEVICE DENSITY BANKS,04\r
-MT16KTF1G64HZ-1G6P1,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21\r
-MT16KTF1G64HZ-1G6P1,6,DDR3-MODULE NOMINAL VDD,02\r
-MT16KTF1G64HZ-1G6P1,7,DDR3-MODULE RANKS DEVICE DQ COUNT,09\r
-MT16KTF1G64HZ-1G6P1,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,03\r
-MT16KTF1G64HZ-1G6P1,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11\r
-MT16KTF1G64HZ-1G6P1,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT16KTF1G64HZ-1G6P1,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT16KTF1G64HZ-1G6P1,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),0A\r
-MT16KTF1G64HZ-1G6P1,13,DDR3-BYTE 13 RESERVED,00\r
-MT16KTF1G64HZ-1G6P1,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),FE\r
-MT16KTF1G64HZ-1G6P1,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),00\r
-MT16KTF1G64HZ-1G6P1,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT16KTF1G64HZ-1G6P1,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT16KTF1G64HZ-1G6P1,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT16KTF1G64HZ-1G6P1,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),30\r
-MT16KTF1G64HZ-1G6P1,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT16KTF1G64HZ-1G6P1,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT16KTF1G64HZ-1G6P1,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),18\r
-MT16KTF1G64HZ-1G6P1,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),81\r
-MT16KTF1G64HZ-1G6P1,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20\r
-MT16KTF1G64HZ-1G6P1,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08\r
-MT16KTF1G64HZ-1G6P1,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT16KTF1G64HZ-1G6P1,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT16KTF1G64HZ-1G6P1,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT16KTF1G64HZ-1G6P1,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,F0\r
-MT16KTF1G64HZ-1G6P1,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83\r
-MT16KTF1G64HZ-1G6P1,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT16KTF1G64HZ-1G6P1,32,DDR3-MODULE THERMAL SENSOR,00\r
-MT16KTF1G64HZ-1G6P1,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT16KTF1G64HZ-1G6P1,34,DDR3-FINE OFFSET FOR TCKMIN,00\r
-MT16KTF1G64HZ-1G6P1,35,DDR3-FINE OFFSET FOR TAAMIN,00\r
-MT16KTF1G64HZ-1G6P1,36,DDR3-FINE OFFSET FOR TRCDMIN,00\r
-MT16KTF1G64HZ-1G6P1,37,DDR3-FINE OFFSET FOR TRPMIN,00\r
-MT16KTF1G64HZ-1G6P1,38,DDR3-FINE OFFSET FOR TRCMIN,00\r
-MT16KTF1G64HZ-1G6P1,39,DDR3-BYTE 39 RESERVED,00\r
-MT16KTF1G64HZ-1G6P1,40,DDR3-BYTE 40 RESERVED,00\r
-MT16KTF1G64HZ-1G6P1,41,DDR3-PTRR TMAW MAC,88\r
-MT16KTF1G64HZ-1G6P1,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000\r
-MT16KTF1G64HZ-1G6P1,60,DDR3-RC REV NOM MODULE HEIGHT,0F\r
-MT16KTF1G64HZ-1G6P1,61,DDR3-MODULE THICKNESS (MAX),11\r
-MT16KTF1G64HZ-1G6P1,62,DDR3-REFERENCE RAW CARD ID,65\r
-MT16KTF1G64HZ-1G6P1,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT16KTF1G64HZ-1G6P1,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT16KTF1G64HZ-1G6P1,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT16KTF1G64HZ-1G6P1,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT16KTF1G64HZ-1G6P1,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT16KTF1G64HZ-1G6P1,68,DDR3-REGISTER TYPE,00\r
-MT16KTF1G64HZ-1G6P1,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT16KTF1G64HZ-1G6P1,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT16KTF1G64HZ-1G6P1,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT16KTF1G64HZ-1G6P1,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT16KTF1G64HZ-1G6P1,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT16KTF1G64HZ-1G6P1,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT16KTF1G64HZ-1G6P1,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT16KTF1G64HZ-1G6P1,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT16KTF1G64HZ-1G6P1,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT16KTF1G64HZ-1G6P1,117,DDR3-MODULE MFR ID (LSB),80\r
-MT16KTF1G64HZ-1G6P1,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT16KTF1G64HZ-1G6P1,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT16KTF1G64HZ-1G6P1,120,DDR3-MODULE MFR YEAR,00\r
-MT16KTF1G64HZ-1G6P1,121,DDR3-MODULE MFR WEEK,00\r
-MT16KTF1G64HZ-1G6P1,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT16KTF1G64HZ-1G6P1,126-127,DDR3-CRC,5759\r
-MT16KTF1G64HZ-1G6P1,128-145,DDR3-MODULE PART NUMBER,16KTF1G64HZ-1G6P1\r
-MT16KTF1G64HZ-1G6P1,146,DDR3-MODULE DIE REV,50\r
-MT16KTF1G64HZ-1G6P1,147,DDR3-MODULE PCB REV,31\r
-MT16KTF1G64HZ-1G6P1,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT16KTF1G64HZ-1G6P1,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT16KTF1G64HZ-1G6P1,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT16KTF1G64HZ-1G6P1,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT16KTF1G64HZ-1G9E1,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT16KTF1G64HZ-1G9E1,1,DDR3-SPD REVISON,13\r
-MT16KTF1G64HZ-1G9E1,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT16KTF1G64HZ-1G9E1,3,DDR3-MODULE TYPE (FORM FACTOR),03\r
-MT16KTF1G64HZ-1G9E1,4,DDR3-SDRAM DEVICE DENSITY BANKS,04\r
-MT16KTF1G64HZ-1G9E1,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21\r
-MT16KTF1G64HZ-1G9E1,6,DDR3-MODULE NOMINAL VDD,02\r
-MT16KTF1G64HZ-1G9E1,7,DDR3-MODULE RANKS DEVICE DQ COUNT,09\r
-MT16KTF1G64HZ-1G9E1,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,03\r
-MT16KTF1G64HZ-1G9E1,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11\r
-MT16KTF1G64HZ-1G9E1,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT16KTF1G64HZ-1G9E1,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT16KTF1G64HZ-1G9E1,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),09\r
-MT16KTF1G64HZ-1G9E1,13,DDR3-BYTE 13 RESERVED,00\r
-MT16KTF1G64HZ-1G9E1,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),FE\r
-MT16KTF1G64HZ-1G9E1,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),02\r
-MT16KTF1G64HZ-1G9E1,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT16KTF1G64HZ-1G9E1,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT16KTF1G64HZ-1G9E1,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT16KTF1G64HZ-1G9E1,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),28\r
-MT16KTF1G64HZ-1G9E1,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT16KTF1G64HZ-1G9E1,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT16KTF1G64HZ-1G9E1,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),10\r
-MT16KTF1G64HZ-1G9E1,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),79\r
-MT16KTF1G64HZ-1G9E1,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20\r
-MT16KTF1G64HZ-1G9E1,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08\r
-MT16KTF1G64HZ-1G9E1,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT16KTF1G64HZ-1G9E1,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT16KTF1G64HZ-1G9E1,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT16KTF1G64HZ-1G9E1,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,D8\r
-MT16KTF1G64HZ-1G9E1,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83\r
-MT16KTF1G64HZ-1G9E1,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT16KTF1G64HZ-1G9E1,32,DDR3-MODULE THERMAL SENSOR,00\r
-MT16KTF1G64HZ-1G9E1,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT16KTF1G64HZ-1G9E1,34,DDR3-FINE OFFSET FOR TCKMIN,CA\r
-MT16KTF1G64HZ-1G9E1,35,DDR3-FINE OFFSET FOR TAAMIN,00\r
-MT16KTF1G64HZ-1G9E1,36,DDR3-FINE OFFSET FOR TRCDMIN,00\r
-MT16KTF1G64HZ-1G9E1,37,DDR3-FINE OFFSET FOR TRPMIN,00\r
-MT16KTF1G64HZ-1G9E1,38,DDR3-FINE OFFSET FOR TRCMIN,00\r
-MT16KTF1G64HZ-1G9E1,39,DDR3-BYTE 39 RESERVED,00\r
-MT16KTF1G64HZ-1G9E1,40,DDR3-BYTE 40 RESERVED,00\r
-MT16KTF1G64HZ-1G9E1,41,DDR3-PTRR TMAW MAC,84\r
-MT16KTF1G64HZ-1G9E1,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000\r
-MT16KTF1G64HZ-1G9E1,60,DDR3-RC REV NOM MODULE HEIGHT,0F\r
-MT16KTF1G64HZ-1G9E1,61,DDR3-MODULE THICKNESS (MAX),11\r
-MT16KTF1G64HZ-1G9E1,62,DDR3-REFERENCE RAW CARD ID,05\r
-MT16KTF1G64HZ-1G9E1,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT16KTF1G64HZ-1G9E1,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT16KTF1G64HZ-1G9E1,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT16KTF1G64HZ-1G9E1,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT16KTF1G64HZ-1G9E1,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT16KTF1G64HZ-1G9E1,68,DDR3-REGISTER TYPE,00\r
-MT16KTF1G64HZ-1G9E1,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT16KTF1G64HZ-1G9E1,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT16KTF1G64HZ-1G9E1,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT16KTF1G64HZ-1G9E1,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT16KTF1G64HZ-1G9E1,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT16KTF1G64HZ-1G9E1,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT16KTF1G64HZ-1G9E1,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT16KTF1G64HZ-1G9E1,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT16KTF1G64HZ-1G9E1,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT16KTF1G64HZ-1G9E1,117,DDR3-MODULE MFR ID (LSB),80\r
-MT16KTF1G64HZ-1G9E1,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT16KTF1G64HZ-1G9E1,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT16KTF1G64HZ-1G9E1,120,DDR3-MODULE MFR YEAR,00\r
-MT16KTF1G64HZ-1G9E1,121,DDR3-MODULE MFR WEEK,00\r
-MT16KTF1G64HZ-1G9E1,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT16KTF1G64HZ-1G9E1,126-127,DDR3-CRC,DDA5\r
-MT16KTF1G64HZ-1G9E1,128-145,DDR3-MODULE PART NUMBER,16KTF1G64HZ-1G9E1\r
-MT16KTF1G64HZ-1G9E1,146,DDR3-MODULE DIE REV,45\r
-MT16KTF1G64HZ-1G9E1,147,DDR3-MODULE PCB REV,31\r
-MT16KTF1G64HZ-1G9E1,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT16KTF1G64HZ-1G9E1,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT16KTF1G64HZ-1G9E1,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT16KTF1G64HZ-1G9E1,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT18KSF1G72HZ-1G4E2,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT18KSF1G72HZ-1G4E2,1,DDR3-SPD REVISON,13\r
-MT18KSF1G72HZ-1G4E2,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT18KSF1G72HZ-1G4E2,3,DDR3-MODULE TYPE (FORM FACTOR),08\r
-MT18KSF1G72HZ-1G4E2,4,DDR3-SDRAM DEVICE DENSITY BANKS,04\r
-MT18KSF1G72HZ-1G4E2,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21\r
-MT18KSF1G72HZ-1G4E2,6,DDR3-MODULE NOMINAL VDD,02\r
-MT18KSF1G72HZ-1G4E2,7,DDR3-MODULE RANKS DEVICE DQ COUNT,09\r
-MT18KSF1G72HZ-1G4E2,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,0B\r
-MT18KSF1G72HZ-1G4E2,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11\r
-MT18KSF1G72HZ-1G4E2,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT18KSF1G72HZ-1G4E2,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT18KSF1G72HZ-1G4E2,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),0C\r
-MT18KSF1G72HZ-1G4E2,13,DDR3-BYTE 13 RESERVED,00\r
-MT18KSF1G72HZ-1G4E2,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),7E\r
-MT18KSF1G72HZ-1G4E2,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),00\r
-MT18KSF1G72HZ-1G4E2,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT18KSF1G72HZ-1G4E2,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT18KSF1G72HZ-1G4E2,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT18KSF1G72HZ-1G4E2,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),30\r
-MT18KSF1G72HZ-1G4E2,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT18KSF1G72HZ-1G4E2,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT18KSF1G72HZ-1G4E2,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),20\r
-MT18KSF1G72HZ-1G4E2,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),89\r
-MT18KSF1G72HZ-1G4E2,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20\r
-MT18KSF1G72HZ-1G4E2,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08\r
-MT18KSF1G72HZ-1G4E2,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT18KSF1G72HZ-1G4E2,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT18KSF1G72HZ-1G4E2,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT18KSF1G72HZ-1G4E2,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,F0\r
-MT18KSF1G72HZ-1G4E2,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83\r
-MT18KSF1G72HZ-1G4E2,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT18KSF1G72HZ-1G4E2,32,DDR3-MODULE THERMAL SENSOR,80\r
-MT18KSF1G72HZ-1G4E2,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT18KSF1G72HZ-1G4E2,34,DDR3-FINE OFFSET FOR TCKMIN,00\r
-MT18KSF1G72HZ-1G4E2,35,DDR3-FINE OFFSET FOR TAAMIN,00\r
-MT18KSF1G72HZ-1G4E2,36,DDR3-FINE OFFSET FOR TRCDMIN,00\r
-MT18KSF1G72HZ-1G4E2,37,DDR3-FINE OFFSET FOR TRPMIN,00\r
-MT18KSF1G72HZ-1G4E2,38,DDR3-FINE OFFSET FOR TRCMIN,00\r
-MT18KSF1G72HZ-1G4E2,39,DDR3-BYTE 39 RESERVED,00\r
-MT18KSF1G72HZ-1G4E2,40,DDR3-BYTE 40 RESERVED,00\r
-MT18KSF1G72HZ-1G4E2,41,DDR3-PTRR TMAW MAC,84\r
-MT18KSF1G72HZ-1G4E2,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000\r
-MT18KSF1G72HZ-1G4E2,60,DDR3-RC REV NOM MODULE HEIGHT,0F\r
-MT18KSF1G72HZ-1G4E2,61,DDR3-MODULE THICKNESS (MAX),11\r
-MT18KSF1G72HZ-1G4E2,62,DDR3-REFERENCE RAW CARD ID,23\r
-MT18KSF1G72HZ-1G4E2,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT18KSF1G72HZ-1G4E2,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT18KSF1G72HZ-1G4E2,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT18KSF1G72HZ-1G4E2,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT18KSF1G72HZ-1G4E2,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT18KSF1G72HZ-1G4E2,68,DDR3-REGISTER TYPE,00\r
-MT18KSF1G72HZ-1G4E2,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT18KSF1G72HZ-1G4E2,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT18KSF1G72HZ-1G4E2,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT18KSF1G72HZ-1G4E2,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT18KSF1G72HZ-1G4E2,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT18KSF1G72HZ-1G4E2,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT18KSF1G72HZ-1G4E2,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT18KSF1G72HZ-1G4E2,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT18KSF1G72HZ-1G4E2,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT18KSF1G72HZ-1G4E2,117,DDR3-MODULE MFR ID (LSB),80\r
-MT18KSF1G72HZ-1G4E2,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT18KSF1G72HZ-1G4E2,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT18KSF1G72HZ-1G4E2,120,DDR3-MODULE MFR YEAR,00\r
-MT18KSF1G72HZ-1G4E2,121,DDR3-MODULE MFR WEEK,00\r
-MT18KSF1G72HZ-1G4E2,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT18KSF1G72HZ-1G4E2,126-127,DDR3-CRC,FCB1\r
-MT18KSF1G72HZ-1G4E2,128-145,DDR3-MODULE PART NUMBER,18KSF1G72HZ-1G4E2\r
-MT18KSF1G72HZ-1G4E2,146,DDR3-MODULE DIE REV,45\r
-MT18KSF1G72HZ-1G4E2,147,DDR3-MODULE PCB REV,32\r
-MT18KSF1G72HZ-1G4E2,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT18KSF1G72HZ-1G4E2,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT18KSF1G72HZ-1G4E2,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT18KSF1G72HZ-1G4E2,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT18KSF1G72HZ-1G6E2,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT18KSF1G72HZ-1G6E2,1,DDR3-SPD REVISON,13\r
-MT18KSF1G72HZ-1G6E2,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT18KSF1G72HZ-1G6E2,3,DDR3-MODULE TYPE (FORM FACTOR),08\r
-MT18KSF1G72HZ-1G6E2,4,DDR3-SDRAM DEVICE DENSITY BANKS,04\r
-MT18KSF1G72HZ-1G6E2,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21\r
-MT18KSF1G72HZ-1G6E2,6,DDR3-MODULE NOMINAL VDD,02\r
-MT18KSF1G72HZ-1G6E2,7,DDR3-MODULE RANKS DEVICE DQ COUNT,09\r
-MT18KSF1G72HZ-1G6E2,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,0B\r
-MT18KSF1G72HZ-1G6E2,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11\r
-MT18KSF1G72HZ-1G6E2,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT18KSF1G72HZ-1G6E2,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT18KSF1G72HZ-1G6E2,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),0A\r
-MT18KSF1G72HZ-1G6E2,13,DDR3-BYTE 13 RESERVED,00\r
-MT18KSF1G72HZ-1G6E2,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),FE\r
-MT18KSF1G72HZ-1G6E2,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),00\r
-MT18KSF1G72HZ-1G6E2,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT18KSF1G72HZ-1G6E2,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT18KSF1G72HZ-1G6E2,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT18KSF1G72HZ-1G6E2,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),30\r
-MT18KSF1G72HZ-1G6E2,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT18KSF1G72HZ-1G6E2,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT18KSF1G72HZ-1G6E2,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),18\r
-MT18KSF1G72HZ-1G6E2,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),81\r
-MT18KSF1G72HZ-1G6E2,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20\r
-MT18KSF1G72HZ-1G6E2,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08\r
-MT18KSF1G72HZ-1G6E2,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT18KSF1G72HZ-1G6E2,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT18KSF1G72HZ-1G6E2,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT18KSF1G72HZ-1G6E2,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,F0\r
-MT18KSF1G72HZ-1G6E2,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83\r
-MT18KSF1G72HZ-1G6E2,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT18KSF1G72HZ-1G6E2,32,DDR3-MODULE THERMAL SENSOR,80\r
-MT18KSF1G72HZ-1G6E2,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT18KSF1G72HZ-1G6E2,34,DDR3-FINE OFFSET FOR TCKMIN,00\r
-MT18KSF1G72HZ-1G6E2,35,DDR3-FINE OFFSET FOR TAAMIN,00\r
-MT18KSF1G72HZ-1G6E2,36,DDR3-FINE OFFSET FOR TRCDMIN,00\r
-MT18KSF1G72HZ-1G6E2,37,DDR3-FINE OFFSET FOR TRPMIN,00\r
-MT18KSF1G72HZ-1G6E2,38,DDR3-FINE OFFSET FOR TRCMIN,00\r
-MT18KSF1G72HZ-1G6E2,39,DDR3-BYTE 39 RESERVED,00\r
-MT18KSF1G72HZ-1G6E2,40,DDR3-BYTE 40 RESERVED,00\r
-MT18KSF1G72HZ-1G6E2,41,DDR3-PTRR TMAW MAC,84\r
-MT18KSF1G72HZ-1G6E2,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000\r
-MT18KSF1G72HZ-1G6E2,60,DDR3-RC REV NOM MODULE HEIGHT,0F\r
-MT18KSF1G72HZ-1G6E2,61,DDR3-MODULE THICKNESS (MAX),11\r
-MT18KSF1G72HZ-1G6E2,62,DDR3-REFERENCE RAW CARD ID,23\r
-MT18KSF1G72HZ-1G6E2,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT18KSF1G72HZ-1G6E2,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT18KSF1G72HZ-1G6E2,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT18KSF1G72HZ-1G6E2,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT18KSF1G72HZ-1G6E2,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT18KSF1G72HZ-1G6E2,68,DDR3-REGISTER TYPE,00\r
-MT18KSF1G72HZ-1G6E2,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT18KSF1G72HZ-1G6E2,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT18KSF1G72HZ-1G6E2,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT18KSF1G72HZ-1G6E2,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT18KSF1G72HZ-1G6E2,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT18KSF1G72HZ-1G6E2,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT18KSF1G72HZ-1G6E2,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT18KSF1G72HZ-1G6E2,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT18KSF1G72HZ-1G6E2,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT18KSF1G72HZ-1G6E2,117,DDR3-MODULE MFR ID (LSB),80\r
-MT18KSF1G72HZ-1G6E2,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT18KSF1G72HZ-1G6E2,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT18KSF1G72HZ-1G6E2,120,DDR3-MODULE MFR YEAR,00\r
-MT18KSF1G72HZ-1G6E2,121,DDR3-MODULE MFR WEEK,00\r
-MT18KSF1G72HZ-1G6E2,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT18KSF1G72HZ-1G6E2,126-127,DDR3-CRC,296F\r
-MT18KSF1G72HZ-1G6E2,128-145,DDR3-MODULE PART NUMBER,18KSF1G72HZ-1G6E2\r
-MT18KSF1G72HZ-1G6E2,146,DDR3-MODULE DIE REV,45\r
-MT18KSF1G72HZ-1G6E2,147,DDR3-MODULE PCB REV,32\r
-MT18KSF1G72HZ-1G6E2,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT18KSF1G72HZ-1G6E2,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT18KSF1G72HZ-1G6E2,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT18KSF1G72HZ-1G6E2,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT8JTF12864AZ-1G4G1,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT8JTF12864AZ-1G4G1,1,DDR3-SPD REVISON,10\r
-MT8JTF12864AZ-1G4G1,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT8JTF12864AZ-1G4G1,3,DDR3-MODULE TYPE (FORM FACTOR),02\r
-MT8JTF12864AZ-1G4G1,4,DDR3-SDRAM DEVICE DENSITY BANKS,02\r
-MT8JTF12864AZ-1G4G1,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,11\r
-MT8JTF12864AZ-1G4G1,6,DDR3-MODULE NOMINAL VDD,00\r
-MT8JTF12864AZ-1G4G1,7,DDR3-MODULE RANKS DEVICE DQ COUNT,01\r
-MT8JTF12864AZ-1G4G1,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,03\r
-MT8JTF12864AZ-1G4G1,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,52\r
-MT8JTF12864AZ-1G4G1,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT8JTF12864AZ-1G4G1,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT8JTF12864AZ-1G4G1,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),0C\r
-MT8JTF12864AZ-1G4G1,13,DDR3-BYTE 13 RESERVED,00\r
-MT8JTF12864AZ-1G4G1,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),7E\r
-MT8JTF12864AZ-1G4G1,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),00\r
-MT8JTF12864AZ-1G4G1,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT8JTF12864AZ-1G4G1,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT8JTF12864AZ-1G4G1,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT8JTF12864AZ-1G4G1,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),30\r
-MT8JTF12864AZ-1G4G1,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT8JTF12864AZ-1G4G1,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT8JTF12864AZ-1G4G1,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),20\r
-MT8JTF12864AZ-1G4G1,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),89\r
-MT8JTF12864AZ-1G4G1,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,70\r
-MT8JTF12864AZ-1G4G1,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,03\r
-MT8JTF12864AZ-1G4G1,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT8JTF12864AZ-1G4G1,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT8JTF12864AZ-1G4G1,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT8JTF12864AZ-1G4G1,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,F0\r
-MT8JTF12864AZ-1G4G1,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,82\r
-MT8JTF12864AZ-1G4G1,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT8JTF12864AZ-1G4G1,32,DDR3-MODULE THERMAL SENSOR,00\r
-MT8JTF12864AZ-1G4G1,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT8JTF12864AZ-1G4G1,34-59,DDR3-RESERVED BYTES 34-59,0000000000000000000000000000000000000000000000000000\r
-MT8JTF12864AZ-1G4G1,60,DDR3-MODULE HEIGHT (NOMINAL),0F\r
-MT8JTF12864AZ-1G4G1,61,DDR3-MODULE THICKNESS (MAX),01\r
-MT8JTF12864AZ-1G4G1,62,DDR3-REFERENCE RAW CARD ID,00\r
-MT8JTF12864AZ-1G4G1,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT8JTF12864AZ-1G4G1,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT8JTF12864AZ-1G4G1,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT8JTF12864AZ-1G4G1,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT8JTF12864AZ-1G4G1,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT8JTF12864AZ-1G4G1,68,DDR3-REGISTER TYPE,00\r
-MT8JTF12864AZ-1G4G1,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT8JTF12864AZ-1G4G1,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT8JTF12864AZ-1G4G1,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT8JTF12864AZ-1G4G1,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT8JTF12864AZ-1G4G1,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT8JTF12864AZ-1G4G1,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT8JTF12864AZ-1G4G1,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT8JTF12864AZ-1G4G1,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT8JTF12864AZ-1G4G1,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT8JTF12864AZ-1G4G1,117,DDR3-MODULE MFR ID (LSB),80\r
-MT8JTF12864AZ-1G4G1,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT8JTF12864AZ-1G4G1,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT8JTF12864AZ-1G4G1,120,DDR3-MODULE MFR YEAR,00\r
-MT8JTF12864AZ-1G4G1,121,DDR3-MODULE MFR WEEK,00\r
-MT8JTF12864AZ-1G4G1,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT8JTF12864AZ-1G4G1,126-127,DDR3-CRC,1461\r
-MT8JTF12864AZ-1G4G1,128-145,DDR3-MODULE PART NUMBER,8JTF12864AZ-1G4G1\r
-MT8JTF12864AZ-1G4G1,146,DDR3-MODULE DIE REV,47\r
-MT8JTF12864AZ-1G4G1,147,DDR3-MODULE PCB REV,31\r
-MT8JTF12864AZ-1G4G1,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT8JTF12864AZ-1G4G1,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT8JTF12864AZ-1G4G1,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT8JTF12864AZ-1G4G1,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT8KTF51264HZ-1G4E1,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT8KTF51264HZ-1G4E1,1,DDR3-SPD REVISON,13\r
-MT8KTF51264HZ-1G4E1,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT8KTF51264HZ-1G4E1,3,DDR3-MODULE TYPE (FORM FACTOR),03\r
-MT8KTF51264HZ-1G4E1,4,DDR3-SDRAM DEVICE DENSITY BANKS,04\r
-MT8KTF51264HZ-1G4E1,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21\r
-MT8KTF51264HZ-1G4E1,6,DDR3-MODULE NOMINAL VDD,02\r
-MT8KTF51264HZ-1G4E1,7,DDR3-MODULE RANKS DEVICE DQ COUNT,01\r
-MT8KTF51264HZ-1G4E1,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,03\r
-MT8KTF51264HZ-1G4E1,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11\r
-MT8KTF51264HZ-1G4E1,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT8KTF51264HZ-1G4E1,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT8KTF51264HZ-1G4E1,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),0C\r
-MT8KTF51264HZ-1G4E1,13,DDR3-BYTE 13 RESERVED,00\r
-MT8KTF51264HZ-1G4E1,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),7E\r
-MT8KTF51264HZ-1G4E1,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),00\r
-MT8KTF51264HZ-1G4E1,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT8KTF51264HZ-1G4E1,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT8KTF51264HZ-1G4E1,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT8KTF51264HZ-1G4E1,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),30\r
-MT8KTF51264HZ-1G4E1,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT8KTF51264HZ-1G4E1,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT8KTF51264HZ-1G4E1,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),20\r
-MT8KTF51264HZ-1G4E1,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),89\r
-MT8KTF51264HZ-1G4E1,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20\r
-MT8KTF51264HZ-1G4E1,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08\r
-MT8KTF51264HZ-1G4E1,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT8KTF51264HZ-1G4E1,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT8KTF51264HZ-1G4E1,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT8KTF51264HZ-1G4E1,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,F0\r
-MT8KTF51264HZ-1G4E1,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83\r
-MT8KTF51264HZ-1G4E1,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT8KTF51264HZ-1G4E1,32,DDR3-MODULE THERMAL SENSOR,00\r
-MT8KTF51264HZ-1G4E1,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT8KTF51264HZ-1G4E1,34,DDR3-FINE OFFSET FOR TCKMIN,00\r
-MT8KTF51264HZ-1G4E1,35,DDR3-FINE OFFSET FOR TAAMIN,00\r
-MT8KTF51264HZ-1G4E1,36,DDR3-FINE OFFSET FOR TRCDMIN,00\r
-MT8KTF51264HZ-1G4E1,37,DDR3-FINE OFFSET FOR TRPMIN,00\r
-MT8KTF51264HZ-1G4E1,38,DDR3-FINE OFFSET FOR TRCMIN,00\r
-MT8KTF51264HZ-1G4E1,39,DDR3-BYTE 39 RESERVED,00\r
-MT8KTF51264HZ-1G4E1,40,DDR3-BYTE 40 RESERVED,00\r
-MT8KTF51264HZ-1G4E1,41,DDR3-PTRR TMAW MAC,84\r
-MT8KTF51264HZ-1G4E1,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G4E1,60,DDR3-RC REV NOM MODULE HEIGHT,0F\r
-MT8KTF51264HZ-1G4E1,61,DDR3-MODULE THICKNESS (MAX),11\r
-MT8KTF51264HZ-1G4E1,62,DDR3-REFERENCE RAW CARD ID,41\r
-MT8KTF51264HZ-1G4E1,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT8KTF51264HZ-1G4E1,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT8KTF51264HZ-1G4E1,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT8KTF51264HZ-1G4E1,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT8KTF51264HZ-1G4E1,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT8KTF51264HZ-1G4E1,68,DDR3-REGISTER TYPE,00\r
-MT8KTF51264HZ-1G4E1,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT8KTF51264HZ-1G4E1,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT8KTF51264HZ-1G4E1,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT8KTF51264HZ-1G4E1,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT8KTF51264HZ-1G4E1,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT8KTF51264HZ-1G4E1,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT8KTF51264HZ-1G4E1,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT8KTF51264HZ-1G4E1,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT8KTF51264HZ-1G4E1,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G4E1,117,DDR3-MODULE MFR ID (LSB),80\r
-MT8KTF51264HZ-1G4E1,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT8KTF51264HZ-1G4E1,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT8KTF51264HZ-1G4E1,120,DDR3-MODULE MFR YEAR,00\r
-MT8KTF51264HZ-1G4E1,121,DDR3-MODULE MFR WEEK,00\r
-MT8KTF51264HZ-1G4E1,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT8KTF51264HZ-1G4E1,126-127,DDR3-CRC,3D17\r
-MT8KTF51264HZ-1G4E1,128-145,DDR3-MODULE PART NUMBER,8KTF51264HZ-1G4E1\r
-MT8KTF51264HZ-1G4E1,146,DDR3-MODULE DIE REV,45\r
-MT8KTF51264HZ-1G4E1,147,DDR3-MODULE PCB REV,31\r
-MT8KTF51264HZ-1G4E1,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT8KTF51264HZ-1G4E1,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT8KTF51264HZ-1G4E1,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G4E1,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT8KTF51264HZ-1G6E1,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT8KTF51264HZ-1G6E1,1,DDR3-SPD REVISON,13\r
-MT8KTF51264HZ-1G6E1,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT8KTF51264HZ-1G6E1,3,DDR3-MODULE TYPE (FORM FACTOR),03\r
-MT8KTF51264HZ-1G6E1,4,DDR3-SDRAM DEVICE DENSITY BANKS,04\r
-MT8KTF51264HZ-1G6E1,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21\r
-MT8KTF51264HZ-1G6E1,6,DDR3-MODULE NOMINAL VDD,02\r
-MT8KTF51264HZ-1G6E1,7,DDR3-MODULE RANKS DEVICE DQ COUNT,01\r
-MT8KTF51264HZ-1G6E1,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,03\r
-MT8KTF51264HZ-1G6E1,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11\r
-MT8KTF51264HZ-1G6E1,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT8KTF51264HZ-1G6E1,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT8KTF51264HZ-1G6E1,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),0A\r
-MT8KTF51264HZ-1G6E1,13,DDR3-BYTE 13 RESERVED,00\r
-MT8KTF51264HZ-1G6E1,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),FE\r
-MT8KTF51264HZ-1G6E1,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),00\r
-MT8KTF51264HZ-1G6E1,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT8KTF51264HZ-1G6E1,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT8KTF51264HZ-1G6E1,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT8KTF51264HZ-1G6E1,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),30\r
-MT8KTF51264HZ-1G6E1,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT8KTF51264HZ-1G6E1,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT8KTF51264HZ-1G6E1,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),18\r
-MT8KTF51264HZ-1G6E1,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),81\r
-MT8KTF51264HZ-1G6E1,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20\r
-MT8KTF51264HZ-1G6E1,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08\r
-MT8KTF51264HZ-1G6E1,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT8KTF51264HZ-1G6E1,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT8KTF51264HZ-1G6E1,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT8KTF51264HZ-1G6E1,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,F0\r
-MT8KTF51264HZ-1G6E1,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83\r
-MT8KTF51264HZ-1G6E1,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT8KTF51264HZ-1G6E1,32,DDR3-MODULE THERMAL SENSOR,00\r
-MT8KTF51264HZ-1G6E1,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT8KTF51264HZ-1G6E1,34,DDR3-FINE OFFSET FOR TCKMIN,00\r
-MT8KTF51264HZ-1G6E1,35,DDR3-FINE OFFSET FOR TAAMIN,00\r
-MT8KTF51264HZ-1G6E1,36,DDR3-FINE OFFSET FOR TRCDMIN,00\r
-MT8KTF51264HZ-1G6E1,37,DDR3-FINE OFFSET FOR TRPMIN,00\r
-MT8KTF51264HZ-1G6E1,38,DDR3-FINE OFFSET FOR TRCMIN,00\r
-MT8KTF51264HZ-1G6E1,39,DDR3-BYTE 39 RESERVED,00\r
-MT8KTF51264HZ-1G6E1,40,DDR3-BYTE 40 RESERVED,00\r
-MT8KTF51264HZ-1G6E1,41,DDR3-PTRR TMAW MAC,84\r
-MT8KTF51264HZ-1G6E1,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G6E1,60,DDR3-RC REV NOM MODULE HEIGHT,0F\r
-MT8KTF51264HZ-1G6E1,61,DDR3-MODULE THICKNESS (MAX),11\r
-MT8KTF51264HZ-1G6E1,62,DDR3-REFERENCE RAW CARD ID,41\r
-MT8KTF51264HZ-1G6E1,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT8KTF51264HZ-1G6E1,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT8KTF51264HZ-1G6E1,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT8KTF51264HZ-1G6E1,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT8KTF51264HZ-1G6E1,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT8KTF51264HZ-1G6E1,68,DDR3-REGISTER TYPE,00\r
-MT8KTF51264HZ-1G6E1,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT8KTF51264HZ-1G6E1,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT8KTF51264HZ-1G6E1,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT8KTF51264HZ-1G6E1,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT8KTF51264HZ-1G6E1,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT8KTF51264HZ-1G6E1,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT8KTF51264HZ-1G6E1,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT8KTF51264HZ-1G6E1,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT8KTF51264HZ-1G6E1,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G6E1,117,DDR3-MODULE MFR ID (LSB),80\r
-MT8KTF51264HZ-1G6E1,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT8KTF51264HZ-1G6E1,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT8KTF51264HZ-1G6E1,120,DDR3-MODULE MFR YEAR,00\r
-MT8KTF51264HZ-1G6E1,121,DDR3-MODULE MFR WEEK,00\r
-MT8KTF51264HZ-1G6E1,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT8KTF51264HZ-1G6E1,126-127,DDR3-CRC,E8C9\r
-MT8KTF51264HZ-1G6E1,128-145,DDR3-MODULE PART NUMBER,8KTF51264HZ-1G6E1\r
-MT8KTF51264HZ-1G6E1,146,DDR3-MODULE DIE REV,45\r
-MT8KTF51264HZ-1G6E1,147,DDR3-MODULE PCB REV,31\r
-MT8KTF51264HZ-1G6E1,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT8KTF51264HZ-1G6E1,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT8KTF51264HZ-1G6E1,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G6E1,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-Part Number,Byte Number,Byte Description,Byte Value\r
-MT8KTF51264HZ-1G9P1,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92\r
-MT8KTF51264HZ-1G9P1,1,DDR3-SPD REVISON,13\r
-MT8KTF51264HZ-1G9P1,2,DDR3-DRAM DEVICE TYPE,0B\r
-MT8KTF51264HZ-1G9P1,3,DDR3-MODULE TYPE (FORM FACTOR),03\r
-MT8KTF51264HZ-1G9P1,4,DDR3-SDRAM DEVICE DENSITY BANKS,04\r
-MT8KTF51264HZ-1G9P1,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21\r
-MT8KTF51264HZ-1G9P1,6,DDR3-MODULE NOMINAL VDD,02\r
-MT8KTF51264HZ-1G9P1,7,DDR3-MODULE RANKS DEVICE DQ COUNT,01\r
-MT8KTF51264HZ-1G9P1,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,03\r
-MT8KTF51264HZ-1G9P1,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11\r
-MT8KTF51264HZ-1G9P1,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01\r
-MT8KTF51264HZ-1G9P1,11,DDR3-MEDIUM TIMEBASE DIVISOR,08\r
-MT8KTF51264HZ-1G9P1,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),09\r
-MT8KTF51264HZ-1G9P1,13,DDR3-BYTE 13 RESERVED,00\r
-MT8KTF51264HZ-1G9P1,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),FE\r
-MT8KTF51264HZ-1G9P1,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),02\r
-MT8KTF51264HZ-1G9P1,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69\r
-MT8KTF51264HZ-1G9P1,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78\r
-MT8KTF51264HZ-1G9P1,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69\r
-MT8KTF51264HZ-1G9P1,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),28\r
-MT8KTF51264HZ-1G9P1,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69\r
-MT8KTF51264HZ-1G9P1,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11\r
-MT8KTF51264HZ-1G9P1,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),10\r
-MT8KTF51264HZ-1G9P1,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),79\r
-MT8KTF51264HZ-1G9P1,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20\r
-MT8KTF51264HZ-1G9P1,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08\r
-MT8KTF51264HZ-1G9P1,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C\r
-MT8KTF51264HZ-1G9P1,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C\r
-MT8KTF51264HZ-1G9P1,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00\r
-MT8KTF51264HZ-1G9P1,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,D8\r
-MT8KTF51264HZ-1G9P1,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83\r
-MT8KTF51264HZ-1G9P1,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05\r
-MT8KTF51264HZ-1G9P1,32,DDR3-MODULE THERMAL SENSOR,00\r
-MT8KTF51264HZ-1G9P1,33,DDR3-SDRAM DEVICE TYPE,00\r
-MT8KTF51264HZ-1G9P1,34,DDR3-FINE OFFSET FOR TCKMIN,CA\r
-MT8KTF51264HZ-1G9P1,35,DDR3-FINE OFFSET FOR TAAMIN,00\r
-MT8KTF51264HZ-1G9P1,36,DDR3-FINE OFFSET FOR TRCDMIN,00\r
-MT8KTF51264HZ-1G9P1,37,DDR3-FINE OFFSET FOR TRPMIN,00\r
-MT8KTF51264HZ-1G9P1,38,DDR3-FINE OFFSET FOR TRCMIN,00\r
-MT8KTF51264HZ-1G9P1,39,DDR3-BYTE 39 RESERVED,00\r
-MT8KTF51264HZ-1G9P1,40,DDR3-BYTE 40 RESERVED,00\r
-MT8KTF51264HZ-1G9P1,41,DDR3-PTRR TMAW MAC,88\r
-MT8KTF51264HZ-1G9P1,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G9P1,60,DDR3-RC REV NOM MODULE HEIGHT,0F\r
-MT8KTF51264HZ-1G9P1,61,DDR3-MODULE THICKNESS (MAX),11\r
-MT8KTF51264HZ-1G9P1,62,DDR3-REFERENCE RAW CARD ID,01\r
-MT8KTF51264HZ-1G9P1,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00\r
-MT8KTF51264HZ-1G9P1,64,DDR3-HEATSPREADER SOLUTION,00\r
-MT8KTF51264HZ-1G9P1,65,DDR3-REGISTER VENDOR ID (LSB),00\r
-MT8KTF51264HZ-1G9P1,66,DDR3-REGISTER VENDOR ID (MSB),00\r
-MT8KTF51264HZ-1G9P1,67,DDR3-REGISTER REVISON NUMBER,00\r
-MT8KTF51264HZ-1G9P1,68,DDR3-REGISTER TYPE,00\r
-MT8KTF51264HZ-1G9P1,69,DDR3-REG CTRL WORDS 1 AND ZERO,00\r
-MT8KTF51264HZ-1G9P1,70,DDR3-REG CTRL WORDS 3 AND 2,00\r
-MT8KTF51264HZ-1G9P1,71,DDR3-REG CTRL WORDS 5 AND 4,00\r
-MT8KTF51264HZ-1G9P1,72,DDR3-REG CTRL WORDS 7 AND 6,00\r
-MT8KTF51264HZ-1G9P1,73,DDR3-REG CTRL WORDS 9 AND 8,00\r
-MT8KTF51264HZ-1G9P1,74,DDR3-REG CTRL WORDS 11 AND 10,00\r
-MT8KTF51264HZ-1G9P1,75,DDR3-REG CTRL WORDS 13 AND 12,00\r
-MT8KTF51264HZ-1G9P1,76,DDR3-REG CTRL WORDS 15 AND 14,00\r
-MT8KTF51264HZ-1G9P1,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G9P1,117,DDR3-MODULE MFR ID (LSB),80\r
-MT8KTF51264HZ-1G9P1,118,DDR3-MODULE MFR ID (MSB),2C\r
-MT8KTF51264HZ-1G9P1,119,DDR3-MODULE MFR LOCATION ID,00\r
-MT8KTF51264HZ-1G9P1,120,DDR3-MODULE MFR YEAR,00\r
-MT8KTF51264HZ-1G9P1,121,DDR3-MODULE MFR WEEK,00\r
-MT8KTF51264HZ-1G9P1,122-125,DDR3-MODULE SERIAL NUMBER,00000000\r
-MT8KTF51264HZ-1G9P1,126-127,DDR3-CRC,46D3\r
-MT8KTF51264HZ-1G9P1,128-145,DDR3-MODULE PART NUMBER,8KTF51264HZ-1G9P1\r
-MT8KTF51264HZ-1G9P1,146,DDR3-MODULE DIE REV,50\r
-MT8KTF51264HZ-1G9P1,147,DDR3-MODULE PCB REV,31\r
-MT8KTF51264HZ-1G9P1,148,DDR3-DRAM DEVICE MFR ID (LSB),80\r
-MT8KTF51264HZ-1G9P1,149,DDR3-DRAM DEVICE MFR (MSB),2C\r
-MT8KTF51264HZ-1G9P1,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000\r
-MT8KTF51264HZ-1G9P1,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
\ No newline at end of file
+++ /dev/null
-body {
- font-family: 'Roboto', sans-serif;
-}
-
-footer {
- text-align: center;
- font-size: 10px;
- padding: 20px;
-}
-
-.dataTables_filter {
- margin: 15px 50px 10px 50px;
-}
-
-.dataTables_filter input {
- width: 400px;
-}
-
-.table-select {
- width: 100%;
- margin: 0 auto;
-}
-
-.table-select ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
- overflow: hidden;
-}
-
-.table-select li {
- float: left;
-}
-
-.table-select li a {
- display: block;
- padding: 10px 0px;
- margin: 0px 20px;
- text-align: center;
- text-decoration: none;
- font-size: 18px;
- color:inherit;
- border-bottom: 1px solid;
- border-color: #ccc;
- transition: 0.2s;
-}
-
-.table-select li a:hover {
- border-color: #111;
-}
-
-/* did not work, .focus() couldn't turn it on */
-/* .table-select li a:focus { */
-/* border-color: #222; */
-/* } */
-.table-select-active {
- border-color: #111 !important;
-}
-
-.tables-wrapper {
- width: 100%;
- margin: auto;
-}
-
-.loading {
- z-index: 999;
- position: absolute;
- top: 50%;
- left: 50%;
- margin-right: -50%;
- transform: translate(-50%, -50%);
-}
-
-/* Loading animation */
-.lds-dual-ring {
- display: inline-block;
- width: 80px;
- height: 80px;
-}
-.lds-dual-ring:after {
- content: " ";
- display: block;
- width: 64px;
- height: 64px;
- margin: 8px;
- border-radius: 50%;
- border: 6px solid #fff;
- border-color: #aaa transparent #aaa transparent;
- animation: lds-dual-ring 1.2s linear infinite;
-}
-@keyframes lds-dual-ring {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(360deg);
- }
-}
-
-/* vim: set ts=2 sw=2: */
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>{{ title }}</title>
-
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
-
- <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
- <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.css">
- <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/fixedheader/3.1.5/js/dataTables.fixedHeader.min.js"></script>
- <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/fixedheader/3.1.5/css/fixedHeader.dataTables.min.css">
-
- <style type="text/css" media="all">
-{% include 'summary.css' %}
-{# Calculate size of table selection elements so that they take up whole space #}
-.table-select li {
- width: calc(100% / {{ tables.keys() | length }});
-}
- </style>
- </head>
- <body>
- {# Loading symbol that gets hidden after initialisation of all tables #}
- <div class="loading lds-dual-ring"></div>
-
- {# Bar for selecting the current data table #}
- <div class="table-select">
- <ul>
- {% for id, name in names.items() %}
- <li id='{{ id }}-button'><a href="#">{{ name }}</a></li>
- {% endfor %}
- </ul>
- {# <hr/> #}
- </div>
-
- {# Display of the current data table #}
- <div class="tables-wrapper">
- {% for id, table in tables.items() %}
- {# Hide tables not to show them before all DataTables are loaded #}
- <div id="{{ id }}-div" style="display: none;">
- {{ table }}
- </div>
- {% endfor %}
- </div>
- </body>
-
- <footer id="footer">
- <a href="https://github.com/enjoy-digital/litedram">LiteDRAM</a> is a part of <a href="https://github.com/enjoy-digital/litex">Litex</a>.
- <br>
- Generated using
- <a href="https://github.com/enjoy-digital/litedram/blob/{{ revision }}/{{ script_path }}">{{ script_path }}</a>,
- revision
- <a href="https://github.com/enjoy-digital/litedram/commit/{{ revision }}">{{ revision_short }}</a>,
- {{ generation_date }}.
- </footer>
-
- {# Script last, so that for large tables we get some content on the page before loading tables #}
- <script>
- {# Ids of the data tables #}
- table_ids = [
- {% for id in tables.keys() %}
- '{{ id }}',
- {% endfor %}
- ];
-
- {# Show table with given id and hide all the others #}
- show_table = function(id) {
- if (!table_ids.includes(id)) {
- console.log('Error: show_table(' + id + ')');
- return;
- }
- for (var table_div of $('.tables-wrapper').children()) {
- if (table_div.id) {
- var table_div = $('#' + table_div.id)
- if (table_div.attr('id') == id + '-div') {
- table_div.show();
- } else {
- table_div.hide();
- }
- }
- }
- }
-
- // sort human-readable values assuming format "123 Kb", only first letter of unit is used
- jQuery.fn.dataTable.ext.type.order['file-size-pre'] = function(data) {
- var matches = data.match(/^(\d+(?:\.\d+)?)\s*(\S+)/i);
- var multipliers = {
- k: Math.pow(2, 10),
- m: Math.pow(2, 20),
- g: Math.pow(2, 30),
- t: Math.pow(2, 40),
- };
-
- if (matches) {
- var float = parseFloat(matches[1]);
- var prefix = matches[2].toLowerCase()[0];
- var multiplier = multipliers[prefix];
- if (multiplier) {
- float = float * multiplier;
- }
- return float;
- } else {
- return -1;
- };
- };
-
- {# Initialization after DOM has been loaded #}
- $(document).ready(function() {
- // generate data tables
- for (var id of table_ids) {
- // add human readable class to all bandwidth columns
- var columns = $('#' + id + ' > thead > tr > th').filter(function(index) {
- var name = $(this).text().toLowerCase();
- return name.includes('bandwidth') || name.includes('latency') || name.includes('efficiency');
- });
- columns.addClass('data-with-unit-human-readable');
-
- // construct data table
- table = $('#' + id);
- table.DataTable({
- paging: false,
- fixedHeader: true,
- columnDefs: [
- { type: 'file-size', targets: [ 'data-with-unit-human-readable' ] },
- { className: 'dt-body-right', targets: [ '_all' ] },
- { className: 'dt-head-center', targets: [ '_all' ] },
- ]
- });
- table.addClass("stripe");
- table.addClass("hover");
- table.addClass("order-column");
- table.addClass("cell-border");
- table.addClass("row-border");
- }
-
- // add click handlers that change the table being shown
- for (var id of table_ids) {
- var ahref = $('#' + id + '-button a');
- // use nested closure so that we avoid the situation
- // where all click handlers end up with the last id
- ahref.click(function(table_id) {
- return function() {
- // get rid of this class after first click
- $('.table-select a').removeClass('table-select-active');
- $(this).addClass('table-select-active');
- show_table(table_id);
- }
- }(id))
- }
-
- // show the first one
- $('#' + table_ids[0] + '-button a:first').click();
-
- // hide all elements of class loading
- $('.loading').hide();
- });
- </script>
-</html>
-{# vim: set ts=2 sts=2 sw=2 et: #}
+++ /dev/null
-# This file is Copyright (c) 2017-2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-
-from migen import *
-
-from litex.soc.interconnect.stream import *
-
-from litedram.common import LiteDRAMNativeWritePort, LiteDRAMNativeReadPort
-from litedram.frontend.adaptation import LiteDRAMNativePortConverter, LiteDRAMNativePortCDC
-
-from test.common import *
-
-from litex.gen.sim import *
-
-
-class ConverterDUT(Module):
- def __init__(self, user_data_width, native_data_width, mem_depth):
- self.write_user_port = LiteDRAMNativeWritePort(address_width=32, data_width=user_data_width)
- self.write_crossbar_port = LiteDRAMNativeWritePort(address_width=32, data_width=native_data_width)
- self.read_user_port = LiteDRAMNativeReadPort( address_width=32, data_width=user_data_width)
- self.read_crossbar_port = LiteDRAMNativeReadPort( address_width=32, data_width=native_data_width)
-
- # Memory
- self.memory = DRAMMemory(native_data_width, mem_depth)
-
- def do_finalize(self):
- self.submodules.write_converter = LiteDRAMNativePortConverter(
- self.write_user_port, self.write_crossbar_port)
- self.submodules.read_converter = LiteDRAMNativePortConverter(
- self.read_user_port, self.read_crossbar_port)
-
- def read(self, address, read_data=True):
- port = self.read_user_port
- yield port.cmd.valid.eq(1)
- yield port.cmd.we.eq(0)
- yield port.cmd.addr.eq(address)
- yield
- while (yield port.cmd.ready) == 0:
- yield
- yield port.cmd.valid.eq(0)
- yield
- if read_data:
- while (yield port.rdata.valid) == 0:
- yield
- data = (yield port.rdata.data)
- yield port.rdata.ready.eq(1)
- yield
- yield port.rdata.ready.eq(0)
- yield
- return data
-
- def write(self, address, data, we=None):
- if we is None:
- we = 2**self.write_user_port.wdata.we.nbits - 1
- if self.write_user_port.data_width > self.write_crossbar_port.data_width:
- yield from self._write_down(address, data, we)
- else:
- yield from self._write_up(address, data, we)
-
- def _write_up(self, address, data, we):
- port = self.write_user_port
- yield port.cmd.valid.eq(1)
- yield port.cmd.we.eq(1)
- yield port.cmd.addr.eq(address)
- yield
- while (yield port.cmd.ready) == 0:
- yield
- yield port.cmd.valid.eq(0)
- yield
- yield port.wdata.valid.eq(1)
- yield port.wdata.data.eq(data)
- yield port.wdata.we.eq(we)
- yield
- while (yield port.wdata.ready) == 0:
- yield
- yield port.wdata.valid.eq(0)
- yield
-
- def _write_down(self, address, data, we):
- # Down converter must have all the data available along with cmd, it will set
- # user_port.cmd.ready only when it sends all input words.
- port = self.write_user_port
- yield port.cmd.valid.eq(1)
- yield port.cmd.we.eq(1)
- yield port.cmd.addr.eq(address)
- yield port.wdata.valid.eq(1)
- yield port.wdata.data.eq(data)
- yield port.wdata.we.eq(we)
- yield
- # Ready goes up only after StrideConverter copied all words
- while (yield port.cmd.ready) == 0:
- yield
- yield port.cmd.valid.eq(0)
- yield
- while (yield port.wdata.ready) == 0:
- yield
- yield port.wdata.valid.eq(0)
- yield
-
-
-class CDCDUT(ConverterDUT):
- def do_finalize(self):
- # Change clock domains
- self.write_user_port.clock_domain = "user"
- self.read_user_port.clock_domain = "user"
- self.write_crossbar_port.clock_domain = "native"
- self.read_crossbar_port.clock_domain = "native"
-
- # Add CDC
- self.submodules.write_converter = LiteDRAMNativePortCDC(
- port_from = self.write_user_port,
- port_to = self.write_crossbar_port)
- self.submodules.read_converter = LiteDRAMNativePortCDC(
- port_from = self.read_user_port,
- port_to = self.read_crossbar_port)
-
-
-class TestAdaptation(MemoryTestDataMixin, unittest.TestCase):
- def test_converter_down_ratio_must_be_integer(self):
- with self.assertRaises(ValueError) as cm:
- dut = ConverterDUT(user_data_width=64, native_data_width=24, mem_depth=128)
- dut.finalize()
- self.assertIn("ratio must be an int", str(cm.exception).lower())
-
- def test_converter_up_ratio_must_be_integer(self):
- with self.assertRaises(ValueError) as cm:
- dut = ConverterDUT(user_data_width=32, native_data_width=48, mem_depth=128)
- dut.finalize()
- self.assertIn("ratio must be an int", str(cm.exception).lower())
-
- def converter_readback_test(self, dut, pattern, mem_expected):
- assert len(set(adr for adr, _ in pattern)) == len(pattern), "Pattern has duplicates!"
- read_data = []
-
- @passive
- def read_handler(read_port):
- yield read_port.rdata.ready.eq(1)
- while True:
- if (yield read_port.rdata.valid):
- read_data.append((yield read_port.rdata.data))
- yield
-
- def main_generator(dut, pattern):
- for adr, data in pattern:
- yield from dut.write(adr, data)
-
- for adr, _ in pattern:
- yield from dut.read(adr, read_data=False)
-
- # Latency delay
- for _ in range(32):
- yield
-
- generators = [
- main_generator(dut, pattern),
- read_handler(dut.read_user_port),
- dut.memory.write_handler(dut.write_crossbar_port),
- dut.memory.read_handler(dut.read_crossbar_port),
- timeout_generator(5000),
- ]
- run_simulation(dut, generators)
- self.assertEqual(dut.memory.mem, mem_expected)
- self.assertEqual(read_data, [data for adr, data in pattern])
-
- def test_converter_1to1(self):
- # Verify 64-bit to 64-bit identify-conversion.
- data = self.pattern_test_data["64bit"]
- dut = ConverterDUT(user_data_width=64, native_data_width=64, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- def test_converter_2to1(self):
- # Verify 64-bit to 32-bit down-conversion.
- data = self.pattern_test_data["64bit_to_32bit"]
- dut = ConverterDUT(user_data_width=64, native_data_width=32, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- def test_converter_4to1(self):
- # Verify 32-bit to 8-bit down-conversion.
- data = self.pattern_test_data["32bit_to_8bit"]
- dut = ConverterDUT(user_data_width=32, native_data_width=8, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- def test_converter_8to1(self):
- # Verify 64-bit to 8-bit down-conversion.
- data = self.pattern_test_data["64bit_to_8bit"]
- dut = ConverterDUT(user_data_width=64, native_data_width=8, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- def test_converter_1to2(self):
- # Verify 8-bit to 16-bit up-conversion.
- data = self.pattern_test_data["8bit_to_16bit"]
- dut = ConverterDUT(user_data_width=8, native_data_width=16, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- def test_converter_1to4(self):
- # Verify 32-bit to 128-bit up-conversion.
- data = self.pattern_test_data["32bit_to_128bit"]
- dut = ConverterDUT(user_data_width=32, native_data_width=128, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- def test_converter_1to8(self):
- # Verify 32-bit to 256-bit up-conversion.
- data = self.pattern_test_data["32bit_to_256bit"]
- dut = ConverterDUT(user_data_width=32, native_data_width=256, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- # TODO: implement case when user does not write all words (LiteDRAMNativeWritePortUpConverter)
- @unittest.skip("Only full-burst writes currently supported")
- def test_converter_up_not_aligned(self):
- data = self.pattern_test_data["8bit_to_32bit_not_aligned"]
- dut = ConverterDUT(user_data_width=8, native_data_width=32, mem_depth=len(data["expected"]))
- self.converter_readback_test(dut, data["pattern"], data["expected"])
-
- def cdc_readback_test(self, dut, pattern, mem_expected, clocks):
- assert len(set(adr for adr, _ in pattern)) == len(pattern), "Pattern has duplicates!"
- read_data = []
-
- @passive
- def read_handler(read_port):
- yield read_port.rdata.ready.eq(1)
- while True:
- if (yield read_port.rdata.valid):
- read_data.append((yield read_port.rdata.data))
- yield
-
- def main_generator(dut, pattern):
- for adr, data in pattern:
- yield from dut.write(adr, data)
-
- for adr, _ in pattern:
- yield from dut.read(adr, read_data=False)
-
- # Latency delay
- for _ in range(32):
- yield
-
- generators = {
- "user": [
- main_generator(dut, pattern),
- read_handler(dut.read_user_port),
- timeout_generator(5000),
- ],
- "native": [
- dut.memory.write_handler(dut.write_crossbar_port),
- dut.memory.read_handler(dut.read_crossbar_port),
- ],
- }
- run_simulation(dut, generators, clocks)
- self.assertEqual(dut.memory.mem, mem_expected)
- self.assertEqual(read_data, [data for adr, data in pattern])
-
- def test_port_cdc_same_clocks(self):
- # Verify CDC with same clocks (frequency and phase).
- data = self.pattern_test_data["32bit"]
- dut = CDCDUT(user_data_width=32, native_data_width=32, mem_depth=len(data["expected"]))
- clocks = {
- "user": 10,
- "native": (7, 3),
- }
- self.cdc_readback_test(dut, data["pattern"], data["expected"], clocks=clocks)
-
- def test_port_cdc_different_period(self):
- # Verify CDC with different clock frequencies.
- data = self.pattern_test_data["32bit"]
- dut = CDCDUT(user_data_width=32, native_data_width=32, mem_depth=len(data["expected"]))
- clocks = {
- "user": 10,
- "native": 7,
- }
- self.cdc_readback_test(dut, data["pattern"], data["expected"], clocks=clocks)
-
- def test_port_cdc_out_of_phase(self):
- # Verify CDC with different clock phases.
- data = self.pattern_test_data["32bit"]
- dut = CDCDUT(user_data_width=32, native_data_width=32, mem_depth=len(data["expected"]))
- clocks = {
- "user": 10,
- "native": (7, 3),
- }
- self.cdc_readback_test(dut, data["pattern"], data["expected"], clocks=clocks)
+++ /dev/null
-# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-import unittest
-import random
-
-from migen import *
-
-from litedram.common import *
-from litedram.frontend.axi import *
-
-from test.common import *
-
-from litex.gen.sim import *
-
-
-class Burst:
- def __init__(self, addr, type=BURST_FIXED, len=0, size=0):
- self.addr = addr
- self.type = type
- self.len = len
- self.size = size
-
- def to_beats(self):
- r = []
- for i in range(self.len + 1):
- if self.type == BURST_INCR:
- offset = i*2**(self.size)
- r += [Beat(self.addr + offset)]
- elif self.type == BURST_WRAP:
- offset = (i*2**(self.size))%((2**self.size)*(self.len))
- r += [Beat(self.addr + offset)]
- else:
- r += [Beat(self.addr)]
- return r
-
-
-class Beat:
- def __init__(self, addr):
- self.addr = addr
-
-
-class Access(Burst):
- def __init__(self, addr, data, id, **kwargs):
- Burst.__init__(self, addr, **kwargs)
- self.data = data
- self.id = id
-
-
-class Write(Access):
- pass
-
-
-class Read(Access):
- pass
-
-
-class TestAXI(unittest.TestCase):
- def _test_axi2native(self,
- naccesses=16, simultaneous_writes_reads=False,
- # Random: 0: min (no random), 100: max.
- # Burst randomness
- id_rand_enable = False,
- len_rand_enable = False,
- data_rand_enable = False,
- # Flow valid randomness
- aw_valid_random = 0,
- w_valid_random = 0,
- ar_valid_random = 0,
- r_valid_random = 0,
- # Flow ready randomness
- w_ready_random = 0,
- b_ready_random = 0,
- r_ready_random = 0
- ):
-
- def writes_cmd_generator(axi_port, writes):
- prng = random.Random(42)
- for write in writes:
- while prng.randrange(100) < aw_valid_random:
- yield
- # Send command
- yield axi_port.aw.valid.eq(1)
- yield axi_port.aw.addr.eq(write.addr<<2)
- yield axi_port.aw.burst.eq(write.type)
- yield axi_port.aw.len.eq(write.len)
- yield axi_port.aw.size.eq(write.size)
- yield axi_port.aw.id.eq(write.id)
- yield
- while (yield axi_port.aw.ready) == 0:
- yield
- yield axi_port.aw.valid.eq(0)
-
- def writes_data_generator(axi_port, writes):
- prng = random.Random(42)
- for write in writes:
- for i, data in enumerate(write.data):
- while prng.randrange(100) < w_valid_random:
- yield
- # Send data
- yield axi_port.w.valid.eq(1)
- if (i == (len(write.data) - 1)):
- yield axi_port.w.last.eq(1)
- else:
- yield axi_port.w.last.eq(0)
- yield axi_port.w.data.eq(data)
- yield axi_port.w.strb.eq(2**axi_port.w.strb.nbits - 1)
- yield
- while (yield axi_port.w.ready) == 0:
- yield
- yield axi_port.w.valid.eq(0)
- axi_port.reads_enable = True
-
- def writes_response_generator(axi_port, writes):
- prng = random.Random(42)
- self.writes_id_errors = 0
- for write in writes:
- # Wait response
- yield axi_port.b.ready.eq(0)
- yield
- while (yield axi_port.b.valid) == 0:
- yield
- while prng.randrange(100) < b_ready_random:
- yield
- yield axi_port.b.ready.eq(1)
- yield
- if (yield axi_port.b.id) != write.id:
- self.writes_id_errors += 1
-
- def reads_cmd_generator(axi_port, reads):
- prng = random.Random(42)
- while not axi_port.reads_enable:
- yield
- for read in reads:
- while prng.randrange(100) < ar_valid_random:
- yield
- # Send command
- yield axi_port.ar.valid.eq(1)
- yield axi_port.ar.addr.eq(read.addr<<2)
- yield axi_port.ar.burst.eq(read.type)
- yield axi_port.ar.len.eq(read.len)
- yield axi_port.ar.size.eq(read.size)
- yield axi_port.ar.id.eq(read.id)
- yield
- while (yield axi_port.ar.ready) == 0:
- yield
- yield axi_port.ar.valid.eq(0)
-
- def reads_response_data_generator(axi_port, reads):
- prng = random.Random(42)
- self.reads_data_errors = 0
- self.reads_id_errors = 0
- self.reads_last_errors = 0
- while not axi_port.reads_enable:
- yield
- for read in reads:
- for i, data in enumerate(read.data):
- # Wait data / response
- yield axi_port.r.ready.eq(0)
- yield
- while (yield axi_port.r.valid) == 0:
- yield
- while prng.randrange(100) < r_ready_random:
- yield
- yield axi_port.r.ready.eq(1)
- yield
- if (yield axi_port.r.data) != data:
- self.reads_data_errors += 1
- if (yield axi_port.r.id) != read.id:
- self.reads_id_errors += 1
- if i == (len(read.data) - 1):
- if (yield axi_port.r.last) != 1:
- self.reads_last_errors += 1
- else:
- if (yield axi_port.r.last) != 0:
- self.reads_last_errors += 1
-
- # DUT
- axi_port = LiteDRAMAXIPort(32, 32, 8)
- dram_port = LiteDRAMNativePort("both", 32, 32)
- dut = LiteDRAMAXI2Native(axi_port, dram_port)
- mem = DRAMMemory(32, 1024)
-
- # Generate writes/reads
- prng = random.Random(42)
- writes = []
- offset = 1
- for i in range(naccesses):
- _id = prng.randrange(2**8) if id_rand_enable else i
- _len = prng.randrange(32) if len_rand_enable else i
- _data = [prng.randrange(2**32) if data_rand_enable else j for j in range(_len + 1)]
- writes.append(Write(offset, _data, _id, type=BURST_INCR, len=_len, size=log2_int(32//8)))
- offset += _len + 1
- # Dummy reads to ensure datas have been written before the effective reads start.
- dummy_reads = [Read(1023, [0], 0, type=BURST_FIXED, len=0, size=log2_int(32//8)) for _ in range(32)]
- reads = dummy_reads + writes
-
- # Simulation
- if simultaneous_writes_reads:
- axi_port.reads_enable = True
- else:
- axi_port.reads_enable = False # Will be set by writes_data_generator
- generators = [
- writes_cmd_generator(axi_port, writes),
- writes_data_generator(axi_port, writes),
- writes_response_generator(axi_port, writes),
- reads_cmd_generator(axi_port, reads),
- reads_response_data_generator(axi_port, reads),
- mem.read_handler(dram_port, rdata_valid_random=r_valid_random),
- mem.write_handler(dram_port, wdata_ready_random=w_ready_random)
- ]
- run_simulation(dut, generators)
- #mem.show_content()
- self.assertEqual(self.writes_id_errors, 0)
- self.assertEqual(self.reads_data_errors, 0)
- self.assertEqual(self.reads_id_errors, 0)
- self.assertEqual(self.reads_last_errors, 0)
-
- # Test with no randomness
- def test_axi2native_writes_then_reads_no_random(self):
- self._test_axi2native(simultaneous_writes_reads=False)
-
- def test_axi2native_writes_and_reads_no_random(self):
- self._test_axi2native(simultaneous_writes_reads=True)
-
- # Test randomness one parameter at a time
- def test_axi2native_writes_then_reads_random_bursts(self):
- self._test_axi2native(
- simultaneous_writes_reads = False,
- id_rand_enable = True,
- len_rand_enable = True,
- data_rand_enable = True)
-
- def test_axi2native_writes_and_reads_random_bursts(self):
- self._test_axi2native(
- simultaneous_writes_reads = True,
- id_rand_enable = True,
- len_rand_enable = True,
- data_rand_enable = True)
-
- def test_axi2native_random_w_ready(self):
- self._test_axi2native(w_ready_random=90)
-
- def test_axi2native_random_b_ready(self):
- self._test_axi2native(b_ready_random=90)
-
- def test_axi2native_random_r_ready(self):
- self._test_axi2native(r_ready_random=90)
-
- def test_axi2native_random_aw_valid(self):
- self._test_axi2native(aw_valid_random=90)
-
- def test_axi2native_random_w_valid(self):
- self._test_axi2native(w_valid_random=90)
-
- def test_axi2native_random_ar_valid(self):
- self._test_axi2native(ar_valid_random=90)
-
- def test_axi2native_random_r_valid(self):
- self._test_axi2native(r_valid_random=90)
-
- # Now let's stress things a bit... :)
- def test_axi2native_random_all(self):
- self._test_axi2native(
- simultaneous_writes_reads=True,
- id_rand_enable = True,
- len_rand_enable = True,
- aw_valid_random = 50,
- w_ready_random = 50,
- b_ready_random = 50,
- w_valid_random = 50,
- ar_valid_random = 90,
- r_valid_random = 90,
- r_ready_random = 90
- )
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import random
-import unittest
-import itertools
-import collections
-
-from migen import *
-
-from litex.soc.interconnect import stream
-
-from litedram.common import *
-from litedram.core.bandwidth import Bandwidth
-
-from test.common import timeout_generator, CmdRequestRWDriver
-
-
-class BandwidthDUT(Module):
- def __init__(self, data_width=8, **kwargs):
- a, ba = 13, 3
- self.cmd = stream.Endpoint(cmd_request_rw_layout(a, ba))
- self.submodules.bandwidth = Bandwidth(self.cmd, data_width, **kwargs)
-
-
-class CommandDriver:
- def __init__(self, cmd, cmd_options=None):
- self.cmd = cmd
- self.driver = CmdRequestRWDriver(cmd)
- self.cmd_counts = collections.defaultdict(int)
-
- @passive
- def random_generator(self, random_ready_max=20, commands=None):
- commands = commands or ["read", "write"]
- prng = random.Random(42)
-
- while True:
- # Generate random command
- command = prng.choice(commands)
- yield from getattr(self.driver, command)()
- yield
- # Wait some times before it becomes ready
- for _ in range(prng.randint(0, random_ready_max)):
- yield
- yield self.cmd.ready.eq(1)
- yield
- self.cmd_counts[command] += 1
- yield self.cmd.ready.eq(0)
- # Disable command
- yield from self.driver.nop()
- yield
-
- @passive
- def timeline_generator(self, timeline):
- # Timeline: an iterator of tuples (cycle, command)
- sim_cycle = 0
- for cycle, command in timeline:
- assert cycle >= sim_cycle
- while sim_cycle != cycle:
- sim_cycle += 1
- yield
- # Set the command
- yield from getattr(self.driver, command)()
- yield self.cmd.ready.eq(1)
- self.cmd_counts[command] += 1
- # Advance 1 cycle
- yield
- sim_cycle += 1
- # Clear state
- yield self.cmd.ready.eq(0)
- yield from self.driver.nop()
-
-
-class TestBandwidth(unittest.TestCase):
- def test_can_read_status_data_width(self):
- # Verify that data width can be read from a CSR.
- def test(data_width):
- def main_generator(dut):
- yield
- self.assertEqual((yield dut.bandwidth.data_width.status), data_width)
-
- dut = BandwidthDUT(data_width=data_width)
- run_simulation(dut, main_generator(dut))
-
- for data_width in [8, 16, 32, 64]:
- with self.subTest(data_width=data_width):
- test(data_width)
-
- def test_requires_update_to_copy_the_data(self):
- # Verify that command counts are copied to CSRs only after `update`.
- def main_generator(dut):
- nreads = (yield from dut.bandwidth.nreads.read())
- nwrites = (yield from dut.bandwidth.nwrites.read())
- self.assertEqual(nreads, 0)
- self.assertEqual(nwrites, 0)
-
- # Wait enough for the period to end
- for _ in range(2**6):
- yield
-
- nreads = (yield from dut.bandwidth.nreads.read())
- nwrites = (yield from dut.bandwidth.nwrites.read())
- self.assertEqual(nreads, 0)
- self.assertEqual(nwrites, 0)
-
- # Update register values
- yield from dut.bandwidth.update.write(1)
-
- nreads = (yield from dut.bandwidth.nreads.read())
- nwrites = (yield from dut.bandwidth.nwrites.read())
- self.assertNotEqual((nreads, nwrites), (0, 0))
-
- dut = BandwidthDUT(period_bits=6)
- cmd_driver = CommandDriver(dut.cmd)
- generators = [
- main_generator(dut),
- cmd_driver.random_generator(),
- ]
- run_simulation(dut, generators)
-
- def test_correct_read_write_counts(self):
- # Verify that the number of registered READ/WRITE commands is correct.
- results = {}
-
- def main_generator(dut):
- # Wait for the first period to end
- for _ in range(2**8):
- yield
- yield from dut.bandwidth.update.write(1)
- yield
- results["nreads"] = (yield from dut.bandwidth.nreads.read())
- results["nwrites"] = (yield from dut.bandwidth.nwrites.read())
-
- dut = BandwidthDUT(period_bits=8)
- cmd_driver = CommandDriver(dut.cmd)
- generators = [
- main_generator(dut),
- cmd_driver.random_generator(),
- ]
- run_simulation(dut, generators)
-
- self.assertEqual(results["nreads"], cmd_driver.cmd_counts["read"])
-
- def test_counts_read_write_only(self):
- # Verify that only READ and WRITE commands are registered.
- results = {}
-
- def main_generator(dut):
- # Wait for the first period to end
- for _ in range(2**8):
- yield
- yield from dut.bandwidth.update.write(1)
- yield
- results["nreads"] = (yield from dut.bandwidth.nreads.read())
- results["nwrites"] = (yield from dut.bandwidth.nwrites.read())
-
- dut = BandwidthDUT(period_bits=8)
- cmd_driver = CommandDriver(dut.cmd)
- commands = ["read", "write", "activate", "precharge", "refresh"]
- generators = [
- main_generator(dut),
- cmd_driver.random_generator(commands=commands),
- ]
- run_simulation(dut, generators)
-
- self.assertEqual(results["nreads"], cmd_driver.cmd_counts["read"])
-
- def test_correct_period_length(self):
- # Verify that period length is correct by measuring time between CSR changes.
- period_bits = 5
- period = 2**period_bits
-
- n_per_period = {0: 3, 1: 6, 2: 9}
- timeline = {}
- for p, n in n_per_period.items():
- for i in range(n):
- margin = 10
- timeline[period*p + margin + i] = "write"
-
- def main_generator(dut):
- # Keep the values always up to date
- yield dut.bandwidth.update.re.eq(1)
-
- # Wait until we have the data from 1st period
- while (yield dut.bandwidth.nwrites.status) != 3:
- yield
-
- # Count time to next period
- cycles = 0
- while (yield dut.bandwidth.nwrites.status) != 6:
- cycles += 1
- yield
-
- self.assertEqual(cycles, period)
-
- dut = BandwidthDUT(period_bits=period_bits)
- cmd_driver = CommandDriver(dut.cmd)
- generators = [
- main_generator(dut),
- cmd_driver.timeline_generator(timeline.items()),
- timeout_generator(period * 3),
- ]
- run_simulation(dut, generators)
-
- def test_not_missing_commands_on_period_boundary(self):
- # Verify that no data is lost in the cycle when new period starts.
- period_bits = 5
- period = 2**period_bits
-
- # Start 10 cycles before period ends, end 10 cycles after it ends
- base = period - 10
- nwrites = 20
- timeline = {base + i: "write" for i in range(nwrites)}
-
- def main_generator(dut):
- # Wait until 1st period ends (+ some margin)
- for _ in range(period + 10):
- yield
-
- # Read the count from 1st period
- yield from dut.bandwidth.update.write(1)
- yield
- nwrites_registered = (yield from dut.bandwidth.nwrites.read())
-
- # Wait until 2nd period ends
- for _ in range(period):
- yield
-
- # Read the count from 1st period
- yield from dut.bandwidth.update.write(1)
- yield
- nwrites_registered += (yield from dut.bandwidth.nwrites.read())
-
- self.assertEqual(nwrites_registered, nwrites)
-
- dut = BandwidthDUT(period_bits=period_bits)
- cmd_driver = CommandDriver(dut.cmd)
- generators = [
- main_generator(dut),
- cmd_driver.timeline_generator(timeline.items()),
- ]
- run_simulation(dut, generators)
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import math
-import unittest
-
-from migen import *
-
-from litedram.common import *
-from litedram.core.bankmachine import BankMachine
-
-from test.common import timeout_generator
-
-
-class BankMachineDUT(Module):
- # Fill only settings needed by BankMachine
- default_controller_settings = dict(
- cmd_buffer_depth = 8,
- cmd_buffer_buffered = False,
- with_auto_precharge = True,
- )
- default_phy_settings = dict(
- cwl = 2,
- nphases = 2,
- nranks = 1,
- # indirectly
- memtype = "DDR2",
- dfi_databits = 2*16,
- )
- default_geom_settings = dict(
- bankbits = 3,
- rowbits = 13,
- colbits = 10,
- )
- default_timing_settings = dict(
- tRAS = None,
- tRC = None,
- tCCD = 1,
- tRCD = 2,
- tRP = 2,
- tWR = 2,
- )
-
- def __init__(self, n,
- controller_settings = None,
- phy_settings = None,
- geom_settings = None,
- timing_settings = None):
- # Update settings if provided
- def updated(settings, update):
- copy = settings.copy()
- copy.update(update or {})
- return copy
-
- controller_settings = updated(self.default_controller_settings, controller_settings)
- phy_settings = updated(self.default_phy_settings, phy_settings)
- geom_settings = updated(self.default_geom_settings, geom_settings)
- timing_settings = updated(self.default_timing_settings, timing_settings)
-
- class SimpleSettings(Settings):
- def __init__(self, **kwargs):
- self.set_attributes(kwargs)
-
- settings = SimpleSettings(**controller_settings)
- settings.phy = SimpleSettings(**phy_settings)
- settings.geom = SimpleSettings(**geom_settings)
- settings.timing = SimpleSettings(**timing_settings)
- settings.geom.addressbits = max(settings.geom.rowbits, settings.geom.colbits)
- self.settings = settings
-
- self.address_align = log2_int(burst_lengths[settings.phy.memtype])
- self.address_width = LiteDRAMInterface(self.address_align, settings).address_width
-
- bankmachine = BankMachine(n=n,
- address_width = self.address_width,
- address_align = self.address_align,
- nranks = settings.phy.nranks,
- settings = settings)
- self.submodules.bankmachine = bankmachine
-
- def get_cmd(self):
- # cmd_request_rw_layout -> name
- layout = [name for name, _ in cmd_request_rw_layout(
- a = self.settings.geom.addressbits,
- ba = self.settings.geom.bankbits)]
- request = {}
- for name in layout + ["valid", "ready", "first", "last"]:
- request[name] = (yield getattr(self.bankmachine.cmd, name))
- request["type"] = {
- (0, 0, 0): "nop",
- (1, 0, 1): "write",
- (1, 0, 0): "read",
- (0, 1, 0): "activate",
- (0, 1, 1): "precharge",
- (1, 1, 0): "refresh",
- }[(request["cas"], request["ras"], request["we"])]
- return request
-
- def req_address(self, row, col):
- col = col & (2**self.settings.geom.colbits - 1)
- row = row & (2**self.settings.geom.rowbits - 1)
- split = self.settings.geom.colbits - self.address_align
- return (row << split) | col
-
-
-class TestBankMachine(unittest.TestCase):
- def test_init(self):
- BankMachineDUT(1)
-
- def bankmachine_commands_test(self, dut, requests, generators=None):
- # Perform a test by simulating requests producer and return registered commands
- commands = []
-
- def producer(dut):
- for req in requests:
- yield dut.bankmachine.req.addr.eq(req["addr"])
- yield dut.bankmachine.req.we.eq(req["we"])
- yield dut.bankmachine.req.valid.eq(1)
- yield
- while not (yield dut.bankmachine.req.ready):
- yield
- yield dut.bankmachine.req.valid.eq(0)
- for _ in range(req.get("delay", 0)):
- yield
-
- def req_consumer(dut):
- for req in requests:
- if req["we"]:
- signal = dut.bankmachine.req.wdata_ready
- else:
- signal = dut.bankmachine.req.rdata_valid
- while not (yield signal):
- yield
- yield
-
- @passive
- def cmd_consumer(dut):
- while True:
- while not (yield dut.bankmachine.cmd.valid):
- yield
- yield dut.bankmachine.cmd.ready.eq(1)
- yield
- commands.append((yield from dut.get_cmd()))
- yield dut.bankmachine.cmd.ready.eq(0)
- yield
-
- all_generators = [
- producer(dut),
- req_consumer(dut),
- cmd_consumer(dut),
- timeout_generator(50 * len(requests)),
- ]
- if generators is not None:
- all_generators += [g(dut) for g in generators]
- run_simulation(dut, all_generators)
- return commands
-
- def test_opens_correct_row(self):
- # Verify that the correct row is activated before read/write commands.
- dut = BankMachineDUT(3)
- requests = [
- dict(addr=dut.req_address(row=0xf0, col=0x0d), we=0),
- dict(addr=dut.req_address(row=0xd0, col=0x0d), we=1),
- ]
- commands = self.bankmachine_commands_test(dut=dut, requests=requests)
- # Commands: activate, read (auto-precharge), activate, write
- self.assertEqual(commands[0]["type"], "activate")
- self.assertEqual(commands[0]["a"], 0xf0)
- self.assertEqual(commands[2]["type"], "activate")
- self.assertEqual(commands[2]["a"], 0xd0)
-
- def test_correct_bank_address(self):
- # Verify that `ba` always corresponds to the BankMachine number.
- for bn in [0, 2, 7]:
- with self.subTest(bn=bn):
- dut = BankMachineDUT(bn, geom_settings=dict(bankbits=3))
- requests = [dict(addr=0, we=0)]
- commands = self.bankmachine_commands_test(dut=dut, requests=requests)
- for cmd in commands:
- self.assertEqual(cmd["ba"], bn)
-
- def test_read_write_same_row(self):
- # Verify that there is only one activate when working on single row.
- dut = BankMachineDUT(1)
- requests = [
- dict(addr=dut.req_address(row=0xba, col=0xad), we=0),
- dict(addr=dut.req_address(row=0xba, col=0xad), we=1),
- dict(addr=dut.req_address(row=0xba, col=0xbe), we=0),
- dict(addr=dut.req_address(row=0xba, col=0xbe), we=1),
- ]
- commands = self.bankmachine_commands_test(dut=dut, requests=requests)
- commands = [(cmd["type"], cmd["a"]) for cmd in commands]
- expected = [
- ("activate", 0xba),
- ("read", 0xad << dut.address_align),
- ("write", 0xad << dut.address_align),
- ("read", 0xbe << dut.address_align),
- ("write", 0xbe << dut.address_align),
- ]
- self.assertEqual(commands, expected)
-
- def test_write_different_rows_with_delay(self):
- # Verify that precharge is used when changing row with a delay this is independent form auto-precharge.
- for auto_precharge in [False, True]:
- with self.subTest(auto_precharge=auto_precharge):
- settings = dict(with_auto_precharge=auto_precharge)
- dut = BankMachineDUT(1, controller_settings=settings)
- requests = [
- dict(addr=dut.req_address(row=0xba, col=0xad), we=1, delay=8),
- dict(addr=dut.req_address(row=0xda, col=0xad), we=1),
- ]
- commands = self.bankmachine_commands_test(dut=dut, requests=requests)
- commands = [(cmd["type"], cmd["a"]) for cmd in commands]
- expected = [
- ("activate", 0xba),
- ("write", 0xad << dut.address_align),
- ("precharge", 0xad << dut.address_align),
- ("activate", 0xda),
- ("write", 0xad << dut.address_align),
- ]
- self.assertEqual(commands, expected)
-
- def test_write_different_rows_with_auto_precharge(self):
- # Verify that auto-precharge is used when changing row without delay.
- settings = dict(with_auto_precharge=True)
- dut = BankMachineDUT(1, controller_settings=settings)
- requests = [
- dict(addr=dut.req_address(row=0xba, col=0xad), we=1),
- dict(addr=dut.req_address(row=0xda, col=0xad), we=1),
- ]
- commands = self.bankmachine_commands_test(dut=dut, requests=requests)
- commands = [(cmd["type"], cmd["a"]) for cmd in commands]
- expected = [
- ("activate", 0xba),
- ("write", (0xad << dut.address_align) | (1 << 10)),
- ("activate", 0xda),
- ("write", 0xad << dut.address_align),
- ]
- self.assertEqual(commands, expected)
-
- def test_write_different_rows_without_auto_precharge(self):
- # Verify that auto-precharge is used when changing row without delay.
- settings = dict(with_auto_precharge=False)
- dut = BankMachineDUT(1, controller_settings=settings)
- requests = [
- dict(addr=dut.req_address(row=0xba, col=0xad), we=1),
- dict(addr=dut.req_address(row=0xda, col=0xad), we=1),
- ]
- commands = self.bankmachine_commands_test(dut=dut, requests=requests)
- commands = [(cmd["type"], cmd["a"]) for cmd in commands]
- expected = [
- ("activate", 0xba),
- ("write", 0xad << dut.address_align),
- ("precharge", 0xad << dut.address_align),
- ("activate", 0xda),
- ("write", 0xad << dut.address_align),
- ]
- self.assertEqual(commands, expected)
-
- def test_burst_no_request_lost(self):
- # Verify that no request is lost in fast bursts of requests regardless of cmd_buffer_depth.
- for cmd_buffer_depth in [8, 1, 0]:
- settings = dict(cmd_buffer_depth=cmd_buffer_depth)
- with self.subTest(**settings):
- dut = BankMachineDUT(1, controller_settings=settings)
- # Long sequence of writes to the same row
- requests = [dict(addr=dut.req_address(row=0xba, col=i), we=1) for i in range(32)]
- expected = ([("activate", 0xba)] +
- [("write", i << dut.address_align) for i in range(32)])
- commands = self.bankmachine_commands_test(dut=dut, requests=requests)
- commands = [(cmd["type"], cmd["a"]) for cmd in commands]
- self.assertEqual(commands, expected)
-
- def test_lock_until_requests_finished(self):
- # Verify that lock is being held until all requests in FIFO are processed.
- @passive
- def lock_checker(dut):
- req = dut.bankmachine.req
- self.assertEqual((yield req.lock), 0)
-
- # Wait until first request becomes locked
- while not (yield req.valid):
- yield
-
- # Wait until lock should be released (all requests in queue gets processed)
- # here it happens when the final wdata_ready ends
- for _ in range(3):
- while not (yield req.wdata_ready):
- yield
- self.assertEqual((yield req.lock), 1)
- yield
-
- yield
- self.assertEqual((yield req.lock), 0)
-
- dut = BankMachineDUT(1)
- # Simple sequence with row change
- requests = [
- dict(addr=dut.req_address(row=0x1a, col=0x01), we=1),
- dict(addr=dut.req_address(row=0x1b, col=0x02), we=1),
- dict(addr=dut.req_address(row=0x1c, col=0x04), we=1),
- ]
- self.bankmachine_commands_test(dut=dut, requests=requests, generators=[lock_checker])
-
- def timing_test(self, from_cmd, to_cmd, time_expected, **dut_kwargs):
- @passive
- def timing_checker(dut):
- def is_cmd(cmd_type, test_ready):
- cmd = (yield from dut.get_cmd())
- ready = cmd["ready"] if test_ready else True
- return cmd["valid"] and ready and cmd["type"] == cmd_type
-
- # Time between WRITE ends (ready and valid) and PRECHARGE becomes valid
- while not (yield from is_cmd(from_cmd, test_ready=True)):
- yield
- yield # Wait until cmd deactivates in case the second cmd is the same as first
- time = 1
- while not (yield from is_cmd(to_cmd, test_ready=False)):
- yield
- time += 1
-
- self.assertEqual(time, time_expected)
-
- dut = BankMachineDUT(1, **dut_kwargs)
- # Simple sequence with row change
- requests = [
- dict(addr=dut.req_address(row=0xba, col=0xad), we=1),
- dict(addr=dut.req_address(row=0xda, col=0xad), we=1),
- ]
- self.bankmachine_commands_test(dut=dut, requests=requests, generators=[timing_checker])
-
- def test_timing_write_to_precharge(self):
- controller_settings = dict(with_auto_precharge=False)
- timing_settings = dict(tWR=6, tCCD=4)
- phy_settings = dict(cwl=2, nphases=2)
- write_latency = math.ceil(phy_settings["cwl"] / phy_settings["nphases"])
- precharge_time = write_latency + timing_settings["tWR"] + timing_settings["tCCD"]
- self.timing_test("write", "precharge", precharge_time,
- controller_settings = controller_settings,
- phy_settings = phy_settings,
- timing_settings = timing_settings)
-
- def test_timing_activate_to_activate(self):
- timing_settings = dict(tRC=16)
- self.timing_test("activate", "activate",
- time_expected = 16,
- timing_settings = timing_settings)
-
- def test_timing_activate_to_precharge(self):
- timing_settings = dict(tRAS=32)
- self.timing_test("activate", "precharge",
- time_expected = 32,
- timing_settings = timing_settings)
-
- def test_refresh(self):
- # Verify that no commands are issued during refresh and after it the row is re-activated.
- @passive
- def refresh_generator(dut):
- # Wait some time for the bankmachine to start
- for _ in range(16):
- yield
-
- # Request a refresh
- yield dut.bankmachine.refresh_req.eq(1)
- while not (yield dut.bankmachine.refresh_gnt):
- yield
-
- # Wait when refresh is being performed
- # Make sure no command is issued during refresh
- for _ in range(32):
- self.assertEqual((yield dut.bankmachine.cmd.valid), 0)
- yield
-
- # Signalize refresh is ready
- yield dut.bankmachine.refresh_req.eq(0)
-
- dut = BankMachineDUT(1)
- requests = [dict(addr=dut.req_address(row=0xba, col=i), we=1) for i in range(16)]
- commands = self.bankmachine_commands_test(dut=dut, requests=requests,
- generators=[refresh_generator])
- commands = [(cmd["type"], cmd["a"]) for cmd in commands]
- # Refresh will close row, so bankmachine should re-activate it after refresh
- self.assertEqual(commands.count(("activate", 0xba)), 2)
- # Verify that the write commands are correct
- write_commands = [cmd for cmd in commands if cmd[0] == "write"]
- expected_writes = [("write", i << dut.address_align) for i in range(16)]
- self.assertEqual(write_commands, expected_writes)
-
- def test_output_annotations(self):
- # Verify that all commands are annotated correctly using is_* signals.
- checked = set()
-
- @passive
- def cmd_checker(dut):
- while True:
- cmd = (yield from dut.get_cmd())
- if cmd["valid"]:
- if cmd["type"] in ["activate", "precharge"]:
- self.assertEqual(cmd["is_cmd"], 1)
- self.assertEqual(cmd["is_write"], 0)
- self.assertEqual(cmd["is_read"], 0)
- elif cmd["type"] in ["write"]:
- self.assertEqual(cmd["is_cmd"], 0)
- self.assertEqual(cmd["is_write"], 1)
- self.assertEqual(cmd["is_read"], 0)
- elif cmd["type"] in ["read"]:
- self.assertEqual(cmd["is_cmd"], 0)
- self.assertEqual(cmd["is_write"], 0)
- self.assertEqual(cmd["is_read"], 1)
- else:
- raise ValueError(cmd["type"])
- checked.add(cmd["type"])
- yield
-
- dut = BankMachineDUT(1)
- requests = [
- dict(addr=dut.req_address(row=0xba, col=0xad), we=0),
- dict(addr=dut.req_address(row=0xba, col=0xad), we=1),
- dict(addr=dut.req_address(row=0xda, col=0xad), we=0),
- # Wait enough time for regular (not auto) precharge to be used
- dict(addr=dut.req_address(row=0xda, col=0xad), we=1, delay=32),
- dict(addr=dut.req_address(row=0xba, col=0xad), we=0),
- dict(addr=dut.req_address(row=0xba, col=0xad), we=1),
- ]
- self.bankmachine_commands_test(dut=dut, requests=requests, generators=[cmd_checker])
- # Bankmachine does not produce refresh commands
- self.assertEqual(checked, {"activate", "precharge", "write", "read"})
+++ /dev/null
-# This file is Copyright (c) 2016-2018 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2016 Tim 'mithro' Ansell <mithro@mithis.com>
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-
-from migen import *
-
-from litex.gen.sim import *
-
-from litedram.common import *
-from litedram.frontend.bist import *
-from litedram.frontend.bist import _LiteDRAMBISTGenerator, _LiteDRAMBISTChecker, \
- _LiteDRAMPatternGenerator, _LiteDRAMPatternChecker
-
-from test.common import *
-
-
-class GenCheckDriver:
- def __init__(self, module):
- self.module = module
-
- def reset(self):
- yield self.module.reset.eq(1)
- yield
- yield self.module.reset.eq(0)
- yield
-
- def configure(self, base, length, end=None, random_addr=None, random_data=None):
- # For non-pattern generators/checkers
- if end is None:
- end = base + 0x100000
- yield self.module.base.eq(base)
- yield self.module.end.eq(end)
- yield self.module.length.eq(length)
- if random_addr is not None:
- yield self.module.random_addr.eq(random_addr)
- if random_data is not None:
- yield self.module.random_data.eq(random_data)
-
- def run(self):
- yield self.module.start.eq(1)
- yield
- yield self.module.start.eq(0)
- yield
- while((yield self.module.done) == 0):
- yield
- if hasattr(self.module, "errors"):
- self.errors = (yield self.module.errors)
-
-
-class GenCheckCSRDriver:
- def __init__(self, module):
- self.module = module
-
- def reset(self):
- yield from self.module.reset.write(1)
- yield from self.module.reset.write(0)
-
- def configure(self, base, length, end=None, random_addr=None, random_data=None):
- # For non-pattern generators/checkers
- if end is None:
- end = base + 0x100000
- yield from self.module.base.write(base)
- yield from self.module.end.write(end)
- yield from self.module.length.write(length)
- if random_addr is not None:
- yield from self.module.random.addr.write(random_addr)
- if random_data is not None:
- yield from self.module.random.data.write(random_data)
-
- def run(self):
- yield from self.module.start.write(1)
- yield
- yield from self.module.start.write(0)
- yield
- while((yield from self.module.done.read()) == 0):
- yield
- if hasattr(self.module, "errors"):
- self.errors = (yield from self.module.errors.read())
-
-
-class TestBIST(MemoryTestDataMixin, unittest.TestCase):
-
- # Generator ------------------------------------------------------------------------------------
-
- def test_generator(self):
- # Verify Generator is behaving correctly in the incr/random modes.
- def main_generator(dut):
- self.errors = 0
-
- # Test incr
- yield dut.ce.eq(1)
- yield dut.random_enable.eq(0)
- yield
- for i in range(1024):
- data = (yield dut.o)
- if data != i:
- self.errors += 1
- yield
-
- # Test random
- datas = []
- yield dut.ce.eq(1)
- yield dut.random_enable.eq(1)
- for i in range(1024):
- data = (yield dut.o)
- if data in datas:
- self.errors += 1
- datas.append(data)
- yield
-
- # DUT
- dut = Generator(23, n_state=23, taps=[17, 22])
-
- # Simulation
- generators = [main_generator(dut)]
- run_simulation(dut, generators)
- self.assertEqual(self.errors, 0)
-
- def generator_test(self, mem_expected, data_width, pattern=None, config_args=None,
- check_mem=True):
- assert pattern is None or config_args is None, \
- "_LiteDRAMBISTGenerator xor _LiteDRAMPatternGenerator"
-
- class DUT(Module):
- def __init__(self):
- self.write_port = LiteDRAMNativeWritePort(address_width=32, data_width=data_width)
- if pattern is not None:
- self.submodules.generator = _LiteDRAMPatternGenerator(self.write_port, pattern)
- else:
- self.submodules.generator = _LiteDRAMBISTGenerator(self.write_port)
- self.mem = DRAMMemory(data_width, len(mem_expected))
-
- def main_generator(driver):
- yield from driver.reset()
- if pattern is None:
- yield from driver.configure(**config_args)
- yield from driver.run()
- yield
-
- dut = DUT()
- generators = [
- main_generator(GenCheckDriver(dut.generator)),
- dut.mem.write_handler(dut.write_port),
- ]
- run_simulation(dut, generators)
- if check_mem:
- self.assertEqual(dut.mem.mem, mem_expected)
- return dut
-
- # _LiteDRAMBISTGenerator -----------------------------------------------------------------------
-
- def test_bist_generator_8bit(self):
- # Verify BISTGenerator with a 8-bit datapath.
- data = self.bist_test_data["8bit"]
- self.generator_test(data.pop("expected"), data_width=8, config_args=data)
-
- def test_bist_generator_range_must_be_pow2(self):
- # NOTE:
- # in the current implementation (end - start) must be a power of 2,
- # but it would be better if this restriction didn't hold, this test
- # is here just to notice the change if it happens unintentionally
- # and may be removed if we start supporting arbitrary ranges
- data = self.bist_test_data["8bit"]
- data["end"] += 1
- reference = data.pop("expected")
- dut = self.generator_test(reference, data_width=8, config_args=data, check_mem=False)
- self.assertNotEqual(dut.mem.mem, reference)
-
- def test_bist_generator_32bit(self):
- # Verify BISTGenerator with a 32-bit datapath.
- data = self.bist_test_data["32bit"]
- self.generator_test(data.pop("expected"), data_width=32, config_args=data)
-
- def test_bist_generator_64bit(self):
- # Verify BISTGenerator with a 64-bit datapath.
- data = self.bist_test_data["64bit"]
- self.generator_test(data.pop("expected"), data_width=64, config_args=data)
-
- def test_bist_generator_32bit_address_masked(self):
- # Verify BISTGenerator with a 32-bit datapath and masked address.
- data = self.bist_test_data["32bit_masked"]
- self.generator_test(data.pop("expected"), data_width=32, config_args=data)
-
- def test_bist_generator_32bit_long_sequential(self):
- # Verify BISTGenerator with a 32-bit datapath and long sequential pattern.
- data = self.bist_test_data["32bit_long_sequential"]
- self.generator_test(data.pop("expected"), data_width=32, config_args=data)
-
- def test_bist_generator_random_data(self):
- # Verify BISTGenerator with a 32-bit datapath and random pattern.
- data = self.bist_test_data["32bit"]
- data["random_data"] = True
- dut = self.generator_test(data.pop("expected"), data_width=32, config_args=data,
- check_mem=False)
- # Only check that there are no duplicates and that data is not a simple sequence
- mem = [val for val in dut.mem.mem if val != 0]
- self.assertEqual(len(set(mem)), len(mem), msg="Duplicate values in memory")
- self.assertNotEqual(mem, list(range(len(mem))), msg="Values are a sequence")
-
- def test_bist_generator_random_addr(self):
- # Verify BISTGenerator with a 32-bit datapath and random address.
- data = self.bist_test_data["32bit"]
- data["random_addr"] = True
- dut = self.generator_test(data.pop("expected"), data_width=32, config_args=data,
- check_mem=False)
- # With random address and address wrapping (generator.end) we _can_ have duplicates
- # we can at least check that the values written are not an ordered sequence
- mem = [val for val in dut.mem.mem if val != 0]
- self.assertNotEqual(mem, list(range(len(mem))), msg="Values are a sequence")
- self.assertLess(max(mem), data["length"], msg="Too big value found")
-
- # _LiteDRAMPatternGenerator --------------------------------------------------------------------
-
- def test_pattern_generator_8bit(self):
- # Verify PatternGenerator with a 8-bit datapath.
- data = self.pattern_test_data["8bit"]
- self.generator_test(data["expected"], data_width=8, pattern=data["pattern"])
-
- def test_pattern_generator_32bit(self):
- # Verify PatternGenerator with a 32-bit datapath.
- data = self.pattern_test_data["32bit"]
- self.generator_test(data["expected"], data_width=32, pattern=data["pattern"])
-
- def test_pattern_generator_64bit(self):
- # Verify PatternGenerator with a 64-bit datapath.
- data = self.pattern_test_data["64bit"]
- self.generator_test(data["expected"], data_width=64, pattern=data["pattern"])
-
- def test_pattern_generator_32bit_not_aligned(self):
- # Verify PatternGenerator with a 32-bit datapath and un-aligned addresses.
- data = self.pattern_test_data["32bit_not_aligned"]
- self.generator_test(data["expected"], data_width=32, pattern=data["pattern"])
-
- def test_pattern_generator_32bit_duplicates(self):
- # Verify PatternGenerator with a 32-bit datapath and duplicate addresses.
- data = self.pattern_test_data["32bit_duplicates"]
- self.generator_test(data["expected"], data_width=32, pattern=data["pattern"])
-
- def test_pattern_generator_32bit_sequential(self):
- # Verify PatternGenerator with a 32-bit datapath and sequential pattern.
- data = self.pattern_test_data["32bit_sequential"]
- self.generator_test(data["expected"], data_width=32, pattern=data["pattern"])
-
- # _LiteDRAMBISTChecker -------------------------------------------------------------------------
-
- def checker_test(self, memory, data_width, pattern=None, config_args=None, check_errors=False):
- assert pattern is None or config_args is None, \
- "_LiteDRAMBISTChecker xor _LiteDRAMPatternChecker"
-
- class DUT(Module):
- def __init__(self):
- self.read_port = LiteDRAMNativeReadPort(address_width=32, data_width=data_width)
- if pattern is not None:
- self.submodules.checker = _LiteDRAMPatternChecker(self.read_port, init=pattern)
- else:
- self.submodules.checker = _LiteDRAMBISTChecker(self.read_port)
- self.mem = DRAMMemory(data_width, len(memory), init=memory)
-
- def main_generator(driver):
- yield from driver.reset()
- if pattern is None:
- yield from driver.configure(**config_args)
- yield from driver.run()
- yield
-
- dut = DUT()
- checker = GenCheckDriver(dut.checker)
- generators = [
- main_generator(checker),
- dut.mem.read_handler(dut.read_port),
- ]
- run_simulation(dut, generators)
- if check_errors:
- self.assertEqual(checker.errors, 0)
- return dut, checker
-
- def test_bist_checker_8bit(self):
- # Verify BISTChecker with a 8-bit datapath.
- data = self.bist_test_data["8bit"]
- memory = data.pop("expected")
- self.checker_test(memory, data_width=8, config_args=data)
-
- def test_bist_checker_32bit(self):
- # Verify BISTChecker with a 32-bit datapath.
- data = self.bist_test_data["32bit"]
- memory = data.pop("expected")
- self.checker_test(memory, data_width=32, config_args=data)
-
- def test_bist_checker_64bit(self):
- # Verify BISTChecker with a 64-bit datapath.
- data = self.bist_test_data["64bit"]
- memory = data.pop("expected")
- self.checker_test(memory, data_width=64, config_args=data)
-
- # _LiteDRAMPatternChecker ----------------------------------------------------------------------
-
- def test_pattern_checker_8bit(self):
- # Verify PatternChecker with a 8-bit datapath.
- data = self.pattern_test_data["8bit"]
- self.checker_test(memory=data["expected"], data_width=8, pattern=data["pattern"])
-
- def test_pattern_checker_32bit(self):
- # Verify PatternChecker with a 32-bit datapath.
- data = self.pattern_test_data["32bit"]
- self.checker_test(memory=data["expected"], data_width=32, pattern=data["pattern"])
-
- def test_pattern_checker_64bit(self):
- # Verify PatternChecker with a 64-bit datapath.
- data = self.pattern_test_data["64bit"]
- self.checker_test(memory=data["expected"], data_width=64, pattern=data["pattern"])
-
- def test_pattern_checker_32bit_not_aligned(self):
- # Verify PatternChecker with a 32-bit datapath and un-aligned addresses.
- data = self.pattern_test_data["32bit_not_aligned"]
- self.checker_test(memory=data["expected"], data_width=32, pattern=data["pattern"])
-
- def test_pattern_checker_32bit_duplicates(self):
- # Verify PatternChecker with a 32-bit datapath and duplicate addresses.
- data = self.pattern_test_data["32bit_duplicates"]
- num_duplicates = len(data["pattern"]) - len(set(adr for adr, _ in data["pattern"]))
- dut, checker = self.checker_test(
- memory=data["expected"], data_width=32, pattern=data["pattern"], check_errors=False)
- self.assertEqual(checker.errors, num_duplicates)
-
- # LiteDRAMBISTGenerator and LiteDRAMBISTChecker ------------------------------------------------
-
- def bist_test(self, generator, checker, mem):
- # write
- yield from generator.reset()
- yield from generator.configure(base=16, length=64)
- yield from generator.run()
-
- # Read (no errors)
- yield from checker.reset()
- yield from checker.configure(base=16, length=64)
- yield from checker.run()
- self.assertEqual(checker.errors, 0)
-
- # Corrupt memory (using generator)
- yield from generator.reset()
- yield from generator.configure(base=16 + 48, length=64)
- yield from generator.run()
-
- # Read (errors)
- yield from checker.reset()
- yield from checker.configure(base=16, length=64)
- yield from checker.run()
- # Errors for words:
- # from (16 + 48) / 4 = 16 (corrupting generator start)
- # to (16 + 64) / 4 = 20 (first generator end)
- self.assertEqual(checker.errors, 4)
-
- # Read (no errors)
- yield from checker.reset()
- yield from checker.configure(base=16 + 48, length=64)
- yield from checker.run()
- self.assertEqual(checker.errors, 0)
-
- def test_bist_base(self):
- # Verify BIST (Generator and Checker) with control from the logic.
- class DUT(Module):
- def __init__(self):
- self.write_port = LiteDRAMNativeWritePort(address_width=32, data_width=32)
- self.read_port = LiteDRAMNativeReadPort(address_width=32, data_width=32)
- self.submodules.generator = _LiteDRAMBISTGenerator(self.write_port)
- self.submodules.checker = _LiteDRAMBISTChecker(self.read_port)
-
- def main_generator(dut, mem):
- generator = GenCheckDriver(dut.generator)
- checker = GenCheckDriver(dut.checker)
- yield from self.bist_test(generator, checker, mem)
-
- # DUT
- dut = DUT()
- mem = DRAMMemory(32, 48)
-
- # Simulation
- generators = [
- main_generator(dut, mem),
- mem.write_handler(dut.write_port),
- mem.read_handler(dut.read_port)
- ]
- run_simulation(dut, generators)
-
- def test_bist_csr(self):
- # Verify BIST (Generator and Checker) with control from CSRs.
- class DUT(Module):
- def __init__(self):
- self.write_port = LiteDRAMNativeWritePort(address_width=32, data_width=32)
- self.read_port = LiteDRAMNativeReadPort(address_width=32, data_width=32)
- self.submodules.generator = LiteDRAMBISTGenerator(self.write_port)
- self.submodules.checker = LiteDRAMBISTChecker(self.read_port)
-
- def main_generator(dut, mem):
- generator = GenCheckCSRDriver(dut.generator)
- checker = GenCheckCSRDriver(dut.checker)
- yield from self.bist_test(generator, checker, mem)
-
- # DUT
- dut = DUT()
- mem = DRAMMemory(32, 48)
-
- # Simulation
- generators = [
- main_generator(dut, mem),
- mem.write_handler(dut.write_port),
- mem.read_handler(dut.read_port)
- ]
- run_simulation(dut, generators)
-
- def test_bist_csr_cdc(self):
- # Verify BIST (Generator and Checker) with control from CSRs in a different clock domain.
- class DUT(Module):
- def __init__(self):
- port_kwargs = dict(address_width=32, data_width=32, clock_domain="async")
- self.write_port = LiteDRAMNativeWritePort(**port_kwargs)
- self.read_port = LiteDRAMNativeReadPort(**port_kwargs)
- self.submodules.generator = LiteDRAMBISTGenerator(self.write_port)
- self.submodules.checker = LiteDRAMBISTChecker(self.read_port)
-
- def main_generator(dut, mem):
- generator = GenCheckCSRDriver(dut.generator)
- checker = GenCheckCSRDriver(dut.checker)
- yield from self.bist_test(generator, checker, mem)
-
- # DUT
- dut = DUT()
- mem = DRAMMemory(32, 48)
-
- generators = {
- "sys": [
- main_generator(dut, mem),
- ],
- "async": [
- mem.write_handler(dut.write_port),
- mem.read_handler(dut.read_port)
- ]
- }
- clocks = {
- "sys": 10,
- "async": (7, 3),
- }
- run_simulation(dut, generators, clocks)
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-
-from migen import *
-from litex.soc.interconnect import stream
-
-from litedram.common import *
-from litedram.core.multiplexer import _CommandChooser
-
-from test.common import CmdRequestRWDriver
-
-
-class CommandChooserDUT(Module):
- def __init__(self, n_requests, addressbits, bankbits):
- self.requests = [stream.Endpoint(cmd_request_rw_layout(a=addressbits, ba=bankbits))
- for _ in range(n_requests)]
- self.submodules.chooser = _CommandChooser(self.requests)
-
- self.drivers = [CmdRequestRWDriver(req, i) for i, req in enumerate(self.requests)]
-
- def set_requests(self, description):
- assert len(description) == len(self.drivers)
- for driver, char in zip(self.drivers, description):
- yield from driver.request(char)
-
-
-class TestCommandChooser(unittest.TestCase):
- def test_helper_methods_correct(self):
- # Verify that helper methods return correct values.
- def main_generator(dut):
- possible_cmds = "_rwap"
- expected_read = "01000"
- expected_write = "00100"
- expected_activate = "00010"
- helper_methods = {
- "write": expected_write,
- "read": expected_read,
- "activate": expected_activate,
- }
-
- # Create a subTest for each method
- for method, expected_values in helper_methods.items():
- with self.subTest(method=method):
- # Set each available command as the first request and verify
- # that the helper method returns the correct value. We can
- # safely use only the first request because no requests are
- # valid as all the want_* signals are 0.
- for cmd, expected in zip(possible_cmds, expected_values):
- yield from dut.set_requests(f"{cmd}___")
- yield
- method_value = (yield getattr(dut.chooser, method)())
- self.assertEqual(method_value, int(expected))
-
- # Test accept helper
- with self.subTest(method="accept"):
- yield dut.chooser.want_writes.eq(1)
- yield
-
- yield from dut.set_requests("____")
- yield
- self.assertEqual((yield dut.chooser.accept()), 0)
-
- # Set write request, this sets request.valid=1
- yield from dut.set_requests("w___")
- yield
- self.assertEqual((yield dut.chooser.accept()), 0)
- self.assertEqual((yield dut.chooser.cmd.valid), 1)
-
- # Accept() is only on after we set cmd.ready=1
- yield dut.chooser.cmd.ready.eq(1)
- yield
- self.assertEqual((yield dut.chooser.accept()), 1)
-
- dut = CommandChooserDUT(n_requests=4, bankbits=3, addressbits=13)
- run_simulation(dut, main_generator(dut))
-
- def test_selects_next_when_request_not_valid(self):
- # Verify that arbiter moves to next request when valid goes inactive.
- def main_generator(dut):
- yield dut.chooser.want_cmds.eq(1)
- yield from dut.set_requests("pppp")
- yield
-
- # Advance to next request
- def invalidate(i):
- yield dut.requests[i].valid.eq(0)
- yield
- yield dut.requests[i].valid.eq(1)
- yield
-
- # First request is selected as it is valid and ~ready
- self.assertEqual((yield dut.chooser.cmd.ba), 0)
- yield
- self.assertEqual((yield dut.chooser.cmd.ba), 0)
-
- # After deactivating `valid`, arbiter should choose next request
- yield from invalidate(0)
- self.assertEqual((yield dut.chooser.cmd.ba), 1)
- yield from invalidate(1)
- self.assertEqual((yield dut.chooser.cmd.ba), 2)
- yield from invalidate(2)
- self.assertEqual((yield dut.chooser.cmd.ba), 3)
- yield from invalidate(3)
- self.assertEqual((yield dut.chooser.cmd.ba), 0)
-
- dut = CommandChooserDUT(n_requests=4, bankbits=3, addressbits=13)
- run_simulation(dut, main_generator(dut))
-
- def test_selects_next_when_cmd_ready(self):
- # Verify that next request is chosen when the current one becomes ready.
- def main_generator(dut):
- yield dut.chooser.want_cmds.eq(1)
- yield from dut.set_requests("pppp")
- yield
-
- # Advance to next request
- def cmd_ready():
- yield dut.chooser.cmd.ready.eq(1)
- yield
- yield dut.chooser.cmd.ready.eq(0)
- yield
-
- # First request is selected as it is valid and ~ready
- self.assertEqual((yield dut.chooser.cmd.ba), 0)
- yield
- self.assertEqual((yield dut.chooser.cmd.ba), 0)
-
- # After deactivating valid arbiter should choose next request
- yield from cmd_ready()
- self.assertEqual((yield dut.chooser.cmd.ba), 1)
- yield from cmd_ready()
- self.assertEqual((yield dut.chooser.cmd.ba), 2)
- yield from cmd_ready()
- self.assertEqual((yield dut.chooser.cmd.ba), 3)
- yield from cmd_ready()
- self.assertEqual((yield dut.chooser.cmd.ba), 0)
-
- dut = CommandChooserDUT(n_requests=4, bankbits=3, addressbits=13)
- run_simulation(dut, main_generator(dut))
-
- def selection_test(self, requests, expected_order, wants):
- # Set requests to given states and tests whether they are being connected
- # to chooser.cmd in the expected order. Using `ba` value to distinguish
- # requests (as initialised in CommandChooserDUT).
- # "_" means no valid request.
- def main_generator(dut):
- for want in wants:
- yield getattr(dut.chooser, want).eq(1)
-
- yield from dut.set_requests(requests)
- yield
-
- for i, expected_index in enumerate(expected_order):
- error_msg = f"requests={requests}, expected_order={expected_order}, i={i}"
- if expected_index == "_": # not valid - cas/ras/we should be 0
- cas = (yield dut.chooser.cmd.cas)
- ras = (yield dut.chooser.cmd.ras)
- we = (yield dut.chooser.cmd.we)
- self.assertEqual((cas, ras, we), (0, 0, 0), msg=error_msg)
- else:
- # Check that ba is as expected
- selected_request_index = (yield dut.chooser.cmd.ba)
- self.assertEqual(selected_request_index, int(expected_index), msg=error_msg)
-
- # Advance to next request
- yield dut.chooser.cmd.ready.eq(1)
- yield
- yield dut.chooser.cmd.ready.eq(0)
- yield
-
- assert len(requests) == 8
- dut = CommandChooserDUT(n_requests=8, bankbits=3, addressbits=13)
- run_simulation(dut, main_generator(dut))
-
- @unittest.skip("Issue #174")
- def test_selects_nothing(self):
- # When want_* = 0, chooser should set cas/ras/we = 0, which means not valid request
- requests = "w_rawpwr"
- order = "____" # cas/ras/we are never set
- self.selection_test(requests, order, wants=[])
-
- def test_selects_writes(self):
- requests = "w_rawpwr"
- order = "0460460"
- self.selection_test(requests, order, wants=["want_writes"])
-
- def test_selects_reads(self):
- requests = "rp_awrrw"
- order = "0560560"
- self.selection_test(requests, order, wants=["want_reads"])
-
- @unittest.skip("Issue #174")
- def test_selects_writes_and_reads(self):
- requests = "rp_awrrw"
- order = "04567045670"
- self.selection_test(requests, order, wants=["want_reads", "want_writes"])
-
- @unittest.skip("Issue #174")
- def test_selects_cmds_without_act(self):
- # When want_cmds = 1, but want_activates = 0, activate commands should not be selected
- requests = "pr_aa_pw"
- order = "06060"
- self.selection_test(requests, order, wants=["want_cmds"])
-
- def test_selects_cmds_with_act(self):
- # When want_cmds/activates = 1, both activate and precharge should be selected
- requests = "pr_aa_pw"
- order = "034603460"
- self.selection_test(requests, order, wants=["want_cmds", "want_activates"])
-
- @unittest.skip("Issue #174")
- def test_selects_nothing_when_want_activates_only(self):
- # When only want_activates = 1, nothing will be selected
- requests = "pr_aa_pw"
- order = "____"
- self.selection_test(requests, order, wants=["want_activates"])
-
- def test_selects_cmds_and_writes(self):
- requests = "pr_aa_pw"
- order = "0670670"
- self.selection_test(requests, order, wants=["want_cmds", "want_writes"])
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import random
-import unittest
-import functools
-import itertools
-from collections import namedtuple, defaultdict
-
-from migen import *
-
-from litedram.common import *
-from litedram.core.crossbar import LiteDRAMCrossbar
-
-from test.common import timeout_generator, NativePortDriver
-
-
-class ControllerStub:
- """Simplified simulation of LiteDRAMController as seen by LiteDRAMCrossbar
-
- This is a simplified implementation of LiteDRAMController suitable for
- testing the crossbar. It consisits of bankmachine handlers that try to mimic
- behaviour of real BankMachines. They also simulate data transmission by
- scheduling it to appear on data interface (data_handler sets it).
- """
- W = namedtuple("WriteData", ["bank", "addr", "data", "we"])
- R = namedtuple("ReadData", ["bank", "addr", "data"])
- WaitingData = namedtuple("WaitingData", ["delay", "data"])
-
- def __init__(self, controller_interface, write_latency, read_latency, cmd_delay=None):
- self.interface = controller_interface
- self.write_latency = write_latency
- self.read_latency = read_latency
- self.data = [] # data registered on datapath (W/R)
- self._waiting = [] # data waiting to be set on datapath
- # Incremental generator of artificial read data
- self._read_data = itertools.count(0x10)
- # Simulated dealy of command processing, by default just constant
- self._cmd_delay = cmd_delay or (lambda: 6)
- # Minimal logic required so that no two banks will become ready at the same moment
- self._multiplexer_lock = None
-
- def generators(self):
- bank_handlers = [self.bankmachine_handler(bn) for bn in range(self.interface.nbanks)]
- return [self.data_handler(), *bank_handlers]
-
- @passive
- def data_handler(self):
- # Responsible for passing data over datapath with requested latency
- while True:
- # Examine requests to find if there is any for that cycle
- available = [w for w in self._waiting if w.delay == 0]
- # Make sure that it is never the case that we have more then 1
- # operation of the same type
- type_counts = defaultdict(int)
- for a in available:
- type_counts[type(a.data)] += 1
- for t, count in type_counts.items():
- assert count == 1, \
- "%d data operations of type %s at the same time!" % (count, t.__name__)
- for a in available:
- # Remove it from the list and get the data
- current = self._waiting.pop(self._waiting.index(a)).data
- # If this was a write, then fill it with data from this cycle
- if isinstance(current, self.W):
- current = current._replace(
- data=(yield self.interface.wdata),
- we=(yield self.interface.wdata_we),
- )
- # If this was a read, then assert the data now
- elif isinstance(current, self.R):
- yield self.interface.rdata.eq(current.data)
- else:
- raise TypeError(current)
- # Add it to the data that appeared on the datapath
- self.data.append(current)
- # Advance simulation time by 1 cycle
- for i, w in enumerate(self._waiting):
- self._waiting[i] = w._replace(delay=w.delay - 1)
- yield
-
- @passive
- def bankmachine_handler(self, n):
- # Simplified simulation of a bank machine.
- # Uses a single buffer (no input fifo). Generates random read data.
- bank = getattr(self.interface, "bank%d" % n)
- while True:
- # Wait for a valid bank command
- while not (yield bank.valid):
- # The lock is being held as long as there is a valid command
- # in the buffer or there is a valid command on the interface.
- # As at this point we have nothing in the buffer, we unlock
- # the lock only if the command on the interface is not valid.
- yield bank.lock.eq(0)
- yield
- # Latch the command to the internal buffer
- cmd_addr = (yield bank.addr)
- cmd_we = (yield bank.we)
- # Lock the buffer as soon as command is valid on the interface.
- # We do this 1 cycle after we see the command, but BankMachine
- # also has latency, because cmd_buffer_lookahead.source must
- # become valid.
- yield bank.lock.eq(1)
- yield bank.ready.eq(1)
- yield
- yield bank.ready.eq(0)
- # Simulate that we are processing the command
- for _ in range(self._cmd_delay()):
- yield
- # Avoid situation that can happen due to the lack of multiplexer,
- # where more than one bank would send data at the same moment
- while self._multiplexer_lock is not None:
- yield
- self._multiplexer_lock = n
- yield
- # After READ/WRITE has been issued, this is signalized by using
- # rdata_valid/wdata_ready. The actual data will appear with latency.
- if cmd_we: # WRITE
- yield bank.wdata_ready.eq(1)
- yield
- yield bank.wdata_ready.eq(0)
- # Send a request to the data_handler, it will check what
- # has been sent from the crossbar port.
- wdata = self.W(bank=n, addr=cmd_addr,
- data=None, we=None) # to be filled in callback
- self._waiting.append(self.WaitingData(data=wdata, delay=self.write_latency))
- else: # READ
- yield bank.rdata_valid.eq(1)
- yield
- yield bank.rdata_valid.eq(0)
- # Send a request with "data from memory" to the data_handler
- rdata = self.R(bank=n, addr=cmd_addr, data=next(self._read_data))
- # Decrease latecy, as data_handler sets data with 1 cycle delay
- self._waiting.append(self.WaitingData(data=rdata, delay=self.read_latency - 1))
- # At this point cmd_buffer.source.ready has been activated and the
- # command in internal buffer has been discarded. The lock will be
- self._multiplexer_lock = None
- # removed in next loop if there is no other command pending.
- yield
-
-
-class CrossbarDUT(Module):
- default_controller_settings = dict(
- cmd_buffer_depth = 8,
- address_mapping = "ROW_BANK_COL",
- )
- default_phy_settings = dict(
- cwl = 2,
- nphases = 2,
- nranks = 1,
- memtype = "DDR2",
- dfi_databits = 2*16,
- read_latency = 5,
- write_latency = 1,
- )
- default_geom_settings = dict(
- bankbits = 3,
- rowbits = 13,
- colbits = 10,
- )
-
- def __init__(self, controller_settings=None, phy_settings=None, geom_settings=None):
- # update settings if provided
- def updated(settings, update):
- copy = settings.copy()
- copy.update(update or {})
- return copy
-
- controller_settings = updated(self.default_controller_settings, controller_settings)
- phy_settings = updated(self.default_phy_settings, phy_settings)
- geom_settings = updated(self.default_geom_settings, geom_settings)
-
- class SimpleSettings(Settings):
- def __init__(self, **kwargs):
- self.set_attributes(kwargs)
-
- settings = SimpleSettings(**controller_settings)
- settings.phy = SimpleSettings(**phy_settings)
- settings.geom = SimpleSettings(**geom_settings)
- self.settings = settings
-
- self.address_align = log2_int(burst_lengths[settings.phy.memtype])
- self.interface = LiteDRAMInterface(self.address_align, settings)
- self.submodules.crossbar = LiteDRAMCrossbar(self.interface)
-
- def addr_port(self, bank, row, col):
- # construct an address the way port master would do it
- assert self.settings.address_mapping == "ROW_BANK_COL"
- aa = self.address_align
- cb = self.settings.geom.colbits
- rb = self.settings.geom.rowbits
- bb = self.settings.geom.bankbits
- col = (col & (2**cb - 1)) >> aa
- bank = (bank & (2**bb - 1)) << (cb - aa)
- row = (row & (2**rb - 1)) << (cb + bb - aa)
- return row | bank | col
-
- def addr_iface(self, row, col):
- # construct address the way bankmachine should receive it
- aa = self.address_align
- cb = self.settings.geom.colbits
- rb = self.settings.geom.rowbits
- col = (col & (2**cb - 1)) >> aa
- row = (row & (2**rb - 1)) << (cb - aa)
- return row | col
-
-
-class TestCrossbar(unittest.TestCase):
- W = ControllerStub.W
- R = ControllerStub.R
-
- def test_init(self):
- dut = CrossbarDUT()
- dut.crossbar.get_port()
- dut.finalize()
-
- def crossbar_test(self, dut, generators, timeout=100, **kwargs):
- # Runs simulation with a controller stub (passive generators) and user generators
- if not isinstance(generators, list):
- generators = [generators]
- controller = ControllerStub(dut.interface,
- write_latency=dut.settings.phy.write_latency,
- read_latency=dut.settings.phy.read_latency,
- **kwargs)
- generators += [*controller.generators(), timeout_generator(timeout)]
- run_simulation(dut, generators)
- return controller.data
-
- def test_available_address_mappings(self):
- # Check that the only supported address mapping is ROW_BANK_COL (if we start supporting new
- # mappings, then update these tests to also test these other mappings).
- def finalize_crossbar(mapping):
- dut = CrossbarDUT(controller_settings=dict(address_mapping=mapping))
- dut.crossbar.get_port()
- dut.crossbar.finalize()
-
- for mapping in ["ROW_BANK_COL", "BANK_ROW_COL"]:
- if mapping in ["ROW_BANK_COL"]:
- finalize_crossbar(mapping)
- else:
- with self.assertRaises(KeyError):
- finalize_crossbar(mapping)
-
- def test_address_mappings(self):
- # Verify that address is translated correctly.
- reads = []
-
- def producer(dut, port):
- driver = NativePortDriver(port)
- for t in transfers:
- addr = dut.addr_port(bank=t["bank"], row=t["row"], col=t["col"])
- if t["rw"] == self.W:
- yield from driver.write(addr, data=t["data"], we=t.get("we", None))
- elif t["rw"] == self.R:
- data = (yield from driver.read(addr))
- reads.append(data)
- else:
- raise TypeError(t["rw"])
-
- geom_settings = dict(colbits=10, rowbits=13, bankbits=2)
- dut = CrossbarDUT(geom_settings=geom_settings)
- port = dut.crossbar.get_port()
- transfers = [
- dict(rw=self.W, bank=2, row=0x30, col=0x03, data=0x20),
- dict(rw=self.W, bank=3, row=0x30, col=0x03, data=0x21),
- dict(rw=self.W, bank=2, row=0xab, col=0x03, data=0x22),
- dict(rw=self.W, bank=2, row=0x30, col=0x13, data=0x23),
- dict(rw=self.R, bank=1, row=0x10, col=0x99),
- dict(rw=self.R, bank=0, row=0x10, col=0x99),
- dict(rw=self.R, bank=1, row=0xcd, col=0x99),
- dict(rw=self.R, bank=1, row=0x10, col=0x77),
- ]
- expected = []
- for i, t in enumerate(transfers):
- cls = t["rw"]
- addr = dut.addr_iface(row=t["row"], col=t["col"])
- if cls == self.W:
- kwargs = dict(data=t["data"], we=0xff)
- elif cls == self.R:
- kwargs = dict(data=0x10 + i)
- return cls(bank=t["bank"], addr=addr, **kwargs)
-
- data = self.crossbar_test(dut, producer(port))
- self.assertEqual(data, expected)
-
- def test_arbitration(self):
- # Create multiple masters that write to the same bank at the same time and verify that all
- # the requests have been sent correctly.
- def producer(dut, port, num):
- driver = NativePortDriver(port)
- addr = dut.addr_port(bank=3, row=0x10 + num, col=0x20 + num)
- yield from driver.write(addr, data=0x30 + num)
-
- dut = CrossbarDUT()
- ports = [dut.crossbar.get_port() for _ in range(4)]
- masters = [producer(dut, port, i) for i, port in enumerate(ports)]
- data = self.crossbar_test(dut, masters)
- expected = {
- self.W(bank=3, addr=dut.addr_iface(row=0x10, col=0x20), data=0x30, we=0xff),
- self.W(bank=3, addr=dut.addr_iface(row=0x11, col=0x21), data=0x31, we=0xff),
- self.W(bank=3, addr=dut.addr_iface(row=0x12, col=0x22), data=0x32, we=0xff),
- self.W(bank=3, addr=dut.addr_iface(row=0x13, col=0x23), data=0x33, we=0xff),
- }
- self.assertEqual(set(data), expected)
-
- def test_lock_write(self):
- # Verify that the locking mechanism works
- # Create a situation when one master A wants to write to banks 0 then 1, but master B is
- # continuously writing to bank 1 (bank is locked) so that master A is blocked. We use
- # wait_data=False because we are only concerned about sending commands fast enough for
- # the lock to be held continuously.
- def master_a(dut, port):
- driver = NativePortDriver(port)
- adr = functools.partial(dut.addr_port, row=1, col=1)
- write = functools.partial(driver.write, wait_data=False)
- yield from write(adr(bank=0), data=0x10)
- yield from write(adr(bank=1), data=0x11)
- yield from write(adr(bank=0), data=0x12, wait_data=True)
-
- def master_b(dut, port):
- driver = NativePortDriver(port)
- adr = functools.partial(dut.addr_port, row=2, col=2)
- write = functools.partial(driver.write, wait_data=False)
- yield from write(adr(bank=1), data=0x20)
- yield from write(adr(bank=1), data=0x21)
- yield from write(adr(bank=1), data=0x22)
- yield from write(adr(bank=1), data=0x23)
- yield from write(adr(bank=1), data=0x24)
-
- dut = CrossbarDUT()
- ports = [dut.crossbar.get_port() for _ in range(2)]
- data = self.crossbar_test(dut, [master_a(dut, ports[0]), master_b(dut, ports[1])])
- expected = [
- self.W(bank=0, addr=dut.addr_iface(row=1, col=1), data=0x10, we=0xff), # A
- self.W(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x20, we=0xff), # B
- self.W(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x21, we=0xff), # B
- self.W(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x22, we=0xff), # B
- self.W(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x23, we=0xff), # B
- self.W(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x24, we=0xff), # B
- self.W(bank=1, addr=dut.addr_iface(row=1, col=1), data=0x11, we=0xff), # A
- self.W(bank=0, addr=dut.addr_iface(row=1, col=1), data=0x12, we=0xff), # A
- ]
- self.assertEqual(data, expected)
-
- def test_lock_read(self):
- # Verify that the locking mechanism works.
- def master_a(dut, port):
- driver = NativePortDriver(port)
- adr = functools.partial(dut.addr_port, row=1, col=1)
- read = functools.partial(driver.read, wait_data=False)
- yield from read(adr(bank=0))
- yield from read(adr(bank=1))
- yield from read(adr(bank=0))
- # Wait for read data to show up
- for _ in range(16):
- yield
-
- def master_b(dut, port):
- driver = NativePortDriver(port)
- adr = functools.partial(dut.addr_port, row=2, col=2)
- read = functools.partial(driver.read, wait_data=False)
- yield from read(adr(bank=1))
- yield from read(adr(bank=1))
- yield from read(adr(bank=1))
- yield from read(adr(bank=1))
- yield from read(adr(bank=1))
-
- dut = CrossbarDUT()
- ports = [dut.crossbar.get_port() for _ in range(2)]
- data = self.crossbar_test(dut, [master_a(dut, ports[0]), master_b(dut, ports[1])])
- expected = [
- self.R(bank=0, addr=dut.addr_iface(row=1, col=1), data=0x10), # A
- self.R(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x11), # B
- self.R(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x12), # B
- self.R(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x13), # B
- self.R(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x14), # B
- self.R(bank=1, addr=dut.addr_iface(row=2, col=2), data=0x15), # B
- self.R(bank=1, addr=dut.addr_iface(row=1, col=1), data=0x16), # A
- self.R(bank=0, addr=dut.addr_iface(row=1, col=1), data=0x17), # A
- ]
- self.assertEqual(data, expected)
-
- def crossbar_stress_test(self, dut, ports, n_banks, n_ops, clocks=None):
- # Runs simulation with multiple masters writing and reading to multiple banks
- controller = ControllerStub(dut.interface,
- write_latency=dut.settings.phy.write_latency,
- read_latency=dut.settings.phy.read_latency)
- # Store data produced per master
- produced = defaultdict(list)
- prng = random.Random(42)
-
- def master(dut, port, num):
- # Choose operation types based on port mode
- ops_choice = {
- "both": ["w", "r"],
- "write": ["w"],
- "read": ["r"],
- }[port.mode]
- driver = NativePortDriver(port)
-
- for i in range(n_ops):
- bank = prng.randrange(n_banks)
- # We will later distinguish data by its row address
- row = num
- col = 0x20 * num + i
- addr = dut.addr_port(bank=bank, row=row, col=col)
- addr_iface = dut.addr_iface(row=row, col=col)
- if prng.choice(ops_choice) == "w":
- yield from driver.write(addr, data=i)
- produced[num].append(self.W(bank, addr_iface, data=i, we=0xff))
- else:
- yield from driver.read(addr)
- produced[num].append(self.R(bank, addr_iface, data=None))
-
- for _ in range(8):
- yield
-
- generators = defaultdict(list)
- for i, port in enumerate(ports):
- generators[port.clock_domain].append(master(dut, port, i))
- generators["sys"] += controller.generators()
- generators["sys"].append(timeout_generator(80 * n_ops))
-
- sim_kwargs = {}
- if clocks is not None:
- sim_kwargs["clocks"] = clocks
- run_simulation(dut, generators, **sim_kwargs)
-
- # Split controller data by master, as this is what we want to compare
- consumed = defaultdict(list)
- for data in controller.data:
- master = data.addr >> (dut.settings.geom.colbits - dut.address_align)
- if isinstance(data, self.R):
- # Master couldn't know the data when it was sending
- data = data._replace(data=None)
- consumed[master].append(data)
-
- return produced, consumed, controller.data
-
- def test_stress(self):
- # Test communication in complex scenarios.
- dut = CrossbarDUT()
- ports = [dut.crossbar.get_port() for _ in range(8)]
- produced, consumed, consumed_all = self.crossbar_stress_test(dut, ports, n_banks=4, n_ops=8)
- for master in produced.keys():
- self.assertEqual(consumed[master], produced[master], msg="master = %d" % master)
-
- def test_stress_single_bank(self):
- # Test communication in complex scenarios
- dut = CrossbarDUT()
- ports = [dut.crossbar.get_port() for _ in range(4)]
- produced, consumed, consumed_all = self.crossbar_stress_test(dut, ports, n_banks=1, n_ops=8)
- for master in produced.keys():
- self.assertEqual(consumed[master], produced[master], msg="master = %d" % master)
-
- def test_stress_single_master(self):
- # Test communication in complex scenarios.
- dut = CrossbarDUT()
- ports = [dut.crossbar.get_port() for _ in range(1)]
- produced, consumed, consumed_all = self.crossbar_stress_test(dut, ports, n_banks=4, n_ops=8)
- for master in produced.keys():
- self.assertEqual(consumed[master], produced[master], msg="master = %d" % master)
-
- def test_port_cdc(self):
- # Verify that correct clock domain is being used.
- dut = CrossbarDUT()
- port = dut.crossbar.get_port(clock_domain="other")
- self.assertEqual(port.clock_domain, "other")
-
- def test_stress_cdc(self):
- # Verify communication when ports are in different clock domains.
- dut = CrossbarDUT()
- clocks = {
- "sys": 10,
- "clk1": (7, 4),
- "clk2": 12,
- }
- master_clocks = ["sys", "clk1", "clk2"]
- ports = [dut.crossbar.get_port(clock_domain=clk) for clk in master_clocks]
- produced, consumed, consumed_all = self.crossbar_stress_test(
- dut, ports, n_banks=4, n_ops=6, clocks=clocks)
- for master in produced.keys():
- self.assertEqual(consumed[master], produced[master], msg="master = %d" % master)
-
- def test_port_mode(self):
- # Verify that ports in different modes can be requested.
- dut = CrossbarDUT()
- for mode in ["both", "write", "read"]:
- port = dut.crossbar.get_port(mode=mode)
- self.assertEqual(port.mode, mode)
-
- # NOTE: Stress testing with different data widths would require complicating
- # the logic a lot to support registering data comming in multiple words (in
- # data_handler), address shifting and recreation of packets. Because of this,
- # and because data width converters are tested separately in test_adaptation,
- # here we only test if ports report correct data widths.
- def test_port_data_width_conversion(self):
- # Verify that correct port data widths are being used.
- dut = CrossbarDUT()
- dw = dut.interface.data_width
- data_widths = [dw*2, dw, dw//2]
- modes = ["both", "write", "read"]
- for mode, data_width in itertools.product(modes, data_widths):
- with self.subTest(mode=mode, data_width=data_width):
- # Up conversion is supported only for single direction ports
- if mode == "both" and data_width < dut.interface.data_width:
- with self.assertRaises(NotImplementedError):
- dut.crossbar.get_port(mode=mode, data_width=data_width)
- else:
- port = dut.crossbar.get_port(mode=mode, data_width=data_width)
- self.assertEqual(port.data_width, data_width)
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-
-from migen import *
-
-from litex.gen.sim import *
-
-from litedram.common import *
-from litedram.frontend.dma import *
-
-from test.common import *
-
-
-class DMAWriterDriver:
- def __init__(self, dma):
- self.dma = dma
-
- def write(self, pattern):
- yield self.dma.sink.valid.eq(1)
- for adr, data in pattern:
- yield self.dma.sink.address.eq(adr)
- yield self.dma.sink.data.eq(data)
- while not (yield self.dma.sink.ready):
- yield
- yield
- yield self.dma.sink.valid.eq(0)
-
- @staticmethod
- def wait_complete(port, n):
- for _ in range(n):
- while not (yield port.wdata.ready):
- yield
- yield
-
-
-class DMAReaderDriver:
- def __init__(self, dma):
- self.dma = dma
- self.data = []
-
- def read(self, address_list):
- n_last = len(self.data)
- yield self.dma.sink.valid.eq(1)
- for adr in address_list:
- yield self.dma.sink.address.eq(adr)
- while not (yield self.dma.sink.ready):
- yield
- while (yield self.dma.sink.ready):
- yield
- yield self.dma.sink.valid.eq(0)
- while len(self.data) < n_last + len(address_list):
- yield
-
- @passive
- def read_handler(self):
- yield self.dma.source.ready.eq(1)
- while True:
- if (yield self.dma.source.valid):
- self.data.append((yield self.dma.source.data))
- yield
-
-
-class TestDMA(MemoryTestDataMixin, unittest.TestCase):
-
- # LiteDRAMDMAWriter ----------------------------------------------------------------------------
-
- def dma_writer_test(self, pattern, mem_expected, data_width, **kwargs):
- class DUT(Module):
- def __init__(self):
- self.port = LiteDRAMNativeWritePort(address_width=32, data_width=data_width)
- self.submodules.dma = LiteDRAMDMAWriter(self.port, **kwargs)
-
- dut = DUT()
- driver = DMAWriterDriver(dut.dma)
- mem = DRAMMemory(data_width, len(mem_expected))
-
- generators = [
- driver.write(pattern),
- driver.wait_complete(dut.port, len(pattern)),
- mem.write_handler(dut.port),
- ]
- run_simulation(dut, generators)
- self.assertEqual(mem.mem, mem_expected)
-
- def test_dma_writer_single(self):
- # Verify DMAWriter with a single 32-bit data.
- pattern = [(0x04, 0xdeadc0de)]
- mem_expected = [0] * 32
- mem_expected[0x04] = 0xdeadc0de
- self.dma_writer_test(pattern, mem_expected, data_width=32)
-
- def test_dma_writer_multiple(self):
- # Verify DMAWriter with multiple 32-bit datas.
- data = self.pattern_test_data["32bit"]
- self.dma_writer_test(data["pattern"], data["expected"], data_width=32)
-
- def test_dma_writer_sequential(self):
- # Verify DMAWriter with sequential 32-bit datas.
- data = self.pattern_test_data["32bit_sequential"]
- self.dma_writer_test(data["pattern"], data["expected"], data_width=32)
-
- def test_dma_writer_long_sequential(self):
- # Verify DMAWriter with long sequential 32-bit datas.
- data = self.pattern_test_data["32bit_long_sequential"]
- self.dma_writer_test(data["pattern"], data["expected"], data_width=32)
-
- def test_dma_writer_no_fifo(self):
- # Verify DMAWriter without FIFO.
- data = self.pattern_test_data["32bit_long_sequential"]
- self.dma_writer_test(data["pattern"], data["expected"], data_width=32, fifo_depth=1)
-
- def test_dma_writer_fifo_buffered(self):
- # Verify DMAWriter with a buffered FIFO.
- data = self.pattern_test_data["32bit_long_sequential"]
- self.dma_writer_test(data["pattern"], data["expected"], data_width=32, fifo_buffered=True)
-
- def test_dma_writer_duplicates(self):
- # Verify DMAWriter with a duplicate addresses.
- data = self.pattern_test_data["32bit_duplicates"]
- self.dma_writer_test(data["pattern"], data["expected"], data_width=32)
-
- # LiteDRAMDMAReader ----------------------------------------------------------------------------
-
- def dma_reader_test(self, pattern, mem_expected, data_width, **kwargs):
- class DUT(Module):
- def __init__(self):
- self.port = LiteDRAMNativeReadPort(address_width=32, data_width=data_width)
- self.submodules.dma = LiteDRAMDMAReader(self.port, **kwargs)
-
- dut = DUT()
- driver = DMAReaderDriver(dut.dma)
- mem = DRAMMemory(data_width, len(mem_expected), init=mem_expected)
-
- generators = [
- driver.read([adr for adr, data in pattern]),
- driver.read_handler(),
- mem.read_handler(dut.port),
- ]
- run_simulation(dut, generators)
- self.assertEqual(driver.data, [data for adr, data in pattern])
-
- def test_dma_reader_single(self):
- # Verify DMAReader with a single 32-bit data.
- pattern = [(0x04, 0xdeadc0de)]
- mem_expected = [0] * 32
- mem_expected[0x04] = 0xdeadc0de
- self.dma_reader_test(pattern, mem_expected, data_width=32)
-
- def test_dma_reader_multiple(self):
- # Verify DMAReader with multiple 32-bit datas.
- data = self.pattern_test_data["32bit"]
- self.dma_reader_test(data["pattern"], data["expected"], data_width=32)
-
- def test_dma_reader_sequential(self):
- # Verify DMAReader with sequential 32-bit datas.
- data = self.pattern_test_data["32bit_sequential"]
- self.dma_reader_test(data["pattern"], data["expected"], data_width=32)
-
- def test_dma_reader_long_sequential(self):
- # Verify DMAReader with long sequential 32-bit datas.
- data = self.pattern_test_data["32bit_long_sequential"]
- self.dma_reader_test(data["pattern"], data["expected"], data_width=32)
-
- def test_dma_reader_no_fifo(self):
- # Verify DMAReader without FIFO.
- data = self.pattern_test_data["32bit_long_sequential"]
- self.dma_reader_test(data["pattern"], data["expected"], data_width=32, fifo_depth=1)
-
- def test_dma_reader_fifo_buffered(self):
- # Verify DMAReader with a buffered FIFO.
- data = self.pattern_test_data["32bit_long_sequential"]
- self.dma_reader_test(data["pattern"], data["expected"], data_width=32, fifo_buffered=True)
+++ /dev/null
-# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-import random
-
-from migen import *
-
-from litedram.common import *
-from litedram.frontend.ecc import *
-
-from litex.gen.sim import *
-from litex.soc.cores.ecc import *
-
-from test.common import *
-
-# Helpers ------------------------------------------------------------------------------------------
-
-def bits(value, width=32):
- # Convert int to a string representing binary value and reverse it so that we can index bits
- # easily with s[0] being LSB
- return f"{value:0{width}b}"[::-1]
-
-def frombits(bits):
- # Reverse of bits()
- return int(bits[::-1], 2)
-
-def bits_pp(value, width=32):
- # Pretty print binary value, groupped by bytes
- if isinstance(value, str):
- value = frombits(value)
- s = f"{value:0{width}b}"
- byte_chunks = [s[i:i+8] for i in range(0, len(s), 8)]
- return "0b " + " ".join(byte_chunks)
-
-def extract_ecc_data(data_width, codeword_width, codeword_bits):
- extracted = ""
- for i in range(8):
- word = codeword_bits[codeword_width*i:codeword_width*(i+1)]
- # Remove parity bit
- word = word[1:]
- data_pos = compute_data_positions(codeword_width - 1) # -1 for parity
- # Extract data bits
- word_ex = list(bits(0, 32))
- for j, d in enumerate(data_pos):
- word_ex[j] = word[d-1]
- word_ex = "".join(word_ex)
- extracted += word_ex
- return extracted
-
-# TestECC ------------------------------------------------------------------------------------------
-
-class TestECC(unittest.TestCase):
- def test_eccw_connected(self):
- # Verify LiteDRAMNativePortECCW ECC encoding.
- class DUT(Module):
- def __init__(self):
- eccw = LiteDRAMNativePortECCW(data_width_from=32*8, data_width_to=39*8)
- self.submodules.eccw = eccw
-
- def main_generator(dut):
- sink_data = seed_to_data(0, nbits=32*8)
- yield dut.eccw.sink.data.eq(sink_data)
- yield
- source_data = (yield dut.eccw.source.data)
-
- sink_data_bits = bits(sink_data, 32*8)
- source_data_bits = bits(source_data, 39*8)
- self.assertNotEqual(sink_data_bits, source_data_bits[:len(sink_data_bits)])
-
- source_extracted = extract_ecc_data(32, 39, source_data_bits)
- # Assert each word separately for more readable assert messages
- for i in range(8):
- word = slice(32*i, 32*(i+1))
- self.assertEqual(bits_pp(source_extracted[word]), bits_pp(sink_data_bits[word]),
- msg=f"Mismatch at i = {i}")
-
- dut = DUT()
- run_simulation(dut, main_generator(dut))
-
- def test_eccw_we_enabled(self):
- # Verify LiteDRAMNativePortECCW always set bytes enable.
- class DUT(Module):
- def __init__(self):
- eccw = LiteDRAMNativePortECCW(data_width_from=32*8, data_width_to=39*8)
- self.submodules.eccw = eccw
-
- def main_generator(dut):
- yield
- source_we = (yield dut.eccw.source.we)
-
- self.assertEqual(bits_pp(source_we, 39//8), bits_pp(2**len(dut.eccw.source.we) - 1))
-
- dut = DUT()
- run_simulation(dut, main_generator(dut))
-
- def test_eccr_connected(self):
- # Verify LiteDRAMNativePortECCR ECC decoding.
- class DUT(Module):
- def __init__(self):
- eccr = LiteDRAMNativePortECCR(data_width_from=32*8, data_width_to=39*8)
- self.submodules.eccr = eccr
-
- def main_generator(dut):
- sink_data = seed_to_data(0, nbits=(39*8 // 32 + 1) * 32)
-
- yield dut.eccr.sink.data.eq(sink_data)
- yield
- source_data = (yield dut.eccr.source.data)
-
- sink_data_bits = bits(sink_data, 39*8)
- source_data_bits = bits(source_data, 32*8)
- self.assertNotEqual(sink_data_bits[:len(source_data_bits)], source_data_bits)
-
- sink_extracted = extract_ecc_data(32, 39, sink_data_bits)
- self.assertEqual(bits_pp(sink_extracted), bits_pp(source_data_bits))
- # Assert each word separately for more readable assert messages
- for i in range(8):
- word = slice(32*i, 32*(i+1))
- self.assertEqual(bits_pp(sink_extracted[word]), bits_pp(source_data_bits[word]),
- msg=f"Mismatch at i = {i}")
-
- dut = DUT()
- run_simulation(dut, main_generator(dut))
-
- def test_eccr_errors_connected_when_sink_valid(self):
- # Verify LiteDRAMNativePortECCR Error detection.
- class DUT(Module):
- def __init__(self):
- eccr = LiteDRAMNativePortECCR(data_width_from=32*8, data_width_to=39*8)
- self.submodules.eccr = eccr
-
- def main_generator(dut):
- yield dut.eccr.enable.eq(1)
- yield dut.eccr.sink.data.eq(0b10) # Wrong parity bit
- yield
- # Verify no errors are detected
- self.assertEqual((yield dut.eccr.sec), 0)
- self.assertEqual((yield dut.eccr.ded), 0)
- # Set sink.valid and verify errors parity error is detected
- yield dut.eccr.sink.valid.eq(1)
- yield
- self.assertEqual((yield dut.eccr.sec), 1)
- self.assertEqual((yield dut.eccr.ded), 0)
-
- dut = DUT()
- run_simulation(dut, main_generator(dut))
-
- def ecc_encode_decode_test(self, from_width, to_width, n, pre=None, post=None, **kwargs):
- """ECC encoding/decoding generic test."""
- class DUT(Module):
- def __init__(self):
- self.port_from = LiteDRAMNativePort("both", 24, from_width)
- self.port_to = LiteDRAMNativePort("both", 24, to_width)
- self.submodules.ecc = LiteDRAMNativePortECC(self.port_from, self.port_to, **kwargs)
- self.mem = DRAMMemory(to_width, n)
-
- self.wdata = [seed_to_data(i, nbits=from_width) for i in range(n)]
- self.rdata = []
-
- def main_generator(dut):
- if pre is not None:
- yield from pre(dut)
-
- port = dut.port_from
-
- # Write
- for i in range(n):
- yield port.cmd.valid.eq(1)
- yield port.cmd.we.eq(1)
- yield port.cmd.addr.eq(i)
- yield
- while (yield port.cmd.ready) == 0:
- yield
- yield port.cmd.valid.eq(0)
- yield
- yield port.wdata.valid.eq(1)
- yield port.wdata.data.eq(dut.wdata[i])
- yield
- while (yield port.wdata.ready) == 0:
- yield
- yield port.wdata.valid.eq(0)
- yield
-
- # Read
- for i in range(n):
- yield port.cmd.valid.eq(1)
- yield port.cmd.we.eq(0)
- yield port.cmd.addr.eq(i)
- yield
- while (yield port.cmd.ready) == 0:
- yield
- yield port.cmd.valid.eq(0)
- yield
- while (yield port.rdata.valid) == 0:
- yield
- dut.rdata.append((yield port.rdata.data))
- yield port.rdata.ready.eq(1)
- yield
- yield port.rdata.ready.eq(0)
- yield
-
- if post is not None:
- yield from post(dut)
-
- dut = DUT()
- generators = [
- main_generator(dut),
- dut.mem.write_handler(dut.port_to),
- dut.mem.read_handler(dut.port_to),
- ]
- run_simulation(dut, generators)
- return dut
-
- def test_ecc_32_7(self):
- # Verify encoding/decoding on 32 data bits + 6 code bits + parity bit.
- dut = self.ecc_encode_decode_test(32*8, 39*8, 2)
- self.assertEqual(dut.wdata, dut.rdata)
-
- def test_ecc_64_8(self):
- # Verify encoding/decoding on 64 data bits + 7 code bits + parity bit.
- dut = self.ecc_encode_decode_test(64*8, 72*8, 2)
- self.assertEqual(dut.wdata, dut.rdata)
-
- def test_ecc_sec_errors(self):
- # Verify SEC errors detection/correction with 1-bit flip.
- def pre(dut):
- yield from dut.ecc.flip.write(0b00000100)
-
- def post(dut):
- dut.sec_errors = (yield from dut.ecc.sec_errors.read())
- dut.ded_errors = (yield from dut.ecc.ded_errors.read())
-
- dut = self.ecc_encode_decode_test(8*8, 13*8, 4, pre, post, with_error_injection=True)
- self.assertEqual(dut.wdata, dut.rdata)
- self.assertEqual(dut.sec_errors, 4)
- self.assertEqual(dut.ded_errors, 0)
-
- def test_ecc_ded_errors(self):
- # Verify DED errors detection with 2-bit flip.
- def pre(dut):
- yield from dut.ecc.flip.write(0b00001100)
-
- def post(dut):
- dut.sec_errors = (yield from dut.ecc.sec_errors.read())
- dut.ded_errors = (yield from dut.ecc.ded_errors.read())
-
- dut = self.ecc_encode_decode_test(8*8, 13*8, 4, pre, post, with_error_injection=True)
- self.assertNotEqual(dut.wdata, dut.rdata)
- self.assertEqual(dut.sec_errors, 0)
- self.assertEqual(dut.ded_errors, 4)
-
- def test_ecc_decoder_disable(self):
- # Verify enable control.
- def pre(dut):
- yield from dut.ecc.flip.write(0b10101100)
- yield from dut.ecc.enable.write(0)
-
- def post(dut):
- dut.sec_errors = (yield from dut.ecc.sec_errors.read())
- dut.ded_errors = (yield from dut.ecc.ded_errors.read())
-
- dut = self.ecc_encode_decode_test(8*8, 13*8, 4, pre, post, with_error_injection=True)
- self.assertNotEqual(dut.wdata, dut.rdata)
- self.assertEqual(dut.sec_errors, 0)
- self.assertEqual(dut.ded_errors, 0)
-
- def test_ecc_clear_sec_errors(self):
- # Verify SEC errors clear.
- def pre(dut):
- yield from dut.ecc.flip.write(0b00000100)
-
- def post(dut):
- # Read errors after test (SEC errors expected)
- dut.sec_errors = (yield from dut.ecc.sec_errors.read())
- dut.ded_errors = (yield from dut.ecc.ded_errors.read())
-
- # Clear errors counters
- yield from dut.ecc.clear.write(1)
- yield
-
- # Re-Read errors to verify clear
- dut.sec_errors_c = (yield from dut.ecc.sec_errors.read())
- dut.ded_errors_c = (yield from dut.ecc.ded_errors.read())
-
- dut = self.ecc_encode_decode_test(8*8, 13*8, 4, pre, post, with_error_injection=True)
- self.assertEqual(dut.wdata, dut.rdata)
- self.assertNotEqual(dut.sec_errors, 0)
- self.assertEqual(dut.ded_errors, 0)
- self.assertEqual(dut.sec_errors_c, 0)
- self.assertEqual(dut.ded_errors_c, 0)
-
- def test_ecc_clear_ded_errors(self):
- # Verify DED errors clear.
- def pre(dut):
- yield from dut.ecc.flip.write(0b10101100)
-
- def post(dut):
- # Read errors after test (DED errors expected)
- dut.sec_errors = (yield from dut.ecc.sec_errors.read())
- dut.ded_errors = (yield from dut.ecc.ded_errors.read())
-
- # Clear errors counters
- yield from dut.ecc.clear.write(1)
- yield
-
- # Re-Read errors to verify clear
- dut.sec_errors_c = (yield from dut.ecc.sec_errors.read())
- dut.ded_errors_c = (yield from dut.ecc.ded_errors.read())
-
- dut = self.ecc_encode_decode_test(8*8, 13*8, 4, pre, post, with_error_injection=True)
- self.assertNotEqual(dut.wdata, dut.rdata)
- self.assertEqual(dut.sec_errors, 0)
- self.assertNotEqual(dut.ded_errors, 0)
- self.assertEqual(dut.sec_errors_c, 0)
- self.assertEqual(dut.ded_errors_c, 0)
-
-
-if __name__ == "__main__":
- unittest.main()
+++ /dev/null
-# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-import unittest
-import os
-
-
-def build_config(name):
- errors = 0
- os.system("rm -rf examples/build")
- os.system("cd examples && python3 ../litedram/gen.py {}.yml".format(name))
- errors += not os.path.isfile("examples/build/gateware/litedram_core.v")
- os.system("rm -rf examples/build")
- return errors
-
-
-class TestExamples(unittest.TestCase):
- def test_arty(self):
- errors = build_config("arty")
- self.assertEqual(errors, 0)
-
- def test_nexys4ddr(self):
- errors = build_config("nexys4ddr")
- self.assertEqual(errors, 0)
-
- def test_genesys2(self):
- errors = build_config("genesys2")
- self.assertEqual(errors, 0)
+++ /dev/null
-# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-import random
-
-from migen import *
-
-from litex.soc.interconnect.stream import *
-
-from litedram.common import LiteDRAMNativeWritePort
-from litedram.common import LiteDRAMNativeReadPort
-from litedram.frontend.fifo import LiteDRAMFIFO, _LiteDRAMFIFOCtrl
-from litedram.frontend.fifo import _LiteDRAMFIFOWriter, _LiteDRAMFIFOReader
-
-from test.common import *
-
-class TestFIFO(unittest.TestCase):
- @passive
- def fifo_ctrl_flag_checker(self, fifo_ctrl, write_threshold, read_threshold):
- # Checks the combinational logic
- while True:
- level = (yield fifo_ctrl.level)
- self.assertEqual((yield fifo_ctrl.writable), level < write_threshold)
- self.assertEqual((yield fifo_ctrl.readable), level > read_threshold)
- yield
-
- # _LiteDRAMFIFOCtrl ----------------------------------------------------------------------------
-
- def test_fifo_ctrl_address_changes(self):
- # Verify FIFOCtrl address changes.
- # We are ignoring thresholds (so readable/writable signals)
- dut = _LiteDRAMFIFOCtrl(base=0, depth=16, read_threshold=0, write_threshold=16)
-
- def main_generator():
- self.assertEqual((yield dut.write_address), 0)
- self.assertEqual((yield dut.read_address), 0)
-
- # Write address
- yield dut.write.eq(1)
- yield
- # Write_address gets updated 1 cycle later
- for i in range(24 - 1):
- self.assertEqual((yield dut.write_address), i % 16)
- yield
- yield dut.write.eq(0)
- yield
- self.assertEqual((yield dut.write_address), 24 % 16)
-
- # Read address
- yield dut.read.eq(1)
- yield
- for i in range(24 - 1):
- self.assertEqual((yield dut.read_address), i % 16)
- yield
- yield dut.read.eq(0)
- yield
- self.assertEqual((yield dut.read_address), 24 % 16)
-
- generators = [
- main_generator(),
- self.fifo_ctrl_flag_checker(dut, write_threshold=16, read_threshold=0),
- ]
- run_simulation(dut, generators)
-
- def test_fifo_ctrl_level_changes(self):
- # Verify FIFOCtrl level changes.
- dut = _LiteDRAMFIFOCtrl(base=0, depth=16, read_threshold=0, write_threshold=16)
-
- def main_generator():
- self.assertEqual((yield dut.level), 0)
-
- # Level
- def check_level_diff(write, read, diff):
- level = (yield dut.level)
- yield dut.write.eq(write)
- yield dut.read.eq(read)
- yield
- yield dut.write.eq(0)
- yield dut.read.eq(0)
- yield
- self.assertEqual((yield dut.level), level + diff)
-
- check_level_diff(write=1, read=0, diff=+1)
- check_level_diff(write=1, read=0, diff=+1)
- check_level_diff(write=1, read=1, diff=+0)
- check_level_diff(write=1, read=1, diff=+0)
- check_level_diff(write=0, read=1, diff=-1)
- check_level_diff(write=0, read=1, diff=-1)
-
- generators = [
- main_generator(),
- self.fifo_ctrl_flag_checker(dut, write_threshold=16, read_threshold=0),
- ]
- run_simulation(dut, generators)
-
- # _LiteDRAMFIFOWriter --------------------------------------------------------------------------
-
- def fifo_writer_test(self, depth, sequence_len, write_threshold):
- class DUT(Module):
- def __init__(self):
- self.port = LiteDRAMNativeWritePort(address_width=32, data_width=32)
- ctrl = _LiteDRAMFIFOCtrl(base=8, depth=depth,
- read_threshold = 0,
- write_threshold = write_threshold)
- self.submodules.ctrl = ctrl
- writer = _LiteDRAMFIFOWriter(data_width=32, port=self.port, ctrl=ctrl)
- self.submodules.writer = writer
-
- self.memory = DRAMMemory(32, 128)
- assert 8 + sequence_len <= len(self.memory.mem)
-
- write_data = [seed_to_data(i) for i in range(sequence_len)]
-
- def generator(dut):
- for data in write_data:
- yield dut.writer.sink.valid.eq(1)
- yield dut.writer.sink.data.eq(data)
- yield
- while (yield dut.writer.sink.ready) == 0:
- yield
- yield dut.writer.sink.valid.eq(0)
-
- for _ in range(16):
- yield
-
- dut = DUT()
- generators = [
- generator(dut),
- dut.memory.write_handler(dut.port),
- self.fifo_ctrl_flag_checker(dut.ctrl,
- write_threshold = write_threshold,
- read_threshold = 0),
- timeout_generator(1500),
- ]
- run_simulation(dut, generators)
-
- mem_expected = [0] * len(dut.memory.mem)
- for i, data in enumerate(write_data):
- mem_expected[8 + i%depth] = data
- self.assertEqual(dut.memory.mem, mem_expected)
-
- def test_fifo_writer_sequence(self):
- # Verify simple FIFOWriter sequence.
- self.fifo_writer_test(sequence_len=48, depth=64, write_threshold=64)
-
- def test_fifo_writer_address_wraps(self):
- # Verify FIFOWriter sequence with address wraps.
- self.fifo_writer_test(sequence_len=48, depth=32, write_threshold=64)
-
- def test_fifo_writer_stops_after_threshold(self):
- # Verify FIFOWriter sequence with stop after threshold is reached.
- with self.assertRaises(TimeoutError):
- self.fifo_writer_test(sequence_len=48, depth=32, write_threshold=32)
-
- # _LiteDRAMFIFOReader --------------------------------------------------------------------------
-
- def fifo_reader_test(self, depth, sequence_len, read_threshold, inital_writes=0):
- memory_data = [seed_to_data(i) for i in range(128)]
- read_data = []
-
- class DUT(Module):
- def __init__(self):
- self.port = LiteDRAMNativeReadPort(address_width=32, data_width=32)
- ctrl = _LiteDRAMFIFOCtrl(base=8, depth=depth,
- read_threshold = read_threshold,
- write_threshold = depth)
- reader = _LiteDRAMFIFOReader(data_width=32, port=self.port, ctrl=ctrl)
- self.submodules.ctrl = ctrl
- self.submodules.reader = reader
-
- self.memory = DRAMMemory(32, len(memory_data), init=memory_data)
- assert 8 + sequence_len <= len(self.memory.mem)
-
- def reader(dut):
- # Fake writing to fifo
- yield dut.ctrl.write.eq(1)
- for _ in range(inital_writes):
- yield
- yield dut.ctrl.write.eq(0)
- yield
-
- for _ in range(sequence_len):
- # Fake single write
- yield dut.ctrl.write.eq(1)
- yield
- yield dut.ctrl.write.eq(0)
-
- while (yield dut.reader.source.valid) == 0:
- yield
- read_data.append((yield dut.reader.source.data))
- yield dut.reader.source.ready.eq(1)
- yield
- yield dut.reader.source.ready.eq(0)
- yield
-
- dut = DUT()
- generators = [
- reader(dut),
- dut.memory.read_handler(dut.port),
- self.fifo_ctrl_flag_checker(dut.ctrl,
- write_threshold = depth,
- read_threshold = read_threshold),
- timeout_generator(1500),
- ]
- run_simulation(dut, generators)
-
- read_data_expected = [memory_data[8 + i%depth] for i in range(sequence_len)]
- self.assertEqual(read_data, read_data_expected)
-
- def test_fifo_reader_sequence(self):
- # Verify simple FIFOReader sequence.
- self.fifo_reader_test(sequence_len=48, depth=64, read_threshold=0)
-
- def test_fifo_reader_address_wraps(self):
- # Verify FIFOReader sequence with address wraps.
- self.fifo_reader_test(sequence_len=48, depth=32, read_threshold=0)
-
- def test_fifo_reader_requires_threshold(self):
- # Verify FIFOReader sequence with start after threshold is reached.
- with self.assertRaises(TimeoutError):
- self.fifo_reader_test(sequence_len=48, depth=32, read_threshold=8)
- # Will work after we perform the initial writes
- self.fifo_reader_test(sequence_len=48, depth=32, read_threshold=8, inital_writes=8)
-
- # LiteDRAMFIFO ---------------------------------------------------------------------------------
-
- def test_fifo_default_thresholds(self):
- # Verify FIFO with default threshold.
- # Defaults: read_threshold=0, write_threshold=depth
- read_threshold, write_threshold = (0, 128)
- write_port = LiteDRAMNativeWritePort(address_width=32, data_width=32)
- read_port = LiteDRAMNativeReadPort(address_width=32, data_width=32)
- fifo = LiteDRAMFIFO(data_width=32, base=0, depth=write_threshold,
- write_port = write_port,
- read_port = read_port)
-
- def generator():
- yield write_port.cmd.ready.eq(1)
- yield write_port.wdata.ready.eq(1)
- for i in range(write_threshold):
- yield fifo.sink.valid.eq(1)
- yield fifo.sink.data.eq(0)
- yield
- while (yield fifo.sink.ready) == 0:
- yield
- yield
-
- checker = self.fifo_ctrl_flag_checker(fifo.ctrl, write_threshold, read_threshold)
- run_simulation(fifo, [generator(), checker])
-
- def test_fifo(self):
- # Verify FIFO.
- class DUT(Module):
- def __init__(self):
- self.write_port = LiteDRAMNativeWritePort(address_width=32, data_width=32)
- self.read_port = LiteDRAMNativeReadPort(address_width=32, data_width=32)
- self.submodules.fifo = LiteDRAMFIFO(
- data_width = 32,
- depth = 32,
- base = 16,
- write_port = self.write_port,
- read_port = self.read_port,
- read_threshold = 8,
- write_threshold = 32 - 8
- )
-
- self.memory = DRAMMemory(32, 128)
-
- def generator(dut, valid_random=90):
- prng = random.Random(42)
- # We need 8 more writes to account for read_threshold=8
- for i in range(64 + 8):
- while prng.randrange(100) < valid_random:
- yield
- yield dut.fifo.sink.valid.eq(1)
- yield dut.fifo.sink.data.eq(i)
- yield
- while (yield dut.fifo.sink.ready) != 1:
- yield
- yield dut.fifo.sink.valid.eq(0)
-
- def checker(dut, ready_random=90):
- prng = random.Random(42)
- for i in range(64):
- yield dut.fifo.source.ready.eq(0)
- yield
- while (yield dut.fifo.source.valid) != 1:
- yield
- while prng.randrange(100) < ready_random:
- yield
- yield dut.fifo.source.ready.eq(1)
- self.assertEqual((yield dut.fifo.source.data), i)
- yield
-
- dut = DUT()
- generators = [
- generator(dut),
- checker(dut),
- dut.memory.write_handler(dut.write_port),
- dut.memory.read_handler(dut.read_port)
- ]
- run_simulation(dut, generators)
+++ /dev/null
-# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-import os
-import filecmp
-import unittest
-
-from litex.build.tools import write_to_file
-
-from litedram.init import get_sdram_phy_c_header, get_sdram_phy_py_header
-
-
-def compare_with_reference(content, filename):
- write_to_file(filename, content)
- r = filecmp.cmp(filename, os.path.join("test", "reference", filename))
- os.remove(filename)
- return r
-
-
-class TestInit(unittest.TestCase):
- def test_sdr(self):
- from litex.boards.targets.minispartan6 import BaseSoC
- soc = BaseSoC()
- c_header = get_sdram_phy_c_header(soc.sdram.controller.settings.phy, soc.sdram.controller.settings.timing)
- py_header = get_sdram_phy_py_header(soc.sdram.controller.settings.phy, soc.sdram.controller.settings.timing)
- self.assertEqual(compare_with_reference(c_header, "sdr_init.h"), True)
- self.assertEqual(compare_with_reference(py_header, "sdr_init.py"), True)
-
- def test_ddr3(self):
- from litex.boards.targets.kc705 import BaseSoC
- soc = BaseSoC()
- c_header = get_sdram_phy_c_header(soc.sdram.controller.settings.phy, soc.sdram.controller.settings.timing)
- py_header = get_sdram_phy_py_header(soc.sdram.controller.settings.phy, soc.sdram.controller.settings.timing)
- self.assertEqual(compare_with_reference(c_header, "ddr3_init.h"), True)
- self.assertEqual(compare_with_reference(py_header, "ddr3_init.py"), True)
-
- def test_ddr4(self):
- from litex.boards.targets.kcu105 import BaseSoC
- soc = BaseSoC(max_sdram_size=0x4000000)
- c_header = get_sdram_phy_c_header(soc.sdram.controller.settings.phy, soc.sdram.controller.settings.timing)
- py_header = get_sdram_phy_py_header(soc.sdram.controller.settings.phy, soc.sdram.controller.settings.timing)
- self.assertEqual(compare_with_reference(c_header, "ddr4_init.h"), True)
- self.assertEqual(compare_with_reference(py_header, "ddr4_init.py"), True)
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import os
-import csv
-import unittest
-
-import litedram.modules
-from litedram.modules import SDRAMModule, DDR3SPDData
-
-
-def load_spd_reference(filename):
- """Load reference SPD data from a CSV file
-
- Micron reference SPD data can be obtained from:
- https://www.micron.com/support/tools-and-utilities/serial-presence-detect
- """
- script_dir = os.path.dirname(os.path.realpath(__file__))
- path = os.path.join(script_dir, "spd_data", filename)
- data = [0] * 256
- with open(path) as f:
- reader = csv.DictReader(f)
- for row in reader:
- address = row["Byte Number"]
- value = row["Byte Value"]
- # Ignore ranges (data we care about is specified per byte anyway)
- if len(address.split("-")) == 1:
- data[int(address)] = int(value, 16)
- return data
-
-
-class TestSPD(unittest.TestCase):
- def test_tck_to_speedgrade(self):
- # Verify that speedgrade transfer rates are calculated correctly from tck
- tck_to_speedgrade = {
- 2.5: 800,
- 1.875: 1066,
- 1.5: 1333,
- 1.25: 1600,
- 1.071: 1866,
- 0.938: 2133,
- }
- for tck, speedgrade in tck_to_speedgrade.items():
- self.assertEqual(speedgrade, DDR3SPDData.speedgrade_freq(tck))
-
- def compare_geometry(self, module, module_ref):
- self.assertEqual(module.nbanks, module_ref.nbanks)
- self.assertEqual(module.nrows, module_ref.nrows)
- self.assertEqual(module.ncols, module_ref.ncols)
-
- def compare_technology_timings(self, module, module_ref, omit=None):
- timings = {"tREFI", "tWTR", "tCCD", "tRRD", "tZQCS"}
- if omit is not None:
- timings -= omit
- for timing in timings:
- txx = getattr(module.technology_timings, timing)
- txx_ref = getattr(module_ref.technology_timings, timing)
- with self.subTest(txx=timing):
- self.assertEqual(txx, txx_ref)
-
- def compare_speedgrade_timings(self, module, module_ref, omit=None):
- timings = {"tRP", "tRCD", "tWR", "tRFC", "tFAW", "tRAS"}
- if omit is not None:
- timings -= omit
- for freq, speedgrade_timings in module.speedgrade_timings.items():
- if freq == "default":
- continue
- for timing in timings:
- txx = getattr(speedgrade_timings, timing)
- txx_ref = getattr(module_ref.speedgrade_timings[freq], timing)
- with self.subTest(freq=freq, txx=timing):
- self.assertEqual(txx, txx_ref)
-
- def compare_modules(self, module, module_ref, omit=None):
- self.assertEqual(module.memtype, module_ref.memtype)
- self.assertEqual(module.rate, module_ref.rate)
- self.compare_geometry(module, module_ref)
- self.compare_technology_timings(module, module_ref, omit=omit)
- self.compare_speedgrade_timings(module, module_ref, omit=omit)
-
- def test_MT16KTF1G64HZ(self):
- kwargs = dict(clk_freq=125e6, rate="1:4")
- module_ref = litedram.modules.MT16KTF1G64HZ(**kwargs)
-
- with self.subTest(speedgrade="-1G6"):
- data = load_spd_reference("MT16KTF1G64HZ-1G6P1.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- self.compare_modules(module, module_ref)
- sgt = module.speedgrade_timings["1600"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 48.125)
-
- with self.subTest(speedgrade="-1G9"):
- data = load_spd_reference("MT16KTF1G64HZ-1G9E1.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- # tRRD it different for this speedgrade
- self.compare_modules(module, module_ref, omit={"tRRD"})
- self.assertEqual(module.technology_timings.tRRD, (4, 5))
- sgt = module.speedgrade_timings["1866"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 47.125)
-
- def test_MT18KSF1G72HZ(self):
- kwargs = dict(clk_freq=125e6, rate="1:4")
- module_ref = litedram.modules.MT18KSF1G72HZ(**kwargs)
-
- with self.subTest(speedgrade="-1G6"):
- data = load_spd_reference("MT18KSF1G72HZ-1G6E2.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- self.compare_modules(module, module_ref)
- sgt = module.speedgrade_timings["1600"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 48.125)
-
- with self.subTest(speedgrade="-1G4"):
- data = load_spd_reference("MT18KSF1G72HZ-1G4E2.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- self.compare_modules(module, module_ref)
- sgt = module.speedgrade_timings["1333"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 49.125)
-
- def test_MT8JTF12864(self):
- kwargs = dict(clk_freq=125e6, rate="1:4")
- module_ref = litedram.modules.MT8JTF12864(**kwargs)
-
- data = load_spd_reference("MT8JTF12864AZ-1G4G1.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- self.compare_modules(module, module_ref)
- sgt = module.speedgrade_timings["1333"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 49.125)
-
- def test_MT8KTF51264(self):
- kwargs = dict(clk_freq=100e6, rate="1:4")
- module_ref = litedram.modules.MT8KTF51264(**kwargs)
-
- with self.subTest(speedgrade="-1G4"):
- data = load_spd_reference("MT8KTF51264HZ-1G4E1.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- self.compare_modules(module, module_ref)
- sgt = module.speedgrade_timings["1333"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 49.125)
-
- with self.subTest(speedgrade="-1G6"):
- data = load_spd_reference("MT8KTF51264HZ-1G6E1.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- self.compare_modules(module, module_ref)
- sgt = module.speedgrade_timings["1600"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 48.125)
-
- with self.subTest(speedgrade="-1G9"):
- data = load_spd_reference("MT8KTF51264HZ-1G9P1.csv")
- module = SDRAMModule.from_spd_data(data, kwargs["clk_freq"])
- # tRRD different for this timing
- self.compare_modules(module, module_ref, omit={"tRRD"})
- self.assertEqual(module.technology_timings.tRRD, (4, 5))
- sgt = module.speedgrade_timings["1866"]
- self.assertEqual(sgt.tRP, 13.125)
- self.assertEqual(sgt.tRCD, 13.125)
- self.assertEqual(sgt.tRP + sgt.tRAS, 47.125)
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import copy
-import random
-import unittest
-from collections import namedtuple
-
-from migen import *
-
-from litex.soc.interconnect import stream
-
-from litedram.common import *
-from litedram.phy import dfi
-from litedram.core.multiplexer import Multiplexer
-
-# load after "* imports" to avoid using Migen version of vcd.py
-from litex.gen.sim import run_simulation
-
-from test.common import timeout_generator, CmdRequestRWDriver
-
-
-def dfi_cmd_to_char(cas_n, ras_n, we_n):
- return {
- (1, 1, 1): "_",
- (0, 1, 0): "w",
- (0, 1, 1): "r",
- (1, 0, 1): "a",
- (1, 0, 0): "p",
- (0, 0, 1): "f",
- }[(cas_n, ras_n, we_n)]
-
-
-class BankMachineStub:
- def __init__(self, babits, abits):
- self.cmd = stream.Endpoint(cmd_request_rw_layout(a=abits, ba=babits))
- self.refresh_req = Signal()
- self.refresh_gnt = Signal()
-
-
-class RefresherStub:
- def __init__(self, babits, abits):
- self.cmd = stream.Endpoint(cmd_request_rw_layout(a=abits, ba=babits))
-
-
-class MultiplexerDUT(Module):
- # Define default settings that can be overwritten in specific tests use only these settings
- # that we actually need for Multiplexer.
- default_controller_settings = dict(
- read_time = 32,
- write_time = 16,
- with_bandwidth = False,
- )
- default_phy_settings = dict(
- nphases = 2,
- rdphase = 0,
- wrphase = 1,
- rdcmdphase = 1,
- wrcmdphase = 0,
- read_latency = 5,
- cwl = 3,
- # Indirectly
- nranks = 1,
- databits = 16,
- dfi_databits = 2*16,
- memtype = "DDR2",
- )
- default_geom_settings = dict(
- bankbits = 3,
- rowbits = 13,
- colbits = 10,
- )
- default_timing_settings = dict(
- tWTR = 2,
- tFAW = None,
- tCCD = 1,
- tRRD = None,
- )
-
- def __init__(self,
- controller_settings = None,
- phy_settings = None,
- geom_settings = None,
- timing_settings = None):
- # Update settings if provided
- def updated(settings, update):
- copy = settings.copy()
- copy.update(update or {})
- return copy
-
- controller_settings = updated(self.default_controller_settings, controller_settings)
- phy_settings = updated(self.default_phy_settings, phy_settings)
- geom_settings = updated(self.default_geom_settings, geom_settings)
- timing_settings = updated(self.default_timing_settings, timing_settings)
-
- # Use simpler settigns to include only Multiplexer-specific members
- class SimpleSettings(Settings):
- def __init__(self, **kwargs):
- self.set_attributes(kwargs)
-
- settings = SimpleSettings(**controller_settings)
- settings.phy = SimpleSettings(**phy_settings)
- settings.geom = SimpleSettings(**geom_settings)
- settings.timing = SimpleSettings(**timing_settings)
- settings.geom.addressbits = max(settings.geom.rowbits, settings.geom.colbits)
- self.settings = settings
-
- # Create interfaces and stubs required to instantiate Multiplexer
- abits = settings.geom.addressbits
- babits = settings.geom.bankbits
- nbanks = 2**babits
- nranks = settings.phy.nranks
- self.bank_machines = [BankMachineStub(abits=abits, babits=babits)
- for _ in range(nbanks*nranks)]
- self.refresher = RefresherStub(abits=abits, babits=babits)
- self.dfi = dfi.Interface(
- addressbits = abits,
- bankbits = babits,
- nranks = settings.phy.nranks,
- databits = settings.phy.dfi_databits,
- nphases = settings.phy.nphases)
- address_align = log2_int(burst_lengths[settings.phy.memtype])
- self.interface = LiteDRAMInterface(address_align=address_align, settings=settings)
-
- # Add Multiplexer
- self.submodules.multiplexer = Multiplexer(settings, self.bank_machines, self.refresher,
- self.dfi, self.interface)
-
- # Add helpers for driving bank machines/refresher
- self.bm_drivers = [CmdRequestRWDriver(bm.cmd, i) for i, bm in enumerate(self.bank_machines)]
- self.refresh_driver = CmdRequestRWDriver(self.refresher.cmd, i=1)
-
- def fsm_state(self):
- # Return name of current state of Multiplexer's FSM
- return self.multiplexer.fsm.decoding[(yield self.multiplexer.fsm.state)]
-
-
-class TestMultiplexer(unittest.TestCase):
- def test_init(self):
- # Verify that instantiation of Multiplexer in MultiplexerDUT is correct. This will fail if
- # Multiplexer starts using any new setting from controller.settings.
- MultiplexerDUT()
-
- def test_fsm_start_at_read(self):
- # FSM should start at READ state (assumed in some other tests).
- def main_generator(dut):
- self.assertEqual((yield from dut.fsm_state()), "READ")
-
- dut = MultiplexerDUT()
- run_simulation(dut, main_generator(dut))
-
- def test_fsm_read_to_write_latency(self):
- # Verify the timing of READ to WRITE transition.
- def main_generator(dut):
- rtw = dut.settings.phy.read_latency
- expected = "r" + (rtw - 1) * ">" + "w"
- states = ""
-
- # Set write_available=1
- yield from dut.bm_drivers[0].write()
- yield
-
- for _ in range(len(expected)):
- state = (yield from dut.fsm_state())
- # Use ">" for all other states, as FSM.delayed_enter uses anonymous states instead
- # of staying in RTW
- states += {
- "READ": "r",
- "WRITE": "w",
- }.get(state, ">")
- yield
-
- self.assertEqual(states, expected)
-
- dut = MultiplexerDUT()
- run_simulation(dut, main_generator(dut))
-
- def test_fsm_write_to_read_latency(self):
- # Verify the timing of WRITE to READ transition.
- def main_generator(dut):
- write_latency = math.ceil(dut.settings.phy.cwl / dut.settings.phy.nphases)
- wtr = dut.settings.timing.tWTR + write_latency + dut.settings.timing.tCCD or 0
-
- expected = "w" + (wtr - 1) * ">" + "r"
- states = ""
-
- # Simulate until we are in WRITE
- yield from dut.bm_drivers[0].write()
- while (yield from dut.fsm_state()) != "WRITE":
- yield
-
- # Set read_available=1
- yield from dut.bm_drivers[0].read()
- yield
-
- for _ in range(len(expected)):
- state = (yield from dut.fsm_state())
- states += {
- "READ": "r",
- "WRITE": "w",
- }.get(state, ">")
- yield
-
- self.assertEqual(states, expected)
-
- dut = MultiplexerDUT()
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_steer_read_correct_phases(self):
- # Check that correct phases are being used during READ.
- def main_generator(dut):
- yield from dut.bm_drivers[2].read()
- yield from dut.bm_drivers[3].activate()
-
- while not (yield dut.bank_machines[2].cmd.ready):
- yield
- yield
-
- # fsm starts in READ
- for phase in range(dut.settings.phy.nphases):
- if phase == dut.settings.phy.rdphase:
- self.assertEqual((yield dut.dfi.phases[phase].bank), 2)
- elif phase == dut.settings.phy.rdcmdphase:
- self.assertEqual((yield dut.dfi.phases[phase].bank), 3)
- else:
- self.assertEqual((yield dut.dfi.phases[phase].bank), 0)
-
- dut = MultiplexerDUT()
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_steer_write_correct_phases(self):
- # Check that correct phases are being used during WRITE.
- def main_generator(dut):
- yield from dut.bm_drivers[2].write()
- yield from dut.bm_drivers[3].activate()
-
- while not (yield dut.bank_machines[2].cmd.ready):
- yield
- yield
-
- # fsm starts in READ
- for phase in range(dut.settings.phy.nphases):
- if phase == dut.settings.phy.wrphase:
- self.assertEqual((yield dut.dfi.phases[phase].bank), 2)
- elif phase == dut.settings.phy.wrcmdphase:
- self.assertEqual((yield dut.dfi.phases[phase].bank), 3)
- else:
- self.assertEqual((yield dut.dfi.phases[phase].bank), 0)
-
- dut = MultiplexerDUT()
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_single_phase_cmd_req(self):
- # Verify that, for a single phase, commands are sent sequentially.
- def main_generator(dut):
- yield from dut.bm_drivers[2].write()
- yield from dut.bm_drivers[3].activate()
- ready = {2: dut.bank_machines[2].cmd.ready, 3: dut.bank_machines[3].cmd.ready}
-
- # Activate should appear first
- while not ((yield ready[2]) or (yield ready[3])):
- yield
- yield from dut.bm_drivers[3].nop()
- yield
- self.assertEqual((yield dut.dfi.phases[0].bank), 3)
-
- # Then write
- while not (yield ready[2]):
- yield
- yield from dut.bm_drivers[2].nop()
- yield
- self.assertEqual((yield dut.dfi.phases[0].bank), 2)
-
- dut = MultiplexerDUT(phy_settings=dict(nphases=1))
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_ras_trrd(self):
- # Verify tRRD.
- def main_generator(dut):
- yield from dut.bm_drivers[2].activate()
- yield from dut.bm_drivers[3].activate()
- ready = {2: dut.bank_machines[2].cmd.ready, 3: dut.bank_machines[3].cmd.ready}
-
- # Wait for activate
- while not ((yield ready[2]) or (yield ready[3])):
- yield
- # Invalidate command that was ready
- if (yield ready[2]):
- yield from dut.bm_drivers[2].nop()
- else:
- yield from dut.bm_drivers[3].nop()
- yield
-
- # Wait for the second activate; start from 1 for the previous cycle
- ras_time = 1
- while not ((yield ready[2]) or (yield ready[3])):
- ras_time += 1
- yield
-
- self.assertEqual(ras_time, 6)
-
- dut = MultiplexerDUT(timing_settings=dict(tRRD=6))
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_cas_tccd(self):
- # Verify tCCD.
- def main_generator(dut):
- yield from dut.bm_drivers[2].read()
- yield from dut.bm_drivers[3].read()
- ready = {2: dut.bank_machines[2].cmd.ready, 3: dut.bank_machines[3].cmd.ready}
-
- # Wait for activate
- while not ((yield ready[2]) or (yield ready[3])):
- yield
- # Invalidate command that was ready
- if (yield ready[2]):
- yield from dut.bm_drivers[2].nop()
- else:
- yield from dut.bm_drivers[3].nop()
- yield
-
- # Wait for the second activate; start from 1 for the previous cycle
- cas_time = 1
- while not ((yield ready[2]) or (yield ready[3])):
- cas_time += 1
- yield
-
- self.assertEqual(cas_time, 3)
-
- dut = MultiplexerDUT(timing_settings=dict(tCCD=3))
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_fsm_anti_starvation(self):
- # Check that anti-starvation works according to controller settings.
- def main_generator(dut):
- yield from dut.bm_drivers[2].read()
- yield from dut.bm_drivers[3].write()
-
- # Go to WRITE
- # anti starvation does not work for 1st read, as read_time_en already starts as 1
- # READ -> RTW -> WRITE
- while (yield from dut.fsm_state()) != "WRITE":
- yield
-
- # wait for write anti starvation
- for _ in range(dut.settings.write_time):
- self.assertEqual((yield from dut.fsm_state()), "WRITE")
- yield
- self.assertEqual((yield from dut.fsm_state()), "WTR")
-
- # WRITE -> WTR -> READ
- while (yield from dut.fsm_state()) != "READ":
- yield
-
- # Wait for read anti starvation
- for _ in range(dut.settings.read_time):
- self.assertEqual((yield from dut.fsm_state()), "READ")
- yield
- self.assertEqual((yield from dut.fsm_state()), "RTW")
-
- dut = MultiplexerDUT()
- generators = [
- main_generator(dut),
- timeout_generator(100),
- ]
- run_simulation(dut, generators)
-
- def test_write_datapath(self):
- # Verify that data is transmitted from native interface to DFI.
- def main_generator(dut):
- yield from dut.bm_drivers[2].write()
- # 16bits * 2 (DDR) * 1 (phases)
- yield dut.interface.wdata.eq(0xbaadf00d)
- yield dut.interface.wdata_we.eq(0xf)
-
- while not (yield dut.bank_machines[2].cmd.ready):
- yield
- yield
-
- self.assertEqual((yield dut.dfi.phases[0].wrdata), 0xbaadf00d)
- self.assertEqual((yield dut.dfi.phases[0].wrdata_en), 1)
- self.assertEqual((yield dut.dfi.phases[0].address), 2)
- self.assertEqual((yield dut.dfi.phases[0].bank), 2)
-
- dut = MultiplexerDUT(phy_settings=dict(nphases=1))
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_read_datapath(self):
- # Verify that data is transmitted from DFI to native interface.
- def main_generator(dut):
- yield from dut.bm_drivers[2].write()
- # 16bits * 2 (DDR) * 1 (phases)
- yield dut.dfi.phases[0].rddata.eq(0xbaadf00d)
- yield dut.dfi.phases[0].rddata_en.eq(1)
- yield
-
- while not (yield dut.bank_machines[2].cmd.ready):
- yield
- yield
-
- self.assertEqual((yield dut.interface.rdata), 0xbaadf00d)
- self.assertEqual((yield dut.interface.wdata_we), 0)
- self.assertEqual((yield dut.dfi.phases[0].address), 2)
- self.assertEqual((yield dut.dfi.phases[0].bank), 2)
-
- dut = MultiplexerDUT(phy_settings=dict(nphases=1))
- generators = [
- main_generator(dut),
- timeout_generator(50),
- ]
- run_simulation(dut, generators)
-
- def test_refresh_requires_gnt(self):
- # After refresher command request, multiplexer waits for permission from all bank machines.
- def main_generator(dut):
- def assert_dfi_cmd(cas, ras, we):
- p = dut.dfi.phases[0]
- cas_n, ras_n, we_n = (yield p.cas_n), (yield p.ras_n), (yield p.we_n)
- self.assertEqual((cas_n, ras_n, we_n), (1 - cas, 1 - ras, 1 - we))
-
- for bm in dut.bank_machines:
- self.assertEqual((yield bm.refresh_req), 0)
-
- yield from dut.refresh_driver.refresh()
- yield
-
- # Bank machines get the request
- for bm in dut.bank_machines:
- self.assertEqual((yield bm.refresh_req), 1)
- # No command yet
- yield from assert_dfi_cmd(cas=0, ras=0, we=0)
-
- # Grant permission for refresh
- prng = random.Random(42)
- delays = [prng.randrange(100) for _ in dut.bank_machines]
- for t in range(max(delays) + 1):
- # Grant permission
- for delay, bm in zip(delays, dut.bank_machines):
- if delay == t:
- yield bm.refresh_gnt.eq(1)
- yield
-
- # Make sure thare is no command yet
- yield from assert_dfi_cmd(cas=0, ras=0, we=0)
- yield
- yield
-
- # Refresh command
- yield from assert_dfi_cmd(cas=1, ras=1, we=0)
-
- dut = MultiplexerDUT()
- run_simulation(dut, main_generator(dut))
-
- def test_requests_from_multiple_bankmachines(self):
- # Check complex communication scenario with requests from multiple bank machines
- # The communication is greatly simplified - data path is completely ignored, no responses
- # from PHY are simulated. Each bank machine performs a sequence of requests, bank machines
- # are ordered randomly and the DFI command data is checked to verify if all the commands
- # have been sent if correct per-bank order.
-
- # Tequests sequence on given bank machines
- bm_sequences = {
- 0: "awwwwwwp",
- 1: "arrrrrrp",
- 2: "arwrwrwp",
- 3: "arrrwwwp",
- 4: "awparpawp",
- 5: "awwparrrrp",
- }
- # convert to lists to use .pop()
- bm_sequences = {bm_num: list(seq) for bm_num, seq in bm_sequences.items()}
-
- def main_generator(bank_machines, drivers):
- # work on a copy
- bm_seq = copy.deepcopy(bm_sequences)
-
- def non_empty():
- return list(filter(lambda n: len(bm_seq[n]) > 0, bm_seq.keys()))
-
- # Artificially perform the work of LiteDRAMCrossbar by always picking only one request
- prng = random.Random(42)
- while len(non_empty()) > 0:
- # Pick random bank machine
- bm_num = prng.choice(non_empty())
-
- # Set given request
- request_char = bm_seq[bm_num].pop(0)
- yield from drivers[bm_num].request(request_char)
- yield
-
- # Wait for ready
- while not (yield bank_machines[bm_num].cmd.ready):
- yield
-
- # Disable it
- yield from drivers[bm_num].nop()
-
- for _ in range(16):
- yield
-
- # Gather data on DFI
- DFISnapshot = namedtuple("DFICapture",
- ["cmd", "bank", "address", "wrdata_en", "rddata_en"])
- dfi_snapshots = []
-
- @passive
- def dfi_monitor(dfi):
- while True:
- # Capture current state of DFI lines
- phases = []
- for i, p in enumerate(dfi.phases):
- # Transform cas/ras/we to command name
- cas_n, ras_n, we_n = (yield p.cas_n), (yield p.ras_n), (yield p.we_n)
- captured = {"cmd": dfi_cmd_to_char(cas_n, ras_n, we_n)}
-
- # Capture rest of fields
- for field in DFISnapshot._fields:
- if field != "cmd":
- captured[field] = (yield getattr(p, field))
-
- phases.append(DFISnapshot(**captured))
- dfi_snapshots.append(phases)
- yield
-
- dut = MultiplexerDUT()
- generators = [
- main_generator(dut.bank_machines, dut.bm_drivers),
- dfi_monitor(dut.dfi),
- timeout_generator(200),
- ]
- run_simulation(dut, generators)
-
- # Check captured DFI data with the description
- for snap in dfi_snapshots:
- for i, phase_snap in enumerate(snap):
- if phase_snap.cmd == "_":
- continue
-
- # Distinguish bank machines by the bank number
- bank = phase_snap.bank
- # Find next command for the given bank
- cmd = bm_sequences[bank].pop(0)
-
- # Check if the captured data is correct
- self.assertEqual(phase_snap.cmd, cmd)
- if cmd in ["w", "r"]:
- # Addresses are artificially forced to bank numbers in drivers
- self.assertEqual(phase_snap.address, bank)
- if cmd == "w":
- self.assertEqual(phase_snap.wrdata_en, 1)
- if cmd == "r":
- self.assertEqual(phase_snap.rddata_en, 1)
+++ /dev/null
-# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-import unittest
-
-from migen import *
-
-from litedram.core.multiplexer import cmd_request_rw_layout
-from litedram.core.refresher import RefreshSequencer, RefreshTimer, Refresher
-
-
-def c2bool(c):
- return {"-": 1, "_": 0}[c]
-
-class TestRefresh(unittest.TestCase):
- def refresh_sequencer_test(self, trp, trfc, starts, dones, cmds):
- cmd = Record(cmd_request_rw_layout(a=16, ba=3))
- def generator(dut):
- dut.errors = 0
- for start, done, cas, ras in zip(starts, dones, cmds.cas, cmds.ras):
- yield dut.start.eq(c2bool(start))
- yield
- if (yield dut.done) != c2bool(done):
- dut.errors += 1
- if (yield cmd.cas) != c2bool(cas):
- dut.errors += 1
- if (yield cmd.ras) != c2bool(ras):
- dut.errors += 1
- dut = RefreshSequencer(cmd, trp, trfc)
- run_simulation(dut, [generator(dut)])
- self.assertEqual(dut.errors, 0)
-
- def test_refresh_sequencer(self):
- trp = 1
- trfc = 2
- class Obj: pass
- cmds = Obj()
- starts = "_-______________"
- cmds.cas = "___-____________"
- cmds.ras = "__--____________"
- dones = "_____-__________"
- self.refresh_sequencer_test(trp, trfc, starts, dones, cmds)
-
- def refresh_timer_test(self, trefi):
- def generator(dut):
- dut.errors = 0
- for i in range(16*trefi):
- if i%trefi == (trefi - 1):
- if (yield dut.refresh.done) != 1:
- dut.errors += 1
- else:
- if (yield dut.refresh.done) != 0:
- dut.errors += 1
- yield
-
- class DUT(Module):
- def __init__(self, trefi):
- self.submodules.refresh = RefreshTimer(trefi)
- self.comb += self.refresh.wait.eq(~self.refresh.done)
-
- dut = DUT(trefi)
- run_simulation(dut, [generator(dut)])
- self.assertEqual(dut.errors, 0)
-
- def test_refresh_timer(self):
- for trefi in range(1, 32):
- with self.subTest(trefi=trefi):
- self.refresh_timer_test(trefi)
-
- def refresher_test(self, postponing):
- class Obj: pass
- settings = Obj()
- settings.with_refresh = True
- settings.refresh_zqcs_freq = 1e0
- settings.timing = Obj()
- settings.timing.tREFI = 64
- settings.timing.tRP = 1
- settings.timing.tRFC = 2
- settings.timing.tZQCS = 64
- settings.geom = Obj()
- settings.geom.addressbits = 16
- settings.geom.bankbits = 3
- settings.phy = Obj()
- settings.phy.nranks = 1
-
- def generator(dut):
- dut.errors = 0
- yield dut.cmd.ready.eq(1)
- for i in range(16):
- while (yield dut.cmd.valid) == 0:
- yield
- cmd_valid_gap = 0
- while (yield dut.cmd.valid) == 1:
- cmd_valid_gap += 1
- yield
- while (yield dut.cmd.valid) == 0:
- cmd_valid_gap += 1
- yield
- if cmd_valid_gap != postponing*settings.timing.tREFI:
- print(cmd_valid_gap)
- dut.errors += 1
-
- dut = Refresher(settings, clk_freq=100e6, postponing=postponing)
- run_simulation(dut, [generator(dut)])
- self.assertEqual(dut.errors, 0)
-
- def test_refresher(self):
- for postponing in [1, 2, 4, 8]:
- with self.subTest(postponing=postponing):
- self.refresher_test(postponing)
+++ /dev/null
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-
-from migen import *
-from litex.soc.interconnect import stream
-
-from litedram.common import *
-from litedram.phy import dfi
-from litedram.core.multiplexer import _Steerer
-from litedram.core.multiplexer import STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH
-
-from test.common import CmdRequestRWDriver
-
-
-class SteererDUT(Module):
- def __init__(self, nranks, dfi_databits, nphases):
- a, ba = 13, 3
- nop = Record(cmd_request_layout(a=a, ba=ba))
- choose_cmd = stream.Endpoint(cmd_request_rw_layout(a=a, ba=ba))
- choose_req = stream.Endpoint(cmd_request_rw_layout(a=a, ba=ba))
- refresher_cmd = stream.Endpoint(cmd_request_rw_layout(a=a, ba=ba))
-
- self.commands = [nop, choose_cmd, choose_req, refresher_cmd]
- self.dfi = dfi.Interface(addressbits=a, bankbits=ba, nranks=nranks, databits=dfi_databits,
- nphases=nphases)
- self.submodules.steerer = _Steerer(self.commands, self.dfi)
-
- # NOP is not an endpoint and does not have is_* signals
- self.drivers = [CmdRequestRWDriver(req, i, ep_layout=i != 0, rw_layout=i != 0)
- for i, req in enumerate(self.commands)]
-
-
-class TestSteerer(unittest.TestCase):
- def test_nop_not_valid(self):
- # If NOP is selected then there should be no command selected on cas/ras/we.
- def main_generator(dut):
- # NOP on both phases
- yield dut.steerer.sel[0].eq(STEER_NOP)
- yield dut.steerer.sel[1].eq(STEER_NOP)
- yield from dut.drivers[0].nop()
- yield
-
- for i in range(2):
- cas_n = (yield dut.dfi.phases[i].cas_n)
- ras_n = (yield dut.dfi.phases[i].ras_n)
- we_n = (yield dut.dfi.phases[i].we_n)
- self.assertEqual((cas_n, ras_n, we_n), (1, 1, 1))
-
- dut = SteererDUT(nranks=2, dfi_databits=16, nphases=2)
- run_simulation(dut, main_generator(dut))
-
- def test_connect_only_if_valid_and_ready(self):
- # Commands should be connected to phases only if they are valid & ready.
- def main_generator(dut):
- # Set possible requests
- yield from dut.drivers[STEER_NOP].nop()
- yield from dut.drivers[STEER_CMD].activate()
- yield from dut.drivers[STEER_REQ].write()
- yield from dut.drivers[STEER_REFRESH].refresh()
- # Set how phases are steered
- yield dut.steerer.sel[0].eq(STEER_CMD)
- yield dut.steerer.sel[1].eq(STEER_NOP)
- yield
- yield
-
- def check(is_ready):
- # CMD on phase 0 should be STEER_CMD=activate
- p = dut.dfi.phases[0]
- self.assertEqual((yield p.bank), STEER_CMD)
- self.assertEqual((yield p.address), STEER_CMD)
- if is_ready:
- self.assertEqual((yield p.cas_n), 1)
- self.assertEqual((yield p.ras_n), 0)
- self.assertEqual((yield p.we_n), 1)
- else: # Not steered
- self.assertEqual((yield p.cas_n), 1)
- self.assertEqual((yield p.ras_n), 1)
- self.assertEqual((yield p.we_n), 1)
-
- # Nop on phase 1 should be STEER_NOP
- p = dut.dfi.phases[1]
- self.assertEqual((yield p.cas_n), 1)
- self.assertEqual((yield p.ras_n), 1)
- self.assertEqual((yield p.we_n), 1)
-
- yield from check(is_ready=False)
- yield dut.commands[STEER_CMD].ready.eq(1)
- yield
- yield
- yield from check(is_ready=True)
-
- dut = SteererDUT(nranks=2, dfi_databits=16, nphases=2)
- run_simulation(dut, main_generator(dut))
-
- def test_no_decode_ba_signle_rank(self):
- # With a single rank the whole `ba` signal is bank address.
- def main_generator(dut):
- yield from dut.drivers[STEER_NOP].nop()
- yield from dut.drivers[STEER_REQ].write()
- yield from dut.drivers[STEER_REFRESH].refresh()
- # All the bits are for bank
- dut.drivers[STEER_CMD].bank = 0b110
- yield from dut.drivers[STEER_CMD].activate()
- yield dut.commands[STEER_CMD].ready.eq(1)
- # Set how phases are steered
- yield dut.steerer.sel[0].eq(STEER_NOP)
- yield dut.steerer.sel[1].eq(STEER_CMD)
- yield
- yield
-
- p = dut.dfi.phases[1]
- self.assertEqual((yield p.cas_n), 1)
- self.assertEqual((yield p.ras_n), 0)
- self.assertEqual((yield p.we_n), 1)
- self.assertEqual((yield p.address), STEER_CMD)
- self.assertEqual((yield p.bank), 0b110)
- self.assertEqual((yield p.cs_n), 0)
-
- dut = SteererDUT(nranks=1, dfi_databits=16, nphases=2)
- run_simulation(dut, main_generator(dut))
-
- def test_decode_ba_multiple_ranks(self):
- # With multiple ranks `ba` signal should be split into bank and chip select.
- def main_generator(dut):
- yield from dut.drivers[STEER_NOP].nop()
- yield from dut.drivers[STEER_REQ].write()
- yield from dut.drivers[STEER_REFRESH].refresh()
- # Set how phases are steered
- yield dut.steerer.sel[0].eq(STEER_NOP)
- yield dut.steerer.sel[1].eq(STEER_CMD)
-
- variants = [
- # ba, phase.bank, phase.cs_n
- (0b110, 0b10, 0b01), # rank=1 -> cs=0b10 -> cs_n=0b01
- (0b101, 0b01, 0b01), # rank=1 -> cs=0b10 -> cs_n=0b01
- (0b001, 0b01, 0b10), # rank=0 -> cs=0b01 -> cs_n=0b10
- ]
- for ba, phase_bank, phase_cs_n in variants:
- with self.subTest(ba=ba):
- # 1 bit for rank, 2 bits for bank
- dut.drivers[STEER_CMD].bank = ba
- yield from dut.drivers[STEER_CMD].activate()
- yield dut.commands[STEER_CMD].ready.eq(1)
- yield
- yield
-
- p = dut.dfi.phases[1]
- self.assertEqual((yield p.cas_n), 1)
- self.assertEqual((yield p.ras_n), 0)
- self.assertEqual((yield p.we_n), 1)
- self.assertEqual((yield p.bank), phase_bank)
- self.assertEqual((yield p.cs_n), phase_cs_n)
-
- dut = SteererDUT(nranks=2, dfi_databits=16, nphases=2)
- run_simulation(dut, main_generator(dut))
-
- def test_select_all_ranks_on_refresh(self):
- # When refresh command is on first phase, all ranks should be selected.
- def main_generator(dut):
- yield from dut.drivers[STEER_NOP].nop()
- yield from dut.drivers[STEER_REQ].write()
- yield from dut.drivers[STEER_CMD].activate()
- # Set how phases are steered
- yield dut.steerer.sel[0].eq(STEER_REFRESH)
- yield dut.steerer.sel[1].eq(STEER_NOP)
-
- variants = [
- # ba, phase.bank, phase.cs_n (always all enabled)
- (0b110, 0b10, 0b00),
- (0b101, 0b01, 0b00),
- (0b001, 0b01, 0b00),
- ]
- for ba, phase_bank, phase_cs_n in variants:
- with self.subTest(ba=ba):
- # 1 bit for rank, 2 bits for bank
- dut.drivers[STEER_REFRESH].bank = ba
- yield from dut.drivers[STEER_REFRESH].refresh()
- yield dut.commands[STEER_REFRESH].ready.eq(1)
- yield
- yield
-
- p = dut.dfi.phases[0]
- self.assertEqual((yield p.cas_n), 0)
- self.assertEqual((yield p.ras_n), 0)
- self.assertEqual((yield p.we_n), 1)
- self.assertEqual((yield p.bank), phase_bank)
- self.assertEqual((yield p.cs_n), phase_cs_n)
-
- dut = SteererDUT(nranks=2, dfi_databits=16, nphases=2)
- run_simulation(dut, main_generator(dut))
-
- def test_reset_n_high(self):
- # Reset_n should be 1 for all phases at all times.
- def main_generator(dut):
- yield dut.steerer.sel[0].eq(STEER_CMD)
- yield dut.steerer.sel[1].eq(STEER_NOP)
- yield
-
- self.assertEqual((yield dut.dfi.phases[0].reset_n), 1)
- self.assertEqual((yield dut.dfi.phases[1].reset_n), 1)
- self.assertEqual((yield dut.dfi.phases[2].reset_n), 1)
- self.assertEqual((yield dut.dfi.phases[3].reset_n), 1)
-
- dut = SteererDUT(nranks=2, dfi_databits=16, nphases=4)
- run_simulation(dut, main_generator(dut))
-
- def test_cke_high_all_ranks(self):
- # CKE should be 1 for all phases and ranks at all times.
- def main_generator(dut):
- yield dut.steerer.sel[0].eq(STEER_CMD)
- yield dut.steerer.sel[1].eq(STEER_NOP)
- yield
-
- self.assertEqual((yield dut.dfi.phases[0].cke), 0b11)
- self.assertEqual((yield dut.dfi.phases[1].cke), 0b11)
- self.assertEqual((yield dut.dfi.phases[2].cke), 0b11)
- self.assertEqual((yield dut.dfi.phases[3].cke), 0b11)
-
- dut = SteererDUT(nranks=2, dfi_databits=16, nphases=4)
- run_simulation(dut, main_generator(dut))
-
- def test_odt_high_all_ranks(self):
- # ODT should be 1 for all phases and ranks at all times.
- # NOTE: only until dynamic ODT is implemented.
- def main_generator(dut):
- yield dut.steerer.sel[0].eq(STEER_CMD)
- yield dut.steerer.sel[1].eq(STEER_NOP)
- yield
-
- self.assertEqual((yield dut.dfi.phases[0].odt), 0b11)
- self.assertEqual((yield dut.dfi.phases[1].odt), 0b11)
- self.assertEqual((yield dut.dfi.phases[2].odt), 0b11)
- self.assertEqual((yield dut.dfi.phases[3].odt), 0b11)
-
- dut = SteererDUT(nranks=2, dfi_databits=16, nphases=4)
- run_simulation(dut, main_generator(dut))
+++ /dev/null
-# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-import unittest
-import random
-
-from migen import *
-
-from litedram.common import tXXDController, tFAWController
-
-
-def c2bool(c):
- return {"-": 1, "_": 0}[c]
-
-
-class TestTiming(unittest.TestCase):
- def txxd_controller_test(self, txxd, valids, readys):
- def generator(dut):
- dut.errors = 0
- for valid, ready in zip(valids, readys):
- yield dut.valid.eq(c2bool(valid))
- yield
- if (yield dut.ready) != c2bool(ready):
- dut.errors += 1
-
- dut = tXXDController(txxd)
- run_simulation(dut, [generator(dut)])
- self.assertEqual(dut.errors, 0)
-
- def test_txxd_controller(self):
- txxd = 1
- valids = "__-______"
- readys = "_--------"
- self.txxd_controller_test(txxd, valids, readys)
-
- txxd = 2
- valids = "__-______"
- readys = "_--_-----"
- self.txxd_controller_test(txxd, valids, readys)
-
- txxd = 3
- valids = "____-______"
- readys = "___--__----"
- self.txxd_controller_test(txxd, valids, readys)
-
- txxd = 4
- valids = "____-______"
- readys = "___--___---"
- self.txxd_controller_test(txxd, valids, readys)
-
- def txxd_controller_random_test(self, txxd, loops):
- def generator(dut, valid_rand):
- prng = random.Random(42)
- for l in range(loops):
- while prng.randrange(100) < valid_rand:
- yield
- yield dut.valid.eq(1)
- yield
- yield dut.valid.eq(0)
-
- @passive
- def checker(dut):
- dut.ready_gaps = []
- while True:
- while (yield dut.ready) != 0:
- yield
- ready_gap = 1
- while (yield dut.ready) != 1:
- ready_gap += 1
- yield
- dut.ready_gaps.append(ready_gap)
-
- dut = tXXDController(txxd)
- run_simulation(dut, [generator(dut, valid_rand=90), checker(dut)])
- self.assertEqual(min(dut.ready_gaps), txxd)
-
- def test_txxd_controller_random(self):
- for txxd in range(2, 32):
- with self.subTest(txxd=txxd):
- self.txxd_controller_random_test(txxd, 512)
-
-
- def tfaw_controller_test(self, txxd, valids, readys):
- def generator(dut):
- dut.errors = 0
- for valid, ready in zip(valids, readys):
- yield dut.valid.eq(c2bool(valid))
- yield
- if (yield dut.ready) != c2bool(ready):
- dut.errors += 1
-
- dut = tFAWController(txxd)
- run_simulation(dut, [generator(dut)])
- self.assertEqual(dut.errors, 0)
-
- def test_tfaw_controller(self):
- tfaw = 8
- valids = "_----___________"
- readys = "-----______-----"
- with self.subTest(tfaw=tfaw, valids=valids, readys=readys):
- self.tfaw_controller_test(tfaw, valids, readys)
-
- tfaw = 8
- valids = "_-_-_-_-________"
- readys = "--------___-----"
- with self.subTest(tfaw=tfaw, valids=valids, readys=readys):
- self.tfaw_controller_test(tfaw, valids, readys)
-
- tfaw = 8
- valids = "_-_-___-_-______"
- readys = "----------_-----"
- with self.subTest(tfaw=tfaw, valids=valids, readys=readys):
- self.tfaw_controller_test(tfaw, valids, readys)
-
- tfaw = 8
- valids = "_-_-____-_-______"
- readys = "-----------------"
- with self.subTest(tfaw=tfaw, valids=valids, readys=readys):
- self.tfaw_controller_test(tfaw, valids, readys)
+++ /dev/null
-# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
-# License: BSD
-
-import unittest
-
-from migen import *
-from litex.gen.sim import run_simulation
-from litex.soc.interconnect import wishbone
-
-from litedram.frontend.wishbone import LiteDRAMWishbone2Native
-from litedram.common import LiteDRAMNativePort
-
-from test.common import DRAMMemory, MemoryTestDataMixin
-
-
-class TestWishbone(MemoryTestDataMixin, unittest.TestCase):
- def test_wishbone_data_width_not_smaller(self):
- with self.assertRaises(AssertionError):
- wb = wishbone.Interface(data_width=32)
- port = LiteDRAMNativePort("both", address_width=32, data_width=wb.data_width * 2)
- LiteDRAMWishbone2Native(wb, port)
-
- def wishbone_readback_test(self, pattern, mem_expected, wishbone, port, base_address=0):
- class DUT(Module):
- def __init__(self):
- self.port = port
- self.wb = wishbone
- self.submodules += LiteDRAMWishbone2Native(
- wishbone = self.wb,
- port = self.port,
- base_address = base_address)
- self.mem = DRAMMemory(port.data_width, len(mem_expected))
-
- def main_generator(dut):
- for adr, data in pattern:
- yield from dut.wb.write(adr, data)
- data_r = (yield from dut.wb.read(adr))
- self.assertEqual(data_r, data)
-
- dut = DUT()
- generators = [
- main_generator(dut),
- dut.mem.write_handler(dut.port),
- dut.mem.read_handler(dut.port),
- ]
- run_simulation(dut, generators)
- self.assertEqual(dut.mem.mem, mem_expected)
-
- def test_wishbone_8bit(self):
- # Verify Wishbone with 8-bit data width.
- data = self.pattern_test_data["8bit"]
- wb = wishbone.Interface(adr_width=30, data_width=8)
- port = LiteDRAMNativePort("both", address_width=30, data_width=8)
- self.wishbone_readback_test(data["pattern"], data["expected"], wb, port)
-
- def test_wishbone_32bit(self):
- # Verify Wishbone with 32-bit data width.
- data = self.pattern_test_data["32bit"]
- wb = wishbone.Interface(adr_width=30, data_width=32)
- port = LiteDRAMNativePort("both", address_width=30, data_width=32)
- self.wishbone_readback_test(data["pattern"], data["expected"], wb, port)
-
- def test_wishbone_64bit(self):
- # Verify Wishbone with 64-bit data width.
- data = self.pattern_test_data["64bit"]
- wb = wishbone.Interface(adr_width=30, data_width=64)
- port = LiteDRAMNativePort("both", address_width=30, data_width=64)
- self.wishbone_readback_test(data["pattern"], data["expected"], wb, port)
-
- def test_wishbone_64bit_to_32bit(self):
- # Verify Wishbone with 64-bit data width down-converted to 32-bit data width.
- data = self.pattern_test_data["64bit_to_32bit"]
- wb = wishbone.Interface(adr_width=30, data_width=64)
- port = LiteDRAMNativePort("both", address_width=30, data_width=32)
- self.wishbone_readback_test(data["pattern"], data["expected"], wb, port)
-
- def test_wishbone_32bit_to_8bit(self):
- # Verify Wishbone with 32-bit data width down-converted to 8-bit data width.
- data = self.pattern_test_data["32bit_to_8bit"]
- wb = wishbone.Interface(adr_width=30, data_width=32)
- port = LiteDRAMNativePort("both", address_width=30, data_width=8)
- self.wishbone_readback_test(data["pattern"], data["expected"], wb, port)
-
- def test_wishbone_32bit_base_address(self):
- # Verify Wishbone with 32-bit data width and non-zero base address.
- data = self.pattern_test_data["32bit"]
- wb = wishbone.Interface(adr_width=30, data_width=32)
- port = LiteDRAMNativePort("both", address_width=30, data_width=32)
- origin = 0x10000000
- # add offset (in data words)
- pattern = [(adr + origin//(32//8), data) for adr, data in data["pattern"]]
- self.wishbone_readback_test(pattern, data["expected"], wb, port, base_address=origin)
-
- def test_wishbone_64bit_to_32bit_base_address(self):
- # Verify Wishbone with 64-bit data width down-converted to 32-bit data width and non-zero base address.
- data = self.pattern_test_data["64bit_to_32bit"]
- wb = wishbone.Interface(adr_width=30, data_width=64)
- port = LiteDRAMNativePort("both", address_width=30, data_width=32)
- origin = 0x10000000
- pattern = [(adr + origin//(64//8), data) for adr, data in data["pattern"]]
- self.wishbone_readback_test(pattern, data["expected"], wb, port, base_address=origin)
-
- def test_wishbone_32bit_to_8bit_base_address(self):
- # Verify Wishbone with 32-bit data width down-converted to 8-bit data width and non-zero base address.
- data = self.pattern_test_data["32bit_to_8bit"]
- wb = wishbone.Interface(adr_width=30, data_width=32)
- port = LiteDRAMNativePort("both", address_width=30, data_width=8)
- origin = 0x10000000
- pattern = [(adr + origin//(32//8), data) for adr, data in data["pattern"]]
- self.wishbone_readback_test(pattern, data["expected"], wb, port, base_address=origin)