From ded3f225743608d009aee6e5e47fc41b61ef5a14 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 27 Apr 2015 14:48:14 +0200 Subject: [PATCH] litesata: use new Migen modules from actorlib/packet.py (avoid duplications between cores) --- misoclib/mem/litesata/common.py | 229 +++++------------- misoclib/mem/litesata/core/link/__init__.py | 4 +- .../mem/litesata/core/transport/__init__.py | 63 ++--- 3 files changed, 83 insertions(+), 213 deletions(-) diff --git a/misoclib/mem/litesata/common.py b/misoclib/mem/litesata/common.py index bb4aa533..44a0ee19 100644 --- a/misoclib/mem/litesata/common.py +++ b/misoclib/mem/litesata/common.py @@ -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) diff --git a/misoclib/mem/litesata/core/link/__init__.py b/misoclib/mem/litesata/core/link/__init__.py index a6b80f3a..5c8ec6e2 100644 --- a/misoclib/mem/litesata/core/link/__init__.py +++ b/misoclib/mem/litesata/core/link/__init__.py @@ -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), diff --git a/misoclib/mem/litesata/core/transport/__init__.py b/misoclib/mem/litesata/core/transport/__init__.py index ed19b9b1..9d31f9a7 100644 --- a/misoclib/mem/litesata/core/transport/__init__.py +++ b/misoclib/mem/litesata/core/transport/__init__.py @@ -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), -- 2.30.2