litesata: cleanup link
This commit is contained in:
parent
0c08055014
commit
453279a7c8
misoclib/mem/litesata/test/model
|
@ -204,254 +204,3 @@ class LinkLayer(Module):
|
|||
else:
|
||||
self.callback(rx_dword)
|
||||
self.insert_cont()
|
||||
|
||||
|
||||
# Transport Layer model
|
||||
def print_transport(s):
|
||||
print_with_prefix(s, "[TRN]: ")
|
||||
|
||||
|
||||
def get_field_data(field, packet):
|
||||
return (packet[field.byte//4] >> field.offset) & (2**field.width-1)
|
||||
|
||||
|
||||
class FIS:
|
||||
def __init__(self, packet, description, direction="H2D"):
|
||||
self.packet = packet
|
||||
self.description = description
|
||||
self.direction = direction
|
||||
self.decode()
|
||||
|
||||
def decode(self):
|
||||
for k, v in self.description.items():
|
||||
setattr(self, k, get_field_data(v, self.packet))
|
||||
|
||||
def encode(self):
|
||||
for k, v in self.description.items():
|
||||
self.packet[v.byte//4] |= (getattr(self, k) << v.offset)
|
||||
|
||||
def __repr__(self):
|
||||
if self.direction == "H2D":
|
||||
r = ">>>>>>>>\n"
|
||||
else:
|
||||
r = "<<<<<<<<\n"
|
||||
for k in sorted(self.description.keys()):
|
||||
r += k + " : 0x{:x}".format(getattr(self, k)) + "\n"
|
||||
return r
|
||||
|
||||
|
||||
class FIS_REG_H2D(FIS):
|
||||
def __init__(self, packet=[0]*fis_reg_h2d_header.length):
|
||||
FIS.__init__(self, packet, fis_reg_h2d_header.fields)
|
||||
self.type = fis_types["REG_H2D"]
|
||||
self.direction = "H2D"
|
||||
|
||||
def __repr__(self):
|
||||
r = "FIS_REG_H2D\n"
|
||||
r += FIS.__repr__(self)
|
||||
return r
|
||||
|
||||
|
||||
class FIS_REG_D2H(FIS):
|
||||
def __init__(self, packet=[0]*fis_reg_d2h_header.length):
|
||||
FIS.__init__(self, packet, fis_reg_d2h_header.fields)
|
||||
self.type = fis_types["REG_D2H"]
|
||||
self.direction = "D2H"
|
||||
|
||||
def __repr__(self):
|
||||
r = "FIS_REG_D2H\n"
|
||||
r += FIS.__repr__(self)
|
||||
return r
|
||||
|
||||
|
||||
class FIS_DMA_ACTIVATE_D2H(FIS):
|
||||
def __init__(self, packet=[0]*fis_dma_activate_d2h_header.length):
|
||||
FIS.__init__(self, packet, fis_dma_activate_d2h_header.fields)
|
||||
self.type = fis_types["DMA_ACTIVATE_D2H"]
|
||||
self.direction = "D2H"
|
||||
|
||||
def __repr__(self):
|
||||
r = "FIS_DMA_ACTIVATE_D2H\n"
|
||||
r += FIS.__repr__(self)
|
||||
return r
|
||||
|
||||
|
||||
class FIS_DATA(FIS):
|
||||
def __init__(self, packet=[0], direction="H2D"):
|
||||
FIS.__init__(self, packet, fis_data_header.fields, direction)
|
||||
self.type = fis_types["DATA"]
|
||||
|
||||
def __repr__(self):
|
||||
r = "FIS_DATA\n"
|
||||
r += FIS.__repr__(self)
|
||||
for data in self.packet[1:]:
|
||||
r += "{:08x}\n".format(data)
|
||||
return r
|
||||
|
||||
|
||||
class FIS_UNKNOWN(FIS):
|
||||
def __init__(self, packet=[0], direction="H2D"):
|
||||
FIS.__init__(self, packet, {}, direction)
|
||||
|
||||
def __repr__(self):
|
||||
r = "UNKNOWN\n"
|
||||
if self.direction == "H2D":
|
||||
r += ">>>>>>>>\n"
|
||||
else:
|
||||
r += "<<<<<<<<\n"
|
||||
for dword in self.packet:
|
||||
r += "{:08x}\n".format(dword)
|
||||
return r
|
||||
|
||||
|
||||
class TransportLayer(Module):
|
||||
def __init__(self, link, debug=False, loopback=False):
|
||||
self.link = link
|
||||
self.debug = debug
|
||||
self.loopback = loopback
|
||||
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_transport(fis)
|
||||
|
||||
def callback(self, packet):
|
||||
fis_type = packet[0] & 0xff
|
||||
if fis_type == fis_types["REG_H2D"]:
|
||||
fis = FIS_REG_H2D(packet)
|
||||
elif fis_type == fis_types["REG_D2H"]:
|
||||
fis = FIS_REG_D2H(packet)
|
||||
elif fis_type == fis_types["DMA_ACTIVATE_D2H"]:
|
||||
fis = FIS_DMA_ACTIVATE_D2H(packet)
|
||||
elif fis_type == fis_types["DATA"]:
|
||||
fis = FIS_DATA(packet, direction="H2D")
|
||||
else:
|
||||
fis = FIS_UNKNOWN(packet, direction="H2D")
|
||||
if self.debug:
|
||||
print_transport(fis)
|
||||
if self.loopback:
|
||||
self.send(fis)
|
||||
else:
|
||||
self.command_callback(fis)
|
||||
|
||||
|
||||
# Command Layer model
|
||||
class CommandLayer(Module):
|
||||
def __init__(self, transport):
|
||||
self.transport = transport
|
||||
self.transport.set_command_callback(self.callback)
|
||||
|
||||
self.hdd = None
|
||||
|
||||
def set_hdd(self, hdd):
|
||||
self.hdd = hdd
|
||||
|
||||
def callback(self, fis):
|
||||
resp = None
|
||||
if isinstance(fis, FIS_REG_H2D):
|
||||
if fis.command == regs["WRITE_DMA_EXT"]:
|
||||
resp = self.hdd.write_dma_callback(fis)
|
||||
elif fis.command == regs["READ_DMA_EXT"]:
|
||||
resp = self.hdd.read_dma_callback(fis)
|
||||
elif isinstance(fis, FIS_DATA):
|
||||
resp = self.hdd.data_callback(fis)
|
||||
|
||||
if resp is not None:
|
||||
for packet in resp:
|
||||
self.transport.send(packet)
|
||||
|
||||
|
||||
# HDD model
|
||||
def print_hdd(s):
|
||||
print_with_prefix(s, "[HDD]: ")
|
||||
|
||||
|
||||
class HDDMemRegion:
|
||||
def __init__(self, base, count, sector_size):
|
||||
self.base = base
|
||||
self.count = count
|
||||
self.data = [0]*(count*sector_size//4)
|
||||
|
||||
|
||||
class HDD(Module):
|
||||
def __init__(self,
|
||||
link_debug=False, link_random_level=0,
|
||||
transport_debug=False, transport_loopback=False,
|
||||
hdd_debug=False,
|
||||
):
|
||||
self.submodules.phy = PHYLayer()
|
||||
self.submodules.link = LinkLayer(self.phy, link_debug, link_random_level)
|
||||
self.submodules.transport = TransportLayer(self.link, transport_debug, transport_loopback)
|
||||
self.submodules.command = CommandLayer(self.transport)
|
||||
|
||||
self.command.set_hdd(self)
|
||||
|
||||
self.debug = hdd_debug
|
||||
self.mem = None
|
||||
self.wr_sector = 0
|
||||
self.wr_end_sector = 0
|
||||
self.rd_sector = 0
|
||||
self.rx_end_sector = 0
|
||||
|
||||
def malloc(self, sector, count):
|
||||
if self.debug:
|
||||
s = "Allocating {n} sectors: {s} to {e}".format(n=count, s=sector, e=sector+count-1)
|
||||
s += " ({} KB)".format(count*logical_sector_size//1024)
|
||||
print_hdd(s)
|
||||
self.mem = HDDMemRegion(sector, count, logical_sector_size)
|
||||
|
||||
def write(self, sector, data):
|
||||
n = math.ceil(dwords2sectors(len(data)))
|
||||
if self.debug:
|
||||
if n == 1:
|
||||
s = "{}".format(sector)
|
||||
else:
|
||||
s = "{s} to {e}".format(s=sector, e=sector+n-1)
|
||||
print_hdd("Writing sector " + s)
|
||||
for i in range(len(data)):
|
||||
offset = sectors2dwords(sector)
|
||||
self.mem.data[offset+i] = data[i]
|
||||
|
||||
def read(self, sector, count):
|
||||
if self.debug:
|
||||
if count == 1:
|
||||
s = "{}".format(sector)
|
||||
else:
|
||||
s = "{s} to {e}".format(s=sector, e=sector+count-1)
|
||||
print_hdd("Reading sector " + s)
|
||||
data = []
|
||||
for i in range(sectors2dwords(count)):
|
||||
data.append(self.mem.data[sectors2dwords(sector)+i])
|
||||
return data
|
||||
|
||||
def write_dma_callback(self, fis):
|
||||
self.wr_sector = fis.lba_lsb + (fis.lba_msb << 32)
|
||||
self.wr_end_sector = self.wr_sector + fis.count
|
||||
return [FIS_DMA_ACTIVATE_D2H()]
|
||||
|
||||
def read_dma_callback(self, fis):
|
||||
self.rd_sector = fis.lba_lsb + (fis.lba_msb << 32)
|
||||
self.rd_end_sector = self.rd_sector + fis.count
|
||||
packets = []
|
||||
while self.rd_sector != self.rd_end_sector:
|
||||
count = min(self.rd_end_sector-self.rd_sector, (fis_max_dwords*4)//logical_sector_size)
|
||||
packet = self.read(self.rd_sector, count)
|
||||
packet.insert(0, 0)
|
||||
packets.append(FIS_DATA(packet, direction="D2H"))
|
||||
self.rd_sector += count
|
||||
packets.append(FIS_REG_D2H())
|
||||
return packets
|
||||
|
||||
def data_callback(self, fis):
|
||||
self.write(self.wr_sector, fis.packet[1:])
|
||||
self.wr_sector += dwords2sectors(len(fis.packet[1:]))
|
||||
if self.wr_sector == self.wr_end_sector:
|
||||
return [FIS_REG_D2H()]
|
||||
else:
|
||||
return [FIS_DMA_ACTIVATE_D2H()]
|
||||
|
|
Loading…
Reference in New Issue