litesata: use new Migen modules from actorlib/packet.py (avoid duplications between cores)

This commit is contained in:
Florent Kermarrec 2015-04-27 14:48:14 +02:00
parent fe867ccf33
commit ded3f22574
3 changed files with 82 additions and 212 deletions

View 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_reg_d2h_header = Header(fis_reg_d2h_header_fields,
fis_reg_d2h_header_length,
swap_field_bytes=False)
fis_dma_activate_d2h_cmd_len = 1
fis_dma_activate_d2h_layout = {
"type": FISField(0, 0, 8),
"pm_port": FISField(0, 8, 4)
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)

View 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),

View 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),