link: fix CONT on RX path

This commit is contained in:
Florent Kermarrec 2014-12-06 01:23:03 +01:00
parent 21a279af72
commit 0f50eab880
4 changed files with 54 additions and 25 deletions

View File

@ -22,23 +22,28 @@ class SATACONTInserter(Module):
cont_insert = Signal()
scrambler_insert = Signal()
last_primitive_insert = Signal()
last_primitive_insert_d = Signal()
self.comb += [
is_primitive.eq(sink.charisk != 0),
change.eq((sink.data != last_primitive) | ~is_primitive),
cont_insert.eq(~change & (cnt==1)),
scrambler_insert.eq(~change & (cnt==2)),
last_primitive_insert.eq(~is_primitive & last_was_primitive & (cnt==2))
last_primitive_insert.eq((cnt==2) & (
(~is_primitive & last_was_primitive) |
(is_primitive & (last_primitive == primitives["HOLD"]) & (last_primitive != sink.data))))
]
self.sync += \
If(sink.stb & source.ack,
last_primitive_insert_d.eq(last_primitive_insert),
If(is_primitive,
last_primitive.eq(sink.data),
last_was_primitive.eq(1)
).Else(
last_was_primitive.eq(0)
),
If(change,
If(change | last_primitive_insert_d,
cnt.eq(0)
).Else(
If(~scrambler_insert,
@ -89,7 +94,7 @@ class SATACONTRemover(Module):
self.comb += [
is_primitive.eq(sink.charisk != 0),
is_cont.eq(is_primitive & sink.data == primitives["CONT"])
is_cont.eq(is_primitive & (sink.data == primitives["CONT"]))
]
self.sync += \
If(is_cont,

View File

@ -63,9 +63,9 @@ class PHYLayer(Module):
self.tx.send(packet)
def receive(self):
yield from self.rx.receive()
if self.debug:
print(self)
yield from self.rx.receive()
def __repr__(self):
receiving = "%08x " %self.rx.dword.dat
@ -78,20 +78,20 @@ class PHYLayer(Module):
return receiving + sending
def import_scrambler_datas():
with subprocess.Popen(["./scrambler"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
process.stdin.write("0x10000".encode("ASCII"))
out, err = process.communicate()
return [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
class LinkPacket(list):
def __init__(self, init=[]):
self.ongoing = False
self.done = False
self.scrambled_datas = self.import_scrambler_datas()
self.scrambled_datas = import_scrambler_datas()
for dword in init:
self.append(dword)
def import_scrambler_datas(self):
with subprocess.Popen(["./scrambler"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
process.stdin.write("0x10000".encode("ASCII"))
out, err = process.communicate()
return [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
class LinkRXPacket(LinkPacket):
def decode(self):
self.descramble()
@ -142,9 +142,14 @@ class LinkLayer(Module):
self.tx_packets = []
self.tx_packet = LinkTXPacket()
self.rx_packet = LinkRXPacket()
self.rx_cont = False
self.rx_last = 0
self.tx_cont = False
self.tx_cont_primitive = 0
self.tx_cont_nb = -1
self.tx_lasts = [0, 0, 0]
self.scrambled_datas = import_scrambler_datas()
self.transport_callback = None
@ -154,12 +159,20 @@ class LinkLayer(Module):
def set_transport_callback(self, callback):
self.transport_callback = callback
def callback(self, dword):
def remove_cont(self, dword):
if dword == primitives["HOLD"]:
if self.rx_cont:
self.tx_lasts = [0, 0, 0]
if dword == primitives["CONT"]:
self.rx_cont = True
elif is_primitive(dword):
self.rx_last = dword
self.rx_cont = False
if self.rx_cont:
dword = self.rx_last
return dword
def callback(self, dword):
if dword == primitives["X_RDY"]:
self.phy.send(primitives["R_RDY"])
elif dword == primitives["WTRM"]:
@ -181,21 +194,12 @@ class LinkLayer(Module):
else:
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, dword):
if dword == primitives["CONT"]:
self.tx_cont = True
elif is_primitive(dword):
self.tx_cont = False
self.tx_cont_primitive = dword
if self.tx_cont:
dword = self.tx_cont_primitive
if self.send_state == "RDY":
self.phy.send(primitives["X_RDY"])
if dword == primitives["R_RDY"]:
@ -220,6 +224,24 @@ class LinkLayer(Module):
elif dword == primitives["R_ERR"]:
self.tx_packet.done = True
def insert_cont(self):
self.tx_lasts.pop(0)
self.tx_lasts.append(self.phy.tx.dword.dat)
self.tx_cont = True
for i in range(3):
if not is_primitive(self.tx_lasts[i]):
self.tx_cont = False
if self.tx_lasts[i] != self.tx_lasts[0]:
self.tx_cont = False
if self.tx_cont:
if self.tx_cont_nb == 0:
self.phy.send(primitives["CONT"])
else:
self.phy.send(self.scrambled_datas[self.tx_cont_nb])
self.tx_cont_nb += 1
else:
self.tx_cont_nb = 0
def gen_simulation(self, selfp):
self.tx_packet.done = True
self.phy.send(primitives["SYNC"])
@ -227,6 +249,7 @@ class LinkLayer(Module):
yield from self.phy.receive()
self.phy.send(primitives["SYNC"])
rx_dword = self.phy.rx.dword.dat
rx_dword = self.remove_cont(rx_dword)
if len(self.tx_packets) != 0:
if self.tx_packet.done:
self.tx_packet = self.tx_packets.pop(0)
@ -235,7 +258,8 @@ class LinkLayer(Module):
if not self.tx_packet.done:
self.send(rx_dword)
else:
self.callback(self.phy.rx.dword.dat)
self.callback(rx_dword)
self.insert_cont()
def get_field_data(field, packet):
return (packet[field.dword] >> field.offset) & (2**field.width-1)

View File

@ -65,7 +65,7 @@ class LinkLogger(Module):
class TB(Module):
def __init__(self):
self.submodules.bfm = BFM(phy_debug=True,
self.submodules.bfm = BFM(phy_debug=False,
link_random_level=50, transport_debug=True, transport_loopback=True)
self.submodules.link_layer = SATALinkLayer(self.bfm.phy)

View File

@ -9,7 +9,7 @@ from lib.sata.test.common import *
class TB(Module):
def __init__(self, length):
self.submodules.scrambler = Scrambler()
self.submodules.scrambler = InsertReset(Scrambler())
self.length = length
def get_c_values(self, length):