self.start = Signal()
self.sector = Signal(48)
self.count = Signal(16)
- self.loops = Signal(8)
self.random = Signal()
self.done = Signal()
source, sink = sata_master_port.source, sata_master_port.sink
self.counter = counter = Counter(bits_sign=32)
- self.loops_counter = loops_counter = Counter(bits_sign=8)
self.scrambler = scrambler = InsertReset(Scrambler())
self.comb += [
fsm.act("IDLE",
self.done.eq(1),
counter.reset.eq(1),
- loops_counter.reset.eq(1),
If(self.start,
NextState("SEND_CMD_AND_DATA")
)
fsm.act("WAIT_ACK",
sink.ack.eq(1),
If(sink.stb,
- loops_counter.ce.eq(1),
- If(loops_counter.value == (self.loops-1),
- NextState("IDLE")
- ).Else(
- counter.reset.eq(1),
- NextState("SEND_CMD_AND_DATA")
- )
+ NextState("IDLE")
)
)
self.start = Signal()
self.sector = Signal(48)
self.count = Signal(16)
- self.loops = Signal(8)
self.random = Signal()
self.done = Signal()
source, sink = sata_master_port.source, sata_master_port.sink
self.counter = counter = Counter(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())
fsm.act("IDLE",
self.done.eq(1),
counter.reset.eq(1),
- loops_counter.reset.eq(1),
If(self.start,
self.error_counter.reset.eq(1),
NextState("SEND_CMD")
),
If(sink.eop,
If(sink.last,
- loops_counter.ce.eq(1),
- If(loops_counter.value == (self.loops-1),
- NextState("IDLE")
- ).Else(
- NextState("SEND_CMD")
- )
+ NextState("IDLE")
).Else(
NextState("WAIT_ACK")
)
self._sector = CSRStorage(48)
self._count = CSRStorage(16)
self._random = CSRStorage()
- self._loops = CSRStorage(8)
self._done = CSRStatus()
self._errors = CSRStatus(32)
+ self._cycles = CSRStatus(32)
###
self.bist_unit = bist_unit
bist_unit.start.eq(self._start.r & self._start.re),
bist_unit.sector.eq(self._sector.storage),
bist_unit.count.eq(self._count.storage),
- bist_unit.loops.eq(self._loops.storage),
bist_unit.random.eq(self._random.storage),
self._done.status.eq(bist_unit.done),
self._errors.status.eq(bist_unit.errors)
]
+ self.cycles_counter = Counter(self._cycles.status)
+ self.sync += [
+ self.cycles_counter.reset.eq(bist_unit.start),
+ self.cycles_counter.ce.eq(~bist_unit.done)
+ ]
class SATABIST(Module, AutoCSR):
def __init__(self, sata_master_ports, with_control=False):
generator = SATABISTGenerator(sata_master_ports[0])
def __init__(self, regs, name):
self.regs = regs
self.name = name
- for s in ["start", "sector", "count", "loops", "random", "done", "errors"]:
+ self.frequency = regs.identifier_frequency.read()
+ self.time = 0
+ for s in ["start", "sector", "count", "random", "done", "errors", "cycles"]:
setattr(self, s, getattr(regs, name + "_"+ s))
- def run(self, sector, count, loops, random):
+ def run(self, sector, count, random):
self.sector.write(sector)
self.count.write(count)
- self.loops.write(loops)
self.random.write(random)
self.start.write(1)
while (self.done.read() == 0):
pass
- return self.errors.read()
+ self.time = self.cycles.read()/self.frequency
+ speed = (count*logical_sector_size)/self.time
+ errors = self.errors.read()
+ return (speed, errors)
class SATABISTGeneratorDriver(SATABISTDriver):
def __init__(self, regs, name):
def __init__(self, regs, name):
SATABISTDriver.__init__(self, regs, name + "_checker")
-class Timer:
- def __init__(self):
- self.value = None
-
- def start(self):
- self._start = time.time()
-
- def stop(self):
- self._stop = time.time()
- self.value = self._stop - self._start
-
KB = 1024
MB = 1024*KB
GB = 1024*MB
-def compute_speed(loops, count, elapsed_time, unit):
- return loops*count*logical_sector_size/unit/elapsed_time
+# Note: use IDENTIFY command to find numbers of sectors
+hdd_max_sector = (32*MB)/logical_sector_size
def _get_args():
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\
SATA BIST utility.
""")
- parser.add_argument("-s", "--sector", default=0, help="start sector")
- parser.add_argument("-c", "--count", default=16384, help="number of sectors per transaction")
- parser.add_argument("-l", "--loops", default=4, help="number of loop for each transaction")
- parser.add_argument("-r", "--random", default=True, help="use random data")
-
+ parser.add_argument("-s", "--transfer_size", default=4, help="transfer sizes (in MB, up to 16MB)")
+ parser.add_argument("-l", "--total_length", default=256, help="total transfer length (in MB, up to HDD capacity)")
+ parser.add_argument("-r", "--random", action="store_true", help="use random data")
+ parser.add_argument("-c", "--continuous", action="store_true", help="continuous mode (Escape to exit)")
return parser.parse_args()
if __name__ == "__main__":
###
generator = SATABISTGeneratorDriver(wb.regs, "sata_bist")
checker = SATABISTCheckerDriver(wb.regs, "sata_bist")
- timer = Timer()
- sector = int(args.sector)
- count = int(args.count)
- loops = int(args.loops)
+ sector = 0
+ count = int(args.transfer_size)*MB//logical_sector_size
+ length = int(args.total_length)*MB
random = int(args.random)
+ continuous = int(args.continuous)
try:
- while True:
+ while (sector*logical_sector_size < length) or continuous:
# generator (write data to HDD)
- timer.start()
- generator.run(sector, count, loops, random)
- timer.stop()
- write_speed = compute_speed(loops, count, timer.value, MB)
+ write_speed, write_errors = generator.run(sector, count, random)
# checker (read and check data from HDD)
- timer.start()
- errors = checker.run(sector, count, loops, random)
- timer.stop()
- read_speed = compute_speed(loops, count, timer.value, MB)
- sector += count
+ read_speed, read_errors = checker.run(sector, count, random)
- print("sector=%d write_speed=%4.2fMB/sec read_speed=%4.2fMB/sec errors=%d" %(sector, write_speed, read_speed, errors))
+ print("sector=%d write_speed=%4.2fMB/sec read_speed=%4.2fMB/sec errors=%d" %(sector, write_speed/MB, read_speed/MB, write_errors + read_errors))
+ sector += count
except KeyboardInterrupt:
pass