From 578903bc115583dcd54048707341e7236b2285d0 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 20 Jan 2015 17:14:01 +0100 Subject: [PATCH] manage reg_d2h errors --- litesata/common.py | 13 +++++++ litesata/core/command/__init__.py | 31 +++++++++++----- litesata/frontend/bist.py | 6 ++++ test/bist.py | 59 ++++++++++++++++++++----------- test/tools.py | 8 +++-- 5 files changed, 86 insertions(+), 31 deletions(-) diff --git a/litesata/common.py b/litesata/common.py index 90f7c23c..19e62fb1 100644 --- a/litesata/common.py +++ b/litesata/common.py @@ -184,6 +184,19 @@ regs = { "IDENTIFY_DEVICE" : 0xEC } +reg_d2h_status = { + "bsy" : 7, + "drdy" : 6, + "df" : 5, + "se" : 5, + "dwe" : 4, + "drq" : 3, + "ae" : 2, + "sns" : 1, + "cc" : 0, + "err" : 0 +} + def command_tx_description(dw): layout = [ ("write", 1), diff --git a/litesata/core/command/__init__.py b/litesata/core/command/__init__.py index 130b5fc3..2241ea7f 100644 --- a/litesata/core/command/__init__.py +++ b/litesata/core/command/__init__.py @@ -8,7 +8,8 @@ tx_to_rx = [ ] rx_to_tx = [ - ("dma_activate", 1) + ("dma_activate", 1), + ("d2h_error", 1) ] class LiteSATACommandTX(Module): @@ -64,6 +65,9 @@ class LiteSATACommandTX(Module): dwords_counter.reset.eq(1), If(from_rx.dma_activate, NextState("SEND_DATA") + ).Elif(from_rx.d2h_error, + sink.ack.eq(1), + NextState("IDLE") ) ) fsm.act("SEND_DATA", @@ -145,10 +149,21 @@ class LiteSATACommandRX(Module): ) self.comb += read_done.eq(self.dwords_counter.value == read_ndwords) + d2h_error = Signal() + clr_d2h_error = Signal() + set_d2h_error = Signal() + self.sync += \ + If(clr_d2h_error, + d2h_error.eq(0) + ).Elif(set_d2h_error, + d2h_error.eq(1) + ) + self.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", self.dwords_counter.reset.eq(1), transport.source.ack.eq(1), + clr_d2h_error.eq(1), If(from_tx.write, NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H") ).Elif(from_tx.read, @@ -167,7 +182,7 @@ class LiteSATACommandRX(Module): If(test_type("DMA_ACTIVATE_D2H"), dma_activate.eq(1), ).Elif(test_type("REG_D2H"), - # XXX: use status and error fields of REG_D2H + set_d2h_error.eq(transport.source.status[reg_d2h_status["err"]]), NextState("PRESENT_WRITE_RESPONSE") ) ) @@ -176,8 +191,8 @@ class LiteSATACommandRX(Module): cmd_buffer.sink.stb.eq(1), cmd_buffer.sink.write.eq(1), cmd_buffer.sink.last.eq(1), - cmd_buffer.sink.success.eq(~transport.source.error), - cmd_buffer.sink.failed.eq(transport.source.error), + cmd_buffer.sink.success.eq(~transport.source.error & ~d2h_error), + cmd_buffer.sink.failed.eq(transport.source.error | d2h_error), If(cmd_buffer.sink.stb & cmd_buffer.sink.ack, NextState("IDLE") ) @@ -189,7 +204,7 @@ class LiteSATACommandRX(Module): If(test_type("DATA"), NextState("PRESENT_READ_DATA") ).Elif(test_type("REG_D2H"), - # XXX: use status and error fields of REG_D2H + set_d2h_error.eq(transport.source.status[reg_d2h_status["err"]]), NextState("PRESENT_READ_RESPONSE") ) ) @@ -205,7 +220,6 @@ class LiteSATACommandRX(Module): ) fsm.act("PRESENT_PIO_SETUP_D2H", transport.source.ack.eq(1), - # XXX : Check error/ status If(transport.source.stb & transport.source.eop, NextState("WAIT_READ_DATA_OR_REG_D2H") ) @@ -242,8 +256,8 @@ class LiteSATACommandRX(Module): cmd_buffer.sink.read.eq(~identify), cmd_buffer.sink.identify.eq(identify), cmd_buffer.sink.last.eq(read_done | identify), - cmd_buffer.sink.success.eq(~read_error), - cmd_buffer.sink.failed.eq(read_error), + cmd_buffer.sink.success.eq(~read_error & ~d2h_error), + cmd_buffer.sink.failed.eq(read_error | d2h_error), If(cmd_buffer.sink.stb & cmd_buffer.sink.ack, If(cmd_buffer.sink.failed, data_buffer.reset.eq(1) @@ -301,6 +315,7 @@ class LiteSATACommandRX(Module): self.comb += [ to_tx.dma_activate.eq(dma_activate), + to_tx.d2h_error.eq(d2h_error) ] class LiteSATACommand(Module): diff --git a/litesata/frontend/bist.py b/litesata/frontend/bist.py index be994cb4..02abd3b9 100644 --- a/litesata/frontend/bist.py +++ b/litesata/frontend/bist.py @@ -12,6 +12,7 @@ class LiteSATABISTGenerator(Module): self.random = Signal() self.done = Signal() + self.aborted = Signal() self.errors = Signal(32) # Note: Not used for writes ### @@ -61,6 +62,7 @@ class LiteSATABISTGenerator(Module): NextState("IDLE") ) ) + self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed)) class LiteSATABISTChecker(Module): def __init__(self, sata_master_port): @@ -70,6 +72,7 @@ class LiteSATABISTChecker(Module): self.random = Signal() self.done = Signal() + self.aborted = Signal() self.errors = Signal(32) ### @@ -136,6 +139,7 @@ class LiteSATABISTChecker(Module): ) ) ) + self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed)) class LiteSATABISTUnitCSR(Module, AutoCSR): def __init__(self, bist_unit): @@ -144,6 +148,7 @@ class LiteSATABISTUnitCSR(Module, AutoCSR): self._count = CSRStorage(16) self._random = CSRStorage() self._done = CSRStatus() + self._aborted = CSRStatus() self._errors = CSRStatus(32) self._cycles = CSRStatus(32) @@ -157,6 +162,7 @@ class LiteSATABISTUnitCSR(Module, AutoCSR): 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) ] diff --git a/test/bist.py b/test/bist.py index a1f60473..464954d2 100644 --- a/test/bist.py +++ b/test/bist.py @@ -15,20 +15,26 @@ class LiteSATABISTUnitDriver: self.name = name self.frequency = regs.identifier_frequency.read() self.time = 0 - for s in ["start", "sector", "count", "random", "done", "errors", "cycles"]: + for s in ["start", "sector", "count", "random", "done", "aborted", "errors", "cycles"]: setattr(self, s, getattr(regs, name + "_"+ s)) - def run(self, sector, count, random): + def run(self, sector, count, random, blocking=True): self.sector.write(sector) self.count.write(count) self.random.write(random) self.start.write(1) - while (self.done.read() == 0): - pass - self.time = self.cycles.read()/self.frequency - speed = (count*logical_sector_size)/self.time - errors = self.errors.read() - return (speed, errors) + if blocking: + while (self.done.read() == 0): + pass + aborted = self.aborted.read() + if not aborted: + self.time = self.cycles.read()/self.frequency + speed = (count*logical_sector_size)/self.time + errors = self.errors.read() + else: + speed = 0 + errors = -1 + return (aborted, errors, speed) class LiteSATABISTGeneratorDriver(LiteSATABISTUnitDriver): def __init__(self, regs, name): @@ -55,13 +61,14 @@ class LiteSATABISTIdentifyDriver: self.data += [word_lsb, word_msb] self.source_ack.write(1) - def run(self): + def run(self, blocking=True): self.read_fifo() # flush the fifo before we start self.start.write(1) - while (self.done.read() == 0): - pass - self.read_fifo() - self.decode() + if blocking: + while (self.done.read() == 0): + pass + self.read_fifo() + self.decode() def decode(self): self.serial_number = "" @@ -102,7 +109,7 @@ def _get_args(): description="""\ SATA BIST utility. """) - parser.add_argument("-s", "--transfer_size", default=4, help="transfer sizes (in MB, up to 16MB)") + 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("-r", "--random", action="store_true", help="use random data") parser.add_argument("-c", "--continuous", action="store_true", help="continuous mode (Escape to exit)") @@ -122,24 +129,36 @@ if __name__ == "__main__": if not int(args.identify): sector = 0 - count = int(args.transfer_size)*MB//logical_sector_size + count = int(args.transfer_size)*KB//logical_sector_size length = int(args.total_length)*MB random = int(args.random) continuous = int(args.continuous) try: while ((sector*logical_sector_size < length) or continuous) and (sector < identify.total_sectors): + retry = 0 # generator (write data to HDD) - write_speed, write_errors = generator.run(sector, count, random) + write_done = False + while not write_done: + write_aborted, write_errors, write_speed = generator.run(sector, count, random) + write_done = not write_aborted + if not write_done: + retry += 1 # checker (read and check data from HDD) - read_speed, read_errors = checker.run(sector, count, random) - - print("sector=%d(%dMB) wr_speed=%4.2fMB/sec rd_speed=%4.2fMB/sec errors=%d" %( + read_done = False + while not read_done: + read_aborted, read_errors, read_speed = checker.run(sector, count, random) + read_done = not read_aborted + if not read_done: + retry += 1 + + print("sector=%d(%dMB) wr_speed=%4.2fMB/s rd_speed=%4.2fMB/s errors=%d retry=%d" %( sector, sector*logical_sector_size/MB, write_speed/MB, read_speed/MB, - write_errors + read_errors)) + write_errors + read_errors, + retry)) sector += count except KeyboardInterrupt: diff --git a/test/tools.py b/test/tools.py index 1e8411af..93f54ff5 100644 --- a/test/tools.py +++ b/test/tools.py @@ -23,7 +23,8 @@ def decode_primitive(dword): return k return "" -def print_link_trace(mila, tx_data_name, rx_data_name): +def link_trace(mila, tx_data_name, rx_data_name): + r = "" dump = Dump() dump.add_from_layout(mila.layout, mila.dat) @@ -33,7 +34,6 @@ def print_link_trace(mila, tx_data_name, rx_data_name): if var.name == rx_data_name: rx_data = var.values - print("") for i in range(len(tx_data)): tx = "%08x " %tx_data[i] tx += decode_primitive(tx_data[i]) @@ -43,4 +43,6 @@ def print_link_trace(mila, tx_data_name, rx_data_name): rx += decode_primitive(rx_data[i]) rx += " "*(16-len(rx)) - print(tx + rx) + r += tx + rx + "\n" + + return r -- 2.30.2