From: Florent Kermarrec Date: Sun, 14 Dec 2014 10:44:12 +0000 (+0100) Subject: bfm: create basic HDD model X-Git-Tag: 24jan2021_ls180~2572^2~130 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b6d5e23264a72375f3218e4823391d0b7434a409;p=litex.git bfm: create basic HDD model --- diff --git a/lib/sata/test/bfm.py b/lib/sata/test/bfm.py index 4fe0a5f8..6b94b901 100644 --- a/lib/sata/test/bfm.py +++ b/lib/sata/test/bfm.py @@ -5,6 +5,7 @@ from migen.fhdl.std import * from lib.sata.common import * from lib.sata.test.common import * +# PHY Layer model class PHYDword: def __init__(self, dat=0): self.dat = dat @@ -76,6 +77,7 @@ class PHYLayer(Module): return receiving + sending +# Link Layer model def import_scrambler_datas(): with subprocess.Popen(["./scrambler"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process: process.stdin.write("0x10000".encode("ASCII")) @@ -259,6 +261,7 @@ class LinkLayer(Module): self.callback(rx_dword) self.insert_cont() +# Transport Layer model def get_field_data(field, packet): return (packet[field.dword] >> field.offset) & (2**field.width-1) @@ -371,66 +374,87 @@ class TransportLayer(Module): else: self.command_callback(fis) +# Command Layer model class CommandLayer(Module): def __init__(self, transport, debug=False): self.transport = transport self.debug = debug self.transport.set_command_callback(self.callback) - self.dma_enable = 0 - self.dma_address = 0 + self.hdd = None - def allocate_dma(self, base, length): - self.dma_base = base - self.dma_buffer = [0]*(length//4) + def set_hdd(self, hdd): + self.hdd = hdd - def enable_dma(self): - self.dma_enable = 1 + def callback(self, fis): + # XXX manage maximum of 2048 DWORDS per DMA + if isinstance(fis, FIS_REG_H2D): + if fis.command == regs["WRITE_DMA_EXT"]: + self.transport.send(self.hdd.write_dma_cmd(fis)) + elif fis.command == regs["READ_DMA_EXT"]: + self.transport.send(self.hdd.read_dma_cmd(fis)) + elif fis.command == regs["IDENTIFY_DEVICE_DMA"]: + self.transport.send(self.hdd.identify_device_dma_cmd(fis)) + elif isinstance(fis, FIS_DATA): + self.hdd.data_cmd(fis) + +# HDD model +class HDDMemRegion: + def __init__(self, base, length): + self.base = base + self.length = length + self.data = [0]*(length//4) + +class HDD(Module): + def __init__(self, command, debug=False): + self.command = command + command.set_hdd(self) + + self.mem = None + self.wr_address = 0 + + def write_dma_cmd(self, fis): + self.wr_address = fis.lba_lsb + return FIS_DMA_ACTIVATE_D2H() - def disable_dma(self): - self.dma_enable = 0 + def read_dma_cmd(self, fis): + return FIS_DATA(self.read_mem(fis.lba_lsb, fis.count*4)) - def dma_write(self, adr, data): - current_adr = (adr-self.dma_base)//4 + def identify_dma_cmd(self, fis): + return FIS_DATA([i for i in range(256)]) + + def data_cmd(self, fis): + self.write_mem(self.wr_address, fis.packet[1:]) + + def allocate_mem(self, base, length): + # XXX add support for multiple memory regions + self.mem = HDDMemRegion(base, length) + + def write_mem(self, adr, data): + # XXX test if adr allocate in one memory region + current_adr = (adr-self.mem.base)//4 for i in range(len(data)): - self.dma_buffer[current_adr+i] = data[i] + self.mem.data[current_adr+i] = data[i] - def dma_read(self, adr, length=1): - current_adr = (adr-self.dma_base)//4 + def read_mem(self, adr, length=1): + # XXX test if adr allocate in one memory region + current_adr = (adr-self.mem.base)//4 data = [] for i in range(length//4): - data.append(self.dma_buffer[current_adr+i]) + data.append(self.mem.data[current_adr+i]) return data - def callback(self, fis): - # XXX maximum of 2048 DWORDS per DMA - if isinstance(fis, FIS_REG_H2D): - if fis.command == regs["WRITE_DMA_EXT"]: - self.dma_address = fis.lba_lsb - dma_activate = FIS_DMA_ACTIVATE_D2H() - self.transport.send(dma_activate) - elif fis.command == regs["READ_DMA_EXT"]: - self.dma_address = fis.lba_lsb - data = FIS_DATA(self.dma_read(fis.lba_lsb, fis.count*4)) - self.transport.send(data) - elif fis.command == regs["IDENTIFY_DEVICE_DMA"]: - self.dma_address = fis.lba_lsb - data = FIS_DATA(self.dma_read(fis.lba_lsb, fis.count*4)) - self.transport.send(data) - elif isinstance(fis, FIS_DATA): - if self.dma_enable: - self.dma_write(self.dma_address, fis.packet[1:]) - self.dma_address += len(fis.packet[1:]) - class BFM(Module): def __init__(self, phy_debug=False, link_debug=False, link_random_level=0, transport_debug=False, transport_loopback=False, - command_debug=False + command_debug=False, + hdd_debug=False ): ### self.submodules.phy = PHYLayer(phy_debug) 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, command_debug) + self.submodules.hdd = HDD(self.command, hdd_debug) diff --git a/lib/sata/test/command_tb.py b/lib/sata/test/command_tb.py index 302ab0d6..b10ae067 100644 --- a/lib/sata/test/command_tb.py +++ b/lib/sata/test/command_tb.py @@ -21,8 +21,7 @@ class TB(Module): self.submodules.command = SATACommand(self.transport) def gen_simulation(self, selfp): - self.bfm.command.allocate_dma(0x00000000, 64*1024*1024) - self.bfm.command.enable_dma() + self.bfm.hdd.allocate_mem(0x00000000, 64*1024*1024) selfp.command.source.ack = 1 for i in range(100): yield