from lib.sata.link.scrambler import Scrambler
from migen.bank.description import *
-class SATABISTUnit(Module):
+class SATABIST(Module):
def __init__(self, sata_con):
- sink = sata_con.source
- source = sata_con.sink
-
- self.start = Signal()
- self.write_only = Signal()
- self.read_only = Signal()
+ self.write = Signal()
+ self.read = Signal()
self.sector = Signal(48)
self.count = Signal(16)
+ self.loops = Signal(8)
+
self.done = Signal()
- self.ctrl_errors = Signal(32)
- self.data_errors = Signal(32)
+ self.errors = Signal(32)
+
+ ###
+
+ sink = sata_con.source
+ source = sata_con.sink
self.counter = counter = Counter(bits_sign=32)
- self.ctrl_error_counter = Counter(self.ctrl_errors, bits_sign=32)
- self.data_error_counter = Counter(self.data_errors, bits_sign=32)
+ self.loops_counter = loops_counter = Counter(bits_sign=8)
+ self.error_counter = Counter(self.errors, bits_sign=32)
self.scrambler = scrambler = InsertReset(Scrambler())
self.comb += [
fsm.act("IDLE",
self.done.eq(1),
counter.reset.eq(1),
- If(self.start,
- self.ctrl_error_counter.reset.eq(1),
- self.data_error_counter.reset.eq(1),
- If(self.read_only,
- NextState("SEND_READ_CMD")
- ).Else(
- NextState("SEND_WRITE_CMD_AND_DATA")
- )
+ loops_counter.reset.eq(1),
+ If(self.write,
+ self.error_counter.reset.eq(1),
+ NextState("SEND_WRITE_CMD_AND_DATA")
+ ).Elif(self.read,
+ self.error_counter.reset.eq(1),
+ NextState("SEND_READ_CMD")
)
)
fsm.act("SEND_WRITE_CMD_AND_DATA",
source.stb.eq(1),
- source.sop.eq((counter.value == 0)),
- source.eop.eq((counter.value == (logical_sector_size//4*self.count)-1)),
+ source.sop.eq(counter.value == 0),
+ source.eop.eq(counter.value == (logical_sector_size//4*self.count)-1),
source.write.eq(1),
source.sector.eq(self.sector),
source.count.eq(self.count),
source.data.eq(scrambler.value),
- counter.ce.eq(source.ack),
- If(source.stb & source.eop & source.ack,
- NextState("WAIT_WRITE_ACK")
+ If(source.stb & source.ack,
+ counter.ce.eq(1),
+ If(source.eop,
+ NextState("WAIT_WRITE_ACK")
+ )
)
)
fsm.act("WAIT_WRITE_ACK",
sink.ack.eq(1),
If(sink.stb,
- If(~sink.write | ~sink.success | sink.failed,
- self.ctrl_error_counter.ce.eq(1)
- ),
- If(self.write_only,
+ loops_counter.ce.eq(1),
+ If(loops_counter.value == (self.loops-1),
NextState("IDLE")
).Else(
- NextState("SEND_READ_CMD")
+ counter.reset.eq(1),
+ NextState("SEND_WRITE_CMD_AND_DATA")
)
)
)
)
fsm.act("WAIT_READ_ACK",
If(sink.stb & sink.read,
- If(~sink.read | ~sink.success | sink.failed,
- self.ctrl_error_counter.ce.eq(1)
- ),
NextState("RECEIVE_READ_DATA")
)
)
If(sink.stb,
counter.ce.eq(1),
If(sink.data != scrambler.value,
- self.data_error_counter.ce.eq(1)
+ self.error_counter.ce.eq(1)
),
If(sink.eop,
If(sink.last,
- NextState("IDLE")
+ loops_counter.ce.eq(1),
+ If(loops_counter.value == (self.loops-1),
+ NextState("IDLE")
+ ).Else(
+ NextState("SEND_READ_CMD")
+ )
).Else(
NextState("WAIT_READ_ACK")
)
)
)
-class SATABIST(Module, AutoCSR):
- def __init__(self, sata_con):
- self._start = CSR()
- self._start_sector = CSRStorage(48)
+class SATABISTControl(Module, AutoCSR):
+ def __init__(self, sata_bist):
+ self._write = CSR()
+ self._read = CSR()
+ self._sector = CSRStorage(48)
self._count = CSRStorage(16)
- self._write_only = CSRStorage()
- self._read_only = CSRStorage()
-
- self._stop = CSRStorage()
+ self._loops = CSRStorage(8)
- self._sector = CSRStatus(48)
+ self._done = CSRStatus()
self._errors = CSRStatus(32)
- start = self._start.r & self._start.re
- start_sector = self._start_sector.storage
- count = self._count.storage
- stop = self._stop.storage
-
- compute = Signal()
-
- write_only = self._write_only.storage
- read_only = self._read_only.storage
- sector = self._sector.status
- errors = self._errors.status
-
- ###
-
- self.unit = SATABISTUnit(sata_con)
self.comb += [
- self.unit.write_only.eq(write_only),
- self.unit.read_only.eq(read_only),
- self.unit.sector.eq(sector),
- self.unit.count.eq(count)
- ]
-
- self.fsm = fsm = FSM(reset_state="IDLE")
-
- # FSM
- fsm.act("IDLE",
- If(start,
- NextState("START")
- )
- )
- fsm.act("START",
- self.unit.start.eq(1),
- NextState("WAIT_DONE")
- )
- fsm.act("WAIT_DONE",
- If(self.unit.done,
- NextState("COMPUTE")
- ).Elif(stop,
- NextState("IDLE")
- )
- )
- fsm.act("COMPUTE",
- compute.eq(1),
- NextState("START")
- )
-
- self.sync += [
- If(start,
- errors.eq(0),
- sector.eq(start_sector)
- ).Elif(compute,
- errors.eq(errors + self.unit.data_errors),
- sector.eq(sector + count)
- )
+ sata_bist.write.eq(self._write.r & self._write.re),
+ sata_bist.read.eq(self._read.r & self._read.re),
+ sata_bist.sector.eq(self._sector.storage),
+ sata_bist.count.eq(self._count.storage),
+ sata_bist.loops.eq(self._loops.storage),
+
+ self._done.status.eq(sata_bist.done),
+ self._errors.status.eq(sata_bist.errors)
]
from lib.sata.common import *
from lib.sata import SATACON
-from lib.sata.bist import SATABISTUnit
+from lib.sata.bist import SATABIST
from lib.sata.test.hdd import *
from lib.sata.test.common import *
transport_debug=False, transport_loopback=False,
hdd_debug=True)
self.con = SATACON(self.hdd.phy)
- self.bist = SATABISTUnit(self.con)
+ self.bist = SATABIST(self.con)
def gen_simulation(self, selfp):
hdd = self.hdd
hdd.malloc(0, 64)
selfp.bist.sector = 0
selfp.bist.count = 17
+ selfp.bist.loops = 1
while True:
- selfp.bist.start = 1
+ selfp.bist.write = 1
yield
- selfp.bist.start = 0
+ selfp.bist.write = 0
yield
while selfp.bist.done == 0:
yield
- print("ctrl_errors: {} / data_errors {}".format(selfp.bist.ctrl_errors, selfp.bist.data_errors))
+ selfp.bist.read = 1
+ yield
+ selfp.bist.read = 0
+ yield
+ while selfp.bist.done == 0:
+ yield
+ print("errors {}".format(selfp.bist.errors))
selfp.bist.sector += 1
selfp.bist.count = max((selfp.bist.count + 1)%8, 1)
from lib.sata.common import *
from lib.sata.phy import SATAPHY
from lib.sata import SATACON
-from lib.sata.bist import SATABIST
+from lib.sata.bist import SATABIST, SATABISTControl
from migen.genlib.cdc import *
class TestDesign(UART2WB, AutoCSR):
default_platform = "kc705"
csr_map = {
- "sata_bist": 10,
- "mila": 11
+ "sata_bist_ctrl": 10,
+ "mila": 11
}
csr_map.update(UART2WB.csr_map)
self.sata_phy = SATAPHY(platform.request("sata_host"), clk_freq, speed="SATA2")
self.sata_con = SATACON(self.sata_phy)
self.sata_bist = SATABIST(self.sata_con)
+ self.sata_bist_ctrl = SATABISTControl(self.sata_bist)
+
self.leds = DebugLeds(platform, self.sata_phy)
class SATABISTDriver:
def __init__(self, regs):
self.regs = regs
- self.last_sector = 0
- self.last_time = time.time()
- self.last_errors = 0
- self.mode = "rw"
- def set_mode(self, mode):
- self.mode = mode
- self.regs.sata_bist_write_only.write(0)
- self.regs.sata_bist_read_only.write(0)
- if mode == "wr":
- self.regs.sata_bist_write_only.write(1)
- if mode == "rd":
- self.regs.sata_bist_read_only.write(1)
+ def run(self, sector, count, loops, mode):
+ self.regs.sata_bist_ctrl_sector.write(sector)
+ self.regs.sata_bist_ctrl_count.write(count)
+ self.regs.sata_bist_ctrl_loops.write(loops)
+ if mode == "write":
+ self.regs.sata_bist_ctrl_write.write(1)
+ elif mode == "read":
+ self.regs.sata_bist_ctrl_read.write(1)
+ while (self.regs.sata_bist_ctrl_done.read() == 0):
+ pass
+ return self.regs.sata_bist_ctrl_errors.read()
- def start(self, sector, count, mode):
- self.set_mode(mode)
- self.regs.sata_bist_start_sector.write(sector)
- self.regs.sata_bist_count.write(count)
- self.regs.sata_bist_stop.write(0)
- self.regs.sata_bist_start.write(1)
-
- def stop(self):
- self.regs.sata_bist_stop.write(1)
-
- def show_status(self):
- errors = self.regs.sata_bist_errors.read() - self.last_errors
- self.last_errors += errors
-
- sector = self.regs.sata_bist_sector.read()
- n = sector - self.last_sector
- self.last_sector = sector
-
- t = self.last_time - time.time()
- self.last_time = time.time()
-
- if self.mode in ["wr", "rd"]:
- speed_mult = 1
- else:
- speed_mult = 2
- print("%4.2f MB/sec errors=%d sector=%d" %(n*logical_sector_size*speed_mult/(1024*1024), errors, sector))
+ def write(self, sector, count, loops):
+ self.run(sector, count, loops, "write")
+ def read(self, sector, count, loops):
+ return self.run(sector, count, loops, "read")
def _get_args():
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
SATA BIST utility.
""")
parser.add_argument("-s", "--sector", default=0, help="BIST start sector")
- parser.add_argument("-c", "--count", default=4, help="BIST count (number of sectors per transaction)")
- parser.add_argument("-m", "--mode", default="rw", help="BIST mode (rw, wr, rd")
+ parser.add_argument("-c", "--count", default=16384, help="BIST count (number of sectors per transaction)")
+ parser.add_argument("-l", "--loops", default=4, help="BIST loops (number of loop for each transaction")
return parser.parse_args()
wb.open()
###
bist = SATABISTDriver(wb.regs)
+ sector = int(args.sector)
+ count = int(args.count)
+ loops = int(args.loops)
try:
- bist.start(int(args.sector), int(args.count), args.mode)
+ write_time = 0
+ read_time = 0
while True:
- bist.show_status()
- time.sleep(1)
+ # Write
+ start = time.time()
+ bist.write(sector, count, loops)
+ end = time.time()
+ write_time = end-start
+ write_speed = loops*count*logical_sector_size/(1024*1024)/write_time
+
+ # Read
+ start = time.time()
+ read_errors = bist.read(sector, count, loops)
+ end = time.time()
+ read_time = end-start
+ read_speed = loops*count*logical_sector_size/(1024*1024)/read_time
+
+ sector += count
+
+ print("sector=%d write_speed=%4.2fMB/sec read_speed=%4.2fMB/sec errors=%d" %(sector, write_speed, read_speed, read_errors))
+
except KeyboardInterrupt:
pass
- bist.stop()
###
wb.close()
# Trigger / wait / receive
mila.trigger(offset=32, length=1024)
-bist.start(0, 4, "rw")
+bist.write(0, 16, 1)
+bist.read(0, 16, 1)
mila.wait_done()
-bist.stop()
mila.read()
mila.export("dump.vcd")