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,
"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):
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)
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]
# # #
- 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)
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),
)
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,
]
-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)
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),
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,
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),