• Rocket


    https://mp.weixin.qq.com/s/-pjCLzzincJz0Z66orx8kg

     
    介绍Broadcast的实现。
     
     
    1. 基本介绍
     
    TLBroadcast实现的是TL-C等级,支持Transfer操作。主要功能是根据输入的请求类型,广播Probe请求进行权限调整,维持缓存一致性(cache coherency)。
     
    2. Tracker
     
    跟踪为了实现缓存一致性而发出的Probe请求的过程。Tracker根据配置参数bufferless,决定是否保存上游节点下发的请求。
     
    3. TLBroadcast
     
    1) 类参数
     
    a. lineBytes
     
    每个Tracker支持的字节数:
    限制条件:
    i. 值大于0;
    i. 值为2的幂;
    i. 值大于数据带宽(beatBytes);
     
    b. numTrackers
     
    支持的Tracker的数量。
     
    c. bufferless
     
    是否保存上游节点下发的请求。
     
    2) node
     
    用于与其他diplomacy节点连接并协商传递参数的diplomacy节点。
     
    A. clientFn
     
    用于向下传递参数的方法:
    因为要对source增加两位进行编码,所以这里乘以4。
     
    B. managerFn
     
    用于向上传递参数的方法:
    a. endSinkId = numTrackers;
    b. 限定下游节点不能支持Acquire操作,即下游节点不支持TL-C:
     
    c. 只处理区域类型为UNCACHED的manager,把UNCACHED转换为TRACKED。即我们看到的下游节点的区间类型为UNCACHED,而上游节点看到的我们支持的这个区间的类型为TRACKED。因为我们做了TRACK的工作。
     
    所谓UNCACHED区间类型,是指当前节点对该区间的支持不包含CACHE,但不妨碍上游节点为之添加缓存的功能。
    这里not cached yet,不是指时间上,而是指结构上。
     
    就时间上而言,一个区域是否缓存是一个动态的过程。而这里区域类型是一个静态的属性,不会随时间的变化而变化。即某个节点对某个区域的支持是否可缓存,不随时间的变化而变化。
     
    但可以随结构的变化而变化。节点不是鼓励的节点,而是DAG中的一个节点。DAG中某个节点对某个区域的支持是不缓存,不代表其上游的节点不可以代为缓存。
     
    所以可以理解几个区域类型的意义:
    UNCACHED:当前节点没为之缓存,上游节点可为之缓存;
    TRACKED:当前节点为下游节点增加了缓存的支持;
    UNCACHEABLE:不可缓存,当前节点不缓存,上游节点也不可以缓存,因为内容会变(比如IO编址区间)。这样的区间每次使用都要重新读取;
    CACHED:当前节点已为之缓存;
     
    d. 支持的传输大小变化:
     
     
    e. 响应不必FIFO顺序返回,也就是说先来的请求的响应可以后面才返回;
     
     
    3) module
     
    A. node.in & node.out
     
     
    因为所有节点组成的是DAG,所以只有上游节点可以缓存下游节点的数据,兄弟节点不能缓存。所以当上游节点发起的请求触发权限相关的Probe操作时,只需要向上游节点(通过node.in)发出Probe请求即可。
     
    B. clients/managers
     
    取出这一条线上的clients/managers:
     
    C. lineShift
     
    用于处理地址,因为缓存的数据大小为lineBytes,所以地址相应的低位可以忽略:
     
    D. caches
     
    取出缓存数据的clients:
     
    E. 创建Trackers
     
    创建numTrackers个Trackers:
    其中:log2Up(caches.size + 1)为记录probe个数所需要的比特数。
     
    F. 处理channel e
     
    channel e只有1种message,即GrantAck:
    a. 一直接收channel e的输出;
    b. 选择与in.e.bits.sink对应的tracker,输入e_last的值;
     
    G. in.a:上游节点的请求
     
    a. 请求类型
     
    左侧列出了各种请求类型。
     
    b. Acquire
     
     
    Acquire操作请求提升权限:
    i. NtoB:从None提升到Branch,Branch节点具有只读权限,所以向其他缓存了数据的节点发送Probe请求,把权限设定为Branch,即只读权限,超过的需要降权。
    i. NtoT:从None提升到Trunk,Trunk节点可读,Trunk节点具有读权限,并且缓存了可能是脏数据的数据。所以如果一个节点要提升至Trunk节点,需要向其他节点发送Probe请求,把权限设定为None,以促使其把数据回写。
    i. BtoT:同NtoT。
     
    c. 其他操作
     
    i. PutFullData:上游节点发来写数据请求,需要其他cache节点回写数据,若有需要之后再重新缓存。所以Probe其他cache节点的权限至None;
    i. PutPartialData:同PutFullData;
    i. ArithmeticData:需要先读、计算、再回写,同PutFullData;
    i. LogicalData:同PutFullData;
    i. Get:为了读取到最新数据,需要回写脏数据,如果没有脏数据则直接从缓存中返回即可。即如果是Trunk权限,则需要降权为Branch。如果是Branch权限,则无需再降权。
    i. Hint:预读取和预写入与读取和写入同理;
     
    d. selectTracker
     
    其中:
    i. freeTrackers:各个tracker是否空闲的标志;
    i. freeTrack:是否存在空闲的Tracker;
    i. matchTrackers:各个tracker跟踪的是否是当前访问的地址的标志;
    i. matchTracker:是否有一个tracker跟踪者当前访问的地址;
    i. allocTracker:从空闲的tracker中分配一个tracker用于跟踪当前访问的地址;
    i. selectTracker:如果有tracker正在跟踪当前访问的地址,则仍然使用这个tracker。否则,使用重新分配的新tracker;
     
    e. trackerReady
     
    trackerReady是各个tracker是否可以接收输入的标志:
     
    f. in.a.ready
     
    是否接收channel a的请求,取决于如下条件:
    i. 选中的tracker可以接收:(selectTracker & trackerReady).orR()
    i. burst请求的后续beat(!a_first)或者已经全部probe完成;
     
    g. 请求存入tracker
     
    其中:t.probe表示要probe的client的个数。如果没有caches则为0。否则要看请求是否来自于某一个cache节点,如果是则为caches.size - 1,如果不是则为caches.size。
     
    H. in.b
     
    channel b用于向上游节点发送Probe请求:
    其中:
    i. probe_todo:待probe的cache节点;
    i. probe_line:probe的address;
    i. probe_perms:param中cap的权限;
    i. probe_next:下一个要probe的对象;
    i. probe_busy:是否probe完所有要probe的cache节点;
    i. probe_target:当前要probe的对象;
    i. in.b.fire()时切换下一个probe对象;
     
    I. in.c
     
    a. 消息类型
    i. ProbeAck:我方发出Proe的响应消息,说明某client Probe完成。递减tracker中的Probe计数器。DROP是指收到ProbeAck无需其他动作。
    i. ProbeAckData:除了递减计数器之外,还需要把返回的数据回写。即通过out.a发出PutFull消息。DROP是指无需再有其他动作。
    i. ReleaseData:不同于ProbeAckData的地方在于,ReleaseData是上游节点发起,是一个请求消息,需要我方回复。回复的动作需要在PutFull完成之后,把PutFull的响应消息即AccessAck转换(transform)成为ReleaseAck返回给上游节点。
    i. Release:直接使用in.d回复ReleaseAck即可。
     
    b. 甄别消息类型
     
     
    c. 消息与tracker的关系
     
     
    d. releaseack
     
    针对Release消息的回复ReleaseAck:
    i. valid:channel c发送release时回复;
    i. 使用in.c.bits组装releaseack;
     
    通过in.d返回:
     
    e. putfull
     
    针对ProbeAckData和ReleaseData消息,需要把Data回写:
    其中:
    i. put_what:标识PutFull是为了ReleaseData还是为了ProbeAckData,如果是ReleaseData,就标识为TRANSFORM_B,如果是ProbeAckData就标识为DROP。
     
    i. put_who:如果是ReleaseData消息,那么source在in.c.bits.source;如果是ProbeAckData,这里source使用的是tracker中存着的in.a中取的source,与ProbeAckData中的Source即Probe消息的目标不一样,后续并没有使用这个source,用意不做分析。
     
    i. Cat(put_what, put_who):修改Put操作的source,以方便响应消息AccessAck返回时处理;因为put_what有四种可能(TRANS_B/TRANS_T/DROP/PASS)占两位,所以下游节点看到的client的endSourceId相比Broadcast节点看到的上游节点cliet的endSourceId,扩大了四倍。这就是diplomacy node的clientFn中cp.endSourceId乘以4的原因:
     
     
    通过out.a发出:
     
    f. probenack
     
    如果in.c返回ProbeAck消息,则告诉tracker递减probe计数器:
     
    J. out.d/in.d
     
    如何根据out.d生成in.d要回复的消息。channel d支持的消息类型如下:
     
    a. 取出编码在source中的信息:
     
     
    b. 判断是否ProbeAckData消息衍生成出的Put消息的响应消息AccessAck:
     
    有个assert限定:
     
    如果是这个AccessAck消息,就允许发送:
     
    然而这个消息不会被传往in.d:
     
    c. d_hasData:是否包含数据:
     
     
    d. d_normal:使用out.d生成的消息,发往in.d
     
    a) 使用in.d克隆的Wire:
     
    这意味着d_normal中各个域的位宽与in.d一致,而不是out.d。
     
    实际上,out.d的source域比in.d的source域多两位,所以把out.d连接到d_normal时,会把这两位丢掉:
     
    b) TRANSFORM
     
    TRANSFORM的信息从out.d.bits.source中取出,即do_what。
     
    这个信息从两处传入:
    i. put_what:
    - ReleaseData需要把Put的响应消息AccessAck变换为ReleaseAck;
    - ProbeAckData需要把Put的响应消息AccessAck丢弃;
    i. in.a的Acquire消息:
    in.a发出的Acquire消息,会被转换为Get消息,从下游节点请求数据,然后返回给上游节点。
     
    c) do_what(1):TRANSFORM_B/TRANSFORM_T
     
     
    如果do_what(1)为真,那么编码在source中的信息是TRANSFORM_B/TRANSFORM_T:
    进而表明tracker中跟踪的是一个Acquire消息或ReleaseData消息。
     
    如果d_hasData为真,out.d返回的是Acquire变换成的Get消息的响应消息AccessAckData,应该被转换为GrantData消息返回;
    如果d_hasData为假,out.d返回的是ReleaseData变换成的Put消息的响应消息AccessAck,应该被转换为ReleaseAck消息返回;
     
    GrantData消息的param:
     
    ReleaseAck消息的param为0:
     
    d) probedack
     
    标志着ProbeAckData处理完成:
    如果ProbeAckData衍生的Put消息返回,则ProbeAckData消息处理完成。
     
    e) d_last
     
    响应消息是否发送完成:
    d_normal.fire() && d_last代表d_normal发送完成。
     
    d_response指除ProbeAckData的AccessAck消息和ReleaseData的ReleaseAck消息之外的其他消息。
     
    为什么要排除这两个消息?
    因为这两个消息的响应消息虽然都是从channel d返回,但他们都是从channel c发送的请求消息。而tracker跟踪的是channel a发出的请求消息。
     
    4. TLBroadcastTracker
     
     
    1) 参数
     
    a. id:tracker的编号;
    b. lineBytes:tracker缓存的字节数;
    c. probeCountBites:需要probe的cache节点计数所需的比特位数;
    d. bufferless:是否保存上游节点下发的请求;
     
    2) io
     
    其中:
    a. in_a_first:是否in_a的第一个beat;
    b. in_a:保存的channel a的输入;
    c. out_a:向channel d输出的信号;
    d. probe:要probe的cache节点的数目;
    e. probenack:处理完成一个ProbeAck消息;
    f. probedack:处理完成一个ProbeAckData消息;
    g. d_last:是否channel d的最后一个beat;
    h. e_last:是否channel e的最后一个beat;
    i. source:提取in_a中的source域,输出用于比对;
    j. line:提取in_a中的address域,处理后输出用于比对;
    k. idle:表示该tracker是否空闲;
    l. need_d:是否需要channel d;
     
    3) 临时变量
     
    其中:
    a. idle = got_e && sent_d:表示已经完成全部消息交互:channel d已经发送完成,并收到了channel e的消息。
    b. count:probe请求的计数器。
     
    4) 存入channel a的请求消息
     
    a. sent_d:假,刚收到in.a的消息,还没有返回响应消息;
    b. got_e:只有Acquire/Grant/GrantAck交互需要用到channel e置为假,其他用不到的置为真。
    c. count:值等于io.probe;
     
    5) sent_d && need_d
     
    当channel d的最后一个beat发出后,sent_d置为真:
     
    channel d的响应消息已发出,则不再需要channel d:
     
    6) e_last && got_e
     
    当channel e的最后一个beat(实际上channel e有且只有一个beat)发出后,got_e置为真:
     
    7) line
     
    根据存的数据大小,地址的低若干位没有意义可以移除:
     
    8) probe计数
     
    a. 处理完一个ProbeAck减1;
    b. 处理完一个ProbeAckData减1;
    c. 同时处理完则减2;
     
    9) probe_done:标志着probe已经完成:
     
     
    10) Queue
     
    创建一个队列用于输入、存储、输出数据:
     
    11) 输入规则:
     
     
    12) 输出规则:
     
    其中:
    a. Acquire消息被转换为Get消息,其余透传;
    b. source进行编码,Acquire消息对应的source编入transform信息,其他的透传(PASS=0b00);
     
    out_a输出到out.a:
     
    5. Broadcast主动发出的消息
     
    无。
     
    6. Broadcast被动发出的消息
     
    1) 向上游发出Probe请求消息;
    2) 向上游直接回复ReleaseAck消息;
    3) 向上游回复transform后的ReleaseAck消息;
    4) 向下游发出transform后的Get消息;
    5) 向下游发出transform后的Put消息;
     
    7. Broadcast透传的消息
     
    channel a支持的消息如下:
    除Acquire需要transform外,其余的都会透传。
     
  • 相关阅读:
    【Python高级编程034 ● 静态web服务器 ● 静态Web服务器-返回固定页面数据】
    【Python高级编程033 ● 静态web服务器 ● 搭建Python自带静态Web服务器】
    【Python高级编程032 ● http协议 ● http响应报文】
    【Python高级编程031 ● http协议 ● http请求报文】
    做更好的自己:如何下得细功夫
    抓取图片视频等资源链接地址的Python小工具
    互联网应用服务端的常用技术思想与机制纲要
    《反脆弱》读书笔记
    错误启示录
    碎碎念集萃三九
  • 原文地址:https://www.cnblogs.com/wjcdx/p/11265568.html
Copyright © 2020-2023  润新知