litepcie: use new Migen modules from actorlib (avoid duplications between cores)

This commit is contained in:
Florent Kermarrec 2015-04-27 14:59:29 +02:00
parent 1ef81c4d24
commit 20dd6d3047
9 changed files with 78 additions and 172 deletions

View file

@ -1,6 +1,8 @@
from migen.fhdl.std import * from migen.fhdl.std import *
from migen.genlib.record import * from migen.genlib.record import *
from migen.genlib.misc import reverse_bytes
from migen.flow.actor import * from migen.flow.actor import *
from migen.actorlib.packet import Arbiter, Dispatcher
KB = 1024 KB = 1024
MB = 1024*KB MB = 1024*KB
@ -18,15 +20,6 @@ def get_bar_mask(size):
size = size >> 1 size = size >> 1
return mask 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): def phy_layout(dw):
layout = [ layout = [
("dat", dw), ("dat", dw),

View file

@ -1,6 +1,7 @@
from migen.fhdl.std import * from migen.fhdl.std import *
from migen.genlib.record import * from migen.genlib.record import *
from migen.flow.actor import EndpointDescription, Sink, Source from migen.flow.actor import EndpointDescription, Sink, Source
from migen.actorlib.packet import HeaderField, Header
from misoclib.com.litepcie.common import * from misoclib.com.litepcie.common import *
@ -26,67 +27,66 @@ max_request_size = 512
# headers # headers
class HField(): tlp_common_header_length = 16
def __init__(self, word, offset, width): tlp_common_header_fields = {
self.word = word "fmt": HeaderField(0*4, 29, 2),
self.offset = offset "type": HeaderField(0*4, 24, 5),
self.width = width
tlp_header_w = 128
tlp_common_header = {
"fmt": HField(0, 29, 2),
"type": HField(0, 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), tlp_request_header_length = 16
"tag": HField(1, 8, 8), tlp_request_header_fields = {
"last_be": HField(1, 4, 4), "fmt": HeaderField(0*4, 29, 2),
"first_be": HField(1, 0, 4), "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), tlp_completion_header_length = 16
"status": HField(1, 13, 3), tlp_completion_header_fields = {
"bcm": HField(1, 12, 1), "fmt": HeaderField(0*4, 29, 2),
"byte_count": HField(1, 0, 12), "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), "completer_id": HeaderField(1*4, 16, 16),
"tag": HField(2, 8, 8), "status": HeaderField(1*4, 13, 3),
"lower_address": HField(2, 0, 7), "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 # 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): def tlp_raw_layout(dw):
layout = [ layout = [
("header", tlp_header_w), ("header", 4*32),
("dat", dw), ("dat", dw),
("be", dw//8) ("be", dw//8)
] ]
@ -94,7 +94,7 @@ def tlp_raw_layout(dw):
def tlp_common_layout(dw): def tlp_common_layout(dw):
layout = _layout_from_header(tlp_common_header) + [ layout = tlp_common_header.get_layout() + [
("dat", dw), ("dat", dw),
("be", dw//8) ("be", dw//8)
] ]
@ -102,7 +102,7 @@ def tlp_common_layout(dw):
def tlp_request_layout(dw): def tlp_request_layout(dw):
layout = _layout_from_header(tlp_request_header) + [ layout = tlp_request_header.get_layout() + [
("dat", dw), ("dat", dw),
("be", dw//8) ("be", dw//8)
] ]
@ -110,7 +110,7 @@ def tlp_request_layout(dw):
def tlp_completion_layout(dw): def tlp_completion_layout(dw):
layout = _layout_from_header(tlp_completion_header) + [ layout = tlp_completion_header.get_layout() + [
("dat", dw), ("dat", dw),
("be", dw//8) ("be", dw//8)
] ]

View file

@ -3,16 +3,6 @@ from migen.actorlib.structuring import *
from migen.genlib.fsm import FSM, NextState from migen.genlib.fsm import FSM, NextState
from misoclib.com.litepcie.core.packet.common import * 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): class HeaderExtracter(Module):
@ -65,7 +55,7 @@ class HeaderExtracter(Module):
source.sop.eq(sop), source.sop.eq(sop),
source.eop.eq(sink.eop), source.eop.eq(sink.eop),
source.dat.eq(Cat(reverse_bytes(sink_dat_r[32:]), reverse_bytes(sink.dat[:32]))), 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, If(source.stb & source.ack & source.eop,
NextState("HEADER1") NextState("HEADER1")
) )
@ -82,7 +72,7 @@ class HeaderExtracter(Module):
source.sop.eq(1), source.sop.eq(1),
source.eop.eq(1), source.eop.eq(1),
source.dat.eq(reverse_bytes(sink.dat[32:])), 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, If(source.stb & source.ack & source.eop,
NextState("HEADER1") NextState("HEADER1")
) )
@ -116,7 +106,7 @@ class Depacketizer(Module):
dispatch_source.eop.eq(header_extracter.source.eop), dispatch_source.eop.eq(header_extracter.source.eop),
dispatch_source.dat.eq(header_extracter.source.dat), dispatch_source.dat.eq(header_extracter.source.dat),
dispatch_source.be.eq(header_extracter.source.be), 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) self.submodules.dispatcher = Dispatcher(dispatch_source, dispatch_sinks)
@ -132,7 +122,7 @@ class Depacketizer(Module):
# decode TLP request and format local request # decode TLP request and format local request
tlp_req = Source(tlp_request_layout(dw)) tlp_req = Source(tlp_request_layout(dw))
self.comb += Record.connect(dispatch_sinks[0], tlp_req) 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 req_source = self.req_source
self.comb += [ self.comb += [
@ -151,7 +141,7 @@ class Depacketizer(Module):
# decode TLP completion and format local completion # decode TLP completion and format local completion
tlp_cmp = Source(tlp_completion_layout(dw)) tlp_cmp = Source(tlp_completion_layout(dw))
self.comb += Record.connect(dispatch_sinks[1], tlp_cmp) 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 cmp_source = self.cmp_source
self.comb += [ self.comb += [

View file

@ -4,16 +4,6 @@ from migen.genlib.fsm import FSM, NextState
from migen.genlib.misc import chooser from migen.genlib.misc import chooser
from misoclib.com.litepcie.core.packet.common import * 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): class HeaderInserter(Module):
@ -53,7 +43,7 @@ class HeaderInserter(Module):
source.sop.eq(0), source.sop.eq(0),
source.eop.eq(sink.eop), source.eop.eq(sink.eop),
source.dat.eq(Cat(sink.header[64:96], reverse_bytes(sink.dat[:32]))), 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, If(source.stb & source.ack,
sink.ack.eq(1), sink.ack.eq(1),
If(source.eop, If(source.eop,
@ -135,7 +125,7 @@ class Packetizer(Module):
tlp_req.ack.eq(tlp_raw_req.ack), tlp_req.ack.eq(tlp_raw_req.ack),
tlp_raw_req.sop.eq(tlp_req.sop), tlp_raw_req.sop.eq(tlp_req.sop),
tlp_raw_req.eop.eq(tlp_req.eop), 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.dat.eq(tlp_req.dat),
tlp_raw_req.be.eq(tlp_req.be), tlp_raw_req.be.eq(tlp_req.be),
] ]
@ -179,7 +169,7 @@ class Packetizer(Module):
tlp_cmp.ack.eq(tlp_raw_cmp.ack), tlp_cmp.ack.eq(tlp_raw_cmp.ack),
tlp_raw_cmp.sop.eq(tlp_cmp.sop), tlp_raw_cmp.sop.eq(tlp_cmp.sop),
tlp_raw_cmp.eop.eq(tlp_cmp.eop), 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.dat.eq(tlp_cmp.dat),
tlp_raw_cmp.be.eq(tlp_cmp.be), tlp_raw_cmp.be.eq(tlp_cmp.be),
] ]

View file

@ -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)

View file

@ -3,8 +3,6 @@ from migen.bank.description import *
from misoclib.com.litepcie.common import * from misoclib.com.litepcie.common import *
from misoclib.com.litepcie.core.switch.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 from misoclib.com.litepcie.core.switch.request_controller import RequestController

View file

@ -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)

View file

@ -4,7 +4,7 @@ from misoclib.com.litepcie.core.packet.common import *
# TLP Layer model # TLP Layer model
def get_field_data(field, dwords): 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 = { tlp_headers_dict = {
"RD32": tlp_request_header, "RD32": tlp_request_header,
@ -23,14 +23,14 @@ class TLP():
self.decode_dwords() self.decode_dwords()
def decode_dwords(self): 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)) setattr(self, k, get_field_data(v, self.header))
def encode_dwords(self, data=[]): def encode_dwords(self, data=[]):
self.header = [0, 0, 0] self.header = [0, 0, 0]
for k, v in tlp_headers_dict[self.name].items(): for k, v in tlp_headers_dict[self.name].fields.items():
field = tlp_headers_dict[self.name][k] field = tlp_headers_dict[self.name].fields[k]
self.header[field.word] |= (getattr(self, k) << field.offset) self.header[field.byte//4] |= (getattr(self, k) << field.offset)
self.data = data self.data = data
self.dwords = self.header + self.data self.dwords = self.header + self.data
return self.dwords return self.dwords
@ -81,8 +81,8 @@ fmt_type_dict = {
def parse_dwords(dwords): def parse_dwords(dwords):
f = get_field_data(tlp_common_header["fmt"], dwords) f = get_field_data(tlp_common_header.fields["fmt"], dwords)
t = get_field_data(tlp_common_header["type"], dwords) t = get_field_data(tlp_common_header.fields["type"], dwords)
fmt_type = (f << 5) | t fmt_type = (f << 5) | t
try: try:
tlp, min_len = fmt_type_dict[fmt_type] tlp, min_len = fmt_type_dict[fmt_type]