mac/sram: Cleanup/Simplify LiteEthMACSRAMWriter.

- Improve signal names.
- Avoid IDLE State.
- Also check for error when length > eth_mtu.
- Use int(math.log2()) instead of log2_int.
This commit is contained in:
Florent Kermarrec 2021-10-01 19:56:10 +02:00
parent 1685c56100
commit 89dbf17cb6
1 changed files with 74 additions and 85 deletions

View File

@ -7,7 +7,7 @@
# Copyright (c) 2017 whitequark <whitequark@whitequark.org> # Copyright (c) 2017 whitequark <whitequark@whitequark.org>
# SPDX-License-Identifier: BSD-2-Clause # SPDX-License-Identifier: BSD-2-Clause
from math import log2, ceil import math
from liteeth.common import * from liteeth.common import *
@ -18,122 +18,111 @@ from litex.soc.interconnect.csr_eventmanager import *
class LiteEthMACSRAMWriter(Module, AutoCSR): class LiteEthMACSRAMWriter(Module, AutoCSR):
def __init__(self, dw, depth, nslots=2, endianness="big", timestamp=None): def __init__(self, dw, depth, nslots=2, endianness="big", timestamp=None):
assert dw in [32, 64] # Endpoint / Signals.
self.sink = sink = stream.Endpoint(eth_phy_description(dw)) self.sink = sink = stream.Endpoint(eth_phy_description(dw))
self.crc_error = Signal() self.crc_error = Signal()
slotbits = max(log2_int(nslots), 1) # Parameters Check / Compute.
lengthbits = 32 assert dw in [32, 64]
slotbits = max(int(math.log2(nslots)), 1)
lengthbits = bits_for(depth * dw//8)
# CSRs.
self._slot = CSRStatus(slotbits) self._slot = CSRStatus(slotbits)
self._length = CSRStatus(lengthbits) self._length = CSRStatus(lengthbits)
self._errors = CSRStatus(32) self._errors = CSRStatus(32)
# Optional Timestamp of the incoming packets and expose value to software.
if timestamp is not None: if timestamp is not None:
# Timestamp the incoming packets when a Timestamp source is provided
# and expose value to a software.
timestampbits = len(timestamp) timestampbits = len(timestamp)
self._timestamp = CSRStatus(timestampbits) self._timestamp = CSRStatus(timestampbits)
# Event Manager.
self.submodules.ev = EventManager() self.submodules.ev = EventManager()
self.ev.available = EventSourceLevel() self.ev.available = EventSourceLevel()
self.ev.finalize() self.ev.finalize()
# # # # # #
# Packet dropped if no slot available write = Signal()
errors = self._errors.status
slot = Signal(slotbits)
length = Signal(lengthbits)
length_inc = Signal(4)
# Sink is already ready: packets are dropped when no slot is available.
sink.ready.reset = 1 sink.ready.reset = 1
# Decode Length increment from from last_be. # Decode Length increment from from last_be.
inc = Signal(4)
if dw == 32: if dw == 32:
self.comb += Case(sink.last_be, { self.comb += Case(sink.last_be, {
0b0001 : inc.eq(1), 0b0001 : length_inc.eq(1),
0b0010 : inc.eq(2), 0b0010 : length_inc.eq(2),
0b0100 : inc.eq(3), 0b0100 : length_inc.eq(3),
"default" : inc.eq(4) "default" : length_inc.eq(4)
}) })
else: else:
self.comb += Case(sink.last_be, { self.comb += Case(sink.last_be, {
0b00000001 : inc.eq(1), 0b00000001 : length_inc.eq(1),
0b00000010 : inc.eq(2), 0b00000010 : length_inc.eq(2),
0b00000100 : inc.eq(3), 0b00000100 : length_inc.eq(3),
0b00001000 : inc.eq(4), 0b00001000 : length_inc.eq(4),
0b00010000 : inc.eq(5), 0b00010000 : length_inc.eq(5),
0b00100000 : inc.eq(6), 0b00100000 : length_inc.eq(6),
0b01000000 : inc.eq(7), 0b01000000 : length_inc.eq(7),
"default" : inc.eq(8) "default" : length_inc.eq(8)
}) })
counter = Signal(lengthbits) # Status FIFO.
# Slot computation
slot = Signal(slotbits)
slot_ce = Signal()
self.sync += If(slot_ce, slot.eq(slot + 1))
start = Signal()
ongoing = Signal()
# Status FIFO
stat_fifo_layout = [("slot", slotbits), ("length", lengthbits)] stat_fifo_layout = [("slot", slotbits), ("length", lengthbits)]
if timestamp is not None: if timestamp is not None:
stat_fifo_layout += [("timestamp", timestampbits)] stat_fifo_layout += [("timestamp", timestampbits)]
self.submodules.stat_fifo = stat_fifo = stream.SyncFIFO(stat_fifo_layout, nslots)
stat_fifo = stream.SyncFIFO(stat_fifo_layout, nslots) # FSM.
self.submodules += stat_fifo self.submodules.fsm = fsm = FSM(reset_state="WRITE")
fsm.act("WRITE",
# FSM
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
If(sink.valid, If(sink.valid,
If(stat_fifo.sink.ready, If(stat_fifo.sink.ready,
start.eq(1), write.eq(1),
ongoing.eq(1), NextValue(length, length + length_inc),
NextValue(counter, counter + inc), If(length >= eth_mtu,
NextState("WRITE") NextState("DISCARD-REMAINING")
),
If(sink.last,
If((sink.error & sink.last_be) != 0,
NextState("DISCARD")
).Else(
NextState("TERMINATE")
)
)
).Else( ).Else(
NextValue(self._errors.status, self._errors.status + 1), NextValue(errors, errors + 1),
NextState("DISCARD_REMAINING") NextState("DISCARD-REMAINING")
) )
) )
) )
fsm.act("WRITE", fsm.act("DISCARD-REMAINING",
If(sink.valid, If(sink.valid & sink.last,
If(counter == eth_mtu, If((sink.error & sink.last_be) != 0,
NextState("DISCARD_REMAINING") NextState("DISCARD")
).Else( ).Else(
NextValue(counter, counter + inc), NextState("TERMINATE")
ongoing.eq(1)
),
If(sink.last,
If((sink.error & sink.last_be) != 0,
NextState("DISCARD")
).Else(
NextState("TERMINATE")
)
) )
) )
) )
fsm.act("DISCARD", fsm.act("DISCARD",
NextValue(counter, 0), NextValue(length, 0),
NextState("IDLE") NextState("WRITE")
) )
fsm.act("DISCARD_REMAINING",
If(sink.valid & sink.last,
NextState("TERMINATE")
)
)
self.comb += [
stat_fifo.sink.slot.eq(slot),
stat_fifo.sink.length.eq(counter)
]
fsm.act("TERMINATE", fsm.act("TERMINATE",
NextValue(counter, 0),
slot_ce.eq(1),
stat_fifo.sink.valid.eq(1), stat_fifo.sink.valid.eq(1),
NextState("IDLE") stat_fifo.sink.slot.eq(slot),
stat_fifo.sink.length.eq(length),
NextValue(length, 0),
NextValue(slot, slot + 1),
NextState("WRITE")
) )
self.comb += [ self.comb += [
@ -143,11 +132,11 @@ class LiteEthMACSRAMWriter(Module, AutoCSR):
self._length.status.eq(stat_fifo.source.length), self._length.status.eq(stat_fifo.source.length),
] ]
if timestamp is not None: if timestamp is not None:
# Latch Timestamp on start of incoming packet. # Latch Timestamp on start of packet.
self.sync += If(start, stat_fifo.sink.timestamp.eq(timestamp)) self.sync += If(sink.length == 0, stat_fifo.sink.timestamp.eq(timestamp))
self.comb += self._timestamp.status.eq(stat_fifo.source.timestamp) self.comb += self._timestamp.status.eq(stat_fifo.source.timestamp)
# Memory # Memory.
mems = [None] * nslots mems = [None] * nslots
ports = [None] * nslots ports = [None] * nslots
for n in range(nslots): for n in range(nslots):
@ -160,9 +149,9 @@ class LiteEthMACSRAMWriter(Module, AutoCSR):
cases = {} cases = {}
for n, port in enumerate(ports): for n, port in enumerate(ports):
cases[n] = [ cases[n] = [
ports[n].adr.eq(counter[log2_int(dw // 8):]), ports[n].adr.eq(length[int(math.log2(dw//8)):]),
ports[n].dat_w.eq(data), ports[n].dat_w.eq(data),
If(sink.valid & ongoing, If(sink.valid & write,
ports[n].we.eq(0xf) ports[n].we.eq(0xf)
) )
] ]
@ -175,13 +164,13 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
assert dw in [32, 64] assert dw in [32, 64]
self.source = source = stream.Endpoint(eth_phy_description(dw)) self.source = source = stream.Endpoint(eth_phy_description(dw))
slotbits = max(log2_int(nslots), 1) slotbits = max(int(math.log2(nslots)), 1)
lengthbits = bits_for(depth * (dw // 8)) # length in bytes lengthbits = bits_for(depth * dw//8)
self.lengthbits = lengthbits self.lengthbits = lengthbits
self._start = CSR() self._start = CSR()
self._ready = CSRStatus() self._ready = CSRStatus()
self._level = CSRStatus(log2_int(nslots) + 1) self._level = CSRStatus(int(math.log2(nslots)) + 1)
self._slot = CSRStorage(slotbits, reset_less=True) self._slot = CSRStorage(slotbits, reset_less=True)
self._length = CSRStorage(lengthbits, reset_less=True) self._length = CSRStorage(lengthbits, reset_less=True)
@ -235,7 +224,7 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
) )
# Encode Length to last_be. # Encode Length to last_be.
length_lsb = cmd_fifo.source.length[0:log2_int(dw // 8)] length_lsb = cmd_fifo.source.length[0:int(math.log2(dw//8))]
if dw == 32: if dw == 32:
self.comb += If(source.last, self.comb += If(source.last,
Case(length_lsb, { Case(length_lsb, {
@ -261,11 +250,11 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
fsm.act("SEND", fsm.act("SEND",
source.valid.eq(1), source.valid.eq(1),
source.last.eq(counter >= (cmd_fifo.source.length - (dw // 8))), source.last.eq(counter >= (cmd_fifo.source.length - dw//8)),
read_address.eq(counter), read_address.eq(counter),
If(source.ready, If(source.ready,
read_address.eq(counter + (dw // 8)), read_address.eq(counter + dw//8),
NextValue(counter, counter + (dw // 8)), NextValue(counter, counter + dw//8),
If(source.last, If(source.last,
NextState("END") NextState("END")
) )
@ -298,7 +287,7 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
cases = {} cases = {}
for n, port in enumerate(ports): for n, port in enumerate(ports):
self.comb += ports[n].adr.eq(read_address[log2_int(dw // 8):]) self.comb += ports[n].adr.eq(read_address[int(math.log2(dw//8)):])
cases[n] = [data.eq(port.dat_r)] cases[n] = [data.eq(port.dat_r)]
self.comb += [ self.comb += [