add PacketBuffer, simplify architecture and reduce ressource usage
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 21 Jan 2015 22:11:38 +0000 (23:11 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 21 Jan 2015 23:13:19 +0000 (00:13 +0100)
litesata/__init__.py
litesata/common.py
litesata/core/__init__.py
litesata/core/command/__init__.py
litesata/core/link/__init__.py
litesata/frontend/bist.py
litesata/test/command_tb.py
litesata/test/link_tb.py
targets/bist.py
test/test_link.py

index c75fc32c216c08a00a569bc80547e66f31b0a8db..78c3a8ca6e3b9263d325c4aaf43ad4170f500d6a 100644 (file)
@@ -6,14 +6,14 @@ from litesata.frontend import *
 from migen.bank.description import *
 
 class LiteSATA(Module, AutoCSR):
-       def __init__(self, phy,
+       def __init__(self, phy, buffer_depth=2*fis_max_dwords,
                        with_crossbar=False,
                        with_bist=False, with_bist_csr=False):
                # phy
                self.phy = phy
 
                # core
-               self.core = LiteSATACore(self.phy)
+               self.core = LiteSATACore(self.phy, buffer_depth)
 
                # frontend
                if with_crossbar:
index 87d77edb39638977d5779104ec31d345bfa78464..235c9065ed6e9d48839fc44d1d7a9d1acf9f0795 100644 (file)
@@ -301,3 +301,79 @@ class BufferizeEndpoints(Module):
 
        def __dir__(self):
                return dir(self.submodule)
+
+class EndpointPacketStatus(Module):
+       def __init__(self, endpoint):
+               self.start = Signal()
+               self.done = Signal()
+               self.ongoing = Signal()
+
+               ongoing = Signal()
+               self.comb += [
+                       self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack),
+                       self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack)
+               ]
+               self.sync += \
+                       If(self.start,
+                               ongoing.eq(1)
+                       ).Elif(self.done,
+                               ongoing.eq(0)
+                       )
+               self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done)
+
+class PacketBuffer(Module):
+       def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
+               self.sink = sink = Sink(description)
+               self.source = source = Source(description)
+
+               ###
+               sink_status = EndpointPacketStatus(self.sink)
+               source_status = EndpointPacketStatus(self.source)
+               self.submodules += sink_status, source_status
+
+               # store incoming packets
+               # cmds
+               def cmd_description():
+                       layout = [("error", 1)]
+                       return EndpointDescription(layout)
+               self.cmd_fifo = cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
+               self.comb += [
+                       cmd_fifo.sink.stb.eq(sink_status.done),
+                       cmd_fifo.sink.error.eq(sink.error)
+               ]
+
+               # data
+               self.data_fifo =  data_fifo = SyncFIFO(description, data_depth, buffered=True)
+               self.comb += [
+                       Record.connect(self.sink, data_fifo.sink),
+                       data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack),
+                       self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack),
+               ]
+
+               # output packets
+               self.fsm = fsm = FSM(reset_state="IDLE")
+               fsm.act("IDLE",
+                       If(cmd_fifo.source.stb,
+                               NextState("SEEK_SOP")
+                       )
+               )
+               fsm.act("SEEK_SOP",
+                       If(~data_fifo.source.sop,
+                               data_fifo.source.ack.eq(1)
+                       ).Else(
+                               NextState("OUTPUT")
+                       )
+               )
+               fsm.act("OUTPUT",
+                       Record.connect(data_fifo.source, self.source),
+                       self.source.error.eq(cmd_fifo.source.error),
+                       If(source_status.done,
+                               cmd_fifo.source.ack.eq(1),
+                               NextState("IDLE")
+                       )
+               )
+
+               # compute almost full
+               if almost_full is not None:
+                       self.almost_full = Signal()
+                       self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full)
index c32028bb983fb6e39c7f26786cc5c7a50748b793..ce7dc90374aab80d59fe0ff698c6029703381db3 100644 (file)
@@ -4,8 +4,8 @@ from litesata.core.transport import LiteSATATransport
 from litesata.core.command import LiteSATACommand
 
 class LiteSATACore(Module):
-       def __init__(self, phy):
-               self.link = LiteSATALink(phy)
+       def __init__(self, phy, buffer_depth):
+               self.link = LiteSATALink(phy, buffer_depth)
                self.transport = LiteSATATransport(self.link)
                self.command = LiteSATACommand(self.transport)
                self.sink, self.source = self.command.sink, self.command.source
index 3e0b9b798563324405cd81558fb649ab89ad21b6..f614415bb3a4aadb91ce46dd949d4cb7752253bd 100644 (file)
@@ -62,6 +62,7 @@ class LiteSATACommandTX(Module):
                                If(is_write,
                                        NextState("WAIT_DMA_ACTIVATE")
                                ).Else(
+                                       sink.ack.eq(1),
                                        NextState("IDLE")
                                )
                        )
@@ -121,11 +122,6 @@ class LiteSATACommandRX(Module):
 
                ###
 
-               cmd_buffer = Buffer(command_rx_cmd_description(32))
-               cmd_buffer.sink, cmd_buffer.source = cmd_buffer.d, cmd_buffer.q
-               data_buffer = InsertReset(SyncFIFO(command_rx_data_description(32), fis_max_dwords, buffered=True))
-               self.submodules += cmd_buffer, data_buffer
-
                def test_type(name):
                        return transport.source.type == fis_types[name]
 
@@ -151,11 +147,22 @@ class LiteSATACommandRX(Module):
                                d2h_error.eq(1)
                        )
 
+               read_error = Signal()
+               clr_read_error = Signal()
+               set_read_error = Signal()
+               self.sync += \
+                       If(clr_read_error,
+                               read_error.eq(0)
+                       ).Elif(set_read_error,
+                               read_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),
+                       clr_read_error.eq(1),
                        If(from_tx.write,
                                NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H")
                        ).Elif(from_tx.read,
@@ -180,12 +187,14 @@ class LiteSATACommandRX(Module):
                        )
                )
                fsm.act("PRESENT_WRITE_RESPONSE",
-                       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 & ~d2h_error),
-                       cmd_buffer.sink.failed.eq(transport.source.error | d2h_error),
-                       If(cmd_buffer.sink.stb & cmd_buffer.sink.ack,
+                       source.stb.eq(1),
+                       source.sop.eq(1),
+                       source.eop.eq(1),
+                       source.write.eq(1),
+                       source.last.eq(1),
+                       source.success.eq(~transport.source.error & ~d2h_error),
+                       source.failed.eq(transport.source.error | d2h_error),
+                       If(source.stb & source.ack,
                                NextState("IDLE")
                        )
                )
@@ -196,7 +205,6 @@ class LiteSATACommandRX(Module):
                                If(test_type("DATA"),
                                        NextState("PRESENT_READ_DATA")
                                ).Elif(test_type("REG_D2H"),
-                                       set_d2h_error.eq(transport.source.status[reg_d2h_status["err"]]),
                                        NextState("PRESENT_READ_RESPONSE")
                                )
                        )
@@ -217,90 +225,39 @@ class LiteSATACommandRX(Module):
                        )
                )
 
-               self.comb += [
-                       data_buffer.sink.sop.eq(transport.source.sop),
-                       data_buffer.sink.eop.eq(transport.source.eop),
-                       data_buffer.sink.data.eq(transport.source.data)
-               ]
                fsm.act("PRESENT_READ_DATA",
-                       data_buffer.sink.stb.eq(transport.source.stb),
-                       transport.source.ack.eq(data_buffer.sink.ack),
-                       If(data_buffer.sink.stb & data_buffer.sink.ack,
+                       set_read_error.eq(transport.source.error),
+                       source.stb.eq(transport.source.stb),
+                       source.sop.eq(transport.source.sop),
+                       source.eop.eq(transport.source.eop),
+                       source.read.eq(~is_identify),
+                       source.identify.eq(is_identify),
+                       source.success.eq(~transport.source.error),
+                       source.failed.eq(transport.source.error),
+                       source.last.eq(is_identify),
+                       source.data.eq(transport.source.data),
+                       transport.source.ack.eq(source.ack),
+                       If(source.stb & source.ack,
                                self.dwords_counter.ce.eq(~read_done),
-                               If(data_buffer.sink.eop,
-                                       If(read_done & ~is_identify,
-                                               NextState("WAIT_READ_DATA_OR_REG_D2H")
+                               If(source.eop,
+                                       If(is_identify,
+                                               NextState("IDLE")
                                        ).Else(
-                                               NextState("PRESENT_READ_RESPONSE")
+                                               NextState("WAIT_READ_DATA_OR_REG_D2H")
                                        )
                                )
                        )
                )
-               read_error = Signal()
-               self.sync += \
-                       If(fsm.before_entering("PRESENT_READ_DATA"),
-                               read_error.eq(1)
-                       ).Elif(transport.source.stb & transport.source.ack & transport.source.eop,
-                               read_error.eq(transport.source.error)
-                       )
-               fsm.act("PRESENT_READ_RESPONSE",
-                       cmd_buffer.sink.stb.eq(1),
-                       cmd_buffer.sink.read.eq(~is_identify),
-                       cmd_buffer.sink.identify.eq(is_identify),
-                       cmd_buffer.sink.last.eq(read_done | is_identify),
-                       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)
-                               ),
-                               If(read_done | is_identify,
-                                       NextState("IDLE")
-                               ).Else(
-                                       NextState("WAIT_READ_DATA_OR_REG_D2H")
-                               )
-                       )
-               )
-
-               self.out_fsm = out_fsm = FSM(reset_state="IDLE")
-               out_fsm.act("IDLE",
-                       If(cmd_buffer.source.stb,
-                               If((cmd_buffer.source.read | cmd_buffer.source.identify) & cmd_buffer.source.success,
-                                       NextState("PRESENT_RESPONSE_WITH_DATA"),
-                               ).Else(
-                                       NextState("PRESENT_RESPONSE_WITHOUT_DATA"),
-                               )
-                       )
-               )
-
-               self.comb += [
-                       source.write.eq(cmd_buffer.source.write),
-                       source.read.eq(cmd_buffer.source.read),
-                       source.identify.eq(cmd_buffer.source.identify),
-                       source.last.eq(cmd_buffer.source.last),
-                       source.success.eq(cmd_buffer.source.success),
-                       source.failed.eq(cmd_buffer.source.failed),
-                       source.data.eq(data_buffer.source.data)
-               ]
-
-               out_fsm.act("PRESENT_RESPONSE_WITH_DATA",
-                       source.stb.eq(data_buffer.source.stb),
-                       source.sop.eq(data_buffer.source.sop),
-                       source.eop.eq(data_buffer.source.eop),
 
-                       data_buffer.source.ack.eq(source.ack),
-
-                       If(source.stb & source.eop & source.ack,
-                               cmd_buffer.source.ack.eq(1),
-                               NextState("IDLE")
-                       )
-               )
-               out_fsm.act("PRESENT_RESPONSE_WITHOUT_DATA",
+               fsm.act("PRESENT_READ_RESPONSE",
                        source.stb.eq(1),
                        source.sop.eq(1),
                        source.eop.eq(1),
+                       source.read.eq(1),
+                       source.last.eq(1),
+                       source.success.eq(read_done & ~read_error & ~d2h_error),
+                       source.failed.eq(~read_done | read_error | d2h_error),
                        If(source.stb & source.ack,
-                               cmd_buffer.source.ack.eq(1),
                                NextState("IDLE")
                        )
                )
index 64884eeee4c3a03dbdaaedf74712577855c53f7b..b6abd9dfbc33f25cb764cb03bd03da8ed6de1922 100644 (file)
@@ -110,6 +110,7 @@ class LiteSATALinkTX(Module):
 class LiteSATALinkRX(Module):
        def __init__(self, phy):
                self.source = Source(link_description(32))
+               self.hold = Signal()
                self.to_tx = Source(from_rx)
 
                ###
@@ -152,15 +153,11 @@ class LiteSATALinkRX(Module):
                                crc_error.eq(crc.source.error)
                        )
 
-               # small fifo to manage HOLD
-               self.fifo = SyncFIFO(link_description(32), 32)
-
                # graph
                self.comb += [
                        cont.source.ack.eq(1),
                        Record.connect(scrambler.source, crc.sink),
-                       Record.connect(crc.source, self.fifo.sink),
-                       Record.connect(self.fifo.source, self.source)
+                       Record.connect(crc.source, self.source),
                ]
                cont_source_data_d = Signal(32)
                self.sync += \
@@ -198,7 +195,7 @@ class LiteSATALinkRX(Module):
                                insert.eq(primitives["HOLDA"])
                        ).Elif(det == primitives["EOF"],
                                NextState("WTRM")
-                       ).Elif(self.fifo.fifo.level > 8,
+                       ).Elif(self.hold,
                                insert.eq(primitives["HOLD"])
                        )
                )
@@ -237,8 +234,15 @@ class LiteSATALinkRX(Module):
                ]
 
 class LiteSATALink(Module):
-       def __init__(self, phy):
+       def __init__(self, phy, buffer_depth):
+               self.tx_buffer = PacketBuffer(link_description(32), buffer_depth)
                self.tx = LiteSATALinkTX(phy)
                self.rx = LiteSATALinkRX(phy)
-               self.comb += Record.connect(self.rx.to_tx, self.tx.from_rx)
-               self.sink, self.source = self.tx.sink, self.rx.source
+               self.rx_buffer = PacketBuffer(link_description(32), buffer_depth, almost_full=3*buffer_depth//4)
+               self.comb += [
+                       Record.connect(self.tx_buffer.source, self.tx.sink),
+                       Record.connect(self.rx.to_tx, self.tx.from_rx),
+                       Record.connect(self.rx.source, self.rx_buffer.sink),
+                       self.rx.hold.eq(self.rx_buffer.almost_full)
+               ]
+               self.sink, self.source = self.tx_buffer.sink, self.rx_buffer.source
index 02abd3b9cabe33fae850ffbcf28a3e26009e7082..afb8daefb51209dac6bf2a83940f7615e1ab96fe 100644 (file)
@@ -128,7 +128,7 @@ class LiteSATABISTChecker(Module):
                        If(sink.stb,
                                counter.ce.eq(1),
                                If(sink.data != expected_data,
-                                       self.error_counter.ce.eq(1)
+                                       self.error_counter.ce.eq(~sink.last)
                                ),
                                If(sink.eop,
                                        If(sink.last,
index b5c9dc497b36d6374d04bd7d18413565f077eded..0b9d53a00dcb24c3a288bf41568b6681952f673c 100644 (file)
@@ -59,7 +59,7 @@ class TB(Module):
                                link_debug=False, link_random_level=50,
                                transport_debug=False, transport_loopback=False,
                                hdd_debug=True)
-               self.core = LiteSATACore(self.hdd.phy)
+               self.core = LiteSATACore(self.hdd.phy, buffer_depth=512)
 
                self.streamer = CommandStreamer()
                self.streamer_randomizer = Randomizer(command_tx_description(32), level=50)
index daca230de823fded395256d3cef4f381272c4b69..17abe2c89650868813073d0a23ddb553ea627f47 100644 (file)
@@ -17,7 +17,7 @@ class TB(Module):
                self.hdd = HDD(
                                link_debug=False, link_random_level=50,
                                transport_debug=False, transport_loopback=True)
-               self.link = InsertReset(LiteSATALink(self.hdd.phy))
+               self.link = InsertReset(LiteSATALink(self.hdd.phy, buffer_depth=512))
 
                self.streamer = LinkStreamer()
                self.streamer_randomizer = Randomizer(link_description(32), level=50)
index 144bf8dcc99a496867e57e59f0c5547b452b3995..29581b28286a3e05463adffc9bf7cccbe8615e40 100644 (file)
@@ -202,7 +202,7 @@ class BISTSoCDevel(BISTSoC, AutoCSR):
                self.mila = MiLa(depth=2048, dat=Cat(*debug))
                self.mila.add_port(Term)
                if export_mila:
-                       mila_filename = os.path.join(platform.soc_ext_path, "test", "mila.csv")
+                       mila_filename = os.path.join("test", "mila.csv")
                        self.mila.export(self, debug, mila_filename)
 
        def do_finalize(self):
index 46e414113464ea97a0157da45edfbb60ea444122..fa4a5d0ad5e1bc6a852da4fa428cc255e4ced929 100644 (file)
@@ -18,27 +18,27 @@ if len(sys.argv) < 2:
 
 conditions = {}
 conditions["wr_cmd"] = {
-       "bistsocdevel_core_sink_stb"                    : 1,
-       "bistsocdevel_core_sink_payload_write"  : 1,
+       "sata_command_tx_sink_stb"                      : 1,
+       "sata_command_tx_sink_payload_write"    : 1,
 }
 conditions["wr_dma_activate"] = {
-       "bistsocdevel_core_source_source_stb"                   : 1,
-       "bistsocdevel_core_source_source_payload_write" : 1,
+       "sata_command_rx_source_stb"                    : 1,
+       "sata_command_rx_source_payload_write"  : 1,
 }
 conditions["rd_cmd"] = {
-       "bistsocdevel_core_sink_stb"                    : 1,
-       "bistsocdevel_core_sink_payload_read"   : 1,
+       "sata_command_tx_sink_stb"                      : 1,
+       "sata_command_tx_sink_payload_read"     : 1,
 }
 conditions["rd_data"] = {
-       "bistsocdevel_core_source_source_stb"                   : 1,
-       "bistsocdevel_core_source_source_payload_read"  : 1,
+       "sata_command_rx_source_stb"                    : 1,
+       "sata_command_rx_source_payload_read"   : 1,
 }
 conditions["id_cmd"] = {
-       "bistsocdevel_core_sink_stb"                            : 1,
-       "bistsocdevel_core_sink_payload_identify"       : 1,
+       "sata_command_tx_sink_stb"                              : 1,
+       "sata_command_tx_sink_payload_identify" : 1,
 }
 conditions["id_pio_setup"] = {
-       "bistsocdevel_source_source_payload_data" : primitives["X_RDY"],
+       "source_source_payload_data" : primitives["X_RDY"],
 }
 
 mila.prog_term(port=0, cond=conditions[sys.argv[1]])
@@ -47,9 +47,9 @@ mila.prog_sum("term")
 # Trigger / wait / receive
 mila.trigger(offset=512, length=2000)
 
-identify.run()
+#identify.run()
 generator.run(0, 2, 0)
-checker.run(0, 2, 0)
+#checker.run(0, 2, 0)
 mila.wait_done()
 
 mila.read()
@@ -57,7 +57,10 @@ mila.export("dump.vcd")
 ###
 wb.close()
 
-print_link_trace(mila,
-       tx_data_name="bistsocdevel_sink_sink_payload_data",
-       rx_data_name="bistsocdevel_source_source_payload_data"
+f = open("dump_link.txt", "w")
+data = link_trace(mila,
+       tx_data_name="sink_sink_payload_data",
+       rx_data_name="source_source_payload_data"
 )
+f.write(data)
+f.close()