litesata: use new Migen modules from actorlib/packet.py (avoid duplications between...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 27 Apr 2015 12:48:14 +0000 (14:48 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 27 Apr 2015 12:48:14 +0000 (14:48 +0200)
misoclib/mem/litesata/common.py
misoclib/mem/litesata/core/link/__init__.py
misoclib/mem/litesata/core/transport/__init__.py

index bb4aa5331488db9c6f9038256c12170f57e93fef..44a0ee19f5f16a1b220c42c5b9a93bbf60ce96d7 100644 (file)
@@ -9,9 +9,11 @@ from migen.genlib.misc import chooser, optree, Counter, Timeout
 from migen.genlib.cdc import *
 from migen.flow.actor import *
 from migen.flow.plumbing import Multiplexer, Demultiplexer
-from migen.flow.plumbing import Buffer
 from migen.actorlib.fifo import *
 from migen.actorlib.structuring import Pipeline, Converter
+from migen.actorlib.packet import Buffer
+from migen.actorlib.misc import BufferizeEndpoints
+from migen.actorlib.packet import HeaderField, Header
 
 bitrates = {
     "sata_gen3": 6.0,
@@ -84,76 +86,84 @@ fis_types = {
     "DATA":             0x46
 }
 
+fis_reg_h2d_header_length = 5
+fis_reg_h2d_header_fields = {
+    "type":         HeaderField(0*4,  0, 8),
+    "pm_port":      HeaderField(0*4,  8, 4),
+    "c":            HeaderField(0*4, 15, 1),
+    "command":      HeaderField(0*4, 16, 8),
+    "features_lsb": HeaderField(0*4, 24, 8),
 
-class FISField():
-    def __init__(self, dword, offset, width):
-        self.dword = dword
-        self.offset = offset
-        self.width = width
+    "lba_lsb":      HeaderField(1*4, 0, 24),
+    "device":       HeaderField(1*4, 24, 8),
 
-fis_reg_h2d_cmd_len = 5
-fis_reg_h2d_layout = {
-    "type":         FISField(0,  0, 8),
-    "pm_port":      FISField(0,  8, 4),
-    "c":            FISField(0, 15, 1),
-    "command":      FISField(0, 16, 8),
-    "features_lsb": FISField(0, 24, 8),
+    "lba_msb":      HeaderField(2*4, 0, 24),
+    "features_msb": HeaderField(2*4, 24, 8),
 
-    "lba_lsb":      FISField(1, 0, 24),
-    "device":       FISField(1, 24, 8),
-
-    "lba_msb":      FISField(2, 0, 24),
-    "features_msb": FISField(2, 24, 8),
-
-    "count":        FISField(3, 0, 16),
-    "icc":          FISField(3, 16, 8),
-    "control":      FISField(3, 24, 8)
+    "count":        HeaderField(3*4, 0, 16),
+    "icc":          HeaderField(3*4, 16, 8),
+    "control":      HeaderField(3*4, 24, 8)
 }
+fis_reg_h2d_header = Header(fis_reg_h2d_header_fields,
+                            fis_reg_h2d_header_length,
+                            swap_field_bytes=False)
 
-fis_reg_d2h_cmd_len = 5
-fis_reg_d2h_layout = {
-    "type":    FISField(0,  0, 8),
-    "pm_port": FISField(0,  8, 4),
-    "i":       FISField(0, 14, 1),
-    "status":  FISField(0, 16, 8),
-    "error":   FISField(0, 24, 8),
+fis_reg_d2h_header_length = 5
+fis_reg_d2h_header_fields = {
+    "type":    HeaderField(0*4,  0, 8),
+    "pm_port": HeaderField(0*4,  8, 4),
+    "i":       HeaderField(0*4, 14, 1),
+    "status":  HeaderField(0*4, 16, 8),
+    "error":   HeaderField(0*4, 24, 8),
 
-    "lba_lsb": FISField(1, 0, 24),
-    "device":  FISField(1, 24, 8),
+    "lba_lsb": HeaderField(1*4, 0, 24),
+    "device":  HeaderField(1*4, 24, 8),
 
-    "lba_msb": FISField(2, 0, 24),
+    "lba_msb": HeaderField(2*4, 0, 24),
 
-    "count":   FISField(3, 0, 16)
+    "count":   HeaderField(3*4, 0, 16)
 }
-
-fis_dma_activate_d2h_cmd_len = 1
-fis_dma_activate_d2h_layout = {
-    "type":    FISField(0,  0, 8),
-    "pm_port": FISField(0,  8, 4)
+fis_reg_d2h_header = Header(fis_reg_d2h_header_fields,
+                            fis_reg_d2h_header_length,
+                            swap_field_bytes=False)
+
+fis_dma_activate_d2h_header_length = 1
+fis_dma_activate_d2h_header_fields = {
+    "type":    HeaderField(0*4,  0, 8),
+    "pm_port": HeaderField(0*4,  8, 4)
 }
+fis_dma_activate_d2h_header = Header(fis_dma_activate_d2h_header_fields,
+                                     fis_dma_activate_d2h_header_length,
+                                     swap_field_bytes=False)
 
-fis_pio_setup_d2h_cmd_len = 5
-fis_pio_setup_d2h_layout = {
-    "type":    FISField(0,  0, 8),
-    "pm_port": FISField(0,  8, 4),
-    "d":       FISField(0, 13, 1),
-    "i":       FISField(0, 14, 1),
-    "status":  FISField(0, 16, 8),
-    "error":   FISField(0, 24, 8),
+fis_pio_setup_d2h_header_length = 5
+fis_pio_setup_d2h_header_fields = {
+    "type":           HeaderField(0*4,  0, 8),
+    "pm_port":        HeaderField(0*4,  8, 4),
+    "d":              HeaderField(0*4, 13, 1),
+    "i":              HeaderField(0*4, 14, 1),
+    "status":         HeaderField(0*4, 16, 8),
+    "error":          HeaderField(0*4, 24, 8),
 
-    "lba_lsb": FISField(1, 0, 24),
+    "lba_lsb":        HeaderField(1*4, 0, 24),
 
-    "lba_msb": FISField(2, 0, 24),
+    "lba_msb":        HeaderField(2*4, 0, 24),
 
-    "count":   FISField(3, 0, 16),
+    "count":          HeaderField(3*4, 0, 16),
 
-    "transfer_count":    FISField(4, 0, 16),
+    "transfer_count": HeaderField(4*4, 0, 16),
 }
+fis_pio_setup_d2h_header = Header(fis_pio_setup_d2h_header_fields,
+                                  fis_pio_setup_d2h_header_length,
+                                  swap_field_bytes=False)
 
-fis_data_cmd_len = 1
-fis_data_layout = {
-    "type": FISField(0,  0, 8)
+fis_data_header_length = 1
+fis_data_header_fields = {
+    "type": HeaderField(0,  0, 8)
 }
+fis_data_header = Header(fis_data_header_fields,
+                         fis_data_header_length,
+                         swap_field_bytes=False)
 
 
 def transport_tx_description(dw):
@@ -263,116 +273,3 @@ def dwords2sectors(n):
 
 def sectors2dwords(n):
     return n*logical_sector_size//4
-
-
-# Generic modules
-class BufferizeEndpoints(ModuleTransformer):
-    def __init__(self, *names):
-        self.names = names
-
-    def transform_instance(self, submodule):
-        endpoints = get_endpoints(submodule)
-        sinks = {}
-        sources = {}
-        for name, endpoint in endpoints.items():
-            if not self.names or name in self.names:
-                if isinstance(endpoint, Sink):
-                    sinks.update({name: endpoint})
-                elif isinstance(endpoint, Source):
-                    sources.update({name: endpoint})
-
-        # add buffer on sinks
-        for name, sink in sinks.items():
-            buf = Buffer(sink.description)
-            submodule.submodules += buf
-            setattr(self, name, buf.d)
-            submodule.comb += Record.connect(buf.q, sink)
-
-        # add buffer on sources
-        for name, source in sources.items():
-            buf = Buffer(source.description)
-            submodule.submodules += buf
-            submodule.comb += Record.connect(source, buf.d)
-            setattr(self, name, buf.q)
-
-
-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)
-        cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
-        self.submodules += cmd_fifo
-        self.comb += [
-            cmd_fifo.sink.stb.eq(sink_status.done),
-            cmd_fifo.sink.error.eq(sink.error)
-        ]
-
-        # data
-        data_fifo = SyncFIFO(description, data_depth, buffered=True)
-        self.submodules += data_fifo
-        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")
-        self.submodules += fsm
-        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 a6b80f3ae527e623e8d016843df0ef7132a14711..5c8ec6e25ab04583bfb672efb0a6b8f2cb6d96dc 100644 (file)
@@ -246,10 +246,10 @@ class LiteSATALinkRX(Module):
 
 class LiteSATALink(Module):
     def __init__(self, phy, buffer_depth):
-        self.submodules.tx_buffer = PacketBuffer(link_description(32), buffer_depth)
+        self.submodules.tx_buffer = Buffer(link_description(32), buffer_depth)
         self.submodules.tx = LiteSATALinkTX(phy)
         self.submodules.rx = LiteSATALinkRX(phy)
-        self.submodules.rx_buffer = PacketBuffer(link_description(32), buffer_depth,
+        self.submodules.rx_buffer = Buffer(link_description(32), buffer_depth,
                                                  almost_full=3*buffer_depth//4)
         self.comb += [
             Record.connect(self.tx_buffer.source, self.tx.sink),
index ed19b9b1770e974c1db04a4f377b185d41e28b04..9d31f9a7e381c9666da8bc60dc7d300d0dea58f7 100644 (file)
@@ -1,26 +1,6 @@
 from misoclib.mem.litesata.common import *
 
 
-def _get_item(obj, name, width):
-    if "_lsb" in name:
-        item = getattr(obj, name.replace("_lsb", ""))[:width]
-    elif "_msb" in name:
-        item = getattr(obj, name.replace("_msb", ""))[width:2*width]
-    else:
-        item = getattr(obj, name)
-    return item
-
-
-def _encode_cmd(obj, description, signal):
-    r = []
-    for k, v in sorted(description.items()):
-        start = v.dword*32 + v.offset
-        end = start + v.width
-        item = _get_item(obj, k, v.width)
-        r.append(signal[start:end].eq(item))
-    return r
-
-
 def test_type(name, signal):
     return signal == fis_types[name]
 
@@ -31,7 +11,8 @@ class LiteSATATransportTX(Module):
 
         # # #
 
-        cmd_ndwords = max(fis_reg_h2d_cmd_len, fis_data_cmd_len)
+        cmd_ndwords = max(fis_reg_h2d_header.length,
+                          fis_data_header.length)
         encoded_cmd = Signal(cmd_ndwords*32)
 
         counter = Counter(max=cmd_ndwords+1)
@@ -72,8 +53,8 @@ class LiteSATATransportTX(Module):
             If(update_fis_type, fis_type.eq(link.source.d[:8]))
 
         fsm.act("SEND_CTRL_CMD",
-            _encode_cmd(sink, fis_reg_h2d_layout, encoded_cmd),
-            cmd_len.eq(fis_reg_h2d_cmd_len-1),
+            fis_reg_h2d_header.encode(sink, encoded_cmd),
+            cmd_len.eq(fis_reg_h2d_header.length-1),
             cmd_send.eq(1),
             If(cmd_done,
                 sink.ack.eq(1),
@@ -82,8 +63,8 @@ class LiteSATATransportTX(Module):
         )
         fsm.act("SEND_DATA_CMD",
             sink.ack.eq(0),
-            _encode_cmd(sink, fis_data_layout, encoded_cmd),
-            cmd_len.eq(fis_data_cmd_len-1),
+            fis_data_header.encode(sink, encoded_cmd),
+            cmd_len.eq(fis_data_header.length-1),
             cmd_with_data.eq(1),
             cmd_send.eq(1),
             If(cmd_done,
@@ -121,24 +102,16 @@ class LiteSATATransportTX(Module):
         ]
 
 
-def _decode_cmd(signal, description, obj):
-    r = []
-    for k, v in sorted(description.items()):
-        start = v.dword*32+v.offset
-        end = start+v.width
-        item = _get_item(obj, k, v.width)
-        r.append(item.eq(signal[start:end]))
-    return r
-
-
 class LiteSATATransportRX(Module):
     def __init__(self, link):
         self.source = source = Source(transport_rx_description(32))
 
         # # #
 
-        cmd_ndwords = max(fis_reg_d2h_cmd_len, fis_dma_activate_d2h_cmd_len,
-                          fis_pio_setup_d2h_cmd_len, fis_data_cmd_len)
+        cmd_ndwords = max(fis_reg_d2h_header.length,
+                          fis_dma_activate_d2h_header.length,
+                          fis_pio_setup_d2h_header.length,
+                          fis_data_header.length)
         encoded_cmd = Signal(cmd_ndwords*32)
 
         counter = Counter(max=cmd_ndwords+1)
@@ -186,11 +159,11 @@ class LiteSATATransportRX(Module):
 
         fsm.act("RECEIVE_CTRL_CMD",
             If(test_type("REG_D2H", fis_type),
-                cmd_len.eq(fis_reg_d2h_cmd_len-1)
+                cmd_len.eq(fis_reg_d2h_header.length-1)
             ).Elif(test_type("DMA_ACTIVATE_D2H", fis_type),
-                cmd_len.eq(fis_dma_activate_d2h_cmd_len-1)
+                cmd_len.eq(fis_dma_activate_d2h_header.length-1)
             ).Else(
-                cmd_len.eq(fis_pio_setup_d2h_cmd_len-1)
+                cmd_len.eq(fis_pio_setup_d2h_header.length-1)
             ),
             cmd_receive.eq(1),
             link.source.ack.eq(1),
@@ -203,18 +176,18 @@ class LiteSATATransportRX(Module):
             source.sop.eq(1),
             source.eop.eq(1),
             If(test_type("REG_D2H", fis_type),
-                _decode_cmd(encoded_cmd, fis_reg_d2h_layout, source),
+                fis_reg_d2h_header.decode(encoded_cmd, source)
             ).Elif(test_type("DMA_ACTIVATE_D2H", fis_type),
-                _decode_cmd(encoded_cmd, fis_dma_activate_d2h_layout, source),
+                fis_dma_activate_d2h_header.decode(encoded_cmd, source)
             ).Else(
-                _decode_cmd(encoded_cmd, fis_pio_setup_d2h_layout, source),
+                fis_pio_setup_d2h_header.decode(encoded_cmd, source)
             ),
             If(source.stb & source.ack,
                 NextState("IDLE")
             )
         )
         fsm.act("RECEIVE_DATA_CMD",
-            cmd_len.eq(fis_data_cmd_len-1),
+            cmd_len.eq(fis_data_header.length-1),
             cmd_receive.eq(1),
             link.source.ack.eq(1),
             If(cmd_done,
@@ -224,7 +197,7 @@ class LiteSATATransportRX(Module):
         fsm.act("PRESENT_DATA",
             data_receive.eq(1),
             source.stb.eq(link.source.stb),
-            _decode_cmd(encoded_cmd, fis_data_layout, source),
+            fis_data_header.decode(encoded_cmd, source),
             source.sop.eq(data_sop),
             source.eop.eq(link.source.eop),
             source.error.eq(link.source.error),