mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
litepcie: use new Migen modules from actorlib (avoid duplications between cores)
This commit is contained in:
parent
1ef81c4d24
commit
20dd6d3047
9 changed files with 78 additions and 172 deletions
|
@ -1,6 +1,8 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.record import *
|
||||
from migen.genlib.misc import reverse_bytes
|
||||
from migen.flow.actor import *
|
||||
from migen.actorlib.packet import Arbiter, Dispatcher
|
||||
|
||||
KB = 1024
|
||||
MB = 1024*KB
|
||||
|
@ -18,15 +20,6 @@ def get_bar_mask(size):
|
|||
size = size >> 1
|
||||
return mask
|
||||
|
||||
|
||||
def reverse_bytes(v):
|
||||
return Cat(v[24:32], v[16:24], v[8:16], v[0:8])
|
||||
|
||||
|
||||
def reverse_bits(v):
|
||||
return Cat(v[3], v[2], v[1], v[0])
|
||||
|
||||
|
||||
def phy_layout(dw):
|
||||
layout = [
|
||||
("dat", dw),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.record import *
|
||||
from migen.flow.actor import EndpointDescription, Sink, Source
|
||||
from migen.actorlib.packet import HeaderField, Header
|
||||
|
||||
from misoclib.com.litepcie.common import *
|
||||
|
||||
|
@ -26,92 +27,91 @@ max_request_size = 512
|
|||
|
||||
|
||||
# headers
|
||||
class HField():
|
||||
def __init__(self, word, offset, width):
|
||||
self.word = word
|
||||
self.offset = offset
|
||||
self.width = width
|
||||
|
||||
tlp_header_w = 128
|
||||
|
||||
tlp_common_header = {
|
||||
"fmt": HField(0, 29, 2),
|
||||
"type": HField(0, 24, 5),
|
||||
tlp_common_header_length = 16
|
||||
tlp_common_header_fields = {
|
||||
"fmt": HeaderField(0*4, 29, 2),
|
||||
"type": HeaderField(0*4, 24, 5),
|
||||
}
|
||||
tlp_common_header = Header(tlp_common_header_fields,
|
||||
tlp_common_header_length,
|
||||
swap_field_bytes=False)
|
||||
|
||||
tlp_request_header = {
|
||||
"fmt": HField(0, 29, 2),
|
||||
"type": HField(0, 24, 5),
|
||||
"tc": HField(0, 20, 3),
|
||||
"td": HField(0, 15, 1),
|
||||
"ep": HField(0, 14, 1),
|
||||
"attr": HField(0, 12, 2),
|
||||
"length": HField(0, 0, 10),
|
||||
|
||||
"requester_id": HField(1, 16, 16),
|
||||
"tag": HField(1, 8, 8),
|
||||
"last_be": HField(1, 4, 4),
|
||||
"first_be": HField(1, 0, 4),
|
||||
tlp_request_header_length = 16
|
||||
tlp_request_header_fields = {
|
||||
"fmt": HeaderField(0*4, 29, 2),
|
||||
"type": HeaderField(0*4, 24, 5),
|
||||
"tc": HeaderField(0*4, 20, 3),
|
||||
"td": HeaderField(0*4, 15, 1),
|
||||
"ep": HeaderField(0*4, 14, 1),
|
||||
"attr": HeaderField(0*4, 12, 2),
|
||||
"length": HeaderField(0*4, 0, 10),
|
||||
|
||||
"address": HField(2, 2, 30),
|
||||
"requester_id": HeaderField(1*4, 16, 16),
|
||||
"tag": HeaderField(1*4, 8, 8),
|
||||
"last_be": HeaderField(1*4, 4, 4),
|
||||
"first_be": HeaderField(1*4, 0, 4),
|
||||
|
||||
"address": HeaderField(2*4, 2, 30),
|
||||
}
|
||||
tlp_request_header = Header(tlp_request_header_fields,
|
||||
tlp_request_header_length,
|
||||
swap_field_bytes=False)
|
||||
|
||||
tlp_completion_header = {
|
||||
"fmt": HField(0, 29, 2),
|
||||
"type": HField(0, 24, 5),
|
||||
"tc": HField(0, 20, 3),
|
||||
"td": HField(0, 15, 1),
|
||||
"ep": HField(0, 14, 1),
|
||||
"attr": HField(0, 12, 2),
|
||||
"length": HField(0, 0, 10),
|
||||
|
||||
"completer_id": HField(1, 16, 16),
|
||||
"status": HField(1, 13, 3),
|
||||
"bcm": HField(1, 12, 1),
|
||||
"byte_count": HField(1, 0, 12),
|
||||
tlp_completion_header_length = 16
|
||||
tlp_completion_header_fields = {
|
||||
"fmt": HeaderField(0*4, 29, 2),
|
||||
"type": HeaderField(0*4, 24, 5),
|
||||
"tc": HeaderField(0*4, 20, 3),
|
||||
"td": HeaderField(0*4, 15, 1),
|
||||
"ep": HeaderField(0*4, 14, 1),
|
||||
"attr": HeaderField(0*4, 12, 2),
|
||||
"length": HeaderField(0*4, 0, 10),
|
||||
|
||||
"requester_id": HField(2, 16, 16),
|
||||
"tag": HField(2, 8, 8),
|
||||
"lower_address": HField(2, 0, 7),
|
||||
"completer_id": HeaderField(1*4, 16, 16),
|
||||
"status": HeaderField(1*4, 13, 3),
|
||||
"bcm": HeaderField(1*4, 12, 1),
|
||||
"byte_count": HeaderField(1*4, 0, 12),
|
||||
|
||||
"requester_id": HeaderField(2*4, 16, 16),
|
||||
"tag": HeaderField(2*4, 8, 8),
|
||||
"lower_address": HeaderField(2*4, 0, 7),
|
||||
}
|
||||
tlp_completion_header = Header(tlp_completion_header_fields,
|
||||
tlp_completion_header_length,
|
||||
swap_field_bytes=False)
|
||||
|
||||
|
||||
# layouts
|
||||
def _layout_from_header(header):
|
||||
_layout = []
|
||||
for k, v in sorted(header.items()):
|
||||
_layout.append((k, v.width))
|
||||
return _layout
|
||||
|
||||
|
||||
def tlp_raw_layout(dw):
|
||||
layout = [
|
||||
("header", tlp_header_w),
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
("header", 4*32),
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
||||
|
||||
def tlp_common_layout(dw):
|
||||
layout = _layout_from_header(tlp_common_header) + [
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
layout = tlp_common_header.get_layout() + [
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
||||
|
||||
def tlp_request_layout(dw):
|
||||
layout = _layout_from_header(tlp_request_header) + [
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
layout = tlp_request_header.get_layout() + [
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
||||
|
||||
def tlp_completion_layout(dw):
|
||||
layout = _layout_from_header(tlp_completion_header) + [
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
layout = tlp_completion_header.get_layout() + [
|
||||
("dat", dw),
|
||||
("be", dw//8)
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
|
|
@ -3,16 +3,6 @@ from migen.actorlib.structuring import *
|
|||
from migen.genlib.fsm import FSM, NextState
|
||||
|
||||
from misoclib.com.litepcie.core.packet.common import *
|
||||
from misoclib.com.litepcie.core.switch.dispatcher import Dispatcher
|
||||
|
||||
|
||||
def _decode_header(h_dict, h_signal, obj):
|
||||
r = []
|
||||
for k, v in sorted(h_dict.items()):
|
||||
start = v.word*32+v.offset
|
||||
end = start+v.width
|
||||
r.append(getattr(obj, k).eq(h_signal[start:end]))
|
||||
return r
|
||||
|
||||
|
||||
class HeaderExtracter(Module):
|
||||
|
@ -65,7 +55,7 @@ class HeaderExtracter(Module):
|
|||
source.sop.eq(sop),
|
||||
source.eop.eq(sink.eop),
|
||||
source.dat.eq(Cat(reverse_bytes(sink_dat_r[32:]), reverse_bytes(sink.dat[:32]))),
|
||||
source.be.eq(Cat(reverse_bits(sink_be_r[4:]), reverse_bits(sink.be[:4]))),
|
||||
source.be.eq(Cat(freversed(sink_be_r[4:]), freversed(sink.be[:4]))),
|
||||
If(source.stb & source.ack & source.eop,
|
||||
NextState("HEADER1")
|
||||
)
|
||||
|
@ -82,7 +72,7 @@ class HeaderExtracter(Module):
|
|||
source.sop.eq(1),
|
||||
source.eop.eq(1),
|
||||
source.dat.eq(reverse_bytes(sink.dat[32:])),
|
||||
source.be.eq(reverse_bits(sink.be[4:])),
|
||||
source.be.eq(freversed(sink.be[4:])),
|
||||
If(source.stb & source.ack & source.eop,
|
||||
NextState("HEADER1")
|
||||
)
|
||||
|
@ -116,7 +106,7 @@ class Depacketizer(Module):
|
|||
dispatch_source.eop.eq(header_extracter.source.eop),
|
||||
dispatch_source.dat.eq(header_extracter.source.dat),
|
||||
dispatch_source.be.eq(header_extracter.source.be),
|
||||
_decode_header(tlp_common_header, header, dispatch_source)
|
||||
tlp_common_header.decode(header, dispatch_source)
|
||||
]
|
||||
|
||||
self.submodules.dispatcher = Dispatcher(dispatch_source, dispatch_sinks)
|
||||
|
@ -132,7 +122,7 @@ class Depacketizer(Module):
|
|||
# decode TLP request and format local request
|
||||
tlp_req = Source(tlp_request_layout(dw))
|
||||
self.comb += Record.connect(dispatch_sinks[0], tlp_req)
|
||||
self.comb += _decode_header(tlp_request_header, header, tlp_req)
|
||||
self.comb += tlp_request_header.decode(header, tlp_req)
|
||||
|
||||
req_source = self.req_source
|
||||
self.comb += [
|
||||
|
@ -151,7 +141,7 @@ class Depacketizer(Module):
|
|||
# decode TLP completion and format local completion
|
||||
tlp_cmp = Source(tlp_completion_layout(dw))
|
||||
self.comb += Record.connect(dispatch_sinks[1], tlp_cmp)
|
||||
self.comb += _decode_header(tlp_completion_header, header, tlp_cmp)
|
||||
self.comb += tlp_completion_header.decode(header, tlp_cmp)
|
||||
|
||||
cmp_source = self.cmp_source
|
||||
self.comb += [
|
||||
|
|
|
@ -4,16 +4,6 @@ from migen.genlib.fsm import FSM, NextState
|
|||
from migen.genlib.misc import chooser
|
||||
|
||||
from misoclib.com.litepcie.core.packet.common import *
|
||||
from misoclib.com.litepcie.core.switch.arbiter import Arbiter
|
||||
|
||||
|
||||
def _encode_header(h_dict, h_signal, obj):
|
||||
r = []
|
||||
for k, v in sorted(h_dict.items()):
|
||||
start = v.word*32+v.offset
|
||||
end = start+v.width
|
||||
r.append(h_signal[start:end].eq(getattr(obj, k)))
|
||||
return r
|
||||
|
||||
|
||||
class HeaderInserter(Module):
|
||||
|
@ -53,7 +43,7 @@ class HeaderInserter(Module):
|
|||
source.sop.eq(0),
|
||||
source.eop.eq(sink.eop),
|
||||
source.dat.eq(Cat(sink.header[64:96], reverse_bytes(sink.dat[:32]))),
|
||||
source.be.eq(Cat(Signal(4, reset=0xf), reverse_bits(sink.be[:4]))),
|
||||
source.be.eq(Cat(Signal(4, reset=0xf), freversed(sink.be[:4]))),
|
||||
If(source.stb & source.ack,
|
||||
sink.ack.eq(1),
|
||||
If(source.eop,
|
||||
|
@ -135,7 +125,7 @@ class Packetizer(Module):
|
|||
tlp_req.ack.eq(tlp_raw_req.ack),
|
||||
tlp_raw_req.sop.eq(tlp_req.sop),
|
||||
tlp_raw_req.eop.eq(tlp_req.eop),
|
||||
_encode_header(tlp_request_header, tlp_raw_req.header, tlp_req),
|
||||
tlp_request_header.encode(tlp_req, tlp_raw_req.header),
|
||||
tlp_raw_req.dat.eq(tlp_req.dat),
|
||||
tlp_raw_req.be.eq(tlp_req.be),
|
||||
]
|
||||
|
@ -179,7 +169,7 @@ class Packetizer(Module):
|
|||
tlp_cmp.ack.eq(tlp_raw_cmp.ack),
|
||||
tlp_raw_cmp.sop.eq(tlp_cmp.sop),
|
||||
tlp_raw_cmp.eop.eq(tlp_cmp.eop),
|
||||
_encode_header(tlp_completion_header, tlp_raw_cmp.header, tlp_cmp),
|
||||
tlp_completion_header.encode(tlp_cmp, tlp_raw_cmp.header),
|
||||
tlp_raw_cmp.dat.eq(tlp_cmp.dat),
|
||||
tlp_raw_cmp.be.eq(tlp_cmp.be),
|
||||
]
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.roundrobin import *
|
||||
from migen.genlib.record import *
|
||||
|
||||
|
||||
class Arbiter(Module):
|
||||
def __init__(self, sources, sink):
|
||||
if len(sources) == 0:
|
||||
pass
|
||||
else:
|
||||
self.submodules.rr = RoundRobin(len(sources))
|
||||
self.grant = self.rr.grant
|
||||
cases = {}
|
||||
for i, source in enumerate(sources):
|
||||
sop = Signal()
|
||||
eop = Signal()
|
||||
ongoing = Signal()
|
||||
self.comb += [
|
||||
sop.eq(source.stb & source.sop),
|
||||
eop.eq(source.stb & source.eop & source.ack),
|
||||
]
|
||||
self.sync += ongoing.eq((sop | ongoing) & ~eop)
|
||||
self.comb += self.rr.request[i].eq((sop | ongoing) & ~eop)
|
||||
cases[i] = [Record.connect(source, sink)]
|
||||
self.comb += Case(self.grant, cases)
|
|
@ -3,8 +3,6 @@ from migen.bank.description import *
|
|||
|
||||
from misoclib.com.litepcie.common import *
|
||||
from misoclib.com.litepcie.core.switch.common import *
|
||||
from misoclib.com.litepcie.core.switch.arbiter import Arbiter
|
||||
from misoclib.com.litepcie.core.switch.dispatcher import Dispatcher
|
||||
from misoclib.com.litepcie.core.switch.request_controller import RequestController
|
||||
|
||||
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.record import *
|
||||
|
||||
|
||||
class Dispatcher(Module):
|
||||
def __init__(self, source, sinks, one_hot=False):
|
||||
if len(sinks) == 0:
|
||||
self.sel = Signal()
|
||||
elif len(sinks) == 1:
|
||||
self.comb += Record.connect(source, sinks[0])
|
||||
self.sel = Signal()
|
||||
else:
|
||||
if one_hot:
|
||||
self.sel = Signal(len(sinks))
|
||||
else:
|
||||
self.sel = Signal(max=len(sinks))
|
||||
###
|
||||
sop = Signal()
|
||||
self.comb += sop.eq(source.stb & source.sop)
|
||||
sel = Signal(flen(self.sel))
|
||||
sel_r = Signal(flen(self.sel))
|
||||
self.sync += \
|
||||
If(sop,
|
||||
sel_r.eq(self.sel)
|
||||
)
|
||||
self.comb += \
|
||||
If(sop,
|
||||
sel.eq(self.sel)
|
||||
).Else(
|
||||
sel.eq(sel_r)
|
||||
)
|
||||
cases = {}
|
||||
for i, sink in enumerate(sinks):
|
||||
if one_hot:
|
||||
idx = 2**i
|
||||
else:
|
||||
idx = i
|
||||
cases[idx] = [Record.connect(source, sink)]
|
||||
cases["default"] = [source.ack.eq(1)]
|
||||
self.comb += Case(sel, cases)
|
|
@ -13,9 +13,9 @@ def print_host(s):
|
|||
# Host model
|
||||
class Host(Module):
|
||||
def __init__(self, dw, root_id, endpoint_id, bar0_size=1*MB,
|
||||
phy_debug=False,
|
||||
chipset_debug=False, chipset_split=False, chipset_reordering=False,
|
||||
host_debug=False):
|
||||
phy_debug=False,
|
||||
chipset_debug=False, chipset_split=False, chipset_reordering=False,
|
||||
host_debug=False):
|
||||
self.debug = host_debug
|
||||
self.chipset_split = chipset_split
|
||||
###
|
||||
|
|
|
@ -4,7 +4,7 @@ from misoclib.com.litepcie.core.packet.common import *
|
|||
|
||||
# TLP Layer model
|
||||
def get_field_data(field, dwords):
|
||||
return (dwords[field.word] >> field.offset) & (2**field.width-1)
|
||||
return (dwords[field.byte//4] >> field.offset) & (2**field.width-1)
|
||||
|
||||
tlp_headers_dict = {
|
||||
"RD32": tlp_request_header,
|
||||
|
@ -23,14 +23,14 @@ class TLP():
|
|||
self.decode_dwords()
|
||||
|
||||
def decode_dwords(self):
|
||||
for k, v in tlp_headers_dict[self.name].items():
|
||||
for k, v in tlp_headers_dict[self.name].fields.items():
|
||||
setattr(self, k, get_field_data(v, self.header))
|
||||
|
||||
def encode_dwords(self, data=[]):
|
||||
self.header = [0, 0, 0]
|
||||
for k, v in tlp_headers_dict[self.name].items():
|
||||
field = tlp_headers_dict[self.name][k]
|
||||
self.header[field.word] |= (getattr(self, k) << field.offset)
|
||||
for k, v in tlp_headers_dict[self.name].fields.items():
|
||||
field = tlp_headers_dict[self.name].fields[k]
|
||||
self.header[field.byte//4] |= (getattr(self, k) << field.offset)
|
||||
self.data = data
|
||||
self.dwords = self.header + self.data
|
||||
return self.dwords
|
||||
|
@ -81,8 +81,8 @@ fmt_type_dict = {
|
|||
|
||||
|
||||
def parse_dwords(dwords):
|
||||
f = get_field_data(tlp_common_header["fmt"], dwords)
|
||||
t = get_field_data(tlp_common_header["type"], dwords)
|
||||
f = get_field_data(tlp_common_header.fields["fmt"], dwords)
|
||||
t = get_field_data(tlp_common_header.fields["type"], dwords)
|
||||
fmt_type = (f << 5) | t
|
||||
try:
|
||||
tlp, min_len = fmt_type_dict[fmt_type]
|
||||
|
|
Loading…
Reference in a new issue