etherbone: add etherbone_tb, able to probe etherbone endpoint
This commit is contained in:
parent
a2279bd2fa
commit
247c30ae26
|
@ -87,8 +87,8 @@ udp_protocol = 0x11
|
||||||
|
|
||||||
etherbone_magic = 0x4e6f
|
etherbone_magic = 0x4e6f
|
||||||
etherbone_version = 1
|
etherbone_version = 1
|
||||||
etherbone_header_len = 8
|
etherbone_packet_header_len = 8
|
||||||
etherbone_header = {
|
etherbone_packet_header = {
|
||||||
"magic": HField( 0, 0, 16),
|
"magic": HField( 0, 0, 16),
|
||||||
|
|
||||||
"version": HField( 2, 4, 4),
|
"version": HField( 2, 4, 4),
|
||||||
|
@ -130,6 +130,17 @@ def _layout_from_header(header):
|
||||||
_layout.append((k, v.width))
|
_layout.append((k, v.width))
|
||||||
return _layout
|
return _layout
|
||||||
|
|
||||||
|
def _remove_from_layout(layout, *args):
|
||||||
|
r = []
|
||||||
|
for f in layout:
|
||||||
|
remove = False
|
||||||
|
for arg in args:
|
||||||
|
if f[0] == arg:
|
||||||
|
remove = True
|
||||||
|
if not remove:
|
||||||
|
r.append(f)
|
||||||
|
return r
|
||||||
|
|
||||||
def eth_phy_description(dw):
|
def eth_phy_description(dw):
|
||||||
payload_layout = [
|
payload_layout = [
|
||||||
("data", dw),
|
("data", dw),
|
||||||
|
@ -230,36 +241,26 @@ def eth_udp_user_description(dw):
|
||||||
]
|
]
|
||||||
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
||||||
|
|
||||||
def eth_etherbone_description(dw):
|
def eth_etherbone_packet_description(dw):
|
||||||
payload_layout = [
|
payload_layout = [
|
||||||
("data", dw),
|
("data", dw),
|
||||||
("error", dw//8)
|
("error", dw//8)
|
||||||
]
|
]
|
||||||
param_layout = _layout_from_header(etherbone_header)
|
param_layout = _layout_from_header(etherbone_packet_header)
|
||||||
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
||||||
|
|
||||||
def eth_etherbone_description(dw):
|
def eth_etherbone_packet_user_description(dw):
|
||||||
payload_layout = [
|
payload_layout = [("data", dw)]
|
||||||
("data", dw),
|
param_layout = _layout_from_header(etherbone_packet_header)
|
||||||
("error", dw//8)
|
param_layout = _remove_from_layout(param_layout, "magic", "portsize", "addrsize", "version")
|
||||||
]
|
param_layout += eth_udp_user_description(dw).param_layout
|
||||||
param_layout = _layout_from_header(etherbone_header)
|
|
||||||
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
||||||
|
|
||||||
def eth_etherbone_user_description(dw):
|
def eth_etherbone_record_description(dw):
|
||||||
payload_layout = [
|
payload_layout = [("data", dw)]
|
||||||
("data", dw),
|
param_layout = _layout_from_header(etherbone_record_header)
|
||||||
("error", dw//8)
|
|
||||||
]
|
|
||||||
param_layout = [
|
|
||||||
("length", 16),
|
|
||||||
("ip_address", 32),
|
|
||||||
("wcount", 8),
|
|
||||||
("rcount", 8)
|
|
||||||
]
|
|
||||||
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
return EndpointDescription(payload_layout, param_layout, packetized=True)
|
||||||
|
|
||||||
|
|
||||||
# Generic classes
|
# Generic classes
|
||||||
class Port:
|
class Port:
|
||||||
def connect(self, port):
|
def connect(self, port):
|
||||||
|
|
|
@ -1,121 +1,30 @@
|
||||||
from liteeth.common import *
|
from liteeth.common import *
|
||||||
from liteeth.core.etherbone import common
|
from liteeth.core.etherbone import common
|
||||||
|
from liteeth.core.etherbone.packet import *
|
||||||
class LiteEthEtherboneTX(Module):
|
|
||||||
def __init__(self, udp_port):
|
|
||||||
self.sink = sink = Sink(eth_etherbone_user_description(32))
|
|
||||||
self.source = source = Source(eth_udp_user_description(32))
|
|
||||||
###
|
|
||||||
self.submodules.packetizer = packetizer = LiteEthEtherbonePacketizer()
|
|
||||||
self.comb += [
|
|
||||||
packetizer.sink.stb.eq(sink.stb),
|
|
||||||
packetizer.sink.sop.eq(sink.sop),
|
|
||||||
packetizer.sink.eop.eq(sink.eop),
|
|
||||||
sink.ack.eq(packetizer.sink.ack),
|
|
||||||
|
|
||||||
packetizer.sink.magic.eq(etherbone_magic),
|
|
||||||
packetizer.sink.portsize.eq(32), # XXX
|
|
||||||
packetizer.sink.addrsize.eq(32), # XXX
|
|
||||||
packetizer.sink.pf.eq(0), # XXX
|
|
||||||
packetizer.sink.version.eq(etherbone_version),
|
|
||||||
|
|
||||||
packetizer.sink.wff.eq(0), # XXX
|
|
||||||
packetizer.sink.wca.eq(0), # XXX
|
|
||||||
packetizer.sink.cyc.eq(0), # XXX
|
|
||||||
packetizer.sink.rff.eq(0), # XXX
|
|
||||||
packetizer.sink.rca.eq(0), # XXX
|
|
||||||
packetizer.sink.bca.eq(0), # XXX
|
|
||||||
|
|
||||||
packetizer.sink.rcount.eq(sink.rcount),
|
|
||||||
packetier.sink.wconut.eq(sink.wcount),
|
|
||||||
|
|
||||||
packetizer.sink.data.eq(sink.data)
|
|
||||||
]
|
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
|
||||||
fsm.act("IDLE",
|
|
||||||
packetizer.source.ack.eq(1),
|
|
||||||
If(packetizer.source.stb & packetizer.source.sop,
|
|
||||||
packetizer.source.ack.eq(0),
|
|
||||||
NextState("SEND")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.comb += [
|
|
||||||
source.src_port.eq(0x1234), # XXX,
|
|
||||||
source.dst_port.eq(udp_port),
|
|
||||||
source.ip_address.eq(sink.ip_address),
|
|
||||||
source.length.eq(sink.length + eth_etherbone_header_len)
|
|
||||||
]
|
|
||||||
fsm.act("SEND",
|
|
||||||
Record.connect(packetizer.source, source),
|
|
||||||
If(source.stb & source.eop & source.ack,
|
|
||||||
NextState("IDLE")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
class LiteEthEtherboneRX(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.sink = sink = Sink(eth_udp_user_description(32))
|
|
||||||
self.source = source = Source(eth_etherbone_user_description(32))
|
|
||||||
###
|
|
||||||
self.submodules.depacketizer = depacketizer = LiteEtherboneDepacketizer()
|
|
||||||
self.comb += Record.connect(sink, depacketizer.sink)
|
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
|
||||||
fsm.act("IDLE",
|
|
||||||
depacketizer.source.ack.eq(1),
|
|
||||||
If(depacketizer.source.stb & depacketizer.source.sop,
|
|
||||||
depacketizer.source.ack.eq(0),
|
|
||||||
NextState("CHECK")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
valid = Signal()
|
|
||||||
self.sync += valid.eq(
|
|
||||||
depacketizer.source.stb &
|
|
||||||
(depacketizer.source.magic == etherbone_magic) &
|
|
||||||
(depacketizer.source.version == etherbone_version)
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm.act("CHECK",
|
|
||||||
If(valid,
|
|
||||||
NextState("PRESENT")
|
|
||||||
).Else(
|
|
||||||
NextState("DROP")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.comb += [
|
|
||||||
source.sop.eq(depacketizer.source.sop),
|
|
||||||
source.eop.eq(depacketizer.source.eop),
|
|
||||||
source.rcount.eq(depacketizer.source.rcount),
|
|
||||||
source.wcount.eq(depacketizer.source.wcount),
|
|
||||||
source.data.eq(depacketizer.source.data),
|
|
||||||
source.error.eq(depacketizer.source.error)
|
|
||||||
]
|
|
||||||
fsm.act("PRESENT",
|
|
||||||
source.stb.eq(depacketizer.source.stb),
|
|
||||||
depacketizer.source.ack.eq(source.ack),
|
|
||||||
If(source.stb & source.eop & source.ack,
|
|
||||||
NextState("IDLE")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
fsm.act("DROP",
|
|
||||||
depacketizer.source.ack.eq(1),
|
|
||||||
If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack,
|
|
||||||
NextState("IDLE")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
class LiteEthEtherbone(Module):
|
class LiteEthEtherbone(Module):
|
||||||
def __init__(self, udp, udp_port):
|
def __init__(self, udp, udp_port):
|
||||||
self.submodules.tx = tx = LiteEthEtherboneTX(udp_port)
|
self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port)
|
||||||
self.submodules.rx = rx = LiteEthEtherboneRX()
|
|
||||||
udp_port = udp.crossbar.get_port(udp_port, dw=32)
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
self.comb += [
|
fsm.act("IDLE",
|
||||||
Record.connect(tx.source, udp_port.sink),
|
packet.source.ack.eq(1),
|
||||||
Record.connect(udp_port.source, rx.sink)
|
If(packet.source.stb & packet.source.sop,
|
||||||
]
|
If(packet.source.pf,
|
||||||
self.master = master = LiteEthEtherboneWishboneMaster()
|
packet.source.ack.eq(0),
|
||||||
self.comb += [
|
NextState("SEND_PROBE_RESPONSE")
|
||||||
Record.connect(rx.source.connect(master.sink)),
|
)
|
||||||
Record.connect(master.source.connect(tx.sink))
|
)
|
||||||
]
|
)
|
||||||
|
fsm.act("SEND_PROBE_RESPONSE",
|
||||||
|
packet.sink.stb.eq(1),
|
||||||
|
packet.sink.sop.eq(1),
|
||||||
|
packet.sink.eop.eq(1),
|
||||||
|
packet.sink.pr.eq(1),
|
||||||
|
packet.sink.ip_address.eq(packet.source.ip_address),
|
||||||
|
packet.sink.length.eq(0),
|
||||||
|
If(packet.sink.ack,
|
||||||
|
packet.source.ack.eq(1),
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -1,19 +1 @@
|
||||||
from liteeth.common import *
|
from liteeth.common import *
|
||||||
from liteeth.generic.depacketizer import LiteEthDepacketizer
|
|
||||||
from liteeth.generic.packetizer import LiteEthPacketizer
|
|
||||||
|
|
||||||
class LiteEthEtherboneDepacketizer(LiteEthDepacketizer):
|
|
||||||
def __init__(self):
|
|
||||||
LiteEthDepacketizer.__init__(self,
|
|
||||||
eth_udp_user_description(32),
|
|
||||||
eth_etherbone_description(32),
|
|
||||||
etherbone_header,
|
|
||||||
etherbone_header_len)
|
|
||||||
|
|
||||||
class LiteEthEtherbonePacketizer(LiteEthPacketizer):
|
|
||||||
def __init__(self):
|
|
||||||
LiteEthPacketizer.__init__(self,
|
|
||||||
eth_etherbone_description(32),
|
|
||||||
eth_udp_user_description(32),
|
|
||||||
etherbone_header,
|
|
||||||
etherbone_header_len)
|
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
from liteeth.common import *
|
||||||
|
from liteeth.generic.depacketizer import LiteEthDepacketizer
|
||||||
|
from liteeth.generic.packetizer import LiteEthPacketizer
|
||||||
|
from liteeth.core.etherbone import common
|
||||||
|
|
||||||
|
class LiteEthEtherbonePacketPacketizer(LiteEthPacketizer):
|
||||||
|
def __init__(self):
|
||||||
|
LiteEthPacketizer.__init__(self,
|
||||||
|
eth_etherbone_packet_description(32),
|
||||||
|
eth_udp_user_description(32),
|
||||||
|
etherbone_packet_header,
|
||||||
|
etherbone_packet_header_len)
|
||||||
|
|
||||||
|
class LiteEthEtherbonePacketTX(Module):
|
||||||
|
def __init__(self, udp_port):
|
||||||
|
self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
|
||||||
|
self.source = source = Source(eth_udp_user_description(32))
|
||||||
|
###
|
||||||
|
self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer()
|
||||||
|
self.comb += [
|
||||||
|
packetizer.sink.stb.eq(sink.stb),
|
||||||
|
packetizer.sink.sop.eq(sink.sop),
|
||||||
|
packetizer.sink.eop.eq(sink.eop),
|
||||||
|
sink.ack.eq(packetizer.sink.ack),
|
||||||
|
|
||||||
|
packetizer.sink.magic.eq(etherbone_magic),
|
||||||
|
packetizer.sink.port_size.eq(32//8),
|
||||||
|
packetizer.sink.addr_size.eq(32//8), # XXX add a parameter?
|
||||||
|
packetizer.sink.pf.eq(sink.pf),
|
||||||
|
packetizer.sink.pr.eq(sink.pr),
|
||||||
|
packetizer.sink.nr.eq(sink.nr),
|
||||||
|
packetizer.sink.version.eq(etherbone_version),
|
||||||
|
|
||||||
|
packetizer.sink.data.eq(sink.data)
|
||||||
|
]
|
||||||
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
|
fsm.act("IDLE",
|
||||||
|
packetizer.source.ack.eq(1),
|
||||||
|
If(packetizer.source.stb & packetizer.source.sop,
|
||||||
|
packetizer.source.ack.eq(0),
|
||||||
|
NextState("SEND")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("SEND",
|
||||||
|
Record.connect(packetizer.source, source),
|
||||||
|
source.src_port.eq(0x1234), # XXX,
|
||||||
|
source.dst_port.eq(udp_port),
|
||||||
|
source.ip_address.eq(sink.ip_address),
|
||||||
|
source.length.eq(sink.length + etherbone_packet_header_len),
|
||||||
|
If(source.stb & source.eop & source.ack,
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
class LiteEthEtherbonePacketDepacketizer(LiteEthDepacketizer):
|
||||||
|
def __init__(self):
|
||||||
|
LiteEthDepacketizer.__init__(self,
|
||||||
|
eth_udp_user_description(32),
|
||||||
|
eth_etherbone_packet_description(32),
|
||||||
|
etherbone_packet_header,
|
||||||
|
etherbone_packet_header_len)
|
||||||
|
|
||||||
|
class LiteEthEtherbonePacketRX(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.sink = sink = Sink(eth_udp_user_description(32))
|
||||||
|
self.source = source = Source(eth_etherbone_packet_user_description(32))
|
||||||
|
###
|
||||||
|
self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer()
|
||||||
|
self.comb += Record.connect(sink, depacketizer.sink)
|
||||||
|
|
||||||
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
|
fsm.act("IDLE",
|
||||||
|
depacketizer.source.ack.eq(1),
|
||||||
|
If(depacketizer.source.stb & depacketizer.source.sop,
|
||||||
|
depacketizer.source.ack.eq(0),
|
||||||
|
NextState("CHECK")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
valid = Signal()
|
||||||
|
self.sync += valid.eq(
|
||||||
|
depacketizer.source.stb &
|
||||||
|
(depacketizer.source.magic == etherbone_magic)
|
||||||
|
)
|
||||||
|
fsm.act("CHECK",
|
||||||
|
If(valid,
|
||||||
|
NextState("PRESENT")
|
||||||
|
).Else(
|
||||||
|
NextState("DROP")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.comb += [
|
||||||
|
source.sop.eq(depacketizer.source.sop),
|
||||||
|
source.eop.eq(depacketizer.source.eop),
|
||||||
|
|
||||||
|
source.pf.eq(depacketizer.source.pf),
|
||||||
|
source.pr.eq(depacketizer.source.pr),
|
||||||
|
source.nr.eq(depacketizer.source.nr),
|
||||||
|
|
||||||
|
source.src_port.eq(sink.src_port),
|
||||||
|
source.dst_port.eq(sink.dst_port),
|
||||||
|
source.ip_address.eq(sink.ip_address),
|
||||||
|
source.length.eq(sink.length - etherbone_packet_header_len)
|
||||||
|
]
|
||||||
|
fsm.act("PRESENT",
|
||||||
|
source.stb.eq(depacketizer.source.stb),
|
||||||
|
depacketizer.source.ack.eq(source.ack),
|
||||||
|
If(source.stb & source.eop & source.ack,
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("DROP",
|
||||||
|
depacketizer.source.ack.eq(1),
|
||||||
|
If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack,
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
class LiteEthEtherbonePacket(Module):
|
||||||
|
def __init__(self, udp, udp_port):
|
||||||
|
self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port)
|
||||||
|
self.submodules.rx = rx = LiteEthEtherbonePacketRX()
|
||||||
|
udp_port = udp.crossbar.get_port(udp_port, dw=32)
|
||||||
|
self.comb += [
|
||||||
|
Record.connect(tx.source, udp_port.sink),
|
||||||
|
Record.connect(udp_port.source, rx.sink)
|
||||||
|
]
|
||||||
|
self.sink, self.source = self.tx.sink, self.rx.source
|
|
@ -46,21 +46,23 @@ class LiteEthDepacketizer(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
no_payload = Signal()
|
||||||
self.sync += \
|
self.sync += \
|
||||||
If(fsm.before_entering("COPY"),
|
If(fsm.before_entering("COPY"),
|
||||||
source.sop.eq(1)
|
source.sop.eq(1),
|
||||||
|
no_payload.eq(sink.eop)
|
||||||
).Elif(source.stb & source.ack,
|
).Elif(source.stb & source.ack,
|
||||||
source.sop.eq(0)
|
source.sop.eq(0)
|
||||||
)
|
)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
source.eop.eq(sink.eop),
|
source.eop.eq(sink.eop | no_payload),
|
||||||
source.data.eq(sink.data),
|
source.data.eq(sink.data),
|
||||||
source.error.eq(sink.error),
|
source.error.eq(sink.error),
|
||||||
_decode_header(header_type, self.header, source)
|
_decode_header(header_type, self.header, source)
|
||||||
]
|
]
|
||||||
fsm.act("COPY",
|
fsm.act("COPY",
|
||||||
sink.ack.eq(source.ack),
|
sink.ack.eq(source.ack),
|
||||||
source.stb.eq(sink.stb),
|
source.stb.eq(sink.stb | no_payload),
|
||||||
If(source.stb & source.ack & source.eop,
|
If(source.stb & source.ack & source.eop,
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,3 +28,6 @@ udp_tb:
|
||||||
|
|
||||||
icmp_tb:
|
icmp_tb:
|
||||||
$(CMD) icmp_tb.py
|
$(CMD) icmp_tb.py
|
||||||
|
|
||||||
|
etherbone_tb:
|
||||||
|
$(CMD) etherbone_tb.py
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.bus import wishbone
|
||||||
|
from migen.bus.transactions import *
|
||||||
|
from migen.sim.generic import run_simulation
|
||||||
|
|
||||||
|
from liteeth.common import *
|
||||||
|
from liteeth.core import LiteEthUDPIPCore
|
||||||
|
from liteeth.core.etherbone import LiteEthEtherbone
|
||||||
|
|
||||||
|
from liteeth.test.common import *
|
||||||
|
from liteeth.test.model import phy, mac, arp, ip, udp, etherbone
|
||||||
|
|
||||||
|
ip_address = 0x12345678
|
||||||
|
mac_address = 0x12345678abcd
|
||||||
|
|
||||||
|
class TB(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.submodules.phy_model = phy.PHY(8, debug=True)
|
||||||
|
self.submodules.mac_model = mac.MAC(self.phy_model, debug=True, loopback=False)
|
||||||
|
self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
|
||||||
|
self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=True, loopback=False)
|
||||||
|
self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=True, loopback=False)
|
||||||
|
self.submodules.etherbone_model = etherbone.Etherbone(self.udp_model, debug=True)
|
||||||
|
|
||||||
|
self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000)
|
||||||
|
self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
for i in range(100):
|
||||||
|
yield
|
||||||
|
|
||||||
|
# test probe
|
||||||
|
packet = etherbone.EtherbonePacket()
|
||||||
|
packet.pf = 1
|
||||||
|
self.etherbone_model.send(packet)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_simulation(TB(), ncycles=1024, vcd_name="my.vcd", keep_files=True)
|
|
@ -194,6 +194,14 @@ class EtherbonePacket(Packet):
|
||||||
self.encoded = init != []
|
self.encoded = init != []
|
||||||
self.records = []
|
self.records = []
|
||||||
|
|
||||||
|
self.magic = etherbone_magic
|
||||||
|
self.version = etherbone_version
|
||||||
|
self.addr_size = 32//8
|
||||||
|
self.port_size = 32//8
|
||||||
|
self.nr = 0
|
||||||
|
self.pr = 0
|
||||||
|
self.pf = 0
|
||||||
|
|
||||||
def get_records(self):
|
def get_records(self):
|
||||||
records = []
|
records = []
|
||||||
done = False
|
done = False
|
||||||
|
@ -209,9 +217,9 @@ class EtherbonePacket(Packet):
|
||||||
if not self.encoded:
|
if not self.encoded:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
header = []
|
header = []
|
||||||
for byte in self[:etherbone_header_len]:
|
for byte in self[:etherbone_packet_header_len]:
|
||||||
header.append(self.pop(0))
|
header.append(self.pop(0))
|
||||||
for k, v in sorted(etherbone_header.items()):
|
for k, v in sorted(etherbone_packet_header.items()):
|
||||||
setattr(self, k, get_field_data(v, header))
|
setattr(self, k, get_field_data(v, header))
|
||||||
self.records = self.get_records()
|
self.records = self.get_records()
|
||||||
self.encoded = False
|
self.encoded = False
|
||||||
|
@ -227,10 +235,10 @@ class EtherbonePacket(Packet):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
self.set_records(self.records)
|
self.set_records(self.records)
|
||||||
header = 0
|
header = 0
|
||||||
for k, v in sorted(etherbone_header.items()):
|
for k, v in sorted(etherbone_packet_header.items()):
|
||||||
value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
|
value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
|
||||||
header += (value << v.offset+(v.byte*8))
|
header += (value << v.offset+(v.byte*8))
|
||||||
for d in split_bytes(header, etherbone_header_len):
|
for d in split_bytes(header, etherbone_packet_header_len):
|
||||||
self.insert(0, d)
|
self.insert(0, d)
|
||||||
self.encoded = True
|
self.encoded = True
|
||||||
|
|
||||||
|
@ -241,7 +249,7 @@ class EtherbonePacket(Packet):
|
||||||
for d in self:
|
for d in self:
|
||||||
r += "{:02x}".format(d)
|
r += "{:02x}".format(d)
|
||||||
else:
|
else:
|
||||||
for k in sorted(etherbone_header.keys()):
|
for k in sorted(etherbone_packet_header.keys()):
|
||||||
r += k + " : 0x{:0x}\n".format(getattr(self,k))
|
r += k + " : 0x{:0x}\n".format(getattr(self,k))
|
||||||
for i, record in enumerate(self.records):
|
for i, record in enumerate(self.records):
|
||||||
r += record.__repr__(i)
|
r += record.__repr__(i)
|
||||||
|
@ -255,7 +263,7 @@ class Etherbone(Module):
|
||||||
self.tx_packet = EtherbonePacket()
|
self.tx_packet = EtherbonePacket()
|
||||||
self.rx_packet = EtherbonePacket()
|
self.rx_packet = EtherbonePacket()
|
||||||
|
|
||||||
self.udp.set_etherbone_callback(self.callback)
|
udp.set_etherbone_callback(self.callback)
|
||||||
|
|
||||||
def send(self, packet):
|
def send(self, packet):
|
||||||
packet.encode()
|
packet.encode()
|
||||||
|
@ -263,14 +271,14 @@ class Etherbone(Module):
|
||||||
print_etherbone(">>>>>>>>")
|
print_etherbone(">>>>>>>>")
|
||||||
print_etherbone(packet)
|
print_etherbone(packet)
|
||||||
udp_packet = udp.UDPPacket(packet)
|
udp_packet = udp.UDPPacket(packet)
|
||||||
udp_packet.src_port = 0x1234
|
udp_packet.src_port = 0x1234 # XXX
|
||||||
udp_packet.dst_port = 0x5678
|
udp_packet.dst_port = 20000 # XXX
|
||||||
udp_packet.length = len(packet)
|
udp_packet.length = len(packet)
|
||||||
udp_packet.checksum = 0
|
udp_packet.checksum = 0
|
||||||
self.udp.send(udp_packet)
|
self.udp.send(udp_packet)
|
||||||
|
|
||||||
def callback(self, packet):
|
def callback(self, packet):
|
||||||
packet = Etherbone(packet)
|
packet = EtherbonePacket(packet)
|
||||||
packet.decode()
|
packet.decode()
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print_etherbone("<<<<<<<<")
|
print_etherbone("<<<<<<<<")
|
||||||
|
@ -306,13 +314,9 @@ if __name__ == "__main__":
|
||||||
# Packet
|
# Packet
|
||||||
packet = EtherbonePacket()
|
packet = EtherbonePacket()
|
||||||
packet.records = [copy.deepcopy(record) for i in range(8)]
|
packet.records = [copy.deepcopy(record) for i in range(8)]
|
||||||
packet.magic = etherbone_magic
|
|
||||||
packet.version = etherbone_version
|
|
||||||
packet.nr = 0
|
packet.nr = 0
|
||||||
packet.pr = 0
|
packet.pr = 0
|
||||||
packet.pf = 0
|
packet.pf = 0
|
||||||
packet.addr_size = 32//8
|
|
||||||
packet.port_size = 32//8
|
|
||||||
#print(packet)
|
#print(packet)
|
||||||
packet.encode()
|
packet.encode()
|
||||||
#print(packet)
|
#print(packet)
|
||||||
|
|
|
@ -51,7 +51,7 @@ class UDP(Module):
|
||||||
|
|
||||||
self.ip.set_udp_callback(self.callback)
|
self.ip.set_udp_callback(self.callback)
|
||||||
|
|
||||||
def set_etherbone_callback(callback):
|
def set_etherbone_callback(self, callback):
|
||||||
self.etherbone_callback = callback
|
self.etherbone_callback = callback
|
||||||
|
|
||||||
def send(self, packet):
|
def send(self, packet):
|
||||||
|
@ -85,7 +85,7 @@ class UDP(Module):
|
||||||
self.process(packet)
|
self.process(packet)
|
||||||
|
|
||||||
def process(self, packet):
|
def process(self, packet):
|
||||||
if packet.dst_port == 22000:
|
if packet.dst_port == 20000:
|
||||||
if self.etherbone_callback is not None:
|
if self.etherbone_callback is not None:
|
||||||
self.etherbone_callback(packet)
|
self.etherbone_callback(packet)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue