continue code refactoring
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 28 Jan 2015 08:14:01 +0000 (09:14 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 28 Jan 2015 08:28:33 +0000 (09:28 +0100)
24 files changed:
liteeth/common.py
liteeth/mac/__init__.py
liteeth/mac/common.py
liteeth/mac/core/__init__.py
liteeth/mac/core/crc.py
liteeth/mac/core/last_be.py
liteeth/mac/core/preamble.py
liteeth/mac/frontend/sram.py
liteeth/mac/frontend/wishbone.py
liteeth/mac/test/Makefile [deleted file]
liteeth/mac/test/__init__.py [deleted file]
liteeth/mac/test/common.py [deleted file]
liteeth/mac/test/crc_tb.py [deleted file]
liteeth/mac/test/ethmac_tb.gtkw [deleted file]
liteeth/mac/test/ethmac_tb.py [deleted file]
liteeth/mac/test/preamble_tb.py [deleted file]
liteeth/phy/gmii.py
liteeth/phy/loopback.py
liteeth/phy/mii.py
liteeth/test/Makefile [new file with mode: 0644]
liteeth/test/__init__.py [new file with mode: 0644]
liteeth/test/common.py [new file with mode: 0644]
liteeth/test/mac_core_tb.py [new file with mode: 0644]
liteeth/test/mac_wishbone_tb.py [new file with mode: 0644]

index 177943ee536d308f5eceba6d6ece6742ccc5cd2f..9f4a1d6eb4aa24b0334a636f6381217228185be8 100644 (file)
@@ -1,4 +1,10 @@
+from collections import OrderedDict
+
+from migen.fhdl.std import *
 from migen.fhdl.std import *
+from migen.flow.actor import Sink, Source
+from migen.bank.description import *
+from migen.genlib.resetsync import AsyncResetSynchronizer
 from migen.flow.actor import EndpointDescription
 
 eth_mtu = 1532
index e9b2ccfaa966905db8f1c1f2c3abc854d2f00228..280fbdf7a37fcf6cf3b561ad2a183dec945a4746 100644 (file)
@@ -1,54 +1,17 @@
-from liteethernet.common import *
-from liteethernet.mac import LiteEthernetMAC
-
-class LiteEthernetMAC(Module, AutoCSR):
-       def __init__(self, phy, frontend="wishbone", with_hw_preamble_crc=True, endianness="be"):
-               self.submodules.core = LiteEthernetMAC(phy, with_hw_preamble, endianness)
-
+from liteeth.common import *
+from liteeth.mac.core import LiteEthMACCore
+from liteeth.mac.frontend import wishbone
+
+class LiteEthMAC(Module, AutoCSR):
+       def __init__(self, phy, interface="wishbone", dw, endianness="be",
+                       with_hw_preamble_crc=True):
+               self.submodules.core = LiteEthMACCore(phy, endianness, with_hw_preamble)
                if interface == "wishbone":
-                       nrxslots = 2
-                       ntxslots = 2
-
-                       self.bus = wishbone.Interface()
-
-                       # SRAM Memories
-                       sram_depth = buffer_depth//(32//8)
-                       self.submodules.sram_writer = SRAMWriter(sram_depth, nrxslots)
-                       self.submodules.sram_reader = SRAMReader(sram_depth, ntxslots)
-                       self.submodules.ev = SharedIRQ(self.sram_writer.ev, self.sram_reader.ev)
-
-                       # Connect to pipelines
-                       self.comb += [
-                               self.rx_pipeline.source.connect(self.sram_writer.sink),
-                               self.sram_reader.source.connect(self.tx_pipeline.sink)
-                       ]
-
-                       # Interface
-                       wb_rx_sram_ifs = [wishbone.SRAM(self.sram_writer.mems[n], read_only=True)
-                               for n in range(nrxslots)]
-                       # TODO: FullMemoryWE should move to Mibuild
-                       wb_tx_sram_ifs = [FullMemoryWE(wishbone.SRAM(self.sram_reader.mems[n], read_only=False))
-                               for n in range(ntxslots)]
-                       wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs
-
-                       wb_slaves = []
-                       decoderoffset = log2_int(sram_depth)
-                       decoderbits = log2_int(len(wb_sram_ifs))
-                       for n, wb_sram_if in enumerate(wb_sram_ifs):
-                               def slave_filter(a, v=n):
-                                       return a[decoderoffset:decoderoffset+decoderbits] == v
-                               wb_slaves.append((slave_filter, wb_sram_if.bus))
-                               self.submodules += wb_sram_if
-                       wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True)
-                       self.submodules += wb_con
-
-               elif interface == "lasmi":
+                       self.interface = wishbone.LiteETHMACWishboneInterface(), dw, nrxslots, ntxslots)
+               elif interface == "dma":
                        raise NotImplementedError
-
-               elif interface == "expose":
-                       # expose pipelines endpoints
-                       self.sink = tx_pipeline.sink
-                       self.source = rx_pipeline.source
-
+               elif interface == "core":
+                       self.sink = self.core.sink
+                       self.source = self.core.source
                else:
-                       raise ValueError("EthMAC only supports Wishbone, LASMI or expose interfaces")
+                       raise ValueError("EthMAC only supports Wishbone, DMA or core interfaces")
index 177943ee536d308f5eceba6d6ece6742ccc5cd2f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,14 +0,0 @@
-from migen.fhdl.std import *
-from migen.flow.actor import EndpointDescription
-
-eth_mtu = 1532
-eth_preamble = 0xD555555555555555
-buffer_depth = 2**log2_int(eth_mtu, need_pow2=False)
-
-def eth_description(dw):
-       layout = [
-               ("d", dw),
-               ("last_be", dw//8),
-               ("error", dw//8)
-       ]
-       return EndpointDescription(layout, packetized=True)
index a361d5dcb76282c26e0790d1de9ecb066fed0a7f..5e223f0c625d8a6b6a662356c633f0de985ffee7 100644 (file)
@@ -1,43 +1,42 @@
-
-from liteethernet.common import *
-from liteethernet.mac.common import *
-from liteethernet.mac.preamble import PreambleInserter, PreambleChecker
-from liteethernet.mac.crc import CRC32Inserter, CRC32Checker
-from liteethernet.mac.last_be import TXLastBE, RXLastBE
-
-class LiteEthernetMACCore(Module, AutoCSR):
-       def __init__(self, phy, with_hw_preamble_crc=True, endianness="be"):
+from liteeth.common import *
+from liteeth.mac.common import *
+from liteeth.mac import preamble, crc, last_be
+
+class LiteEthMACCore(Module, AutoCSR):
+       def __init__(self, phy, dw, endianness="be", with_hw_preamble_crc=True):
+               if dw > phy.dw:
+                       raise ValueError("Core data width must be larger than PHY data width")
                # Preamble / CRC (optional)
                if with_hw_preamble_crc:
                        self._hw_preamble_crc = CSRStatus(reset=1)
                        # Preamble insert/check
-                       preamble_inserter = PreambleInserter(phy.dw)
-                       preamble_checker = PreambleChecker(phy.dw)
+                       preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
+                       preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
                        self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
                        self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
 
                        # CRC insert/check
-                       crc32_inserter = CRC32Inserter(eth_description(phy.dw))
-                       crc32_checker = CRC32Checker(eth_description(phy.dw))
+                       crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_description(phy.dw))
+                       crc32_checker = crc.LiteEthMACCRC32Checker(eth_description(phy.dw))
                        self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
                        self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
 
                # Delimiters
-               tx_last_be = TXLastBE(phy.dw)
-               rx_last_be = RXLastBE(phy.dw)
+               tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
+               rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
                self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
                self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
 
                # Converters
                reverse = endianness == "be"
-               tx_converter = Converter(eth_description(32), eth_description(phy.dw), reverse=reverse)
-               rx_converter = Converter(eth_description(phy.dw), eth_description(32), reverse=reverse)
+               tx_converter = Converter(eth_description(dw), eth_description(phy.dw), reverse=reverse)
+               rx_converter = Converter(eth_description(phy.dw), eth_description(dw), reverse=reverse)
                self.submodules += RenameClockDomains(tx_converter, "eth_tx")
                self.submodules += RenameClockDomains(rx_converter, "eth_rx")
 
                # Cross Domain Crossing
-               tx_cdc = AsyncFIFO(eth_description(32), 4)
-               rx_cdc = AsyncFIFO(eth_description(32), 4)
+               tx_cdc = AsyncFIFO(eth_description(dw), 4)
+               rx_cdc = AsyncFIFO(eth_description(dw), 4)
                self.submodules +=  RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
                self.submodules +=  RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
 
index 8a058faebda913ebd8a4d2d1405c1df0a218e82f..f77c5e0dfa6683eeead6b5a72c9ecb4d7910b6a5 100644 (file)
@@ -1,14 +1,7 @@
-from migen.fhdl.std import *
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.record import *
-from migen.genlib.misc import optree, chooser
-from migen.genlib.crc import *
-from migen.flow.actor import Sink, Source
-from migen.actorlib.fifo import SyncFIFO
+from liteeth.common import *
+from liteeth.mac.common import *
 
-from collections import OrderedDict
-
-class CRCEngine(Module):
+class LiteEthMACCRCEngine(Module):
        """Cyclic Redundancy Check Engine
 
        Compute next CRC value from last CRC value and data input using
@@ -78,7 +71,7 @@ class CRCEngine(Module):
 
 @DecorateModule(InsertReset)
 @DecorateModule(InsertCE)
-class CRC32(Module):
+class LiteEthMACCRC32(Module):
        """IEEE 802.3 CRC
 
        Implement an IEEE 802.3 CRC generator/checker.
@@ -108,7 +101,7 @@ class CRC32(Module):
 
                ###
 
-               self.submodules.engine = CRCEngine(dat_width, self.width, self.polynom)
+               self.submodules.engine = LiteEthCRCEngine(dat_width, self.width, self.polynom)
                reg = Signal(self.width, reset=self.init)
                self.sync += reg.eq(self.engine.next)
                self.comb += [
@@ -119,7 +112,7 @@ class CRC32(Module):
                        self.error.eq(self.engine.next != self.check)
                ]
 
-class CRCInserter(Module):
+class LiteEthMACCRCInserter(Module):
        """CRC Inserter
 
        Append a CRC at the end of each packet.
@@ -193,11 +186,11 @@ class CRCInserter(Module):
                        )
                self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
 
-class CRC32Inserter(CRCInserter):
+class LiteEthMACCRC32Inserter(CRCInserter):
        def __init__(self, layout):
-               CRCInserter.__init__(self, CRC32, layout)
+               LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, layout)
 
-class CRCChecker(Module):
+class LiteEthMACCRCChecker(Module):
        """CRC Checker
 
        Check CRC at the end of each packet.
@@ -279,6 +272,6 @@ class CRCChecker(Module):
                )
                self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
 
-class CRC32Checker(CRCChecker):
+class LiteEthMACCRC32Checker(CRCChecker):
        def __init__(self, layout):
-               CRCChecker.__init__(self, CRC32, layout)
+               LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, layout)
index 555e523f5dc658e85aa5e5b6593c3eee9b606fab..cfab1c6966408ee11e02582ac36cc426af3b35ee 100644 (file)
@@ -1,11 +1,7 @@
-from migen.fhdl.std import *
-from migen.genlib.record import *
-from migen.flow.actor import Sink, Source
+from liteeth.common import *
+from liteeth.mac.common import *
 
-from liteethernet.common import *
-from liteethernet.mac.common import *
-
-class TXLastBE(Module):
+class LiteEthMACTXLastBE(Module):
        def __init__(self, d_w):
                self.sink = sink = Sink(eth_description(d_w))
                self.source = source = Source(eth_description(d_w))
@@ -27,7 +23,7 @@ class TXLastBE(Module):
                        self.source.stb.eq(self.sink.stb & (self.sink.sop | ongoing))
                ]
 
-class RXLastBE(Module):
+class LiteEthMACRXLastBE(Module):
        def __init__(self, d_w):
                self.sink = sink = Sink(eth_description(d_w))
                self.source = source = Source(eth_description(d_w))
index f1c760347250cf5db467ab9b21bc4c7f6a4dc95e..9f4cb0ccb968da8325727010212eda1c45935c39 100644 (file)
@@ -1,13 +1,7 @@
-from migen.fhdl.std import *
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import chooser
-from migen.genlib.record import *
-from migen.flow.actor import Sink, Source
+from liteeth.common import *
+from liteeth.mac.common import *
 
-from liteethernet.common import *
-from liteethernet.ethmac.common import *
-
-class PreambleInserter(Module):
+class LiteEthMACPreambleInserter(Module):
        def __init__(self, d_w):
                self.sink = Sink(eth_description(d_w))
                self.source = Source(eth_description(d_w))
@@ -56,7 +50,7 @@ class PreambleInserter(Module):
                        )
                )
 
-class PreambleChecker(Module):
+class LiteEthMACPreambleChecker(Module):
        def __init__(self, d_w):
                self.sink = Sink(eth_description(d_w))
                self.source = Source(eth_description(d_w))
index c51c0ecbee75e5a9b36b42598c9e6f46cf3de489..ec4f963bd175b02af1beabd6d4576b61352d5c4c 100644 (file)
@@ -1,17 +1,9 @@
-from migen.fhdl.std import *
-from migen.genlib.fifo import SyncFIFO
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import chooser
-from migen.flow.actor import Sink, Source
-from migen.bank.description import *
-from migen.bank.eventmanager import *
-
-from liteethernet.common import *
-from liteethernet.mac.common import *
-
-class SRAMWriter(Module, AutoCSR):
-       def __init__(self, depth, nslots=2):
-               self.sink = sink = Sink(eth_description(32))
+from liteeth.common import *
+from liteeth.mac.common import *
+
+class LiteEthMACSRAMWriter(Module, AutoCSR):
+       def __init__(self, dw, depth, nslots=2):
+               self.sink = sink = Sink(eth_description(dw))
                self.crc_error = Signal()
 
                slotbits = max(log2_int(nslots), 1)
@@ -117,7 +109,7 @@ class SRAMWriter(Module, AutoCSR):
                mems = [None]*nslots
                ports = [None]*nslots
                for n in range(nslots):
-                       mems[n] = Memory(32, depth)
+                       mems[n] = Memory(dw, depth)
                        ports[n] = mems[n].get_port(write_capable=True)
                        self.specials += ports[n]
                self.mems = mems
@@ -134,9 +126,9 @@ class SRAMWriter(Module, AutoCSR):
                self.comb += Case(slot, cases)
 
 
-class SRAMReader(Module, AutoCSR):
-       def __init__(self, depth, nslots=2):
-               self.source = source = Source(eth_description(32))
+class LiteEthMACSRAMReader(Module, AutoCSR):
+       def __init__(self, dw, depth, nslots=2):
+               self.source = source = Source(eth_description(dw))
 
                slotbits = max(log2_int(nslots), 1)
                lengthbits = log2_int(depth*4) # length in bytes
@@ -240,7 +232,7 @@ class SRAMReader(Module, AutoCSR):
                mems = [None]*nslots
                ports = [None]*nslots
                for n in range(nslots):
-                       mems[n] = Memory(32, depth)
+                       mems[n] = Memory(dw, depth)
                        ports[n] = mems[n].get_port()
                        self.specials += ports[n]
                self.mems = mems
@@ -250,3 +242,10 @@ class SRAMReader(Module, AutoCSR):
                        self.comb += ports[n].adr.eq(cnt[2:])
                        cases[n] = [source.d.eq(port.dat_r)]
                self.comb += Case(rd_slot, cases)
+
+class LiteMACEthMACSRAM(Module, AutoCSR):
+       def __init__(self, dw, depth, nrxslots, ntxslots):
+               self.submodules.writer = LiteEthSRAMWriter(dw, depth, nrxslots)
+               self.submodules.reader = LiteEthSRAMReader(dw, depth, ntxslots)
+               self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
+               self.sink, self.source = self.witer.sink, self.reader.source
index 56601e12684a1d4cacd93ff7d60b157943804cac..c81590181698ba5357129c6e580b5414218feeb4 100644 (file)
@@ -1,25 +1,22 @@
-from liteethernet.common import *
-from liteethernet.mac import LiteEthernetMAC
+from liteeth.common import *
+from liteeth.mac.common import *
+from liteeth.mac.frontend import sram
 
-class LiteEthernetMACWishboneInterface(Module, AutoCSR):
-       def __init__(self, nrxslots=2, ntxslots=2):
+class LiteEthMACWishboneInterface(Module, AutoCSR):
+       def __init__(self, dw, nrxslots=2, ntxslots=2):
                self.sink = Sink(mac_description(dw))
                self.source = Source(max_description(dw))
                self.bus = wishbone.Interface()
-
                ###
-
-               # SRAM Storage
-               sram_depth = buffer_depth//(32//8)
-               self.submodules.sram_writer = SRAMWriter(sram_depth, nrxslots)
-               self.submodules.sram_reader = SRAMReader(sram_depth, ntxslots)
-               self.submodules.ev = SharedIRQ(self.sram_writer.ev, self.sram_reader.ev)
+               # storage in SRAM
+               sram_depth = buffer_depth//(dw//8)
+               self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots)
                self.comb += [
-                       Record.connect(self.sink, self.sram_writer.sink),
-                       Record.connect(self.sram_reader.source, self.source)
+                       Record.connect(self.sink, self.sram.sink),
+                       Record.connect(self.sram.source, self.source)
                ]
 
-               # Interface
+               # Wishbone interface
                wb_rx_sram_ifs = [wishbone.SRAM(self.sram_writer.mems[n], read_only=True)
                        for n in range(nrxslots)]
                # TODO: FullMemoryWE should move to Mibuild
diff --git a/liteeth/mac/test/Makefile b/liteeth/mac/test/Makefile
deleted file mode 100644 (file)
index 55d28e1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-MSCDIR = ../../../
-PYTHON = python3
-
-CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
-
-crc_tb:
-       $(CMD) crc_tb.py
-
-preamble_tb:
-       $(CMD) preamble_tb.py
-
-ethmac_tb:
-       $(CMD) ethmac_tb.py
diff --git a/liteeth/mac/test/__init__.py b/liteeth/mac/test/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/liteeth/mac/test/common.py b/liteeth/mac/test/common.py
deleted file mode 100644 (file)
index 1312370..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-import random, copy
-
-from migen.fhdl.std import *
-from migen.flow.actor import Sink, Source
-from migen.genlib.record import *
-
-from misoclib.ethmac.common import *
-
-def seed_to_data(seed, random=True):
-       if random:
-               return (seed * 0x31415979 + 1) & 0xffffffff
-       else:
-               return seed
-
-def check(p1, p2):
-       p1 = copy.deepcopy(p1)
-       p2 = copy.deepcopy(p2)
-       if isinstance(p1, int):
-               return 0, 1, int(p1 != p2)
-       else:
-               if len(p1) >= len(p2):
-                       ref, res = p1, p2
-               else:
-                       ref, res = p2, p1
-               shift = 0
-               while((ref[0] != res[0]) and (len(res)>1)):
-                       res.pop(0)
-                       shift += 1
-               length = min(len(ref), len(res))
-               errors = 0
-               for i in range(length):
-                       if ref.pop(0) != res.pop(0):
-                               errors += 1
-               return shift, length, errors
-
-def randn(max_n):
-       return random.randint(0, max_n-1)
-
-class Packet(list):
-       def __init__(self, init=[]):
-               self.ongoing = False
-               self.done = False
-               for data in init:
-                       self.append(data)
-
-class PacketStreamer(Module):
-       def __init__(self, description):
-               self.source = Source(description)
-               ###
-               self.packets = []
-               self.packet = Packet()
-               self.packet.done = 1
-
-       def send(self, packet):
-               packet = copy.deepcopy(packet)
-               self.packets.append(packet)
-
-       def do_simulation(self, selfp):
-               if len(self.packets) and self.packet.done:
-                       self.packet = self.packets.pop(0)
-               if not self.packet.ongoing and not self.packet.done:
-                       selfp.source.stb = 1
-                       selfp.source.sop = 1
-                       selfp.source.d = self.packet.pop(0)
-                       self.packet.ongoing = True
-               elif selfp.source.stb == 1 and selfp.source.ack == 1:
-                       selfp.source.sop = 0
-                       selfp.source.eop = (len(self.packet) == 1)
-                       if len(self.packet) > 0:
-                               selfp.source.stb = 1
-                               selfp.source.d = self.packet.pop(0)
-                       else:
-                               self.packet.done = 1
-                               selfp.source.stb = 0
-
-class PacketLogger(Module):
-       def __init__(self, description):
-               self.sink = Sink(description)
-               ###
-               self.packet = Packet()
-
-       def receive(self):
-               self.packet.done = 0
-               while self.packet.done == 0:
-                       yield
-
-       def do_simulation(self, selfp):
-               selfp.sink.ack = 1
-               if selfp.sink.stb == 1 and selfp.sink.sop == 1:
-                       self.packet = Packet()
-                       self.packet.append(selfp.sink.d)
-               elif selfp.sink.stb:
-                       self.packet.append(selfp.sink.d)
-               if selfp.sink.stb == 1 and selfp.sink.eop == 1:
-                       self.packet.done = True
-
-class AckRandomizer(Module):
-       def __init__(self, description, level=0):
-               self.level = level
-
-               self.sink = Sink(description)
-               self.source = Source(description)
-
-               self.run = Signal()
-
-               self.comb += \
-                       If(self.run,
-                               Record.connect(self.sink, self.source)
-                       ).Else(
-                               self.source.stb.eq(0),
-                               self.sink.ack.eq(0),
-                       )
-
-       def do_simulation(self, selfp):
-               n = randn(100)
-               if n < self.level:
-                       selfp.run = 0
-               else:
-                       selfp.run = 1
-
diff --git a/liteeth/mac/test/crc_tb.py b/liteeth/mac/test/crc_tb.py
deleted file mode 100644 (file)
index 5d185ac..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-from migen.fhdl.std import *
-from migen.actorlib.crc import *
-
-from misoclib.ethmac.common import *
-from misoclib.ethmac.test.common import *
-
-payload = [
-       0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12,
-       0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00,
-       0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11,
-       0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00,
-       0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C,
-       0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
-       0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
-       0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
-]
-
-crc = [
-       0x7A, 0xD5, 0x6B, 0xB3
-]
-
-mux = {
-       "inserter": 0,
-       "checker": 1,
-       "both": 2
-}
-
-class TB(Module):
-       def __init__(self, random_level=50):
-               sm = self.submodules
-               sm.streamer = PacketStreamer(eth_description(8))
-               sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level)
-               sm.logger = PacketLogger(eth_description(8))
-               sm.logger_randomizer = AckRandomizer(eth_description(8), random_level)
-
-               self.comb += [
-                       self.streamer.source.connect(self.streamer_randomizer.sink),
-                       self.logger_randomizer.source.connect(self.logger.sink)
-               ]
-
-               sm.crc32_inserter = CRC32Inserter(eth_description(8))
-               sm.crc32_checker = CRC32Checker(eth_description(8))
-
-               self.mux = Signal(2)
-               self.comb += [
-                       If(self.mux == mux["inserter"],
-                               self.streamer_randomizer.source.connect(self.crc32_inserter.sink),
-                               self.crc32_inserter.source.connect(self.logger_randomizer.sink)
-                       ).Elif(self.mux == mux["checker"],
-                               self.streamer_randomizer.source.connect(self.crc32_checker.sink),
-                               self.crc32_checker.source.connect(self.logger_randomizer.sink)
-                       ).Elif(self.mux == mux["both"],
-                               self.streamer_randomizer.source.connect(self.crc32_inserter.sink),
-                               self.crc32_inserter.source.connect(self.crc32_checker.sink),
-                               self.crc32_checker.source.connect(self.logger_randomizer.sink)
-                       )
-               ]
-
-       def gen_simulation(self, selfp):
-               selfp.mux = mux["inserter"]
-               print("streamer --> crc32_inserter --> logger:")
-               self.streamer.send(Packet(payload))
-               yield from self.logger.receive()
-               s, l, e = check(payload+crc, self.logger.packet)
-               print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
-               selfp.mux = mux["checker"]
-               print("streamer --> crc32_checker --> logger:")
-               self.streamer.send(Packet(payload+crc))
-               yield from self.logger.receive()
-               s, l, e = check(payload, self.logger.packet)
-               print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
-               selfp.mux = mux["both"]
-               print("streamer --> crc32_inserter --> crc32_checker --> logger:")
-               self.streamer.send(Packet(payload))
-               yield from self.logger.receive()
-               s, l, e = check(payload, self.logger.packet)
-               print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
-if __name__ == "__main__":
-       from migen.sim.generic import run_simulation
-       run_simulation(TB(), ncycles=1000, vcd_name="my.vcd")
diff --git a/liteeth/mac/test/ethmac_tb.gtkw b/liteeth/mac/test/ethmac_tb.gtkw
deleted file mode 100644 (file)
index 350521a..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-[*]
-[*] GTKWave Analyzer v3.3.46 (w)1999-2012 BSI
-[*] Fri Oct 31 11:20:55 2014
-[*]
-[dumpfile] "/home/florent/Dev/misoc/misoclib/ethmac/test/my.vcd"
-[dumpfile_mtime] "Fri Oct 31 11:20:07 2014"
-[dumpfile_size] 5152269
-[savefile] "/home/florent/Dev/misoc/misoclib/ethmac/test/ethmac_tb.gtkw"
-[timestart] 0
-[size] 1548 849
-[pos] 101 171
-*-25.000000 34300000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-[treeopen] top.
-[sst_width] 379
-[signals_width] 464
-[sst_expanded] 1
-[sst_vpaned_height] 485
-@200
--WISHBONE
-@28
-top.dut.bus_ack
-@22
-top.dut.bus_adr[29:0]
-@28
-top.dut.bus_bte[1:0]
-top.dut.bus_cti[2:0]
-top.dut.bus_cyc
-@22
-top.dut.bus_dat_r[31:0]
-top.dut.bus_dat_w[31:0]
-@28
-top.dut.bus_err
-@22
-top.dut.bus_sel[3:0]
-@28
-top.dut.bus_stb
-top.dut.bus_we
-@200
--SRAM_READER --> PHYTx
-@28
-top.dut.sram_reader_source_ack
-top.dut.sram_reader_source_eop
-@22
-top.dut.sram_reader_source_payload_d[31:0]
-top.dut.sram_reader_source_payload_error[3:0]
-top.dut.sram_reader_source_payload_last_be[3:0]
-@28
-top.dut.sram_reader_source_sop
-top.dut.sram_reader_source_stb
-@200
--LOOPBACK
-@28
-top.dut.phy_source_ack
-top.dut.phy_source_eop
-@22
-top.dut.phy_source_payload_d[7:0]
-@28
-top.dut.phy_source_payload_error
-top.dut.phy_source_payload_last_be
-top.dut.phy_source_sop
-top.dut.phy_source_stb
-@200
--PHYRx --> SRAM_WRITER
-@28
-top.dut.sram_writer_sink_ack
-top.dut.sram_writer_sink_eop
-@22
-top.dut.sram_writer_sink_payload_d[31:0]
-top.dut.sram_writer_sink_payload_error[3:0]
-top.dut.sram_writer_sink_payload_last_be[3:0]
-@28
-top.dut.sram_writer_sink_sop
-top.dut.sram_writer_sink_stb
-[pattern_trace] 1
-[pattern_trace] 0
diff --git a/liteeth/mac/test/ethmac_tb.py b/liteeth/mac/test/ethmac_tb.py
deleted file mode 100644 (file)
index 1e4dbf1..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.bus.transactions import *
-from migen.sim.generic import run_simulation
-
-from misoclib.ethmac import EthMAC
-from misoclib.ethmac.phy import loopback
-
-from misoclib.ethmac.test.common import *
-
-class WishboneMaster:
-       def __init__(self, obj):
-               self.obj = obj
-               self.dat = 0
-
-       def write(self, adr, dat):
-               self.obj.cyc = 1
-               self.obj.stb = 1
-               self.obj.adr = adr
-               self.obj.we = 1
-               self.obj.sel = 0xF
-               self.obj.dat_w = dat
-               while self.obj.ack == 0:
-                       yield
-               self.obj.cyc = 0
-               self.obj.stb = 0
-               yield
-
-       def read(self, adr):
-               self.obj.cyc = 1
-               self.obj.stb = 1
-               self.obj.adr = adr
-               self.obj.we = 0
-               self.obj.sel = 0xF
-               self.obj.dat_w = 0
-               while self.obj.ack == 0:
-                       yield
-               self.dat = self.obj.dat_r
-               self.obj.cyc = 0
-               self.obj.stb = 0
-               yield
-
-class SRAMReaderDriver:
-       def __init__(self, obj):
-               self.obj = obj
-
-       def start(self, slot, length):
-               self.obj._slot.storage = slot
-               self.obj._length.storage = length
-               self.obj._start.re = 1
-               yield
-               self.obj._start.re = 0
-               yield
-
-       def wait_done(self):
-               while self.obj.ev.done.pending == 0:
-                       yield
-
-       def clear_done(self):
-               self.obj.ev.done.clear = 1
-               yield
-               self.obj.ev.done.clear = 0
-               yield
-
-class TB(Module):
-       def __init__(self):
-               self.submodules.ethphy = loopback.LoopbackPHY()
-               self.submodules.ethmac = EthMAC(phy=self.ethphy, with_hw_preamble_crc=True)
-
-               # use sys_clk for each clock_domain
-               self.clock_domains.cd_eth_rx = ClockDomain()
-               self.clock_domains.cd_eth_tx = ClockDomain()
-               self.comb += [
-                       self.cd_eth_rx.clk.eq(ClockSignal()),
-                       self.cd_eth_rx.rst.eq(ResetSignal()),
-                       self.cd_eth_tx.clk.eq(ClockSignal()),
-                       self.cd_eth_tx.rst.eq(ResetSignal()),
-               ]
-
-       def gen_simulation(self, selfp):
-               selfp.cd_eth_rx.rst = 1
-               selfp.cd_eth_tx.rst = 1
-               yield
-               selfp.cd_eth_rx.rst = 0
-               selfp.cd_eth_tx.rst = 0
-
-               wishbone_master = WishboneMaster(selfp.ethmac.bus)
-               sram_reader_driver = SRAMReaderDriver(selfp.ethmac.sram_reader)
-
-               sram_writer_slots_offset = [0x000, 0x200]
-               sram_reader_slots_offset = [0x400, 0x600]
-
-               length = 1500+2
-
-               tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0]
-
-               errors = 0
-
-               for slot in range(2):
-                       print("slot {}:".format(slot))
-                       # fill tx memory
-                       for i in range(length//4+1):
-                               dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big")
-                               yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat)
-
-                       # send tx payload & wait
-                       yield from sram_reader_driver.start(slot, length)
-                       yield from sram_reader_driver.wait_done()
-                       yield from sram_reader_driver.clear_done()
-
-                       # get rx payload (loopback on PHY Model)
-                       rx_payload = []
-                       for i in range(length//4+1):
-                               yield from wishbone_master.read(sram_writer_slots_offset[slot]+i)
-                               dat = wishbone_master.dat
-                               rx_payload += list(dat.to_bytes(4, byteorder='big'))
-
-                       # check results
-                       s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))])
-                       print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
-if __name__ == "__main__":
-       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/liteeth/mac/test/preamble_tb.py b/liteeth/mac/test/preamble_tb.py
deleted file mode 100644 (file)
index 85bd7e6..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-from migen.fhdl.std import *
-
-from misoclib.ethmac.common import *
-from misoclib.ethmac.preamble import *
-from misoclib.ethmac.test.common import *
-
-preamble = [
-       0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5
-]
-
-payload = [
-       0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12,
-       0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00,
-       0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11,
-       0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00,
-       0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C,
-       0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
-       0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
-       0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
-]
-
-mux = {
-       "inserter": 0,
-       "checker": 1,
-       "both": 2
-}
-
-class TB(Module):
-       def __init__(self, random_level=50):
-               sm = self.submodules
-               sm.streamer = PacketStreamer(eth_description(8))
-               sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level)
-               sm.logger = PacketLogger(eth_description(8))
-               sm.logger_randomizer = AckRandomizer(eth_description(8), random_level)
-
-               self.comb += [
-                       self.streamer.source.connect(self.streamer_randomizer.sink),
-                       self.logger_randomizer.source.connect(self.logger.sink)
-               ]
-
-               sm.preamble_inserter = PreambleInserter(8)
-               sm.preamble_checker = PreambleChecker(8)
-
-               self.mux = Signal(2)
-               self.comb += [
-                       If(self.mux == mux["inserter"],
-                               self.streamer_randomizer.source.connect(self.preamble_inserter.sink),
-                               self.preamble_inserter.source.connect(self.logger_randomizer.sink)
-                       ).Elif(self.mux == mux["checker"],
-                               self.streamer_randomizer.source.connect(self.preamble_checker.sink),
-                               self.preamble_checker.source.connect(self.logger_randomizer.sink)
-                       ).Elif(self.mux == mux["both"],
-                               self.streamer_randomizer.source.connect(self.preamble_inserter.sink),
-                               self.preamble_inserter.source.connect(self.preamble_checker.sink),
-                               self.preamble_checker.source.connect(self.logger_randomizer.sink)
-                       )
-               ]
-       def gen_simulation(self, selfp):
-               selfp.mux = mux["inserter"]
-               print("streamer --> preamble_inserter --> logger:")
-               self.streamer.send(Packet(payload))
-               yield from self.logger.receive()
-               s, l, e = check(preamble+payload, self.logger.packet)
-               print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
-               selfp.mux = mux["checker"]
-               print("streamer --> preamble_checker --> logger:")
-               self.streamer.send(Packet(preamble+payload))
-               yield from self.logger.receive()
-               s, l, e = check(payload, self.logger.packet)
-               print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
-               selfp.mux = mux["both"]
-               print("streamer --> preamble_inserter --> preamble_checker --> logger:")
-               self.streamer.send(Packet(payload))
-               yield from self.logger.receive()
-               s, l, e = check(payload, self.logger.packet)
-               print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
-
-if __name__ == "__main__":
-       from migen.sim.generic import run_simulation
-       run_simulation(TB(), ncycles=1000, vcd_name="my.vcd")
index c1b8243d78c7b96c2962ce15f2c7e635023735fb..703f3c6c3570596de70d11792b5a3f5785c0fc7f 100644 (file)
@@ -1,11 +1,6 @@
-from migen.fhdl.std import *
-from migen.flow.actor import Sink, Source
-from migen.bank.description import *
-from migen.genlib.resetsync import AsyncResetSynchronizer
+from liteeth.common import *
 
-from liteethernet.common import *
-
-class GMIIPHYTX(Module):
+class LiteEthPHYGMIITX(Module):
        def __init__(self, pads):
                self.sink = sink = Sink(eth_description(8))
                ###
@@ -16,7 +11,7 @@ class GMIIPHYTX(Module):
                ]
                self.comb += sink.ack.eq(1)
 
-class GMIIPHYRX(Module):
+class LiteEthPHYGMIIRX(Module):
        def __init__(self, pads):
                self.source = source = Source(eth_description(8))
                ###
@@ -38,7 +33,7 @@ class GMIIPHYRX(Module):
 
 # CRG is the only Xilinx specific module.
 # TODO: use generic code or add support for others vendors
-class GMIIPHYCRG(Module, AutoCSR):
+class LiteEthPHYGMIICRG(Module, AutoCSR):
        def __init__(self, clock_pads, pads):
                self._reset = CSRStorage()
                ###
@@ -61,10 +56,10 @@ class GMIIPHYCRG(Module, AutoCSR):
                        AsyncResetSynchronizer(self.cd_eth_rx, reset),
                ]
 
-class GMIIPHY(Module, AutoCSR):
+class LiteEthPHYMII(Module, AutoCSR):
        def __init__(self, clock_pads, pads):
                self.dw = 8
-               self.submodules.crg = GMIIPHYCRG(clock_pads, pads)
-               self.submodules.tx = RenameClockDomains(GMIIPHYTX(pads), "eth_tx")
-               self.submodules.rx = RenameClockDomains(GMIIPHYRX(pads), "eth_rx")
+               self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads)
+               self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads), "eth_tx")
+               self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads), "eth_rx")
                self.sink, self.source = self.tx.sink, self.rx.source
index 04a51d07e028320fe652fca59b6be5e5eb0f1a4f..b4edb165196919dcaafda95f2833fc00e727afcb 100644 (file)
@@ -1,11 +1,6 @@
-from migen.fhdl.std import *
-from migen.flow.actor import Sink, Source
-from migen.bank.description import *
-from migen.genlib.record import *
+from liteeth.common import *
 
-from liteethernet.common import *
-
-class LoopbackPHYCRG(Module, AutoCSR):
+class LiteEthPHYLoopbackCRG(Module, AutoCSR):
        def __init__(self):
                self._reset = CSRStorage()
                ###
@@ -22,10 +17,10 @@ class LoopbackPHYCRG(Module, AutoCSR):
                        self.cd_eth_tx.rst.eq(reset)
                ]
 
-class LoopbackPHY(Module, AutoCSR):
+class LiteEthPHYLoopback(Module, AutoCSR):
        def __init__(self):
                self.dw = 8
-               self.submodules.crg = LoopbackPHYCRG()
+               self.submodules.crg = LiteEthLoopbackPHYCRG()
                self.sink = sink = Sink(eth_description(8))
                self.source = source = Source(eth_description(8))
                self.comb += Record.connect(self.sink, self.source)
index a58b52b5df0d8f01696f39945e95000b22645dc8..8d6d19c7958ac0d83418c956b544f81e03f885a2 100644 (file)
@@ -1,12 +1,6 @@
-from migen.fhdl.std import *
-from migen.genlib.fsm import FSM, NextState
-from migen.flow.actor import Sink, Source
-from migen.bank.description import *
-from migen.genlib.resetsync import AsyncResetSynchronizer
+from liteeth.common import *
 
-from liteethernet.common import *
-
-class MIIPHYTX(Module):
+class LiteEthPHYMIITX(Module):
        def __init__(self, pads):
                self.sink = sink = Sink(eth_description(8))
                ###
@@ -43,7 +37,7 @@ class MIIPHYTX(Module):
                        )
                )
 
-class MIIPHYRX(Module):
+class LiteEthPHYMIIRX(Module):
        def __init__(self, pads):
                self.source = source = Source(eth_description(8))
                ###
@@ -95,7 +89,7 @@ class MIIPHYRX(Module):
                        NextState("LOAD_LO")
                )
 
-class MIIPHYCRG(Module, AutoCSR):
+class LiteEthPHYMIICRG(Module, AutoCSR):
        def __init__(self, clock_pads, pads):
                self._reset = CSRStorage()
                ###
@@ -113,10 +107,10 @@ class MIIPHYCRG(Module, AutoCSR):
                        AsyncResetSynchronizer(self.cd_eth_rx, reset),
                ]
 
-class MIIPHY(Module, AutoCSR):
+class LiteEthPHYMII(Module, AutoCSR):
        def __init__(self, clock_pads, pads):
                self.dw = 8
-               self.submodules.crg = MIIPHYCRG(clock_pads, pads)
-               self.submodules.tx = RenameClockDomains(MIIPHYTX(pads), "eth_tx")
-               self.submodules.rx = RenameClockDomains(MIIPHYRX(pads), "eth_rx")
+               self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads)
+               self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx")
+               self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx")
                self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/liteeth/test/Makefile b/liteeth/test/Makefile
new file mode 100644 (file)
index 0000000..7741461
--- /dev/null
@@ -0,0 +1,13 @@
+LEDIR = ../../
+PYTHON = python3
+
+CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
+
+mac_crc_tb:
+       $(CMD) mac_crc_tb.py
+
+mac_preamble_tb:
+       $(CMD) mac_preamble_preamble_tb.py
+
+ethmac_tb:
+       $(CMD) ethmac_tb.py
diff --git a/liteeth/test/__init__.py b/liteeth/test/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/test/common.py b/liteeth/test/common.py
new file mode 100644 (file)
index 0000000..1312370
--- /dev/null
@@ -0,0 +1,120 @@
+import random, copy
+
+from migen.fhdl.std import *
+from migen.flow.actor import Sink, Source
+from migen.genlib.record import *
+
+from misoclib.ethmac.common import *
+
+def seed_to_data(seed, random=True):
+       if random:
+               return (seed * 0x31415979 + 1) & 0xffffffff
+       else:
+               return seed
+
+def check(p1, p2):
+       p1 = copy.deepcopy(p1)
+       p2 = copy.deepcopy(p2)
+       if isinstance(p1, int):
+               return 0, 1, int(p1 != p2)
+       else:
+               if len(p1) >= len(p2):
+                       ref, res = p1, p2
+               else:
+                       ref, res = p2, p1
+               shift = 0
+               while((ref[0] != res[0]) and (len(res)>1)):
+                       res.pop(0)
+                       shift += 1
+               length = min(len(ref), len(res))
+               errors = 0
+               for i in range(length):
+                       if ref.pop(0) != res.pop(0):
+                               errors += 1
+               return shift, length, errors
+
+def randn(max_n):
+       return random.randint(0, max_n-1)
+
+class Packet(list):
+       def __init__(self, init=[]):
+               self.ongoing = False
+               self.done = False
+               for data in init:
+                       self.append(data)
+
+class PacketStreamer(Module):
+       def __init__(self, description):
+               self.source = Source(description)
+               ###
+               self.packets = []
+               self.packet = Packet()
+               self.packet.done = 1
+
+       def send(self, packet):
+               packet = copy.deepcopy(packet)
+               self.packets.append(packet)
+
+       def do_simulation(self, selfp):
+               if len(self.packets) and self.packet.done:
+                       self.packet = self.packets.pop(0)
+               if not self.packet.ongoing and not self.packet.done:
+                       selfp.source.stb = 1
+                       selfp.source.sop = 1
+                       selfp.source.d = self.packet.pop(0)
+                       self.packet.ongoing = True
+               elif selfp.source.stb == 1 and selfp.source.ack == 1:
+                       selfp.source.sop = 0
+                       selfp.source.eop = (len(self.packet) == 1)
+                       if len(self.packet) > 0:
+                               selfp.source.stb = 1
+                               selfp.source.d = self.packet.pop(0)
+                       else:
+                               self.packet.done = 1
+                               selfp.source.stb = 0
+
+class PacketLogger(Module):
+       def __init__(self, description):
+               self.sink = Sink(description)
+               ###
+               self.packet = Packet()
+
+       def receive(self):
+               self.packet.done = 0
+               while self.packet.done == 0:
+                       yield
+
+       def do_simulation(self, selfp):
+               selfp.sink.ack = 1
+               if selfp.sink.stb == 1 and selfp.sink.sop == 1:
+                       self.packet = Packet()
+                       self.packet.append(selfp.sink.d)
+               elif selfp.sink.stb:
+                       self.packet.append(selfp.sink.d)
+               if selfp.sink.stb == 1 and selfp.sink.eop == 1:
+                       self.packet.done = True
+
+class AckRandomizer(Module):
+       def __init__(self, description, level=0):
+               self.level = level
+
+               self.sink = Sink(description)
+               self.source = Source(description)
+
+               self.run = Signal()
+
+               self.comb += \
+                       If(self.run,
+                               Record.connect(self.sink, self.source)
+                       ).Else(
+                               self.source.stb.eq(0),
+                               self.sink.ack.eq(0),
+                       )
+
+       def do_simulation(self, selfp):
+               n = randn(100)
+               if n < self.level:
+                       selfp.run = 0
+               else:
+                       selfp.run = 1
+
diff --git a/liteeth/test/mac_core_tb.py b/liteeth/test/mac_core_tb.py
new file mode 100644 (file)
index 0000000..1e4dbf1
--- /dev/null
@@ -0,0 +1,123 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.bus.transactions import *
+from migen.sim.generic import run_simulation
+
+from misoclib.ethmac import EthMAC
+from misoclib.ethmac.phy import loopback
+
+from misoclib.ethmac.test.common import *
+
+class WishboneMaster:
+       def __init__(self, obj):
+               self.obj = obj
+               self.dat = 0
+
+       def write(self, adr, dat):
+               self.obj.cyc = 1
+               self.obj.stb = 1
+               self.obj.adr = adr
+               self.obj.we = 1
+               self.obj.sel = 0xF
+               self.obj.dat_w = dat
+               while self.obj.ack == 0:
+                       yield
+               self.obj.cyc = 0
+               self.obj.stb = 0
+               yield
+
+       def read(self, adr):
+               self.obj.cyc = 1
+               self.obj.stb = 1
+               self.obj.adr = adr
+               self.obj.we = 0
+               self.obj.sel = 0xF
+               self.obj.dat_w = 0
+               while self.obj.ack == 0:
+                       yield
+               self.dat = self.obj.dat_r
+               self.obj.cyc = 0
+               self.obj.stb = 0
+               yield
+
+class SRAMReaderDriver:
+       def __init__(self, obj):
+               self.obj = obj
+
+       def start(self, slot, length):
+               self.obj._slot.storage = slot
+               self.obj._length.storage = length
+               self.obj._start.re = 1
+               yield
+               self.obj._start.re = 0
+               yield
+
+       def wait_done(self):
+               while self.obj.ev.done.pending == 0:
+                       yield
+
+       def clear_done(self):
+               self.obj.ev.done.clear = 1
+               yield
+               self.obj.ev.done.clear = 0
+               yield
+
+class TB(Module):
+       def __init__(self):
+               self.submodules.ethphy = loopback.LoopbackPHY()
+               self.submodules.ethmac = EthMAC(phy=self.ethphy, with_hw_preamble_crc=True)
+
+               # use sys_clk for each clock_domain
+               self.clock_domains.cd_eth_rx = ClockDomain()
+               self.clock_domains.cd_eth_tx = ClockDomain()
+               self.comb += [
+                       self.cd_eth_rx.clk.eq(ClockSignal()),
+                       self.cd_eth_rx.rst.eq(ResetSignal()),
+                       self.cd_eth_tx.clk.eq(ClockSignal()),
+                       self.cd_eth_tx.rst.eq(ResetSignal()),
+               ]
+
+       def gen_simulation(self, selfp):
+               selfp.cd_eth_rx.rst = 1
+               selfp.cd_eth_tx.rst = 1
+               yield
+               selfp.cd_eth_rx.rst = 0
+               selfp.cd_eth_tx.rst = 0
+
+               wishbone_master = WishboneMaster(selfp.ethmac.bus)
+               sram_reader_driver = SRAMReaderDriver(selfp.ethmac.sram_reader)
+
+               sram_writer_slots_offset = [0x000, 0x200]
+               sram_reader_slots_offset = [0x400, 0x600]
+
+               length = 1500+2
+
+               tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0]
+
+               errors = 0
+
+               for slot in range(2):
+                       print("slot {}:".format(slot))
+                       # fill tx memory
+                       for i in range(length//4+1):
+                               dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big")
+                               yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat)
+
+                       # send tx payload & wait
+                       yield from sram_reader_driver.start(slot, length)
+                       yield from sram_reader_driver.wait_done()
+                       yield from sram_reader_driver.clear_done()
+
+                       # get rx payload (loopback on PHY Model)
+                       rx_payload = []
+                       for i in range(length//4+1):
+                               yield from wishbone_master.read(sram_writer_slots_offset[slot]+i)
+                               dat = wishbone_master.dat
+                               rx_payload += list(dat.to_bytes(4, byteorder='big'))
+
+                       # check results
+                       s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))])
+                       print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+
+if __name__ == "__main__":
+       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/liteeth/test/mac_wishbone_tb.py b/liteeth/test/mac_wishbone_tb.py
new file mode 100644 (file)
index 0000000..1e4dbf1
--- /dev/null
@@ -0,0 +1,123 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.bus.transactions import *
+from migen.sim.generic import run_simulation
+
+from misoclib.ethmac import EthMAC
+from misoclib.ethmac.phy import loopback
+
+from misoclib.ethmac.test.common import *
+
+class WishboneMaster:
+       def __init__(self, obj):
+               self.obj = obj
+               self.dat = 0
+
+       def write(self, adr, dat):
+               self.obj.cyc = 1
+               self.obj.stb = 1
+               self.obj.adr = adr
+               self.obj.we = 1
+               self.obj.sel = 0xF
+               self.obj.dat_w = dat
+               while self.obj.ack == 0:
+                       yield
+               self.obj.cyc = 0
+               self.obj.stb = 0
+               yield
+
+       def read(self, adr):
+               self.obj.cyc = 1
+               self.obj.stb = 1
+               self.obj.adr = adr
+               self.obj.we = 0
+               self.obj.sel = 0xF
+               self.obj.dat_w = 0
+               while self.obj.ack == 0:
+                       yield
+               self.dat = self.obj.dat_r
+               self.obj.cyc = 0
+               self.obj.stb = 0
+               yield
+
+class SRAMReaderDriver:
+       def __init__(self, obj):
+               self.obj = obj
+
+       def start(self, slot, length):
+               self.obj._slot.storage = slot
+               self.obj._length.storage = length
+               self.obj._start.re = 1
+               yield
+               self.obj._start.re = 0
+               yield
+
+       def wait_done(self):
+               while self.obj.ev.done.pending == 0:
+                       yield
+
+       def clear_done(self):
+               self.obj.ev.done.clear = 1
+               yield
+               self.obj.ev.done.clear = 0
+               yield
+
+class TB(Module):
+       def __init__(self):
+               self.submodules.ethphy = loopback.LoopbackPHY()
+               self.submodules.ethmac = EthMAC(phy=self.ethphy, with_hw_preamble_crc=True)
+
+               # use sys_clk for each clock_domain
+               self.clock_domains.cd_eth_rx = ClockDomain()
+               self.clock_domains.cd_eth_tx = ClockDomain()
+               self.comb += [
+                       self.cd_eth_rx.clk.eq(ClockSignal()),
+                       self.cd_eth_rx.rst.eq(ResetSignal()),
+                       self.cd_eth_tx.clk.eq(ClockSignal()),
+                       self.cd_eth_tx.rst.eq(ResetSignal()),
+               ]
+
+       def gen_simulation(self, selfp):
+               selfp.cd_eth_rx.rst = 1
+               selfp.cd_eth_tx.rst = 1
+               yield
+               selfp.cd_eth_rx.rst = 0
+               selfp.cd_eth_tx.rst = 0
+
+               wishbone_master = WishboneMaster(selfp.ethmac.bus)
+               sram_reader_driver = SRAMReaderDriver(selfp.ethmac.sram_reader)
+
+               sram_writer_slots_offset = [0x000, 0x200]
+               sram_reader_slots_offset = [0x400, 0x600]
+
+               length = 1500+2
+
+               tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0]
+
+               errors = 0
+
+               for slot in range(2):
+                       print("slot {}:".format(slot))
+                       # fill tx memory
+                       for i in range(length//4+1):
+                               dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big")
+                               yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat)
+
+                       # send tx payload & wait
+                       yield from sram_reader_driver.start(slot, length)
+                       yield from sram_reader_driver.wait_done()
+                       yield from sram_reader_driver.clear_done()
+
+                       # get rx payload (loopback on PHY Model)
+                       rx_payload = []
+                       for i in range(length//4+1):
+                               yield from wishbone_master.read(sram_writer_slots_offset[slot]+i)
+                               dat = wishbone_master.dat
+                               rx_payload += list(dat.to_bytes(4, byteorder='big'))
+
+                       # check results
+                       s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))])
+                       print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+
+if __name__ == "__main__":
+       run_simulation(TB(), vcd_name="my.vcd")