command: code TX part and add command_tb

This commit is contained in:
Florent Kermarrec 2014-12-12 22:26:04 +01:00
parent 71f6a16913
commit 66ef7950ab
7 changed files with 220 additions and 6 deletions

View file

@ -0,0 +1,123 @@
from migen.fhdl.std import *
from migen.genlib.fsm import FSM, NextState
from lib.sata.std import *
from lib.sata.transport.std import *
regs = {
"WRITE_DMA_EXT" : 0x35,
"READ_DMA_EXT" : 0x25,
"IDENTIFY_DEVICE_DMA" : 0xEE
}
from_rx = [
("dma_activate", 1)
]
class SATACommandTX(Module):
def __init__(self, transport):
self.sink = sink = Sink(command_tx_layout(32))
self.from_rx = Sink(from_rx)
###
self.comb += [
transport.sink.pm_port.eq(0),
transport.sink.features.eq(0),
transport.sink.lba.eq(sink.address), # XXX need adaptation?
transport.sink.device.eq(0xe0),
transport.sink.count.eq(sink.length), # XXX need adaptation?
transport.sink.icc.eq(0),
transport.sink.control.eq(0),
]
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
fsm.act("IDLE",
If(sink.stb & sink.sop,
If(sink.write,
NextState("SEND_WRITE_DMA_CMD")
).Elif(sink.read,
NextState("SEND_READ_DMA_CMD")
).Elif(sink.identify,
NextState("SEND_IDENTIFY_CMD")
).Else(
sink.ack.eq(1)
)
).Else(
sink.ack.eq(1)
)
)
fsm.act("SEND_WRITE_DMA_CMD",
transport.sink.stb.eq(1),
transport.sink.sop.eq(1),
transport.sink.eop.eq(1),
transport.sink.type.eq(fis_types["REG_H2D"]),
transport.sink.c.eq(1),
transport.sink.command.eq(regs["WRITE_DMA_EXT"]),
If(transport.sink.ack,
NextState("WAIT_DMA_ACTIVATE")
)
)
fsm.act("WAIT_DMA_ACTIVATE",
If(self.from_rx.dma_activate,
NextState("SEND_DATA")
)
)
fsm.act("SEND_DATA",
transport.sink.stb.eq(sink.stb),
transport.sink.sop.eq(sink.sop),
transport.sink.eop.eq(sink.eop),
transport.sink.type.eq(fis_types["DATA"]),
transport.sink.data.eq(sink.data),
sink.ack.eq(transport.sink.ack),
If(sink.stb & sink.ack & sink.eop,
NextState("IDLE")
)
)
fsm.act("SEND_READ_DMA_CMD",
transport.sink.stb.eq(sink.stb),
transport.sink.sop.eq(1),
transport.sink.eop.eq(1),
transport.sink.type.eq(fis_types["REG_H2D"]),
transport.sink.c.eq(1),
transport.sink.command.eq(regs["READ_DMA_EXT"]),
sink.ack.eq(transport.sink.ack),
If(sink.stb & sink.ack,
NextState("IDLE")
)
)
fsm.act("SEND_IDENTIFY_CMD",
transport.sink.stb.eq(sink.stb),
transport.sink.sop.eq(1),
transport.sink.eop.eq(1),
transport.sink.type.eq(fis_types["REG_H2D"]),
transport.sink.c.eq(1),
transport.sink.command.eq(regs["IDENTIFY_DEVICE_DMA"]),
sink.ack.eq(transport.sink.ack),
If(sink.stb & sink.ack,
NextState("IDLE")
)
)
class SATACommandRX(Module):
def __init__(self, transport):
self.source = source = Source(command_tx_layout(32))
self.to_tx = Source(from_rx)
###
self.comb += [
transport.source.ack.eq(1),
If(transport.source.stb & (transport.source.type == fis_types["DMA_ACTIVATE_D2H"]),
self.to_tx.dma_activate.eq(1)
)
]
class SATACommand(Module):
def __init__(self, transport):
self.submodules.tx = SATACommandTX(transport)
self.submodules.rx = SATACommandRX(transport)
self.sink, self.source = self.tx.sink, self.rx.source
self.comb += self.rx.to_tx.connect(self.tx.from_rx)

View file

@ -82,6 +82,7 @@ def command_tx_layout(dw):
layout = [ layout = [
("write", 1), ("write", 1),
("read", 1), ("read", 1),
("identify", 1),
("address", 32), ("address", 32),
("length", 32), ("length", 32),
("data", dw) ("data", dw)
@ -92,6 +93,7 @@ def command_rx_layout(dw):
layout = [ layout = [
("write", 1), ("write", 1),
("read", 1), ("read", 1),
("identify", 1),
("success", 1), ("success", 1),
("failed", 1), ("failed", 1),
("data", dw) ("data", dw)

View file

@ -20,6 +20,9 @@ link_tb:
transport_tb: transport_tb:
$(CMD) transport_tb.py $(CMD) transport_tb.py
command_tb:
$(CMD) command_tb.py
all: crc_tb scrambler_tb link_tb all: crc_tb scrambler_tb link_tb
clean: clean:

View file

@ -287,6 +287,7 @@ class FIS:
class FIS_REG_H2D(FIS): class FIS_REG_H2D(FIS):
def __init__(self, packet=[0]*fis_reg_h2d_cmd_len): def __init__(self, packet=[0]*fis_reg_h2d_cmd_len):
FIS.__init__(self, packet,fis_reg_h2d_layout) FIS.__init__(self, packet,fis_reg_h2d_layout)
self.type = fis_types["REG_H2D"]
def __repr__(self): def __repr__(self):
r = "FIS_REG_H2D\n" r = "FIS_REG_H2D\n"
@ -296,6 +297,7 @@ class FIS_REG_H2D(FIS):
class FIS_REG_D2H(FIS): class FIS_REG_D2H(FIS):
def __init__(self, packet=[0]*fis_reg_d2h_cmd_len): def __init__(self, packet=[0]*fis_reg_d2h_cmd_len):
FIS.__init__(self, packet,fis_reg_d2h_layout) FIS.__init__(self, packet,fis_reg_d2h_layout)
self.type = fis_types["REG_D2H"]
def __repr__(self): def __repr__(self):
r = "FIS_REG_D2H\n" r = "FIS_REG_D2H\n"
@ -305,6 +307,7 @@ class FIS_REG_D2H(FIS):
class FIS_DMA_ACTIVATE_D2H(FIS): class FIS_DMA_ACTIVATE_D2H(FIS):
def __init__(self, packet=[0]*fis_dma_activate_d2h_cmd_len): def __init__(self, packet=[0]*fis_dma_activate_d2h_cmd_len):
FIS.__init__(self, packet,fis_dma_activate_d2h_layout) FIS.__init__(self, packet,fis_dma_activate_d2h_layout)
self.type = fis_types["DMA_ACTIVATE_D2H"]
def __repr__(self): def __repr__(self):
r = "FIS_DMA_ACTIVATE_D2H\n" r = "FIS_DMA_ACTIVATE_D2H\n"
@ -314,6 +317,7 @@ class FIS_DMA_ACTIVATE_D2H(FIS):
class FIS_DATA(FIS): class FIS_DATA(FIS):
def __init__(self, packet=[0]): def __init__(self, packet=[0]):
FIS.__init__(self, packet,fis_data_layout) FIS.__init__(self, packet,fis_data_layout)
self.type = fis_types["DATA"]
def __repr__(self): def __repr__(self):
r = "FIS_DATA\n" r = "FIS_DATA\n"
@ -340,8 +344,18 @@ class TransportLayer(Module):
self.loopback = loopback self.loopback = loopback
self.link.set_transport_callback(self.callback) self.link.set_transport_callback(self.callback)
def set_command_callback(self, callback):
self.command_callback = callback
def send(self, fis):
fis.encode()
packet = LinkTXPacket(fis.packet)
self.link.tx_packets.append(packet)
if self.debug and not self.loopback:
print(fis)
def callback(self, packet): def callback(self, packet):
fis_type = packet[0] fis_type = packet[0] & 0xff
if fis_type == fis_types["REG_H2D"]: if fis_type == fis_types["REG_H2D"]:
fis = FIS_REG_H2D(packet) fis = FIS_REG_H2D(packet)
elif fis_type == fis_types["REG_D2H"]: elif fis_type == fis_types["REG_D2H"]:
@ -355,16 +369,39 @@ class TransportLayer(Module):
if self.debug: if self.debug:
print(fis) print(fis)
if self.loopback: if self.loopback:
packet = LinkTXPacket(fis.packet) self.send(fis)
self.link.tx_packets.append(packet) else:
self.command_callback(fis)
regs = {
"WRITE_DMA_EXT" : 0x35,
"READ_DMA_EXT" : 0x25,
"IDENTIFY_DEVICE_DMA" : 0xEE
}
class CommandLayer(Module):
def __init__(self, transport, debug=False):
self.transport = transport
self.debug = debug
self.transport.set_command_callback(self.callback)
def callback(self, fis):
if isinstance(fis, FIS_REG_H2D):
if fis.command == regs["WRITE_DMA_EXT"]:
# XXX add checks
dma_activate = FIS_DMA_ACTIVATE_D2H()
# XXX fill dma_activate
self.transport.send(dma_activate)
class BFM(Module): class BFM(Module):
def __init__(self, def __init__(self,
phy_debug=False, phy_debug=False,
link_debug=False, link_random_level=0, link_debug=False, link_random_level=0,
transport_debug=False, transport_loopback=False transport_debug=False, transport_loopback=False,
command_debug=False
): ):
### ###
self.submodules.phy = PHYLayer(phy_debug) self.submodules.phy = PHYLayer(phy_debug)
self.submodules.link = LinkLayer(self.phy, link_debug, link_random_level) self.submodules.link = LinkLayer(self.phy, link_debug, link_random_level)
self.submodules.transport = TransportLayer(self.link, transport_debug, transport_loopback) self.submodules.transport = TransportLayer(self.link, transport_debug, transport_loopback)
self.submodules.command = CommandLayer(self.transport, command_debug)

View file

@ -0,0 +1,40 @@
import random
from migen.fhdl.std import *
from migen.genlib.record import *
from migen.sim.generic import run_simulation
from lib.sata.std import *
from lib.sata.link import SATALink
from lib.sata.transport import SATATransport
from lib.sata.command import SATACommand
from lib.sata.test.bfm import *
from lib.sata.test.common import *
class TB(Module):
def __init__(self):
self.submodules.bfm = BFM(phy_debug=False,
link_random_level=0, transport_debug=True, transport_loopback=False)
self.submodules.link = SATALink(self.bfm.phy)
self.submodules.transport = SATATransport(self.link)
self.submodules.command = SATACommand(self.transport)
def gen_simulation(self, selfp):
for i in range(100):
yield
for i in range(32):
selfp.command.sink.stb = 1
selfp.command.sink.sop = (i==0)
selfp.command.sink.eop = (i==31)
selfp.command.sink.write = 1
selfp.command.sink.address = 0x1234
selfp.command.sink.length = 32
selfp.command.sink.data = i
yield
while selfp.command.sink.ack == 0:
yield
selfp.command.sink.ack = 0
if __name__ == "__main__":
run_simulation(TB(), ncycles=512, vcd_name="my.vcd", keep_files=True)

View file

@ -218,15 +218,24 @@ class SATATransportRX(Module):
for i in range(cmd_ndwords): for i in range(cmd_ndwords):
cmd_cases[i] = [encoded_cmd[32*i:32*(i+1)].eq(link.source.d)] cmd_cases[i] = [encoded_cmd[32*i:32*(i+1)].eq(link.source.d)]
self.sync += \ self.comb += \
If(cmd_receive, If(cmd_receive,
If(link.source.stb, If(link.source.stb,
Case(cnt, cmd_cases),
inc_cnt.eq(1), inc_cnt.eq(1),
).Else( ).Else(
inc_cnt.eq(0) inc_cnt.eq(0)
) )
) )
self.sync += \
If(cmd_receive,
Case(cnt, cmd_cases),
)
self.sync += \
If(clr_cnt,
cnt.eq(0)
).Elif(inc_cnt,
cnt.eq(cnt+1)
)
self.comb += cmd_done.eq(cnt==cmd_len) self.comb += cmd_done.eq(cnt==cmd_len)
self.comb += link.source.ack.eq(cmd_receive | (data_receive & source.ack)) self.comb += link.source.ack.eq(cmd_receive | (data_receive & source.ack))