bist: add loops parameter for more precision in speed computation
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 22 Jan 2015 00:33:02 +0000 (01:33 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 22 Jan 2015 00:33:02 +0000 (01:33 +0100)
litesata/frontend/bist.py
test/bist.py
test/test_link.py

index afb8daefb51209dac6bf2a83940f7615e1ab96fe..e34e71bcdc58aa95bd2e1fcd55e8d9f81d2e88c3 100644 (file)
@@ -146,7 +146,9 @@ class LiteSATABISTUnitCSR(Module, AutoCSR):
                self._start = CSR()
                self._sector = CSRStorage(48)
                self._count = CSRStorage(16)
+               self._loops = CSRStorage(8)
                self._random = CSRStorage()
+
                self._done = CSRStatus()
                self._aborted = CSRStatus()
                self._errors = CSRStatus(32)
@@ -155,21 +157,50 @@ class LiteSATABISTUnitCSR(Module, AutoCSR):
                ###
 
                self.bist_unit = bist_unit
+               start = self._start.r & self._start.re
+               done = self._done.status
+               loops = self._loops.storage
+
                self.comb += [
-                       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.random.eq(self._random.storage),
 
-                       self._done.status.eq(bist_unit.done),
                        self._aborted.status.eq(bist_unit.aborted),
                        self._errors.status.eq(bist_unit.errors)
                ]
 
+               self.fsm = fsm = FSM(reset_state="IDLE")
+               self.loop_counter = Counter(bits_sign=8)
+               fsm.act("IDLE",
+                       self._done.status.eq(1),
+                       self.loop_counter.reset.eq(1),
+                       If(start,
+                               NextState("CHECK")
+                       )
+               )
+               fsm.act("CHECK",
+                       If(self.loop_counter.value < loops,
+                               NextState("START")
+                       ).Else(
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("START",
+                       bist_unit.start.eq(1),
+                       NextState("WAIT_DONE")
+               )
+               fsm.act("WAIT_DONE",
+                       If(bist_unit.done,
+                               self.loop_counter.ce.eq(1),
+                               NextState("CHECK")
+                       )
+               )
+
                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)
+                       self.cycles_counter.reset.eq(start),
+                       self.cycles_counter.ce.eq(~fsm.ongoing("IDLE"))
                ]
 
 class LiteSATABISTIdentify(Module):
index 464954d29b7fa5a3ccc0e6bcaabf420bdf9deb81..a707199cf17c24061097b35ce6bcff5947a7dcfe 100644 (file)
@@ -9,27 +9,45 @@ GB = 1024*MB
 
 logical_sector_size = 512
 
+class Timer:
+       def __init__(self):
+               self.value = None
+
+       def start(self):
+               self._start = time.time()
+
+       def stop(self):
+               self._stop = time.time()
+               self.value = max(self._stop - self._start, 1/1000000)
+
 class LiteSATABISTUnitDriver:
        def __init__(self, regs, name):
                self.regs = regs
                self.name = name
                self.frequency = regs.identifier_frequency.read()
                self.time = 0
-               for s in ["start", "sector", "count", "random", "done", "aborted", "errors", "cycles"]:
+               for s in ["start", "sector", "count", "loops", "random", "done", "aborted", "errors", "cycles"]:
                        setattr(self, s, getattr(regs, name + "_"+ s))
 
-       def run(self, sector, count, random, blocking=True):
+       def run(self, sector, count, loops, random, blocking=True, hw_timer=False):
                self.sector.write(sector)
                self.count.write(count)
+               self.loops.write(loops)
                self.random.write(random)
+               timer = Timer()
+               timer.start()
                self.start.write(1)
                if blocking:
                        while (self.done.read() == 0):
                                pass
+               timer.stop()
                aborted = self.aborted.read()
                if not aborted:
-                       self.time = self.cycles.read()/self.frequency
-                       speed = (count*logical_sector_size)/self.time
+                       if hw_timer:
+                               self.time = self.cycles.read()/self.frequency
+                       else:
+                               self.time = timer.value
+                       speed = (loops*count*logical_sector_size)/self.time
                        errors = self.errors.read()
                else:
                        speed = 0
@@ -111,6 +129,7 @@ SATA BIST utility.
 """)
        parser.add_argument("-s", "--transfer_size", default=1024, help="transfer sizes (in KB, up to 16MB)")
        parser.add_argument("-l", "--total_length", default=256, help="total transfer length (in MB, up to HDD capacity)")
+       parser.add_argument("-n", "--loops", default=1, help="number of loop per transfer (allow more precision on speed calculation for small transfers)")
        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)")
        parser.add_argument("-i", "--identify", action="store_true", help="only run identify")
@@ -130,6 +149,7 @@ if __name__ == "__main__":
        if not int(args.identify):
                sector = 0
                count = int(args.transfer_size)*KB//logical_sector_size
+               loops = int(args.loops)
                length = int(args.total_length)*MB
                random = int(args.random)
                continuous = int(args.continuous)
@@ -139,7 +159,7 @@ if __name__ == "__main__":
                                # generator (write data to HDD)
                                write_done = False
                                while not write_done:
-                                       write_aborted, write_errors, write_speed = generator.run(sector, count, random)
+                                       write_aborted, write_errors, write_speed = generator.run(sector, count, loops, random)
                                        write_done = not write_aborted
                                        if not write_done:
                                                retry += 1
@@ -147,7 +167,7 @@ if __name__ == "__main__":
                                # checker (read and check data from HDD)
                                read_done = False
                                while not read_done:
-                                       read_aborted, read_errors, read_speed = checker.run(sector, count, random)
+                                       read_aborted, read_errors, read_speed = checker.run(sector, count, loops, random)
                                        read_done = not read_aborted
                                        if not read_done:
                                                retry += 1
index fa4a5d0ad5e1bc6a852da4fa428cc255e4ced929..de8013cc23b42375873ecf23b1bf13332b23f4db 100644 (file)
@@ -48,8 +48,8 @@ mila.prog_sum("term")
 mila.trigger(offset=512, length=2000)
 
 #identify.run()
-generator.run(0, 2, 0)
-#checker.run(0, 2, 0)
+generator.run(0, 2, 1, 0)
+#checker.run(0, 2, 1, 0)
 mila.wait_done()
 
 mila.read()