From c28067d67213937edbfb1b6efb2ce8f7a5a7263d Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 5 Dec 2014 20:26:09 +0100 Subject: [PATCH] link: test RX path --- lib/sata/link/__init__.py | 36 ++++++++++---- lib/sata/link/cont.py | 2 +- lib/sata/link/scrambler.py | 14 +----- lib/sata/test/bfm.py | 96 +++++++++++++++++++++++++++----------- lib/sata/test/link_tb.py | 24 ++++++---- 5 files changed, 114 insertions(+), 58 deletions(-) diff --git a/lib/sata/link/__init__.py b/lib/sata/link/__init__.py index dff597257..ebbc76b4b 100644 --- a/lib/sata/link/__init__.py +++ b/lib/sata/link/__init__.py @@ -6,8 +6,8 @@ from lib.sata.link.crc import SATACRCInserter, SATACRCChecker from lib.sata.link.scrambler import SATAScrambler from lib.sata.link.cont import SATACONTInserter, SATACONTRemover -# TODO: -# - Do more tests +#TODO: +# -Test HOLD on RX path from_rx = [ ("idle", 1), @@ -67,16 +67,19 @@ class SATALinkLayerTX(Module): # FSM fsm.act("IDLE", - insert.eq(primitives["SYNC"]), - If(scrambler.source.stb & scrambler.source.sop, - If(self.from_rx.idle, - NextState("RDY") + scrambler.reset.eq(1), + If(self.from_rx.idle, + insert.eq(primitives["SYNC"]), + If(scrambler.source.stb & scrambler.source.sop, + NextState("RDY"), ) ) ) fsm.act("RDY", insert.eq(primitives["X_RDY"]), - If(self.from_rx.det == primitives["R_RDY"], + If(~self.from_rx.idle, + NextState("IDLE") + ).Elif(self.from_rx.det == primitives["R_RDY"], NextState("SOF") ) ) @@ -141,12 +144,25 @@ class SATALinkLayerRX(Module): crc = SATACRCChecker(link_layout(32)) self.submodules += crc + sop = Signal() + self.sync += \ + If(fsm.ongoing("RDY"), + sop.eq(1) + ).Elif(scrambler.sink.stb & scrambler.sink.ack, + sop.eq(0) + ) + # graph - self.comb += [ + self.sync += \ If(fsm.ongoing("COPY") & (det == 0), scrambler.sink.stb.eq(cont.source.stb & (cont.source.charisk == 0)), scrambler.sink.d.eq(cont.source.data), - ), + ).Else( + scrambler.sink.stb.eq(0) + ) + self.comb += [ + scrambler.sink.sop.eq(sop), + scrambler.sink.eop.eq(det == primitives["EOF"]), cont.source.ack.eq(1), Record.connect(scrambler.source, crc.sink), Record.connect(crc.source, self.source) @@ -154,6 +170,7 @@ class SATALinkLayerRX(Module): # FSM fsm.act("IDLE", + scrambler.reset.eq(1), If(det == primitives["X_RDY"], NextState("RDY") ) @@ -165,6 +182,7 @@ class SATALinkLayerRX(Module): ) ) fsm.act("COPY", + insert.eq(primitives["R_IP"]), If(det == primitives["HOLD"], insert.eq(primitives["HOLDA"]) ).Elif(det == primitives["EOF"], diff --git a/lib/sata/link/cont.py b/lib/sata/link/cont.py index 447e9179d..63f5f7335 100644 --- a/lib/sata/link/cont.py +++ b/lib/sata/link/cont.py @@ -48,7 +48,7 @@ class SATACONTInserter(Module): ) # scrambler (between CONT and next primitive) - scrambler = Scrambler() + scrambler = InsertReset(Scrambler()) self.submodules += scrambler self.comb += [ scrambler.reset.eq(ResetSignal()), #XXX: should be reseted on COMINIT / COMRESET diff --git a/lib/sata/link/scrambler.py b/lib/sata/link/scrambler.py index 5f4a0faa9..9d8783db6 100644 --- a/lib/sata/link/scrambler.py +++ b/lib/sata/link/scrambler.py @@ -3,7 +3,6 @@ from migen.genlib.misc import optree from lib.sata.std import * -@DecorateModule(InsertReset) @DecorateModule(InsertCE) class Scrambler(Module): """SATA Scrambler @@ -68,6 +67,7 @@ class Scrambler(Module): self.comb += self.value.eq(next_value) +@DecorateModule(InsertReset) class SATAScrambler(Module): def __init__(self, layout): self.sink = sink = Sink(layout) @@ -76,18 +76,8 @@ class SATAScrambler(Module): ### self.submodules.scrambler = Scrambler() - ongoing = Signal() - self.sync += \ - If(sink.stb & sink.ack, - If(sink.eop, - ongoing.eq(0) - ).Elif(sink.sop, - ongoing.eq(1) - ) - ) self.comb += [ - self.scrambler.ce.eq(sink.stb & sink.ack & (sink.sop | ongoing)), - self.scrambler.reset.eq(~(sink.sop | ongoing)), + self.scrambler.ce.eq(sink.stb & sink.ack), Record.connect(sink, source), source.d.eq(sink.d ^ self.scrambler.value) ] diff --git a/lib/sata/test/bfm.py b/lib/sata/test/bfm.py index 5f0902882..6272dd94e 100644 --- a/lib/sata/test/bfm.py +++ b/lib/sata/test/bfm.py @@ -49,7 +49,7 @@ class PHYSink(Module): self.dword.dat = selfp.sink.data class PHYLayer(Module): - def __init__(self, debug): + def __init__(self, debug=False): self.debug = debug self.submodules.rx = PHYSink() @@ -116,8 +116,8 @@ class LinkRXPacket(LinkPacket): class LinkTXPacket(LinkPacket): def encode(self): - self.scramble() self.insert_crc() + self.scramble() def scramble(self): for i in range(len(self)): @@ -125,7 +125,7 @@ class LinkTXPacket(LinkPacket): def insert_crc(self): stdin = "" - for v in self[:-1]: + for v in self: stdin += "0x%08x " %v stdin += "exit" with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process: @@ -135,16 +135,20 @@ class LinkTXPacket(LinkPacket): self.append(crc) class LinkLayer(Module): - def __init__(self, phy, debug, hold_random_level=0): + def __init__(self, phy, debug=False, random_level=0): self.phy = phy self.debug = debug - self.hold_random_level = hold_random_level + self.random_level = random_level + self.tx_packets = [] self.tx_packet = LinkTXPacket() self.rx_packet = LinkRXPacket() self.rx_cont = False self.transport_callback = None + self.send_state = "" + self.send_states = ["RDY", "SOF", "DATA", "EOF", "WTRM"] + def set_transport_callback(self, callback): self.transport_callback = callback @@ -156,42 +160,68 @@ class LinkLayer(Module): if dword == primitives["X_RDY"]: self.phy.send(primitives["R_RDY"]) - elif dword == primitives["WTRM"]: self.phy.send(primitives["R_OK"]) - + if self.rx_packet.ongoing: + self.rx_packet.decode() + if self.transport_callback is not None: + self.transport_callback(self.rx_packet) + self.rx_packet.ongoing = False elif dword == primitives["HOLD"]: self.phy.send(primitives["HOLDA"]) - elif dword == primitives["EOF"]: - self.rx_packet.decode() - if self.transport_callback is not None: - self.transport_callback(self.rx_packet) - self.rx_packet.ongoing = False - + pass elif self.rx_packet.ongoing: if dword != primitives["HOLD"]: n = randn(100) - if n < self.hold_random_level: + if n < self.random_level: self.phy.send(primitives["HOLD"]) else: - self.phy.send(primitives["R_RDY"]) + self.phy.send(primitives["R_IP"]) if not is_primitive(dword): if not self.rx_cont: self.rx_packet.append(dword) - elif dword == primitives["SOF"]: self.rx_packet = LinkRXPacket() self.rx_packet.ongoing = True - def send(self, packet): - pass + def send(self, dword): + if self.send_state == "RDY": + self.phy.send(primitives["X_RDY"]) + if dword == primitives["R_RDY"]: + self.send_state = "SOF" + elif self.send_state == "SOF": + self.phy.send(primitives["SOF"]) + self.send_state = "DATA" + elif self.send_state == "DATA": + self.phy.send(self.tx_packet.pop(0)) + if len(self.tx_packet) == 0: + self.send_state = "EOF" + elif self.send_state == "EOF": + self.phy.send(primitives["EOF"]) + self.send_state = "WTRM" + elif self.send_state == "WTRM": + self.phy.send(primitives["WTRM"]) + if dword == primitives["R_OK"]: + self.tx_packet.done = True + elif dword == primitives["R_ERR"]: + self.tx_packet.done = True def gen_simulation(self, selfp): - self.phy.send(primitives["SYNC"]) + self.tx_packet.done = True while True: yield from self.phy.receive() - self.callback(self.phy.rx.dword.dat) + self.phy.send(primitives["SYNC"]) + rx_dword = self.phy.rx.dword.dat + if len(self.tx_packets) != 0: + if self.tx_packet.done: + self.tx_packet = self.tx_packets.pop(0) + self.tx_packet.encode() + self.send_state = "RDY" + if not self.tx_packet.done: + self.send(rx_dword) + else: + self.callback(self.phy.rx.dword.dat) def get_field_data(field, packet): return (packet[field.dword] >> field.offset) & (2**field.width-1) @@ -282,8 +312,11 @@ class FIS_UNKNOWN(FIS): return r class TransportLayer(Module): - def __init__(self, link): - pass + 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 callback(self, packet): fis_type = packet[0] @@ -301,12 +334,19 @@ class TransportLayer(Module): fis = FIS_PIO_SETUP_D2H(packet) else: fis = FIS_UNKNOWN(packet) - print(fis) + if self.debug: + print(fis) + if self.loopback: + packet = LinkTXPacket(fis.packet) + self.link.tx_packets.append(packet) class BFM(Module): - def __init__(self, dw, debug=False, hold_random_level=0): + def __init__(self, + phy_debug=False, + link_debug=False, link_random_level=0, + transport_debug=False, transport_loopback=False + ): ### - self.submodules.phy = PHYLayer(debug) - self.submodules.link = LinkLayer(self.phy, debug, hold_random_level) - self.submodules.transport = TransportLayer(self.link) - self.link.set_transport_callback(self.transport.callback) + 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) diff --git a/lib/sata/test/link_tb.py b/lib/sata/test/link_tb.py index f2d63ce68..a8ea97b2f 100644 --- a/lib/sata/test/link_tb.py +++ b/lib/sata/test/link_tb.py @@ -11,8 +11,8 @@ from lib.sata.test.bfm import * from lib.sata.test.common import * class LinkStreamer(Module): - def __init__(self, dw): - self.source = Source(link_layout(dw)) + def __init__(self): + self.source = Source(link_layout(32)) ### self.packets = [] self.packet = LinkTXPacket() @@ -43,8 +43,8 @@ class LinkStreamer(Module): selfp.source.stb = 0 class LinkLogger(Module): - def __init__(self, dw): - self.sink = Sink(link_layout(dw)) + def __init__(self): + self.sink = Sink(link_layout(32)) ### self.packet = LinkRXPacket() @@ -57,6 +57,7 @@ class LinkLogger(Module): selfp.sink.ack = 1 if selfp.sink.stb == 1 and selfp.sink.sop == 1: self.packet = LinkRXPacket() + print("rx : %08x" %selfp.sink.d) self.packet.append(selfp.sink.d) elif selfp.sink.stb: self.packet.append(selfp.sink.d) @@ -65,13 +66,14 @@ class LinkLogger(Module): class TB(Module): def __init__(self): - self.submodules.bfm = BFM(32, debug=True, hold_random_level=50) + self.submodules.bfm = BFM(phy_debug=False, + link_random_level=50, transport_debug=False, transport_loopback=True) self.submodules.link_layer = SATALinkLayer(self.bfm.phy) - self.submodules.streamer = LinkStreamer(32) + self.submodules.streamer = LinkStreamer() streamer_ack_randomizer = AckRandomizer(link_layout(32), level=50) self.submodules += streamer_ack_randomizer - self.submodules.logger = LinkLogger(32) + self.submodules.logger = LinkLogger() self.comb += [ Record.connect(self.streamer.source, streamer_ack_randomizer.sink), Record.connect(streamer_ack_randomizer.source, self.link_layer.sink), @@ -79,10 +81,16 @@ class TB(Module): ] def gen_simulation(self, selfp): - for i in range(200): + for i in range(24): yield for i in range(8): yield from self.streamer.send(LinkTXPacket([i for i in range(16)])) + yield from self.logger.receive() + print("Logger:") + print("-------") + for v in self.logger.packet: + print("%08x" %v) + if __name__ == "__main__": run_simulation(TB(), ncycles=512, vcd_name="my.vcd", keep_files=True)